コード例 #1
0
    def test_ExchangeWorkflowBuyTokensWithEth(self):
        ##
        ## STARTING STATE
        ##
        self.chain.mine(1)
        self.assertEqual(TOTAL_TOKEN_SUPPLY - TOKEN_AMOUNT_STARTING - BOB_STARTING_TOKEN_AMOUNT, self.token_contract.balanceOf(CONTRACT_OWNER_ADDRESS))
        self.assertEqual(TOKEN_AMOUNT_STARTING, self.token_contract.balanceOf(self.exchange_contract.address))
        self.assertEqual(ACCOUNT_STARTING_BALANCE - ETH_AMOUNT_STARTING, self.chain.head_state.get_balance(rec_hex(CONTRACT_OWNER_ADDRESS)))
        self.assertEqual(ACCOUNT_STARTING_BALANCE, self.chain.head_state.get_balance(rec_hex(ALICE_ADDRESS)))
        self.assertEqual(ETH_AMOUNT_STARTING, self.chain.head_state.get_balance(rec_hex(self.exchange_contract.address)))
        self.assertEqual(BOB_STARTING_TOKEN_AMOUNT, self.token_contract.balanceOf(BOB_ADDRESS))
        self.assertEqual(0, self.token_contract.balanceOf(ALICE_ADDRESS))
        self.assertEqual(ETH_AMOUNT_STARTING, self.exchange_contract.ethPool())
        self.assertEqual(TOKEN_AMOUNT_STARTING, self.exchange_contract.tokenPool())
        self.assertEqual(ETH_AMOUNT_STARTING * TOKEN_AMOUNT_STARTING, self.exchange_contract.invariant())
        currentInvariant = ETH_AMOUNT_STARTING * TOKEN_AMOUNT_STARTING
        self.assertEqual(COMMIT_PERIOD_LENGTH, self.exchange_contract.commitPeriodLength())

        ##
        ## ALICE BUYS TOKENS WITH ETH
        ##
        commitAddressAlice, commitAlice, witnessAlice, unlock_tx_hexAlice = generate_submarine_commit.generateCommitAddress(
             normalize_address(rec_hex(ALICE_ADDRESS)),
             normalize_address(rec_hex(self.exchange_contract.address)),
             ALICE_TRADE_AMOUNT, 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
        )

        commit_tx_objectAlice = transactions.Transaction(
            0, OURGASPRICE, BASIC_SEND_GAS_LIMIT, rec_bin(commitAddressAlice),
            (ALICE_TRADE_AMOUNT + extraTransactionFees),
            b'').sign(ALICE_PRIVATE_KEY)

        self.chain.direct_tx(commit_tx_objectAlice)
        commit_gasAlice = int(self.chain.head_state.gas_used)
        self.chain.mine(1)

        commit_block_numberAlice, commit_block_indexAlice = self.chain.chain.get_tx_position(
            commit_tx_objectAlice)
        self.assertEqual(ALICE_TRADE_AMOUNT + extraTransactionFees,
                         self.chain.head_state.get_balance(commitAddressAlice))
        self.assertEqual(
            ACCOUNT_STARTING_BALANCE - (ALICE_TRADE_AMOUNT + extraTransactionFees +
                                        BASIC_SEND_GAS_LIMIT * OURGASPRICE),
            self.chain.head_state.get_balance(rec_hex(ALICE_ADDRESS)))

        session_dataAlice = self.exchange_contract.getSubmarineState(rec_bin(commitAlice))
        self.assertListEqual(session_dataAlice,
                [SOLIDITY_NULL_INITIALVAL, SOLIDITY_NULL_INITIALVAL, SOLIDITY_NULL_INITIALVAL, SOLIDITY_NULL_INITIALVAL])

        finished_boolAlice = self.exchange_contract.revealedAndUnlocked(rec_bin(commitAlice))
        self.assertFalse(
            finished_boolAlice,
            "The contract should not be finished before it's even begun.")


        ##
        ## GENERATE AND BROADCAST REVEAL BID TXS
        ##
        self.chain.mine(COMMIT_PERIOD_LENGTH)

        proveth_commit_blockAlice = proveth_compatible_commit_block(
            self.chain.chain.get_block_by_number(commit_block_numberAlice),
            commit_tx_objectAlice,
        )
        commit_proof_blobAlice = proveth.generate_proof_blob(
            proveth_commit_blockAlice, 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.chain.mine(5)
        self.exchange_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,
            gasprice=OURGASPRICE)
        reveal_gasAlice = int(self.chain.head_state.gas_used)

        ##
        ## BROADCAST UNLOCK
        ##
        self.chain.mine(1)
        self.chain.direct_tx(unlock_tx_objectAlice)
        self.chain.mine(1)

        ##
        ## Call the actual ethToTokenSwap function
        ##
        self.exchange_contract.ethToTokenSwap(rec_bin(commitAlice), sender=ALICE_PRIVATE_KEY, gasprice=OURGASPRICE)
        swapcall_gasAlice = int(self.chain.head_state.gas_used)
        self.chain.mine(1)

        # 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())
        # print(unlock_block_objectAlice.as_dict()['transactions'][0].as_dict())
        # print(unlock_block_objectAlice.as_dict()['header'].as_dict())

        ##
        ## CHECK STATE AFTER TOKEN PURCHASE
        ##
        self.assertEqual(ETH_AMOUNT_STARTING+ALICE_TRADE_AMOUNT, self.exchange_contract.ethPool())
        self.assertEqual(ETH_AMOUNT_STARTING+ALICE_TRADE_AMOUNT, self.chain.head_state.get_balance(rec_hex(self.exchange_contract.address)))
        self.assertEqual(ACCOUNT_STARTING_BALANCE - ALICE_TRADE_AMOUNT - (OURGASPRICE*(commit_gasAlice + reveal_gasAlice + swapcall_gasAlice)) - extraTransactionFees, self.chain.head_state.get_balance(rec_hex(ALICE_ADDRESS)))
        tokens_out = int(TOKEN_AMOUNT_STARTING - (currentInvariant //(ETH_AMOUNT_STARTING + ALICE_TRADE_AMOUNT))) # // floor division
        self.assertEqual(tokens_out, self.token_contract.balanceOf(ALICE_ADDRESS))
        self.assertEqual(TOKEN_AMOUNT_STARTING - tokens_out, self.token_contract.balanceOf(self.exchange_contract.address))
        self.assertEqual(TOKEN_AMOUNT_STARTING - tokens_out, self.exchange_contract.tokenPool())
コード例 #2
0
    def test_spam_unlock_large_spam(self):
        ##
        ## STARTING STATE
        ##
        ALICE_ADDRESS = t.a1
        ALICE_PRIVATE_KEY = t.k1
        SPAM_PRIVATE_KEY_MALLORY = t.k7


        self.chain.mine(1)

        ##
        ## GENERATE UNLOCK TX
        ##
        addressB, commit, witness, unlock_tx_hex = generate_submarine_commit.generateCommitAddress(
            normalize_address(rec_hex(ALICE_ADDRESS)),
            normalize_address(rec_hex(self.verifier_contract.address)),
            UNLOCK_AMOUNT, b'', OURGASPRICE, OURGASLIMIT)

        unlock_tx_info = rlp.decode(rec_bin(unlock_tx_hex))

        unlock_tx_object = transactions.Transaction(
            int.from_bytes(unlock_tx_info[0], byteorder="big"),  # nonce;
            int.from_bytes(unlock_tx_info[1], byteorder="big"),  # gasprice
            int.from_bytes(unlock_tx_info[2], byteorder="big"),  # startgas
            unlock_tx_info[3],                                   # to addr
            int.from_bytes(unlock_tx_info[4], byteorder="big"),  # value
            unlock_tx_info[5],                                   # data
            int.from_bytes(unlock_tx_info[6], byteorder="big"),  # v
            int.from_bytes(unlock_tx_info[7], byteorder="big"),  # r
            int.from_bytes(unlock_tx_info[8], byteorder="big")   # s
        )
        unlock_tx_unsigned_object = transactions.UnsignedTransaction(
            int.from_bytes(unlock_tx_info[0], byteorder="big"),  # nonce;
            int.from_bytes(unlock_tx_info[1], byteorder="big"),  # gasprice
            int.from_bytes(unlock_tx_info[2], byteorder="big"),  # startgas
            unlock_tx_info[3],  # to addr
            int.from_bytes(unlock_tx_info[4], byteorder="big"),  # value
            unlock_tx_info[5],  # data
        )

        unlock_tx_unsigned_rlp = rlp.encode(unlock_tx_unsigned_object, transactions.UnsignedTransaction)



        ##
        ## SPAM THE UNLOCK FUNCTION
        ##
        SPAM_AMOUNT = UNLOCK_AMOUNT + 3235
        spam_tx_object = transactions.Transaction(
            0,
            OURGASPRICE,
            OURGASLIMIT,
            normalize_address(rec_hex(self.verifier_contract.address)),
            SPAM_AMOUNT,
            unlock_tx_object[5]).sign(SPAM_PRIVATE_KEY_MALLORY)

        self.chain.direct_tx(spam_tx_object)
        session_data = self.verifier_contract.getSubmarineState(rec_bin(commit))
        self.assertListEqual(session_data, [SOLIDITY_NULL_INITIALVAL, SPAM_AMOUNT, SOLIDITY_NULL_INITIALVAL, SOLIDITY_NULL_INITIALVAL])
        self.chain.mine(1)

        ##
        ## GENERATE COMMIT
        ##
        commit_tx_object = transactions.Transaction(
            0, OURGASPRICE, BASIC_SEND_GAS_LIMIT, rec_bin(addressB),
            (UNLOCK_AMOUNT + extraTransactionFees),
            b'').sign(ALICE_PRIVATE_KEY)

        self.chain.direct_tx(commit_tx_object)

        self.chain.mine(4)

        session_data = self.verifier_contract.getSubmarineState(rec_bin(commit))
        self.assertListEqual(session_data, [SOLIDITY_NULL_INITIALVAL, SPAM_AMOUNT, SOLIDITY_NULL_INITIALVAL, SOLIDITY_NULL_INITIALVAL])

        finished_bool = self.verifier_contract.revealedAndUnlocked(rec_bin(commit))
        self.assertFalse(
            finished_bool,
            "The contract should not be finished until after the reveal.")

        commit_block_number, commit_block_index = self.chain.chain.get_tx_position(commit_tx_object)

        ##
        ## BROADCAST UNLOCK (this should cause an exception since someone else donated money to your cause)
        ##
        with self.assertRaises(t.TransactionFailed):
            self.chain.direct_tx(unlock_tx_object)

        ##
        ## CHECK STATE AFTER UNLOCK
        ##
        session_data = self.verifier_contract.getSubmarineState(rec_bin(commit))
        self.assertListEqual(
            session_data, [SOLIDITY_NULL_INITIALVAL, SPAM_AMOUNT, SOLIDITY_NULL_INITIALVAL, SOLIDITY_NULL_INITIALVAL],
            "State does not match expected value after unlock.")

        finished_bool = self.verifier_contract.revealedAndUnlocked(rec_bin(commit))
        self.assertFalse(finished_bool)

        ##
        ## GENERATE AND BROADCAST REVEAL TX
        ##
        assert (isinstance(witness, str))
        commit_block_object = self.chain.chain.get_block_by_number(
            commit_block_number)
        log.info("Block information: {}".format(
            str(commit_block_object.as_dict())))
        log.info("Block header: {}".format(
            str(commit_block_object.as_dict()['header'].as_dict())))
        log.info("Block transactions: {}".format(
            str(commit_block_object.as_dict()['transactions'][0].as_dict())))

        proveth_commit_block = proveth_compatible_commit_block(commit_block_object, commit_tx_object)
        commit_proof_blob = proveth.generate_proof_blob(
            proveth_commit_block, commit_block_index)
        log.info("Proof Blob generate by proveth.py: {}".format(
            rec_hex(commit_proof_blob)))

        # Solidity Event log listener
        def _event_listener(llog):
            log.info('Solidity Event listener log fire: {}'.format(str(llog)))
            log.info('Solidity Event listener log fire hex: {}'.format(
                str(rec_hex(llog['data']))))

        self.chain.head_state.log_listeners.append(_event_listener)
        _unlockExtraData = b''  # In this example we dont have any extra embedded data as part of the unlock TX

        self.chain.mine(20)
        self.verifier_contract.reveal(
            #print(
            commit_block_number,  # uint32 _commitBlockNumber,
            _unlockExtraData,  # bytes _commitData,
            rec_bin(witness),  # bytes32 _witness,
            unlock_tx_unsigned_rlp,  # bytes _rlpUnlockTxUnsigned,
            commit_proof_blob,  # bytes _proofBlob
            sender=ALICE_PRIVATE_KEY)

        log.info("Reveal TX Gas Used HeadState {}".format(
            self.chain.head_state.gas_used))
        reveal_gas = int(self.chain.head_state.gas_used)

        self.chain.mine(1)

        ##
        ## CHECK STATE AFTER REVEAL TX
        ##
        session_data = self.verifier_contract.getSubmarineState(rec_bin(commit))
        self.assertListEqual(
            session_data, [UNLOCK_AMOUNT, SPAM_AMOUNT, commit_block_number, commit_block_index],
            "After the Reveal, the state should report both revealed and unlocked."
        )
        finished_bool = self.verifier_contract.revealedAndUnlocked(rec_bin(commit))
        self.assertTrue(
            finished_bool,
            "The contract was unlocked first and then revealed, it should be finished"
        )
コード例 #3
0
    def test_fake_unlock_commit_does_not_match_to_address(self):
        ##
        ## STARTING STATE
        ##
        ALICE_ADDRESS = t.a1
        ALICE_PRIVATE_KEY = t.k1
        MALICIOUS_ADDRESS = t.a7

        self.chain.mine(1)

        ##
        ## GENERATE FAKE UNLOCK TX
        ##
        unlock_tx_object, unlock_tx_unsigned_object, commit_addr, commit, witness = self.generateInvalidUnlockTx(ALICE_ADDRESS, self.verifier_contract.address, MALICIOUS_ADDRESS)
        unlock_tx_unsigned_rlp = rlp.encode(unlock_tx_unsigned_object, transactions.UnsignedTransaction)

        ##
        ## GENERATE COMMIT
        ##
        commit_tx_object = transactions.Transaction(
            0, OURGASPRICE, BASIC_SEND_GAS_LIMIT, commit_addr,
            (UNLOCK_AMOUNT + extraTransactionFees),
            b'').sign(ALICE_PRIVATE_KEY)

        self.chain.direct_tx(commit_tx_object)

        self.chain.mine(4)

        commit_block_number, commit_block_index = self.chain.chain.get_tx_position(commit_tx_object)
        log.info("Commit Tx block number {} and tx block index {}".format(
            commit_block_number, commit_block_index))
        log.info("State: After commit A1 has {} and has address {}".format(
            self.chain.head_state.get_balance(rec_hex(ALICE_ADDRESS)),
            rec_hex(ALICE_ADDRESS)))
        log.info("State: After commit B has {} and has address {}".format(
            self.chain.head_state.get_balance(commit_addr), commit_addr))
        log.info("State: After commit C has {} and has address {}".format(
            self.chain.head_state.get_balance(MALICIOUS_ADDRESS), MALICIOUS_ADDRESS))
        afterCommitCommitAddressAmount = UNLOCK_AMOUNT + extraTransactionFees
        afterCommitAliceAddressAmount = ACCOUNT_STARTING_BALANCE - (UNLOCK_AMOUNT + extraTransactionFees + BASIC_SEND_GAS_LIMIT * OURGASPRICE)
        self.assertEqual(afterCommitCommitAddressAmount,
                         self.chain.head_state.get_balance(commit_addr))
        self.assertEqual(afterCommitAliceAddressAmount,
            self.chain.head_state.get_balance(rec_hex(ALICE_ADDRESS)))

        ##
        ## GENERATE AND BROADCAST REVEAL TX
        ##
        commit_block_object = self.chain.chain.get_block_by_number(
            commit_block_number)
        log.info("Block information: {}".format(
            str(commit_block_object.as_dict())))
        log.info("Block header: {}".format(
            str(commit_block_object.as_dict()['header'].as_dict())))
        log.info("Block transactions: {}".format(
            str(commit_block_object.as_dict()['transactions'][0].as_dict())))

        proveth_commit_block = proveth_compatible_commit_block(commit_block_object, commit_tx_object)
        commit_proof_blob = proveth.generate_proof_blob(
            proveth_commit_block, commit_block_index)
        log.info("Proof Blob generate by proveth.py: {}".format(
            rec_hex(commit_proof_blob)))

        # Solidity Event log listener
        def _event_listener(llog):
            log.info('Solidity Event listener log fire: {}'.format(str(llog)))
            log.info('Solidity Event listener log fire hex: {}'.format(
                str(rec_hex(llog['data']))))

        self.chain.head_state.log_listeners.append(_event_listener)
        _unlockExtraData = b''  # In this example we dont have any extra embedded data as part of the unlock TX


        self.chain.direct_tx(unlock_tx_object)

        log.info("State: After unlock A1 has {} and has address {}".format(
            self.chain.head_state.get_balance(rec_hex(ALICE_ADDRESS)),
            rec_hex(ALICE_ADDRESS)))
        log.info("State: After unlock B has {} and has address {}".format(
            self.chain.head_state.get_balance(commit_addr), commit_addr))
        log.info("State: After unlock C has {} and has address {}".format(
            self.chain.head_state.get_balance(MALICIOUS_ADDRESS), MALICIOUS_ADDRESS))
        self.assertLess(self.chain.head_state.get_balance(commit_addr), afterCommitCommitAddressAmount)
        self.assertGreater(self.chain.head_state.get_balance(rec_hex(MALICIOUS_ADDRESS)), ACCOUNT_STARTING_BALANCE)

        self.chain.mine(20)
        ##
        ## THE REVEAL SHOULD NOW FAIL
        ##
        with self.assertRaises(t.TransactionFailed):
            self.verifier_contract.reveal(
                commit_block_number,  # uint32 _commitBlockNumber,
                _unlockExtraData,  # bytes _commitData,
                witness,  # bytes32 _witness,
                unlock_tx_unsigned_rlp,  # bytes _rlpUnlockTxUnsigned,
                commit_proof_blob,  # bytes _proofBlob
                sender=ALICE_PRIVATE_KEY
            )
コード例 #4
0
    def test_workflow(self):
        ##
        ## STARTING STATE
        ##
        ALICE_ADDRESS = t.a1
        ALICE_PRIVATE_KEY = t.k1

        log.info("Contract Address: {}".format(
            rec_hex(self.verifier_contract.address)))
        log.info("State: Starting A1 has {} and has address {}".format(
            self.chain.head_state.get_balance(rec_hex(ALICE_ADDRESS)),
            rec_hex(ALICE_ADDRESS)))

        self.chain.mine(1)

        ##
        ## GENERATE UNLOCK AND BROADCAST TX, THEN BROADCAST JUST COMMIT TX
        ##
        addressB, commit, witness, unlock_tx_hex = generate_submarine_commit.generateCommitAddress(
            normalize_address(rec_hex(ALICE_ADDRESS)),
            normalize_address(rec_hex(self.verifier_contract.address)),
            UNLOCK_AMOUNT, b'', OURGASPRICE, OURGASLIMIT)
        log.info("Precomputed address of commit target: {}".format(addressB))

        assert (isinstance(witness, str))

        unlock_tx_info = rlp.decode(rec_bin(unlock_tx_hex))
        log.info("Unlock tx hex object: {}".format(rec_hex(unlock_tx_info)))

        unlock_tx_object = transactions.Transaction(
            int.from_bytes(unlock_tx_info[0], byteorder="big"),  # nonce;
            int.from_bytes(unlock_tx_info[1], byteorder="big"),  # gasprice
            int.from_bytes(unlock_tx_info[2], byteorder="big"),  # startgas
            unlock_tx_info[3],  # to addr
            int.from_bytes(unlock_tx_info[4], byteorder="big"),  # value
            unlock_tx_info[5],  # data
            int.from_bytes(unlock_tx_info[6], byteorder="big"),  # v
            int.from_bytes(unlock_tx_info[7], byteorder="big"),  # r
            int.from_bytes(unlock_tx_info[8], byteorder="big")  # s
        )
        log.info("Unlock tx hash: {}".format(rec_hex(unlock_tx_object.hash)))
        unlock_tx_unsigned_object = transactions.UnsignedTransaction(
            int.from_bytes(unlock_tx_info[0], byteorder="big"),  # nonce;
            int.from_bytes(unlock_tx_info[1], byteorder="big"),  # gasprice
            int.from_bytes(unlock_tx_info[2], byteorder="big"),  # startgas
            unlock_tx_info[3],  # to addr
            int.from_bytes(unlock_tx_info[4], byteorder="big"),  # value
            unlock_tx_info[5],  # data
        )

        unlock_tx_unsigned_rlp = rlp.encode(unlock_tx_unsigned_object, transactions.UnsignedTransaction)

        commit_tx_object = transactions.Transaction(
            0, OURGASPRICE, BASIC_SEND_GAS_LIMIT, rec_bin(addressB),
            (UNLOCK_AMOUNT + extraTransactionFees),
            b'').sign(ALICE_PRIVATE_KEY)
        log.info("Commit TX Object: {}".format(
            str(commit_tx_object.to_dict())))
        log.info("Commit TX gas used Intrinsic: {}".format(
            str(commit_tx_object.intrinsic_gas_used)))
        commit_gas = int(self.chain.head_state.gas_used)

        self.chain.direct_tx(commit_tx_object)
        log.info("Commit TX Gas Used HeadState {}".format(
            self.chain.head_state.gas_used))
        self.chain.mine(1)


        ##
        ## CHECK STATE AFTER COMMIT TX
        ##
        commit_block_number, commit_block_index = self.chain.chain.get_tx_position(
            commit_tx_object)
        log.info("Commit Tx block number {} and tx block index {}".format(
            commit_block_number, commit_block_index))
        log.info("State: After commit A1 has {} and has address {}".format(
            self.chain.head_state.get_balance(rec_hex(ALICE_ADDRESS)),
            rec_hex(ALICE_ADDRESS)))
        log.info("State: After commit B has {} and has address {}".format(
            self.chain.head_state.get_balance(addressB), addressB))
        self.assertEqual(UNLOCK_AMOUNT + extraTransactionFees,
                         self.chain.head_state.get_balance(addressB))
        self.assertEqual(
            ACCOUNT_STARTING_BALANCE - (UNLOCK_AMOUNT + extraTransactionFees +
                                        BASIC_SEND_GAS_LIMIT * OURGASPRICE),
            self.chain.head_state.get_balance(rec_hex(ALICE_ADDRESS)))

        session_data = self.verifier_contract.getSubmarineState(rec_bin(commit))
        self.assertListEqual(
            session_data, [SOLIDITY_NULL_INITIALVAL, SOLIDITY_NULL_INITIALVAL, SOLIDITY_NULL_INITIALVAL, SOLIDITY_NULL_INITIALVAL],
            "The contract should not know anything about the commit until after it's been revealed... "
        )

        finished_bool = self.verifier_contract.revealedAndUnlocked(rec_bin(commit))
        self.assertFalse(
            finished_bool,
            "The contract should not be finished before it's even begun.")

        ##
        ## GENERATE AND BROADCAST REVEAL TX
        ##
        commit_block_object = self.chain.chain.get_block_by_number(
            commit_block_number)
        log.info("Block information: {}".format(
            str(commit_block_object.as_dict())))
        log.info("Block header: {}".format(
            str(commit_block_object.as_dict()['header'].as_dict())))
        log.info("Block transactions: {}".format(
            str(commit_block_object.as_dict()['transactions'][0].as_dict())))

        proveth_commit_block = proveth_compatible_commit_block(commit_block_object, commit_tx_object)
        commit_proof_blob = proveth.generate_proof_blob(
            proveth_commit_block, commit_block_index)

        log.info("Proof Blob generate by proveth.py: {}".format(
            rec_hex(commit_proof_blob)))

        # Solidity Event log listener
        def _event_listener(llog):
            log.info('Solidity Event listener log fire: {}'.format(str(llog)))
            log.info('Solidity Event listener log fire hex: {}'.format(
                str(rec_hex(llog['data']))))

        self.chain.head_state.log_listeners.append(_event_listener)
        _unlockExtraData = b''  # In this example we dont have any extra embedded data as part of the unlock TX

        self.chain.mine(20)
        self.verifier_contract.reveal(
            #print(
            commit_block_number,  # uint32 _commitBlockNumber,
            _unlockExtraData,  # bytes _commitData,
            rec_bin(witness),  # bytes32 _witness,
            unlock_tx_unsigned_rlp,  # bytes _rlpUnlockTxUnsigned,
            commit_proof_blob,  # bytes _proofBlob
            sender=ALICE_PRIVATE_KEY)
        log.info("Reveal TX Gas Used HeadState {}".format(
            self.chain.head_state.gas_used))
        reveal_gas = int(self.chain.head_state.gas_used)

        self.chain.mine(1)

        ##
        ## CHECK STATE AFTER REVEAL TX
        ##
        session_data = self.verifier_contract.getSubmarineState(rec_bin(commit))
        self.assertListEqual(
            session_data, [UNLOCK_AMOUNT, SOLIDITY_NULL_INITIALVAL, commit_block_number, commit_block_index ],
            "After the Reveal, the state should report revealed but not unlocked."
        )
        finished_bool = self.verifier_contract.revealedAndUnlocked(rec_bin(commit))
        self.assertFalse(
            finished_bool,
            "The contract is only revealed, not unlocked and therefore finished."
        )

        ##
        ## BROADCAST UNLOCK
        ##
        self.chain.direct_tx(unlock_tx_object)
        log.info("Unlock TX Gas Used HeadState {}".format(
            self.chain.head_state.gas_used))
        unlock_gas = int(self.chain.head_state.gas_used)

        ##
        ## CHECK STATE AFTER UNLOCK
        ##
        log.info("State: After unlock B has {} and has address {}".format(
            self.chain.head_state.get_balance(addressB), addressB))

        self.assertLess(
            self.chain.head_state.get_balance(addressB),
            UNLOCK_AMOUNT + extraTransactionFees,
            "Address B should send along the money and have almost 0 money left."
        )
        self.assertEqual(
            999998562999979000000000,
            self.chain.head_state.get_balance(rec_hex(ALICE_ADDRESS)))

        session_data = self.verifier_contract.getSubmarineState(rec_bin(commit))
        self.assertListEqual(
            session_data, [UNLOCK_AMOUNT, UNLOCK_AMOUNT, commit_block_number, commit_block_index ],
            "State does not match expected value after unlock.")

        finished_bool = self.verifier_contract.revealedAndUnlocked(rec_bin(commit))
        self.assertTrue(finished_bool,
                        "After unlock, contract should be finished.")

        sumGas = commit_gas + reveal_gas + unlock_gas
        log.info("Final Gas Estimation {}".format(str(sumGas)))