def _create_apkh2pkh_transaction(cold_storage_key, signing_key, certificate, unspent, output): """Create a ArculaPublicKeyHash2PublicKeyHash transaction.""" certificate, (public_signing_key, identifier) = certificate script_code = arcula_locking_script(cold_storage_key, identifier) tx_in, hashed, output_block = _tx_in_boilerplate(unspent, output, script_code, construct_output_block) signature = signing_key.sign(hashed) + b'\x41' unlocking_script = (int_to_varint(len(signature)) + signature + int_to_varint(len(certificate)) + certificate + int_to_varint(len(public_signing_key)) + public_signing_key) return _tx_out_boilerplate(tx_in, unlocking_script, output_block)
def create_p2pkh_transaction(private_key, unspents, outputs, custom_pushdata=False): public_key = private_key.public_key public_key_len = len(public_key).to_bytes(1, byteorder="little") scriptCode = private_key.scriptcode scriptCode_len = int_to_varint(len(scriptCode)) version = VERSION_1 lock_time = LOCK_TIME # sequence = SEQUENCE hash_type = HASH_TYPE input_count = int_to_unknown_bytes(len(unspents), byteorder="little") output_count = int_to_unknown_bytes(len(outputs), byteorder="little") output_block = construct_output_block(outputs, custom_pushdata=custom_pushdata) # Optimize for speed, not memory, by pre-computing values. inputs = [] for unspent in unspents: script = hex_to_bytes(unspent.script) script_len = int_to_unknown_bytes(len(script), byteorder="little") txid = hex_to_bytes(unspent.txid)[::-1] txindex = unspent.txindex.to_bytes(4, byteorder="little") amount = unspent.amount.to_bytes(8, byteorder="little") inputs.append(TxIn(script, script_len, txid, txindex, amount)) hashPrevouts = double_sha256(b"".join([i.txid + i.txindex for i in inputs])) hashSequence = double_sha256(b"".join([SEQUENCE for i in inputs])) hashOutputs = double_sha256(output_block) # scriptCode_len is part of the script. for i, txin in enumerate(inputs): to_be_hashed = (version + hashPrevouts + hashSequence + txin.txid + txin.txindex + scriptCode_len + scriptCode + txin.amount + SEQUENCE + hashOutputs + lock_time + hash_type) hashed = sha256(to_be_hashed) # BIP-143: Used for Bitcoin Cash # signature = private_key.sign(hashed) + b'\x01' signature = private_key.sign(hashed) + b"\x41" script_sig = (len(signature).to_bytes(1, byteorder="little") + signature + public_key_len + public_key) inputs[i].script = script_sig inputs[i].script_len = int_to_unknown_bytes(len(script_sig), byteorder="little") return bytes_to_hex(version + input_count + construct_input_block(inputs) + output_count + output_block + lock_time)
def get_headers_payload(block_locator_hash, hash_stop="0000000000000000000000000000000000000000000000000000000000000000"): """makes a getheaders serialized payload""" version = struct.pack("i", 70015) hash_count = ut.int_to_varint(1) block_locator_hash = ut.hex_to_bytes(ut.flip_hex_byte_order(block_locator_hash)) hash_stop = ut.hex_to_bytes(hash_stop) payload = version + hash_count + block_locator_hash + hash_stop return payload
def _tx_in_boilerplate(unspent, output, script_code, construct_output_block_f): script = hex_to_bytes(unspent.script) script_len = int_to_unknown_bytes(len(script), byteorder='little') tx_id = hex_to_bytes(unspent.txid)[::-1] tx_index = unspent.txindex.to_bytes(4, byteorder='little') amount = unspent.amount.to_bytes(8, byteorder='little') tx_in = TxIn(script, script_len, tx_id, tx_index, amount) hash_previous_outputs = double_sha256(tx_id + tx_index) hash_sequence = double_sha256(SEQUENCE) output_block = construct_output_block_f([output]) hash_outputs = double_sha256(output_block) to_be_hashed = (VERSION_1 + hash_previous_outputs + hash_sequence + tx_in.txid + tx_in.txindex + int_to_varint(len(script_code)) + script_code + tx_in.amount + SEQUENCE + hash_outputs + LOCK_TIME + HASH_TYPE) hashed = sha256(to_be_hashed) # BIP-143: Used for Bitcoin Cash return tx_in, hashed, output_block
def get_op_return_size(message, custom_pushdata=False): # calculate op_return size for each individual message if custom_pushdata is False: op_return_size = ( 8 # int64_t amount 0x00000000 + len(OP_RETURN) # 1 byte + len(get_op_pushdata_code( message)) # 1 byte if <75 bytes, 2 bytes if OP_PUSHDATA1... + len(message) # Max 220 bytes at present ) if custom_pushdata is True: op_return_size = ( 8 # int64_t amount 0x00000000 + len(OP_RETURN) # 1 byte + len( message ) # Unsure if Max size will be >220 bytes due to extra OP_PUSHDATA codes... ) # "Var_Int" that preceeds OP_RETURN - 0xdf is max value with current 220 byte limit (so only adds 1 byte) op_return_size += len(int_to_varint(op_return_size)) return op_return_size
def test_val_more_than_4294967295(self): assert int_to_varint( 10000000000) == b"\xff\x00\xe4\x0bT\x02\x00\x00\x00"
def test_val_less_than_4294967295(self): assert int_to_varint(4294967294) == b"\xfe\xfe\xff\xff\xff"
def test_val_less_than_65535(self): assert int_to_varint(65535) == b"\xfd\xff\xff"