def build_spend_message(outpoint, pk, sequence, txouts) -> bytes: """ similar to: SIGHASH_ALL """ return sha256d( serialize(outpoint) + str(sequence) + binascii.hexlify(pk).decode() + serialize(txouts)).encode()
def encode_socket_data(data: object) -> bytes: """ Our protocol is: first 4 bytes signify msg length """ to_send = serialize(data).encode() return int_to_8bytes(len(to_send)) + to_send
def test_serialization(): outpoint1 = OutPoint(txid='coffee', txout_idx=0) outpoint2 = OutPoint(txid='coffee', txout_idx=0) txin1 = TxIn(outpoint=outpoint1, signature=SignatureScript(unlock_sig=b'sign', unlock_pk=b'bar'), sequence=1) txin2 = TxIn(outpoint=outpoint2, signature=SignatureScript(unlock_sig=b'sign', unlock_pk=b'bar'), sequence=2) txout = TxOut(value=101, pubkey='abcnddfjrwof123') txn1 = Transaction(txins=[txin1], txouts=[txout], locktime=0) txn2 = Transaction(txins=[txin2], txouts=[txout], locktime=0) block = Block(1, 'deadbeef', 'coffee', int(time.time()), 100, 100, [txn1, txn2]) utxo = UnspentTxOut(*txout, txid=txn1.id, txout_idx=0, is_coinbase=False, height=0) utxo_set = [utxo.outpoint, utxo] for obj in (outpoint1, outpoint2, txin1, txin2, txout, txn1, txn2, block, utxo, utxo_set): assert deserialize(serialize(obj)) == obj
def assemble_and_solve_block(pay_coinbase_to_addr, txns=None): """ Construct a Block by pulling transactions from the mempool, the mine it """ with chain_lock: prev_block_hash = get_active_chain()[-1].id if get_active_chain( ) else None block = Block(version=0, prev_block_hash=prev_block_hash, merkle_tree_hash='', timestamp=int(time.time()), bits=get_next_work_required(prev_block_hash), nonce=0, txns=txns or []) if not block.txns: block = select_from_mempool(block) fees = calculate_fees(block) coinbase_txn = Transaction.create_coinbase(pay_coinbase_to_addr, (get_block_subsidy() + fees), len(get_active_chain())) block = block._replace(txns=[coinbase_txn, *block.txns]) block = block._replace( merkle_tree_hash=get_merkle_root_of_txns(block.txns).value) if len(serialize(block)) > Params.MAX_BLOCK_SERIALIZED_SIZE: raise ValueError('txns specified create a block too large') return mine(block)
def validate_basics(self, as_coinbase=False): if not self.txouts or (not self.txins and not as_coinbase): raise TxnValidationError('Missing txouts or txins') txn_len = len(serialize(self)) if txn_len > Params.MAX_BLOCK_SERIALIZED_SIZE: raise TxnValidationError('Too Large: {txn_len}') spend_sum = sum(t.value for t in self.txouts) if spend_sum > Params.MAX_MONEY: raise TxnValidationError('Spend value too high: {spend_sum}')
def check_block_size(b) -> bool: return len(serialize(block)) < Params.MAX_BLOCK_SERIALIZED_SIZE
def id(self) -> str: return sha256d(serialize(self))