The Protocol

A standard Pay-To-Pubkey-Hash address looks like this:

OP_DUP OP_HASH160 <pubkeyHash> OP_EQUALVERIFY OP_CHECKSIG

For colored outputs we just prepend a new OP_GROUP opcode as well as a group identifier. The identifier is a 160-bit hash as we will see, but for the sake of this example I'm just going to use the word

blue

to represent the hash.

<blue> OP_GROUP OP_DUP OP_HASH160 <pubkeyHash> OP_EQUALVERIFY OP_CHECKSIG

The only addition to the Bitcoin Cash protocol would be a requirement that when a transaction contains a colored input, that an equal value colored output must also be included (and vise versa). The only two exceptions to this rule would be the Mint and Burn (uncolor) transactions.

MINT Transactions

The following is an example MINT transaction in JSON showing hypothetical inputs and outputs.

{

"inputs": [

{

"outpoint": XXXXXXXXXX,

"value": 1000000,

"linkedScript": OP_DUP OP_HASH160 <blue> OP_EQUALVERIFY OP_CHECKSIG

}

],

"outputs": [

{

"value": 1000000,

"script": <blue> OP_GROUP OP_DUP OP_HASH160 <pubkeyHash> OP_EQUALVERIFY OP_CHECKSIG

}

]

}

You'll notice above that while the output script contains an OP_GROUP opcode the input does not. Normally this would cause transaction validation to fail. However, since the data element in the linked input script is the

same

hash as the group identifier, this is treated as a valid MINT transaction. Basically only the person who controls the private key to the "blue" address can mint new blue coins. Also this transaction does not pay a fee. If the sender wished to include a fee, he would need to attach another uncolored input and an uncolored change output. The same will be the case for all colored coin transactions.

SPEND Transactions

{

"inputs": [

{

"outpoint": XXXXXXXXXX,

"value": 1000000,

"linkedScript": <blue> OP_GROUP OP_DUP OP_HASH160 <pubkeyHash> OP_EQUALVERIFY OP_CHECKSIG

}

],

"outputs": [

{

"value": 1000000,

"script": <blue> OP_GROUP OP_DUP OP_HASH160 <pubkeyHash> OP_EQUALVERIFY OP_CHECKSIG

}

]

}

SPEND transactions follow the normal rule of colored input and output values matching. There can be more than one type of colored input and output in the transaction so long as they match. This would allow atomic swaps to be done in a single transaction.

BURN Transactions

The BURN transaction uncolors the coins and turns them back into normal Bitcoin Cash coins. The rule here is if any output does not include the OP_GROUP identifier but

does

pay to that group's identifier, then the transaction is considered valid. Presumably something like the following would uncolor the blue coins and send the normal Bitcoin Cash to an address of your choice.

{ "inputs": [ { "outpoint": XXXXXXXXXX, "value": 1000000, "linkedScript": <blue> OP_GROUP OP_DUP OP_HASH160 <pubkeyHash> OP_EQUALVERIFY OP_CHECKSIG } ], "outputs": [ { "value": 1000000, "script": OP_DUP OP_HASH160 <pubkeyHash> OP_EQUALVERIFY OP_CHECKSIG }, { "value": 0, "script": OP_RETURN <blue> } ] }

Fixed Supply Coins

The above protocol proposed by Andrew allows the issuer of the coin to continue issuing more coins after the first MINT transaction. This is probably what you want for most cases (like a gold backed coin, or a stock token). But there might be some other cases where you just want a fixed supply (maybe you've got some specific use case for a token in your app when you want/need the supply to be fixed). Is there a way we could prevent further issuance? A solution I came up with could be to use a P2SH address instead of P2PKH for the group address. The redeem script could look something like this:

OP_CHAINHEIGHT <505500> OP_LESSTHAN OP_VERIFY <pubkey> OP_CHECKSIG

This says, "This output can only be spent before block 505500". This would mean the issuer could mint new coins up to block 505499 but no more after that. OP_CHAINHEIGHT does not exist today and I think would need to be a hardfork to include, but if we're doing a hardfork to include script enhancements it might be worth considering adding that opcode as well.

Conclusion