def is_valid_signature(provider: BaseProvider, data: str, signature: str, signer_address: str) -> bool: """Check the validity of the supplied signature. Check if the supplied `signature`:code: corresponds to signing `data`:code: with the private key corresponding to `signer_address`:code:. :param provider: A Web3 provider able to access the 0x Exchange contract. :param data: The hex encoded data signed by the supplied signature. :param signature: The hex encoded signature. :param signer_address: The hex encoded address that signed the data to produce the supplied signature. :returns: Tuple consisting of a boolean and a string. Boolean is true if valid, false otherwise. If false, the string describes the reason. >>> is_valid_signature( ... Web3.HTTPProvider("http://127.0.0.1:8545"), ... '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0', ... '0x1B61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403', ... '0x5409ed021d9299bf6814279a6a1411a7e866a631', ... ) True """ # noqa: E501 (line too long) assert_is_provider(provider, "provider") assert_is_hex_string(data, "data") assert_is_hex_string(signature, "signature") assert_is_address(signer_address, "signer_address") return Exchange( provider, chain_to_addresses(ChainId(1 # hard-coded to always be mainnet )).exchange, ).is_valid_hash_signature.call( bytes.fromhex(remove_0x_prefix(HexStr(data))), to_checksum_address(signer_address), bytes.fromhex(remove_0x_prefix(HexStr(signature))), )
def parse_BIP122_uri(blockchain_uri: URI) -> Tuple[HexStr, str, HexStr]: match = re.match(BIP122_URL_REGEX, blockchain_uri) if match is None: raise ValueError(f"Invalid URI format: '{blockchain_uri}'") chain_id, resource_type, resource_hash = match.groups() return (add_0x_prefix(HexStr(chain_id)), resource_type, add_0x_prefix(HexStr(resource_hash)))
def ping_munger( module: Any, identifier: Union[ENRAPI, str, bytes, NodeID, HexStr]) -> List[str]: """ See: https://github.com/ethereum/web3.py/blob/002151020cecd826a694ded2fdc10cc70e73e636/web3/method.py#L77 # noqa: E501 Normalizes the any of the following inputs into the appropriate payload for the ``discv5_ping` JSON-RPC API endpoint. - An ENR object - The string representation of an ENR - A NodeID in the form of a bytestring - A NodeID in the form of a hex string - An ENode URI Throws a ``ValueError`` if the input cannot be matched to one of these formats. """ if isinstance(identifier, ENRAPI): return [repr(identifier)] elif isinstance(identifier, bytes): if len(identifier) == 32: return [encode_hex(identifier)] raise ValueError(f"Unrecognized node identifier: {identifier!r}") elif isinstance(identifier, str): if identifier.startswith("enode://") or identifier.startswith("enr:"): return [identifier] elif len(remove_0x_prefix(HexStr(identifier))) == 64: return [add_0x_prefix(HexStr(identifier))] else: raise ValueError(f"Unrecognized node identifier: {identifier}") else: raise ValueError(f"Unrecognized node identifier: {identifier}")
def to_hex( primitive: Primitives = None, hexstr: HexStr = None, text: str = None ) -> HexStr: """ Auto converts any supported value into its hex representation. Trims leading zeros, as defined in: https://github.com/ethereum/wiki/wiki/JSON-RPC#hex-value-encoding """ if hexstr is not None: return add_0x_prefix(HexStr(hexstr.lower())) if text is not None: return encode_hex(text.encode("utf-8")) if is_boolean(primitive): return HexStr("0x1") if primitive else HexStr("0x0") if isinstance(primitive, (bytes, bytearray)): return encode_hex(primitive) elif is_string(primitive): raise TypeError( "Unsupported type: The primitive argument must be one of: bytes," "bytearray, int or bool and not str" ) if is_integer(primitive): return HexStr(hex(primitive)) raise TypeError( "Unsupported type: '{0}'. Must be one of: bool, str, bytes, bytearray" "or int.".format(repr(type(primitive))) )
def _deserialize_channel_withdraw( raw_event: Dict[str, Any], identity_address_map: Dict[ChecksumAddress, ChecksumAddress], ) -> ChannelWithdraw: """Deserialize a channel withdraw event. Only for Tom pool. It may raise KeyError. TODO: use bidict or already pass the inverse identity_address_map. """ inverse_identity_address_map = { address: identity for identity, address in identity_address_map.items() } address = to_checksum_address(raw_event['user']) identity_address = inverse_identity_address_map[address] amount = FVal(raw_event['amount']) / ADX_AMOUNT_MANTISSA return ChannelWithdraw( tx_hash=HexStr(raw_event['id'].split(':')[0]), address=address, identity_address=identity_address, timestamp=Timestamp(raw_event['timestamp']), value=Balance(amount=amount), channel_id=HexStr(raw_event['channelId']), pool_id=TOM_POOL_ID, )
def normalize_node_id_identifier(identifier: NodeIDIdentifier) -> str: """ Normalizes any of the following inputs into the appropriate payload for representing a `NodeID` over a JSON-RPC API endpoint. - An ENR object - The string representation of an ENR - A NodeID in the form of a bytestring - A NodeID in the form of a hex string - An ENode URI Throws a ``ValueError`` if the input cannot be matched to one of these formats. """ if isinstance(identifier, ENRAPI): return repr(identifier) elif isinstance(identifier, bytes): if len(identifier) == 32: return encode_hex(identifier) raise ValueError(f"Unrecognized node identifier: {identifier!r}") elif isinstance(identifier, str): if identifier.startswith("enode://") or identifier.startswith("enr:"): return identifier elif len(remove_0x_prefix(HexStr(identifier))) == 64: return add_0x_prefix(HexStr(identifier)) else: raise ValueError(f"Unrecognized node identifier: {identifier}") else: raise ValueError(f"Unrecognized node identifier: {identifier}")
def from_order(cls, order: Order) -> "OrderORM": return cls( exchange_address=order.exchange_address, maker_address=order.maker_address, taker_address=order.taker_address, maker_token=order.maker_token, taker_token=order.taker_token, fee_recipient=order.fee_recipient, maker_token_amount=order.maker_token_amount, taker_token_amount=order.taker_token_amount, filled_maker_token_amount=order.filled_maker_token_amount, filled_taker_token_amount=order.filled_taker_token_amount, cancelled_maker_token_amount=order.cancelled_maker_token_amount, cancelled_taker_token_amount=order.cancelled_taker_token_amount, price=order.price, maker_fee=order.maker_fee, taker_fee=order.taker_fee, expiration_timestamp_in_sec=order.expiration_timestamp_in_sec, salt=order.salt, v=order.v, # remove 0x from r, s and msg_hash to keep backwards compatibility: r=remove_0x_prefix(HexStr(order.r.hex())), s=remove_0x_prefix(HexStr(order.s.hex())), msg_hash=remove_0x_prefix(HexStr(order.hash().hex())), )
def _get_user_identity(address: ChecksumAddress) -> ChecksumEthAddress: """Given an address (signer) returns its protocol user identity. """ return generate_address_via_create2( address=HexAddress(HexStr(IDENTITY_FACTORY_ADDR)), salt=HexStr(CREATE2_SALT), init_code=HexStr( IDENTITY_PROXY_INIT_CODE.format(signer_address=address)), )
def test_trace_replay_transaction( self, web3: "Web3", parity_fixture_data: Dict[str, str]) -> None: trace = web3.parity.traceReplayTransaction( HexStr(parity_fixture_data['mined_txn_hash'])) assert trace['stateDiff'] is None assert trace['vmTrace'] is None assert trace['trace'][0]['action']['from'] == add_0x_prefix( HexStr(parity_fixture_data['coinbase']), )
def test_eth_submitWork(self, web3: "Web3") -> None: nonce = 1 pow_hash = HexStr( '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' ) mix_digest = HexStr( '0xD1FE5700000000000000000000000000D1FE5700000000000000000000000000' ) result = web3.eth.submitWork(nonce, pow_hash, mix_digest) assert result is False
def test_traceTransaction_deprecated( self, web3: "Web3", parity_fixture_data: Dict[str, str]) -> None: with pytest.warns( DeprecationWarning, match= "traceTransaction is deprecated in favor of trace_transaction" ): trace = web3.parity.traceTransaction( HexStr(parity_fixture_data['mined_txn_hash'])) assert trace[0]['action']['from'] == add_0x_prefix( HexStr(parity_fixture_data['coinbase']))
def to_hex_twos_compliment(value: Any, bit_size: int) -> HexStr: """ Converts integer value to twos compliment hex representation with given bit_size """ if value >= 0: return to_hex_with_size(value, bit_size) value = (1 << bit_size) + value hex_value = hex(value) hex_value = HexStr(hex_value.rstrip("L")) return hex_value
def to_checksum_address(value: AnyStr) -> ChecksumAddress: """ Makes a checksum address given a supported format. """ norm_address = to_normalized_address(value) address_hash = encode_hex( keccak(text=remove_0x_prefix(HexStr(norm_address)))) checksum_address = add_0x_prefix( HexStr("".join((norm_address[i].upper( ) if int(address_hash[i], 16) > 7 else norm_address[i]) for i in range(2, 42)))) return ChecksumAddress(HexAddress(checksum_address))
def test_generate_address_via_create2( address, salt, init_code, expected_contract_address, ): """Test the CREATE2 opcode Python implementation. """ contract_address = generate_address_via_create2( address=HexAddress(address), salt=HexStr(salt), init_code=HexStr(init_code), ) assert contract_address == to_checksum_address(expected_contract_address)
def test_traceReplayTransaction_deprecated( self, web3: "Web3", parity_fixture_data: Dict[str, str], ) -> None: with pytest.warns( DeprecationWarning, match='traceReplayTransaction is deprecated in favor of ' 'trace_replay_transaction'): trace = web3.parity.traceReplayTransaction( HexStr(parity_fixture_data['mined_txn_hash'])) assert trace['stateDiff'] is None assert trace['vmTrace'] is None assert trace['trace'][0]['action']['from'] == add_0x_prefix( HexStr(parity_fixture_data['coinbase']), )
def build_etherscan_manifest(uri: URI, package_name: str, version: str) -> Iterable[Tuple[str, Any]]: address, chain_id = parse.urlparse(uri).netloc.split(":") network = get_etherscan_network(chain_id) body = make_etherscan_request(address, network) contract_type = body["ContractName"] w3 = setup_w3(to_int(text=chain_id)) block_uri = create_latest_block_uri(w3) runtime_bytecode = to_hex( w3.eth.getCode(ChecksumAddress(HexAddress(HexStr(address))))) yield "package_name", package_name yield "version", version yield "manifest_version", "2" yield "sources", {f"./{contract_type}.sol": body["SourceCode"]} yield "contract_types", { contract_type: { "abi": json.loads(body["ABI"]), "runtime_bytecode": { "bytecode": runtime_bytecode }, "compiler": generate_compiler_info(body), } } yield "deployments", { block_uri: { contract_type: { "contract_type": contract_type, "address": address } } }
def test_verify_existent_deployment_with_wrong_code( token_network_registry_contract: Contract, ) -> None: """ Test verify_deployed_contracts_in_filesystem() with an existent deployment data but with a fake web3 that does not return the correct code. """ web3_mock = Mock() web3_mock.version.network = 42 web3_mock.eth.getTransactionReceipt = lambda _: { "blockNumber": 10711807, "gasUsed": 555366, "contractAddress": "0x8Ff327f7ed03cD6Bd5e611E9e404B47d8c9Db81E", } verifier = ContractVerifier(web3=web3_mock, contracts_version="0.11.1") # The Mock returns a wrong block number, so the comparison fails. with pytest.raises(RuntimeError): verifier.verify_deployed_contracts_in_filesystem() with pytest.raises(RuntimeError): verifier.verify_deployed_service_contracts_in_filesystem( token_address=HexAddress( HexStr("0x3Aa761BcDB064179a1e37748D8A5F577a177Be5c")), user_deposit_whole_balance_limit=2**256 - 1, token_network_registry_address=token_network_registry_contract. address, )
def decode_hex(value: str) -> bytes: if not is_text(value): raise TypeError("Value must be an instance of str") non_prefixed = remove_0x_prefix(HexStr(value)) # unhexlify will only accept bytes type someday ascii_hex = non_prefixed.encode("ascii") return binascii.unhexlify(ascii_hex)
def get_escrow(escrow_addr: str) -> Contract: """Retrieve the Escrow contract from a given address. >>> credentials = { ... "gas_payer": "0x1413862C2B7054CDbfdc181B83962CB0FC11fD92", ... "gas_payer_priv": "28e516f1e2f99e96a48a23cea1f94ee5f073403a1c68e818263f0eb898f1c8e5" ... } >>> rep_oracle_pub_key = b"2dbc2c2c86052702e7c219339514b2e8bd4687ba1236c478ad41b43330b08488c12c8c1797aa181f3a4596a1bd8a0c18344ea44d6655f61fa73e56e743f79e0d" >>> job = Job(credentials=credentials, escrow_manifest=manifest) Deploying a new Job to the ethereum network succeeds. >>> job.launch(rep_oracle_pub_key) True >>> type(get_escrow(job.job_contract.address)) <class 'web3._utils.datatypes.Contract'> Args: escrow_addr (str): an ethereum address of the escrow contract. Returns: Contract: returns the Escrow solidity contract. """ w3 = get_w3() contract_interface = get_contract_interface( "{}/Escrow.sol:Escrow".format(CONTRACT_FOLDER)) escrow = w3.eth.contract( address=ChecksumAddress(HexAddress(HexStr(escrow_addr))), abi=contract_interface["abi"], ) return escrow
def get_factory(factory_addr: str) -> Contract: """Retrieve the EscrowFactory contract from a given address. >>> credentials = { ... "gas_payer": "0x1413862C2B7054CDbfdc181B83962CB0FC11fD92", ... "gas_payer_priv": "28e516f1e2f99e96a48a23cea1f94ee5f073403a1c68e818263f0eb898f1c8e5" ... } >>> job = Job(credentials=credentials, escrow_manifest=manifest) >>> type(get_factory(job.factory_contract.address)) <class 'web3._utils.datatypes.Contract'> Args: factory_addr (str): the ethereum address of the Escrow contract. Returns: Contract: returns the EscrowFactory solidity contract. """ w3 = get_w3() contract_interface = get_contract_interface( "{}/EscrowFactory.sol:EscrowFactory".format(CONTRACT_FOLDER)) escrow_factory = w3.eth.contract( address=ChecksumAddress(HexAddress(HexStr(factory_addr))), abi=contract_interface["abi"], ) return escrow_factory
def test_setup_name(ens, name, normalized_name, namehash_hex): address = ens.w3.eth.accounts[3] assert not ens.name(address) owner = ens.owner('tester.eth') ens.setup_name(name, address) assert ens.name(address) == normalized_name # check that the correct namehash is set: node = Web3.toBytes(hexstr=HexStr(namehash_hex)) assert ens.resolver(normalized_name).caller.addr(node) == address # check that the correct owner is set: assert ens.owner(name) == owner # setup name to point to new address new_address = ens.w3.eth.accounts[4] ens.setup_address(name, None) ens.setup_name(name, new_address) # validate that ens.name() only returns a name if the forward resolution also returns the # address assert ens.name(new_address) == normalized_name # reverse resolution assert ens.address(name) == new_address # forward resolution assert not ens.name(address) ens.setup_name(None, address) ens.setup_address(name, None) assert not ens.name(address) assert not ens.address(name)
def _deserialize_bond( self, raw_event: Dict[str, Any], identity_address_map: Dict[ChecksumAddress, ChecksumAddress], ) -> Bond: """Deserialize a bond event. It may raise KeyError. """ event_core_data = self._deserialize_event_core_data( raw_event=raw_event, identity_address_map=identity_address_map, ) amount_int = int(raw_event['amount']) amount = FVal(raw_event['amount']) / ADX_AMOUNT_MANTISSA pool_id = HexStr(raw_event['poolId']) nonce = int(raw_event['nonce']) bond_id = self._get_bond_id( identity_address=event_core_data.identity_address, amount=amount_int, pool_id=pool_id, nonce=nonce, ) return Bond( tx_hash=event_core_data.tx_hash, address=event_core_data.address, identity_address=event_core_data.identity_address, timestamp=event_core_data.timestamp, bond_id=bond_id, value=Balance(amount=amount), pool_id=pool_id, nonce=nonce, slashed_at=Timestamp(int(raw_event['slashedAtStart'])), )
def test_shh_remove_filter(self, web3: "Web3") -> None: receiver = web3.parity.shh.new_key_pair() receiver_pub = web3.parity.shh.get_public_key(receiver) payload = web3.toHex(text="test message :)") topic = HexStr('0x13370000') shh_filter = web3.parity.shh.new_message_filter({'decryptWith': None, 'topics': [topic]}) assert web3.parity.shh.post({ 'payload': payload, 'topics': [topic], 'to': {'public': receiver_pub}, 'priority': 500, 'ttl': 400, }) time.sleep(1) # Commented out until parity filter bug is resolved # https://github.com/paritytech/parity-ethereum/issues/10565 # message = ShhFilter(web3, shh_filter).get_new_entries() # assert message["payload"] == HexBytes(payload) assert web3.parity.shh.delete_message_filter(shh_filter) try: web3.parity.shh.get_filter_messages(shh_filter) assert False except BaseException: assert True
def test_eth_sign(self, web3: "Web3", unlocked_account_dual_type: ChecksumAddress) -> None: signature = web3.eth.sign(unlocked_account_dual_type, text='Message tö sign. Longer than hash!') assert is_bytes(signature) assert len(signature) == 32 + 32 + 1 # test other formats hexsign = web3.eth.sign( unlocked_account_dual_type, hexstr=HexStr( '0x4d6573736167652074c3b6207369676e2e204c6f6e676572207468616e206861736821' )) assert hexsign == signature intsign = web3.eth.sign( unlocked_account_dual_type, 0x4d6573736167652074c3b6207369676e2e204c6f6e676572207468616e206861736821 ) assert intsign == signature bytessign = web3.eth.sign( unlocked_account_dual_type, b'Message t\xc3\xb6 sign. Longer than hash!') assert bytessign == signature new_signature = web3.eth.sign(unlocked_account_dual_type, text='different message is different') assert new_signature != signature
def solidityKeccak(cls, abi_types: List[TypeStr], values: List[Any]) -> bytes: """ 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]` """ 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))) if isinstance(cls, type): w3 = None else: w3 = cls normalized_values = map_abi_data([abi_ens_resolver(w3)], abi_types, values) hex_string = add_0x_prefix( HexStr(''.join( remove_0x_prefix(hex_encode_abi_type(abi_type, value)) for abi_type, value in zip(abi_types, normalized_values)))) return cls.keccak(hexstr=hex_string)
def hex_encode_abi_type(abi_type: TypeStr, value: Any, force_size: int = None) -> HexStr: """ Encodes value into a hex string in format of abi_type """ validate_abi_type(abi_type) validate_abi_value(abi_type, value) data_size = force_size or size_of_type(abi_type) if is_array_type(abi_type): sub_type = sub_type_of_array_type(abi_type) return HexStr("".join([ remove_0x_prefix(hex_encode_abi_type(sub_type, v, 256)) for v in value ])) elif is_bool_type(abi_type): return to_hex_with_size(value, data_size) elif is_uint_type(abi_type): return to_hex_with_size(value, data_size) elif is_int_type(abi_type): return to_hex_twos_compliment(value, data_size) elif is_address_type(abi_type): return pad_hex(value, data_size) elif is_bytes_type(abi_type): if is_bytes(value): return encode_hex(value) else: return value elif is_string_type(abi_type): return to_hex(text=value) else: raise ValueError("Unsupported ABI type: {0}".format(abi_type))
def eth_transfer(priv_key: str, from_addr: str, to_addr: str, amount: float) -> TransferFuncResponse: myweb3 = Web3(provider=HTTPProvider(endpoint_uri=ETH_FULL_NODE_RPC_URL)) # https://web3py.readthedocs.io/en/stable/web3.eth.account.html?highlight=transaction # https://web3py.readthedocs.io/en/stable/web3.eth.account.html?highlight=transaction#sign-a-transaction from_address = to_checksum_address(from_addr) #必须使用 checksum addres block_identifier = HexStr('pending') nonce = myweb3.eth.getTransactionCount(from_address, block_identifier=block_identifier) cur_gas_price = myweb3.eth.gasPrice #获取实时手续费 if cur_gas_price > Web3.toWei(500, 'gwei'): #防止手续费过高 cur_gas_price = Web3.toWei(500, 'gwei') elif cur_gas_price < Web3.toWei(50, 'gwei'): #防止手续费过小 cur_gas_price = Web3.toWei(50, 'gwei') private_key = priv_key chksum_to_address = to_checksum_address(to_addr) transaction = { 'to': to_checksum_address(chksum_to_address), #必须使用 checksum 'value': Web3.toWei(number=amount, unit='ether'), 'gas': 21000, 'gasPrice': cur_gas_price, 'nonce': nonce } print(transaction) return sign_and_sendtransaction(myweb3=myweb3, unsigned_tranaction=transaction, private_key=private_key)
def test_trace_replay_block_with_transactions( self, web3: "Web3", block_with_txn: BlockData, parity_fixture_data: Dict[str, str] ) -> None: trace = web3.parity.traceReplayBlockTransactions(block_with_txn['number']) assert len(trace) > 0 trace_0_action = trace[0]['trace'][0]['action'] assert trace_0_action['from'] == add_0x_prefix(HexStr(parity_fixture_data['coinbase']))
def test_eth_getLogs_with_logs_topic_args( self, web3: "Web3", block_with_txn_with_log: BlockData, emitter_contract_address: ChecksumAddress, txn_hash_with_log: HexStr, ) -> None: def assert_contains_log(result: Sequence[LogReceipt]) -> None: assert len(result) == 1 log_entry = result[0] assert log_entry['blockNumber'] == block_with_txn_with_log[ 'number'] assert log_entry['blockHash'] == block_with_txn_with_log['hash'] assert log_entry['logIndex'] == 0 assert is_same_address(log_entry['address'], emitter_contract_address) assert log_entry['transactionIndex'] == 0 assert log_entry['transactionHash'] == HexBytes(txn_hash_with_log) # Test with None event sig filter_params: FilterParams = { "fromBlock": BlockNumber(0), "topics": [ None, HexStr( '0x000000000000000000000000000000000000000000000000000000000000d431' ) ], } result = web3.eth.getLogs(filter_params) assert_contains_log(result) # Test with None indexed arg filter_params = { "fromBlock": BlockNumber(0), "topics": [ HexStr( '0x057bc32826fbe161da1c110afcdcae7c109a8b69149f727fc37a603c60ef94ca' ), None ], } result = web3.eth.getLogs(filter_params) assert_contains_log(result)
def get_deployment_chain_data(w3: Web3) -> Tuple[Optional[str], Optional[Any]]: # todo: deployment_bytecode, runtime_bytecode, compiler flag = parse_bool_flag("Do you have a tx hash for your deployment?") if flag: tx_hash = HexStr(input("Please enter your tx hash. ")) tx = w3.eth.getTransaction(tx_hash) return tx_hash, to_hex(tx["blockHash"]) return (None, None)