def _build_witnesses(self, tx_aux_hash: str): witnesses = [] for index, node in enumerate(self.nodes): message = (b"\x01" + cbor.encode(self.protocol_magic) + b"\x58\x20" + tx_aux_hash) signature = ed25519.sign_ext(node.private_key(), node.private_key_ext(), message) extended_public_key = (remove_ed25519_prefix(node.public_key()) + node.chain_code()) witnesses.append([ self.types[index], cbor.Tagged(24, cbor.encode([extended_public_key, signature])), ]) return witnesses
def _get_address_root(node, payload): extpubkey = remove_ed25519_prefix(node.public_key()) + node.chain_code() if payload: payload = {1: cbor.encode(payload)} else: payload = {} return _address_hash([0, [0, extpubkey], payload])
def _build_witnesses(self, tx_aux_hash: str): witnesses = [] for input in self.inputs: _, node = derive_address_and_node(self.keychain, input.address_n) message = (b"\x01" + cbor.encode(self.protocol_magic) + b"\x58\x20" + tx_aux_hash) signature = ed25519.sign_ext(node.private_key(), node.private_key_ext(), message) extended_public_key = (remove_ed25519_prefix(node.public_key()) + node.chain_code()) witnesses.append([ (input.type or 0), cbor.Tagged(24, cbor.encode([extended_public_key, signature])), ]) return witnesses
def derive_address_and_node(keychain, path: list): node = keychain.derive(path) address_payload = None address_attributes = {} address_root = _get_address_root(node, address_payload) address_type = 0 address_data = [address_root, address_attributes, address_type] address_data_encoded = cbor.encode(address_data) address = base58.encode( cbor.encode( [cbor.Tagged(24, address_data_encoded), crc.crc32(address_data_encoded)] ) ) return (address, node)
def derive_address_and_node(keychain, path: list): node = keychain.derive(path) address_payload = None address_attributes = {} address_root = _get_address_root(node, address_payload) address_type = 0 address_data = [address_root, address_attributes, address_type] address_data_encoded = cbor.encode(address_data) return (_encode_address_raw(address_data_encoded), node)
def serialise_tx(self): self._process_inputs() self._process_outputs() inputs_cbor = [] for i, output_index in enumerate(self.output_indexes): inputs_cbor.append( [ self.types[i], cbor.Tagged(24, cbor.encode([self.input_hashes[i], output_index])), ] ) inputs_cbor = cbor.IndefiniteLengthArray(inputs_cbor) outputs_cbor = [] for index, address in enumerate(self.output_addresses): outputs_cbor.append( [cbor.Raw(base58.decode(address)), self.outgoing_coins[index]] ) for index, address in enumerate(self.change_addresses): outputs_cbor.append( [cbor.Raw(base58.decode(address)), self.change_coins[index]] ) outputs_cbor = cbor.IndefiniteLengthArray(outputs_cbor) tx_aux_cbor = [inputs_cbor, outputs_cbor, self.attributes] tx_hash = hashlib.blake2b(data=cbor.encode(tx_aux_cbor), outlen=32).digest() witnesses = self._build_witnesses(tx_hash) tx_body = cbor.encode([tx_aux_cbor, witnesses]) self.fee = self.compute_fee( self.input_coins, self.outgoing_coins, self.change_coins ) return tx_body, tx_hash
def test_cbor_encoding(self): test_vectors = [ # integers (0, '00'), (1, '01'), (10, '0a'), (23, '17'), (24, '1818'), (25, '1819'), (100, '1864'), (1000, '1903e8'), (1000000, '1a000f4240'), (1000000000000, '1b000000e8d4a51000'), # binary strings (b'', '40'), (unhexlify('01020304'), '4401020304'), # tags (Tagged(1, 1363896240), 'c11a514b67b0'), (Tagged(23, unhexlify('01020304')), 'd74401020304'), # arrays ([], '80'), ([1, 2, 3], '83010203'), ([1, [2, 3], [4, 5]], '8301820203820405'), (list(range(1, 26)), '98190102030405060708090a0b0c0d0e0f101112131415161718181819'), # maps ({}, 'a0'), # Note: normal python dict doesn't have a fixed item ordering ({ 1: 2, 3: 4 }, 'a203040102'), # indefinite (IndefiniteLengthArray([]), '9fff'), (IndefiniteLengthArray([1, [2, 3], [4, 5]]), '9f01820203820405ff'), (IndefiniteLengthArray([1, [2, 3], IndefiniteLengthArray([4, 5])]), '9f018202039f0405ffff'), ] for val, expected in test_vectors: encoded = encode(val) self.assertEqual(unhexlify(expected), encoded)
def _build_witnesses(self, tx_aux_hash: str): witnesses = [] for index, node in enumerate(self.nodes): message = self.CARDANO_WITNESS_MAGIC_PREFIX + tx_aux_hash signature = ed25519.sign_ext( node.private_key(), node.private_key_ext(), message ) extended_public_key = ( seed.remove_ed25519_prefix(node.public_key()) + node.chain_code() ) witnesses.append( [ self.types[index], cbor.Tagged(24, cbor.encode([extended_public_key, signature])), ] ) return witnesses
def _address_hash(data) -> bytes: data = cbor.encode(data) data = hashlib.sha3_256(data).digest() res = hashlib.blake2b(data=data, outlen=28).digest() return res
def _encode_address_raw(address_data_encoded): return base58.encode( cbor.encode([ cbor.Tagged(24, address_data_encoded), crc.crc32(address_data_encoded) ]))