def test_rejects_invalid_signature(chain, web3, token_v2, token_v1_owner, token_id, get_mint_data, eth_sign): assert token_v2.call().balanceOf(token_v1_owner) == 1 assert token_v2.call().upgradeCount() == 0 assert token_v2.call().isTokenUpgraded(token_id) is False new_owner = web3.eth.accounts[3] signature_data = b''.join(( decode_hex(token_v2.address), decode_hex(token_v1_owner), decode_hex(new_owner), )) signature = eth_sign(web3.eth.coinbase, signature_data) upgrade_txn_hash = token_v2.transact({ 'from': web3.eth.coinbase, }).proxyUpgrade(token_v1_owner, new_owner, signature) chain.wait.for_receipt(upgrade_txn_hash) with pytest.raises(AssertionError): get_mint_data(upgrade_txn_hash) assert token_v2.call().upgradeCount() == 0 assert token_v2.call().isTokenUpgraded(token_id) is False
def test_rejects_already_upgraded_token(chain, web3, token_v2, token_v1_owner, upgraded_token, get_mint_data, eth_sign): new_owner = web3.eth.accounts[3] assert token_v2.call().balanceOf(token_v1_owner) == 1 assert token_v2.call().isTokenUpgraded(upgraded_token) is True assert token_v2.call().isTokenOwner(new_owner) is False signature_data = b''.join(( decode_hex(token_v2.address), decode_hex(token_v1_owner), decode_hex(new_owner), )) signature = eth_sign(token_v1_owner, signature_data) upgrade_txn_hash = token_v2.transact({ 'from': web3.eth.coinbase, }).proxyUpgrade(token_v1_owner, new_owner, signature) chain.wait.for_receipt(upgrade_txn_hash) with pytest.raises(AssertionError): get_mint_data(upgrade_txn_hash) assert token_v2.call().isTokenOwner(new_owner) is False
def test_proxy_upgrade_same_owner(chain, web3, token_v2, token_v1_owner, token_id, get_mint_data, eth_sign): assert token_v2.call().balanceOf(token_v1_owner) == 1 assert token_v2.call().upgradeCount() == 0 assert token_v2.call().isTokenUpgraded(token_id) is False signature_data = b''.join(( decode_hex(token_v2.address), decode_hex(token_v1_owner), decode_hex(token_v1_owner), )) signature = eth_sign(token_v1_owner, signature_data) upgrade_txn_hash = token_v2.transact({ 'from': web3.eth.coinbase, }).proxyUpgrade(token_v1_owner, token_v1_owner, signature) chain.wait.for_receipt(upgrade_txn_hash) mint_data = get_mint_data(upgrade_txn_hash) assert token_v2.call().upgradeCount() == 1 assert token_v2.call().isTokenUpgraded(token_id) is True assert mint_data['args']['_owner'] == token_v1_owner assert mint_data['args']['_tokenID'] == token_id assert mint_data['address'] == token_v2.address
def test_rejects_if_new_owner_is_null_address(chain, web3, token_v2, token_v1_owner, token_id, other_token_v1_owner, get_mint_data, NULL_ADDRESS, eth_sign): assert token_v2.call().isTokenUpgraded(token_id) is False signature_data = b''.join(( decode_hex(token_v2.address), decode_hex(token_v1_owner), decode_hex(NULL_ADDRESS), )) signature = eth_sign(token_v1_owner, signature_data) upgrade_txn_hash = token_v2.transact({ 'from': web3.eth.coinbase, }).proxyUpgrade(token_v1_owner, other_token_v1_owner, signature) chain.wait.for_receipt(upgrade_txn_hash) with pytest.raises(AssertionError): get_mint_data(upgrade_txn_hash) assert token_v2.call().isTokenUpgraded(token_id) is False
def test_miner_setExtra(web3_empty, wait_for_block): web3 = web3_empty initial_extra = decode_hex( web3.eth.getBlock(web3.eth.blockNumber)['extraData']) new_extra_data = b'-this-is-32-bytes-of-extra-data-' # sanity assert initial_extra != new_extra_data web3.miner.setExtra(new_extra_data) with gevent.Timeout(60): while True: extra_data = decode_hex( web3.eth.getBlock(web3.eth.blockNumber)['extraData']) if extra_data == new_extra_data: break gevent.sleep(random.random()) after_extra = decode_hex( web3.eth.getBlock(web3.eth.blockNumber)['extraData']) assert after_extra == new_extra_data
def test_txn_request_for_txn_that_throw_exception(chain, web3, get_execute_data, RequestData, error_generator): txn_request = RequestData(createdBy=error_generator.address, donation=12345, toAddress=error_generator.address, callData=decode_hex( error_generator._encode_transaction_data( 'doThrow'))).direct_deploy() request_data = RequestData.from_contract(txn_request) chain.wait.for_block(request_data.schedule.windowStart) execute_txn_hash = txn_request.transact({ 'from': web3.eth.accounts[1], 'gas': 3000000, }).execute() execute_txn_receipt = chain.wait.for_receipt(execute_txn_hash) execute_data = get_execute_data(execute_txn_hash) request_data = RequestData.from_contract(txn_request) assert request_data.meta.wasCalled is True assert request_data.meta.wasSuccessful is False gas_used = execute_txn_receipt['gasUsed'] measured_gas_consumption = execute_data['args']['measuredGasConsumption'] assert measured_gas_consumption > gas_used assert measured_gas_consumption - gas_used < 120000
def request_blocking(self, method, params): if method == 'eth_sendTransaction': base_transaction = params[0] # create a fully signed transaction and send through the # `eth_sendRawTransaction` endpoint instead. full_transaction = self.construct_full_transaction(base_transaction) raw_transaction_bytes = self.sign_and_serialize_transaction( full_transaction, ) raw_transaction_bytes_as_hex = encode_hex(raw_transaction_bytes) return self.request_blocking( 'eth_sendRawTransaction', [raw_transaction_bytes_as_hex], ) result = super(BaseSendRawTransactionMixin, self).request_blocking( method, params, ) if method in self.TXN_SENDING_METHODS: if method == 'eth_sendRawTransaction': txn = rlp.decode(decode_hex(params[0]), Transaction) self._known_transactions[to_address(txn.sender)].add(result) self._known_nonces[to_address(txn.sender)].add(txn.nonce) else: txn = params[0] self._known_transactions[to_address(txn['from'])].add(result) if 'nonce' in txn: self._known_nonces[to_address(txn['from'])].add( to_decimal(txn['nonce']) ) return result
def test_proxy_execution_accepted_at_minimum_gas(chain, RequestData, proxy, txn_recorder, request_lib, execution_lib, get_execute_data, get_abort_data, AbortReasons): txn_request = RequestData( toAddress=txn_recorder.address, callGas=100000, ).direct_deploy() request_data = RequestData.from_contract(txn_request) assert txn_recorder.call().wasCalled() is False chain.wait.for_block(request_data.schedule.windowStart) minimum_call_gas = (request_data.txnData.callGas + request_lib.call().EXECUTION_GAS_OVERHEAD() + execution_lib.call().GAS_PER_DEPTH() * request_data.txnData.requiredStackDepth) call_data_hex = txn_request._encode_transaction_data('execute') execute_txn_hash = proxy.transact({ 'gas': 3000000 }).__proxy( to=txn_request.address, callData=decode_hex(call_data_hex), callGas=minimum_call_gas, ) chain.wait.for_receipt(execute_txn_hash) request_data.refresh() assert get_execute_data(execute_txn_hash) assert txn_recorder.call().wasCalled() is True assert request_data.meta.wasCalled is True
def test_dynamic_length_argument_extraction(web3, emitter, wait_for_transaction, emitter_log_topics, emitter_event_ids): string_0 = "this-is-the-first-string-which-exceeds-32-bytes-in-length" string_1 = "this-is-the-second-string-which-exceeds-32-bytes-in-length" txn_hash = emitter.transact().logDynamicArgs(string_0, string_1) txn_receipt = wait_for_transaction(web3, txn_hash) assert len(txn_receipt['logs']) == 1 log_entry = txn_receipt['logs'][0] event_abi = emitter._find_matching_event_abi('LogDynamicArgs') event_topic = emitter_log_topics.LogDynamicArgs assert event_topic in log_entry['topics'] string_0_topic = web3.sha3(string_0, encoding='utf8') assert string_0_topic in log_entry['topics'] event_data = get_event_data(event_abi, log_entry) expected_args = { "arg0": force_text(decode_hex(string_0_topic)), "arg1": string_1, } assert event_data['args'] == expected_args assert event_data['blockHash'] == txn_receipt['blockHash'] assert event_data['blockNumber'] == txn_receipt['blockNumber'] assert event_data['transactionIndex'] == txn_receipt['transactionIndex'] assert event_data['address'] == emitter.address assert event_data['event'] == 'LogDynamicArgs'
def test_adding_signature_to_transaction(wait_for_first_block, web3, skip_if_testrpc): skip_if_testrpc(web3) transaction = { 'nonce': hex(0), 'to': '0xd3cda913deb6f67967b99d67acdfa1712c293601', 'value': hex(12345), 'gas': hex(1200300), 'gasPrice': hex(54321), 'data': '0x1234567890abcdef', } serialized_txn = serialize_transaction(transaction) signature_hex = web3.eth.sign(web3.eth.coinbase, serialized_txn) signed_transaction = add_signature_to_transaction( serialized_txn, decode_hex(signature_hex), ) assert to_address(signed_transaction.to) == transaction['to'] assert signed_transaction.startgas == int(transaction['gas'], 16) assert signed_transaction.gasprice == int(transaction['gasPrice'], 16) assert signed_transaction.nonce == int(transaction['nonce'], 16) assert signed_transaction.value == int(transaction['value'], 16) assert encode_hex(signed_transaction.data) == transaction['data'] assert signed_transaction.sender == web3.eth.coinbase
def test_txn_request_for_txn_that_throw_exception(chain, web3, get_execute_data, RequestData, error_generator): txn_request = RequestData( createdBy=error_generator.address, donation=12345, toAddress=error_generator.address, callData=decode_hex(error_generator._encode_transaction_data('doThrow')) ).direct_deploy() request_data = RequestData.from_contract(txn_request) chain.wait.for_block(request_data.schedule.windowStart) execute_txn_hash = txn_request.transact({ 'from': web3.eth.accounts[1], 'gas': 3000000, }).execute() execute_txn_receipt = chain.wait.for_receipt(execute_txn_hash) execute_data = get_execute_data(execute_txn_hash) request_data = RequestData.from_contract(txn_request) assert request_data.meta.wasCalled is True assert request_data.meta.wasSuccessful is False gas_used = execute_txn_receipt['gasUsed'] measured_gas_consumption = execute_data['args']['measuredGasConsumption'] assert measured_gas_consumption > gas_used assert measured_gas_consumption - gas_used < 120000
def test_private_key_signing_manager(web3_pk_signer, account_private_key, account_public_key, wait_for_transaction): web3 = web3_pk_signer assert account_public_key not in web3_pk_signer.eth.accounts with pytest.raises(ValueError): web3.eth.sendTransaction({ 'from': account_public_key, 'to': web3.eth.coinbase, 'value': 1, }) from ethereum import tester tester.keys.append(account_private_key) tester.accounts.append(decode_hex(account_public_key)) txn_hash = web3.eth.sendTransaction({ 'from': account_public_key, 'to': web3.eth.coinbase, 'value': 1, }) txn_receipt = wait_for_transaction(web3, txn_hash) txn = web3.eth.getTransaction(txn_hash) assert txn['from'] == account_public_key
def extract_ecdsa_signer(msg_hash, signature): msg_hash_bytes = decode_hex(msg_hash) if msg_hash.startswith(b'0x') else msg_hash signature_bytes = decode_hex(signature) if signature.startswith(b'0x') else signature pk = PublicKey(flags=ALL_FLAGS) rec_id = signature_bytes[64] if is_string(rec_id): rec_id = ord(rec_id) pk.public_key = pk.ecdsa_recover( msg_hash_bytes, pk.ecdsa_recoverable_deserialize( signature_bytes[:64], rec_id, ), raw=True, ) pk_serialized = pk.serialize(compressed=False) address = add_0x_prefix(sha3(encode_pubkey(pk_serialized, 'bin')[1:])[-40:]) return address
def unknown_token_id(token_v1, web3): token = token_v1 unknown_token_id = decode_hex(web3.sha3(encode_hex('Hudson James'))) assert unknown_token_id == sha3_256(b'Hudson James').digest() assert token.call().identityOf(unknown_token_id) == '' assert token.call().ownerOf( unknown_token_id) == '0x0000000000000000000000000000000000000000' return unknown_token_id
def test_miner_setExtra(web3_empty, wait_for_block): web3 = web3_empty initial_extra = decode_hex(web3.eth.getBlock(web3.eth.blockNumber)['extraData']) new_extra_data = b'-this-is-32-bytes-of-extra-data-' # sanity assert initial_extra != new_extra_data web3.miner.setExtra(new_extra_data) with gevent.Timeout(60): while True: extra_data = decode_hex(web3.eth.getBlock(web3.eth.blockNumber)['extraData']) if extra_data == new_extra_data: break gevent.sleep(random.random()) after_extra = decode_hex(web3.eth.getBlock(web3.eth.blockNumber)['extraData']) assert after_extra == new_extra_data
def set_can_call(chain, authority, caller_address, code_address, can_call, function_signature): sig_as_hex = function_signature_to_4byte_selector(function_signature) sig_as_bytes = decode_hex(sig_as_hex) can_already_call = authority.call().canCall( callerAddress=caller_address, codeAddress=code_address, sig=sig_as_bytes, ) if can_already_call: click.echo( "Permissions already set for: {0}".format(function_signature)) return click.echo("Setting up permissions for:\n" "- function: {0}\n" "- sig: {1}\n" "- caller_address: {2}\n" "- code_address: {3}\n" "- can_call: {4}".format( function_signature, sig_as_hex, caller_address, code_address, ("Yes" if can_call else "No"), )) click.echo("Sending authorization transaction... ", nl=False) authorize_txn_hash = authority.transact().setCanCall( callerAddress=caller_address, codeAddress=code_address, sig=sig_as_bytes, can=can_call, ) click.echo("SENT") click.echo("Authorize Transaction Hash: {0}".format(authorize_txn_hash)) click.echo("Waiting for transaction to be mined... ", nl=False) chain.wait.for_receipt(authorize_txn_hash, timeout=600) click.echo("MINED") check_can_call = authority.call().canCall( callerAddress=caller_address, codeAddress=code_address, sig=sig_as_bytes, ) if check_can_call is not can_call: click.echo("Something went wrong. Authorization did not go though") import pdb pdb.set_trace() raise ValueError("Failed to set authorization") return
def test_txn_request_when_everything_throws(chain, web3, get_execute_data, RequestData, error_generator): txn_request = RequestData( createdBy=error_generator.address, owner=error_generator.address, donationBenefactor=error_generator.address, toAddress=error_generator.address, callData=decode_hex(error_generator._encode_transaction_data('doThrow')) ).direct_deploy() request_data = RequestData.from_contract(txn_request) chain.wait.for_block(request_data.schedule.windowStart) proxy_call_data = decode_hex(txn_request._encode_transaction_data('execute')) execute_txn_hash = error_generator.transact({ 'from': web3.eth.accounts[1], 'gas': 3000000, }).__proxy( to=txn_request.address, callData=proxy_call_data, ) execute_txn_receipt = chain.wait.for_receipt(execute_txn_hash) execute_data = get_execute_data(execute_txn_hash) request_data = RequestData.from_contract(txn_request) assert request_data.meta.wasCalled is True assert request_data.meta.wasSuccessful is False gas_used = execute_txn_receipt['gasUsed'] measured_gas_consumption = execute_data['args']['measuredGasConsumption'] assert measured_gas_consumption > gas_used assert measured_gas_consumption - gas_used < 50000
def get_transaction_signature(self, transaction): serialized_txn = serialize_transaction(transaction) hash_to_sign = self.signing_manager.request_blocking( 'web3_sha3', [encode_hex(serialized_txn)], ) signature_hex = self.signing_manager.request_blocking( 'eth_sign', [ transaction['from'], hash_to_sign, ], ) signature = decode_hex(signature_hex) return signature
def _set_timestamp(timestamp): evm.block.finalize() evm.block.commit_state() evm.db.put(evm.block.hash, rlp.encode(evm.block)) block = blocks.Block.init_from_parent( evm.block, decode_hex(web3.eth.coinbase), timestamp=timestamp, ) evm.block = block evm.blocks.append(evm.block) return timestamp
def test_txn_request_when_everything_throws(chain, web3, get_execute_data, RequestData, error_generator): txn_request = RequestData(createdBy=error_generator.address, owner=error_generator.address, donationBenefactor=error_generator.address, toAddress=error_generator.address, callData=decode_hex( error_generator._encode_transaction_data( 'doThrow'))).direct_deploy() request_data = RequestData.from_contract(txn_request) chain.wait.for_block(request_data.schedule.windowStart) proxy_call_data = decode_hex( txn_request._encode_transaction_data('execute')) execute_txn_hash = error_generator.transact({ 'from': web3.eth.accounts[1], 'gas': 3000000, }).__proxy( to=txn_request.address, callData=proxy_call_data, ) execute_txn_receipt = chain.wait.for_receipt(execute_txn_hash) execute_data = get_execute_data(execute_txn_hash) request_data = RequestData.from_contract(txn_request) assert request_data.meta.wasCalled is True assert request_data.meta.wasSuccessful is False gas_used = execute_txn_receipt['gasUsed'] measured_gas_consumption = execute_data['args']['measuredGasConsumption'] assert measured_gas_consumption > gas_used assert measured_gas_consumption - gas_used < 50000
def _inner_sign(account, data_to_sign): signature_hash_hex = web3.sha3(encode_hex(data_to_sign)) signature_hash_bytes = decode_hex(signature_hash_hex) private_key = tester.keys[tester.accounts.index(decode_hex(account))] priv_key = PrivateKey(flags=ALL_FLAGS) priv_key.set_raw_privkey(private_key) signature_raw = priv_key.ecdsa_sign_recoverable( signature_hash_bytes, raw=True, digest=sha3_256, ) signature_bytes, rec_id = priv_key.ecdsa_recoverable_serialize(signature_raw) signature = signature_bytes + force_bytes(chr(rec_id)) # Sanity check that the signature is valid. signer_address = force_text(extract_ecdsa_signer( signature_hash_bytes, signature, )) assert signer_address == account return signature
def sign_and_serialize_transaction(self, transaction): txn_from = to_address(transaction['from']) if txn_from not in self.keys: raise KeyError("No signing key registered for from address: {0}".format(txn_from)) transaction = Transaction( nonce=to_decimal(transaction['nonce']), gasprice=to_decimal(transaction['gasPrice']), startgas=to_decimal(transaction['gas']), to=transaction['to'], value=to_decimal(transaction['value']), data=decode_hex(transaction['data']), ) transaction.sign(self.keys[txn_from]) assert to_address(transaction.sender) == txn_from return rlp.encode(transaction, Transaction)
def _whitelist_call(code_address, function_signature, can_call): sig = decode_hex( function_signature_to_4byte_selector(function_signature)) chain.wait.for_receipt( authority.transact({ 'from': authority.call().owner(), }).setAnyoneCanCall( codeAddress=code_address, sig=sig, can=can_call, )) assert authority.call().canCall( '0x0000000000000000000000000000000000000000', codeAddress=code_address, sig=sig, ) is can_call
def outputPostFormatter(post): """ Formats the output of a received post message """ post["expiry"] = to_decimal(post["expiry"]) post["sent"] = to_decimal(post["sent"]) post["ttl"] = to_decimal(post["ttl"]) post["workProved"] = to_decimal(post["workProved"]) if not post.get("topics"): post["topics"] = [] post["topics"] = [decode_hex(topic) for topic in post["topics"]] return post
def _authorize_call(caller_address, code_address, function_signature, can_call): sig = decode_hex( function_signature_to_4byte_selector(function_signature)) chain.wait.for_receipt( authority.transact({ 'from': authority.call().authority(), }).setCanCall( callerAddress=caller_address, codeAddress=code_address, sig=sig, can=can_call, )) assert authority.call().canCall( callerAddress=caller_address, codeAddress=code_address, sig=sig, ) is can_call
def test_proxy_execution_rejected_for_insufficient_gas(chain, RequestData, proxy, txn_recorder, request_lib, execution_lib, get_execute_data, get_abort_data, AbortReasons): txn_request = RequestData( toAddress=txn_recorder.address, callGas=100000, ).direct_deploy() request_data = RequestData.from_contract(txn_request) assert txn_recorder.call().wasCalled() is False chain.wait.for_block(request_data.schedule.windowStart) minimum_call_gas = ( request_data.txnData.callGas + request_lib.call().EXECUTION_GAS_OVERHEAD() + execution_lib.call().GAS_PER_DEPTH() * request_data.txnData.requiredStackDepth ) too_low_call_gas = minimum_call_gas - request_lib.call().PRE_EXECUTION_GAS() call_data_hex = txn_request._encode_transaction_data('execute') execute_txn_hash = proxy.transact({'gas': 3000000}).__proxy( to=txn_request.address, callData=decode_hex(call_data_hex), callGas=too_low_call_gas, ) chain.wait.for_receipt(execute_txn_hash) assert txn_recorder.call().wasCalled() is False assert request_data.meta.wasCalled is False with pytest.raises(AssertionError): get_execute_data(execute_txn_hash) abort_data = get_abort_data(execute_txn_hash) reasons = {entry['args']['reason'] for entry in abort_data} assert AbortReasons.InsufficientGas in reasons
def generate_registrar_value_setters(receipt, prefix=None): if prefix is None: prefix = [] if is_string(prefix): prefix = [prefix] if isinstance(receipt, RegistrarValue): raise ValueError("Receipt should not be instantiated at this point") elif is_hex_address(receipt): # Special case for addresses return [ Address.defer(key='/'.join(prefix), value=receipt) ] elif is_hex_transaction_hash(receipt): # Special case for transaction hashes and addresses. return [ Bytes32.defer(key='/'.join(prefix), value=decode_hex(receipt)) ] elif isinstance(receipt, type) and issubclass(receipt, RegistrarValue): return [ receipt.defer( key=receipt.key or '/'.join(prefix), value_type=receipt.value_type, value=receipt.value, ) ] elif isinstance(receipt, dict): return list(itertools.chain.from_iterable([ generate_registrar_value_setters(value, prefix + [key]) for key, value in receipt.items() ])) elif isinstance(receipt, (list, tuple)): return list(itertools.chain.from_iterable([ generate_registrar_value_setters(value, prefix + [str(index)]) for index, value in enumerate(receipt) ])) else: raise ValueError( "Invalid type. Must be one of transaction hash, address, " "ReceiptValue, dict, or list" )
def test_execution_rejected_if_stack_too_deep(chain, web3, RequestData, txn_recorder, digger_proxy, get_execute_data, get_abort_data, AbortReasons): txn_request = RequestData( toAddress=txn_recorder.address, requiredStackDepth=1000, ).direct_deploy() request_data = RequestData.from_contract(txn_request) assert txn_recorder.call().wasCalled() is False assert request_data.meta.wasCalled is False assert request_data.txnData.requiredStackDepth == 1000 chain.wait.for_block(request_data.schedule.windowStart) execute_call_data = decode_hex(txn_request._encode_transaction_data('execute')) execute_txn_hash = digger_proxy.transact({'gas': 3000000}).__dig_then_proxy( 24, txn_request.address, execute_call_data, ) chain.wait.for_receipt(execute_txn_hash) request_data.refresh() assert digger_proxy.call().result() is True assert txn_recorder.call().wasCalled() is False assert request_data.meta.wasCalled is False with pytest.raises(AssertionError): get_execute_data(execute_txn_hash) abort_data = get_abort_data(execute_txn_hash) reasons = {entry['args']['reason'] for entry in abort_data} assert AbortReasons.StackTooDeep in reasons
def test_proxy_execution_rejected_for_insufficient_gas( chain, RequestData, proxy, txn_recorder, request_lib, execution_lib, get_execute_data, get_abort_data, AbortReasons): txn_request = RequestData( toAddress=txn_recorder.address, callGas=100000, ).direct_deploy() request_data = RequestData.from_contract(txn_request) assert txn_recorder.call().wasCalled() is False chain.wait.for_block(request_data.schedule.windowStart) minimum_call_gas = (request_data.txnData.callGas + request_lib.call().EXECUTION_GAS_OVERHEAD() + execution_lib.call().GAS_PER_DEPTH() * request_data.txnData.requiredStackDepth) too_low_call_gas = minimum_call_gas - request_lib.call().PRE_EXECUTION_GAS( ) call_data_hex = txn_request._encode_transaction_data('execute') execute_txn_hash = proxy.transact({ 'gas': 3000000 }).__proxy( to=txn_request.address, callData=decode_hex(call_data_hex), callGas=too_low_call_gas, ) chain.wait.for_receipt(execute_txn_hash) assert txn_recorder.call().wasCalled() is False assert request_data.meta.wasCalled is False with pytest.raises(AssertionError): get_execute_data(execute_txn_hash) abort_data = get_abort_data(execute_txn_hash) reasons = {entry['args']['reason'] for entry in abort_data} assert AbortReasons.InsufficientGas in reasons
def test_proxy_execution_accepted_at_minimum_gas(chain, RequestData, proxy, txn_recorder, request_lib, execution_lib, get_execute_data, get_abort_data, AbortReasons): txn_request = RequestData( toAddress=txn_recorder.address, callGas=100000, ).direct_deploy() request_data = RequestData.from_contract(txn_request) assert txn_recorder.call().wasCalled() is False chain.wait.for_block(request_data.schedule.windowStart) minimum_call_gas = ( request_data.txnData.callGas + request_lib.call().EXECUTION_GAS_OVERHEAD() + execution_lib.call().GAS_PER_DEPTH() * request_data.txnData.requiredStackDepth ) call_data_hex = txn_request._encode_transaction_data('execute') execute_txn_hash = proxy.transact({'gas': 3000000}).__proxy( to=txn_request.address, callData=decode_hex(call_data_hex), callGas=minimum_call_gas, ) chain.wait.for_receipt(execute_txn_hash) request_data.refresh() assert get_execute_data(execute_txn_hash) assert txn_recorder.call().wasCalled() is True assert request_data.meta.wasCalled is True
def test_claim_deposit_returned_even_if_returning_it_throws( chain, web3, RequestData, get_claim_data, error_generator): txn_request = RequestData(windowStart=web3.eth.blockNumber + 255 + 10 + 5).direct_deploy() request_data = RequestData.from_contract(txn_request) try_claim_at = request_data.schedule.windowStart - request_data.schedule.freezePeriod - request_data.schedule.claimWindowSize - 3 # sanity assert try_claim_at > web3.eth.blockNumber chain.wait.for_block(try_claim_at) deposit_amount = 2 * request_data.paymentData.payment before_contract_balance = web3.eth.getBalance(txn_request.address) before_account_balance = web3.eth.getBalance(error_generator.address) assert before_account_balance == 0 claim_call_data = decode_hex(txn_request._encode_transaction_data('claim')) claim_txn_hash = error_generator.transact({ 'value': deposit_amount, }).__proxy( txn_request.address, claim_call_data, ) chain.wait.for_receipt(claim_txn_hash) after_contract_balance = web3.eth.getBalance(txn_request.address) after_account_balance = web3.eth.getBalance(error_generator.address) assert after_contract_balance == before_contract_balance assert after_account_balance == deposit_amount request_data.refresh() assert request_data.claimData.claimedBy == '0x0000000000000000000000000000000000000000'
def test_claim_deposit_returned_even_if_returning_it_throws(chain, web3, RequestData, get_claim_data, error_generator): txn_request = RequestData(windowStart=web3.eth.blockNumber + 255 + 10 + 5).direct_deploy() request_data = RequestData.from_contract(txn_request) try_claim_at = request_data.schedule.windowStart - request_data.schedule.freezePeriod - request_data.schedule.claimWindowSize - 3 # sanity assert try_claim_at > web3.eth.blockNumber chain.wait.for_block(try_claim_at) deposit_amount = 2 * request_data.paymentData.payment before_contract_balance = web3.eth.getBalance(txn_request.address) before_account_balance = web3.eth.getBalance(error_generator.address) assert before_account_balance == 0 claim_call_data = decode_hex(txn_request._encode_transaction_data('claim')) claim_txn_hash = error_generator.transact({ 'value': deposit_amount, }).__proxy(txn_request.address, claim_call_data, ) chain.wait.for_receipt(claim_txn_hash) after_contract_balance = web3.eth.getBalance(txn_request.address) after_account_balance = web3.eth.getBalance(error_generator.address) assert after_contract_balance == before_contract_balance assert after_account_balance == deposit_amount request_data.refresh() assert request_data.claimData.claimedBy == '0x0000000000000000000000000000000000000000'
def test_execution_accepted_when_stack_extendable(chain, web3, RequestData, txn_recorder, digger_proxy, get_execute_data, get_abort_data, AbortReasons): txn_request = RequestData( toAddress=txn_recorder.address, requiredStackDepth=1000, ).direct_deploy() request_data = RequestData.from_contract(txn_request) assert txn_recorder.call().wasCalled() is False assert request_data.meta.wasCalled is False assert request_data.txnData.requiredStackDepth == 1000 chain.wait.for_block(request_data.schedule.windowStart) execute_call_data = decode_hex(txn_request._encode_transaction_data('execute')) execute_txn_hash = digger_proxy.transact({'gas': 3000000}).__dig_then_proxy( 21, txn_request.address, execute_call_data, ) chain.wait.for_receipt(execute_txn_hash) request_data.refresh() assert digger_proxy.call().result() is True assert txn_recorder.call().wasCalled() is True assert request_data.meta.wasCalled is True assert get_execute_data(execute_txn_hash)
def test_eth_sign(web3_empty, skip_if_testrpc): web3 = web3_empty skip_if_testrpc(web3) private_key_hex = '0x5e95384d8050109aab08c1922d3c230739bc16976553c317e5d0b87b59371f2a' private_key = decode_hex(private_key_hex) # This imports the private key into the running geth instance and unlocks # the account so that it can sign things. # `0xa5df35f30ba0ce878b1061ae086289adff3ba1e0` address = web3.personal.importRawKey(private_key, "password") web3.personal.unlockAccount(address, "password") assert add_0x_prefix(encode_hex( privtoaddr(private_key))) == add_0x_prefix(address) assert address == '0xa5df35f30ba0ce878b1061ae086289adff3ba1e0' # the data to be signed data = b'1234567890abcdefghijklmnopqrstuvwxyz' # the hash of the data `0x089c33d56ed10bd8b571a0f493cedb28db1ae0f40c6cd266243001528c06eab3` data_hash = web3.sha3(data, encoding=None) data_hash_bytes = decode_hex(data_hash) assert force_bytes(data_hash) == sha3(data) priv_key = PrivateKey(flags=ALL_FLAGS) priv_key.set_raw_privkey(private_key) # sanit check the extract_ecdsa_signer function works as expected. vector_sig = priv_key.ecdsa_sign_recoverable(data_hash_bytes, raw=True, digest=sha3_256) vector_sig_bytes, rec_id = priv_key.ecdsa_recoverable_serialize(vector_sig) vector_sig_bytes_full = vector_sig_bytes + force_bytes(chr(rec_id)) vector_address = force_text( extract_ecdsa_signer(data_hash_bytes, vector_sig_bytes_full)) assert vector_address == address # Now have geth sign some data. signature_hex = web3.eth.sign(address, data) signature_bytes = decode_hex(signature_hex) actual_signer = extract_ecdsa_signer(data_hash_bytes, signature_bytes) assert actual_signer == address # Verify the signature against the public key derived from the # original private key. It fails. rec_id = signature_bytes[64] if is_string(rec_id): rec_id = ord(rec_id) recoverable_signature = priv_key.ecdsa_recoverable_deserialize( signature_bytes[:64], rec_id, ) signature = priv_key.ecdsa_recoverable_convert(recoverable_signature) is_valid = priv_key.pubkey.ecdsa_verify( msg=data, raw_sig=signature, digest=sha3_256, ) assert is_valid
def test_accounting_when_everything_throws(chain, web3, get_execute_data, RequestData, error_generator): txn_request = RequestData( createdBy=error_generator.address, owner=error_generator.address, donationBenefactor=error_generator.address, toAddress=error_generator.address, callData=decode_hex(error_generator._encode_transaction_data('doThrow')), windowStart=web3.eth.blockNumber + 10 + 255 + 5, ).direct_deploy() request_data = RequestData.from_contract(txn_request) claim_at = request_data.schedule.windowStart - 10 - 5 deposit_amount = request_data.paymentData.payment * 2 assert claim_at > web3.eth.blockNumber chain.wait.for_block(claim_at) claim_call_data = decode_hex(txn_request._encode_transaction_data('claim')) claim_txn_hash = error_generator.transact({ 'value': deposit_amount, }).__proxy(txn_request.address, claim_call_data, ) chain.wait.for_receipt(claim_txn_hash) chain.wait.for_block(request_data.schedule.windowStart) execute_call_data = decode_hex(txn_request._encode_transaction_data('execute')) execute_txn_hash = error_generator.transact({ 'from': web3.eth.accounts[1], 'gas': 3000000, }).__proxy( to=txn_request.address, callData=execute_call_data, ) execute_txn_receipt = chain.wait.for_receipt(execute_txn_hash) chain.wait.for_block(request_data.schedule.windowStart + request_data.schedule.windowSize) execute_data = get_execute_data(execute_txn_hash) request_data.refresh() assert request_data.meta.wasCalled is True assert request_data.meta.wasSuccessful is False gas_used = execute_txn_receipt['gasUsed'] measured_gas_consumption = execute_data['args']['measuredGasConsumption'] assert measured_gas_consumption > gas_used assert measured_gas_consumption - gas_used < 50000 payment_owed = request_data.paymentData.paymentOwed donation_owed = request_data.paymentData.donationOwed assert payment_owed > 0 assert payment_owed == execute_data['args']['payment'] assert donation_owed > 0 assert donation_owed == execute_data['args']['donation'] # make the contract stop throwing now. chain.wait.for_receipt(error_generator.transact().toggle()) assert error_generator.call().shouldThrow() is False before_payments_contract_balance = web3.eth.getBalance(txn_request.address) before_owner_refund_balance = web3.eth.getBalance(error_generator.address) issue_owner_refund_txn_hash = txn_request.transact().sendOwnerEther() chain.wait.for_receipt(issue_owner_refund_txn_hash) after_owner_refund_balance = web3.eth.getBalance(error_generator.address) owner_refund = after_owner_refund_balance - before_owner_refund_balance assert owner_refund > 0 before_payment_balance = web3.eth.getBalance(error_generator.address) issue_payment_txn_hash = txn_request.transact().sendPayment() chain.wait.for_receipt(issue_payment_txn_hash) request_data.refresh() after_payment_balance = web3.eth.getBalance(error_generator.address) assert after_payment_balance - before_payment_balance == payment_owed before_donation_balance = web3.eth.getBalance(error_generator.address) issue_donation_txn_hash = txn_request.transact().sendDonation() chain.wait.for_receipt(issue_donation_txn_hash) request_data.refresh() after_donation_balance = web3.eth.getBalance(error_generator.address) assert after_donation_balance - before_donation_balance == donation_owed assert owner_refund + payment_owed + donation_owed == before_payments_contract_balance
def test_hex_encode_decode_round_trip(value): intermediate_value = encode_hex(value) result_value = decode_hex(intermediate_value) assert result_value == value, "Expected: {0!r}, Result: {1!r}, Intermediate: {2!r}".format( value, result_value, intermediate_value)
def test_eth_sign(web3_empty, skip_if_testrpc): web3 = web3_empty skip_if_testrpc(web3) private_key_hex = '0x5e95384d8050109aab08c1922d3c230739bc16976553c317e5d0b87b59371f2a' private_key = decode_hex(private_key_hex) # This imports the private key into the running geth instance and unlocks # the account so that it can sign things. # `0xa5df35f30ba0ce878b1061ae086289adff3ba1e0` address = web3.personal.importRawKey(private_key, "password") web3.personal.unlockAccount(address, "password") assert add_0x_prefix(encode_hex(privtoaddr(private_key))) == add_0x_prefix(address) assert address == '0xa5df35f30ba0ce878b1061ae086289adff3ba1e0' # the data to be signed data = b'1234567890abcdefghijklmnopqrstuvwxyz' # the hash of the data `0x089c33d56ed10bd8b571a0f493cedb28db1ae0f40c6cd266243001528c06eab3` data_hash = web3.sha3(data, encoding=None) data_hash_bytes = decode_hex(data_hash) assert force_bytes(data_hash) == sha3(data) priv_key = PrivateKey(flags=ALL_FLAGS) priv_key.set_raw_privkey(private_key) # sanit check the extract_ecdsa_signer function works as expected. vector_sig = priv_key.ecdsa_sign_recoverable(data_hash_bytes, raw=True, digest=sha3_256) vector_sig_bytes, rec_id = priv_key.ecdsa_recoverable_serialize(vector_sig) vector_sig_bytes_full = vector_sig_bytes + force_bytes(chr(rec_id)) vector_address = force_text(extract_ecdsa_signer(data_hash_bytes, vector_sig_bytes_full)) assert vector_address == address # Now have geth sign some data. signature_hex = web3.eth.sign(address, data) signature_bytes = decode_hex(signature_hex) actual_signer = extract_ecdsa_signer(data_hash_bytes, signature_bytes) assert actual_signer == address # Verify the signature against the public key derived from the # original private key. It fails. rec_id = signature_bytes[64] if is_string(rec_id): rec_id = ord(rec_id) recoverable_signature = priv_key.ecdsa_recoverable_deserialize( signature_bytes[:64], rec_id, ) signature = priv_key.ecdsa_recoverable_convert(recoverable_signature) is_valid = priv_key.pubkey.ecdsa_verify( msg=data, raw_sig=signature, digest=sha3_256, ) assert is_valid
def test_hex_encode_decode_round_trip(value): intermediate_value = encode_hex(value) result_value = decode_hex(intermediate_value) assert result_value == value, "Expected: {0!r}, Result: {1!r}, Intermediate: {2!r}".format(value, result_value, intermediate_value)
def test_accounting_when_everything_throws(chain, web3, get_execute_data, RequestData, error_generator): txn_request = RequestData( createdBy=error_generator.address, owner=error_generator.address, donationBenefactor=error_generator.address, toAddress=error_generator.address, callData=decode_hex( error_generator._encode_transaction_data('doThrow')), windowStart=web3.eth.blockNumber + 10 + 255 + 5, ).direct_deploy() request_data = RequestData.from_contract(txn_request) claim_at = request_data.schedule.windowStart - 10 - 5 deposit_amount = request_data.paymentData.payment * 2 assert claim_at > web3.eth.blockNumber chain.wait.for_block(claim_at) claim_call_data = decode_hex(txn_request._encode_transaction_data('claim')) claim_txn_hash = error_generator.transact({ 'value': deposit_amount, }).__proxy( txn_request.address, claim_call_data, ) chain.wait.for_receipt(claim_txn_hash) chain.wait.for_block(request_data.schedule.windowStart) execute_call_data = decode_hex( txn_request._encode_transaction_data('execute')) execute_txn_hash = error_generator.transact({ 'from': web3.eth.accounts[1], 'gas': 3000000, }).__proxy( to=txn_request.address, callData=execute_call_data, ) execute_txn_receipt = chain.wait.for_receipt(execute_txn_hash) chain.wait.for_block(request_data.schedule.windowStart + request_data.schedule.windowSize) execute_data = get_execute_data(execute_txn_hash) request_data.refresh() assert request_data.meta.wasCalled is True assert request_data.meta.wasSuccessful is False gas_used = execute_txn_receipt['gasUsed'] measured_gas_consumption = execute_data['args']['measuredGasConsumption'] assert measured_gas_consumption > gas_used assert measured_gas_consumption - gas_used < 50000 payment_owed = request_data.paymentData.paymentOwed donation_owed = request_data.paymentData.donationOwed assert payment_owed > 0 assert payment_owed == execute_data['args']['payment'] assert donation_owed > 0 assert donation_owed == execute_data['args']['donation'] # make the contract stop throwing now. chain.wait.for_receipt(error_generator.transact().toggle()) assert error_generator.call().shouldThrow() is False before_payments_contract_balance = web3.eth.getBalance(txn_request.address) before_owner_refund_balance = web3.eth.getBalance(error_generator.address) issue_owner_refund_txn_hash = txn_request.transact().sendOwnerEther() chain.wait.for_receipt(issue_owner_refund_txn_hash) after_owner_refund_balance = web3.eth.getBalance(error_generator.address) owner_refund = after_owner_refund_balance - before_owner_refund_balance assert owner_refund > 0 before_payment_balance = web3.eth.getBalance(error_generator.address) issue_payment_txn_hash = txn_request.transact().sendPayment() chain.wait.for_receipt(issue_payment_txn_hash) request_data.refresh() after_payment_balance = web3.eth.getBalance(error_generator.address) assert after_payment_balance - before_payment_balance == payment_owed before_donation_balance = web3.eth.getBalance(error_generator.address) issue_donation_txn_hash = txn_request.transact().sendDonation() chain.wait.for_receipt(issue_donation_txn_hash) request_data.refresh() after_donation_balance = web3.eth.getBalance(error_generator.address) assert after_donation_balance - before_donation_balance == donation_owed assert owner_refund + payment_owed + donation_owed == before_payments_contract_balance