def test_storage_restriction(valid_shard_chain, funded_address): # noqa: F811 shard_chain = valid_shard_chain vm = shard_chain.get_vm() address = funded_address other_address = b'\xaa' * 20 access_list = to_prefix_list_form([[address, b'\x00', b'\xff' * 32]]) tests = ( (True, 'get_storage', [address, big_endian_to_int(b'\x00' * 32)]), (True, 'get_storage', [address, big_endian_to_int(b'\x00' * 31 + b'\xff')]), (True, 'get_storage', [address, big_endian_to_int(b'\xff' * 32)]), (False, 'get_storage', [address, big_endian_to_int(b'\xaa' * 32)]), (False, 'get_storage', [other_address, big_endian_to_int(b'\x00' * 32)]), (True, 'set_storage', [address, big_endian_to_int(b'\x00' * 32), 0]), (True, 'set_storage', [address, big_endian_to_int(b'\x00' * 31 + b'\xff'), 0]), (True, 'set_storage', [address, big_endian_to_int(b'\xff' * 32), 0]), (False, 'set_storage', [address, big_endian_to_int(b'\xaa' * 32), 0]), (False, 'set_storage', [other_address, big_endian_to_int(b'\x00' * 32), 0]), ) for valid, method, args in tests: if valid: with vm.state.state_db(access_list=access_list) as state_db: getattr(state_db, method)(*args) else: with pytest.raises(UnannouncedStateAccess): with vm.state.state_db(access_list=access_list) as state_db: getattr(state_db, method)(*args) # without access list everything is invalid with pytest.raises(UnannouncedStateAccess): with vm.state.state_db(access_list=[]) as state_db: getattr(state_db, method)(*args)
def precompile_ecrecover(computation): computation.gas_meter.consume_gas(constants.GAS_ECRECOVER, reason="ECRecover Precompile") raw_message_hash = computation.msg.data[:32] message_hash = pad32r(raw_message_hash) v_bytes = pad32r(computation.msg.data[32:64]) v = big_endian_to_int(v_bytes) r_bytes = pad32r(computation.msg.data[64:96]) r = big_endian_to_int(r_bytes) s_bytes = pad32r(computation.msg.data[96:128]) s = big_endian_to_int(s_bytes) try: validate_lt_secpk1n(r) validate_lt_secpk1n(s) validate_lte(v, 28) validate_gte(v, 27) except ValidationError: return computation try: raw_public_key = ecdsa_raw_recover(message_hash, (v, r, s)) except ValueError: return computation public_key = encode_raw_public_key(raw_public_key) address = public_key_to_address(public_key) padded_address = pad32(address) computation.output = padded_address return computation
def ecrecover(computation): computation.gas_meter.consume_gas(constants.GAS_ECRECOVER, reason="ECRecover Precompile") raw_message_hash = computation.msg.data[:32] message_hash = pad32r(raw_message_hash) v_bytes = pad32r(computation.msg.data[32:64]) v = big_endian_to_int(v_bytes) r_bytes = pad32r(computation.msg.data[64:96]) r = big_endian_to_int(r_bytes) s_bytes = pad32r(computation.msg.data[96:128]) s = big_endian_to_int(s_bytes) try: validate_lt_secpk1n(r, title="ECRecover: R") validate_lt_secpk1n(s, title="ECRecover: S") validate_lte(v, 28, title="ECRecover: V") validate_gte(v, 27, title="ECRecover: V") except ValidationError: return computation canonical_v = v - 27 try: signature = keys.Signature(vrs=(canonical_v, r, s)) public_key = signature.recover_public_key_from_msg_hash(message_hash) except BadSignature: return computation address = public_key.to_canonical_address() padded_address = pad32(address) computation.output = padded_address return computation
def _modexp(data): base_length, exponent_length, modulus_length = _extract_lengths(data) if base_length == 0: return 0 elif modulus_length == 0: return 0 # compute start:end indexes base_end_idx = 96 + base_length exponent_end_idx = base_end_idx + exponent_length modulus_end_dx = exponent_end_idx + modulus_length # extract arguments modulus_bytes = zpad_right( data[exponent_end_idx:modulus_end_dx], to_size=modulus_length, ) modulus = big_endian_to_int(modulus_bytes) if modulus == 0: return 0 base_bytes = zpad_right(data[96:base_end_idx], to_size=base_length) base = big_endian_to_int(base_bytes) exponent_bytes = zpad_right( data[base_end_idx:exponent_end_idx], to_size=exponent_length, ) exponent = big_endian_to_int(exponent_bytes) print('base', base, 'exponent', exponent, 'modulus', modulus) result = pow(base, exponent, modulus) return result
def _modexp(data): base_length, exponent_length, modulus_length = _extract_lengths(data) if base_length == 0: return 0 elif modulus_length == 0: return 0 # compute start:end indexes base_end_idx = 96 + base_length exponent_end_idx = base_end_idx + exponent_length modulus_end_dx = exponent_end_idx + modulus_length # extract arguments modulus_bytes = zpad_right( data[exponent_end_idx:modulus_end_dx], to_size=modulus_length, ) modulus = big_endian_to_int(modulus_bytes) if modulus == 0: return 0 base_bytes = zpad_right(data[96:base_end_idx], to_size=base_length) base = big_endian_to_int(base_bytes) exponent_bytes = zpad_right( data[base_end_idx:exponent_end_idx], to_size=exponent_length, ) exponent = big_endian_to_int(exponent_bytes) print('base', base, 'exponent', exponent, 'modulus', modulus) result = pow(base, exponent, modulus) return result
def ecdsa_raw_sign(self, msg_hash, private_key): signature = self.keys.PrivateKey(private_key).sign_recoverable( msg_hash, hasher=None) v = safe_ord(signature[64]) + 27 r = big_endian_to_int(signature[0:32]) s = big_endian_to_int(signature[32:64]) return v, r, s
def _compute_adjusted_exponent_length(exponent_length, first_32_exponent_bytes): exponent = big_endian_to_int(first_32_exponent_bytes) if exponent_length <= 32 and exponent == 0: return 0 elif exponent_length <= 32: return get_highest_bit_index(exponent) else: first_32_bytes_as_int = big_endian_to_int(first_32_exponent_bytes) return (8 * (exponent_length - 32) + get_highest_bit_index(first_32_bytes_as_int))
def parse_collation_added_log(log): # here assume `shard_id` is the first indexed , which is the second element in topics shard_id_bytes32 = log['topics'][1] data_hex = log['data'] data_bytes = decode_hex(data_hex) score = big_endian_to_int(data_bytes[-32:]) is_new_head = bool(big_endian_to_int(data_bytes[-64:-32])) header_bytes = shard_id_bytes32 + data_bytes[:-64] collation_header = CollationHeader.from_bytes(header_bytes) yield 'header', collation_header yield 'is_new_head', is_new_head yield 'score', score
def _extract_lengths(data): # extract argument lengths base_length_bytes = pad32r(data[:32]) base_length = big_endian_to_int(base_length_bytes) exponent_length_bytes = pad32r(data[32:64]) exponent_length = big_endian_to_int(exponent_length_bytes) modulus_length_bytes = pad32r(data[64:96]) modulus_length = big_endian_to_int(modulus_length_bytes) return base_length, exponent_length, modulus_length
def check_pow(block_number, mining_hash, mix_hash, nonce, difficulty): validate_length(mix_hash, 32) validate_length(mining_hash, 32) validate_length(nonce, 8) cache = get_cache(block_number) mining_output = hashimoto_light(block_number, cache, mining_hash, big_endian_to_int(nonce)) if mining_output[b'mix digest'] != mix_hash: raise ValidationError("mix hash mistmatch; {0} != {1}".format( encode_hex(mining_output[b'mix digest']), encode_hex(mix_hash))) result = big_endian_to_int(mining_output[b'result']) validate_lte(result, 2**256 // difficulty)
def _extract_lengths(data): # extract argument lengths base_length_bytes = pad32r(data[:32]) base_length = big_endian_to_int(base_length_bytes) exponent_length_bytes = pad32r(data[32:64]) exponent_length = big_endian_to_int(exponent_length_bytes) modulus_length_bytes = pad32r(data[64:96]) modulus_length = big_endian_to_int(modulus_length_bytes) return base_length, exponent_length, modulus_length
def check_pow(block_number, mining_hash, mix_hash, nonce, difficulty): validate_length(mix_hash, 32, title="Mix Hash") validate_length(mining_hash, 32, title="Mining Hash") validate_length(nonce, 8, title="POW Nonce") cache = get_cache(block_number) mining_output = hashimoto_light( block_number, cache, mining_hash, big_endian_to_int(nonce)) if mining_output[b'mix digest'] != mix_hash: raise ValidationError("mix hash mismatch; {0} != {1}".format( encode_hex(mining_output[b'mix digest']), encode_hex(mix_hash))) result = big_endian_to_int(mining_output[b'result']) validate_lte(result, 2**256 // difficulty, title="POW Difficulty")
def _ecmull(data): x_bytes = pad32r(data[:32]) y_bytes = pad32r(data[32:64]) m_bytes = pad32r(data[64:96]) x = big_endian_to_int(x_bytes) y = big_endian_to_int(y_bytes) m = big_endian_to_int(m_bytes) p = validate_point(x, y) result = bn128.normalize(bn128.multiply(p, m)) return result
def check_pow(block_number: int, mining_hash: Hash32, mix_hash: Hash32, nonce: bytes, difficulty: int) -> None: validate_length(mix_hash, 32, title="Mix Hash") validate_length(mining_hash, 32, title="Mining Hash") validate_length(nonce, 8, title="POW Nonce") cache = get_cache(block_number) mining_output = hashimoto_light(block_number, cache, mining_hash, big_endian_to_int(nonce)) if mining_output[b'mix digest'] != mix_hash: raise ValidationError("mix hash mismatch; {0} != {1}".format( encode_hex(mining_output[b'mix digest']), encode_hex(mix_hash))) result = big_endian_to_int(mining_output[b'result']) validate_lte(result, 2**256 // difficulty, title="POW Difficulty")
def _ecmull(data): x_bytes = pad32r(data[:32]) y_bytes = pad32r(data[32:64]) m_bytes = pad32r(data[64:96]) x = big_endian_to_int(x_bytes) y = big_endian_to_int(y_bytes) m = big_endian_to_int(m_bytes) p = validate_point(x, y) result = bn128.normalize(bn128.multiply(p, m)) return result
def populated_shard_chaindb_and_root_hash(shard_chaindb): if shard_chaindb.trie_class is HexaryTrie: root_hash = BLANK_ROOT_HASH else: root_hash = EMPTY_SHA3 state_db = shard_chaindb.get_state_db(root_hash, read_only=False) state_db.set_balance(A_ADDRESS, 1) state_db.set_code(B_ADDRESS, b"code") state_db.set_storage(B_ADDRESS, big_endian_to_int(b"key1"), 100) state_db.set_storage(B_ADDRESS, big_endian_to_int(b"key2"), 200) state_db.set_storage(B_ADDRESS, big_endian_to_int(b"key"), 300) return shard_chaindb, state_db.root_hash
def _compute_adjusted_exponent_length(exponent_length, first_32_exponent_bytes): exponent = big_endian_to_int(first_32_exponent_bytes) if exponent_length <= 32 and exponent == 0: return 0 elif exponent_length <= 32: return get_highest_bit_index(exponent) else: first_32_bytes_as_int = big_endian_to_int(first_32_exponent_bytes) return ( 8 * (exponent_length - 32) + get_highest_bit_index(first_32_bytes_as_int) )
def normalize_block_header(header): normalized_header = { 'bloom': big_endian_to_int(decode_hex(header['bloom'])), 'coinbase': to_canonical_address(header['coinbase']), 'difficulty': to_int(header['difficulty']), 'extraData': decode_hex(header['extraData']), 'gasLimit': to_int(header['gasLimit']), 'gasUsed': to_int(header['gasUsed']), 'hash': decode_hex(header['hash']), 'mixHash': decode_hex(header['mixHash']), 'nonce': decode_hex(header['nonce']), 'number': to_int(header['number']), 'parentHash': decode_hex(header['parentHash']), 'receiptTrie': decode_hex(header['receiptTrie']), 'stateRoot': decode_hex(header['stateRoot']), 'timestamp': to_int(header['timestamp']), 'transactionsTrie': decode_hex(header['transactionsTrie']), 'uncleHash': decode_hex(header['uncleHash']), } if 'blocknumber' in header: normalized_header['blocknumber'] = to_int(header['blocknumber']) if 'chainname' in header: normalized_header['chainname'] = header['chainname'] if 'chainnetwork' in header: normalized_header['chainnetwork'] = header['chainnetwork'] return normalized_header
def _ecadd(data): x1_bytes = pad32r(data[:32]) y1_bytes = pad32r(data[32:64]) x2_bytes = pad32r(data[64:96]) y2_bytes = pad32r(data[96:128]) x1 = big_endian_to_int(x1_bytes) y1 = big_endian_to_int(y1_bytes) x2 = big_endian_to_int(x2_bytes) y2 = big_endian_to_int(y2_bytes) p1 = validate_point(x1, y1) p2 = validate_point(x2, y2) result = bn128.normalize(bn128.add(p1, p2)) return result
def get_balance(self, address): validate_canonical_address(address, title="Storage Address") key = get_balance_key(address) self._check_accessibility(key) if key in self._trie: return big_endian_to_int(self._trie[key]) else: return 0
def mine_pow_nonce(block_number: int, mining_hash: Hash32, difficulty: int) -> Tuple[bytes, bytes]: cache = get_cache(block_number) for nonce in range(MAX_TEST_MINE_ATTEMPTS): mining_output = hashimoto_light(block_number, cache, mining_hash, nonce) result = big_endian_to_int(mining_output[b'result']) result_cap = 2**256 // difficulty if result <= result_cap: return nonce.to_bytes(8, 'big'), mining_output[b'mix digest'] raise Exception("Too many attempts at POW mining, giving up")
def get_storage(self, address, slot): validate_canonical_address(address, title="Storage Address") validate_uint256(slot, title="Storage Slot") key = get_storage_key(address, slot) self._check_accessibility(key) if key in self._trie: return big_endian_to_int(self._trie[key]) else: return 0
def normalize_account_state(account_state): return { to_canonical_address(address): { 'balance': to_int(state['balance']), 'code': decode_hex(state['code']), 'nonce': to_int(state['nonce']), 'storage': { to_int(slot): big_endian_to_int(decode_hex(value)) for slot, value in state['storage'].items() }, } for address, state in account_state.items() }
def ecrecover(computation): computation.gas_meter.consume_gas(constants.GAS_ECRECOVER, reason="ECRecover Precompile") raw_message_hash = computation.msg.data[:32] message_hash = pad32r(raw_message_hash) v_bytes = pad32r(computation.msg.data[32:64]) v = big_endian_to_int(v_bytes) r_bytes = pad32r(computation.msg.data[64:96]) r = big_endian_to_int(r_bytes) s_bytes = pad32r(computation.msg.data[96:128]) s = big_endian_to_int(s_bytes) try: validate_lt_secpk1n(r, title="ECRecover: R") validate_lt_secpk1n(s, title="ECRecover: S") validate_lte(v, 28, title="ECRecover: V") validate_gte(v, 27, title="ECRecover: V") except ValidationError: return computation canonical_v = v - 27 try: signature = keys.Signature(vrs=(canonical_v, r, s)) public_key = signature.recover_public_key_from_msg_hash(message_hash) except BadSignature: return computation address = public_key.to_canonical_address() padded_address = pad32(address) computation.output = padded_address return computation
def test_get_witness_nodes(populated_shard_chaindb_and_root_hash): chaindb, root_hash = populated_shard_chaindb_and_root_hash header = CollationHeader( shard_id=1, expected_period_number=0, period_start_prevhash=ZERO_HASH32, parent_hash=ZERO_HASH32, number=0, state_root=root_hash ) prefixes = [ get_balance_key(A_ADDRESS), get_balance_key(B_ADDRESS), get_storage_key(A_ADDRESS, big_endian_to_int(b"key1")), get_storage_key(B_ADDRESS, big_endian_to_int(b"key1")), get_storage_key(B_ADDRESS, big_endian_to_int(b"key2")), get_storage_key(B_ADDRESS, big_endian_to_int(b"key")), get_storage_key(B_ADDRESS, big_endian_to_int(b"")), ] witness_nodes = chaindb.get_witness_nodes(header, prefixes) assert len(witness_nodes) == len(set(witness_nodes)) # no duplicates assert sorted(witness_nodes) == sorted(witness_nodes) # sorted
def print_var(value, var_typ): if isinstance(value, int): v = int_to_big_endian(value) else: v = value if isinstance(v, bytes): if var_typ == 'uint256': print(big_endian_to_int(v)) elif var_typ == 'int128': print('TODO!') elif var_typ == 'address': print(to_hex(v[12:])) else: print(v)
def _extract_point(data_slice): x1_bytes = data_slice[:32] y1_bytes = data_slice[32:64] x2_i_bytes = data_slice[64:96] x2_r_bytes = data_slice[96:128] y2_i_bytes = data_slice[128:160] y2_r_bytes = data_slice[160:192] x1 = big_endian_to_int(x1_bytes) y1 = big_endian_to_int(y1_bytes) x2_i = big_endian_to_int(x2_i_bytes) x2_r = big_endian_to_int(x2_r_bytes) y2_i = big_endian_to_int(y2_i_bytes) y2_r = big_endian_to_int(y2_r_bytes) return x1, y1, x2_i, x2_r, y2_i, y2_r
def _extract_point(data_slice): x1_bytes = data_slice[:32] y1_bytes = data_slice[32:64] x2_i_bytes = data_slice[64:96] x2_r_bytes = data_slice[96:128] y2_i_bytes = data_slice[128:160] y2_r_bytes = data_slice[160:192] x1 = big_endian_to_int(x1_bytes) y1 = big_endian_to_int(y1_bytes) x2_i = big_endian_to_int(x2_i_bytes) x2_r = big_endian_to_int(x2_r_bytes) y2_i = big_endian_to_int(y2_i_bytes) y2_r = big_endian_to_int(y2_r_bytes) return x1, y1, x2_i, x2_r, y2_i, y2_r
def _pop(self, num_items, type_hint): for _ in range(num_items): if type_hint == constants.UINT256: value = self.values.pop() if isinstance(value, int): yield value else: yield big_endian_to_int(value) elif type_hint == constants.BYTES: value = self.values.pop() if isinstance(value, bytes): yield value else: yield int_to_big_endian(value) elif type_hint == constants.ANY: yield self.values.pop() else: raise TypeError( "Unknown type_hint: {0}. Must be one of {1}".format( type_hint, ", ".join((constants.UINT256, constants.BYTES)), ))
def _pop(self, num_items, type_hint): for _ in range(num_items): if type_hint == constants.UINT256: value = self.values.pop() if isinstance(value, int): yield value else: yield big_endian_to_int(value) elif type_hint == constants.BYTES: value = self.values.pop() if isinstance(value, bytes): yield value else: yield int_to_big_endian(value) elif type_hint == constants.ANY: yield self.values.pop() else: raise TypeError( "Unknown type_hint: {0}. Must be one of {1}".format( type_hint, ", ".join((constants.UINT256, constants.BYTES)), ) )
def from_endpoint(cls, ip, udp_port, tcp_port='\x00\x00'): udp_port = big_endian_to_int(udp_port) tcp_port = big_endian_to_int(tcp_port) return cls(ip, udp_port, tcp_port)
from evm.utils.hexadecimal import ( decode_hex, ) from evm.utils.numeric import ( big_endian_to_int, ) # S <= N // 2 MAX_ALLOWED_S = SECPK1_N // 2 VALIDATION_CODE_GAS = 3500 GAS_RESERVE = 4500 # amount of gas reserved for returning GAS_RESERVE_OFFSET = 200 # standard id for a method with signature `get_nonce()` NONCE_GETTER_ID = 0x141b5b48 ENTRY_POINT_INT = big_endian_to_int(ENTRY_POINT) ECRECOVER_ADDRESS = 1 ECRECOVER_GAS = 3000 # calldata locations CALLDATA_FUNCTION_ID = 0 CALLDATA_SIGNATURE = 0 ( CALLDATA_V, CALLDATA_R, CALLDATA_S, CALLDATA_NONCE, CALLDATA_GASPRICE, CALLDATA_VALUE, CALLDATA_MIN_BLOCK,
def gen_request_id(): return big_endian_to_int(os.urandom(8))
def recv_find_node(self, node: kademlia.Node, payload: List[Any], _: bytes) -> None: # The find_node payload should have 2 elements: node_id, expiration self.logger.debug('<<< find_node from %s', node) node_id, _ = payload self.kademlia.recv_find_node(node, big_endian_to_int(node_id))
def recv_find_node(self, node, payload, message_hash): # The find_node payload should have 2 elements: node_id, expiration self.logger.debug('<<< find_node from {}'.format(node)) node_id, _ = payload self.kademlia.recv_find_node(node, big_endian_to_int(node_id))
def __init__(self, pubkey: datatypes.PublicKey, address: Address) -> None: self.pubkey = pubkey self.address = address self.id = big_endian_to_int(keccak(pubkey.to_bytes()))
def from_endpoint(cls, ip: str, udp_port: str, tcp_port: str = '\x00\x00'): return cls(ip, big_endian_to_int(udp_port), big_endian_to_int(tcp_port))
def gen_request_id() -> int: return big_endian_to_int(os.urandom(8))
def __init__(self, pubkey, address): self.pubkey = pubkey self.address = address self.id = big_endian_to_int(keccak(pubkey.to_bytes()))