CIP Proposal - Simultaneous Asset Changes

In this thread, I would like to discuss modifying the issuance code to allow asset owners to make certain changes simultaneously that they currently perform separately.

For those that don’t know, the issuance message in Counterparty is multipurpose, with it you can…

  • Create a new asset with N tokens.
  • Update an asset, so more tokens are circulating.
  • Update an asset, so it is locked (no new tokens).
  • Update an asset, in order to edit its description.
  • Update an asset, to transfer address ownership.

Some of these actions you can do simultaneously, but most you cannot…

  • You cannot transfer an asset AND increase its issuance.
  • You cannot create a new asset AND transfer it.
  • You cannot create a new asset AND lock its issuance.
  • You cannot create a new asset AND transfer it AND lock its issuance.

So, at present, counterparty-lib requires most actions to be handled separately, but it appears to be more a matter of preference than a matter of technical limitations. If I’m reading the code correctly, you can transfer assets AND lock them.

If we work on allowing simultaneous changes, asset owners will incur fewer Bitcoin transaction fees. I also think such an improvement would aid interesting subasset use-cases.

Some of the code that would need to be changed…

Prevents transferring AND issuing…

IMO - This code seems to enforce a preference for major actions such as “transfer” to be separate, but perhaps that’s not something we really need to enforce.

218 if destination and quantity:
219 problems.append(‘cannot issue and transfer simultaneously’)

I think this could be removed, I believe the code after this check would work as expected.

Prevents creating AND locking assets…

These two pieces of code are related. The first lines (147-148) prevent users from locking an asset at its initial creation, a second tx is required to lock the asset after its creation. The second line (392) handles re-using the last description, in the case of performing a “lock” action.

147 if description.lower() == ‘lock’:
148 problems.append(‘cannot lock a non‐existent asset’)

392 description = issuances[-1][‘description’] # Use last description. (Assume previous issuance exists because tx is valid.)

Basically, to lock an asset, you set the description to “lock”. That’s taken as a command by counterparty-lib, but is not stored as the literal description, the last issuance’s description is used.

I think we should just get rid of 147-148. That should allow you to create a locked asset.

To handle the asset’s description when locking, we have some options…

  • We can add logic to use either the last issuance’s description OR blank if it’s a new issuance.
  • We could do something like lock("My description here") rather than simply lock.

So, I would be interested to know if this is a feature that people would like or use. I think the major use case is for subassets, like I could issue and transfer a subasset in one bitcoin tx, but it’s useful generally as a way to minimize bitcoin txs required to perform routine actions.

I support it, but wonder if a more general tx batching approach is better use or dev time?

How it can work:

  • New batch message type
  • Indicate how many messages and start index (bit) or each one
  • Counteparty reads through all in order, just as if it were parsing multiple transactions

Most counterparty messages are less than 80 bytes, i.e. small marginal cost for each instruction

CIP6 allows for adding kilobytes of data at 60% efficiency.

If a lossless compression algorithm is implemented, a Counterparty batch send, I think, can be reduced in half (i.e. offset the CIP6 inefficiency).

If included in MCAT, even those who need to make just one single operation will benefit from lower fees.

@droplister - I don’t see any reason not to allow these combination actions.

Can you make the changes to the code and write unit tests that verify the expected results?

I find that writing unit tests is a great way to investigate the full ramifications of a change and help ensure there are no unintended consequences to a change.

After you do that, you can submit the change and the tests as a pull request.

Since this is not a material change to the protocol rules, I don’t think this necessarily needs to go through the CIP process.

Jurgen, this proposed change doesn’t really impact the tx encoding, but it does reduce total txs needs from 2-3 down to 1 in some cases.

Please consider creating a separate CIP proposal as your suggestions would be a different project.

Devon, I agree that it’s not a major change. But it is a change to the protocol specification, which says…

  1. A subasset may be transferred to a new owner address after initial issuance

And this change would require block height checks so that previously invalid messages do not become valid and potentially update an asset in unexpected ways. Is that still a non-material change?

I looked at the code and will mess with unit tests and PRs after some further feedback and discussion.

It looks like transfers are done by including a dust output. Have you thought about moving the transfer function to the description? You could use the same address encoding method used in enhanced asset send txs and would allow you to string commands together.

Okay, so that would be an enhanced_issuance that mirrors the approach of enhanced_send. That seems doable and makes sense since it was accepted as a standard. I’d really like to enable the ability to create, transfer, and lock in one tx, especially for subassets.

I like the idea of using lock("My description here.") instead of just lock which gets rid of the need for their to be a previous description to use, in the event of a lock command.

You could do the same thing for transfer: tranfer("My description here.). But I’m not sure what a lock and a transfer might look like, maybe it could be like…

Lock: L("My description here.")
Transfer: T("My description here.")
Lock & Transfer: LT("My description here.")

Since space is limited, I recommend using delimiters with a single byte key followed by the value. This would be similar to what I suggested in my client-side subasset proposal,

We could save some additional space and use single byte delimiters if we pick a value that’s not an ASCII character (this also prevents users from inadvertently creating a description that’s parsed as message parameters). Instead of ;; (3b3b) which equates to two bytes, we could use a single byte between 00 and 1f (see The issuance parse function in could then parse values for each parameter by looking for the delimiter byte + key byte.

For example… (using # to symbolize the delimiter byte)


1 Like