def value_hash(val): if isinstance(val, int): return eth_utils.keccak(encode_single_packed('(uint256)', [val])) # return eth_utils.keccak(encode_single_packed( # '(uint8,uint256)', # [INT_TYPE_CODE, val] # )) if isinstance(val, Tuple): return eth_utils.keccak( encode_single_packed('(uint8' + ',bytes32' * len(val) + ')', [TUPLE_TYPE_CODE + len(val)] + [value_hash(v) for v in val.val])) if isinstance(val, AVMCodePoint): if hasattr(val.op, "op_code"): return eth_utils.keccak( encode_single_packed( '(uint8,uint8,bytes32)', [CODE_POINT_CODE, val.op.op_code, val.next_hash])) if isinstance(val.op, int): return eth_utils.keccak( encode_single_packed('(uint8,uint8,bytes32)', [CODE_POINT_CODE, val.op, val.next_hash])) if hasattr(val.op, "val"): return eth_utils.keccak( encode_single_packed('(uint8,uint8,bytes32,bytes32)', [ CODE_POINT_CODE, val.op.op.op_code, value_hash(val.op.val), val.next_hash ])) raise Exception("Bad op type {}".format(val.op)) raise Exception("Can't hash {}".format(val))
def application_specific_data( self ) -> bytes: # TODO: Think a better name, perhaps something related to "message body" or something like that """ In EIP191 version 0 signatures, data to be signed follows the following format: 0x19 + 0x00 + validator_address + application_specific_data In the context of our MultiSig (which is the "validator"), the application specific data is the concatenation of: - Trustee address (actual sender of the TX) - Target address - Value included in the transaction (in wei) - Transaction data (e.g., an encoded call to a contract function) - MultiSig nonce """ typed_elements = ( ('address', self.trustee_address), # Trustee address ('address', self.target_address), # Target address ('uint256', self.value), # Value of the transaction ('bytes', self.data), # Transaction data ('uint256', self.nonce) # MultiSig nonce ) packed_elements = b''.join( [encode_single_packed(t, e) for t, e in typed_elements]) return packed_elements
def test_defunct_hash_message(self): safe_tx_hash = HexBytes('0x4c9577d1b1b8dec52329a983ae26238b65f74b7dd9fb28d74ad9548e92aaf196') ethereum_signed_message = '\x19Ethereum Signed Message:\n32' encoded_message = encode_single_packed('(string,bytes32)', (ethereum_signed_message, HexBytes(safe_tx_hash))) encoded_hash = Web3.keccak(encoded_message) self.assertEqual(encoded_hash, defunct_hash_message(primitive=safe_tx_hash))
def solidityKeccak(abi_types, values, validity_check=False): """ 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]` Adapted from web3.py """ 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 validity_check: for t, v in zip(abi_types, values): if not is_encodable(t, v): print(f'Value {v} is not encodable for ABI type {t}') return False hex_string = eth_utils.add_0x_prefix(''.join( encode_single_packed(abi_type, value).hex() for abi_type, value in zip(abi_types, values) )) # hex_string = encode_abi_packed(abi_types, values).hex() return eth_utils.keccak(hexstr=hex_string)
def value_hash(val): if isinstance(val, int): return eth_utils.keccak(encode_single_packed("(uint256)", [val])) # return eth_utils.keccak(encode_single_packed( # '(uint8,uint256)', # [INT_TYPE_CODE, val] # )) if isinstance(val, Tuple): size = val.get_size() first_hash = eth_utils.keccak( encode_single_packed( "(uint8" + ",bytes32" * len(val) + ")", [len(val)] + [value_hash(v) for v in val.val], )) return eth_utils.keccak( encode_single_packed("(uint8,bytes32,uint256)", [TUPLE_TYPE_CODE] + [first_hash] + [size])) if isinstance(val, AVMCodePoint): if hasattr(val.op, "op_code"): return eth_utils.keccak( encode_single_packed( "(uint8,uint8,bytes32)", [CODE_POINT_CODE, val.op.op_code, val.next_hash], )) if isinstance(val.op, int): return eth_utils.keccak( encode_single_packed("(uint8,uint8,bytes32)", [CODE_POINT_CODE, val.op, val.next_hash])) if hasattr(val.op, "val"): return eth_utils.keccak( encode_single_packed( "(uint8,uint8,bytes32,bytes32)", [ CODE_POINT_CODE, val.op.op.op_code, value_hash(val.op.val), val.next_hash, ], )) raise Exception("Bad op type {}".format(val.op)) raise Exception("Can't hash {}".format(val))
def test_encode_single(typ, python_value, _, packed_encoding): actual = encode_single_packed(typ, python_value) assert actual == packed_encoding
def test_auctionWorkflow(self): ## ## STARTING STATE ## starting_block_height = self.chain.head_state.block_number starting_owner_eth_holdings = self.chain.head_state.get_balance(rec_hex(CONTRACT_OWNER_ADDRESS)) self.chain.mine(1) self.assertTrue(self.erc721_contract.isMinter(CONTRACT_OWNER_ADDRESS)) self.chain.mine(1) self.assertEqual(1, self.erc721_contract.balanceOf(rec_hex(CONTRACT_OWNER_ADDRESS), sender=CONTRACT_OWNER_PRIVATE_KEY)) self.assertEqual(rec_hex(CONTRACT_OWNER_ADDRESS), self.erc721_contract.ownerOf(TOKEN_ID, sender=CONTRACT_OWNER_PRIVATE_KEY)) self.assertEqual(ACCOUNT_STARTING_BALANCE, self.chain.head_state.get_balance(rec_hex(ALICE_ADDRESS))) self.assertEqual(ACCOUNT_STARTING_BALANCE, self.chain.head_state.get_balance(rec_hex(BOB_ADDRESS))) self.assertEqual(ACCOUNT_STARTING_BALANCE, self.chain.head_state.get_balance(rec_hex(CHARLIE_ADDRESS))) self.assertTrue(self.auction_contract.address) self.assertEqual(27, self.auction_contract.vee()) ## ## START THE AUCTION ## (By sending the token to the auction contract, triggering onERC721Received) startAuctionBlock = self.chain.head_state.block_number + 1 endCommitPeriodBlock = self.chain.head_state.block_number + COMMIT_PERIOD_LENGTH onERC721RecievedDataField = encode_single_packed('(uint32,uint32)', [startAuctionBlock, endCommitPeriodBlock]) self.erc721_contract.safeTransferFrom(CONTRACT_OWNER_ADDRESS, self.auction_contract.address, TOKEN_ID, onERC721RecievedDataField, sender=CONTRACT_OWNER_PRIVATE_KEY) self.assertEqual(rec_hex(self.auction_contract.address), self.erc721_contract.ownerOf(TOKEN_ID)) self.assertEqual(rec_hex(CONTRACT_OWNER_ADDRESS), self.auction_contract.seller()) self.assertEqual(startAuctionBlock, self.auction_contract.startBlock()) self.assertEqual(endCommitPeriodBlock, self.auction_contract.endCommitBlock()) self.assertEqual(endCommitPeriodBlock+REVEAL_PERIOD_LENGTH, self.auction_contract.endRevealBlock()) self.assertEqual(TOKEN_ID, self.auction_contract.erc721TokenId()) self.assertEqual(rec_hex(self.erc721_contract.address), self.auction_contract.erc721()) # # GENERATE UNLOCK TXs # commitAddressAlice, commitAlice, witnessAlice, unlock_tx_hexAlice = generate_submarine_commit.generateCommitAddress( normalize_address(rec_hex(ALICE_ADDRESS)), normalize_address(rec_hex(self.auction_contract.address)), BID_AMOUNT_Alice, b'', OURGASPRICE, OURGASLIMIT) unlock_tx_infoAlice = rlp.decode(rec_bin(unlock_tx_hexAlice)) unlock_tx_objectAlice = transactions.Transaction( int.from_bytes(unlock_tx_infoAlice[0], byteorder="big"), # nonce; int.from_bytes(unlock_tx_infoAlice[1], byteorder="big"), # gasprice int.from_bytes(unlock_tx_infoAlice[2], byteorder="big"), # startgas unlock_tx_infoAlice[3], # to addr int.from_bytes(unlock_tx_infoAlice[4], byteorder="big"), # value unlock_tx_infoAlice[5], # data int.from_bytes(unlock_tx_infoAlice[6], byteorder="big"), # v int.from_bytes(unlock_tx_infoAlice[7], byteorder="big"), # r int.from_bytes(unlock_tx_infoAlice[8], byteorder="big") # s ) commitAddressBob, commitBob, witnessBob, unlock_tx_hexBob = generate_submarine_commit.generateCommitAddress( normalize_address(rec_hex(BOB_ADDRESS)), normalize_address(rec_hex(self.auction_contract.address)), BID_AMOUNT_Bob, b'', OURGASPRICE, OURGASLIMIT) unlock_tx_infoBob = rlp.decode(rec_bin(unlock_tx_hexBob)) unlock_tx_objectBob = transactions.Transaction( int.from_bytes(unlock_tx_infoBob[0], byteorder="big"), # nonce; int.from_bytes(unlock_tx_infoBob[1], byteorder="big"), # gasprice int.from_bytes(unlock_tx_infoBob[2], byteorder="big"), # startgas unlock_tx_infoBob[3], # to addr int.from_bytes(unlock_tx_infoBob[4], byteorder="big"), # value unlock_tx_infoBob[5], # data int.from_bytes(unlock_tx_infoBob[6], byteorder="big"), # v int.from_bytes(unlock_tx_infoBob[7], byteorder="big"), # r int.from_bytes(unlock_tx_infoBob[8], byteorder="big") # s ) commitAddressCharlie, commitCharlie, witnessCharlie, unlock_tx_hexCharlie = generate_submarine_commit.generateCommitAddress( normalize_address(rec_hex(CHARLIE_ADDRESS)), normalize_address(rec_hex(self.auction_contract.address)), BID_AMOUNT_Charlie, b'', OURGASPRICE, OURGASLIMIT) unlock_tx_infoCharlie = rlp.decode(rec_bin(unlock_tx_hexCharlie)) unlock_tx_objectCharlie = transactions.Transaction( int.from_bytes(unlock_tx_infoCharlie[0], byteorder="big"), # nonce; int.from_bytes(unlock_tx_infoCharlie[1], byteorder="big"), # gasprice int.from_bytes(unlock_tx_infoCharlie[2], byteorder="big"), # startgas unlock_tx_infoCharlie[3], # to addr int.from_bytes(unlock_tx_infoCharlie[4], byteorder="big"), # value unlock_tx_infoCharlie[5], # data int.from_bytes(unlock_tx_infoCharlie[6], byteorder="big"), # v int.from_bytes(unlock_tx_infoCharlie[7], byteorder="big"), # r int.from_bytes(unlock_tx_infoCharlie[8], byteorder="big") # s ) # # GENERATE + BROADCAST COMMIT TXs # commit_tx_objectAlice = transactions.Transaction( 0, OURGASPRICE, BASIC_SEND_GAS_LIMIT, rec_bin(commitAddressAlice), (BID_AMOUNT_Alice + extraTransactionFees), b'').sign(ALICE_PRIVATE_KEY) commit_gasAlice = int(self.chain.head_state.gas_used) self.chain.mine(1) self.chain.direct_tx(commit_tx_objectAlice) self.chain.mine(1) commit_tx_objectBob = transactions.Transaction( 0, OURGASPRICE, BASIC_SEND_GAS_LIMIT, rec_bin(commitAddressBob), (BID_AMOUNT_Bob + extraTransactionFees), b'').sign(BOB_PRIVATE_KEY) commit_gasBob = int(self.chain.head_state.gas_used) self.chain.direct_tx(commit_tx_objectBob) self.chain.mine(1) commit_tx_objectCharlie = transactions.Transaction( 0, OURGASPRICE, BASIC_SEND_GAS_LIMIT, rec_bin(commitAddressCharlie), (BID_AMOUNT_Charlie + extraTransactionFees), b'').sign(CHARLIE_PRIVATE_KEY) commit_gasCharlie = int(self.chain.head_state.gas_used) self.chain.direct_tx(commit_tx_objectCharlie) self.chain.mine(1) ## ## CHECK STATE AFTER COMMIT TX ## commit_block_numberAlice, commit_block_indexAlice = self.chain.chain.get_tx_position( commit_tx_objectAlice) self.assertEqual(BID_AMOUNT_Alice + extraTransactionFees, self.chain.head_state.get_balance(commitAddressAlice)) self.assertEqual( ACCOUNT_STARTING_BALANCE - (BID_AMOUNT_Alice + extraTransactionFees + BASIC_SEND_GAS_LIMIT * OURGASPRICE), self.chain.head_state.get_balance(rec_hex(ALICE_ADDRESS))) session_dataAlice = self.auction_contract.getSubmarineState(rec_bin(commitAlice)) self.assertListEqual(session_dataAlice, [SOLIDITY_NULL_INITIALVAL, SOLIDITY_NULL_INITIALVAL, SOLIDITY_NULL_INITIALVAL, SOLIDITY_NULL_INITIALVAL]) revealedAndUnlocked_boolAlice = self.auction_contract.revealedAndUnlocked(rec_bin(commitAlice)) self.assertFalse( revealedAndUnlocked_boolAlice, "The contract should not be revealedAndUnlocked before it's even begun.") commit_block_numberBob, commit_block_indexBob = self.chain.chain.get_tx_position( commit_tx_objectBob) self.assertEqual(BID_AMOUNT_Bob + extraTransactionFees, self.chain.head_state.get_balance(commitAddressBob)) self.assertEqual( ACCOUNT_STARTING_BALANCE - (BID_AMOUNT_Bob + extraTransactionFees + BASIC_SEND_GAS_LIMIT * OURGASPRICE), self.chain.head_state.get_balance(rec_hex(BOB_ADDRESS))) session_dataBob = self.auction_contract.getSubmarineState(rec_bin(commitBob)) self.assertListEqual(session_dataBob, [SOLIDITY_NULL_INITIALVAL, SOLIDITY_NULL_INITIALVAL, SOLIDITY_NULL_INITIALVAL, SOLIDITY_NULL_INITIALVAL]) revealedAndUnlocked_boolBob = self.auction_contract.revealedAndUnlocked(rec_bin(commitBob)) self.assertFalse( revealedAndUnlocked_boolBob, "The contract should not be revealedAndUnlocked before it's even begun.") commit_block_numberCharlie, commit_block_indexCharlie = self.chain.chain.get_tx_position( commit_tx_objectCharlie) self.assertEqual(BID_AMOUNT_Charlie + extraTransactionFees, self.chain.head_state.get_balance(commitAddressCharlie)) self.assertEqual( ACCOUNT_STARTING_BALANCE - (BID_AMOUNT_Charlie + extraTransactionFees + BASIC_SEND_GAS_LIMIT * OURGASPRICE), self.chain.head_state.get_balance(rec_hex(CHARLIE_ADDRESS))) session_dataCharlie = self.auction_contract.getSubmarineState(rec_bin(commitCharlie)) self.assertListEqual(session_dataCharlie, [SOLIDITY_NULL_INITIALVAL, SOLIDITY_NULL_INITIALVAL, SOLIDITY_NULL_INITIALVAL, SOLIDITY_NULL_INITIALVAL]) revealedAndUnlocked_boolCharlie = self.auction_contract.revealedAndUnlocked(rec_bin(commitCharlie)) self.assertFalse( revealedAndUnlocked_boolCharlie, "The contract should not be revealedAndUnlocked before it's even begun.") ## ## GENERATE AND BROADCAST REVEAL BID TXS ## self.chain.mine(COMMIT_PERIOD_LENGTH + 1) commit_block_objectAlice = self.chain.chain.get_block_by_number(commit_block_numberAlice) proveth_expected_block_format_dictAlice = dict() proveth_expected_block_format_dictAlice['parentHash'] = commit_block_objectAlice['prevhash'] proveth_expected_block_format_dictAlice['sha3Uncles'] = commit_block_objectAlice['uncles_hash'] proveth_expected_block_format_dictAlice['miner'] = commit_block_objectAlice['coinbase'] proveth_expected_block_format_dictAlice['stateRoot'] = commit_block_objectAlice['state_root'] proveth_expected_block_format_dictAlice['transactionsRoot'] = commit_block_objectAlice['tx_list_root'] proveth_expected_block_format_dictAlice['receiptsRoot'] = commit_block_objectAlice['receipts_root'] proveth_expected_block_format_dictAlice['logsBloom'] = commit_block_objectAlice['bloom'] proveth_expected_block_format_dictAlice['difficulty'] = commit_block_objectAlice['difficulty'] proveth_expected_block_format_dictAlice['number'] = commit_block_objectAlice['number'] proveth_expected_block_format_dictAlice['gasLimit'] = commit_block_objectAlice['gas_limit'] proveth_expected_block_format_dictAlice['gasUsed'] = commit_block_objectAlice['gas_used'] proveth_expected_block_format_dictAlice['timestamp'] = commit_block_objectAlice['timestamp'] proveth_expected_block_format_dictAlice['extraData'] = commit_block_objectAlice['extra_data'] proveth_expected_block_format_dictAlice['mixHash'] = commit_block_objectAlice['mixhash'] proveth_expected_block_format_dictAlice['nonce'] = commit_block_objectAlice['nonce'] proveth_expected_block_format_dictAlice['hash'] = commit_block_objectAlice.hash proveth_expected_block_format_dictAlice['uncles'] = [] proveth_expected_block_format_dictAlice['transactions'] = ({ "blockHash": commit_block_objectAlice.hash, "blockNumber": str(hex((commit_block_objectAlice['number']))), "from": checksum_encode(ALICE_ADDRESS), "gas": str(hex(commit_tx_objectAlice['startgas'])), "gasPrice": str(hex(commit_tx_objectAlice['gasprice'])), "hash": rec_hex(commit_tx_objectAlice['hash']), "input": rec_hex(commit_tx_objectAlice['data']), "nonce": str(hex(commit_tx_objectAlice['nonce'])), "to": checksum_encode(commit_tx_objectAlice['to']), "transactionIndex": str(hex(0)), "value": str(hex(commit_tx_objectAlice['value'])), "v": str(hex(commit_tx_objectAlice['v'])), "r": str(hex(commit_tx_objectAlice['r'])), "s": str(hex(commit_tx_objectAlice['s'])) }, ) commit_proof_blobAlice = proveth.generate_proof_blob( proveth_expected_block_format_dictAlice, commit_block_indexAlice) _unlockExtraData = b'' # In this example we dont have any extra embedded data as part of the unlock TX unlock_tx_unsigned_objectAlice = transactions.UnsignedTransaction( int.from_bytes(unlock_tx_infoAlice[0], byteorder="big"), # nonce; int.from_bytes(unlock_tx_infoAlice[1], byteorder="big"), # gasprice int.from_bytes(unlock_tx_infoAlice[2], byteorder="big"), # startgas unlock_tx_infoAlice[3], # to addr int.from_bytes(unlock_tx_infoAlice[4], byteorder="big"), # value unlock_tx_infoAlice[5], # data ) unlock_tx_unsigned_rlpAlice = rlp.encode(unlock_tx_unsigned_objectAlice, transactions.UnsignedTransaction) self.auction_contract.reveal( commit_block_numberAlice, # uint32 _commitBlockNumber, _unlockExtraData, # bytes _commitData, rec_bin(witnessAlice), # bytes32 _witness, unlock_tx_unsigned_rlpAlice, # bytes _rlpUnlockTxUnsigned, commit_proof_blobAlice, # bytes _proofBlob sender=ALICE_PRIVATE_KEY) reveal_gasAlice = int(self.chain.head_state.gas_used) self.chain.mine(1) commit_block_objectBob = self.chain.chain.get_block_by_number(commit_block_numberBob) proveth_expected_block_format_dictBob = dict() proveth_expected_block_format_dictBob['parentHash'] = commit_block_objectBob['prevhash'] proveth_expected_block_format_dictBob['sha3Uncles'] = commit_block_objectBob['uncles_hash'] proveth_expected_block_format_dictBob['miner'] = commit_block_objectBob['coinbase'] proveth_expected_block_format_dictBob['stateRoot'] = commit_block_objectBob['state_root'] proveth_expected_block_format_dictBob['transactionsRoot'] = commit_block_objectBob['tx_list_root'] proveth_expected_block_format_dictBob['receiptsRoot'] = commit_block_objectBob['receipts_root'] proveth_expected_block_format_dictBob['logsBloom'] = commit_block_objectBob['bloom'] proveth_expected_block_format_dictBob['difficulty'] = commit_block_objectBob['difficulty'] proveth_expected_block_format_dictBob['number'] = commit_block_objectBob['number'] proveth_expected_block_format_dictBob['gasLimit'] = commit_block_objectBob['gas_limit'] proveth_expected_block_format_dictBob['gasUsed'] = commit_block_objectBob['gas_used'] proveth_expected_block_format_dictBob['timestamp'] = commit_block_objectBob['timestamp'] proveth_expected_block_format_dictBob['extraData'] = commit_block_objectBob['extra_data'] proveth_expected_block_format_dictBob['mixHash'] = commit_block_objectBob['mixhash'] proveth_expected_block_format_dictBob['nonce'] = commit_block_objectBob['nonce'] proveth_expected_block_format_dictBob['hash'] = commit_block_objectBob.hash proveth_expected_block_format_dictBob['uncles'] = [] proveth_expected_block_format_dictBob['transactions'] = ({ "blockHash": commit_block_objectBob.hash, "blockNumber": str(hex((commit_block_objectBob['number']))), "from": checksum_encode(BOB_ADDRESS), "gas": str(hex(commit_tx_objectBob['startgas'])), "gasPrice": str(hex(commit_tx_objectBob['gasprice'])), "hash": rec_hex(commit_tx_objectBob['hash']), "input": rec_hex(commit_tx_objectBob['data']), "nonce": str(hex(commit_tx_objectBob['nonce'])), "to": checksum_encode(commit_tx_objectBob['to']), "transactionIndex": str(hex(0)), "value": str(hex(commit_tx_objectBob['value'])), "v": str(hex(commit_tx_objectBob['v'])), "r": str(hex(commit_tx_objectBob['r'])), "s": str(hex(commit_tx_objectBob['s'])) }, ) commit_proof_blobBob = proveth.generate_proof_blob( proveth_expected_block_format_dictBob, commit_block_indexBob) _unlockExtraData = b'' # In this example we dont have any extra embedded data as part of the unlock TX unlock_tx_unsigned_objectBob = transactions.UnsignedTransaction( int.from_bytes(unlock_tx_infoBob[0], byteorder="big"), # nonce; int.from_bytes(unlock_tx_infoBob[1], byteorder="big"), # gasprice int.from_bytes(unlock_tx_infoBob[2], byteorder="big"), # startgas unlock_tx_infoBob[3], # to addr int.from_bytes(unlock_tx_infoBob[4], byteorder="big"), # value unlock_tx_infoBob[5], # data ) unlock_tx_unsigned_rlpBob = rlp.encode(unlock_tx_unsigned_objectBob, transactions.UnsignedTransaction) self.auction_contract.reveal( commit_block_numberBob, # uint32 _commitBlockNumber, _unlockExtraData, # bytes _commitData, rec_bin(witnessBob), # bytes32 _witness, unlock_tx_unsigned_rlpBob, # bytes _rlpUnlockTxUnsigned, commit_proof_blobBob, # bytes _proofBlob sender=BOB_PRIVATE_KEY) reveal_gasBob = int(self.chain.head_state.gas_used) self.chain.mine(1) commit_block_objectCharlie = self.chain.chain.get_block_by_number(commit_block_numberCharlie) proveth_expected_block_format_dictCharlie = dict() proveth_expected_block_format_dictCharlie['parentHash'] = commit_block_objectCharlie['prevhash'] proveth_expected_block_format_dictCharlie['sha3Uncles'] = commit_block_objectCharlie['uncles_hash'] proveth_expected_block_format_dictCharlie['miner'] = commit_block_objectCharlie['coinbase'] proveth_expected_block_format_dictCharlie['stateRoot'] = commit_block_objectCharlie['state_root'] proveth_expected_block_format_dictCharlie['transactionsRoot'] = commit_block_objectCharlie['tx_list_root'] proveth_expected_block_format_dictCharlie['receiptsRoot'] = commit_block_objectCharlie['receipts_root'] proveth_expected_block_format_dictCharlie['logsBloom'] = commit_block_objectCharlie['bloom'] proveth_expected_block_format_dictCharlie['difficulty'] = commit_block_objectCharlie['difficulty'] proveth_expected_block_format_dictCharlie['number'] = commit_block_objectCharlie['number'] proveth_expected_block_format_dictCharlie['gasLimit'] = commit_block_objectCharlie['gas_limit'] proveth_expected_block_format_dictCharlie['gasUsed'] = commit_block_objectCharlie['gas_used'] proveth_expected_block_format_dictCharlie['timestamp'] = commit_block_objectCharlie['timestamp'] proveth_expected_block_format_dictCharlie['extraData'] = commit_block_objectCharlie['extra_data'] proveth_expected_block_format_dictCharlie['mixHash'] = commit_block_objectCharlie['mixhash'] proveth_expected_block_format_dictCharlie['nonce'] = commit_block_objectCharlie['nonce'] proveth_expected_block_format_dictCharlie['hash'] = commit_block_objectCharlie.hash proveth_expected_block_format_dictCharlie['uncles'] = [] proveth_expected_block_format_dictCharlie['transactions'] = ({ "blockHash": commit_block_objectCharlie.hash, "blockNumber": str(hex((commit_block_objectCharlie['number']))), "from": checksum_encode(CHARLIE_ADDRESS), "gas": str(hex(commit_tx_objectCharlie['startgas'])), "gasPrice": str(hex(commit_tx_objectCharlie['gasprice'])), "hash": rec_hex(commit_tx_objectCharlie['hash']), "input": rec_hex(commit_tx_objectCharlie['data']), "nonce": str(hex(commit_tx_objectCharlie['nonce'])), "to": checksum_encode(commit_tx_objectCharlie['to']), "transactionIndex": str(hex(0)), "value": str(hex(commit_tx_objectCharlie['value'])), "v": str(hex(commit_tx_objectCharlie['v'])), "r": str(hex(commit_tx_objectCharlie['r'])), "s": str(hex(commit_tx_objectCharlie['s'])) }, ) commit_proof_blobCharlie = proveth.generate_proof_blob( proveth_expected_block_format_dictCharlie, commit_block_indexCharlie) _unlockExtraData = b'' # In this example we dont have any extra embedded data as part of the unlock TX unlock_tx_unsigned_objectCharlie = transactions.UnsignedTransaction( int.from_bytes(unlock_tx_infoCharlie[0], byteorder="big"), # nonce; int.from_bytes(unlock_tx_infoCharlie[1], byteorder="big"), # gasprice int.from_bytes(unlock_tx_infoCharlie[2], byteorder="big"), # startgas unlock_tx_infoCharlie[3], # to addr int.from_bytes(unlock_tx_infoCharlie[4], byteorder="big"), # value unlock_tx_infoCharlie[5], # data ) unlock_tx_unsigned_rlpCharlie = rlp.encode(unlock_tx_unsigned_objectCharlie, transactions.UnsignedTransaction) self.auction_contract.reveal( commit_block_numberCharlie, # uint32 _commitBlockNumber, _unlockExtraData, # bytes _commitData, rec_bin(witnessCharlie), # bytes32 _witness, unlock_tx_unsigned_rlpCharlie, # bytes _rlpUnlockTxUnsigned, commit_proof_blobCharlie, # bytes _proofBlob sender=CHARLIE_PRIVATE_KEY) reveal_gasCharlie = int(self.chain.head_state.gas_used) self.chain.mine(1) ## ## CHECK THE STATE AFTER REVEAL ## bidRecordAlice = self.auction_contract.bidders(rec_bin(commitAlice)) self.assertEqual(rec_hex(ALICE_ADDRESS), bidRecordAlice) session_dataAlice = self.auction_contract.getSubmarineState(rec_bin(commitAlice)) self.assertListEqual(session_dataAlice, [BID_AMOUNT_Alice, SOLIDITY_NULL_INITIALVAL, commit_block_numberAlice, commit_block_indexAlice]) revealedAndUnlocked_boolAlice = self.auction_contract.revealedAndUnlocked(rec_bin(commitAlice)) self.assertFalse(revealedAndUnlocked_boolAlice) bidRecordBob = self.auction_contract.bidders(rec_bin(commitBob)) self.assertEqual(rec_hex(BOB_ADDRESS), bidRecordBob) session_dataBob = self.auction_contract.getSubmarineState(rec_bin(commitBob)) self.assertListEqual(session_dataBob, [BID_AMOUNT_Bob, SOLIDITY_NULL_INITIALVAL, commit_block_numberBob, commit_block_indexBob]) revealedAndUnlocked_boolBob = self.auction_contract.revealedAndUnlocked(rec_bin(commitBob)) self.assertFalse(revealedAndUnlocked_boolBob) bidRecordCharlie = self.auction_contract.bidders(rec_bin(commitCharlie)) self.assertEqual(rec_hex(CHARLIE_ADDRESS), bidRecordCharlie) session_dataCharlie = self.auction_contract.getSubmarineState(rec_bin(commitCharlie)) self.assertListEqual(session_dataCharlie, [BID_AMOUNT_Charlie, SOLIDITY_NULL_INITIALVAL, commit_block_numberCharlie, commit_block_indexCharlie]) revealedAndUnlocked_boolCharlie = self.auction_contract.revealedAndUnlocked(rec_bin(commitCharlie)) self.assertFalse(revealedAndUnlocked_boolCharlie) ## ## BROADCAST UNLOCK ## self.chain.mine(1) self.chain.direct_tx(unlock_tx_objectAlice) unlock_gasAlice = int(self.chain.head_state.gas_used) self.chain.mine(1) self.chain.mine(1) self.chain.direct_tx(unlock_tx_objectBob) unlock_gasBob = int(self.chain.head_state.gas_used) self.chain.mine(1) self.chain.mine(1) self.chain.direct_tx(unlock_tx_objectCharlie) unlock_gasCharlie = int(self.chain.head_state.gas_used) self.chain.mine(1) ## ## CHECK STATE AFTER UNLOCK ## # # stuff to help with debugging # # unlock_block_numberAlice, unlock_block_indexAlice = self.chain.chain.get_tx_position( # # unlock_tx_objectAlice) # # unlock_block_objectAlice = self.chain.chain.get_block_by_number(unlock_block_numberAlice) # # print(unlock_block_objectAlice.as_dict()) self.assertEqual( self.chain.head_state.get_balance(commitAddressAlice), (extraTransactionFees - unlock_gasAlice*OURGASPRICE), "Commit address should send along the money and have almost 0 money left." ) self.assertEqual( self.chain.head_state.get_balance(commitAddressBob), (extraTransactionFees - unlock_gasBob*OURGASPRICE), "Commit address should send along the money and have almost 0 money left." ) self.assertEqual( self.chain.head_state.get_balance(commitAddressCharlie), (extraTransactionFees - unlock_gasCharlie*OURGASPRICE), "Commit address should send along the money and have almost 0 money left." ) self.assertEqual( self.chain.head_state.get_balance(self.auction_contract.address), (BID_AMOUNT_Alice + BID_AMOUNT_Bob + BID_AMOUNT_Charlie), "Contract address should have the sum of the bids balance." ) session_dataAlice = self.auction_contract.getSubmarineState(rec_bin(commitAlice)) self.assertListEqual(session_dataAlice, [BID_AMOUNT_Alice, BID_AMOUNT_Alice, commit_block_numberAlice, commit_block_indexAlice]) revealedAndUnlocked_boolAlice = self.auction_contract.revealedAndUnlocked(rec_bin(commitAlice)) self.assertTrue(revealedAndUnlocked_boolAlice) session_dataBob = self.auction_contract.getSubmarineState(rec_bin(commitBob)) self.assertListEqual(session_dataBob, [BID_AMOUNT_Bob, BID_AMOUNT_Bob, commit_block_numberBob, commit_block_indexBob]) revealedAndUnlocked_boolBob = self.auction_contract.revealedAndUnlocked(rec_bin(commitBob)) self.assertTrue(revealedAndUnlocked_boolBob) session_dataCharlie = self.auction_contract.getSubmarineState(rec_bin(commitCharlie)) self.assertListEqual(session_dataCharlie, [BID_AMOUNT_Charlie, BID_AMOUNT_Charlie, commit_block_numberCharlie, commit_block_indexCharlie]) revealedAndUnlocked_boolCharlie = self.auction_contract.revealedAndUnlocked(rec_bin(commitCharlie)) self.assertTrue(revealedAndUnlocked_boolCharlie) ## ## END AUCTION ## self.chain.mine(REVEAL_PERIOD_LENGTH) self.auction_contract.finalize(rec_bin(commitAlice), sender=ALICE_PRIVATE_KEY) self.auction_contract.finalize(rec_bin(commitBob), sender=BOB_PRIVATE_KEY) self.auction_contract.finalize(rec_bin(commitCharlie), sender=CHARLIE_PRIVATE_KEY) # ## # ## CHECK STATE NOW THAT AUCTION IS OVER self.assertEqual(commitCharlie, self.auction_contract.winningSubmarineId().hex()) self.assertEqual( ACCOUNT_STARTING_BALANCE - (extraTransactionFees + BASIC_SEND_GAS_LIMIT * OURGASPRICE), self.chain.head_state.get_balance(rec_hex(ALICE_ADDRESS))) self.assertEqual( ACCOUNT_STARTING_BALANCE - (extraTransactionFees + BASIC_SEND_GAS_LIMIT * OURGASPRICE), self.chain.head_state.get_balance(rec_hex(BOB_ADDRESS))) self.assertEqual( ACCOUNT_STARTING_BALANCE - (BID_AMOUNT_Charlie + extraTransactionFees + BASIC_SEND_GAS_LIMIT * OURGASPRICE), self.chain.head_state.get_balance(rec_hex(CHARLIE_ADDRESS))) self.assertEqual(starting_owner_eth_holdings + BID_AMOUNT_Charlie, self.chain.head_state.get_balance(rec_hex(CONTRACT_OWNER_ADDRESS)))
def ethhash2(self): op1 = self.stack.pop() op2 = self.stack.pop() res = keccak(encode_single_packed("(uint256,uint256)", [op1, op2])) self.stack.push(big_endian_to_int(res))