Ejemplo n.º 1
0
 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())
Ejemplo n.º 2
0
 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())
Ejemplo n.º 3
0
 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)
Ejemplo n.º 4
0
 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)
Ejemplo n.º 5
0
 def test_is_coinbase(self):
     raw_tx = unhexlify(
         '01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff5e03d71b07254d696e656420627920416e74506f6f6c20626a31312f4542312f4144362f43205914293101fabe6d6d678e2c8c34afc36896e7d9402824ed38e856676ee94bfdb0c6c4bcd8b2e5666a0400000000000000c7270000a5e00e00ffffffff01faf20b58000000001976a914338c84849423992471bffb1a54a8d9b1d69dc28a88ac00000000'
     )
     stream = BytesIO(raw_tx)
     tx = Tx.parse(stream)
     self.assertTrue(tx.is_coinbase())
 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(b'filterload', bf.filterload())
     getheaders_message = GetHeadersMessage(start_block=last_block)
     node.send(getheaders_message.command, getheaders_message.serialize())
     headers_envelope = node.wait_for_commands([HeadersMessage.command])
     stream = headers_envelope.stream()
     headers = HeadersMessage.parse(stream)
     get_data_message = GetDataMessage()
     for block in headers.blocks:
         self.assertTrue(block.check_pow())
         if last_block is not None:
             self.assertEqual(block.prev_block, last_block)
         last_block = block.hash()
         get_data_message.add_data(FILTERED_BLOCK_DATA_TYPE, last_block)
     node.send(get_data_message.command, get_data_message.serialize())
     prev_tx = None
     while prev_tx is None:
         envelope = node.wait_for_commands([b'merkleblock', b'tx'])
         stream = envelope.stream()
         if envelope.command == b'merkleblock':
             mb = MerkleBlock.parse(stream)
             self.assertTrue(mb.is_valid())
         else:
             prev = Tx.parse(stream, testnet=True)
             for i, tx_out in enumerate(prev.tx_outs):
                 if tx_out.script_pubkey.address(testnet=True) == addr:
                     prev_tx = prev.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'
     )
Ejemplo n.º 7
0
    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()
Ejemplo n.º 8
0
	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')
Ejemplo n.º 9
0
 def test_verify_input2(self):
     raw_tx = unhexlify(
         '0100000001868278ed6ddfb6c1ed3ad5f8181eb0c7a385aa0836f01d5e4789e6bd304d87221a000000db00483045022100dc92655fe37036f47756db8102e0d7d5e28b3beb83a8fef4f5dc0559bddfb94e02205a36d4e4e6c7fcd16658c50783e00c341609977aed3ad00937bf4ee942a8993701483045022100da6bee3c93766232079a01639d07fa869598749729ae323eab8eef53577d611b02207bef15429dcadce2121ea07f233115c6f09034c0be68db99980b9a6c5e75402201475221022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb7152aeffffffff04d3b11400000000001976a914904a49878c0adfc3aa05de7afad2cc15f483a56a88ac7f400900000000001976a914418327e3f3dda4cf5b9089325a4b95abdfa0334088ac722c0c00000000001976a914ba35042cfe9fc66fd35ac2224eebdafd1028ad2788acdc4ace020000000017a91474d691da1574e6b3c192ecfb52cc8984ee7b6c568700000000'
     )
     stream = BytesIO(raw_tx)
     tx = Tx.parse(stream)
     self.assertTrue(tx.verify_input(0))
Ejemplo n.º 10
0
 def test_serialize(self):
     raw_tx = unhexlify(
         '0100000001813f79011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d1000000006b483045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f02207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed01210349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278afeffffff02a135ef01000000001976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac99c39800000000001976a9141c4bc762dd5423e332166702cb75f40df79fea1288ac19430600'
     )
     stream = BytesIO(raw_tx)
     tx = Tx.parse(stream)
     self.assertEqual(tx.serialize(), raw_tx)
Ejemplo n.º 11
0
 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'
     )
Ejemplo n.º 12
0
 def test_example_4(self):
     modified_tx = bytes.fromhex('0100000001813f79011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d1000000001976a914a802fc56c704ce87c42d7c92eb75e7896bdc41ae88acfeffffff02a135ef01000000001976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac99c39800000000001976a9141c4bc762dd5423e332166702cb75f40df79fea1288ac1943060001000000')
     h256 = hash256(modified_tx)
     z = int.from_bytes(h256, 'big')
     stream = BytesIO(bytes.fromhex('0100000001813f79011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d1000000006b483045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f02207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed01210349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278afeffffff02a135ef01000000001976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac99c39800000000001976a9141c4bc762dd5423e332166702cb75f40df79fea1288ac19430600'))
     transaction = Tx.parse(stream)
     tx_in = transaction.tx_ins[0]
     combined_script = tx_in.script_sig + tx_in.script_pubkey()
     self.assertTrue(combined_script.evaluate(z))
Ejemplo n.º 13
0
 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
Ejemplo n.º 14
0
 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))
Ejemplo n.º 15
0
def listen_for_channel_request(peer):

    request = json.loads(peer.receive())
    funding_tx = Tx.parse(BytesIO(bytes.fromhex(request['funding_tx'])))
    if (funding_tx.verify()):
        new_channel = Channel(peer, request['remote_amt'],
                              request['local_amt'], funding_tx)
        return new_channel
    else:
        print("Invalid Channel Request")
        return None
Ejemplo n.º 16
0
 def test_sig_hash(self):
     raw_tx = unhexlify(
         '0100000001813f79011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d1000000006b483045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f02207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed01210349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278afeffffff02a135ef01000000001976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac99c39800000000001976a9141c4bc762dd5423e332166702cb75f40df79fea1288ac19430600'
     )
     stream = BytesIO(raw_tx)
     tx = Tx.parse(stream)
     tx.testnet = True
     hash_type = SIGHASH_ALL
     want = int(
         '27e0c5994dec7824e56dec6b2fcb342eb7cdb0d0957c2fce9882f715e85d81a6',
         16)
     self.assertEqual(tx.sig_hash(0, hash_type), want)
Ejemplo n.º 17
0
 def parse(cls, s, testnet=False):
     """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 = []
     b.tx_lookup = {}
     for _ in range(num_txs):
         t = Tx.parse(s, testnet=testnet)
         b.txs.append(t)
         b.tx_hashes.append(t.hash())
         b.tx_lookup[t.hash()] = t
     return b
Ejemplo n.º 18
0
 def test_exercise_7(self):
     hex_tx = '010000000456919960ac691763688d3d3bcea9ad6ecaf875df5339e148a1fc61c6ed7a069e010000006a47304402204585bcdef85e6b1c6af5c2669d4830ff86e42dd205c0e089bc2a821657e951c002201024a10366077f87d6bce1f7100ad8cfa8a064b39d4e8fe4ea13a7b71aa8180f012102f0da57e85eec2934a82a585ea337ce2f4998b50ae699dd79f5880e253dafafb7feffffffeb8f51f4038dc17e6313cf831d4f02281c2a468bde0fafd37f1bf882729e7fd3000000006a47304402207899531a52d59a6de200179928ca900254a36b8dff8bb75f5f5d71b1cdc26125022008b422690b8461cb52c3cc30330b23d574351872b7c361e9aae3649071c1a7160121035d5c93d9ac96881f19ba1f686f15f009ded7c62efe85a872e6a19b43c15a2937feffffff567bf40595119d1bb8a3037c356efd56170b64cbcc160fb028fa10704b45d775000000006a47304402204c7c7818424c7f7911da6cddc59655a70af1cb5eaf17c69dadbfc74ffa0b662f02207599e08bc8023693ad4e9527dc42c34210f7a7d1d1ddfc8492b654a11e7620a0012102158b46fbdff65d0172b7989aec8850aa0dae49abfb84c81ae6e5b251a58ace5cfeffffffd63a5e6c16e620f86f375925b21cabaf736c779f88fd04dcad51d26690f7f345010000006a47304402200633ea0d3314bea0d95b3cd8dadb2ef79ea8331ffe1e61f762c0f6daea0fabde022029f23b3e9c30f080446150b23852028751635dcee2be669c2a1686a4b5edf304012103ffd6f4a67e94aba353a00882e563ff2722eb4cff0ad6006e86ee20dfe7520d55feffffff0251430f00000000001976a914ab0c0b2e98b1ab6dbf67d4750b0a56244948a87988ac005a6202000000001976a9143c82d7df364eb6c75be8c80df2b3eda8db57397088ac46430600'
     stream = BytesIO(bytes.fromhex(hex_tx))
     t = Tx.parse(stream)
     input_sum = 0
     for tx_in in t.tx_ins:
         value = tx_in.value()
         input_sum += value
     output_sum = 0
     for tx_out in t.tx_outs:
         value = tx_out.amount
         output_sum += value
     fee = input_sum - output_sum
     self.assertEqual(fee, 140500)
Ejemplo n.º 19
0
	def parse(cls, stream):
		if stream.read(4) != MAGIC:
			raise PSBTError("Invalid PSBT: MAGIC")
		if stream.read(1) != HEAD_SEPARATOR:
			raise PSBTError("Invalid PSBT: Head Separator 0xff missing")

		new_map = {
			"global":{},
			"inputs":[],
			"outputs":[]
		}
		expect_global = True
		in_count = 0
		out_count = 0

		while expect_global or in_count or out_count:
			try:
				new_key, new_val = cls.parse_pair(stream)
			except IndexError:
				raise PSBTError("Parsing Error")
			if expect_global:
				# separator 0x00 reached. End of Globals
				if new_key is None:
					expect_global = False
					continue

				new_map["global"][new_key] = new_val
				if new_key == GLOBAL_UNSIGNED_TX:
					unsigned_tx = Tx.parse(BytesIO(new_val))
					in_count = len(unsigned_tx.tx_ins)
					out_count = len(unsigned_tx.tx_outs)
					# create correct number of empty inputs and outputs
					[new_map["inputs"].append({}) for _ in range(in_count)]
					[new_map["outputs"].append({}) for _ in range(out_count)]
			elif in_count:
				# separator means end of input
				if new_key is None:
					in_count -= 1
					continue
				current = abs(len(new_map["inputs"]) - in_count)
				new_map["inputs"][current][new_key] = new_val

				
			elif out_count:
				if new_key is None:
					out_count -= 1
					continue
				current = abs(len(new_map["outputs"]) - out_count)
				new_map["outputs"][current][new_key] = new_val
		return cls(maps=new_map)
Ejemplo n.º 20
0
 def test_exercise_3(self):
     hex_tx = '0100000001868278ed6ddfb6c1ed3ad5f8181eb0c7a385aa0836f01d5e4789e6bd304d87221a000000db00483045022100dc92655fe37036f47756db8102e0d7d5e28b3beb83a8fef4f5dc0559bddfb94e02205a36d4e4e6c7fcd16658c50783e00c341609977aed3ad00937bf4ee942a8993701483045022100da6bee3c93766232079a01639d07fa869598749729ae323eab8eef53577d611b02207bef15429dcadce2121ea07f233115c6f09034c0be68db99980b9a6c5e75402201475221022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb7152aeffffffff04d3b11400000000001976a914904a49878c0adfc3aa05de7afad2cc15f483a56a88ac7f400900000000001976a914418327e3f3dda4cf5b9089325a4b95abdfa0334088ac722c0c00000000001976a914ba35042cfe9fc66fd35ac2224eebdafd1028ad2788acdc4ace020000000017a91474d691da1574e6b3c192ecfb52cc8984ee7b6c568700000000'
     hex_sec = '03b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb71'
     hex_der = '3045022100da6bee3c93766232079a01639d07fa869598749729ae323eab8eef53577d611b02207bef15429dcadce2121ea07f233115c6f09034c0be68db99980b9a6c5e754022'
     hex_redeem_script = '475221022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb7152ae'
     sec = bytes.fromhex(hex_sec)
     der = bytes.fromhex(hex_der)
     redeem_script = Script.parse(BytesIO(bytes.fromhex(hex_redeem_script)))
     stream = BytesIO(bytes.fromhex(hex_tx))
     tx_obj = Tx.parse(stream)
     tx_obj.tx_ins[0].script_sig = redeem_script
     s = tx_obj.serialize() + int_to_little_endian(SIGHASH_ALL, 4)
     z = int.from_bytes(hash256(s), 'big')
     point = S256Point.parse(sec)
     sig = Signature.parse(der)
     self.assertTrue(point.verify(z, sig))
Ejemplo n.º 21
0
 def test_parse_inputs(self):
     raw_tx = unhexlify(
         '0100000001813f79011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d1000000006b483045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f02207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed01210349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278afeffffff02a135ef01000000001976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac99c39800000000001976a9141c4bc762dd5423e332166702cb75f40df79fea1288ac19430600'
     )
     stream = BytesIO(raw_tx)
     tx = Tx.parse(stream)
     self.assertEqual(len(tx.tx_ins), 1)
     want = unhexlify(
         'd1c789a9c60383bf715f3f6ad9d14b91fe55f3deb369fe5d9280cb1a01793f81')
     self.assertEqual(tx.tx_ins[0].prev_tx, want)
     self.assertEqual(tx.tx_ins[0].prev_index, 0)
     want = unhexlify(
         '483045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f02207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed01210349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278a'
     )
     self.assertEqual(tx.tx_ins[0].script_sig.serialize(), want)
     self.assertEqual(tx.tx_ins[0].sequence, 0xfffffffe)
Ejemplo n.º 22
0
	def __init__(self, serialized_psbt):
		self.tx_obj = Tx.parse(BytesIO(self.psbt.maps["global"][GLOBAL_UNSIGNED_TX]))
		for i in range(len(self.psbt.maps["inputs"])):
			curr_input = self.psbt.maps["inputs"][i]
			if self._is_witness_input(curr_input):
				try:
					# Add final scriptWit 
					self.tx_obj.tx_ins[i].witness_program = curr_input[IN_FINAL_SCRIPTWITNESS]
				except KeyError:
					raise PSBTError("PSBT input is missing finalized scriptWitness")
				if IN_FINAL_SCRIPTSIG in curr_input:
					self.tx_obj.tx_ins[i].script_sig = Script.parse(curr_input[IN_FINAL_SCRIPTSIG])
			else:
				try:
					self.tx_obj.tx_ins[i].script_sig = Script.parse(curr_input[IN_FINAL_SCRIPTSIG])
				except KeyError:
					raise PSBTError("PSBT input is missing finalized scriptSig")
Ejemplo n.º 23
0
 def test_exercise_10(self):
     block_hex = '0000000000044b01a9440b34f582fe171c7b8642fedd0ebfccf8fdf6a1810900'
     block_hash = bytes.fromhex(block_hex)
     node = SimpleNode('tbtc.programmingblockchain.com', testnet=True)
     node.handshake()
     getdata = GetDataMessage()
     getdata.add_data(BLOCK_DATA_TYPE, block_hash)
     node.send(getdata.command, getdata.serialize())
     block_envelope = node.wait_for_commands([b'block'])
     stream = block_envelope.stream()
     b = Block.parse(stream)
     self.assertTrue(b.check_pow())
     num_txs = read_varint(stream)
     tx_hashes = []
     for _ in range(num_txs):
         t = Tx.parse(stream)
         tx_hashes.append(t.hash())
     b.tx_hashes = tx_hashes
     self.assertTrue(b.validate_merkle_root())
Ejemplo n.º 24
0
 def test_example_5(self):
     last_block_hex = '00000000000538d5c2246336644f9a4956551afb44ba47278759ec55ea912e19'
     address = 'mwJn1YPMq7y5F8J3LkC5Hxg9PHyZ5K4cFv'
     h160 = decode_base58(address)
     node = SimpleNode('tbtc.programmingblockchain.com',
                       testnet=True,
                       logging=False)
     bf = BloomFilter(30, 5, 90210)
     bf.add(h160)
     node.handshake()
     node.send(b'filterload', bf.filterload())
     start_block = bytes.fromhex(last_block_hex)
     getheaders_message = GetHeadersMessage(start_block=start_block)
     node.send(b'getheaders', getheaders_message.serialize())
     headers_envelope = node.wait_for_commands({b'headers'})
     stream = headers_envelope.stream()
     headers = HeadersMessage.parse(stream)
     get_data_message = GetDataMessage()
     for b in headers.blocks:
         if not b.check_pow():
             raise RuntimeError('proof of work is invalid')
         get_data_message.add_data(FILTERED_BLOCK_DATA_TYPE, b.hash())
     node.send(b'getdata', get_data_message.serialize())
     found = False
     while not found:
         envelope = node.wait_for_commands({b'merkleblock', b'tx'})
         stream = envelope.stream()
         if envelope.command == b'merkleblock':
             mb = MerkleBlock.parse(stream)
             if not mb.is_valid():
                 raise RuntimeError('invalid merkle proof')
         else:
             prev_tx_obj = Tx.parse(stream, testnet=True)
             for i, tx_out in enumerate(prev_tx_obj.tx_outs):
                 if tx_out.script_pubkey.address(testnet=True) == address:
                     self.assertEqual(
                         prev_tx_obj.id(),
                         'e3930e1e566ca9b75d53b0eb9acb7607f547e1182d1d22bd4b661cfe18dcddf1'
                     )
                     self.assertEqual(i, 0)
                     found = True
                     break
Ejemplo n.º 25
0
 def parse(cls, s):
     '''Takes a byte stream and parses a block. Returns a BlockHeader object'''
     # s.read(n) will read n bytes from the stream
     # version - 4 bytes, little endian, interpret as int
     version = little_endian_to_int(s.read(4))
     # prev_block - 32 bytes, little endian (use [::-1] to reverse)
     prev_block = s.read(32)[::-1]
     # merkle_root - 32 bytes, little endian (use [::-1] to reverse)
     merkle_root = s.read(32)[::-1]
     # timestamp - 4 bytes, little endian, interpret as int
     timestamp = little_endian_to_int(s.read(4))
     # bits - 4 bytes
     bits = s.read(4)
     # nonce - 4 bytes
     nonce = s.read(4)
     # read the actual transactions
     num_txns = read_varint(s)
     txns = [Tx.parse(s) for _ in range(num_txns)]
     # initialize class
     return cls(version, prev_block, merkle_root, timestamp, bits, nonce,
                txns)
Ejemplo n.º 26
0
	def add_partial_sig(self, new_sig, pubkey, idx=None):
		if idx is None:
			idx = self._get_input_index(pubkey)
		# Note: Assumes that the sighash type is only the last byte of sig. 
		# Note: Assumes inputs in psbt and indexed the same as in unsigned tx
		this_sighash = little_to_int(new_sig[-1:])
		if idx is not None:
			if not self.check_sighash(idx=idx, sighash=this_sighash):
				raise PSBTError(f"Sighash type {this_sighash} on Signature does not match specified Sighash ({self.get_sighash_type(idx)}) for this input.")
			curr_input = self.psbt.maps["inputs"][idx]
			if IN_NON_WITNESS_UTXO in curr_input:
				global_txid = Tx.parse(BytesIO(self.psbt.maps["global"][GLOBAL_UNSIGNED_TX])).tx_ins[idx].prev_tx
				curr_txid = hash256(curr_input[IN_NON_WITNESS_UTXO])#[::-1]
				if global_txid != curr_txid:
					raise PSBTError("UTXO of this input does not match the UTXO specified in global unsigned Tx")
			elif IN_WITNESS_UTXO in curr_input:
				raise NotImplementedError("SegWit Not yet implemented.")

			self.psbt.maps["inputs"][idx][IN_PARTIAL_SIG+pubkey] = new_sig
		else:
			raise PSBTError("Signature cannot be added. The Pubkey provided is not avaialbe in this PSBT")
		return
Ejemplo n.º 27
0
1574e6b3c192ecfb52cc8984ee7b6c568700000000'

hex_sec = '03b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4b\
b71'

hex_der = '3045022100da6bee3c93766232079a01639d07fa869598749729ae323eab8ee\
f53577d611b02207bef15429dcadce2121ea07f233115c6f09034c0be68db99980b9a6c5e75402\
2'

hex_redeem_script = '475221022626e955ea6ea6d98850c994f9107b036b1334f18ca88\
30bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7f\
bdbd4bb7152ae'

sec = bytes.fromhex(hex_sec)
der = bytes.fromhex(hex_der)
redeem_script = Script.parse(BytesIO(bytes.fromhex(hex_redeem_script)))
stream = BytesIO(bytes.fromhex(hex_tx))
tx_obj = Tx.parse(stream)
s = int_to_little_endian(tx_obj.version, 4)
s += encode_varint(len(tx_obj.tx_ins))
i = tx_obj.tx_ins[0]
s += TxIn(i.prev_tx, i.prev_index, redeem_script, i.sequence).serialize()
s += encode_varint(len(tx_obj.tx_outs))
for tx_out in tx_obj.tx_outs:
    s += tx_out.serialize()
s += int_to_little_endian(tx_obj.locktime, 4)
s += int_to_little_endian(SIGHASH_ALL, 4)
z = int.from_bytes(hash256(s), 'big')
point = S256Point.parse(sec)
sig = Signature.parse(der)
print(point.verify(z, sig))
Ejemplo n.º 28
0
	def add_witness_utxo(self, idx, tx_hex, vout): #BROKEN
		tx_obj = Tx.parse(BytesIO(tx_hex))
		outpoint = tx_obj.tx_outs[vout].serialize()
		self.psbt.maps["inputs"][idx][IN_WITNESS_UTXO] = outpoint
Ejemplo n.º 29
0
	def get_tx_obj(self):
		return Tx.parse(BytesIO(self.maps["global"][GLOBAL_UNSIGNED_TX]))
Ejemplo n.º 30
0
from io import BytesIO
from ecc import S256Point, Signature
from helper import encode_varint, hash256, int_to_little_endian, little_endian_to_int, read_varint
from script import Script
from tx import Tx, SIGHASH_ALL, TxIn

hex_tx = '0100000001868278ed6ddfb6c1ed3ad5f8181eb0c7a385aa0836f01d5e4789e6bd304d87221a000000db00483045022100dc92655fe37036f47756db8102e0d7d5e28b3beb83a8fef4f5dc0559bddfb94e02205a36d4e4e6c7fcd16658c50783e00c341609977aed3ad00937bf4ee942a8993701483045022100da6bee3c93766232079a01639d07fa869598749729ae323eab8eef53577d611b02207bef15429dcadce2121ea07f233115c6f09034c0be68db99980b9a6c5e75402201475221022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb7152aeffffffff04d3b11400000000001976a914904a49878c0adfc3aa05de7afad2cc15f483a56a88ac7f400900000000001976a914418327e3f3dda4cf5b9089325a4b95abdfa0334088ac722c0c00000000001976a914ba35042cfe9fc66fd35ac2224eebdafd1028ad2788acdc4ace020000000017a91474d691da1574e6b3c192ecfb52cc8984ee7b6c568700000000'
hex_sec = '03b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb71'
hex_der = '3045022100da6bee3c93766232079a01639d07fa869598749729ae323eab8eef53577d611b02207bef15429dcadce2121ea07f233115c6f09034c0be68db99980b9a6c5e754022'
hex_redeem_script = '475221022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb7152ae'
sec = bytes.fromhex(hex_sec)
der = bytes.fromhex(hex_der)
redeem_script = Script.parse(BytesIO(bytes.fromhex(hex_redeem_script)))
stream = BytesIO(bytes.fromhex(hex_tx))

tx = Tx.parse(stream, False)
dat_s = int_to_little_endian(tx.version, 4)
dat_s += encode_varint(len(tx.tx_ins))
dat_s += TxIn(
    prev_tx = tx.tx_ins[0].prev_tx,
    prev_index = tx.tx_ins[0].prev_index,
    script_sig = redeem_script,
    sequence = tx.tx_ins[0].sequence,
    ).serialize()
dat_s += encode_varint(len(tx.tx_outs))
for tx_out in tx.tx_outs:
    dat_s += tx_out.serialize()
dat_s += int_to_little_endian(tx.locktime, 4)
dat_s += int_to_little_endian(SIGHASH_ALL, 4)
dat_h256 = hash256(dat_s)
dat_z = int.from_bytes(dat_h256, 'big')