def get_sender_address(cls, tx): """ Get sender address from tx. Recover public key from tx and then get address from public key, if tx has single signature type, or get decoded sender address, if tx has multi signature type. Args: tx (dict): transaction dict Returns: Minter address (string) """ # Remember signature data and remove it from tx signature_data = tx.pop('signature_data') # If there is sender address in signature data (multi signature tx), return it if signature_data.get('from_mx'): return signature_data['from_mx'] # Otherwise (single signature tx), recover public key and get address from public key # Unhexlify (convert to bin (ascii)) all non-numeric dict values tx = MinterHelper.hex2bin_recursive(tx) # Encode tx data to RLP tx['data'] = rlp.encode(list(tx['data'].values())) # Message tx_rlp = rlp.encode(list(tx.values())) _keccak = MinterHelper.keccak_hash(tx_rlp) # Recover public key public_key = MinterPrefix.PUBLIC_KEY + ECDSA.recover(_keccak, tuple(signature_data.values())) return MinterWallet.get_address_from_public_key(public_key)
def from_raw(cls, rawcheck): """ Create check instance from raw check Args: rawcheck (str) Returns: MinterCheck """ # Remove check prefix and RLP decode it rawcheck = MinterPrefix.remove_prefix( string=rawcheck, prefix=MinterPrefix.CHECK ) rawcheck = binascii.unhexlify(rawcheck) decoded = rlp.decode(rawcheck) # Create MinterCheck instance kwargs = { 'nonce': int(decoded[0].decode()), 'chain_id': MinterHelper.bin2int(decoded[1]), 'due_block': MinterHelper.bin2int(decoded[2]), 'coin': MinterConvertor.decode_coin_name(decoded[3]), 'value': MinterConvertor.convert_value( value=MinterHelper.bin2int(decoded[4]), to='bip' ), 'lock': binascii.hexlify(decoded[5]).decode(), 'signature': { 'v': MinterHelper.bin2int(decoded[6]), 'r': MinterHelper.bin2hex(decoded[7]), 's': MinterHelper.bin2hex(decoded[8]) } } check = MinterCheck(**kwargs) # Recover owner address msg_hash = cls.__hash(data=[ int(binascii.hexlify(str(check.nonce).encode()), 16), check.chain_id, check.due_block, MinterConvertor.encode_coin_name(check.coin), MinterConvertor.convert_value(value=check.value, to='pip'), MinterHelper.hex2bin(check.lock) ]) public_key = ECDSA.recover(msg_hash, list(check.signature.values())) public_key = MinterPrefix.PUBLIC_KEY + public_key check.owner = MinterWallet.get_address_from_public_key(public_key) return check
def from_raw(cls, rawcheck): """ Create check instance from raw check Args: rawcheck (str) Returns: MinterCheck """ # Remove check prefix and RLP decode it rawcheck = MinterHelper.prefix_remove(rawcheck) rawcheck = bytes.fromhex(rawcheck) decoded = rlp.decode(rawcheck) # Create MinterCheck instance kwargs = { 'nonce': int(decoded[0].decode()), 'chain_id': int.from_bytes(decoded[1], 'big'), 'due_block': int.from_bytes(decoded[2], 'big'), 'coin': MinterHelper.decode_coin_name(decoded[3]), 'value': MinterHelper.to_bip(int.from_bytes(decoded[4], 'big')), 'gas_coin': MinterHelper.decode_coin_name(decoded[5]), 'lock': decoded[6].hex(), 'signature': { 'v': int.from_bytes(decoded[7], 'big'), 'r': decoded[8].hex(), 's': decoded[9].hex() } } check = MinterCheck(**kwargs) # Recover owner address msg_hash = cls.__hash(data=[ int(str(check.nonce).encode().hex(), 16), check.chain_id, check.due_block, MinterHelper.encode_coin_name(check.coin), MinterHelper.to_pip(check.value), MinterHelper.encode_coin_name(check.gas_coin), bytes.fromhex(check.lock) ]) public_key = ECDSA.recover(msg_hash, tuple(check.signature.values())) public_key = MinterHelper.prefix_add(public_key, PREFIX_PUBKEY) check.owner = MinterWallet.get_address_from_public_key(public_key) return check
def from_raw(cls, raw_tx): """ Generate tx object from raw tx Args: raw_tx (string) Returns: MinterTx child instance """ tx = rlp.decode(binascii.unhexlify(raw_tx)) # Populate structure dict with decoded tx data struct = copy.copy(cls._STRUCTURE_DICT) struct.update({ 'nonce': int(binascii.hexlify(tx[0]), 16), 'chain_id': int(binascii.hexlify(tx[1]), 16), 'gas_price': int(binascii.hexlify(tx[2]), 16), 'gas_coin': tx[3].decode(), 'type': int(binascii.hexlify(tx[4]), 16), 'payload': tx[6].decode().replace(chr(0), ''), 'service_data': tx[7].decode().replace(chr(0), ''), 'signature_type': int(binascii.hexlify(tx[8]), 16) }) # Get signature data signature_data = rlp.decode(tx[9]) struct.update({ 'signature_data': { 'v': int(binascii.hexlify(signature_data[0]), 16), 'r': binascii.hexlify(signature_data[1]).decode(), 's': binascii.hexlify(signature_data[2]).decode() } }) # Find out which of tx instance need to create depending on it's type data = rlp.decode(tx[5]) if struct['type'] == MinterDelegateTx.TYPE: _class = MinterDelegateTx elif struct['type'] == MinterSendCoinTx.TYPE: _class = MinterSendCoinTx elif struct['type'] == MinterBuyCoinTx.TYPE: _class = MinterBuyCoinTx elif struct['type'] == MinterCreateCoinTx.TYPE: _class = MinterCreateCoinTx elif struct['type'] == MinterDeclareCandidacyTx.TYPE: _class = MinterDeclareCandidacyTx elif struct['type'] == MinterRedeemCheckTx.TYPE: _class = MinterRedeemCheckTx elif struct['type'] == MinterSellAllCoinTx.TYPE: _class = MinterSellAllCoinTx elif struct['type'] == MinterSellCoinTx.TYPE: _class = MinterSellCoinTx elif struct['type'] == MinterSetCandidateOffTx.TYPE: _class = MinterSetCandidateOffTx elif struct['type'] == MinterSetCandidateOnTx.TYPE: _class = MinterSetCandidateOnTx elif struct['type'] == MinterUnbondTx.TYPE: _class = MinterUnbondTx elif struct['type'] == MinterEditCandidateTx.TYPE: _class = MinterEditCandidateTx elif struct['type'] == MinterMultiSendCoinTx.TYPE: _class = MinterMultiSendCoinTx else: raise Exception('Undefined tx type.') # Set tx data to minter dict struct.update({'data': _class._data_from_raw(data)}) # Recover public key. # We should not change curent struct, so pass copy # of the struct to recover method. public_key = cls.recover_public_key(copy.copy(struct)) struct.update({ 'from_mx': MinterWallet.get_address_from_public_key(public_key), 'signed_tx': raw_tx }) # Prepare **kwargs for creating _class instance. # Pass copy of the struct. kwargs = _class._structure_to_kwargs(copy.copy(struct)) return _class(**kwargs)