def make_btc_block_merkle_tree(blk_txids): assert len(blk_txids) > 0 digests = blk_txids while len(digests) > 1: # The famously broken Satoshi algorithm: if the # of digests at this # level is odd, double the last one. if len(digests) % 2: digests.append(digests[-1].msg) next_level = [] for i in range(0, len(digests), 2): next_level.append(cat_sha256d(digests[i], digests[i + 1])) digests = next_level return digests[0]
def make_timestamp_from_block_tx(confirmed_tx, block, blockheight): commitment_tx = confirmed_tx.tx serialized_tx = commitment_tx.serialize(params={'include_witness': False}) digest = confirmed_tx.tip_timestamp.msg try: i = serialized_tx.index(digest) except ValueError: assert False, "can't build a block_timestamp from my tx, this is not supposed to happen, exiting" prefix = serialized_tx[0:i] suffix = serialized_tx[i + len(digest):] digest_timestamp = Timestamp(digest) # Add the commitment ops necessary to go from the digest to the txid op prefix_stamp = digest_timestamp.ops.add(OpPrepend(prefix)) txid_stamp = cat_sha256d(prefix_stamp, suffix) assert commitment_tx.GetTxid() == txid_stamp.msg # Create the txid list, with our commitment txid op in the appropriate # place block_txid_stamps = [] for tx in block.vtx: if tx.GetTxid() != txid_stamp.msg: block_txid_stamps.append(Timestamp(tx.GetTxid())) else: block_txid_stamps.append(txid_stamp) # Build the merkle tree merkleroot_stamp = make_btc_block_merkle_tree(block_txid_stamps) assert merkleroot_stamp.msg == block.hashMerkleRoot if bitcoin.params.NAME.lower() == "testnet": attestation = BitcoinTestnetBlockHeaderAttestation(blockheight) else: attestation = BitcoinBlockHeaderAttestation(blockheight) merkleroot_stamp.attestations.add(attestation) return digest_timestamp