def serialize_coinbase_transaction(pubkey_hash, coinbase_data, reward): """ Generates a serialized coinbase transaction to be included as a transaction in a mined block. :param pubkey_hash: HASH160 of the public key that can claim this coinbase transaction :param coinbase_data: data to include in the coinbase input (contains the extranounce) :param reward: reward (in satoshis) awarded to the miner of the block that will contain this coinbase transaction """ pubkey_script = pay_pubkey_hash_script(pubkey_hash) VERSION = 1 SEQUENCE = 0xFFFFFFFF serialized = bytearray() serialized.extend(pack("<I", VERSION)) serialized.extend(encode_var_int(1)) # only 1 "input" serialized.extend(bytes([0] * 32)) # hash with 0s (not a transaction ref) serialized.extend(bytes([0xFF] * 4)) # out index with 1s serialized.extend(encode_var_int(len(coinbase_data))) serialized.extend(coinbase_data) serialized.extend(pack("<I", SEQUENCE)) serialized.extend(encode_var_int(1)) # only 1 output serialized.extend(pack("<Q", reward)) serialized.extend(encode_var_int(len(pubkey_script))) serialized.extend(pubkey_script) serialized.extend(pack("<I", 0)) # lock time return bytes(serialized)
def serialize(self): """ Serialize the block into a chunk of data that can be submited to the bitcoin client. """ serialized = bytearray() serialized.extend(self.serialize_header()) serialized.extend(encode_var_int(len(self.merkle_tree.transactions))) for tx in self.merkle_tree.transactions: serialized.extend(tx.data) return bytes(serialized)
def test_encode_var_int_0x1000000000(self): expected = bytes([0xFF, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00]) self.assertEqual(expected, encode_var_int(0x1000000000))
def test_encode_var_int_0xFFFFFFFF(self): expected = bytes([0xFE, 0xFF, 0xFF, 0xFF, 0xFF]) self.assertEqual(expected, encode_var_int(0xFFFFFFFF))
def test_encode_var_int_0xFFFF(self): self.assertEqual(bytes([0xFD, 0xFF, 0xFF]), encode_var_int(0xFFFF))
def test_encode_var_int_0xFD(self): self.assertEqual(bytes([0xFD, 0xFD, 0x00]), encode_var_int(0xFD))
def test_encode_var_int_0xFC(self): self.assertEqual(bytes([0xFC]), encode_var_int(0xFC))
def test_encode_var_int_0(self): self.assertEqual(bytes([0]), encode_var_int(0))
def test_encode_var_int_0x1000000000(self): expected = bytes( [0xFF, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00]) self.assertEqual(expected, encode_var_int(0x1000000000))