def build_transaction(transidsarr, transindexarr, pubeysarr, amountsarr, privatekey): tx_ins = buildinputs(transidsarr, transindexarr) tx_outs = buildoutputs(pubkeysarr, amountsarr) tx_obj = Tx(version=1, tx_ins=tx_ins, tx_outs=tx_outs, locktime=0, testnet=True) hash_type = SIGHASH_ALL z = tx_obj.sig_hash(0, hash_type) pk = PrivateKey(secret=privatekey) sighash = SIGHASH_ALL z = tx_obj.sig_hash(0, sighash) #print(z) sig = pk.sign(z) #print("r: " + str(sig.r)) #print("s: " + str(sig.s)) der = pk.sign(z).der() sig = der + bytes([sighash]) sec = pk.point.sec() tx_obj.tx_ins[0].script_sig = Script([sig, sec]) #print("serialized:") #print(hexlify(Script([sig,sec]).serialize())) #print("----------") return hexlify(tx_obj.serialize())
def add_channel(local_node, remote_peer, input_tx_id, input_tx_index): tx_in = TxIn(bytes.fromhex(input_tx_id), input_tx_index) local_amount = tx_in.value() remote_amount = 0 # Construct the output: amount, scriptPubKey = 2-of-2 Bare Multisig = Script([op_1, pubkey1, pubkey2, op_2, op_checkmultisig]) scriptPubKey = Script([ 0x52, local_node.public_key.sec(), remote_peer.public_key.sec(), 0x52, 0xae ]) tx_out = TxOut(amount=local_amount, script_pubkey=scriptPubKey) # Construct the transaction object funding_tx = Tx(1, [tx_in], [tx_out], 0, True) # Sign the input funding_tx.sign_input(0, local_node.private_key) #send channel request new_channel = Channel(remote_peer, local_amount, remote_amount, funding_tx) remote_peer.send(str.encode(new_channel.toJSON())) return new_channel
def test_example_1(self): tx_ins = [] prev_tx = bytes.fromhex( '8be2f69037de71e3bc856a6627ed3e222a7a2d0ce81daeeb54a3aea8db274149') prev_index = 4 tx_ins.append(TxIn(prev_tx, prev_index)) tx_outs = [] h160 = decode_base58('mzx5YhAH9kNHtcN481u6WkjeHjYtVeKVh2') tx_outs.append( TxOut( amount=int(0.38 * 100000000), script_pubkey=p2pkh_script(h160), )) h160 = decode_base58('mnrVtF8DWjMu839VW3rBfgYaAfKk8983Xf') tx_outs.append( TxOut( amount=int(0.1 * 100000000), script_pubkey=p2pkh_script(h160), )) tx_obj = Tx(1, tx_ins, tx_outs, 0, testnet=True) z = tx_obj.sig_hash(0) pk = PrivateKey(secret=8675309) der = pk.sign(z).der() sig = der + SIGHASH_ALL.to_bytes(1, 'big') sec = pk.point.sec() tx_obj.tx_ins[0].script_sig = Script([sig, sec]) want = '0100000001494127dba8aea354ebae1de80c2d7a2a223eed27666a85bce371de3790f6e28b040000006b483045022100fa3032607b50e8cb05bedc9d43f986f19dedc22e61320b9765061c5cd9c66946022072d514ef637988515bfa59a660596206de68f0ed4090d0a398e70f4d81370dfb012103935581e52c354cd2f484fe8ed83af7a3097005b2f9c60bff71d35bd795f54b67ffffffff0280d54302000000001976a914d52ad7ca9b3d096a38e752c2018e6fbc40cdf26f88ac80969800000000001976a914507b27411ccf7f16f10297de6cef3f291623eddf88ac00000000' self.assertEqual(tx_obj.serialize().hex(), want)
def test_exercise_4(self): prev_tx = bytes.fromhex( '75a1c4bc671f55f626dda1074c7725991e6f68b8fcefcfca7b64405ca3b45f1c') prev_index = 1 target_address = 'miKegze5FQNCnGw6PKyqUbYUeBa4x2hFeM' target_amount = 0.01 change_address = 'mzx5YhAH9kNHtcN481u6WkjeHjYtVeKVh2' change_amount = 0.009 secret = 8675309 priv = PrivateKey(secret=secret) tx_ins = [] tx_ins.append(TxIn(prev_tx, prev_index, Script([]), 0xffffffff)) tx_outs = [] h160 = decode_base58(target_address) script_pubkey = p2pkh_script(h160) target_satoshis = int(target_amount * 100000000) tx_outs.append(TxOut(target_satoshis, script_pubkey)) h160 = decode_base58(change_address) script_pubkey = p2pkh_script(h160) change_satoshis = int(change_amount * 100000000) tx_outs.append(TxOut(change_satoshis, script_pubkey)) tx_obj = Tx(1, tx_ins, tx_outs, 0, testnet=True) self.assertTrue(tx_obj.sign_input(0, priv)) self.assertTrue(tx_obj.verify()) want = '01000000011c5fb4a35c40647bcacfeffcb8686f1e9925774c07a1dd26f6551f67bcc4a175010000006b483045022100a08ebb92422b3599a2d2fcdaa11f8f807a66ccf33e7f4a9ff0a3c51f1b1ec5dd02205ed21dfede5925362b8d9833e908646c54be7ac6664e31650159e8f69b6ca539012103935581e52c354cd2f484fe8ed83af7a3097005b2f9c60bff71d35bd795f54b67ffffffff0240420f00000000001976a9141ec51b3654c1f1d0f4929d11a1f702937eaf50c888ac9fbb0d00000000001976a914d52ad7ca9b3d096a38e752c2018e6fbc40cdf26f88ac00000000' self.assertEqual(tx_obj.serialize().hex(), want)
def test_sign_input(self): private_key = PrivateKey(secret=8675309) tx_ins = [] prev_tx = unhexlify( '0025bc3c0fa8b7eb55b9437fdbd016870d18e0df0ace7bc9864efc38414147c8') tx_ins.append( TxIn( prev_tx=prev_tx, prev_index=0, script_sig=b'', sequence=0xffffffff, )) tx_ins[0]._value = 110000000 tx_ins[0]._script_pubkey = Script.parse( private_key.point.p2pkh_script()) tx_outs = [] h160 = Tx.get_address_data( 'mzx5YhAH9kNHtcN481u6WkjeHjYtVeKVh2')['h160'] tx_outs.append( TxOut(amount=int(0.99 * 100000000), script_pubkey=p2pkh_script(h160))) h160 = Tx.get_address_data( 'mnrVtF8DWjMu839VW3rBfgYaAfKk8983Xf')['h160'] tx_outs.append( TxOut(amount=int(0.1 * 100000000), script_pubkey=p2pkh_script(h160))) tx = Tx( version=1, tx_ins=tx_ins, tx_outs=tx_outs, locktime=0, testnet=True, ) self.assertTrue(tx.sign_input(0, private_key, SIGHASH_ALL))
def test_segwit(self): raw_tx = unhexlify( '01000000000101db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a5477010000001716001479091972186c449eb1ded22b78e40d009bdf0089feffffff02b8b4eb0b000000001976a914a457b684d7f0d539a46a45bbc043f35b59d0d96388ac0008af2f000000001976a914fd270b1ee6abcaea97fea7ad0402e8bd8ad6d77c88ac02473044022047ac8e878352d3ebbde1c94ce3a10d057c24175747116f8288e5d794d12d482f0220217f36a485cae903c713331d877c1f64677e3622ad4010726870540656fe9dcb012103ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a2687392040000' ) stream = BytesIO(raw_tx) tx = Tx.parse(stream) tx.tx_ins[0]._script_pubkey = Script.parse( unhexlify('a9144733f37cf4db86fbc2efed2500b4f4e49f31202387')) tx.tx_ins[0]._value = 1000000000 want = b'b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a' self.assertEqual(hexlify(tx.hash_prevouts()), want) want = b'18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198' self.assertEqual(hexlify(tx.hash_sequence()), want) want = b'de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83' self.assertEqual(hexlify(tx.hash_outputs()), want) want = b'01000000b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a5477010000001976a91479091972186c449eb1ded22b78e40d009bdf008988ac00ca9a3b00000000feffffffde984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c839204000001000000' self.assertEqual(hexlify(tx.sig_hash_preimage_bip143(0, 1)), want) self.assertEqual(tx.serialize(), raw_tx) self.assertTrue(tx.verify()) raw_tx = unhexlify( '01000000000101712e5b4e97ab549d50ca60a4f5968b2225215e9fab82dae4720078711406972f0000000017160014848202fc47fb475289652fbd1912cc853ecb0096feffffff0232360000000000001976a914121ae7a2d55d2f0102ccc117cbcb70041b0e037f88ac10270000000000001976a914ec0be50951651261765cfa71d7bd41c7b9245bb388ac024830450221009263c7de80c297d5b21aba846cf6f0a970e1d339568167d1e4c1355c7711bc1602202c9312b8d32fd9c7acc54c46cab50eb7255ce3c012214c41fe1ad91bccb16a13012102ebdf6fc448431a2bd6380f912a0fa6ca291ca3340e79b6f0c1fdaff73cf54061075a0700' ) stream = BytesIO(raw_tx) tx = Tx.parse(stream) self.assertEqual(tx.serialize(), raw_tx) self.assertTrue(tx.verify()) raw_tx = unhexlify( '020000000001081446a37707dc7ea5cf61806dd904f4ef4f0875a1ae0677cb2558af8154294db5070000001716001420b884a7838912a368ed6529f920edf39c0eabf6ffffffff3ec88712de2bc1812829a407e22c477e416df9437ef18e15c80cb6d415928f18000000001716001427dbca14f538846467a4b5ba0bc08014854db9c5ffffffff3176ffed5b1de43807d223216a82c6f68637ab7dbe2b585e184341f3a7d594cb0000000017160014d8f1c025669899719d87b3b21ca8e8fc2b139f15ffffffff54d8e606273ca57a3a559f3ce56619ad473701e19e5d2b4346d5082f47656fc3000000006b4830450221009447ef2f0ffb9e133f351161c2c3885f43c15d4b7682d7188011b07658537355022044c76b845efe00f1984d7c375a6af94280b4464917ea8274fa6eafa614647c83012102282deea2ecd8a0807ccfd51f9df5e1fd4bc9505b7e7e41ba922964ed59078c0cffffffff05392ab19a8d84d9db21d01d83bb2fc9c78a7b9555a7900a9b7b314a4f52d6990b00000017160014602845b585bdbb8a3e0cb6f7d2e54b50da1dc2caffffffff3ea224000c9023d3329f9fe10f0980deb05df5a089a77b8bda326476d0676b60000000006a4730440220499c7c60669b3b2f6e7a3535aa695d26c879cbf904c2a4d27abe8e9ce603b21b022022b126f3a3eb3800d56fc4b120e62b2bf8656160f42477709ab94c08488a57440121033fd51607ad8c7b20678ce90dc00e67305468dc5359f10d2b8e12bde1aad6b70affffffff2b380df0036fb56ce6abb604100c4475c44c5f78eb1ccb7eb3c8c68d4c07964401000000171600141222eb5661b5239b625a66596bf51c057dd6e36effffffff044f03ae06fe2cf464f0c06621f005f8584b17c83df3c274cc0532d92b0b4cbf030000001716001430128f1e88752aff630253a09502433615591817ffffffff0ae7546101000000001976a914fe129300f08787df2433ea1f179855ad631f521588ac7060b506000000001976a9141e52cea2417015d68a395961ded221e8773af94c88acfa331d000000000017a914718a41bebbfcfe7fc6f1713566e0e494062ccfe1877e905900000000001976a914d516332ccf4513a86e02103cb3723fcc4cc6d10488acf1523f000000000017a9149a1f25e8b22e06b94b36992690173927663e7a67873ca02f00000000001976a914781bc2683d9b8ca38a4805a2b3a3209c607f643988ac5b1fa5020000000017a914add3e0a14b450f7d68ec264d6c3eb3c4948ec611875e6f1800000000001976a91483449d8cfe9fdfbb16cb5632ca7b2ebb63ae90ab88aca342bc000000000017a914087d0060b24f68430474c5d048990158fd1ca7fb8700204e00000000001976a9147d79d91ffcc4d2ab74da606d22e60b794526244388ac0247304402200f6479c8a098d0d32e80023a6841273cb3bf2d9190c4ca9efed2d5a4b453d510022026c34fd235ba7a5e4f4dff2470b97b218672694738766fd3a6e562b1d73e9eff01210224af4a7a92c9967f3683fa3e0206daa5b928a84b35cae4de7427b0c0b1f7e0bf02473044022052c438047e0e7b44ff7c4e2072b79a69738420b9355d13a5c9d1094e3532968e02204eaaf65f26e11e346d23b39102194bed1ebc2c3e37521a9f00509616449fdb130121023638167aa99a910f4a4275b5bb628cc26facbfa5bf31f5cf2a6d554bc8db606002473044022014fa5476e6d80665113cc2b2555cc9ccb1c18333118a49a353dd1a932986ecab022035cdde8443957562510f0ee52e8ee400ca27f56785266ce4615ace4d1afb7c210121034ea7a539ad591d853b3ed679e5cf212801f063f0540ce1b9ee1085a2f6eac6aa0002483045022100ef9b368dd2498909df5cadde878c6ef708dfcbc3f0ca603c127bf531baff2be902201dd537223c6e67f5776b4ecf1a2baacfc0e198600431016a2f6e4928e2efc254012102e6b2a2dae2045633814c126ebeceebc036fc55a40f7aa56d03633b4f3cb407bf0002483045022100e426e718989f4141767bb5861d6d66c5b3d4b76bee849e8a05d0def1399b9a0c0220256b3c2e7e7e7e2cf7481e9e37feb6b1a877f13e396071f5c30af78557f89c0d012102d82c01881a7458f936b4c551e48adee3949585f842ece86a77e14c0976119ec602483045022100f4e5291e42dbe421eda30d670caf284b7d675ed439df64371d14d9dac028646502202e04dcea07a7d8bfc59f95172c87cdf9f2fa4f97559971cd08e2efd50cf3acb4012103a5c6e168f4acf6470b018fb9b86ef9ae58ba1834c3646a2ed1bebbfb94acf83500000000' ) stream = BytesIO(raw_tx) tx = Tx.parse(stream) self.assertEqual(tx.serialize(), raw_tx) self.assertTrue(tx.verify())
def test_example_6(self): tx_ins = [] prev_tx = bytes.fromhex( '0d6fe5213c0b3291f208cba8bfb59b7476dffacc4e5cb66f6eb20a080843a299') prev_index = 13 tx_ins.append(TxIn(prev_tx, prev_index, Script([]), 0xffffffff)) tx_outs = [] change_amount = int(0.33 * 100000000) change_h160 = decode_base58('mzx5YhAH9kNHtcN481u6WkjeHjYtVeKVh2') change_script = p2pkh_script(change_h160) tx_outs.append(TxOut(amount=change_amount, script_pubkey=change_script)) target_amount = int(0.1 * 100000000) target_h160 = decode_base58('mnrVtF8DWjMu839VW3rBfgYaAfKk8983Xf') target_script = p2pkh_script(target_h160) tx_outs.append(TxOut(amount=target_amount, script_pubkey=target_script)) transaction = Tx(1, tx_ins, tx_outs, 0, testnet=True) z = transaction.sig_hash(0) private_key = PrivateKey(secret=8675309) der = private_key.sign(z).der() sig = der + SIGHASH_ALL.to_bytes(1, 'big') sec = private_key.point.sec() transaction.tx_ins[0].script_sig = Script([sig, sec]) want = '010000000199a24308080ab26e6fb65c4eccfadf76749bb5bfa8cb08f291320b3c21e56f0d0d0000006b4830450221008ed46aa2cf12d6d81065bfabe903670165b538f65ee9a3385e6327d80c66d3b502203124f804410527497329ec4715e18558082d489b218677bd029e7fa306a72236012103935581e52c354cd2f484fe8ed83af7a3097005b2f9c60bff71d35bd795f54b67ffffffff02408af701000000001976a914d52ad7ca9b3d096a38e752c2018e6fbc40cdf26f88ac80969800000000001976a914507b27411ccf7f16f10297de6cef3f291623eddf88ac00000000' self.assertEqual(transaction.serialize().hex(), want)
def test_exercise_5(self): prev_tx_1 = bytes.fromhex( '11d05ce707c1120248370d1cbf5561d22c4f83aeba0436792c82e0bd57fe2a2f') prev_index_1 = 1 prev_tx_2 = bytes.fromhex( '51f61f77bd061b9a0da60d4bedaaf1b1fad0c11e65fdc744797ee22d20b03d15') prev_index_2 = 1 target_address = 'mwJn1YPMq7y5F8J3LkC5Hxg9PHyZ5K4cFv' target_amount = 0.0429 secret = 8675309 priv = PrivateKey(secret=secret) tx_ins = [] tx_ins.append(TxIn(prev_tx_1, prev_index_1, Script([]), 0xffffffff)) tx_ins.append(TxIn(prev_tx_2, prev_index_2, Script([]), 0xffffffff)) tx_outs = [] h160 = decode_base58(target_address) script_pubkey = p2pkh_script(h160) target_satoshis = int(target_amount * 100000000) tx_outs.append(TxOut(target_satoshis, script_pubkey)) tx_obj = Tx(1, tx_ins, tx_outs, 0, testnet=True) self.assertTrue(tx_obj.sign_input(0, priv)) self.assertTrue(tx_obj.sign_input(1, priv)) self.assertTrue(tx_obj.verify()) want = '01000000022f2afe57bde0822c793604baae834f2cd26155bf1c0d37480212c107e75cd011010000006a47304402204cc5fe11b2b025f8fc9f6073b5e3942883bbba266b71751068badeb8f11f0364022070178363f5dea4149581a4b9b9dbad91ec1fd990e3fa14f9de3ccb421fa5b269012103935581e52c354cd2f484fe8ed83af7a3097005b2f9c60bff71d35bd795f54b67ffffffff153db0202de27e7944c7fd651ec1d0fab1f1aaed4b0da60d9a1b06bd771ff651010000006b483045022100b7a938d4679aa7271f0d32d83b61a85eb0180cf1261d44feaad23dfd9799dafb02205ff2f366ddd9555f7146861a8298b7636be8b292090a224c5dc84268480d8be1012103935581e52c354cd2f484fe8ed83af7a3097005b2f9c60bff71d35bd795f54b67ffffffff01d0754100000000001976a914ad346f8eb57dee9a37981716e498120ae80e44f788ac00000000' self.assertEqual(tx_obj.serialize().hex(), want)
def test_exercise_6(self): last_block_hex = '000000000d65610b5af03d73ed67704713c9b734d87cf4b970d39a0416dd80f9' secret = little_endian_to_int( hash256(b'Jimmy Song Programming Blockchain')) private_key = PrivateKey(secret=secret) addr = private_key.point.address(testnet=True) h160 = decode_base58(addr) target_address = 'mwJn1YPMq7y5F8J3LkC5Hxg9PHyZ5K4cFv' self.assertEqual(addr, target_address) target_h160 = decode_base58(target_address) target_script = p2pkh_script(target_h160) fee = 5000 node = SimpleNode('tbtc.programmingblockchain.com', testnet=True) bf = BloomFilter(30, 5, 90210) bf.add(h160) node.handshake() node.send(bf.filterload()) start_block = bytes.fromhex(last_block_hex) getheaders = GetHeadersMessage(start_block=start_block) node.send(getheaders) headers = node.wait_for(HeadersMessage) last_block = None getdata = GetDataMessage() for b in headers.blocks: if not b.check_pow(): raise RuntimeError('proof of work is invalid') if last_block is not None and b.prev_block != last_block: raise RuntimeError('chain broken') getdata.add_data(FILTERED_BLOCK_DATA_TYPE, b.hash()) last_block = b.hash() node.send(getdata) prev_tx, prev_index, prev_tx_obj = None, None, None while prev_tx is None: message = node.wait_for(MerkleBlock, Tx) if message.command == b'merkleblock': if not message.is_valid(): raise RuntimeError('invalid merkle proof') else: message.testnet = True for i, tx_out in enumerate(message.tx_outs): if tx_out.script_pubkey.address(testnet=True) == addr: prev_tx = message.hash() prev_index = i prev_amount = tx_out.amount self.assertEqual( message.id(), '6ec96c9eafc62c0e42a4a6965be614c61101aaa316162ac79e07e1b9ab31e694' ) self.assertEqual(i, 0) break tx_in = TxIn(prev_tx, prev_index) output_amount = prev_amount - fee tx_out = TxOut(output_amount, target_script) tx_obj = Tx(1, [tx_in], [tx_out], 0, testnet=True) tx_obj.sign_input(0, private_key) self.assertEqual( tx_obj.serialize().hex(), '010000000194e631abb9e1079ec72a1616a3aa0111c614e65b96a6a4420e2cc6af9e6cc96e000000006a47304402203cc8c56abe1c0dd043afa9eb125dafbebdde2dd4cd7abf0fb1aae0667a22006e02203c95b74d0f0735bbf1b261d36e077515b6939fc088b9d7c1b7030a5e494596330121021cdd761c7eb1c90c0af0a5963e94bf0203176b4662778d32bd6d7ab5d8628b32ffffffff01f8829800000000001976a914ad346f8eb57dee9a37981716e498120ae80e44f788ac00000000' )
def test_exercise_4(self): last_block_hex = '000000000d65610b5af03d73ed67704713c9b734d87cf4b970d39a0416dd80f9' last_block = bytes.fromhex(last_block_hex) secret = little_endian_to_int( hash256(b'Jimmy Song Programming Blockchain')) private_key = PrivateKey(secret=secret) addr = private_key.point.address(testnet=True) h160 = decode_base58(addr) target_address = 'mwJn1YPMq7y5F8J3LkC5Hxg9PHyZ5K4cFv' self.assertEqual(addr, target_address) filter_size = 30 filter_num_functions = 5 filter_tweak = 90210 # FILL THIS IN target_h160 = decode_base58(target_address) target_script = p2pkh_script(target_h160) fee = 5000 # fee in satoshis node = SimpleNode('tbtc.programmingblockchain.com', testnet=True, logging=False) bf = BloomFilter(filter_size, filter_num_functions, filter_tweak) bf.add(h160) node.handshake() node.send(bf.filterload()) getheaders_message = GetHeadersMessage(start_block=last_block) node.send(getheaders_message) headers = node.wait_for(HeadersMessage) get_data_message = GetDataMessage() for header in headers.headers: self.assertTrue(header.check_pow()) if last_block is not None: self.assertEqual(header.prev_block, last_block) last_block = header.hash() get_data_message.add_data(FILTERED_BLOCK_DATA_TYPE, last_block) node.send(get_data_message) prev_tx = None while prev_tx is None: message = node.wait_for(MerkleBlock, Tx) if message.command == b'merkleblock': self.assertTrue(message.is_valid()) else: message.testnet = True for i, tx_out in enumerate(message.tx_outs): if tx_out.script_pubkey.address(testnet=True) == addr: prev_tx = message.hash() prev_index = i prev_amount = tx_out.amount break tx_in = TxIn(prev_tx, prev_index) output_amount = prev_amount - fee tx_out = TxOut(output_amount, target_script) tx_obj = Tx(1, [tx_in], [tx_out], 0, testnet=True) tx_obj.sign_input(0, private_key) self.assertEqual( tx_obj.serialize().hex(), '010000000194e631abb9e1079ec72a1616a3aa0111c614e65b96a6a4420e2cc6af9e6cc96e000000006a47304402203cc8c56abe1c0dd043afa9eb125dafbebdde2dd4cd7abf0fb1aae0667a22006e02203c95b74d0f0735bbf1b261d36e077515b6939fc088b9d7c1b7030a5e494596330121021cdd761c7eb1c90c0af0a5963e94bf0203176b4662778d32bd6d7ab5d8628b32ffffffff01f8829800000000001976a914ad346f8eb57dee9a37981716e498120ae80e44f788ac00000000' )
def test_coinbase_height(self): raw_tx = unhexlify( '01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff5e03d71b07254d696e656420627920416e74506f6f6c20626a31312f4542312f4144362f43205914293101fabe6d6d678e2c8c34afc36896e7d9402824ed38e856676ee94bfdb0c6c4bcd8b2e5666a0400000000000000c7270000a5e00e00ffffffff01faf20b58000000001976a914338c84849423992471bffb1a54a8d9b1d69dc28a88ac00000000' ) stream = BytesIO(raw_tx) tx = Tx.parse(stream) self.assertEqual(tx.coinbase_height(), 465879) raw_tx = unhexlify( '0100000001813f79011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d1000000006b483045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f02207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed01210349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278afeffffff02a135ef01000000001976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac99c39800000000001976a9141c4bc762dd5423e332166702cb75f40df79fea1288ac19430600' ) stream = BytesIO(raw_tx) tx = Tx.parse(stream) self.assertIsNone(tx.coinbase_height())
def test_fee(self): raw_tx = unhexlify( '0100000001813f79011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d1000000006b483045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f02207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed01210349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278afeffffff02a135ef01000000001976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac99c39800000000001976a9141c4bc762dd5423e332166702cb75f40df79fea1288ac19430600' ) stream = BytesIO(raw_tx) tx = Tx.parse(stream) self.assertEqual(tx.fee(), 40000) raw_tx = unhexlify( '010000000456919960ac691763688d3d3bcea9ad6ecaf875df5339e148a1fc61c6ed7a069e010000006a47304402204585bcdef85e6b1c6af5c2669d4830ff86e42dd205c0e089bc2a821657e951c002201024a10366077f87d6bce1f7100ad8cfa8a064b39d4e8fe4ea13a7b71aa8180f012102f0da57e85eec2934a82a585ea337ce2f4998b50ae699dd79f5880e253dafafb7feffffffeb8f51f4038dc17e6313cf831d4f02281c2a468bde0fafd37f1bf882729e7fd3000000006a47304402207899531a52d59a6de200179928ca900254a36b8dff8bb75f5f5d71b1cdc26125022008b422690b8461cb52c3cc30330b23d574351872b7c361e9aae3649071c1a7160121035d5c93d9ac96881f19ba1f686f15f009ded7c62efe85a872e6a19b43c15a2937feffffff567bf40595119d1bb8a3037c356efd56170b64cbcc160fb028fa10704b45d775000000006a47304402204c7c7818424c7f7911da6cddc59655a70af1cb5eaf17c69dadbfc74ffa0b662f02207599e08bc8023693ad4e9527dc42c34210f7a7d1d1ddfc8492b654a11e7620a0012102158b46fbdff65d0172b7989aec8850aa0dae49abfb84c81ae6e5b251a58ace5cfeffffffd63a5e6c16e620f86f375925b21cabaf736c779f88fd04dcad51d26690f7f345010000006a47304402200633ea0d3314bea0d95b3cd8dadb2ef79ea8331ffe1e61f762c0f6daea0fabde022029f23b3e9c30f080446150b23852028751635dcee2be669c2a1686a4b5edf304012103ffd6f4a67e94aba353a00882e563ff2722eb4cff0ad6006e86ee20dfe7520d55feffffff0251430f00000000001976a914ab0c0b2e98b1ab6dbf67d4750b0a56244948a87988ac005a6202000000001976a9143c82d7df364eb6c75be8c80df2b3eda8db57397088ac46430600' ) stream = BytesIO(raw_tx) tx = Tx.parse(stream) self.assertEqual(tx.fee(), 140500)
def check_htlc(node, commitment_tx, secret): tx_in = TxIn(bytes.fromhex(commitment_tx.id()), 2) tx_out = TxOut(amount=commitment_tx.tx_outs[2].amount, script_pubkey=commitment_tx.tx_outs[0].script_pubkey) spendingTx = Tx(1, [tx_in], [tx_out], 0, True) z = spendingTx.sig_hash(0) signature = node.private_key.sign(z).der() + SIGHASH_ALL.to_bytes(1, 'big') combined = Script( [signature, node.public_key.sec(), str.encode(secret), b'1']) + commitment_tx.tx_outs[2].script_pubkey return combined.evaluate(z, None)
def test_sign(self, gp): gp.return_value = 'password' mnemonic = 'method wire potato cotton fame can repair mother elder festival hurry trophy' enc = EncryptedPrivateKey.from_mnemonic(mnemonic, testnet=True) path = "m/84'/1'/0'/0/0" hd_priv = enc.get_private_key().traverse(path) tx_id = bytes.fromhex('07affe8b0ef5f009eef5399c20586b3181103564e8ffe444631dcae20389738c') tx_index = 0 amount = 12753130 tx_in = TxIn(tx_id, tx_index) tx_out = TxOut(amount - 5000, hd_priv.p2wpkh_script()) tx_obj = Tx(1, [tx_in], [tx_out], 0, testnet=True, segwit=True) self.assertTrue(tx_obj.sign_p2wpkh(0, hd_priv.private_key)) want = '010000000001018c738903e2ca1d6344e4ffe864351081316b58209c39f5ee09f0f50e8bfeaf070000000000ffffffff016285c200000000001600145b3a0784c7674df3645541a39f1d0061fafd121302483045022100ed55340424848ac402279a703440c3e64234cda15693b155e23daddea8e3ea75022018af9c2df35393e168980b835d1c08318e5417647522fb3c71c936fa20a416ae012102221f70f0e3f9cb3e164a45e7994e6e83816c76dc122d0987e4559536b888530b00000000' self.assertEqual(want, tx_obj.serialize().hex())
def new_commitment_tx(node, current_channel, cost, secret_hash): remote_peer = current_channel.peer # Create input using the output from the funding tx tx_in = TxIn(bytes.fromhex(current_channel.funding_tx.id()), 0) # Create 3 outputs. 1 to nodeA and 1 to nodeB and 1 to an HTLC script script_1 = p2pkh_script(decode_base58(node.address)) tx_out_1 = TxOut(amount=current_channel.local_amt - cost, script_pubkey=script_1) script_2 = p2pkh_script(decode_base58(remote_peer.btc_addr.decode())) tx_out_2 = TxOut(amount=current_channel.remote_amt, script_pubkey=script_2) #script_3 HTLC script_3 = Script([ 99, 168, secret_hash, 136, 118, 169, hash160(remote_peer.public_key.sec()), 103, encode_varint(1000), 177, 117, 118, 169, hash160(node.public_key.sec()), 104, 136, 172 ]) tx_out_3 = TxOut(amount=cost, script_pubkey=script_3) # Construct the commitment tx object commitment_tx = Tx(1, [tx_in], [tx_out_1, tx_out_2, tx_out_3], 0, True) #sign it commitment_tx.tx_ins[0].script_sig = get_script_sig( commitment_tx, node.private_key) return commitment_tx
def test_verify_input2(self): raw_tx = unhexlify( '0100000001868278ed6ddfb6c1ed3ad5f8181eb0c7a385aa0836f01d5e4789e6bd304d87221a000000db00483045022100dc92655fe37036f47756db8102e0d7d5e28b3beb83a8fef4f5dc0559bddfb94e02205a36d4e4e6c7fcd16658c50783e00c341609977aed3ad00937bf4ee942a8993701483045022100da6bee3c93766232079a01639d07fa869598749729ae323eab8eef53577d611b02207bef15429dcadce2121ea07f233115c6f09034c0be68db99980b9a6c5e75402201475221022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb7152aeffffffff04d3b11400000000001976a914904a49878c0adfc3aa05de7afad2cc15f483a56a88ac7f400900000000001976a914418327e3f3dda4cf5b9089325a4b95abdfa0334088ac722c0c00000000001976a914ba35042cfe9fc66fd35ac2224eebdafd1028ad2788acdc4ace020000000017a91474d691da1574e6b3c192ecfb52cc8984ee7b6c568700000000' ) stream = BytesIO(raw_tx) tx = Tx.parse(stream) self.assertTrue(tx.verify_input(0))
def wlogin(self,user,passwd): url = self.urlEntry.get() self.tx = Tx(url,user,passwd,0) status = self.tx.status # print(user,passwd,status) self.info.config(state=NORMAL) if status == 0: self.tx.get_family_id() userinfo = '当前登录用户ID:%s\n当前登录用户名:%s\n当前登录用户家族ID:%s\n当前登录用户家族名称:%s\n'%(str(self.tx.userId),self.tx.username,str(self.tx.family_id),self.tx.family_name) self.info.insert(END,userinfo) self.info.config(state=DISABLED) else: userinfo = '当前登录用户ID:%s\n'%(user) self.info.insert(END,userinfo) self.info.config(state=DISABLED) return status
def sign_psbt(self, serialized_psbt): """ Sign PSBT. Currently assumes inputs are ordered the same in unsigned tx and psbt. For now, only SIGHASH_ALL is approved. - If a non-witness UTXO is provided, its hash must match the hash specified in the prevout - TODO If a witness UTXO is provided, no non-witness signature may be created - TODO If a redeemScript is provided, the scriptPubKey must be for that redeemScript - TODO If a witnessScript is provided, the scriptPubKey or the redeemScript must be for that witnessScript - TODO If a sighash type is provided, the signer must check that the sighash is acceptable. If unacceptable, they must fail. - If a sighash type is not provided, the signer signs using SIGHASH_ALL """ psbt_si = Signer(serialized_psbt) tx_obj = Tx.parse(BytesIO(psbt_si.get_unsigned_tx())) for i in range(len(psbt_si.psbt.maps["inputs"])): curr_input = psbt_si.psbt.maps["inputs"][i] # check prev_tx_id if IN_NON_WITNESS_UTXO in curr_input: psbt_tx_id = hash256(curr_input[IN_NON_WITNESS_UTXO]) gutx_tx_id = tx_obj.tx_ins[i].prev_tx if psbt_tx_id != gutx_tx_id: raise PSBTError( f"UTXO {i} and Unsigned TX input {i} have different prev_tx_id: {psbt_tx_id} vs {gutx_tx_id}" ) # TODO SegWit elif IN_WITNESS_UTXO in curr_input: pass # TODO Handle RedeemScripts # Look for redeemScripts if IN_REDEEM_SCRIPT in curr_input: raise NotImplementedError( "Redeem Scripts not signable Yet. Unknown how to find ScriptPubKey" ) # read sighash sighash_type = psbt_si.get_sighash_type(i) if sighash_type is None: sighash_type = SIGHASH_ALL elif sighash_type != SIGHASH_ALL: raise NotImplementedError( "Other sighash types not yet supported.") # sign pubkey_sec, fingerprint, path = psbt_si.get_bip32_info(i) if fingerprint.hex() == self.master_fingerprint(): privkey = self.derive_key(path, priv=True, absolute=True).to_priv_key() if privkey.point.sec() == pubkey_sec: script_sig = tx_obj.sign_input(i, privkey, sighash_type) if not script_sig: raise SignatureError(f"Signing of input {i} failed.") sig = script_sig.cmds[0] psbt_si.add_partial_sig(sig, pubkey_sec, i) else: raise PSBTWarning( f"Private Key does not match pubkey provided. Skipping input {i}..." ) else: raise PSBTWarning( f"Fingerprint does not match this wallet. Skipping input {i}..." ) return psbt_si.serialize()
def test_is_coinbase(self): raw_tx = unhexlify( '01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff5e03d71b07254d696e656420627920416e74506f6f6c20626a31312f4542312f4144362f43205914293101fabe6d6d678e2c8c34afc36896e7d9402824ed38e856676ee94bfdb0c6c4bcd8b2e5666a0400000000000000c7270000a5e00e00ffffffff01faf20b58000000001976a914338c84849423992471bffb1a54a8d9b1d69dc28a88ac00000000' ) stream = BytesIO(raw_tx) tx = Tx.parse(stream) self.assertTrue(tx.is_coinbase())
def transfer(self, amount, address): uTxs = [] total = 0 for (tx, i) in self.unspentOutputs(): total += tx.outputs[i].amount uTxs.append((tx, i)) if total >= amount: break else: raise ValueError( "Wallet dose not have enough spendable outputs for transfer.") txIns = [] for (tx, i) in uTxs: txIn = TxIn(tx.toHash(), i) txIn.setScriptSig( generateSignature(txIn.toBytes(), self.privateKey), self.publicKey) txIns.append(txIn) txOuts = [TxOut(amount, address)] change = total - amount if change > 0: txOuts.append(TxOut(change, self.address)) self.receiveTx(Tx(txIns, txOuts))
def _vavidity_checking(self): # check for unsigned tx if GLOBAL_UNSIGNED_TX not in self.maps["global"]: raise PSBTError("Invalid PSBT: Missing unsigned tx.") else: tx_obj = Tx.parse(BytesIO(self.maps["global"][GLOBAL_UNSIGNED_TX])) for i in tx_obj.tx_ins: if len(i.script_sig.cmds) > 0 or len(i.witness_program) > 1: raise PSBTError("Invalid PSBT: Transaction in global map has ScriptSig or scriptWitness") gutx_ins_count = len(tx_obj.tx_ins) psbt_ins_count = len(self.maps["inputs"]) if gutx_ins_count == 0: raise PSBTError("Invalid PSBT: unsigned tx missing inputs") elif psbt_ins_count == 0: raise PSBTError("Invalid PSBT: no PSBT inputs") elif gutx_ins_count != psbt_ins_count: raise PSBTError('Invalid PSBT: number of inputs in unsigned transaction and PSBT do not match') gutx_outs_count = len(tx_obj.tx_outs) psbt_outs_count = len(tx_obj.tx_outs) if gutx_outs_count == 0: raise PSBTError('Invalid PSBT: unsigned transaction missing outputs') elif psbt_outs_count == 0: raise PSBTError('Invalid PSBT: psbt has outputs') elif gutx_outs_count != psbt_outs_count: raise PSBTError('Invalid PSBT: number of outputs in unsigned transaction and PSBT do not match')
def test_serialize(self): raw_tx = unhexlify( '0100000001813f79011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d1000000006b483045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f02207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed01210349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278afeffffff02a135ef01000000001976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac99c39800000000001976a9141c4bc762dd5423e332166702cb75f40df79fea1288ac19430600' ) stream = BytesIO(raw_tx) tx = Tx.parse(stream) self.assertEqual(tx.serialize(), raw_tx)
def test_fetch_address_utxos(self): addr = 'mgzCpjQxLVmw89FRrxrZqpzfE33HRAjaSU' utxos = Tx.fetch_address_utxos(addr) total = 0 for _, prev_tx, prev_index, value in utxos: total += value self.assertTrue(total > 0)
def test_bch(self): raw = unhexlify( '01000000021128db2baee531447170d0916a553b07e8912a1c47e4e174afc7bfdf4afd3185010000008a4730440220211497a5609bcdeba19552e54a96b63f153656ecc5ba997ca8174a8102b4d8c602206a079685c36b46902ba366e112ba17b44e79dc8cb9b3b4792848c4f2f97192ae41410456e1306c1068ff31f1e8dbdd0b976092b1b4903b1a8ee3fe878508fa7f584d399b3a0a48c4215cded444257ce358b04720c62c73d5a8c0bb4ad261096baaaec4ffffffffedc5aa7918bd8beb801277177b3b7d15924682358e6342570be84f91e6d11835010000008a47304402203b0ee7aedaa5237325caee0433eeaba2ce2aff53d5c09c91bc2a79c51500f0b702201ecfd381d027a0d08b2409691bc73c16e626cbcd3c80a9980fa1e41b7a11cb5041410456e1306c1068ff31f1e8dbdd0b976092b1b4903b1a8ee3fe878508fa7f584d399b3a0a48c4215cded444257ce358b04720c62c73d5a8c0bb4ad261096baaaec4ffffffff01ac3ae60e000000001976a91441e904a482e61766cec490a8a5f3fbcf6bffdb2a88ac00000000' ) stream = BytesIO(raw) tx = BCHTx.parse(stream) self.assertTrue(tx.verify()) raw_tx = unhexlify( '01000000066f267f335a54abf404c66a7a6e9ed3d77566a09ce11632f57029a677f42c6095000000006b483045022100fb0b16699c9b0984345c7860e208c04694aaa5117c8306082cfafc58b53e489a02203cd53408f1f8c8ff29701a9d1f6960b2dc5e1039f0eea949c5a886ac367e1e38412102fdcae0e5a55b20c8d3cbdf451d39f6d47daa50f884ed0ffcf0ae0adfeec4abb9ffffffff4ceb6a2894b19b96fedd543750bf7307805a2f6ca189c8c42d1abbe2930235fa000000006a4730440220794c269d519b567aa694de6dcde1d09dffa30b69dc18a619ce9ea65f239899150220156394f70f405c0710851490b9f21dc8a23931fbdc8a70ea51f73e9b00274a5c412103b708cd0b3329cff03611b0155384d1d4f40cb3aa30f82d8f4a34da044c868058ffffffff15053ac5123a25e0adf0ed998dfb710fff827861ac1a4c6601be8034179350ab000000006a473044022020e7b448318fa44b977d557b639aaf3a9666cf6d8dd446bd7812e752ddfcd1d302207159d22c2e379b77b0514b8e0767d0e9fff7063a659c268d605be436f65703884121031a97eb1664ceffa32988f7ea7c6726d681f1385b9765be1a40d6083fba4e6c69ffffffff2e1fb2ad94461104b147ffe95d0534eb98495c45831547b70eae652ac6cf52d0000000006b483045022100b0ce5496d51673f82430eee24c57f7f2f2631e5b9b32c78bbd79e1cbf3f6297b02201c807ecfa86c1c493e83f1235a19e4426da651e8f76c2f4b41ceebf1222a9291412102e4aa3631fd0b4a877c7c0a040b8211636f743c392ce17e6f266beb1b62490af9ffffffff311368bcf1bac2ae2e906bd7e84e9b45da861a63154ae5c3d69840f65486ba86000000006b483045022100d5f63c5284604eefb942fa9710f8d5b5bccf431e63c496237a0c41eb5c6debf102202bda17f3b7406b9c41f44c7377261413cfa144489a70a40e9e9126b3e7f2fc734121032e413587a71814365b7912eac3a052d8ac0c5f2351d3d84863a02bafefd41f19ffffffff2e9e219c5a68079891a8d2b00bfcf3772fa605997773c2c516bb5ac99aa8ee06000000006a47304402207b6e0d96d0ce538fb54fcb1731a35632b6e40efde834ce45ee22f0c0f5baa886022009327de37e3fb657af29161d265db558869c09e295e84ddb2f686a492db0015a41210389c44f336f7c8cc3096f8f40bc5bdbffea24da9e26649dbe6b862d7d369698d0ffffffff0102b84f05000000001976a9145c52250125494685f133df34f47fb88799b2903588ac00000000' ) stream = BytesIO(raw_tx) tx = BCHTx.parse(stream) inputs = ( ('18Lk6CB2WSpc4BVbxWhZrxLaYaJA2XVtyU', 24285000), ('13xY6E2tnBC5eGFCkayAUdVVcuGkFPoebJ', 824730), ('1BjFmsA4StiDa9xjAwahFXNpzR6SfXxBFD', 7583000), ('1Nn5QirD9iFT5kSF35XN8E3SX3SJM1daPL', 13150000), ('1HE8AdXHkP2bbnKmgENET4iyCHncP7rd7G', 32850000), ('1J3BgNjoqeR5JhHzC2rgorzBXTmdbmYcau', 10422900), ) for i, data in enumerate(inputs): addr, value = data tx_in = tx.tx_ins[i] i += 1 h160 = Tx.get_address_data(addr)['h160'] tx_in._value = value tx_in._script_pubkey = Script.parse(p2pkh_script(h160)) self.assertTrue(tx.verify())
def parse(cls, s): version = little_endian_to_int(s.read(4)) prev_block = s.read(32)[::-1] merkle_root = s.read(32)[::-1] timestamp = little_endian_to_int(s.read(4)) bits = s.read(4) nonce = s.read(4) num_tx = read_varint(s) txs = [] for i in range(num_tx): if i == 0: txs.append(Tx.parse(s, coinbase_tx=True)) else: txs.append(Tx.parse(s)) return cls(version, prev_block, merkle_root, timestamp, bits, nonce, txs)
def build_transaction2(transidsarr, transindexarr, pubkeysarr, amountsarr, tnet=True): tx_ins = buildinputs(transidsarr, transindexarr) print("ins") print(tx_ins) tx_outs = buildoutputs(pubkeysarr, amountsarr) print("pubkeys") print(pubkeysarr) print("outs") print(tx_outs) tx_obj = Tx(version=1, tx_ins=tx_ins, tx_outs=tx_outs, locktime=0, testnet=tnet) #hash_type = SIGHASH_ALL #z = tx_obj.sig_hash(0, hash_type) #pk = PrivateKey(secret=privatekey) for i in range(len(tx_ins)): sighash = SIGHASH_ALL z = tx_obj.sig_hash(i, sighash) #print("getting sign:") r, s = ardubridge.sign(z) s = int(s) others = N - s if others < s: s = others #print("r: " + str(r)) #print("s: " + str(s)) sig = Signature(int(r), s) der = sig.der() sig = der + bytes([sighash]) #sec = pk.point.sec() #print("public point:") #print(int(pk.point.x.hex(), 16)) #print(int(pk.point.y.hex(), 16)) x, y = ardubridge.getpubkey() if (x == -1 and y == -1): return '-1' #pub = S256Point(53237820045986896539096637357322002537362350769420441605069248472301971758546, 49407176618187043960559197373734381057571970898731550795341045595301080938882) pub = S256Point(int(x), int(y)) sec2 = pub.sec() tx_obj.tx_ins[i].script_sig = Script([sig, sec2]) return hexlify(tx_obj.serialize())
def test_example_5(self): tx_ins = [] prev_tx = bytes.fromhex('0d6fe5213c0b3291f208cba8bfb59b7476dffacc4e5cb66f6eb20a080843a299') prev_index = 13 tx_ins.append(TxIn(prev_tx, prev_index, Script([]), 0xffffffff)) tx_outs = [] change_amount = int(0.33 * 100000000) change_h160 = decode_base58('mzx5YhAH9kNHtcN481u6WkjeHjYtVeKVh2') change_script = p2pkh_script(change_h160) tx_outs.append(TxOut(change_amount, change_script)) target_amount = int(0.1 * 100000000) target_h160 = decode_base58('mnrVtF8DWjMu839VW3rBfgYaAfKk8983Xf') target_script = p2pkh_script(target_h160) tx_outs.append(TxOut(target_amount, target_script)) transaction = Tx(1, tx_ins, tx_outs, 0, testnet=True) want = '010000000199a24308080ab26e6fb65c4eccfadf76749bb5bfa8cb08f291320b3c21e56f0d0d00000000ffffffff02408af701000000001976a914d52ad7ca9b3d096a38e752c2018e6fbc40cdf26f88ac80969800000000001976a914507b27411ccf7f16f10297de6cef3f291623eddf88ac00000000' self.assertEqual(transaction.serialize().hex(), want)
def test_exercise_2(self): hex_tx = '01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000' stream = BytesIO(bytes.fromhex(hex_tx)) coinbase = Tx.parse(stream) self.assertEqual( coinbase.tx_ins[0].script_sig.instructions[2], b'The Times 03/Jan/2009 Chancellor on brink of second bailout for banks' )
def parse(cls, s): b = cls.parse_header(s) num_txs = read_varint(s) tx_hashes = [] for _ in range(num_txs): t = Tx.parse(s) tx_hashes.append(t.hash()) b.tx_hashes = tx_hashes return b
def test_exercise_9(self): hex_tx = '01000000012f5ab4d2666744a44864a63162060c2ae36ab0a2375b1c2b6b43077ed5dcbed6000000006a473044022034177d53fcb8e8cba62432c5f6cc3d11c16df1db0bce20b874cfc61128b529e1022040c2681a2845f5eb0c46adb89585604f7bf8397b82db3517afb63f8e3d609c990121035e8b10b675477614809f3dde7fd0e33fb898af6d86f51a65a54c838fddd417a5feffffff02c5872e00000000001976a91441b835c78fb1406305727d8925ff315d90f9bbc588acae2e1700000000001976a914c300e84d277c6c7bcf17190ebc4e7744609f8b0c88ac31470600' stream = BytesIO(bytes.fromhex(hex_tx)) index = 0 t = Tx.parse(stream) tx_in = t.tx_ins[index] z = t.sig_hash(index) combined_script = tx_in.script_sig + tx_in.script_pubkey() self.assertTrue(combined_script.evaluate(z))