Skip to content

Instantly share code, notes, and snippets.

@A60AB5450353F40E
Last active August 31, 2022 18:33
Show Gist options
  • Save A60AB5450353F40E/15d6c688dcd73f151b1bebbc91a422ac to your computer and use it in GitHub Desktop.
Save A60AB5450353F40E/15d6c688dcd73f151b1bebbc91a422ac to your computer and use it in GitHub Desktop.
{
"$schema": "https://ide.bitauth.com/authentication-template-v0.schema.json",
"description": "Fungible token management contract, consisting of 3 outputs:\n- tracker NFT (invariant category-specific P2SH address)\n- owner NFT (user-set address)\n- baton NFT (reserved supply and metadata carrier)\n\nOwner NFT can be transferred independently, while spending tracker+baton requires the owner is spent in the same transaction.",
"name": "One Token Standard v0.1",
"entities": {
"baton": {
"description": "",
"name": "baton",
"scripts": [
"baton_current"
],
"variables": {
"index_baton_output": {
"description": "",
"name": "",
"type": "AddressData"
},
"index_baton_input": {
"description": "",
"name": "",
"type": "AddressData"
},
"index_tracker_input": {
"description": "",
"name": "",
"type": "AddressData"
},
"index_tracker_output": {
"description": "",
"name": "",
"type": "AddressData"
},
"baton_current_supply_lock": {
"description": "",
"name": "",
"type": "AddressData"
},
"baton_new_supply_lock": {
"description": "",
"name": "",
"type": "AddressData"
},
"genesis_supply": {
"description": "",
"name": "",
"type": "WalletData"
},
"genesis_policy": {
"description": "",
"name": "",
"type": "WalletData"
},
"baton_new_decimals": {
"description": "",
"name": "",
"type": "AddressData"
},
"baton_new_ticker": {
"description": "",
"name": "",
"type": "AddressData"
},
"baton_new_name": {
"description": "",
"name": "",
"type": "AddressData"
},
"baton_new_document_hash": {
"description": "",
"name": "",
"type": "AddressData"
},
"baton_new_document": {
"description": "",
"name": "",
"type": "AddressData"
},
"baton_new_back_validation": {
"description": "",
"name": "",
"type": "AddressData"
},
"baton_new_metadata_locks": {
"description": "",
"name": "",
"type": "AddressData"
},
"baton_current_decimals": {
"description": "",
"name": "",
"type": "AddressData"
},
"baton_current_ticker": {
"description": "",
"name": "",
"type": "AddressData"
},
"baton_current_name": {
"description": "",
"name": "",
"type": "AddressData"
},
"baton_current_document_hash": {
"description": "",
"name": "",
"type": "AddressData"
},
"baton_current_document": {
"description": "",
"name": "",
"type": "AddressData"
},
"baton_current_back_validation": {
"description": "",
"name": "",
"type": "AddressData"
},
"baton_current_metadata_locks": {
"description": "",
"name": "",
"type": "AddressData"
}
}
}
},
"scenarios": {
"base": {
"data": {
"bytecode": {
"genesis_supply": "0x070040075af07507",
"genesis_policy": "0x1976a914112233445566778899001122334455667788990088ac"
}
},
"description": "",
"name": "Unnamed Scenario"
},
"first_spend": {
"data": {
"bytecode": {
"index_tracker_input": "0x020100",
"index_tracker_output": "0x020100",
"index_baton_input": "0x020000",
"index_baton_output": "0x020000",
"baton_new_supply_lock": "0x00",
"baton_new_decimals": "0x59",
"baton_new_ticker": "0x0442434848",
"baton_new_name": "0x0c426974636f696e2043617368",
"baton_new_document_hash": "0x20b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553",
"baton_new_document": "0x2368747470733a2f2f7777772e626974636f696e2e636f6d2f626974636f696e2e706466",
"baton_new_back_validation": "0x1b68747470733a2f2f7777772e626974636f696e2e636f6d2f6f7473",
"baton_new_metadata_locks": "0x01ee",
"baton_current_supply_lock": "0x51",
"baton_current_decimals": "0x58",
"baton_current_ticker": "0x03424348",
"baton_current_name": "0x0c426974636f696e2043617368",
"baton_current_document_hash": "0x20b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553",
"baton_current_document": "0x2368747470733a2f2f7777772e626974636f696e2e636f6d2f626974636f696e2e706466",
"baton_current_back_validation": "0x1b68747470733a2f2f7777772e626974636f696e2e636f6d2f6f7473",
"baton_current_metadata_locks": "0x01ff"
}
},
"description": "first spend",
"extends": "base",
"name": "first_spend"
},
"first_spend_baton": {
"description": "",
"extends": "first_spend",
"name": "first_spend_baton",
"transaction": {
"inputs": [
{
"outpointTransactionHash": "9bd914b5ccf93a41ab2d765c0d4d46e8a5dc9718423b6c105531ad06ca86894a",
"outpointIndex": 0,
"unlockingBytecode": [
"slot"
]
},
{
"outpointTransactionHash": "9bd914b5ccf93a41ab2d765c0d4d46e8a5dc9718423b6c105531ad06ca86894a",
"outpointIndex": 1,
"unlockingBytecode": {
"script": "unlock_baton_tracker"
}
}
],
"outputs": [
{
"lockingBytecode": {
"script": "baton_new"
},
"valueSatoshis": 4559963
},
{
"lockingBytecode": {
"script": "baton_tracker"
},
"valueSatoshis": 1614783
}
]
},
"sourceOutputs": [
{
"lockingBytecode": [
"slot"
],
"valueSatoshis": 6175921
},
{
"lockingBytecode": {
"script": "baton_tracker"
}
}
]
},
"first_spend_baton_tracker": {
"description": "",
"extends": "first_spend",
"name": "first_spend_baton_tracker",
"transaction": {
"inputs": [
{
"outpointTransactionHash": "9bd914b5ccf93a41ab2d765c0d4d46e8a5dc9718423b6c105531ad06ca86894a",
"outpointIndex": 0,
"unlockingBytecode": {
"script": "metadata_first_update"
}
},
{
"outpointTransactionHash": "9bd914b5ccf93a41ab2d765c0d4d46e8a5dc9718423b6c105531ad06ca86894a",
"outpointIndex": 1,
"unlockingBytecode": [
"slot"
]
},
{
"outpointTransactionHash": "9bd914b5ccf93a41ab2d765c0d4d46e8a5dc9718423b6c105531ad06ca86894a",
"outpointIndex": 2
}
],
"outputs": [
{
"lockingBytecode": {
"script": "baton_new"
},
"valueSatoshis": 4559963,
"token": {
"amount": 2100000000000000,
"category": "efbe00000000000000000000000000000000000000000000000000000000adde",
"nft": {
"capability": "none",
"commitment": "01"
}
}
},
{
"lockingBytecode": {
"script": "baton_tracker"
},
"valueSatoshis": 1614783,
"token": {
"category": "efbe00000000000000000000000000000000000000000000000000000000adde",
"amount": 0,
"nft": {
"capability": "none",
"commitment": "00"
}
}
},
{
"lockingBytecode": {
"script": "burn_opreturn"
},
"valueSatoshis": 1614783,
"token": {
"category": "efbe00000000000000000000000000000000000000000000000000000000adde",
"amount": 0,
"nft": {
"capability": "none",
"commitment": "00"
}
}
}
]
},
"sourceOutputs": [
{
"lockingBytecode": {
"script": "baton_current"
},
"valueSatoshis": 6175921,
"token": {
"category": "efbe00000000000000000000000000000000000000000000000000000000adde",
"amount": 2100000000000000,
"nft": {
"capability": "none",
"commitment": "01"
}
}
},
{
"lockingBytecode": [
"slot"
],
"token": {
"category": "efbe00000000000000000000000000000000000000000000000000000000adde",
"amount": 0,
"nft": {
"capability": "none",
"commitment": "00"
}
}
},
{
"lockingBytecode": {
"script": "baton_current"
},
"valueSatoshis": 6175921,
"token": {
"category": "efbe00000000000000000000000000000000000000000000000000000000adde",
"amount": 0,
"nft": {
"capability": "none",
"commitment": "00"
}
}
}
]
}
},
"scripts": {
"metadata_first_update": {
"passes": [
"first_spend_baton"
],
"name": "metadata_first_update",
"script": "// Baton tracker contract's input index\nindex_tracker_input\n\n// Baton change output's index\nindex_baton_output\n\n// New metadata blob\nmacro_metadata_blob_new\n\n// Current metadata blob\nmacro_metadata_blob_current",
"unlocks": "baton_current"
},
"baton_genesis": {
"name": "baton_genesis",
"script": "",
"unlocks": "baton_constructor"
},
"metadata_copy": {
"passes": [
"first_spend_baton"
],
"name": "metadata_copy",
"script": "// Baton tracker contract's input index\nindex_tracker_input\n\n// Baton change output's index\nindex_baton_output\n\n// New metadata blob\nmacro_metadata_blob_new\n\n// Current metadata blob\nmacro_metadata_blob_new",
"unlocks": "baton_new"
},
"unlock_baton_tracker": {
"passes": [
"first_spend_baton_tracker"
],
"name": "unlock_baton_tracker",
"script": "// Baton NFT output index\nindex_baton_output\n// Baton NFT input index\nindex_baton_input\n// Owner NFT input index\n<0x0200>\n// Owner change output index\n<0x0200>\n// Tracker change\n<0x0100>",
"unlocks": "baton_tracker"
},
"baton_current": {
"lockingType": "p2sh20",
"name": "baton_current",
"script": "// Verify the commitment to current metadata\nOP_DUP OP_HASH256\n<$(macro_metadata_blob_current OP_HASH256)>\nOP_EQUALVERIFY\n\n// Input's unlocking data must have exactly 4 pushes\nOP_DEPTH <4> OP_EQUALVERIFY\n\n// Compute the commitment to new metadata\n<1> OP_PICK OP_HASH256\n// Construct variable part of new redeem script\n<OP_DUP OP_HASH256 0x20> OP_SWAP OP_CAT\n// Append the invariant part of redeem script\nOP_ACTIVEBYTECODE <35> OP_SPLIT OP_NIP OP_CAT\n// Compute new redeem script hash\nOP_HASH160\n// Construct new metadata address\n<OP_HASH160 0x14> OP_SWAP OP_CAT <OP_EQUAL> OP_CAT\n// Verify it against the referenced output\n<3> OP_ROLL OP_BIN2NUM\nOP_OUTPUTBYTECODE OP_DUP\nOP_ROT\nOP_EQUAL\n// Alternatively, allow a burn to OP_RETURN\nOP_SWAP <OP_RETURN>\nOP_EQUAL\nOP_ADD\nOP_VERIFY\n\nOP_2DROP\n\n// Verify baton tracker back-reference\nOP_BIN2NUM OP_DUP\nOP_INPUTBYTECODE\n<3> OP_SPLIT OP_DROP <1> OP_SPLIT OP_NIP OP_BIN2NUM\nOP_INPUTINDEX\nOP_EQUALVERIFY\n\n// Verify baton tracker\nOP_UTXOBYTECODE\n<$(<OP_HASH160 0x14> <baton_tracker> OP_HASH160 <OP_EQUAL> OP_CAT OP_CAT)>\nOP_EQUAL"
},
"baton_constructor": {
"lockingType": "p2sh20",
"name": "baton_constructor",
"script": ""
},
"baton_new": {
"lockingType": "p2sh20",
"name": "baton_new",
"script": "// Verify the commitment to current metadata\nOP_DUP OP_HASH256\n<$(macro_metadata_blob_new OP_HASH256)> OP_EQUALVERIFY\n\n// Input's unlocking data must have exactly 4 pushes\nOP_DEPTH <4> OP_EQUALVERIFY\n\n// Compute the commitment to new metadata\n<1> OP_PICK OP_HASH256\n// Construct variable part of new redeem script\n<OP_DUP OP_HASH256 0x20> OP_SWAP OP_CAT\n// Append the invariant part of redeem script\nOP_ACTIVEBYTECODE <35> OP_SPLIT OP_NIP OP_CAT\n// Compute new redeem script hash\nOP_HASH160\n// Construct new metadata address\n<OP_HASH160 0x14> OP_SWAP OP_CAT <OP_EQUAL> OP_CAT\n// Verify it against the referenced output\n<3> OP_ROLL OP_BIN2NUM\nOP_OUTPUTBYTECODE OP_DUP\nOP_ROT\nOP_EQUAL\n// Alternatively, allow a burn to OP_RETURN\nOP_SWAP <OP_RETURN>\nOP_EQUAL\nOP_ADD\nOP_VERIFY\n\nOP_2DROP\n\n// Verify baton tracker back-reference\nOP_BIN2NUM OP_DUP\nOP_INPUTBYTECODE\n<3> OP_SPLIT OP_DROP <1> OP_SPLIT OP_NIP OP_BIN2NUM\nOP_INPUTINDEX\nOP_EQUALVERIFY\n\n// Verify baton tracker\nOP_UTXOBYTECODE\n<$(<OP_HASH160 0x14> <baton_tracker> OP_HASH160 <OP_EQUAL> OP_CAT OP_CAT)>\nOP_EQUAL"
},
"baton_tracker": {
"lockingType": "p2sh20",
"name": "baton_tracker",
"script": "// Hardcode tracker category\n<0xdead00000000000000000000000000000000000000000000000000000000beef>\n\n// Verify tracker input\n// Verify tracker input category\nOP_INPUTINDEX\nOP_UTXOTOKENCATEGORY\nOP_EQUALVERIFY\n// Verify tracker input commitment\nOP_INPUTINDEX OP_UTXOTOKENCOMMITMENT\n<0x00>\nOP_EQUALVERIFY\n\n// Owner and tracker change can't be the same output\nOP_2DUP OP_EQUAL OP_NOT OP_VERIFY\n\n// Verify tracker change output\n// Verify tracker change output category\nOP_BIN2NUM OP_DUP\nOP_OUTPUTTOKENCATEGORY\nOP_INPUTINDEX OP_UTXOTOKENCATEGORY\nOP_EQUALVERIFY\n// Verify tracker change output commitment\nOP_DUP\nOP_OUTPUTTOKENCOMMITMENT\nOP_INPUTINDEX OP_UTXOTOKENCOMMITMENT\nOP_EQUALVERIFY\n// Verify tracker change output locking script\nOP_OUTPUTBYTECODE\nOP_INPUTINDEX OP_UTXOBYTECODE\nOP_EQUALVERIFY\n\n// Verify owner change output\n// Verify owner change output commitment\nOP_BIN2NUM OP_DUP\nOP_OUTPUTTOKENCOMMITMENT\nOP_INPUTINDEX OP_UTXOTOKENCOMMITMENT\nOP_EQUALVERIFY\n// Verify owner change output category\nOP_OUTPUTTOKENCATEGORY\nOP_INPUTINDEX OP_UTXOTOKENCATEGORY\nOP_EQUALVERIFY\n\n// Verify owner input\n// Tracker input cannot be the owner\nOP_BIN2NUM OP_DUP\nOP_INPUTINDEX\nOP_EQUAL OP_NOT OP_VERIFY\n// Verify owner input commitment\nOP_DUP\nOP_UTXOTOKENCOMMITMENT\nOP_INPUTINDEX\nOP_UTXOTOKENCOMMITMENT\nOP_EQUALVERIFY\n// Verify owner input category\nOP_UTXOTOKENCATEGORY\nOP_INPUTINDEX OP_UTXOTOKENCATEGORY\nOP_EQUALVERIFY\n\n// Verify baton input commitment\nOP_BIN2NUM OP_DUP\nOP_UTXOTOKENCOMMITMENT\n<0x01> OP_EQUALVERIFY\n\n// Verify baton input category\nOP_DUP\nOP_UTXOTOKENCATEGORY\nOP_INPUTINDEX OP_UTXOTOKENCATEGORY\nOP_EQUALVERIFY\n\nOP_SWAP\n\n// Verify baton output commitment\nOP_BIN2NUM OP_DUP\nOP_OUTPUTTOKENCOMMITMENT\n<0x01> OP_EQUALVERIFY\n\n// Verify baton output category\nOP_DUP\nOP_OUTPUTTOKENCATEGORY\nOP_INPUTINDEX OP_UTXOTOKENCATEGORY\nOP_EQUALVERIFY\n\nOP_SWAP\n\n// Check if baton input and output token amount is the same,\n// we will use the result later\nOP_2DUP\nOP_UTXOTOKENAMOUNT\nOP_SWAP\nOP_OUTPUTTOKENAMOUNT\nOP_EQUAL\nOP_ROT\n// Verify Baton Contents\nOP_INPUTBYTECODE\n// Verify back-reference\n<3> OP_SPLIT OP_SWAP <1> OP_SPLIT OP_BIN2NUM\nOP_INPUTINDEX\nOP_EQUALVERIFY\n<2> OP_EQUALVERIFY\n// Verify both are validating against same output\n<3> OP_SPLIT OP_SWAP <1> OP_SPLIT OP_BIN2NUM\n<4> OP_ROLL OP_EQUALVERIFY\n<2> OP_EQUALVERIFY\n// Get new metadata blob\n<1> OP_SPLIT OP_SWAP <0x4b> OP_SUB OP_SPLIT OP_SWAP <0x00> OP_CAT OP_BIN2NUM OP_SPLIT\n// Get old metadata blob\n<1> OP_SPLIT OP_SWAP <0x4b> OP_SUB OP_SPLIT OP_SWAP <0x00> OP_CAT OP_BIN2NUM OP_SPLIT\n// Get redeem script\n<1> OP_SPLIT OP_SWAP <0x4b> OP_SUB OP_SPLIT OP_SWAP <0x00> OP_CAT OP_BIN2NUM OP_SPLIT <0> OP_EQUALVERIFY\n\n// Verify baton contract template\n<3> OP_SPLIT\n<32> OP_SPLIT\nOP_SIZE <24> OP_SUB OP_SPLIT\n<23> OP_SPLIT\n<OP_EQUAL>\nOP_EQUALVERIFY\nOP_INPUTINDEX OP_UTXOBYTECODE\nOP_EQUALVERIFY\nOP_HASH256\n<macro_baton_invariant_sha256>\nOP_EQUALVERIFY\nOP_DROP\n<OP_DUP OP_HASH256 0x20>\nOP_EQUALVERIFY\n\n// Parse current metadata\n<1> OP_SPLIT OP_OVER OP_BIN2NUM <1> OP_LESSTHANOREQUAL OP_VERIFY\n<8> OP_SPLIT\n<1> OP_SPLIT OP_SWAP OP_SPLIT\n<1> OP_SPLIT OP_OVER OP_BIN2NUM <9> OP_LESSTHANOREQUAL OP_VERIFY\n<1> OP_SPLIT OP_SWAP OP_SPLIT\n<1> OP_SPLIT OP_SWAP OP_SPLIT\n<1> OP_SPLIT OP_SWAP OP_SPLIT\n<1> OP_SPLIT OP_SWAP OP_SPLIT\n<1> OP_SPLIT OP_SWAP OP_SPLIT\nOP_SIZE <1> OP_EQUALVERIFY\n\n// Parse new metadata\n<10> OP_ROLL\n<1> OP_SPLIT OP_OVER OP_BIN2NUM <1> OP_LESSTHANOREQUAL OP_VERIFY\n<8> OP_SPLIT\n<1> OP_SPLIT OP_SWAP OP_SPLIT\n<1> OP_SPLIT OP_OVER OP_BIN2NUM <9> OP_LESSTHANOREQUAL OP_VERIFY\n<1> OP_SPLIT OP_SWAP OP_SPLIT\n<1> OP_SPLIT OP_SWAP OP_SPLIT\n<1> OP_SPLIT OP_SWAP OP_SPLIT\n<1> OP_SPLIT OP_SWAP OP_SPLIT\n<1> OP_SPLIT OP_SWAP OP_SPLIT\nOP_SIZE <1> OP_EQUALVERIFY\n\n// Verify that metadata locks are correctly passed on\n<10> OP_PICK\n<0xff> OP_XOR\nOP_AND OP_BIN2NUM\nOP_NOT OP_VERIFY\n\n// Get current metadata locks\n<9> OP_ROLL\n\n// Verify metadata field 1 lock\nOP_DUP <0x01> OP_AND OP_BIN2NUM OP_0NOTEQUAL\nOP_ROT <11> OP_ROLL\nOP_EQUAL\nOP_ADD\nOP_VERIFY\n\n// Verify metadata field 2 lock\nOP_DUP <0x02> OP_AND OP_BIN2NUM OP_0NOTEQUAL\nOP_ROT <10> OP_ROLL\nOP_EQUAL\nOP_ADD\nOP_VERIFY\n\n// Verify metadata field 3 lock\nOP_DUP <0x04> OP_AND OP_BIN2NUM OP_0NOTEQUAL\nOP_ROT <9> OP_ROLL\nOP_EQUAL\nOP_ADD\nOP_VERIFY\n\n// Verify metadata field 4 lock\nOP_DUP <0x08> OP_AND OP_BIN2NUM OP_0NOTEQUAL\nOP_ROT <8> OP_ROLL\nOP_EQUAL\nOP_ADD\nOP_VERIFY\n\n// Verify metadata field 5 lock\nOP_DUP <0x10> OP_AND OP_BIN2NUM OP_0NOTEQUAL\nOP_ROT <7> OP_ROLL\nOP_EQUAL\nOP_ADD\nOP_VERIFY\n\n// Verify metadata field 6 lock\nOP_DUP <0x20> OP_AND OP_BIN2NUM OP_0NOTEQUAL\nOP_ROT <6> OP_ROLL\nOP_EQUAL\nOP_ADD\nOP_VERIFY\n\n// Verify that genesis first owner record is correctly passed on\nOP_DROP\n<3> OP_ROLL\nOP_EQUALVERIFY\n\n// Verify that genesis initial supply record is correctly passed on\n<2> OP_ROLL\nOP_EQUALVERIFY\n\n// Verify token supply lock\nOP_BIN2NUM OP_DUP OP_ROT\nOP_BIN2NUM\nOP_LESSTHANOREQUAL\nOP_VERIFY\n// Will be >0 if supply didn't change or if it is unlocked.\nOP_ADD"
},
"macro_metadata_blob_new": {
"name": "macro_metadata_blob_new",
"script": "<$(\n// Token supply lock (0x00-locked, 0x01-open)\nbaton_new_supply_lock <1> OP_NUM2BIN\n// Token invariants\n // Genesis supply\n genesis_supply <8> OP_NUM2BIN \n OP_CAT\n // Genesis supply policy (first owner's address)\n genesis_policy\n OP_SIZE <1> OP_NUM2BIN OP_SWAP\n OP_CAT OP_CAT\n// Token metadata\n // Decimals\n baton_new_decimals <1> OP_NUM2BIN\n OP_CAT\n // Ticker\n baton_new_ticker\n OP_SIZE <1> OP_NUM2BIN OP_SWAP\n OP_CAT OP_CAT\n // Name\n baton_new_name\n OP_SIZE <1> OP_NUM2BIN OP_SWAP\n OP_CAT OP_CAT\n // Document hash\n baton_new_document_hash\n OP_SIZE <1> OP_NUM2BIN OP_SWAP\n OP_CAT OP_CAT\n // Document\n baton_new_document\n OP_SIZE <1> OP_NUM2BIN OP_SWAP\n OP_CAT OP_CAT\n // Back-validation API\n baton_new_back_validation\n OP_SIZE <1> OP_NUM2BIN OP_SWAP\n OP_CAT OP_CAT\n // Metadata locks (bit flags, 0-locked, 1-open)\n baton_new_metadata_locks\n OP_CAT\n)>"
},
"burn_opreturn": {
"name": "burn_opreturn",
"script": "OP_RETURN"
},
"macro_metadata_blob_current": {
"name": "macro_metadata_blob_current",
"script": "<$(\n// Token supply lock (0x00-locked, 0x01-open)\nbaton_current_supply_lock <1> OP_NUM2BIN\n// Token invariants\n // Genesis supply\n genesis_supply <8> OP_NUM2BIN \n OP_CAT\n // Genesis supply policy (first owner's address)\n genesis_policy\n OP_SIZE <1> OP_NUM2BIN OP_SWAP\n OP_CAT OP_CAT\n// Token metadata\n // Decimals\n baton_current_decimals <1> OP_NUM2BIN\n OP_CAT\n // Ticker\n baton_current_ticker\n OP_SIZE <1> OP_NUM2BIN OP_SWAP\n OP_CAT OP_CAT\n // Name\n baton_current_name\n OP_SIZE <1> OP_NUM2BIN OP_SWAP\n OP_CAT OP_CAT\n // Document hash\n baton_current_document_hash\n OP_SIZE <1> OP_NUM2BIN OP_SWAP\n OP_CAT OP_CAT\n // Document\n baton_current_document\n OP_SIZE <1> OP_NUM2BIN OP_SWAP\n OP_CAT OP_CAT\n // Back-validation API\n baton_current_back_validation\n OP_SIZE <1> OP_NUM2BIN OP_SWAP\n OP_CAT OP_CAT\n // Metadata locks (bit flags, 0-locked, 1-open)\n baton_current_metadata_locks\n OP_CAT\n)>"
},
"macro_baton_invariant_sha256": {
"name": "macro_baton_invariant_sha256",
"script": "$(\n<\n\nOP_EQUALVERIFY\n\n// Input's unlocking data must have exactly 4 pushes\nOP_DEPTH <4> OP_EQUALVERIFY\n\n// Compute the commitment to new metadata\n<1> OP_PICK OP_HASH256\n// Construct variable part of new redeem script\n<OP_DUP OP_HASH256 0x20> OP_SWAP OP_CAT\n// Append the invariant part of redeem script\nOP_ACTIVEBYTECODE <35> OP_SPLIT OP_NIP OP_CAT\n// Compute new redeem script hash\nOP_HASH160\n// Construct new metadata address\n<OP_HASH160 0x14> OP_SWAP OP_CAT <OP_EQUAL> OP_CAT\n// Verify it against the referenced output\n<3> OP_ROLL OP_BIN2NUM\nOP_OUTPUTBYTECODE OP_DUP\nOP_ROT\nOP_EQUAL\n// Alternatively, allow a burn to OP_RETURN\nOP_SWAP <OP_RETURN>\nOP_EQUAL\nOP_ADD\nOP_VERIFY\n\nOP_2DROP\n\n// Verify baton tracker back-reference\nOP_BIN2NUM OP_DUP\nOP_INPUTBYTECODE\n<3> OP_SPLIT OP_DROP <1> OP_SPLIT OP_NIP OP_BIN2NUM\nOP_INPUTINDEX\nOP_EQUALVERIFY\n\n// Verify baton tracker\nOP_UTXOBYTECODE\n\n>\n<0x17> OP_CAT\nOP_HASH256 \n) "
}
},
"supported": [
"BCH_SPEC"
],
"version": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment