Esempio n. 1
0
 def test_fee(self):
     raw_tx = "0100000001813f79011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d1000000006b483045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f02207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed01210349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278afeffffff02a135ef01000000001976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac99c39800000000001976a9141c4bc762dd5423e332166702cb75f40df79fea1288ac19430600"
     tx = Tx.parse_hex(raw_tx)
     self.assertEqual(tx.fee(), 40000)
     raw_tx = "010000000456919960ac691763688d3d3bcea9ad6ecaf875df5339e148a1fc61c6ed7a069e010000006a47304402204585bcdef85e6b1c6af5c2669d4830ff86e42dd205c0e089bc2a821657e951c002201024a10366077f87d6bce1f7100ad8cfa8a064b39d4e8fe4ea13a7b71aa8180f012102f0da57e85eec2934a82a585ea337ce2f4998b50ae699dd79f5880e253dafafb7feffffffeb8f51f4038dc17e6313cf831d4f02281c2a468bde0fafd37f1bf882729e7fd3000000006a47304402207899531a52d59a6de200179928ca900254a36b8dff8bb75f5f5d71b1cdc26125022008b422690b8461cb52c3cc30330b23d574351872b7c361e9aae3649071c1a7160121035d5c93d9ac96881f19ba1f686f15f009ded7c62efe85a872e6a19b43c15a2937feffffff567bf40595119d1bb8a3037c356efd56170b64cbcc160fb028fa10704b45d775000000006a47304402204c7c7818424c7f7911da6cddc59655a70af1cb5eaf17c69dadbfc74ffa0b662f02207599e08bc8023693ad4e9527dc42c34210f7a7d1d1ddfc8492b654a11e7620a0012102158b46fbdff65d0172b7989aec8850aa0dae49abfb84c81ae6e5b251a58ace5cfeffffffd63a5e6c16e620f86f375925b21cabaf736c779f88fd04dcad51d26690f7f345010000006a47304402200633ea0d3314bea0d95b3cd8dadb2ef79ea8331ffe1e61f762c0f6daea0fabde022029f23b3e9c30f080446150b23852028751635dcee2be669c2a1686a4b5edf304012103ffd6f4a67e94aba353a00882e563ff2722eb4cff0ad6006e86ee20dfe7520d55feffffff0251430f00000000001976a914ab0c0b2e98b1ab6dbf67d4750b0a56244948a87988ac005a6202000000001976a9143c82d7df364eb6c75be8c80df2b3eda8db57397088ac46430600"
     tx = Tx.parse_hex(raw_tx)
     self.assertEqual(tx.fee(), 140500)
Esempio n. 2
0
 def test_coinbase_height(self):
     raw_tx = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff5e03d71b07254d696e656420627920416e74506f6f6c20626a31312f4542312f4144362f43205914293101fabe6d6d678e2c8c34afc36896e7d9402824ed38e856676ee94bfdb0c6c4bcd8b2e5666a0400000000000000c7270000a5e00e00ffffffff01faf20b58000000001976a914338c84849423992471bffb1a54a8d9b1d69dc28a88ac00000000"
     tx = Tx.parse_hex(raw_tx)
     self.assertEqual(tx.coinbase_height(), 465879)
     raw_tx = "0100000001813f79011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d1000000006b483045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f02207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed01210349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278afeffffff02a135ef01000000001976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac99c39800000000001976a9141c4bc762dd5423e332166702cb75f40df79fea1288ac19430600"
     tx = Tx.parse_hex(raw_tx)
     self.assertIsNone(tx.coinbase_height())
Esempio n. 3
0
 def test_sig_hash_bip143(self):
     raw_tx = "0100000000010115e180dc28a2327e687facc33f10f2a20da717e5548406f7ae8b4c811072f8560100000000ffffffff0100b4f505000000001976a9141d7cd6c75c2e86f4cbf98eaed221b30bd9a0b92888ac02483045022100df7b7e5cda14ddf91290e02ea10786e03eb11ee36ec02dd862fe9a326bbcb7fd02203f5b4496b667e6e281cc654a2da9e4f08660c620a1051337fa8965f727eb19190121038262a6c6cec93c2d3ecd6c6072efea86d02ff8e3328bbd0242b20af3425990ac00000000"
     tx = Tx.parse_hex(raw_tx, network="testnet")
     want = int(
         "12bb9e0988736b8d1c3a180acd828b8a7eddae923a6a4bf0b4c14c40cd7327d1", 16
     )
     self.assertEqual(tx.sig_hash_legacy(0), want)
     tx = Tx.parse_hex(raw_tx, network="signet")
     self.assertEqual(tx.sig_hash_legacy(0), want)
Esempio n. 4
0
 def test_sign_input(self):
     private_key = PrivateKey(secret=8675309)
     tx_ins = []
     prev_tx = bytes.fromhex(
         "0025bc3c0fa8b7eb55b9437fdbd016870d18e0df0ace7bc9864efc38414147c8"
     )
     tx_ins.append(TxIn(prev_tx, 0))
     tx_outs = [
         TxOut.to_address("mzx5YhAH9kNHtcN481u6WkjeHjYtVeKVh2", 99000000),
         TxOut.to_address("mnrVtF8DWjMu839VW3rBfgYaAfKk8983Xf", 10000000),
     ]
     tx = Tx(1, tx_ins, tx_outs, 0, network="testnet")
     self.assertTrue(tx.sign_input(0, private_key))
Esempio n. 5
0
 def test_sign_p2wpkh(self):
     private_key = PrivateKey(secret=8675309)
     prev_tx = bytes.fromhex(
         "6bfa079532dd9fad6cfbf218edc294fdfa7dd0cb3956375bc864577fb36fad97"
     )
     prev_index = 0
     fee = 500
     tx_in = TxIn(prev_tx, prev_index)
     amount = tx_in.value(network="testnet") - fee
     tx_out = TxOut.to_address("mqYz6JpuKukHzPg94y4XNDdPCEJrNkLQcv", amount)
     t = Tx(1, [tx_in], [tx_out], 0, network="testnet", segwit=True)
     self.assertTrue(t.sign_input(0, private_key))
     want = "0100000000010197ad6fb37f5764c85b375639cbd07dfafd94c2ed18f2fb6cad9fdd329507fa6b0000000000ffffffff014c400f00000000001976a9146e13971913b9aa89659a9f53d327baa8826f2d7588ac02483045022100feab5b8feefd5e774bdfdc1dc23525b40f1ffaa25a376f8453158614f00fa6cb02204456493d0bc606ebeb3fa008e056bbc96a67cb0c11abcc871bfc2bec60206bf0012103935581e52c354cd2f484fe8ed83af7a3097005b2f9c60bff71d35bd795f54b6700000000"
     self.assertEqual(t.serialize().hex(), want)
Esempio n. 6
0
 def test_sign_p2sh_p2wpkh(self):
     private_key = PrivateKey(secret=8675309)
     redeem_script = private_key.point.p2sh_p2wpkh_redeem_script()
     prev_tx = bytes.fromhex(
         "2e19b463bd5c8a3e0f10ae827f5a670f6794fca96394ecf8488321291d1c2ee9"
     )
     prev_index = 1
     fee = 500
     tx_in = TxIn(prev_tx, prev_index)
     amount = tx_in.value(network="testnet") - fee
     tx_out = TxOut.to_address("mqYz6JpuKukHzPg94y4XNDdPCEJrNkLQcv", amount)
     t = Tx(1, [tx_in], [tx_out], 0, network="testnet", segwit=True)
     self.assertTrue(t.sign_input(0, private_key, redeem_script=redeem_script))
     want = "01000000000101e92e1c1d29218348f8ec9463a9fc94670f675a7f82ae100f3e8a5cbd63b4192e0100000017160014d52ad7ca9b3d096a38e752c2018e6fbc40cdf26fffffffff014c400f00000000001976a9146e13971913b9aa89659a9f53d327baa8826f2d7588ac0247304402205e3ae5ac9a0e0a16ae04b0678c5732973ce31051ba9f42193e69843e600d84f2022060a91cbd48899b1bf5d1ffb7532f69ab74bc1701a253a415196b38feb599163b012103935581e52c354cd2f484fe8ed83af7a3097005b2f9c60bff71d35bd795f54b6700000000"
     self.assertEqual(t.serialize().hex(), want)
Esempio n. 7
0
 def test_op_checksig(self):
     tests = (
         (
             "010000000148dcc16482f5c835828020498ec1c35f48a578585721b5a77445a4ce93334d18000000006a4730440220636b9f822ea2f85e6375ecd066a49cc74c20ec4f7cf0485bebe6cc68da92d8ce022068ae17620b12d99353287d6224740b585ff89024370a3212b583fb454dce7c160121021f955d36390a38361530fb3724a835f4f504049492224a028fb0ab8c063511a7ffffffff0220960705000000001976a914d23541bd04c58a1265e78be912e63b2557fb439088aca0860100000000001976a91456d95dc3f2414a210efb7188d287bff487df96c688ac00000000",
             "30440220636b9f822ea2f85e6375ecd066a49cc74c20ec4f7cf0485bebe6cc68da92d8ce022068ae17620b12d99353287d6224740b585ff89024370a3212b583fb454dce7c1601",
             "021f955d36390a38361530fb3724a835f4f504049492224a028fb0ab8c063511a7",
             "testnet",
         ),
         (
             "01000000000101e92e1c1d29218348f8ec9463a9fc94670f675a7f82ae100f3e8a5cbd63b4192e0100000017160014d52ad7ca9b3d096a38e752c2018e6fbc40cdf26fffffffff014c400f00000000001976a9146e13971913b9aa89659a9f53d327baa8826f2d7588ac0247304402205e3ae5ac9a0e0a16ae04b0678c5732973ce31051ba9f42193e69843e600d84f2022060a91cbd48899b1bf5d1ffb7532f69ab74bc1701a253a415196b38feb599163b012103935581e52c354cd2f484fe8ed83af7a3097005b2f9c60bff71d35bd795f54b6700000000",
             "304402205e3ae5ac9a0e0a16ae04b0678c5732973ce31051ba9f42193e69843e600d84f2022060a91cbd48899b1bf5d1ffb7532f69ab74bc1701a253a415196b38feb599163b01",
             "03935581e52c354cd2f484fe8ed83af7a3097005b2f9c60bff71d35bd795f54b67",
             "testnet",
         ),
         (
             "0200000000010140d43a99926d43eb0e619bf0b3d83b4a31f60c176beecfb9d35bf45e54d0f7420100000017160014a4b4ca48de0b3fffc15404a1acdc8dbaae226955ffffffff0100e1f5050000000017a9144a1154d50b03292b3024370901711946cb7cccc387024830450221008604ef8f6d8afa892dee0f31259b6ce02dd70c545cfcfed8148179971876c54a022076d771d6e91bed212783c9b06e0de600fab2d518fad6f15a2b191d7fbd262a3e0121039d25ab79f41f75ceaf882411fd41fa670a4c672c23ffaf0e361a969cde0692e800000000",
             "30450221008604ef8f6d8afa892dee0f31259b6ce02dd70c545cfcfed8148179971876c54a022076d771d6e91bed212783c9b06e0de600fab2d518fad6f15a2b191d7fbd262a3e01",
             "039d25ab79f41f75ceaf882411fd41fa670a4c672c23ffaf0e361a969cde0692e8",
             "mainnet",
         ),
     )
     for raw_tx, sig_hex, sec_hex, network in tests:
         tx_obj = Tx.parse(BytesIO(bytes.fromhex(raw_tx)), network=network)
         sec = bytes.fromhex(sec_hex)
         sig = bytes.fromhex(sig_hex)
         stack = [sig, sec]
         self.assertTrue(op_checksig(stack, tx_obj, 0))
         self.assertEqual(decode_num(stack[0]), 1)
Esempio n. 8
0
 def test_sig_hash(self):
     raw_tx = "0100000001813f79011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d1000000006b483045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f02207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed01210349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278afeffffff02a135ef01000000001976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac99c39800000000001976a9141c4bc762dd5423e332166702cb75f40df79fea1288ac19430600"
     tx = Tx.parse_hex(raw_tx)
     want = int(
         "27e0c5994dec7824e56dec6b2fcb342eb7cdb0d0957c2fce9882f715e85d81a6", 16
     )
     self.assertEqual(tx.sig_hash_legacy(0), want)
Esempio n. 9
0
    def test_serialize(self):
        raw_tx = "0100000001813f79011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d1000000006b483045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f02207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed01210349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278afeffffff02a135ef01000000001976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac99c39800000000001976a9141c4bc762dd5423e332166702cb75f40df79fea1288ac19430600"
        tx = Tx.parse_hex(raw_tx)
        self.assertEqual(tx.serialize().hex(), raw_tx)

        # simple test to show repr works (otherwise this would throw an error)
        str(tx)
Esempio n. 10
0
 def test_parse_segwit(self):
     raw_tx = "01000000000101c70c4ede5731f1b47a89d133be9244927fa12e15778ec78a7e071273c0c58a870400000000ffffffff02809698000000000017a9144f34d55c56f827169921df008e8dfdc23678fc1787d464da1f00000000220020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d0400473044022050a5a50e78e6f9c65b5d94c78f8e4b339848456ff7c2231702b4a37439e2a3bd02201569cbf1c672bbb1608d6e9feea28705d8d6e54aa51d9fa396469be6ffc83c2d0147304402200b69a83cc3e3e1694037ef639049b0ece00f15718a03e9038aa42ac9d1bd0ea50220780c510821cd5205e5d178e6277005f4dd61a7fcccd4f8fae9e2d2adc355e728016952210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae00000000"
     tx = Tx.parse_hex(raw_tx)
     self.assertTrue(tx.segwit)
     self.assertEqual(tx.version, 1)
     self.assertEqual(tx.tx_ins[0].prev_index, 4)
     self.assertEqual(tx.tx_outs[0].amount, 10000000)
     self.assertEqual(tx.locktime, 0)
Esempio n. 11
0
 def test_op_cltv(self):
     locktime_0 = Locktime(1234)
     locktime_1 = Locktime(2345)
     sequence = Sequence()
     tx_in = TxIn(b"\x00" * 32, 0, sequence=sequence)
     tx_out = TxOut(1, Script())
     tx_obj = Tx(1, [tx_in], [tx_out], locktime_1)
     stack = []
     self.assertFalse(op_checklocktimeverify(stack, tx_obj, 0))
     tx_in.sequence = Sequence(0xFFFFFFFE)
     self.assertFalse(op_checklocktimeverify(stack, tx_obj, 0))
     stack = [encode_num(-5)]
     self.assertFalse(op_checklocktimeverify(stack, tx_obj, 0))
     stack = [encode_num(locktime_0)]
     self.assertTrue(op_checklocktimeverify(stack, tx_obj, 0))
     tx_obj.locktime = Locktime(1582820194)
     self.assertFalse(op_checklocktimeverify(stack, tx_obj, 0))
     tx_obj.locktime = Locktime(500)
     self.assertFalse(op_checklocktimeverify(stack, tx_obj, 0))
Esempio n. 12
0
 def test_p2tr_validation(self):
     tests = [
         "01000000000101d1f1c1f8cdf6759167b90f52c9ad358a369f95284e841d7a2536cef31c0549580100000000fdffffff020000000000000000316a2f49206c696b65205363686e6f7272207369677320616e6420492063616e6e6f74206c69652e204062697462756734329e06010000000000225120a37c3903c8d0db6512e2b40b0dffa05e5a3ab73603ce8c9c4b7771e5412328f90140a60c383f71bac0ec919b1d7dbc3eb72dd56e7aa99583615564f9f99b8ae4e837b758773a5b2e4c51348854c8389f008e05029db7f464a5ff2e01d5e6e626174affd30a00",
         "020000000001027bc0bba407bc67178f100e352bf6e047fae4cbf960d783586cb5e430b3b700e70000000000feffffff7bc0bba407bc67178f100e352bf6e047fae4cbf960d783586cb5e430b3b700e70100000000feffffff01b4ba0e0000000000160014173fd310e9db2c7e9550ce0f03f1e6c01d833aa90140134896c42cd95680b048845847c8054756861ffab7d4abab72f6508d67d1ec0c590287ec2161dd7884983286e1cd56ce65c08a24ee0476ede92678a93b1b180c03407b5d614a4610bf9196775791fcc589597ca066dcd10048e004cd4c7341bb4bb90cee4705192f3f7db524e8067a5222c7f09baf29ef6b805b8327ecd1e5ab83ca2220f5b059b9a72298ccbefff59d9b943f7e0fc91d8a3b944a95e7b6390cc99eb5f4ac41c0d9dfdf0fe3c83e9870095d67fff59a8056dad28c6dfb944bb71cf64b90ace9a7776b22a1185fb2dc9524f6b178e2693189bf01655d7f38f043923668dc5af45bffd30a00",
         "02000000000101b41b20295ac85fd2ae3e3d02900f1a1e7ddd6139b12e341386189c03d6f5795b0000000000fdffffff0100000000000000003c6a3a546878205361746f7368692120e2889e2f32316d696c20466972737420546170726f6f74206d756c7469736967207370656e64202d426974476f044123b1d4ff27b16af4b0fcb9672df671701a1a7f5a6bb7352b051f461edbc614aa6068b3e5313a174f90f3d95dc4e06f69bebd9cf5a3098fde034b01e69e8e788901400fd4a0d3f36a1f1074cb15838a48f572dc18d412d0f0f0fc1eeda9fa4820c942abb77e4d1a3c2b99ccf4ad29d9189e6e04a017fe611748464449f681bc38cf394420febe583fa77e49089f89b78fa8c116710715d6e40cc5f5a075ef1681550dd3c4ad20d0fa46cb883e940ac3dc5421f05b03859972639f51ed2eccbf3dc5a62e2e1b15ac41c02e44c9e47eaeb4bb313adecd11012dfad435cd72ce71f525329f24d75c5b9432774e148e9209baf3f1656a46986d5f38ddf4e20912c6ac28f48d6bf747469fb100000000",
         "010000000001022373cf02ce7df6500ae46a4a0fbbb1b636d2debed8f2df91e2415627397a34090000000000fdffffff88c23d928893cd3509845516cf8411b7cab2738c054cc5ce7e4bde9586997c770000000000fdffffff0200000000000000002b6a29676d20746170726f6f7420f09fa5952068747470733a2f2f626974636f696e6465766b69742e6f72676e9e1100000000001976a91405070d0290da457409a37db2e294c1ffbc52738088ac04410adf90fd381d4a13c3e73740b337b230701189ed94abcb4030781635f035e6d3b50b8506470a68292a2bc74745b7a5732a28254b5f766f09e495929ec308090b01004620c13e6d193f5d04506723bd67abcc5d31b610395c445ac6744cb0a1846b3aabaeac20b0e2e48ad7c3d776cf6f2395c504dc19551268ea7429496726c5d5bf72f9333cba519c21c0000000000000000000000000000000000000000000000000000000000000000104414636070d21adc8280735383102f7a0f5978cea257777a23934dd3b458b79bf388aca218e39e23533a059da173e402c4fc5e3375e1f839efb22e9a5c2a815b07301004620c13e6d193f5d04506723bd67abcc5d31b610395c445ac6744cb0a1846b3aabaeac20b0e2e48ad7c3d776cf6f2395c504dc19551268ea7429496726c5d5bf72f9333cba519c21c0000000000000000000000000000000000000000000000000000000000000000100000000",
     ]
     for i, hex_tx in enumerate(tests):
         tx_obj = Tx.parse(BytesIO(bytes.fromhex(hex_tx)))
         self.assertTrue(tx_obj.verify())
Esempio n. 13
0
 def test_op_csv(self):
     sequence_0 = Sequence()
     sequence_1 = Sequence(2345)
     tx_in = TxIn(b"\x00" * 32, 0, sequence=sequence_0)
     tx_out = TxOut(1, Script())
     tx_obj = Tx(1, [tx_in], [tx_out])
     stack = []
     self.assertFalse(op_checksequenceverify(stack, tx_obj, 0))
     tx_in.sequence = sequence_1
     self.assertFalse(op_checksequenceverify(stack, tx_obj, 0))
     stack = [encode_num(-5)]
     self.assertFalse(op_checksequenceverify(stack, tx_obj, 0))
     tx_obj.version = 2
     self.assertFalse(op_checksequenceverify(stack, tx_obj, 0))
     stack = [encode_num(1234 | (1 << 22))]
     self.assertFalse(op_checksequenceverify(stack, tx_obj, 0))
     stack = [encode_num(9999)]
     self.assertFalse(op_checksequenceverify(stack, tx_obj, 0))
     stack = [encode_num(1234)]
     self.assertTrue(op_checksequenceverify(stack, tx_obj, 0))
Esempio n. 14
0
 def parse(cls, s):
     """Takes a byte stream and parses a block. Returns a Block object"""
     b = cls.parse_header(s)
     num_txs = read_varint(s)
     b.txs = []
     b.tx_hashes = []
     for _ in range(num_txs):
         t = Tx.parse(s)
         b.txs.append(t)
         b.tx_hashes.append(t.hash())
     return b
Esempio n. 15
0
 def test_parse_outputs(self):
     raw_tx = "0100000001813f79011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d1000000006b483045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f02207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed01210349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278afeffffff02a135ef01000000001976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac99c39800000000001976a9141c4bc762dd5423e332166702cb75f40df79fea1288ac19430600"
     tx = Tx.parse_hex(raw_tx)
     self.assertEqual(len(tx.tx_outs), 2)
     want = 32454049
     self.assertEqual(tx.tx_outs[0].amount, want)
     want = bytes.fromhex("1976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac")
     self.assertEqual(tx.tx_outs[0].script_pubkey.serialize(), want)
     want = 10011545
     self.assertEqual(tx.tx_outs[1].amount, want)
     want = bytes.fromhex("1976a9141c4bc762dd5423e332166702cb75f40df79fea1288ac")
     self.assertEqual(tx.tx_outs[1].script_pubkey.serialize(), want)
Esempio n. 16
0
 def test_sign_p2pkh(self):
     private_key = PrivateKey(secret=8675309)
     tx_ins = []
     prev_tx = bytes.fromhex(
         "448c1cf931cb8a35d648b75a63c7dbdc6d81a8b82be07c055d599a4ce810a20a"
     )
     tx_ins.append(TxIn(prev_tx, 0))
     tx_outs = [
         TxOut.to_address("mzx5YhAH9kNHtcN481u6WkjeHjYtVeKVh2", 5999000),
         TxOut.to_address("tb1qjfavna0z7r484w674f723w7g4jpeaplttt464w", 1000000),
         TxOut.to_address(
             "tb1qdhd06yyf7pazh2vx3hm37c3gq8lpra2993hlr784z4e3xwpgksmsceq9wc",
             1000000,
         ),
         TxOut.to_address("2MyJsxLnxj7DsNch4xE7B3nMpB94kDPoE2s", 1000000),
         TxOut.to_address(
             "tb1p9gpzhc5fhlwlf49ze00fgjszxh5pl2p7az76758xwarweq08gcas8qa0r7",
             1000000,
         ),
     ]
     tx_obj = Tx(1, tx_ins, tx_outs, 0, network="signet")
     self.assertTrue(tx_obj.sign_p2pkh(0, private_key))
Esempio n. 17
0
 def test_parse_inputs(self):
     raw_tx = "0100000001813f79011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d1000000006b483045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f02207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed01210349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278afeffffff02a135ef01000000001976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac99c39800000000001976a9141c4bc762dd5423e332166702cb75f40df79fea1288ac19430600"
     tx = Tx.parse_hex(raw_tx)
     self.assertEqual(len(tx.tx_ins), 1)
     want = bytes.fromhex(
         "d1c789a9c60383bf715f3f6ad9d14b91fe55f3deb369fe5d9280cb1a01793f81"
     )
     self.assertEqual(tx.tx_ins[0].prev_tx, want)
     self.assertEqual(tx.tx_ins[0].prev_index, 0)
     want = bytes.fromhex(
         "6b483045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f02207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed01210349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278a"
     )
     self.assertEqual(tx.tx_ins[0].script_sig.serialize(), want)
     self.assertEqual(tx.tx_ins[0].sequence, 0xFFFFFFFE)
Esempio n. 18
0
 def test_op_checkmultisig(self):
     raw_tx = "0100000001868278ed6ddfb6c1ed3ad5f8181eb0c7a385aa0836f01d5e4789e6bd304d87221a000000db00483045022100dc92655fe37036f47756db8102e0d7d5e28b3beb83a8fef4f5dc0559bddfb94e02205a36d4e4e6c7fcd16658c50783e00c341609977aed3ad00937bf4ee942a8993701483045022100da6bee3c93766232079a01639d07fa869598749729ae323eab8eef53577d611b02207bef15429dcadce2121ea07f233115c6f09034c0be68db99980b9a6c5e75402201475221022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb7152aeffffffff04d3b11400000000001976a914904a49878c0adfc3aa05de7afad2cc15f483a56a88ac7f400900000000001976a914418327e3f3dda4cf5b9089325a4b95abdfa0334088ac722c0c00000000001976a914ba35042cfe9fc66fd35ac2224eebdafd1028ad2788acdc4ace020000000017a91474d691da1574e6b3c192ecfb52cc8984ee7b6c568700000000"
     tx_obj = Tx.parse(BytesIO(bytes.fromhex(raw_tx)))
     sig1 = bytes.fromhex(
         "3045022100dc92655fe37036f47756db8102e0d7d5e28b3beb83a8fef4f5dc0559bddfb94e02205a36d4e4e6c7fcd16658c50783e00c341609977aed3ad00937bf4ee942a8993701"
     )
     sig2 = bytes.fromhex(
         "3045022100da6bee3c93766232079a01639d07fa869598749729ae323eab8eef53577d611b02207bef15429dcadce2121ea07f233115c6f09034c0be68db99980b9a6c5e75402201"
     )
     sec1 = bytes.fromhex(
         "022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb70"
     )
     sec2 = bytes.fromhex(
         "03b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb71"
     )
     stack = [b"", sig1, sig2, b"\x02", sec1, sec2, b"\x02"]
     self.assertTrue(op_checkmultisig(stack, tx_obj, 0))
     self.assertEqual(decode_num(stack[0]), 1)
Esempio n. 19
0
 def test_sign_p2sh_multisig(self):
     private_key1 = PrivateKey(secret=8675309)
     private_key2 = PrivateKey(secret=8675310)
     redeem_script = RedeemScript.create_p2sh_multisig(
         quorum_m=2,
         pubkey_hexes=[
             private_key1.point.sec().hex(),
             private_key2.point.sec().hex(),
         ],
         sort_keys=False,
     )
     prev_tx = bytes.fromhex(
         "ded9b3c8b71032d42ea3b2fd5211d75b39a90637f967e637b64dfdb887dd11d7"
     )
     prev_index = 1
     fee_sats = 500
     tx_in = TxIn(prev_tx, prev_index)
     tx_in_sats = 1000000
     amount = tx_in_sats - fee_sats
     tx_out = TxOut.to_address("mqYz6JpuKukHzPg94y4XNDdPCEJrNkLQcv", amount)
     t = Tx(1, [tx_in], [tx_out], 0, network="testnet", segwit=True)
     sig1 = t.get_sig_legacy(0, private_key1, redeem_script=redeem_script)
     sig2 = t.get_sig_legacy(0, private_key2, redeem_script=redeem_script)
     self.assertTrue(
         t.check_sig_legacy(
             0,
             private_key1.point,
             Signature.parse(sig1[:-1]),
             redeem_script=redeem_script,
         )
     )
     self.assertTrue(
         t.check_sig_legacy(
             0,
             private_key2.point,
             Signature.parse(sig2[:-1]),
             redeem_script=redeem_script,
         )
     )
     tx_in.finalize_p2sh_multisig([sig1, sig2], redeem_script)
     want = "01000000000101d711dd87b8fd4db637e667f93706a9395bd71152fdb2a32ed43210b7c8b3d9de01000000da00483045022100c457fa45f63636eb2552cef642116a8363469d60b99dcda19686d30ed2a539bb0220222c7617e3dd9aef37095df52047e9a6bf11254a88eab521aec1b8b4e7913b3401473044022003d3d6a1b232b42d9fb961b42ab6854077a1e195473d952d54e6dcf22ef6dede02206f62a44b65e1dbccbdd54a3fd6f87c05a8d8da39c70e06f5ee07d469e1155e020147522103935581e52c354cd2f484fe8ed83af7a3097005b2f9c60bff71d35bd795f54b672103674944c63d8dc3373a88cd1f8403b39b48be07bdb83d51dbbaa34be070c72e1452aeffffffff014c400f00000000001976a9146e13971913b9aa89659a9f53d327baa8826f2d7588ac0000000000"
     self.assertEqual(t.serialize().hex(), want)
Esempio n. 20
0
    def test_sign_p2sh_p2wsh_multisig(self):
        private_key1 = PrivateKey(secret=8675309)
        private_key2 = PrivateKey(secret=8675310)
        witness_script = WitnessScript(
            [0x52, private_key1.point.sec(), private_key2.point.sec(), 0x52, 0xAE]
        )
        prev_tx = bytes.fromhex(
            "f92c8c8e40296c6a94539b6d22d8994a56dd8ff2d6018d07a8371fef1f66efee"
        )
        prev_index = 0
        fee = 500
        tx_in = TxIn(prev_tx, prev_index)
        amount = tx_in.value(network="testnet") - fee
        tx_out = TxOut.to_address("mqYz6JpuKukHzPg94y4XNDdPCEJrNkLQcv", amount)
        t = Tx(1, [tx_in], [tx_out], 0, network="testnet", segwit=True)
        sig1 = t.get_sig_segwit(0, private_key1, witness_script=witness_script)
        sig2 = t.get_sig_segwit(0, private_key2, witness_script=witness_script)
        self.assertTrue(
            t.check_sig_segwit(
                0,
                private_key1.point,
                Signature.parse(sig1[:-1]),
                witness_script=witness_script,
            )
        )
        self.assertTrue(
            t.check_sig_segwit(
                0,
                private_key2.point,
                Signature.parse(sig2[:-1]),
                witness_script=witness_script,
            )
        )
        tx_in.finalize_p2sh_p2wsh_multisig([sig1, sig2], witness_script)

        want = "01000000000101eeef661fef1f37a8078d01d6f28fdd564a99d8226d9b53946a6c29408e8c2cf900000000232200206ddafd1089f07a2ba9868df71f622801fe11f5452c6ff1f8f51573133828b437ffffffff014c400f00000000001976a9146e13971913b9aa89659a9f53d327baa8826f2d7588ac0400483045022100d31433973b7f8014a4e17d46c4720c6c9bed1ee720dc1f0839dd847fa6972553022039278e98a3c18f4748a2727b99acd41eb1534dcf041a3abefd0c7546c868f55801473044022027be7d616b0930c1edf7ed39cc99edf5975e7b859d3224fe340d55c595c2798f02206c05662d39e5b05cc13f936360d62a482b122ad9791074bbdafec3ddc221b8c00147522103935581e52c354cd2f484fe8ed83af7a3097005b2f9c60bff71d35bd795f54b672103674944c63d8dc3373a88cd1f8403b39b48be07bdb83d51dbbaa34be070c72e1452ae00000000"
        self.assertEqual(t.serialize().hex(), want)
Esempio n. 21
0
 def test_sign_p2wsh_multisig(self):
     private_key1 = PrivateKey(secret=8675309)
     private_key2 = PrivateKey(secret=8675310)
     witness_script = WitnessScript(
         [0x52, private_key1.point.sec(), private_key2.point.sec(), 0x52, 0xAE]
     )
     prev_tx = bytes.fromhex(
         "61cd20e3ffdf9216cee9cd607e1a65d3096513c4df3a63d410c047379b54a94a"
     )
     prev_index = 1
     fee = 500
     tx_in = TxIn(prev_tx, prev_index)
     amount = tx_in.value(network="testnet") - fee
     tx_out = TxOut.to_address("mqYz6JpuKukHzPg94y4XNDdPCEJrNkLQcv", amount)
     t = Tx(1, [tx_in], [tx_out], 0, network="testnet", segwit=True)
     sig1 = t.get_sig_segwit(0, private_key1, witness_script=witness_script)
     sig2 = t.get_sig_segwit(0, private_key2, witness_script=witness_script)
     self.assertTrue(
         t.check_sig_segwit(
             0,
             private_key1.point,
             Signature.parse(sig1[:-1]),
             witness_script=witness_script,
         )
     )
     self.assertTrue(
         t.check_sig_segwit(
             0,
             private_key2.point,
             Signature.parse(sig2[:-1]),
             witness_script=witness_script,
         )
     )
     tx_in.finalize_p2wsh_multisig([sig1, sig2], witness_script)
     want = "010000000001014aa9549b3747c010d4633adfc4136509d3651a7e60cde9ce1692dfffe320cd610100000000ffffffff014c400f00000000001976a9146e13971913b9aa89659a9f53d327baa8826f2d7588ac04004730440220325e9f389c4835dab74d644e8c8e295535d9b082d28aefc3fa127e23538051bd022050d68dcecda660d4c01a8443c2b30bd0b3e4b1a405b0f352dcb068210862f6810147304402201abceabfc94903644cf7be836876eaa418cb226e03554c17a71c65b232f4507302202105a8344abae9632d1bc8249a52cf651c4ea02ca5259e20b50d8169c949f5a20147522103935581e52c354cd2f484fe8ed83af7a3097005b2f9c60bff71d35bd795f54b672103674944c63d8dc3373a88cd1f8403b39b48be07bdb83d51dbbaa34be070c72e1452ae00000000"
     self.assertEqual(t.serialize().hex(), want)
Esempio n. 22
0
 def test_p2tr_spending(self):
     test = {
         "given": {
             "rawUnsignedTx": "02000000097de20cbff686da83a54981d2b9bab3586f4ca7e48f57f5b55963115f3b334e9c010000000000000000d7b7cab57b1393ace2d064f4d4a2cb8af6def61273e127517d44759b6dafdd990000000000fffffffff8e1f583384333689228c5d28eac13366be082dc57441760d957275419a418420000000000fffffffff0689180aa63b30cb162a73c6d2a38b7eeda2a83ece74310fda0843ad604853b0100000000feffffffaa5202bdf6d8ccd2ee0f0202afbbb7461d9264a25e5bfd3c5a52ee1239e0ba6c0000000000feffffff956149bdc66faa968eb2be2d2faa29718acbfe3941215893a2a3446d32acd050000000000000000000e664b9773b88c09c32cb70a2a3e4da0ced63b7ba3b22f848531bbb1d5d5f4c94010000000000000000e9aa6b8e6c9de67619e6a3924ae25696bb7b694bb677a632a74ef7eadfd4eabf0000000000ffffffffa778eb6a263dc090464cd125c466b5a99667720b1c110468831d058aa1b82af10100000000ffffffff0200ca9a3b000000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac807840cb0000000020ac9a87f5594be208f8532db38cff670c450ed2fea8fcdefcc9a663f78bab962b0065cd1d",
             "utxosSpent": [
                 {
                     "scriptPubKey": "512053a1f6e454df1aa2776a2814a721372d6258050de330b3c6d10ee8f4e0dda343",
                     "amountSats": 420000000,
                 },
                 {
                     "scriptPubKey": "5120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3",
                     "amountSats": 462000000,
                 },
                 {
                     "scriptPubKey": "76a914751e76e8199196d454941c45d1b3a323f1433bd688ac",
                     "amountSats": 294000000,
                 },
                 {
                     "scriptPubKey": "5120e4d810fd50586274face62b8a807eb9719cef49c04177cc6b76a9a4251d5450e",
                     "amountSats": 504000000,
                 },
                 {
                     "scriptPubKey": "512091b64d5324723a985170e4dc5a0f84c041804f2cd12660fa5dec09fc21783605",
                     "amountSats": 630000000,
                 },
                 {
                     "scriptPubKey": "00147dd65592d0ab2fe0d0257d571abf032cd9db93dc",
                     "amountSats": 378000000,
                 },
                 {
                     "scriptPubKey": "512075169f4001aa68f15bbed28b218df1d0a62cbbcf1188c6665110c293c907b831",
                     "amountSats": 672000000,
                 },
                 {
                     "scriptPubKey": "5120712447206d7a5238acc7ff53fbe94a3b64539ad291c7cdbc490b7577e4b17df5",
                     "amountSats": 546000000,
                 },
                 {
                     "scriptPubKey": "512077e30a5522dd9f894c3f8b8bd4c4b2cf82ca7da8a3ea6a239655c39c050ab220",
                     "amountSats": 588000000,
                 },
             ],
         },
         "intermediary": {
             "hashAmounts": "58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde6",
             "hashOutputs": "a2e6dab7c1f0dcd297c8d61647fd17d821541ea69c3cc37dcbad7f90d4eb4bc5",
             "hashPrevouts": "e3b33bb4ef3a52ad1fffb555c0d82828eb22737036eaeb02a235d82b909c4c3f",
             "hashScriptPubkeys": "23ad0f61ad2bca5ba6a7693f50fce988e17c3780bf2b1e720cfbb38fbdd52e21",
             "hashSequences": "18959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957e",
         },
         "inputSpending": [
             {
                 "given": {
                     "txinIndex": 0,
                     "internalPrivkey": "6b973d88838f27366ed61c9ad6367663045cb456e28335c109e30717ae0c6baa",
                     "merkleRoot": None,
                     "hashType": 3,
                 },
                 "intermediary": {
                     "internalPubkey": "d6889cb081036e0faefa3a35157ad71086b123b2b144b649798b494c300a961d",
                     "tweak": "b86e7be8f39bab32a6f2c0443abbc210f0edac0e2c53d501b36b64437d9c6c70",
                     "tweakedPrivkey": "2405b971772ad26915c8dcdf10f238753a9b837e5f8e6a86fd7c0cce5b7296d9",
                     "sigMsg": "0003020000000065cd1de3b33bb4ef3a52ad1fffb555c0d82828eb22737036eaeb02a235d82b909c4c3f58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde623ad0f61ad2bca5ba6a7693f50fce988e17c3780bf2b1e720cfbb38fbdd52e2118959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957e0000000000d0418f0e9a36245b9a50ec87f8bf5be5bcae434337b87139c3a5b1f56e33cba0",
                     "precomputedUsed": [
                         "hashAmounts",
                         "hashPrevouts",
                         "hashScriptPubkeys",
                         "hashSequences",
                     ],
                     "sigHash": "2514a6272f85cfa0f45eb907fcb0d121b808ed37c6ea160a5a9046ed5526d555",
                 },
                 "expected": {
                     "witness": [
                         "ed7c1647cb97379e76892be0cacff57ec4a7102aa24296ca39af7541246d8ff14d38958d4cc1e2e478e4d4a764bbfd835b16d4e314b72937b29833060b87276c03"
                     ]
                 },
             },
             {
                 "given": {
                     "txinIndex": 1,
                     "internalPrivkey": "1e4da49f6aaf4e5cd175fe08a32bb5cb4863d963921255f33d3bc31e1343907f",
                     "merkleRoot": "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21",
                     "hashType": 131,
                 },
                 "intermediary": {
                     "internalPubkey": "187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27",
                     "tweak": "cbd8679ba636c1110ea247542cfbd964131a6be84f873f7f3b62a777528ed001",
                     "tweakedPrivkey": "ea260c3b10e60f6de018455cd0278f2f5b7e454be1999572789e6a9565d26080",
                     "sigMsg": "0083020000000065cd1d00d7b7cab57b1393ace2d064f4d4a2cb8af6def61273e127517d44759b6dafdd9900000000808f891b00000000225120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3ffffffffffcef8fb4ca7efc5433f591ecfc57391811ce1e186a3793024def5c884cba51d",
                     "precomputedUsed": [],
                     "sigHash": "325a644af47e8a5a2591cda0ab0723978537318f10e6a63d4eed783b96a71a4d",
                 },
                 "expected": {
                     "witness": [
                         "052aedffc554b41f52b521071793a6b88d6dbca9dba94cf34c83696de0c1ec35ca9c5ed4ab28059bd606a4f3a657eec0bb96661d42921b5f50a95ad33675b54f83"
                     ]
                 },
             },
             {
                 "given": {
                     "txinIndex": 3,
                     "internalPrivkey": "d3c7af07da2d54f7a7735d3d0fc4f0a73164db638b2f2f7c43f711f6d4aa7e64",
                     "merkleRoot": "c525714a7f49c28aedbbba78c005931a81c234b2f6c99a73e4d06082adc8bf2b",
                     "hashType": 1,
                 },
                 "intermediary": {
                     "internalPubkey": "93478e9488f956df2396be2ce6c5cced75f900dfa18e7dabd2428aae78451820",
                     "tweak": "6af9e28dbf9d6aaf027696e2598a5b3d056f5fd2355a7fd5a37a0e5008132d30",
                     "tweakedPrivkey": "97323385e57015b75b0339a549c56a948eb961555973f0951f555ae6039ef00d",
                     "sigMsg": "0001020000000065cd1de3b33bb4ef3a52ad1fffb555c0d82828eb22737036eaeb02a235d82b909c4c3f58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde623ad0f61ad2bca5ba6a7693f50fce988e17c3780bf2b1e720cfbb38fbdd52e2118959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957ea2e6dab7c1f0dcd297c8d61647fd17d821541ea69c3cc37dcbad7f90d4eb4bc50003000000",
                     "precomputedUsed": [
                         "hashAmounts",
                         "hashOutputs",
                         "hashPrevouts",
                         "hashScriptPubkeys",
                         "hashSequences",
                     ],
                     "sigHash": "bf013ea93474aa67815b1b6cc441d23b64fa310911d991e713cd34c7f5d46669",
                 },
                 "expected": {
                     "witness": [
                         "ff45f742a876139946a149ab4d9185574b98dc919d2eb6754f8abaa59d18b025637a3aa043b91817739554f4ed2026cf8022dbd83e351ce1fabc272841d2510a01"
                     ]
                 },
             },
             {
                 "given": {
                     "txinIndex": 4,
                     "internalPrivkey": "f36bb07a11e469ce941d16b63b11b9b9120a84d9d87cff2c84a8d4affb438f4e",
                     "merkleRoot": "ccbd66c6f7e8fdab47b3a486f59d28262be857f30d4773f2d5ea47f7761ce0e2",
                     "hashType": 0,
                 },
                 "intermediary": {
                     "internalPubkey": "e0dfe2300b0dd746a3f8674dfd4525623639042569d829c7f0eed9602d263e6f",
                     "tweak": "b57bfa183d28eeb6ad688ddaabb265b4a41fbf68e5fed2c72c74de70d5a786f4",
                     "tweakedPrivkey": "a8e7aa924f0d58854185a490e6c41f6efb7b675c0f3331b7f14b549400b4d501",
                     "sigMsg": "0000020000000065cd1de3b33bb4ef3a52ad1fffb555c0d82828eb22737036eaeb02a235d82b909c4c3f58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde623ad0f61ad2bca5ba6a7693f50fce988e17c3780bf2b1e720cfbb38fbdd52e2118959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957ea2e6dab7c1f0dcd297c8d61647fd17d821541ea69c3cc37dcbad7f90d4eb4bc50004000000",
                     "precomputedUsed": [
                         "hashAmounts",
                         "hashOutputs",
                         "hashPrevouts",
                         "hashScriptPubkeys",
                         "hashSequences",
                     ],
                     "sigHash": "4f900a0bae3f1446fd48490c2958b5a023228f01661cda3496a11da502a7f7ef",
                 },
                 "expected": {
                     "witness": [
                         "b4010dd48a617db09926f729e79c33ae0b4e94b79f04a1ae93ede6315eb3669de185a17d2b0ac9ee09fd4c64b678a0b61a0a86fa888a273c8511be83bfd6810f"
                     ]
                 },
             },
             {
                 "given": {
                     "txinIndex": 6,
                     "internalPrivkey": "415cfe9c15d9cea27d8104d5517c06e9de48e2f986b695e4f5ffebf230e725d8",
                     "merkleRoot": "2f6b2c5397b6d68ca18e09a3f05161668ffe93a988582d55c6f07bd5b3329def",
                     "hashType": 2,
                 },
                 "intermediary": {
                     "internalPubkey": "55adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312d",
                     "tweak": "6579138e7976dc13b6a92f7bfd5a2fc7684f5ea42419d43368301470f3b74ed9",
                     "tweakedPrivkey": "241c14f2639d0d7139282aa6abde28dd8a067baa9d633e4e7230287ec2d02901",
                     "sigMsg": "0002020000000065cd1de3b33bb4ef3a52ad1fffb555c0d82828eb22737036eaeb02a235d82b909c4c3f58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde623ad0f61ad2bca5ba6a7693f50fce988e17c3780bf2b1e720cfbb38fbdd52e2118959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957e0006000000",
                     "precomputedUsed": [
                         "hashAmounts",
                         "hashPrevouts",
                         "hashScriptPubkeys",
                         "hashSequences",
                     ],
                     "sigHash": "15f25c298eb5cdc7eb1d638dd2d45c97c4c59dcaec6679cfc16ad84f30876b85",
                 },
                 "expected": {
                     "witness": [
                         "a3785919a2ce3c4ce26f298c3d51619bc474ae24014bcdd31328cd8cfbab2eff3395fa0a16fe5f486d12f22a9cedded5ae74feb4bbe5351346508c5405bcfee002"
                     ]
                 },
             },
             {
                 "given": {
                     "txinIndex": 7,
                     "internalPrivkey": "c7b0e81f0a9a0b0499e112279d718cca98e79a12e2f137c72ae5b213aad0d103",
                     "merkleRoot": "6c2dc106ab816b73f9d07e3cd1ef2c8c1256f519748e0813e4edd2405d277bef",
                     "hashType": 130,
                 },
                 "intermediary": {
                     "internalPubkey": "ee4fe085983462a184015d1f782d6a5f8b9c2b60130aff050ce221ecf3786592",
                     "tweak": "9e0517edc8259bb3359255400b23ca9507f2a91cd1e4250ba068b4eafceba4a9",
                     "tweakedPrivkey": "65b6000cd2bfa6b7cf736767a8955760e62b6649058cbc970b7c0871d786346b",
                     "sigMsg": "0082020000000065cd1d00e9aa6b8e6c9de67619e6a3924ae25696bb7b694bb677a632a74ef7eadfd4eabf00000000804c8b2000000000225120712447206d7a5238acc7ff53fbe94a3b64539ad291c7cdbc490b7577e4b17df5ffffffff",
                     "precomputedUsed": [],
                     "sigHash": "cd292de50313804dabe4685e83f923d2969577191a3e1d2882220dca88cbeb10",
                 },
                 "expected": {
                     "witness": [
                         "ea0c6ba90763c2d3a296ad82ba45881abb4f426b3f87af162dd24d5109edc1cdd11915095ba47c3a9963dc1e6c432939872bc49212fe34c632cd3ab9fed429c482"
                     ]
                 },
             },
             {
                 "given": {
                     "txinIndex": 8,
                     "internalPrivkey": "77863416be0d0665e517e1c375fd6f75839544eca553675ef7fdf4949518ebaa",
                     "merkleRoot": "ab179431c28d3b68fb798957faf5497d69c883c6fb1e1cd9f81483d87bac90cc",
                     "hashType": 129,
                 },
                 "intermediary": {
                     "internalPubkey": "f9f400803e683727b14f463836e1e78e1c64417638aa066919291a225f0e8dd8",
                     "tweak": "639f0281b7ac49e742cd25b7f188657626da1ad169209078e2761cefd91fd65e",
                     "tweakedPrivkey": "ec18ce6af99f43815db543f47b8af5ff5df3b2cb7315c955aa4a86e8143d2bf5",
                     "sigMsg": "0081020000000065cd1da2e6dab7c1f0dcd297c8d61647fd17d821541ea69c3cc37dcbad7f90d4eb4bc500a778eb6a263dc090464cd125c466b5a99667720b1c110468831d058aa1b82af101000000002b0c230000000022512077e30a5522dd9f894c3f8b8bd4c4b2cf82ca7da8a3ea6a239655c39c050ab220ffffffff",
                     "precomputedUsed": ["hashOutputs"],
                     "sigHash": "cccb739eca6c13a8a89e6e5cd317ffe55669bbda23f2fd37b0f18755e008edd2",
                 },
                 "expected": {
                     "witness": [
                         "bbc9584a11074e83bc8c6759ec55401f0ae7b03ef290c3139814f545b58a9f8127258000874f44bc46db7646322107d4d86aec8e73b8719a61fff761d75b5dd981"
                     ]
                 },
             },
         ],
         "auxiliary": {
             "fullySignedTx": "020000000001097de20cbff686da83a54981d2b9bab3586f4ca7e48f57f5b55963115f3b334e9c010000000000000000d7b7cab57b1393ace2d064f4d4a2cb8af6def61273e127517d44759b6dafdd990000000000fffffffff8e1f583384333689228c5d28eac13366be082dc57441760d957275419a41842000000006b4830450221008f3b8f8f0537c420654d2283673a761b7ee2ea3c130753103e08ce79201cf32a022079e7ab904a1980ef1c5890b648c8783f4d10103dd62f740d13daa79e298d50c201210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798fffffffff0689180aa63b30cb162a73c6d2a38b7eeda2a83ece74310fda0843ad604853b0100000000feffffffaa5202bdf6d8ccd2ee0f0202afbbb7461d9264a25e5bfd3c5a52ee1239e0ba6c0000000000feffffff956149bdc66faa968eb2be2d2faa29718acbfe3941215893a2a3446d32acd050000000000000000000e664b9773b88c09c32cb70a2a3e4da0ced63b7ba3b22f848531bbb1d5d5f4c94010000000000000000e9aa6b8e6c9de67619e6a3924ae25696bb7b694bb677a632a74ef7eadfd4eabf0000000000ffffffffa778eb6a263dc090464cd125c466b5a99667720b1c110468831d058aa1b82af10100000000ffffffff0200ca9a3b000000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac807840cb0000000020ac9a87f5594be208f8532db38cff670c450ed2fea8fcdefcc9a663f78bab962b0141ed7c1647cb97379e76892be0cacff57ec4a7102aa24296ca39af7541246d8ff14d38958d4cc1e2e478e4d4a764bbfd835b16d4e314b72937b29833060b87276c030141052aedffc554b41f52b521071793a6b88d6dbca9dba94cf34c83696de0c1ec35ca9c5ed4ab28059bd606a4f3a657eec0bb96661d42921b5f50a95ad33675b54f83000141ff45f742a876139946a149ab4d9185574b98dc919d2eb6754f8abaa59d18b025637a3aa043b91817739554f4ed2026cf8022dbd83e351ce1fabc272841d2510a010140b4010dd48a617db09926f729e79c33ae0b4e94b79f04a1ae93ede6315eb3669de185a17d2b0ac9ee09fd4c64b678a0b61a0a86fa888a273c8511be83bfd6810f0247304402202b795e4de72646d76eab3f0ab27dfa30b810e856ff3a46c9a702df53bb0d8cc302203ccc4d822edab5f35caddb10af1be93583526ccfbade4b4ead350781e2f8adcd012102f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f90141a3785919a2ce3c4ce26f298c3d51619bc474ae24014bcdd31328cd8cfbab2eff3395fa0a16fe5f486d12f22a9cedded5ae74feb4bbe5351346508c5405bcfee0020141ea0c6ba90763c2d3a296ad82ba45881abb4f426b3f87af162dd24d5109edc1cdd11915095ba47c3a9963dc1e6c432939872bc49212fe34c632cd3ab9fed429c4820141bbc9584a11074e83bc8c6759ec55401f0ae7b03ef290c3139814f545b58a9f8127258000874f44bc46db7646322107d4d86aec8e73b8719a61fff761d75b5dd9810065cd1d"
         },
     }
     hex_tx = test["given"]["rawUnsignedTx"]
     tx_obj = Tx.parse(BytesIO(bytes.fromhex(hex_tx)))
     self.maxDiff = None
     self.assertEqual(tx_obj.serialize().hex(), hex_tx)
     tx_obj.segwit = True
     for tx_in, utxo in zip(tx_obj.tx_ins, test["given"]["utxosSpent"]):
         tx_in._value = utxo["amountSats"]
         tx_in._script_pubkey = Script.parse(
             BytesIO(encode_varstr(bytes.fromhex(utxo["scriptPubKey"])))
         )
     shas = test["intermediary"]
     self.assertEqual(tx_obj.sha_amounts().hex(), shas["hashAmounts"])
     self.assertEqual(tx_obj.sha_outputs().hex(), shas["hashOutputs"])
     self.assertEqual(tx_obj.sha_prevouts().hex(), shas["hashPrevouts"])
     self.assertEqual(tx_obj.sha_script_pubkeys().hex(), shas["hashScriptPubkeys"])
     self.assertEqual(tx_obj.sha_sequences().hex(), shas["hashSequences"])
     fully_signed = test["auxiliary"]["fullySignedTx"]
     signed_tx = Tx.parse(BytesIO(bytes.fromhex(fully_signed)))
     for input_data in test["inputSpending"]:
         i = input_data["given"]["txinIndex"]
         secret = big_endian_to_int(
             bytes.fromhex(input_data["given"]["internalPrivkey"])
         )
         tx_in = tx_obj.tx_ins[i]
         private_key = PrivateKey(secret)
         pubkey = private_key.point
         hash_type = input_data["given"]["hashType"]
         self.assertEqual(
             pubkey.bip340().hex(), input_data["intermediary"]["internalPubkey"]
         )
         mr_hex = input_data["given"]["merkleRoot"]
         if mr_hex is None:
             merkle_root = None
         else:
             merkle_root = bytes.fromhex(mr_hex)
         tap_root = TapRoot(pubkey, merkle_root=merkle_root)
         tweak_want = big_endian_to_int(
             bytes.fromhex(input_data["intermediary"]["tweak"])
         )
         self.assertEqual(tap_root.tweak, tweak_want)
         tweaked_private_key = private_key.tweaked(tap_root.tweak)
         tweaked_want = big_endian_to_int(
             bytes.fromhex(input_data["intermediary"]["tweakedPrivkey"])
         )
         self.assertEqual(tweaked_private_key.secret, tweaked_want)
         sig_hash_want = input_data["intermediary"]["sigHash"]
         self.assertEqual(
             tx_obj.sig_hash_bip341(i, hash_type=hash_type).hex(), sig_hash_want
         )
         tx_obj.sign_input(i, tweaked_private_key, hash_type=hash_type)
         for j, witness_want in enumerate(input_data["expected"]["witness"]):
             self.assertEqual(tx_in.witness[j].hex(), witness_want)
     # the two we can't sign
     for i in (2, 5):
         signed_tx.tx_ins[i].script_sig = Script()
         signed_tx.tx_ins[i].witness = Witness()
     self.assertEqual(tx_obj.serialize(), signed_tx.serialize())
Esempio n. 23
0
def create_multisig_psbt(
    public_key_records,
    input_dicts,
    output_dicts,
    fee_sats,
    script_type="p2sh",
):
    """
    Helper method to create a multisig PSBT whose change can be validated.

    network (testnet/mainnet/signet) will be inferred from xpubs/tpubs.

    public_key_records are a list of entries that loom like this: [xfp_hex, xpub_b58, base_path]
    # TODO: turn this into a new object?
    """
    if script_type != "p2sh":
        raise NotImplementedError(f"script_type {script_type} not yet implemented")

    # initialize variables
    network = None
    tx_lookup, pubkey_lookup, redeem_lookup, hd_pubs = {}, {}, {}, {}

    # Use a nested default dict for increased readability
    # It's possible (though nonstandard) for one xfp to have multiple public_key_records in a multisig wallet
    # https://stackoverflow.com/a/19189356
    recursive_defaultdict = lambda: defaultdict(recursive_defaultdict)  # noqa: E731
    xfp_dict = recursive_defaultdict()

    # This at the child pubkey lookup that each input will traverse off of
    for xfp_hex, xpub_b58, base_path in public_key_records:
        hd_pubkey_obj = HDPublicKey.parse(xpub_b58)

        # We will use this dict/list structure for each input/ouput in the for-loops below
        xfp_dict[xfp_hex][base_path] = hd_pubkey_obj

        named_global_hd_pubkey_obj = NamedHDPublicKey.from_hd_pub(
            child_hd_pub=hd_pubkey_obj,
            xfp_hex=xfp_hex,
            # we're only going to base path level
            path=base_path,
        )
        hd_pubs[named_global_hd_pubkey_obj.serialize()] = named_global_hd_pubkey_obj

        if network is None:
            # Set the initial value
            network = hd_pubkey_obj.network
        else:
            # Confirm it hasn't changed
            if network != hd_pubkey_obj.network:
                raise MixedNetwork(
                    f"Mixed networks in public key records: {public_key_records}"
                )

    tx_ins, total_input_sats = [], 0
    for cnt, input_dict in enumerate(input_dicts):

        # Prev tx stuff
        prev_tx_dict = input_dict["prev_tx_dict"]
        prev_tx_obj = Tx.parse_hex(prev_tx_dict["hex"], network=network)
        tx_lookup[prev_tx_obj.hash()] = prev_tx_obj

        if prev_tx_dict["hash_hex"] != prev_tx_obj.hash().hex():
            raise ValueError(
                f"Hash digest mismatch for input #{cnt}: {prev_tx_dict['hash_hex']} != {prev_tx_obj.hash().hex()}"
            )

        if "path_dict" in input_dict:
            # Standard BIP67 unordered list of pubkeys (will be sorted lexicographically)
            iterator = input_dict["path_dict"].items()
            sort_keys = True
        elif "path_list" in input_dict:
            # Caller supplied ordering of pubkeys (will not be sorted)
            iterator = input_dict["path_list"]
            sort_keys = False
        else:
            raise RuntimeError(
                f"input_dict has no `path_dict` nor a `path_list`: {input_dict}"
            )

        input_pubkey_hexes = []
        for xfp_hex, root_path in iterator:
            # Get the correct xpub/path
            child_hd_pubkey = _safe_get_child_hdpubkey(
                xfp_dict=xfp_dict,
                xfp_hex=xfp_hex,
                root_path=root_path,
                cnt=cnt,
            )
            input_pubkey_hexes.append(child_hd_pubkey.sec().hex())

            # Enhance the PSBT
            named_hd_pubkey_obj = NamedHDPublicKey.from_hd_pub(
                child_hd_pub=child_hd_pubkey,
                xfp_hex=xfp_hex,
                path=root_path,
            )
            # pubkey lookups needed for validation
            pubkey_lookup[named_hd_pubkey_obj.sec()] = named_hd_pubkey_obj

        utxo = prev_tx_obj.tx_outs[prev_tx_dict["output_idx"]]

        # Grab amount as developer safety check
        if prev_tx_dict["output_sats"] != utxo.amount:
            raise ValueError(
                f"Wrong number of sats for input #{cnt}! Expecting {prev_tx_dict['output_sats']} but got {utxo.amount}"
            )
        total_input_sats += utxo.amount

        redeem_script = RedeemScript.create_p2sh_multisig(
            quorum_m=input_dict["quorum_m"],
            pubkey_hexes=input_pubkey_hexes,
            sort_keys=sort_keys,
            expected_addr=utxo.script_pubkey.address(network=network),
            expected_addr_network=network,
        )

        # Confirm address matches previous ouput
        if redeem_script.address(network=network) != utxo.script_pubkey.address(
            network=network
        ):
            raise ValueError(
                f"Invalid redeem script for input #{cnt}. Expecting {redeem_script.address(network=network)} but got {utxo.script_pubkey.address(network=network)}"
            )

        tx_in = TxIn(prev_tx=prev_tx_obj.hash(), prev_index=prev_tx_dict["output_idx"])
        tx_ins.append(tx_in)

        # For enhancing the PSBT for HWWs:
        redeem_lookup[redeem_script.hash160()] = redeem_script

    tx_outs = []
    for cnt, output_dict in enumerate(output_dicts):
        tx_out = TxOut(
            amount=output_dict["sats"],
            script_pubkey=address_to_script_pubkey(output_dict["address"]),
        )
        tx_outs.append(tx_out)

        if output_dict.get("path_dict"):
            # This output claims to be change, so we must validate it here
            output_pubkey_hexes = []
            for xfp_hex, root_path in output_dict["path_dict"].items():
                child_hd_pubkey = _safe_get_child_hdpubkey(
                    xfp_dict=xfp_dict,
                    xfp_hex=xfp_hex,
                    root_path=root_path,
                    cnt=cnt,
                )
                output_pubkey_hexes.append(child_hd_pubkey.sec().hex())

                # Enhance the PSBT
                named_hd_pubkey_obj = NamedHDPublicKey.from_hd_pub(
                    child_hd_pub=child_hd_pubkey,
                    xfp_hex=xfp_hex,
                    path=root_path,
                )
                pubkey_lookup[named_hd_pubkey_obj.sec()] = named_hd_pubkey_obj

            redeem_script = RedeemScript.create_p2sh_multisig(
                quorum_m=output_dict["quorum_m"],
                pubkey_hexes=output_pubkey_hexes,
                # We intentionally only allow change addresses to be lexicographically sorted
                sort_keys=True,
            )
            # Confirm address matches previous ouput
            if redeem_script.address(network=network) != output_dict["address"]:
                raise ValueError(
                    f"Invalid redeem script for output #{cnt}. Expecting {redeem_script.address(network=network)} but got {output_dict['address']}"
                )

            # For enhancing the PSBT for HWWs:
            redeem_lookup[redeem_script.hash160()] = redeem_script

    tx_obj = Tx(
        version=1,
        tx_ins=tx_ins,
        tx_outs=tx_outs,
        locktime=0,
        network=network,
        segwit=False,
    )

    # Safety check to try and prevent footgun

    calculated_fee_sats = total_input_sats - sum([tx_out.amount for tx_out in tx_outs])
    if fee_sats != calculated_fee_sats:
        raise ValueError(
            f"TX fee of {fee_sats} sats supplied != {calculated_fee_sats} sats calculated"
        )

    return PSBT.create(
        tx_obj=tx_obj,
        validate=True,
        tx_lookup=tx_lookup,
        pubkey_lookup=pubkey_lookup,
        redeem_lookup=redeem_lookup,
        witness_lookup={},
        hd_pubs=hd_pubs,
    )
Esempio n. 24
0
 def test_is_coinbase(self):
     raw_tx = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff5e03d71b07254d696e656420627920416e74506f6f6c20626a31312f4542312f4144362f43205914293101fabe6d6d678e2c8c34afc36896e7d9402824ed38e856676ee94bfdb0c6c4bcd8b2e5666a0400000000000000c7270000a5e00e00ffffffff01faf20b58000000001976a914338c84849423992471bffb1a54a8d9b1d69dc28a88ac00000000"
     tx = Tx.parse_hex(raw_tx)
     self.assertTrue(tx.is_coinbase())
Esempio n. 25
0
 def test_parse_tricky(self):
     raw_tx = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff2f0315230e0004ae03ca57043e3d1e1d0c8796bf579aef0c0000000000122f4e696e6a61506f6f6c2f5345475749542fffffffff038427a112000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9ed5c748e121c0fe146d973a4ac26fa4a68b0549d46ee22d25f50a5e46fe1b377ee00000000000000002952534b424c4f434b3acd16772ad61a3c5f00287480b720f6035d5e54c9efc71be94bb5e3727f10909000000000"
     tx_obj = Tx.parse_hex(raw_tx)
     self.assertEqual(tx_obj.serialize().hex(), raw_tx)