Bitcoin contracts

11 min read

function parseInto(source, editor) { internals.readTransactionFromHexString(source.get()).then(function(tx) { editor.set(JSON.stringify(tx, null, 2)); }, function(e) { editor.set("// parse error: " + e); }); } parseInto(source, target);

Bitcoin is designed to support a wide variety of transaction types. Although currently the majority of transactions are standard payments to address it is possible to build more complex protocols.

Block chain can be used to build agreements between people that do not require trust or central authorities. Properties exchanged via the block chain may even be physical things like cars.

Bitcoin achieves high flexibility due to three features:

scripts — unlocking funds in transactions is done using a simple scripting language, signature hash flags — indicate which parts of the transaction are signed, sequence numbers and lock time — mark transactions as not valid until specified time.

This implementation uses several ES6 features not yet enabled by default in Chrome (version 36). It is necessary to enable Experimental JavaScript at chrome://flags/#enable-javascript-harmony .

Firefox (version 31) supports generators as well as Promises.

ES6 generators

JavaScript Promises

Stack visualization uses position: sticky CSS property that can be enabled by Experimental Web Platform Features at chrome://flags/#enable-experimental-web-platform-features in Chrome or layout.css.sticky.enabled toggle at about:config in Firefox.

Standard transaction Most of Bitcoin transactions are sending funds to an address. Addresses are encoded public key hashes with a checksum. Sending bitcoins to an address internally creates a transaction containing a script with embedded public key hash. This script checks if the spending transaction is signed by a correct key. The address below is a version 1 bitcoin address: 1DTjvhLV6S72NQrSDrCX1GTCb9B3D5pmCB Decoding it using the base58 encoding yields a byte array: … This array can be split into three parts. First byte is a version tag ( … ), last 4 bytes are used as a checksum ( … ) and the rest is a public key hash: … The checksum is verified by using the SHA-256 function on the version and the public key hash twice and taking first four bytes of the digest: … The address above is …. The extracted public key hash is used to construct the output script. The script will unlock funds only when the next transaction provides two parameters — the public key that hashes to the given hash and a signature created using the private key that matches that public key. var hex = internals.hex; var bytes = internals.base58.decode(address.get()); intro.querySelector('.hex').textContent = hex.encode(bytes); var checksum = hex.encode(bytes.splice(bytes.length - 4, 4)); intro.querySelector('.version').textContent = hex.encode([bytes[0]]); intro.querySelector('.checksum').textContent = checksum; intro.querySelector('.pubkeyhash').textContent = hex.encode(bytes.slice(1)); var sha = hex.encode(digest.sha256(digest.sha256(bytes))); intro.querySelector('.sha').innerHTML = "<strong>" + sha.substring(0, 8) + "</strong>" + sha.substring(9); var validity = intro.querySelector('.validity'); validity.textContent = sha.substring(0, 8) === checksum ? "valid" : "invalid"; validity.className = sha.substring(0, 8) === checksum ? "success icon-ok validity" : "failure icon-cancel validity"; 082eae... in #0 out #0 8d212a... in #0 out #0 Transaction of the left ( 082eae ) transfers ownership of bitcoins to the address 1DTjvhLV6S72NQrSDrCX1GTCb9B3D5pmCB by setting up a short script in one of its outputs. Output #0’s script contains the following five operators: OP_DUP — duplicates an item on the stack, OP_HASH160 — hashes top-most item on the stack twice — once with SHA-256 and then with RIPEMD-160, 88b028348642ad1bbaa8fcc054273070eda045fe — pushes this byte vector onto the stack, OP_EQUALVERIFY — takes two top-most items on the stack and checks if they are equal, if not the entire script execution fails, OP_CHECKSIG — verifies if the current transaction is signed by the correct key (the private key that corresponds to the public key that was hashed earlier). The output script can be also represented in a simple programming language as a list of parameters that will be provided by spending the transaction’s input script ( assume statements) and list of assertions that should be met to move funds ( verify statements). assume signature, pubKey verify hash160(pubKey) == '88b028348642ad1bbaa8fcc054273070eda045fe' verify checkSig(signature, pubKey) Compiling to the Bitcoin Script results in these opcodes: … var str; try { str = superscript.compile(input.get()).join('

'); } catch (e) { str = "// Error: " + e; } output.textContent = str; Executing script When a different transaction wants to claim the coins sent to this output it has to provide a second part of the script — the input script. The input script is also called scriptSig as it usually contains signatures. These two scripts — the input script and the output script — are executed in that order and if the execution completes successfully and leaves a truthy item on the top of the stack then the transaction is considered valid. The input script (two opcodes) from the spending transaction is concatenated with the output script from the first one: Stack: // input script 3045022100de14671eaebfe7eaa085e100f40b4a452fdd3a55975a9007062de361dfc4ccb302207a00ee3ec2341a36effa37d0b7b196202348f0840d6b46fa111d040827d1f39b01 0381fa985809e1a23fc261cb4c02ffdc968a1d2548f40428af1931c3e706f5c7d4 // output script OP_DUP OP_HASH160 88b028348642ad1bbaa8fcc054273070eda045fe OP_EQUALVERIFY OP_CHECKSIG

Raw transactions Raw bytes of the transaction on the left: 010000000192572bd6cb7e01247c7f876d63e79e754d7c1e246eda3f2ccf5305b97dc67e73000000006a47304402203a21c63594018be1f0d475ad4cd8e3f6a9465c18ff14ee3da489be8d32690819022019bf6f328c128dcab3cea878cbf2b87efaf4922a0915f8603bef9126eb57ea53012102744bd7d38356ab4563a91b3a2a8aae190feec76cf2e329f488bf429c7b351752ffffffff01b0360000000000001976a91488b028348642ad1bbaa8fcc054273070eda045fe88ac00000000 Parsed into a JavaScript object reveal the transaction’s structure — version field that is currently always 1, lockTime that allows creating transactions that will become valid in the future and a list of inputs and outputs. // click Parse Each input references the output in a different transaction (with an exception of inputs in generation transactions), has a sequence number that allows updating that input and a script. Scripts in standard transaction’s inputs push a signature and a public key byte arrays onto the stack. Outputs contain only the value in satoshi that is assigned to this output and the output script that will decide whether a different transaction’s input can claim this output’s coins. Raw transaction on the right: 0100000001c21ae5cfc3a73eba85ad9c7d06304840b1e3f0d147feea41f62ab3392dae2e08000000006b483045022100de14671eaebfe7eaa085e100f40b4a452fdd3a55975a9007062de361dfc4ccb302207a00ee3ec2341a36effa37d0b7b196202348f0840d6b46fa111d040827d1f39b01210381fa985809e1a23fc261cb4c02ffdc968a1d2548f40428af1931c3e706f5c7d4ffffffff01c8320000000000001976a914f4f1d83d4ce7b5a3d2dfb2384af09f6d95c8279388ac00000000 Parsed into a JavaScript object: // click Parse

Escrow Standard transactions require exactly one key pair to unlock. Using the OP_CHECKMULTISIG operator instead of the OP_CHECKSIG in the output script allows creating transactions that need several keys to unlock funds. A classic example is an escrow where a trusted third party (broker) is used between the merchant and the client to secure funds. A transaction is set up that requires two keys out of three (merchant, client and a trusted party) to move coins. If a good is delivered then the merchant and the client agree to move funds to the merchant’s account. If the merchant fails to send the good, the client and the trusted party move funds back to the client. And if the merchant can prove to the broker that the good was indeed sent then that third party and the merchant send coins to the merchant’s account. Another example of using the OP_CHECKMULTISIG requires both husband and wife agreeing to paying for something or using multiple keys to protect coins in a cold storage. 4bfd9c... in #0 out #0 out #1 436a9a... in #0 out #0 Left transaction’s output #1 contains a script that uses OP_CHECKMULTISIG: OP_2 — pushes digit 2 on the stack (number of required signatures), 041ce544058996033a34adb07be380e63956c588… — pushes first public key, 04db5efff14362653c0fc2e5437ac964dd3e0931… — pushes second public key, 043b9264a9afb2c9dbc3602cf25ab9a5f5ee1f99… — pushes third public key, OP_3 — pushes digit 3 on the stack (number of provided public keys), OP_CHECKMULTISIG — takes a number of public keys, then these public keys, then a number of signatures and these signatures and performs the signature verification, if all signatures are valid pushes true on the stack, false otherwise. The output script represented in a simple programming language: assume unused, signature1, signature2 let pubKeyA = '041ce544058996033a34adb07be380e63956c588dd036d20824447d88700ec91f45a98894bbbdab68ac304b5e68f77ea2f614516d0ace35f76e3b376b9917d6c84' let pubKeyB = '04db5efff14362653c0fc2e5437ac964dd3e093110c8fbcd5d9fd135ec3c98dc926d26b344def4397c3d99ebbd56e35c53cdd501e2c7a9a0cc5c2b04e7d0a38751' let pubKeyC = '043b9264a9afb2c9dbc3602cf25ab9a5f5ee1f991e6edfb9c2982a9d31cd7e41c2c9c2a8ad2a8da0c8943b54192c9fea120bf5cce390b459269698efaadb42d649' verify checkMultiSig(2, pubKeyA, pubKeyB, pubKeyC, 3) Compiling to the Bitcoin Script results in these opcodes: … Executing script The input script (three opcodes) from the spending transaction is concatenated with the output script from the first one: Stack: // input script OP_FALSE 30450220523b47504644354214e847d3a91337516835591e25b5eaeefb8c349823c5ff92022100e4fc44e18a252c853495923f0f88668f1aa539f5c69418dfb392d77cff84049c01 3046022100ab63540868657b7674a77c1fc691f6842d8d15f825241d7ad12fb1ff87e63de3022100dec537d994abccebac546bc260f0dbbed6135c7d470f35409a21d21746380fe601 // output script OP_2 041ce544058996033a34adb07be380e63956c588dd036d20824447d88700ec91f45a98894bbbdab68ac304b5e68f77ea2f614516d0ace35f76e3b376b9917d6c84 04db5efff14362653c0fc2e5437ac964dd3e093110c8fbcd5d9fd135ec3c98dc926d26b344def4397c3d99ebbd56e35c53cdd501e2c7a9a0cc5c2b04e7d0a38751 043b9264a9afb2c9dbc3602cf25ab9a5f5ee1f991e6edfb9c2982a9d31cd7e41c2c9c2a8ad2a8da0c8943b54192c9fea120bf5cce390b459269698efaadb42d649 OP_3 OP_CHECKMULTISIG One extra argument ( OP_FALSE ) is needed in the input script due to a bug in OP_CHECKMULTISIG .

Raw transactions The first transaction is a lot longer than the standard one because output #1 contains full public keys and not just their hashes. Raw bytes of the transaction on the left: 0100000001c532b97ded19882906d4f8cfb2f5df927010e57cc17816f44a76d28a5b22d650000000008c493046022100fb0c6b6ab08420425e054e4bbc7d2f022229619ad94dcfe6a5091c43b11b8dff02210097ea263ca74fd561470e1e7da37708faa19661963fc388644c83dbb7914aca8601410413a73711ae2ff667b1b4bf60c5cdf1f63f972cbc7c5fbadc50dc5510dc9d25930c2536b6432c8ab8d8ddadb55a96e5ad957fd2f835bc9b6949a86efa3a65d3acffffffff0290d00300000000001976a9148dc294df289c81d6eb61f72475061ee4da2ee5f988ac7082030000000000c95241041ce544058996033a34adb07be380e63956c588dd036d20824447d88700ec91f45a98894bbbdab68ac304b5e68f77ea2f614516d0ace35f76e3b376b9917d6c844104db5efff14362653c0fc2e5437ac964dd3e093110c8fbcd5d9fd135ec3c98dc926d26b344def4397c3d99ebbd56e35c53cdd501e2c7a9a0cc5c2b04e7d0a3875141043b9264a9afb2c9dbc3602cf25ab9a5f5ee1f991e6edfb9c2982a9d31cd7e41c2c9c2a8ad2a8da0c8943b54192c9fea120bf5cce390b459269698efaadb42d64953ae00000000 Transaction object: // click Parse Raw bytes of the transaction on the right: 0100000001c68db8fc6652dc9d7c7a58e48c118c42086f670dd8f87987625cc910ef9cfd4b0100000094004830450220523b47504644354214e847d3a91337516835591e25b5eaeefb8c349823c5ff92022100e4fc44e18a252c853495923f0f88668f1aa539f5c69418dfb392d77cff84049c01493046022100ab63540868657b7674a77c1fc691f6842d8d15f825241d7ad12fb1ff87e63de3022100dec537d994abccebac546bc260f0dbbed6135c7d470f35409a21d21746380fe601ffffffff01605b0300000000001976a9149bfdf3e906ce07448dac85ce385ab6bdad7e7b8188ac00000000 Transaction object: // click Parse

Kickstarter Each signature used in input scripts contains a flags field indicating which parts of the transaction are signed. Using this field it is possible to implement crowdfunding campaign (or any other assurance contract). An entrepreneur announces that they will complete a project only when a specified amount of bitcoins (for example 150 μBTC) is collected. Backers who want to pledge money create transactions sending bitcoins (for example 50 μBTC) to this address, setting the output value to the target amount (150 μBTC) and sign it with SIGHASH_ANYONECANPAY flag. These pledge transactions are not broadcast but are sent directly to the entrepreneur. As the output value (150 μBTC) is higher than the input value (50 μBTC) it is impossible for the entrepreneur to retrieve bitcoins from these transactions directly. The SIGHASH_ANYONECANPAY flag allows merging transaction inputs. When enough funds have been gathered (the sum of inputs is higher than target value) the entrepreneur creates one final transaction from all pledges and broadcasts it collecting all the funds. Creating pledges Backers create pledge transactions (on the right) that take a small amount of bitcoins (50 μBTC) and set output to target value (150 μBTC). All pledges have one and the same output containing amount and receiving address of the entrepreneur. 878d07... in #0 out #0 443de4... in #0 out #0 86626c... in #0 out #0 f392df... in #0 out #0 c21484... in #0 out #0 e18f50... in #0 out #0 83e1bb... in #0 out #0 33e4d7... in #0 out #0

Raw transaction Raw bytes of the transaction on the left: 01000000011f5e7131923054920104e5080983572c6e29366d0c7f95548398e7a1c80dfa23500000006b4830450221009ce31d9d621c4ef2a753cb238d8bbb4b02edaf17cea98d95945011b84448bd39022010c699f51a8d1399748ce57b3db3ccd7a076872fd564492df96b1c7ff5ad57e5012103a72a9fc1615f45b461534c0a035ea4ea228f86c11f52dbfa6997f1483dbcc21bffffffff0188130000000000001976a914da8df9cc99e719562b52c209ebea7e28b8b3c60b88ac00000000 Transaction object: // click Parse

Raw transaction — pledge Raw bytes of the transaction on the right: 0100000001b6c88c761235e7ccc6ee59d53348537c94a4fe1adaf04c92ce767b4f4c078d87000000006a4730440220207ab184b288275c6466075d724a9f632487b6996489d49c8148cf30f9d5fc1a0220518b62471a25f8da86d0184de5b0496d4c2b272115c84fa58ea32e568b53053d8121032153889b1813175f337f24944ff632a6b9a78b63e09ff8c6a569f5d5d429cf97ffffffff01983a0000000000001976a91454000657e2b8ebed5b1a1565b17aec63583ddc6688ac00000000 Transaction object: // click Parse

Collecting funds When the entrepreneur receives enough funds (the sum of inputs is higher than 150 μBTC) they create the final transaction that takes all inputs from pledges and one output (the same output that is used in all pledges). Because the inputs were signed by backers with the SIGHASH_ANYONECANPAY flag the signatures are still valid. The final transaction is broadcast and the entrepreneur collects all the pledges. 878d07... in #0 out #0 443de4... in #0 out #0 86626c... in #0 out #0 f392df... in #0 out #0 737ec6... in #0 in #1 in #2 in #3 out #0

Raw final transaction Raw bytes of the final transaction on the right: 0100000004b6c88c761235e7ccc6ee59d53348537c94a4fe1adaf04c92ce767b4f4c078d87000000006a4730440220207ab184b288275c6466075d724a9f632487b6996489d49c8148cf30f9d5fc1a0220518b62471a25f8da86d0184de5b0496d4c2b272115c84fa58ea32e568b53053d8121032153889b1813175f337f24944ff632a6b9a78b63e09ff8c6a569f5d5d429cf97ffffffff064a3e45ad865f6ee493e0d1dc48d54f8f275ddf5f9f271cae1d294d70e43d44000000006b483045022059f303e73e34d3e56bc6a91ee02248da2ff12ffcdf8b676bc743f886c90ef165022100a4d7e00e4d325fe7e7406757bc9647e2f4f620ceb30ce759e22ecb88fc67f8b081210341607135b7e955eacd6d14018348911c5fc7b930af359ee9ced887f175ba89c4fffffffff0f231fc2ac7fdc5a62836127a747b795931f65a9a4b7379448521617b6c6286000000006a473044022001e345ebcc3e8c0673a77dd9e5fa2bf3d0fa295c7eb867edd4e9269b5bd4e8d002200970be9d82380a4cb7b7778fe078992b65199a5f77e07f953119f44ced6e7a5a8121033a76c02081da7453bc040f781959cca920f19cc2344731510bd81cde3469febfffffffff84639d836b4c7558f815a53fbcaed239f5383dec4e4d6a61c79cd0ff8adf92f3000000006b48304502200a513923f5e71f9f84377a605d38ecb7978d3ea013a58e60bce77ac1c8b94bc5022100d1b9547e610ce4022877dc95ab7cbd9538679a7ecd04f7da300270871b53256e81210341607135b7e955eacd6d14018348911c5fc7b930af359ee9ced887f175ba89c4ffffffff01983a0000000000001976a91454000657e2b8ebed5b1a1565b17aec63583ddc6688ac00000000 Transaction object: // click Parse Executing script The following script validates the first input in the final transaction. The only difference between this script and the standard transaction’s is the signature hash type ( 81 — ALL with ANYONECANPAY flag) at the end of the backer’s signature (line 2). Standard transactions are signed with ALL ( 01 ). Stack: // input script 30440220207ab184b288275c6466075d724a9f632487b6996489d49c8148cf30f9d5fc1a0220518b62471a25f8da86d0184de5b0496d4c2b272115c84fa58ea32e568b53053d81 032153889b1813175f337f24944ff632a6b9a78b63e09ff8c6a569f5d5d429cf97 // output script OP_DUP OP_HASH160 da8df9cc99e719562b52c209ebea7e28b8b3c60b OP_EQUALVERIFY OP_CHECKSIG

Multilottery One example that uses both time-locked transactions and non-standard scripts is the decentralized lottery. This scheme allows multiple users to gamble bitcoins so that one of them — randomly — wins. The protocol is composed out of two parts: Open — all users create strings of random data and publish hashes of these strings. Then they create transactions that forces them to reveal the data in the second phase or pay a fine to the rest of the players. Gamble — users create a gamble transaction that contains all those hashes and sign it. Then they reveal their secret strings and the lottery winner claims the coins. The example below uses three players that randomly choose a number (0, 1 or 2). If sum of their numbers modulo 3 is 0 the first player wins, if it is 1 the second player wins and if it is 2 the third player wins. To make the lottery secure against brute force attacks players use long strings of random data instead of their random numbers directly. If the drawn number is 0 the player uses a string of length 32, if it is 1 — 33 and if it is 2 — 34.

Open phase 7ae576... in #0 out #0 be7749... in #0 out #0 b78a94... in #0 out #0 Users create and broadcast transaction that requires either one signature and a secret string or two signatures to unlock. Owner’s signature and secret string — forces user to reveal the secret string.

Two signatures — used when the owner does not reveal the secret string. This transaction is given to other users and is time-locked so that the owner has enough time to reveal the secret. assume signatureA, signatureB, secret let secretKnown = sha256(secret) == '527ccdd755dcccf03192383624e0a7d0263815ce2ecf1f69cb0423ab7e6f0f3e' let pubKeyA = '04d4bf4642f56fc7af0d2382e2cac34fa16ed3321633f91d06128f0e5c0d17479778cc1f2cc7e4a0c6f1e72d905532e8e127a031bb9794b3ef9b68b657f51cc691' let pubKeyB = '04c9ce67ff2df2cd6be5f58345b4e311c5f10aab49d3cf3f73e8dcac1f9cd0de966e924be091e7bc854aef0d0baafa80fe5f2d6af56b1788e1e8ec8d241b41c40d' let signedByA = checkSig(signatureA, pubKeyA) let signedByB = checkSig(signatureB, pubKeyB) verify (secretKnown || signedByB) && signedByA Compiling to Bitcoin Script results in opcodes: … Open phase — Executing reveal script The input script (three opcodes) from the spending transaction is concatenated with the output script from the first one: Stack contents: // input script 30440220749de3ac2a014374ca7952ebbbd5e094ed45c90f1d069d392c2c0589e3812e330220261f1d1184a4d1b4b4424d710a19dcff492404e1831a6ef8e251000b7f8de95d01 30450220363ee61c89c8369df409c186f099c60e128b758e64364100011c39df91141c3b022100ab26b4a7c2bbd3c14ef30d71d063c8a0db61a20e4dd856fbffe60ca26ea0f15e01 ca42095840735e89283fec298e62ac2ddea9b5f34a8cbb7097ad965b87568123 // output script OP_SHA256 527ccdd755dcccf03192383624e0a7d0263815ce2ecf1f69cb0423ab7e6f0f3e OP_EQUAL OP_SWAP 04d4bf4642f56fc7af0d2382e2cac34fa16ed3321633f91d06128f0e5c0d17479778cc1f2cc7e4a0c6f1e72d905532e8e127a031bb9794b3ef9b68b657f51cc691 OP_CHECKSIG OP_BOOLOR OP_SWAP 04c9ce67ff2df2cd6be5f58345b4e311c5f10aab49d3cf3f73e8dcac1f9cd0de966e924be091e7bc854aef0d0baafa80fe5f2d6af56b1788e1e8ec8d241b41c40d OP_CHECKSIG OP_BOOLAND

Gamble phase In this phase one of the users creates a transaction that contains hashes of all secrets. The output can be unlocked only when all secrets have been revealed and only by the lottery winner. 540d81... in #0 in #1 in #2 out #0 aef4cf... in #0 out #0 The output script checks the sizes of revealed secrets and their hashes. Then it computes one number from these sizes and uses it to select a public key that will be used to verify the spending transaction. assume signature, sC, sB, sA let sizeA = size(sA) verify within(sizeA, 32, 35) verify sha256(sA) == '197bf68fb520e8d3419dc1d4ac1eb89e7dfd7cfe561c19abf7611d7626d9f02c' let sizeB = size(sB) verify within(sizeB, 32, 35) verify sha256(sB) == 'f531f3041d3136701ea09067c53e7159c8f9b2746a56c3d82966c54bbc553226' let sizeC = size(sC) verify within(sizeC, 32, 35) verify sha256(sC) == '527ccdd755dcccf03192383624e0a7d0263815ce2ecf1f69cb0423ab7e6f0f3e' // sum of random numbers modulo 3 let mutable num = sizeB + sizeC + sizeA - 96 if (num > 2) { num <- num - 3 } if (num > 2) { num <- num - 3 } let keyA = '04d4bf4642f56fc7af0d2382e2cac34fa16ed3321633f91d06128f0e5c0d17479778cc1f2cc7e4a0c6f1e72d905532e8e127a031bb9794b3ef9b68b657f51cc691' let keyB = '04208a50909284aede02ad107bb1f52175b025cdf0453537b686433bcade6d3e210b6c82bcbdf8676b2161687e232f5d9afdaa4ed7b3e3bf9608d41b40ebde6ed4' let keyC = '04c9ce67ff2df2cd6be5f58345b4e311c5f10aab49d3cf3f73e8dcac1f9cd0de966e924be091e7bc854aef0d0baafa80fe5f2d6af56b1788e1e8ec8d241b41c40d' // select one of keys using num (if num == 0 -> keyA etc.) let key = roll(keyA, keyB, keyC, num) verify checkSigVerify(signature, key) Compiling to Bitcoin Script results in opcodes: … Gamble phase — Executing winner’s script The input script (four opcodes) from the spending transaction is concatenated with the output script from the first one: Stack contents: // input script 304402207d9184b4e4a1fe11bcb7743db85f1f82ff00ab8c54f58b44de2ae50d8b1c35f3022019d9f60cd927a317e258d7ee3b9ceba49cd2a6bf15c195e4fc5d5f5915b83b6201 ca42095840735e89283fec298e62ac2ddea9b5f34a8cbb7097ad965b87568123 1b1b01dc829177da4a14551d2fc96a9db00c6501edfa12f22cd9cefd335c227f 2c2c01dc829177da4a14551d2fc96a9db00c6501edfa12f22cd9cefd335c338e // output script OP_SIZE OP_TUCK 20 23 OP_WITHIN OP_VERIFY OP_SHA256 197bf68fb520e8d3419dc1d4ac1eb89e7dfd7cfe561c19abf7611d7626d9f02c OP_EQUALVERIFY OP_SWAP OP_SIZE OP_TUCK 20 23 OP_WITHIN OP_VERIFY OP_SHA256 f531f3041d3136701ea09067c53e7159c8f9b2746a56c3d82966c54bbc553226 OP_EQUALVERIFY OP_ROT OP_SIZE OP_TUCK 20 23 OP_WITHIN OP_VERIFY OP_SHA256 527ccdd755dcccf03192383624e0a7d0263815ce2ecf1f69cb0423ab7e6f0f3e OP_EQUALVERIFY OP_ADD OP_ADD 60 OP_SUB OP_DUP OP_2 OP_GREATERTHAN OP_IF OP_3 OP_SUB OP_ENDIF OP_DUP OP_2 OP_GREATERTHAN OP_IF OP_3 OP_SUB OP_ENDIF 04d4bf4642f56fc7af0d2382e2cac34fa16ed3321633f91d06128f0e5c0d17479778cc1f2cc7e4a0c6f1e72d905532e8e127a031bb9794b3ef9b68b657f51cc691 04208a50909284aede02ad107bb1f52175b025cdf0453537b686433bcade6d3e210b6c82bcbdf8676b2161687e232f5d9afdaa4ed7b3e3bf9608d41b40ebde6ed4 04c9ce67ff2df2cd6be5f58345b4e311c5f10aab49d3cf3f73e8dcac1f9cd0de966e924be091e7bc854aef0d0baafa80fe5f2d6af56b1788e1e8ec8d241b41c40d OP_3 OP_ROLL OP_ROLL OP_3 OP_ROLL OP_SWAP OP_CHECKSIGVERIFY