def signHash(self, message_hash, private_key): ''' Sign the hash provided. .. WARNING:: *Never* sign a hash that you didn't generate, it can be an arbitrary transaction. For example, it might send all of your account's ether to an attacker. If you would like compatibility with :meth:`w3.eth.sign() <web3.eth.Eth.sign>` you can use :meth:`~eth_account.messages.defunct_hash_message`. Several other message standards are proposed, but none have a clear consensus. You'll need to manually comply with any of those message standards manually. :param message_hash: the 32-byte message hash to be signed :type message_hash: hex str, bytes or int :param private_key: the key to sign the message with :type private_key: hex str, bytes or int :returns: Various details about the signature - most importantly the fields: v, r, and s :rtype: ~eth_account.datastructures.AttributeDict .. code-block:: python >>> msg = "I♥SF" >>> from eth_account.messages import defunct_hash_message >>> msghash = defunct_hash_message(text=msg) HexBytes('0x1476abb745d423bf09273f1afd887d951181d25adc66c4834a70491911b7f750') >>> key = "0xb25c7db31feed9122727bf0939dc769a96564b2de4c4726d035b36ecf1e5b364" >>> Account.signHash(msghash, key) {'messageHash': HexBytes('0x1476abb745d423bf09273f1afd887d951181d25adc66c4834a70491911b7f750'), # noqa: E501 'r': 104389933075820307925104709181714897380569894203213074526835978196648170704563, 's': 28205917190874851400050446352651915501321657673772411533993420917949420456142, 'signature': HexBytes('0xe6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb33e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce1c'), # noqa: E501 'v': 28} # these are equivalent: >>> Account.signHash( 0x1476abb745d423bf09273f1afd887d951181d25adc66c4834a70491911b7f750, key ) >>> Account.signHash( "0x1476abb745d423bf09273f1afd887d951181d25adc66c4834a70491911b7f750", key ) ''' msg_hash_bytes = HexBytes(message_hash) if len(msg_hash_bytes) != 32: raise ValueError("The message hash must be exactly 32-bytes") key_bytes = HexBytes(private_key) key = self._keys.PrivateKey(key_bytes) (v, r, s, eth_signature_bytes) = sign_message_hash(key, msg_hash_bytes) return AttributeDict({ 'messageHash': msg_hash_bytes, 'r': r, 's': s, 'v': v, 'signature': HexBytes(eth_signature_bytes), })
def get_account(self, key_name): return AttributeDict({ 'address': ADDRESS, 'public_key': 'ab00000000000000000000000000000000000000', })
def sign_transaction(account, transaction_dict): if not isinstance(transaction_dict, Mapping): raise TypeError("transaction_dict must be dict-like, got %r" % transaction_dict) # allow from field, *only* if it matches the private key if 'from' in transaction_dict: if transaction_dict['from'] == account.address: sanitized_transaction = dissoc(transaction_dict, 'from') else: raise TypeError("from field must match key's %s, but it was %s" % ( account.address, transaction_dict['from'], )) else: sanitized_transaction = transaction_dict # sign transaction ( v, r, s, rlp_encoded, ) = sign_transaction_dict(account._key_obj, sanitized_transaction) transaction_hash = keccak(rlp_encoded) return AttributeDict({ 'rawTransaction': HexBytes(rlp_encoded), 'hash': HexBytes(transaction_hash), 'r': r, 's': s, 'v': v, })
def signTransaction(self, transaction_dict, private_key): ''' Sign a transaction using a local private key. Produces signature details and the hex-encoded transaction suitable for broadcast using :meth:`w3.eth.sendRawTransaction() <web3.eth.Eth.sendRawTransaction>`. Create the transaction dict for a contract method with `my_contract.functions.my_function().buildTransaction() <http://web3py.readthedocs.io/en/latest/contracts.html#methods>`_ :param dict transaction_dict: the transaction with keys: nonce, chainId, to, data, value, gas, and gasPrice. :param private_key: the private key to sign the data with :type private_key: hex str, bytes or int :returns: Various details about the signature - most importantly the fields: v, r, and s :rtype: AttributeDict .. code-block:: python >>> transaction = { 'to': '0xF0109fC8DF283027b6285cc889F5aA624EaC1F55', 'value': 1000000000, 'gas': 2000000, 'gasPrice': 234567897654321, 'nonce': 0, 'chainId': 1 } >>> key = '0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318' >>> signed = Account.signTransaction(transaction, key) {'hash': HexBytes('0x6893a6ee8df79b0f5d64a180cd1ef35d030f3e296a5361cf04d02ce720d32ec5'), 'r': 4487286261793418179817841024889747115779324305375823110249149479905075174044, 'rawTransaction': HexBytes('0xf86a8086d55698372431831e848094f0109fc8df283027b6285cc889f5aa624eac1f55843b9aca008025a009ebb6ca057a0535d6186462bc0b465b561c94a295bdb0621fc19208ab149a9ca0440ffd775ce91a833ab410777204d5341a6f9fa91216a6f3ee2c051fea6a0428'), # noqa: E501 's': 30785525769477805655994251009256770582792548537338581640010273753578382951464, 'v': 37} >>> w3.eth.sendRawTransaction(signed.rawTransaction) ''' if not isinstance(transaction_dict, Mapping): raise TypeError("transaction_dict must be dict-like, got %r" % transaction_dict) account = self.privateKeyToAccount(private_key) # sign transaction ( v, r, s, rlp_encoded, ) = sign_transaction_dict(account._key_obj, transaction_dict) transaction_hash = keccak(rlp_encoded) return AttributeDict({ 'rawTransaction': HexBytes(rlp_encoded), 'hash': HexBytes(transaction_hash), 'r': r, 's': s, 'v': v, })
def sign(self, transaction_dict, key_name): return AttributeDict({ 'rawTransaction': HexBytes('0x000000000000'), 'hash': HexBytes('0x000000000000'), 'r': 100000000000, 's': 100000000000, 'v': 37, })
def get_account(self, key_name): key = self.sgx_server.get_public_key(key_name) key = add_0x_prefix(key) address = public_key_to_address(key) return AttributeDict({ 'address': address, 'public_key': key, })
def generate_key(self): return AttributeDict({ 'name': 'NEK:aaabbb', 'address': ADDRESS, 'public_key': 'ab00000000000000000000000000000000000000', })
def sign(self, message=None, private_key=None, message_hexstr=None, message_text=None): ''' Sign the message provided. This is equivalent to :meth:`w3.eth.sign() <web3.eth.Eth.sign>` but with a local private key instead of an account in a connected client. Caller must supply exactly one of the message types: in bytes, a hex string, or a unicode string. The message will automatically be prepended with the text indicating that it is a message (preventing it from being used to sign a transaction). The prefix is: ``b'\\x19Ethereum Signed Message:\\n'`` concatenated with the number of bytes in the message. :param message: the message message to be signed :type message: bytes or int :param private_key: the key to sign the message with :type private_key: hex str, bytes or int :param str message_hexstr: the message encoded as hex :param str message_text: the message as a series of unicode characters (a normal Py3 str) :returns: Various details about the signature - most importantly the fields: v, r, and s :rtype: ~eth_account.datastructures.AttributeDict .. code-block:: python >>> msg = "I♥SF" >>> key = "0xb25c7db31feed9122727bf0939dc769a96564b2de4c4726d035b36ecf1e5b364" >>> Account.sign(message_text=msg, private_key=key) {'message': b'I\\xe2\\x99\\xa5SF', 'messageHash': HexBytes('0x1476abb745d423bf09273f1afd887d951181d25adc66c4834a70491911b7f750'), # noqa: E501 'r': 104389933075820307925104709181714897380569894203213074526835978196648170704563, 's': 28205917190874851400050446352651915501321657673772411533993420917949420456142, 'signature': HexBytes('0xe6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb33e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce1c'), # noqa: E501 'v': 28} # these are all equivalent: >>> Account.sign(w3.toBytes(text=msg), key) >>> Account.sign(bytes(msg, encoding='utf-8'), key) >>> Web3.toHex(text=msg) '0x49e299a55346' >>> Account.sign(message_hexstr='0x49e299a55346', private_key=key) >>> Account.sign(0x49e299a55346, key) ''' msg_bytes = to_bytes(message, hexstr=message_hexstr, text=message_text) msg_hash = self.hashMessage(msg_bytes) key_bytes = HexBytes(private_key) key = self._keys.PrivateKey(key_bytes) (v, r, s, eth_signature_bytes) = sign_message_hash(key, msg_hash) return AttributeDict({ 'message': HexBytes(msg_bytes), 'messageHash': msg_hash, 'r': r, 's': s, 'v': v, 'signature': HexBytes(eth_signature_bytes), })
def generate_key(self): key_name, public_key = self.sgx_server.generate_key() public_key = add_0x_prefix(public_key) address = public_key_to_address(public_key) return AttributeDict({ 'name': key_name, 'address': address, 'public_key': public_key, })
def complaint_response(self, poly_name, idx): share, dh_key, verification_vector_mult = self.sgx_server.complaint_response( poly_name, self.n, self.t, idx) return AttributeDict({ 'share': share, 'dh_key': dh_key, 'verification_vector_mult': verification_vector_mult })
def signed_tx(cls, sutx, v, r, s): enctx = encode_transaction(sutx, (v, r, s)) transaction_hash = keccak(enctx) attr_dict = AttributeDict({ 'rawTransaction': HexBytes(enctx), 'hash': HexBytes(transaction_hash), 'r': r, 's': s, 'v': v, }) return attr_dict
def test_validate_ethereum_transaction(self): seller = EthereumCrypto() client = EthereumCrypto() ledger_apis = LedgerApis( {ETHEREUM: DEFAULT_ETHEREUM_CONFIG, FETCHAI: DEFAULT_FETCHAI_CONFIG}, FETCHAI, ) tx_nonce = ledger_apis.generate_tx_nonce( ETHEREUM, seller.address, client.address ) tx_digest = "0xbefa7768c313ff49bf274eefed001042a0ff9e3cfbe75ff1a9c2baf18001cec4" result = AttributeDict( { "blockHash": HexBytes( "0x0bfc237d2a17f719a3300a4822779391ec6e3a74832fe1b05b8c477902b0b59e" ), "blockNumber": 7161932, "from": client.address, "gas": 200000, "gasPrice": 50000000000, "hash": HexBytes( "0xbefa7768c313ff49bf274eefed001042a0ff9e3cfbe75ff1a9c2baf18001cec4" ), "input": tx_nonce, "nonce": 4, "r": HexBytes( "0xb54ce8b9fa1d1be7be316c068af59a125d511e8dd51202b1a7e3002dee432b52" ), "s": HexBytes( "0x4f44702b3812d3b4e4b76da0fd5b554b3ae76d1717db5b6b5faebd7b85ae0303" ), "to": seller.address, "transactionIndex": 0, "v": 42, "value": 2, } ) with mock.patch.object( ledger_apis.apis.get(ETHEREUM).api.eth, "getTransaction", return_value=result, ): assert ledger_apis.is_tx_valid( identifier=ETHEREUM, tx_digest=tx_digest, seller=seller.address, client=client.address, tx_nonce=tx_nonce, amount=2, )
def sign_hash(self, message, key_name, chain_id): msg_hash_bytes = HexBytes(message) if len(msg_hash_bytes) != 32: raise ValueError("The message hash must be exactly 32-bytes") (v, r, s) = self._sign_hash(key_name, msg_hash_bytes, chain_id) signature_bytes = signing.to_bytes32(r) + signing.to_bytes32( s) + signing.to_bytes(v) return AttributeDict({ 'messageHash': msg_hash_bytes, 'r': r, 's': s, 'v': v, 'signature': HexBytes(signature_bytes), })
def _sign_hash(self, message_hash, private_key): msg_hash_bytes = HexBytes(message_hash) if len(msg_hash_bytes) != 32: raise ValueError("The message hash must be exactly 32-bytes") key = self._parsePrivateKey(private_key) (v, r, s, eth_signature_bytes) = sign_message_hash(key, msg_hash_bytes) return AttributeDict({ 'messageHash': msg_hash_bytes, 'r': r, 's': s, 'v': v, 'signature': HexBytes(eth_signature_bytes), })
def parse_sign_result(cls, tx, exchange_result): sign_v = exchange_result[0] sign_r = int((exchange_result[1:1 + 32]).hex(), 16) sign_s = int((exchange_result[1 + 32:1 + 32 + 32]).hex(), 16) enctx = encode_transaction(tx, (sign_v, sign_r, sign_s)) transaction_hash = keccak(enctx) signed_txn = AttributeDict({ 'rawTransaction': HexBytes(enctx), 'hash': HexBytes(transaction_hash), 'v': sign_v, 'r': sign_r, 's': sign_s, }) return signed_txn
def default_address(self, address: str) -> None: """Sets the address used with all Tron API. Will not sign any transactions. Args: address (str) Tron Address """ if not self.isAddress(address): raise InvalidTronError('Invalid address provided') _hex = self.address.to_hex(address) _base58 = self.address.from_hex(address) _private_base58 = self.address.from_private_key( self._private_key).base58 # check the addresses if self._private_key and _private_base58 != _base58: self._private_key = None self._default_address = AttributeDict({'hex': _hex, 'base58': _base58})
def address(self): public_key = self._key.public_key address = '41' + public_key.to_address()[2:] to_base58 = base58.b58encode_check(bytes.fromhex(address)) return AttributeDict({'hex': address, 'base58': to_base58.decode()})
class Tron: # Providers HTTPProvider = HttpProvider _default_block = None _private_key = None _default_address = AttributeDict({}) # Encoding and Decoding toBytes = staticmethod(to_bytes) toInt = staticmethod(to_int) toHex = staticmethod(to_hex) toText = staticmethod(to_text) toJSON = staticmethod(to_json) # Currency Utility toSun = staticmethod(to_sun) fromSun = staticmethod(from_sun) # Validate address isAddress = staticmethod(is_address) def __init__(self, **kwargs): """Connect to the Tron network. Args: kwargs (Any): We fill the most necessary parameters for working with blockchain Tron """ # We check the obtained nodes, if the necessary parameters # are not specified, then we take the default kwargs.setdefault('full_node', constants.DEFAULT_NODES['full_node']) kwargs.setdefault('solidity_node', constants.DEFAULT_NODES['solidity_node']) kwargs.setdefault('event_server', constants.DEFAULT_NODES['event_server']) # The node manager allows you to automatically determine the node # on the router or manually refer to a specific node. # solidity_node, full_node or event_server self.manager = TronManager( self, dict(full_node=kwargs.get('full_node'), solidity_node=kwargs.get('solidity_node'), event_server=kwargs.get('event_server'))) # If the parameter of the private key is not empty, # then write to the variable if 'private_key' in kwargs: self.private_key = kwargs.get('private_key') # We check whether the default wallet address is set when # defining the class, and then written to the variable if 'default_address' in kwargs: self.default_address = kwargs.get('default_address') # If custom methods are not declared, # we take the default from the list modules = kwargs.setdefault('modules', DEFAULT_MODULES) for module_name, module_class in modules.items(): module_class.attach(self, module_name) self.transaction_builder = TransactionBuilder(self) @property def default_block(self): return self._default_block @default_block.setter def default_block(self, block_id): """Sets the default block used as a reference for all future calls.""" if block_id in ('latest', 'earliest', 0): self._default_block = block_id return if not is_integer(block_id) or not block_id: raise ValueError('Invalid block ID provided') self._default_block = abs(block_id) @property def providers(self): """List providers""" return self.manager.providers @property def private_key(self): """Get a private key""" return self._private_key @private_key.setter def private_key(self, value: str) -> None: """Set a private key used with the TronAPI instance, used for obtaining the address, signing transactions etc... Args: value (str): Private key """ try: private_key = PrivateKey(value) except ValueError: raise TronError('Invalid private key provided') self._private_key = str(private_key).lower() @property def default_address(self) -> AttributeDict: """Get a TRON Address""" return self._default_address @default_address.setter def default_address(self, address: str) -> None: """Sets the address used with all Tron API. Will not sign any transactions. Args: address (str) Tron Address """ if not self.isAddress(address): raise InvalidTronError('Invalid address provided') _hex = self.address.to_hex(address) _base58 = self.address.from_hex(address) _private_base58 = self.address.from_private_key( self._private_key).base58 # check the addresses if self._private_key and _private_base58 != _base58: self._private_key = None self._default_address = AttributeDict({'hex': _hex, 'base58': _base58}) def get_event_result(self, **kwargs): """Will return all events matching the filters. Args: kwargs (any): List parameters """ # Check the most necessary parameters since_timestamp = kwargs.setdefault('since_timestamp', 0) event_name = kwargs.setdefault('event_name', 'Notify') block_number = kwargs.setdefault('block_number', '') size = kwargs.setdefault('size', 20) page = kwargs.setdefault('page', 1) only_confirmed = kwargs.setdefault('only_confirmed', None) only_unconfirmed = kwargs.setdefault('only_unconfirmed', None) previous_last = kwargs.setdefault('previous_last_event_fingerprint', None) contract_address = kwargs.setdefault('contract_address', self.default_address.hex) if not self.isAddress(contract_address): raise InvalidTronError('Invalid contract address provided') if event_name and not contract_address: raise TronError( 'Usage of event name filtering requires a contract address') if block_number and event_name is None: raise TronError( 'Usage of block number filtering requires an event name') if not is_integer(page): raise ValueError('Invalid size provided') if not is_integer(since_timestamp): raise ValueError('Invalid sinceTimestamp provided') # If the size exceeds 200, displays an error if size > 200: raise ValueError('Defaulting to maximum accepted size: 200') # We collect all parameters in one array route_params = [] if contract_address: route_params.append(contract_address) if event_name: route_params.append(event_name) if block_number: route_params.append(block_number) route = '/'.join(route_params) qs = {'since': since_timestamp, 'page': page, 'size': size} if only_confirmed is not None: qs.update({'onlyConfirmed': only_confirmed}) if only_unconfirmed is not None and not only_confirmed: qs.update({'onlyUnconfirmed': only_unconfirmed}) if previous_last is not None: qs.update({'previousLastEventFingerprint': previous_last}) return self.manager.request("/event/contract/{0}?{1}".format( route, urlencode(qs)), method='get') def get_event_transaction_id(self, tx_id): """Will return all events within a transactionID. Args: tx_id (str): TransactionID to query for events. """ response = self.manager.request('/event/transaction/' + tx_id, method='get') return response @property def address(self) -> Address: """Helper object that allows you to convert between hex/base58 and private key representations of a TRON address. Note: If you wish to convert generic data to hexadecimal strings, please use the function tron.to_hex. """ return Address() @property def create_account(self) -> PrivateKey: """Create account Warning: Please control risks when using this API. To ensure environmental security, please do not invoke APIs provided by other or invoke this very API on a public network. """ return Account.create() @staticmethod def is_valid_provider(provider) -> bool: """Check connected provider Args: provider(HttpProvider): Provider """ return isinstance(provider, HttpProvider) def solidity_sha3(self, abi_types, values): """ Executes keccak256 exactly as Solidity does. Takes list of abi_types as inputs -- `[uint24, int8[], bool]` and list of corresponding values -- `[20, [-1, 5, 0], True]` Args: abi_types (any): types abi values (any): values Examples: >>> tron = Tron() >>> sol = tron.solidity_sha3(['uint8[]'], [[1, 2, 3, 4, 5]]) >>> assert sol.hex() == '0x5917e5a395fb9b454434de59651d36822a9e29c5ec57474df3e67937b969460c' """ if len(abi_types) != len(values): raise ValueError( "Length mismatch between provided abi types and values. Got " "{0} types and {1} values.".format(len(abi_types), len(values))) normalized_values = map_abi_data([abi_resolver()], abi_types, values) hex_string = add_0x_prefix(''.join( remove_0x_prefix(hex_encode_abi_type(abi_type, value)) for abi_type, value in zip(abi_types, normalized_values))) return self.keccak(hexstr=hex_string) @staticmethod @apply_to_return_value(HexBytes) def keccak(primitive=None, text=None, hexstr=None): if isinstance(primitive, (bytes, int, type(None))): input_bytes = to_bytes(primitive, hexstr=hexstr, text=text) return tron_keccak(input_bytes) raise TypeError( "You called keccak with first arg %r and keywords %r. You must call it with one of " "these approaches: keccak(text='txt'), keccak(hexstr='0x747874'), " "keccak(b'\\x74\\x78\\x74'), or keccak(0x747874)." % (primitive, { 'text': text, 'hexstr': hexstr })) def is_connected(self): """List of available providers""" return self.manager.is_connected()
def complaint_response(self, poly_name, idx): share, dh_key = self.sgx_server.complaint_response(poly_name, self.n, self.t, idx) return AttributeDict({'share': share, 'dh_key': dh_key})
def signBlock(self, header_dict: dict, private_key: str, send_transaction_dicts: List[dict] = [], receive_transaction_dicts: List[dict] = []) -> AttributeDict: ''' transaction = { # Note that the address must be in checksum format: 'to': '0xF0109fC8DF283027b6285cc889F5aA624EaC1F55', 'value': 1000000000, 'gas': 2000000, 'gasPrice': 234567897654321, 'nonce': 0, 'chainId': 1 } receive_transaction = { 'senderBlockHash', 'sendTransactionHash', 'isRefund', 'remainingRefund' } header = { 'parentHash', 'blockNumber', 'extraData', } :param send_transaction_dicts: :param receive_transaction_dicts: :param reward_bundle: :param private_key: :return: ''' timestamp = int(time.time()) if not is_bytes(header_dict['parentHash']): header_dict['parentHash'] = to_bytes( hexstr=header_dict['parentHash']) if "extraData" in header_dict: if not is_bytes(header_dict['extraData']): extra_data = to_bytes(hexstr=header_dict['extraData']) else: extra_data = header_dict['extraData'] else: extra_data = b'' if "chainId" in header_dict: chain_id = header_dict['chainId'] else: if len(send_transaction_dicts) > 0: if 'chainId' in send_transaction_dicts[0]: chain_id = send_transaction_dicts[0]['chainId'] else: chain_id = 1 else: chain_id = 1 photon_timestamp = get_photon_timestamp(chain_id) if timestamp < photon_timestamp: fork_id = 0 else: fork_id = 1 account = self.privateKeyToAccount(private_key) send_transactions = [] for transaction_dict in send_transaction_dicts: if 'data' in transaction_dict: if not is_bytes(transaction_dict['data']): data = to_bytes(hexstr=transaction_dict['data']) else: data = transaction_dict['data'] else: data = b'' if not is_bytes(transaction_dict['to']): to = to_bytes(hexstr=transaction_dict['to']) else: to = transaction_dict['to'] if fork_id == 0: tx = BosonTransaction(nonce=transaction_dict['nonce'], gas_price=transaction_dict['gasPrice'], gas=transaction_dict['gas'], to=to, value=transaction_dict['value'], data=data, v=0, r=0, s=0) signed_tx = tx.get_signed(account._key_obj, chain_id) elif fork_id == 1: if 'codeAddress' in transaction_dict: if not is_bytes(transaction_dict['codeAddress']): code_address = to_bytes( hexstr=transaction_dict['codeAddress']) else: code_address = transaction_dict['codeAddress'] else: code_address = b'' if 'executeOnSend' in transaction_dict: execute_on_send = bool(transaction_dict['executeOnSend']) else: execute_on_send = False tx = PhotonTransaction(nonce=transaction_dict['nonce'], gas_price=transaction_dict['gasPrice'], gas=transaction_dict['gas'], to=to, value=transaction_dict['value'], data=data, code_address=code_address, execute_on_send=execute_on_send, v=0, r=0, s=0) signed_tx = tx.get_signed(account._key_obj, chain_id) else: raise Exception("Unknown fork id") send_transactions.append(signed_tx) receive_transactions = [] for receive_transaction_dict in receive_transaction_dicts: if not is_bytes(receive_transaction_dict['senderBlockHash']): receive_transaction_dict['senderBlockHash'] = to_bytes( hexstr=receive_transaction_dict['senderBlockHash']) if not is_bytes(receive_transaction_dict['sendTransactionHash']): receive_transaction_dict['sendTransactionHash'] = to_bytes( hexstr=receive_transaction_dict['sendTransactionHash']) if not is_boolean(receive_transaction_dict['isRefund']): receive_transaction_dict['isRefund'] = False if to_int( hexstr=receive_transaction_dict['isRefund']) == 0 else True # We renamed the fourth parameter in the new photon fork fourth_parameter = 0 if 'remainingRefund' in receive_transaction_dict: if not is_integer(receive_transaction_dict['remainingRefund']): fourth_parameter = to_int( hexstr=receive_transaction_dict['remainingRefund']) else: fourth_parameter = receive_transaction_dict[ 'remainingRefund'] elif 'refundAmount' in receive_transaction_dict: if not is_integer(receive_transaction_dict['refundAmount']): fourth_parameter = to_int( hexstr=receive_transaction_dict['refundAmount']) else: fourth_parameter = receive_transaction_dict['refundAmount'] if fork_id == 0: receive_transaction_class = BosonReceiveTransaction elif fork_id == 1: receive_transaction_class = PhotonReceiveTransaction else: raise Exception("Unknown fork id") tx = receive_transaction_class( receive_transaction_dict['senderBlockHash'], receive_transaction_dict['sendTransactionHash'], receive_transaction_dict['isRefund'], fourth_parameter) receive_transactions.append(tx) send_tx_root_hash, _ = make_trie_root_and_nodes(send_transactions) receive_tx_root_hash, _ = make_trie_root_and_nodes( receive_transactions) chain_address = account.address reward_bundle = StakeRewardBundle() header = BlockHeader(chain_address=decode_hex(chain_address), parent_hash=header_dict['parentHash'], transaction_root=send_tx_root_hash, receive_transaction_root=receive_tx_root_hash, block_number=header_dict['blockNumber'], timestamp=timestamp, extra_data=extra_data, reward_hash=reward_bundle.hash) signed_header = header.get_signed(account._key_obj, chain_id) signed_micro_header = signed_header.to_micro_header() if fork_id == 0: micro_block = BosonMicroBlock( header=signed_micro_header, transactions=send_transactions, receive_transactions=receive_transactions, reward_bundle=reward_bundle) rlp_encoded_micro_block = rlp.encode(micro_block, sedes=BosonMicroBlock) elif fork_id == 1: micro_block = PhotonMicroBlock( header=signed_micro_header, transactions=send_transactions, receive_transactions=receive_transactions, reward_bundle=reward_bundle) rlp_encoded_micro_block = rlp.encode(micro_block, sedes=PhotonMicroBlock) else: raise Exception("Unknown fork id") return AttributeDict({ 'rawBlock': encode_hex(rlp_encoded_micro_block), 'send_tx_hashes': [tx.hash for tx in send_transactions], 'receive_tx_hashes': [tx.hash for tx in receive_transactions], 'r': signed_header.r, 's': signed_header.s, 'v': signed_header.v, })