예제 #1
0
    def tx(
            vm,
            from_,
            to,
            amount,
            private_key=None,
            gas_price=10,
            gas=100000,
            data=b''):

        if request.param:
            return new_transaction(
                vm,
                from_,
                to,
                amount,
                private_key,
                gas_price,
                gas,
                data)

        else:
            return new_transaction(
                vm,
                from_,
                to,
                amount,
                private_key=None,
                gas_price=gas_price,
                gas=gas,
                data=data)
예제 #2
0
def test_estimate_gas(chain, data, gas_estimator, to, on_pending, expected,
                      funded_address, funded_address_private_key,
                      should_sign_tx):
    if gas_estimator:
        chain.gas_estimator = gas_estimator
    vm = chain.get_vm()
    amount = 100
    from_ = funded_address

    tx_params = dict(vm=vm, from_=from_, to=to, amount=amount, data=data)

    # either make a signed or unsigned transaction
    if should_sign_tx:
        tx = new_transaction(private_key=funded_address_private_key,
                             **tx_params)
    else:
        tx = new_transaction(**tx_params)

    if on_pending:
        # estimate on *pending* block
        pending_header = chain.create_header_from_parent(
            chain.get_canonical_head())
        assert chain.estimate_gas(tx, pending_header) == expected
    else:
        # estimates on top of *latest* block
        assert chain.estimate_gas(tx) == expected
예제 #3
0
파일: test_vm.py 프로젝트: firefox0x/py-evm
def test_get_cumulative_gas_used(chain, funded_address, funded_address_private_key):
    vm = chain.get_vm()

    # Empty block.
    block = vm.mine_block()
    chain.import_block(block)
    block1 = chain.get_canonical_block_by_number(1)

    blockgas = vm.get_cumulative_gas_used(block1)

    assert blockgas == 0

    # Only one transaction in the block.
    recipient = decode_hex('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0c')
    amount = 100
    vm = chain.get_vm()
    from_ = funded_address
    tx = new_transaction(vm, from_, recipient, amount, funded_address_private_key)

    vm.apply_transaction(tx)
    block = vm.mine_block()
    chain.import_block(block)
    block2 = chain.get_canonical_block_by_number(2)

    blockgas = vm.get_cumulative_gas_used(block2)

    assert blockgas == constants.GAS_TX
예제 #4
0
파일: test_vm.py 프로젝트: firefox0x/py-evm
def test_apply_transaction(
        chain,
        funded_address,
        funded_address_private_key,
        funded_address_initial_balance):
    vm = chain.get_vm()
    tx_idx = len(vm.block.transactions)
    recipient = decode_hex('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0c')
    amount = 100
    from_ = funded_address
    tx = new_transaction(vm, from_, recipient, amount, funded_address_private_key)
    computation, _ = vm.apply_transaction(tx)
    access_logs = computation.vm_state.access_logs

    assert not computation.is_error
    tx_gas = tx.gas_price * constants.GAS_TX
    with vm.state.state_db(read_only=True) as state_db:
        assert state_db.get_balance(from_) == (
            funded_address_initial_balance - amount - tx_gas)
        assert state_db.get_balance(recipient) == amount
    block = vm.block
    assert block.transactions[tx_idx] == tx
    assert block.header.gas_used == constants.GAS_TX

    assert len(access_logs.reads) > 0
    assert len(access_logs.writes) > 0
예제 #5
0
파일: test_vm.py 프로젝트: skarafia/py-evm
def test_import_block(chain, funded_address, funded_address_private_key):
    recipient = decode_hex('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0c')
    amount = 100
    from_ = funded_address
    tx = new_transaction(chain.get_vm(), from_, recipient, amount,
                         funded_address_private_key)
    if isinstance(chain, MiningChain):
        # Can use the mining chain functionality to build transactions in-flight
        pending_header = chain.header
        new_block, _, computation = chain.apply_transaction(tx)
    else:
        # Have to manually build the block for the import_block test
        new_block, _, computations = chain.build_block_with_transactions([tx])
        computation = computations[0]

        # Generate the pending header to import the new block on
        pending_header = chain.create_header_from_parent(
            chain.get_canonical_head())

    assert not computation.is_error

    # import the built block
    validation_vm = chain.get_vm(pending_header)
    block = validation_vm.import_block(new_block)
    assert block.transactions == (tx, )
def test_building_block_incrementally_with_multiple_transactions(
        chain, funded_address, funded_address_private_key):
    txns = []
    head_hash = chain.get_canonical_head().hash
    for expected_len in range(1, 4):
        tx = new_transaction(
            chain.get_vm(),
            from_=funded_address,
            to=ADDRESS_1010,
            private_key=funded_address_private_key,
        )
        txns.append(tx)
        _, _, computation = chain.apply_transaction(tx)
        assert computation.is_success

        # test that the pending block has the expected number of transactions
        vm = chain.get_vm()
        assert len(vm.block.transactions) == expected_len
        assert vm.block.transactions[-1] == tx

        # test that the *latest* block hasn't changed
        assert chain.get_canonical_head().hash == head_hash

    mined_block = chain.mine_block()
    assert len(mined_block.transactions) == 3

    for expected, actual in zip(txns, mined_block.transactions):
        assert expected == actual
예제 #7
0
def tx(chain, funded_address, funded_address_private_key):
    recipient = decode_hex('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0c')
    amount = 100
    vm = chain.get_vm()
    from_ = funded_address
    return new_transaction(vm, from_, recipient, amount,
                           funded_address_private_key)
예제 #8
0
파일: test_vm.py 프로젝트: thomaslu3/py-evm
def test_get_cumulative_gas_used(chain):
    vm = chain.get_vm()

    # Empty block.
    block = vm.mine_block()
    chain.import_block(block)
    block1 = chain.get_canonical_block_by_number(1)

    blockgas = vm.get_cumulative_gas_used(block1)

    assert blockgas == 0

    # Only one transaction in the block.
    recipient = decode_hex('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0c')
    amount = 100
    vm = chain.get_vm()
    from_ = chain.funded_address
    tx = new_transaction(vm, from_, recipient, amount,
                         chain.funded_address_private_key)

    vm.apply_transaction(tx)
    block = vm.mine_block()
    chain.import_block(block)
    block2 = chain.get_canonical_block_by_number(2)

    blockgas = vm.get_cumulative_gas_used(block2)

    assert blockgas == constants.GAS_TX
예제 #9
0
def test_estimate_gas(
        chain,
        data,
        gas_estimator,
        to,
        on_pending,
        expected,
        funded_address,
        funded_address_private_key):
    if gas_estimator:
        chain.gas_estimator = gas_estimator
    vm = chain.get_vm()
    if to:
        recipient = to
    else:
        recipient = decode_hex('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0c')
    amount = 100
    from_ = funded_address
    tx = new_transaction(vm, from_, recipient, amount, funded_address_private_key, data=data)
    if on_pending:
        # estimate on *pending* block
        assert chain.estimate_gas(tx, chain.header) == expected
    else:
        # estimates on top of *latest* block
        assert chain.estimate_gas(tx) == expected
예제 #10
0
 def mk_estimation_txn(chain, from_, from_key, data):
     vm = chain.get_vm()
     tx_params = dict(from_=from_,
                      to=ADDR_1010,
                      amount=200,
                      private_key=from_key,
                      gas=chain.header.gas_limit,
                      data=data)
     return new_transaction(vm, **tx_params)
예제 #11
0
파일: test_vm.py 프로젝트: firefox0x/py-evm
def test_import_block(chain, funded_address, funded_address_private_key):
    vm = chain.get_vm()
    recipient = decode_hex('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0c')
    amount = 100
    from_ = funded_address
    tx = new_transaction(vm, from_, recipient, amount, funded_address_private_key)
    computation, _ = vm.apply_transaction(tx)

    assert not computation.is_error
    parent_vm = chain.get_chain_at_block_parent(vm.block).get_vm()
    block = parent_vm.import_block(vm.block)
    assert block.transactions == [tx]
예제 #12
0
파일: test_vm.py 프로젝트: ycdk/py-evm
def test_import_block(chain_without_block_validation):  # noqa: F811
    chain = chain_without_block_validation  # noqa: F811
    vm = chain.get_vm()
    recipient = decode_hex('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0c')
    amount = 100
    from_ = chain.funded_address
    tx = new_transaction(vm, from_, recipient, amount, chain.funded_address_private_key)
    computation = vm.apply_transaction(tx)
    assert not computation.is_error
    parent_vm = chain.get_chain_at_block_parent(vm.block).get_vm()
    block = parent_vm.import_block(vm.block)
    assert block.transactions == [tx]
예제 #13
0
 def estimation_txn(chain, from_, from_key, data):
     to = decode_hex('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0c')
     gas = chain.header.gas_limit
     amount = 200
     vm = chain.get_vm()
     return new_transaction(vm,
                            from_,
                            to,
                            amount,
                            from_key,
                            gas=gas,
                            data=data)
예제 #14
0
def test_import_block(chain, funded_address, funded_address_private_key):
    recipient = decode_hex('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0c')
    amount = 100
    from_ = funded_address
    tx = new_transaction(chain.get_vm(), from_, recipient, amount,
                         funded_address_private_key)
    new_block, _, computation = chain.apply_transaction(tx)

    assert not computation.is_error
    parent_vm = chain.get_chain_at_block_parent(new_block).get_vm()
    block = parent_vm.import_block(new_block)
    assert block.transactions == (tx, )
예제 #15
0
def test_missing_state_root(chain_without_block_validation, funded_address):
    valid_vm = chain_without_block_validation.get_vm()
    tx = new_transaction(valid_vm, from_=funded_address, to=ADDRESS)

    head = chain_without_block_validation.get_canonical_head()
    header_with_bad_state_root = head.copy(state_root=b'X' * 32)
    busted_vm = chain_without_block_validation.get_vm(
        header_with_bad_state_root)

    # notice that the state root is missing by the raised MissingAccountTrieNode
    with pytest.raises(MissingAccountTrieNode):
        busted_vm.state.apply_transaction(tx)
예제 #16
0
파일: test_chain.py 프로젝트: ycdk/py-evm
def test_import_block(chain_without_block_validation):  # noqa: F811
    chain = chain_without_block_validation  # noqa: F811
    recipient = decode_hex('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0c')
    amount = 100
    vm = chain.get_vm()
    from_ = chain.funded_address
    tx = new_transaction(vm, from_, recipient, amount, chain.funded_address_private_key)
    computation = vm.apply_transaction(tx)
    assert not computation.is_error
    block = chain.import_block(vm.block)
    assert block.transactions == [tx]
    assert chain.get_block_by_hash(block.hash) == block
    assert chain.get_canonical_block_by_number(block.number) == block
예제 #17
0
def main():
    args = parse_args()
    # print('Called with args:')
    # print(args)

    # genesis address
    init_address = to_canonical_address(
        "8888f1f195afa192cfee860698584c030f4c9db1")
    base_state = base_genesis_state(init_address,
                                    funded_address_initial_balance())

    # just an address
    simple_contract_address = create_simple_contract_address()

    # create chain
    klass = MiningChain.configure(
        __name__='MyTestChain',
        vm_configuration=((constants.GENESIS_BLOCK_NUMBER,
                           SpuriousDragonVM), ),
        network_id=1337,
    )
    chain = klass.from_genesis(
        MemoryDB(), GENESIS_PARAMS,
        genesis_state(base_state, simple_contract_address, args.data))

    # TODO
    # signature = 'getMeaningOfLife()'  # function name
    # function_selector = function_signature_to_4byte_selector(signature)
    '''
		new_transaction(
		    vm,
		    from_,
		    to,
		    amount=0,
		    private_key=None,
		    gas_price=10,
		    gas=100000,
		    data=b''
		)
    '''
    call_txn = new_transaction(
        chain.get_vm(),
        SENDER,
        simple_contract_address,
        gas_price=0,
        # data=function_selector,
        data=decode_hex(args.signature),
    )
    result_bytes = chain.get_transaction_result(call_txn,
                                                chain.get_canonical_head())
예제 #18
0
def test_get_transaction_result(chain, simple_contract_address, signature,
                                gas_price, expected):

    function_selector = function_signature_to_4byte_selector(signature)
    call_txn = new_transaction(
        chain.get_vm(),
        b'\xff' * 20,
        simple_contract_address,
        gas_price=gas_price,
        data=function_selector,
    )
    result_bytes = chain.get_transaction_result(call_txn,
                                                chain.get_canonical_head())
    assert result_bytes == expected
예제 #19
0
def test_get_transaction_result_revert(vm, chain_from_vm,
                                       simple_contract_address, signature,
                                       expected):

    chain = chain_from_vm(vm)
    function_selector = function_signature_to_4byte_selector(signature)
    call_txn = new_transaction(
        chain.get_vm(),
        b'\xff' * 20,
        simple_contract_address,
        data=function_selector,
    )
    with pytest.raises(expected):
        chain.get_transaction_result(call_txn, chain.get_canonical_head())
예제 #20
0
def test_chaindb_get_receipt_by_index(
        chain,
        funded_address,
        funded_address_private_key):
    NUMBER_BLOCKS_IN_CHAIN = 5
    TRANSACTIONS_IN_BLOCK = 10
    REQUIRED_BLOCK_NUMBER = 2
    REQUIRED_RECEIPT_INDEX = 3

    for block_number in range(NUMBER_BLOCKS_IN_CHAIN):
        for tx_index in range(TRANSACTIONS_IN_BLOCK):
            tx = new_transaction(
                chain.get_vm(),
                from_=funded_address,
                to=force_bytes_to_address(b'\x10\x10'),
                private_key=funded_address_private_key,
            )
            new_block, tx_receipt, computation = chain.apply_transaction(tx)
            assert computation.is_success

            if (block_number + 1) == REQUIRED_BLOCK_NUMBER and tx_index == REQUIRED_RECEIPT_INDEX:
                actual_receipt = tx_receipt

        chain.mine_block()

    # Check that the receipt retrieved is indeed the actual one
    chaindb_retrieved_receipt = chain.chaindb.get_receipt_by_index(
        REQUIRED_BLOCK_NUMBER,
        REQUIRED_RECEIPT_INDEX,
    )
    assert chaindb_retrieved_receipt == actual_receipt

    # Raise error if block number is not found
    with pytest.raises(ReceiptNotFound):
        chain.chaindb.get_receipt_by_index(
            NUMBER_BLOCKS_IN_CHAIN + 1,
            REQUIRED_RECEIPT_INDEX,
        )

    # Raise error if receipt index is out of range
    with pytest.raises(ReceiptNotFound):
        chain.chaindb.get_receipt_by_index(
            NUMBER_BLOCKS_IN_CHAIN,
            TRANSACTIONS_IN_BLOCK + 1,
        )
예제 #21
0
파일: test_vm.py 프로젝트: ycdk/py-evm
def test_apply_transaction(chain_without_block_validation):  # noqa: F811
    chain = chain_without_block_validation  # noqa: F811
    vm = chain.get_vm()
    tx_idx = len(vm.block.transactions)
    recipient = decode_hex('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0c')
    amount = 100
    from_ = chain.funded_address
    tx = new_transaction(vm, from_, recipient, amount, chain.funded_address_private_key)
    computation = vm.apply_transaction(tx)
    assert not computation.is_error
    tx_gas = tx.gas_price * constants.GAS_TX
    with vm.state.state_db(read_only=True) as state_db:
        assert state_db.get_balance(from_) == (
            chain.funded_address_initial_balance - amount - tx_gas)
        assert state_db.get_balance(recipient) == amount
    block = vm.block
    assert block.transactions[tx_idx] == tx
    assert block.header.gas_used == constants.GAS_TX
예제 #22
0
def test_apply_transaction(chain, funded_address, funded_address_private_key,
                           funded_address_initial_balance):
    vm = chain.get_vm()
    recipient = decode_hex('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0c')
    amount = 100
    from_ = funded_address
    tx = new_transaction(vm, from_, recipient, amount,
                         funded_address_private_key)
    new_header, _, computation = vm.apply_transaction(vm.block.header, tx)

    assert not computation.is_error
    tx_gas = tx.gas_price * constants.GAS_TX
    account_db = vm.state.account_db
    assert account_db.get_balance(from_) == (funded_address_initial_balance -
                                             amount - tx_gas)
    assert account_db.get_balance(recipient) == amount

    assert new_header.gas_used == constants.GAS_TX
def test_building_block_incrementally_with_single_transaction(
        chain, funded_address, funded_address_private_key):
    head_hash = chain.get_canonical_head().hash
    tx = new_transaction(
        chain.get_vm(),
        from_=funded_address,
        to=ADDRESS_1010,
        private_key=funded_address_private_key,
    )
    _, _, computation = chain.apply_transaction(tx)
    assert computation.is_success

    # test that the *latest* block hasn't changed
    assert chain.get_canonical_head().hash == head_hash

    mined_block = chain.mine_block()
    assert len(mined_block.transactions) == 1

    actual_tx = mined_block.transactions[0]
    assert actual_tx == tx
예제 #24
0
파일: test_vm.py 프로젝트: you77520/py-evm
def test_apply_transaction(chain, funded_address, funded_address_private_key,
                           funded_address_initial_balance):
    vm = chain.get_vm()
    tx_idx = len(vm.block.transactions)
    recipient = decode_hex('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0c')
    amount = 100
    from_ = funded_address
    tx = new_transaction(vm, from_, recipient, amount,
                         funded_address_private_key)
    computation, _ = vm.apply_transaction(tx)

    assert not computation.is_error
    tx_gas = tx.gas_price * constants.GAS_TX
    state_db = vm.state.read_only_state_db
    assert state_db.get_balance(from_) == (funded_address_initial_balance -
                                           amount - tx_gas)
    assert state_db.get_balance(recipient) == amount
    block = vm.block
    assert block.transactions[tx_idx] == tx
    assert block.header.gas_used == constants.GAS_TX
예제 #25
0
def main():
    # genesis address
    init_address = to_canonical_address(
        "8888f1f195afa192cfee860698584c030f4c9db1")
    base_state = base_genesis_state(init_address,
                                    funded_address_initial_balance())

    simple_contract_address = RECEIVER

    # create chain
    klass = MiningChain.configure(
        __name__='MyTestChain',
        vm_configuration=((constants.GENESIS_BLOCK_NUMBER, ByzantiumVM), ))
    chain = klass.from_genesis(
        MemoryDB(), GENESIS_PARAMS,
        genesis_state(base_state, simple_contract_address))
    # chain = klass.from_genesis(MemoryDB(), GENESIS_PARAMS, base_state)
    vm = chain.get_vm()

    # tx = vm.create_unsigned_transaction(
    #       nonce=vm.state.account_db.get_nonce(SENDER),
    #       gas_price=0x1,
    #       gas=0x90710,
    #       to=simple_contract_address,
    #       value=0x10,
    #       data=DATA.encode(),
    # )
    # signed_tx = tx.as_signed_transaction(SENDER_PRIVATE_KEY)
    # _, _, computation = chain.apply_transaction(signed_tx, 0x90777)

    call_txn = new_transaction(
        vm,
        SENDER,
        RECEIVER,
        amount=0x10,
        data=DATA.encode(),
    )
    result_bytes = chain.get_transaction_result(call_txn,
                                                chain.get_canonical_head(),
                                                1000)
예제 #26
0
def test_apply_transaction(
        chain_without_block_validation,
        funded_address,
        funded_address_private_key):
    chain = chain_without_block_validation

    # Don't change these variables
    vm = chain.get_vm()
    chaindb = copy.deepcopy(vm.chaindb)
    block0 = copy.deepcopy(vm.block)
    prev_block_hash = chain.get_canonical_block_by_number(0).hash
    initial_state_root = vm.block.header.state_root

    # (1) Get VM.apply_transaction(transaction) result for assertion
    # The first transaction
    chain1 = copy.deepcopy(chain)
    vm_example = chain1.get_vm()
    recipient1 = decode_hex('0x1111111111111111111111111111111111111111')
    amount = 100
    from_ = funded_address
    tx1 = new_transaction(
        vm_example,
        from_,
        recipient1,
        amount,
        private_key=funded_address_private_key,
    )
    computation, result_block = vm_example.apply_transaction(tx1)

    # The second transaction
    recipient2 = decode_hex('0x2222222222222222222222222222222222222222')
    tx2 = new_transaction(
        vm_example,
        from_,
        recipient2,
        amount,
        private_key=funded_address_private_key,
    )
    computation, result_block = vm_example.apply_transaction(tx2)
    assert len(result_block.transactions) == 2

    # (2) Test State.apply_transaction(...)
    # Use SpuriousDragonState to apply transaction
    chaindb1 = copy.deepcopy(chaindb)
    block1 = copy.deepcopy(block0)
    prev_hashes = vm.get_prev_hashes(
        last_block_hash=prev_block_hash,
        db=vm.chaindb,
    )
    execution_context = block1.header.create_execution_context(prev_hashes)
    state1 = SpuriousDragonState(
        chaindb=chaindb1,
        execution_context=execution_context,
        state_root=block1.header.state_root,
        gas_used=0,
    )
    parent_hash = copy.deepcopy(prev_hashes[0])

    computation, block, _ = state1.apply_transaction(
        tx1,
        block1,
    )

    # Check if prev_hashes hasn't been changed
    assert parent_hash == prev_hashes[0]
    # Make sure that block1 hasn't been changed
    assert block1.header.state_root == initial_state_root
    execution_context = block.header.create_execution_context(prev_hashes)
    state1 = SpuriousDragonState(
        chaindb=chaindb1,
        execution_context=execution_context,
        state_root=block.header.state_root,
        gas_used=computation.state.gas_used,
    )
    computation, block, _ = state1.apply_transaction(
        tx2,
        block,
    )
    post_state = computation.state

    # Check block data are correct
    assert block.header.state_root == result_block.header.state_root
    assert block.header.gas_limit == result_block.header.gas_limit
    assert block.header.gas_used == result_block.header.gas_used
    assert block.header.transaction_root == result_block.header.transaction_root
    assert block.header.receipt_root == result_block.header.receipt_root

    # Make sure that state1 hasn't been changed
    assert post_state.state_root == result_block.header.state_root
예제 #27
0
파일: test_vm.py 프로젝트: thomaslu3/py-evm
def test_create_block(chain):

    # (1) Empty block.
    # block = vm.mine_block()
    block0 = chain.import_block(chain.get_vm().block)
    initial_state_root = block0.header.state_root

    # (2) Use VM.apply_transaction to get the witness data
    chain1 = copy.deepcopy(chain)
    vm1 = chain1.get_vm()

    # The first transaction
    vm = chain.get_vm()
    recipient1 = decode_hex('0x1111111111111111111111111111111111111111')
    amount = 100
    from_ = chain.funded_address
    tx1 = new_transaction(vm1, from_, recipient1, amount,
                          chain.funded_address_private_key)

    # Get the witness of tx1
    computation, _ = vm1.apply_transaction(tx1)
    transaction_witness1 = computation.vm_state.access_logs.reads

    # The second transaction
    recipient2 = decode_hex('0x2222222222222222222222222222222222222222')
    tx2 = new_transaction(vm1, from_, recipient2, amount,
                          chain.funded_address_private_key)

    # Get the witness of tx2
    computation, block = vm1.apply_transaction(tx2)
    transaction_witness2 = computation.vm_state.access_logs.reads

    # Check AccessLogs
    witness_db = BaseChainDB(MemoryDB(computation.vm_state.access_logs.writes))
    state_db = witness_db.get_state_db(block.header.state_root, read_only=True)
    assert state_db.get_balance(recipient2) == amount
    with pytest.raises(KeyError):
        state_db.get_balance(recipient1)

    # Create a block and import to chain
    coinbase = decode_hex('0x3333333333333333333333333333333333333333')
    vm1.block.header.coinbase = coinbase
    assert len(vm1.block.transactions) == 2
    block1 = chain1.import_block(vm1.block)

    # Check the block
    vm1 = chain1.get_vm()
    assert block1.header.coinbase == coinbase
    assert len(block1.transactions) == 2
    assert len(block1.get_receipts(vm1.chaindb)) == 2
    with vm1.state.state_db(read_only=True) as state_db1:
        assert state_db1.root_hash == block1.header.state_root

    # (3) Try to create a block by witnesses
    vm2 = copy.deepcopy(vm)
    transaction_packages = [
        (tx1, transaction_witness1),
        (tx2, transaction_witness2),
    ]
    prev_hashes = vm2.get_prev_hashes(
        last_block_hash=block0.hash,
        db=vm2.chaindb,
    )
    parent_header = block0.header

    # Create a block
    block2 = vm2.create_block(
        transaction_packages=transaction_packages,
        prev_hashes=prev_hashes,
        coinbase=coinbase,
        parent_header=parent_header,
    )

    # Check the block
    assert len(block2.transactions) == 2
    assert block2.header.block_number == 2
    assert block2.header.coinbase == coinbase

    # Check if block2 == block1
    assert block2.hash == block1.hash

    # Check if the given parameters are changed
    assert block0.header.state_root == initial_state_root
    assert block0.header.block_number == 1
예제 #28
0
def test_apply_transaction(  # noqa: F811
        chain_without_block_validation,
        funded_address,
        funded_address_private_key):
    chain = chain_without_block_validation  # noqa: F811

    # Don't change these variables
    vm = chain.get_vm()
    chaindb = copy.deepcopy(vm.chaindb)
    block0 = copy.deepcopy(vm.block)
    prev_block_hash = chain.get_canonical_block_by_number(0).hash
    initial_state_root = vm.block.header.state_root

    # (1) Get VM.apply_transaction(transaction) result for assertion
    # The first transaction
    chain1 = copy.deepcopy(chain)
    vm_example = chain1.get_vm()
    recipient1 = decode_hex('0x1111111111111111111111111111111111111111')
    amount = 100
    from_ = funded_address
    tx1 = new_transaction(
        vm_example,
        from_,
        recipient1,
        amount,
        private_key=funded_address_private_key,
    )
    computation, result_block = vm_example.apply_transaction(tx1)

    # The second transaction
    recipient2 = decode_hex('0x2222222222222222222222222222222222222222')
    tx2 = new_transaction(
        vm_example,
        from_,
        recipient2,
        amount,
        private_key=funded_address_private_key,
    )
    computation, result_block = vm_example.apply_transaction(tx2)
    assert len(result_block.transactions) == 2

    # (2) Test VMState.apply_transaction(...)
    # Use FrontierVMState to apply transaction
    chaindb1 = copy.deepcopy(chaindb)
    block1 = copy.deepcopy(block0)
    prev_hashes = vm.get_prev_hashes(
        last_block_hash=prev_block_hash,
        db=vm.chaindb,
    )
    execution_context = ExecutionContext.from_block_header(block1.header, prev_hashes)
    vm_state1 = FrontierVMState(
        chaindb=chaindb1,
        execution_context=execution_context,
        state_root=block1.header.state_root,
        receipts=[],
    )
    parent_hash = copy.deepcopy(prev_hashes[0])

    computation, block, _ = vm_state1.apply_transaction(
        tx1,
        block1,
    )
    access_logs1 = computation.vm_state.access_logs

    # Check if prev_hashes hasn't been changed
    assert parent_hash == prev_hashes[0]
    # Make sure that block1 hasn't been changed
    assert block1.header.state_root == initial_state_root
    execution_context = ExecutionContext.from_block_header(block.header, prev_hashes)
    vm_state1 = FrontierVMState(
        chaindb=chaindb1,
        execution_context=execution_context,
        state_root=block.header.state_root,
        receipts=computation.vm_state.receipts,
    )
    computation, block, _ = vm_state1.apply_transaction(
        tx2,
        block,
    )
    access_logs2 = computation.vm_state.access_logs
    post_vm_state = computation.vm_state

    # Check AccessLogs
    witness_db = ChainDB(MemoryDB(access_logs2.writes))
    state_db = witness_db.get_state_db(block.header.state_root, read_only=True)
    assert state_db.get_balance(recipient2) == amount
    with pytest.raises(KeyError):
        _ = state_db.get_balance(recipient1)

    # Check block data are correct
    assert block.header.state_root == result_block.header.state_root
    assert block.header.gas_limit == result_block.header.gas_limit
    assert block.header.gas_used == result_block.header.gas_used
    assert block.header.transaction_root == result_block.header.transaction_root
    assert block.header.receipt_root == result_block.header.receipt_root

    # Make sure that vm_state1 hasn't been changed
    assert post_vm_state.state_root == result_block.header.state_root

    # (3) Testing using witness as db data
    # Witness_db
    block2 = copy.deepcopy(block0)

    witness_db = ChainDB(MemoryDB(access_logs1.reads))
    prev_hashes = vm.get_prev_hashes(
        last_block_hash=prev_block_hash,
        db=vm.chaindb,
    )
    execution_context = ExecutionContext.from_block_header(block2.header, prev_hashes)
    # Apply the first transaction
    vm_state2 = FrontierVMState(
        chaindb=witness_db,
        execution_context=execution_context,
        state_root=block2.header.state_root,
        receipts=[],
    )
    computation, block, _ = vm_state2.apply_transaction(
        tx1,
        block2,
    )

    # Update witness_db
    recent_trie_nodes = merge(access_logs2.reads, access_logs1.writes)
    witness_db = ChainDB(MemoryDB(recent_trie_nodes))
    execution_context = ExecutionContext.from_block_header(block.header, prev_hashes)
    # Apply the second transaction
    vm_state2 = FrontierVMState(
        chaindb=witness_db,
        execution_context=execution_context,
        state_root=block.header.state_root,
        receipts=computation.vm_state.receipts,
    )
    computation, block, _ = vm_state2.apply_transaction(
        tx2,
        block,
    )

    # After applying
    assert block.header.state_root == computation.vm_state.state_root
    assert block.header.transaction_root == result_block.header.transaction_root
    assert block.header.receipt_root == result_block.header.receipt_root
    assert block.hash == result_block.hash

    # (3) Testing using witness_db and block_header to reconstruct vm_state
    prev_hashes = vm.get_prev_hashes(
        last_block_hash=prev_block_hash,
        db=vm.chaindb,
    )
    execution_context = ExecutionContext.from_block_header(block.header, prev_hashes)
    vm_state3 = FrontierVMState(
        chaindb=witness_db,
        execution_context=execution_context,
        state_root=block.header.state_root,
    )
    assert vm_state3.state_root == post_vm_state.state_root
    assert vm_state3.state_root == result_block.header.state_root
예제 #29
0
def test_apply_transaction(  # noqa: F811
        chain_without_block_validation,
        funded_address,
        funded_address_private_key):
    chain = chain_without_block_validation  # noqa: F811

    # Don't change these variables
    vm = chain.get_vm()
    chaindb = copy.deepcopy(vm.chaindb)
    block0 = copy.deepcopy(vm.block)
    prev_block_hash = chain.get_canonical_block_by_number(0).hash
    initial_state_root = vm.block.header.state_root

    # (1) Get VM.apply_transaction(transaction) result for assertion
    # The first transaction
    chain1 = copy.deepcopy(chain)
    vm_example = chain1.get_vm()
    recipient1 = decode_hex('0x1111111111111111111111111111111111111111')
    amount = 100
    from_ = funded_address
    tx1 = new_transaction(
        vm_example,
        from_,
        recipient1,
        amount,
        private_key=funded_address_private_key,
    )
    computation, result_block = vm_example.apply_transaction(tx1)

    # The second transaction
    recipient2 = decode_hex('0x2222222222222222222222222222222222222222')
    tx2 = new_transaction(
        vm_example,
        from_,
        recipient2,
        amount,
        private_key=funded_address_private_key,
    )
    computation, result_block = vm_example.apply_transaction(tx2)
    assert len(result_block.transactions) == 2

    # (2) Test VMState.apply_transaction(...)
    # Use SpuriousDragonVMState to apply transaction
    chaindb1 = copy.deepcopy(chaindb)
    block1 = copy.deepcopy(block0)
    prev_hashes = vm.get_prev_hashes(
        last_block_hash=prev_block_hash,
        db=vm.chaindb,
    )
    execution_context = block1.header.create_execution_context(prev_hashes)
    vm_state1 = SpuriousDragonVMState(
        chaindb=chaindb1,
        execution_context=execution_context,
        state_root=block1.header.state_root,
        receipts=[],
    )
    parent_hash = copy.deepcopy(prev_hashes[0])

    computation, block, _ = vm_state1.apply_transaction(
        tx1,
        block1,
    )
    access_logs1 = computation.vm_state.access_logs

    # Check if prev_hashes hasn't been changed
    assert parent_hash == prev_hashes[0]
    # Make sure that block1 hasn't been changed
    assert block1.header.state_root == initial_state_root
    execution_context = block.header.create_execution_context(prev_hashes)
    vm_state1 = SpuriousDragonVMState(
        chaindb=chaindb1,
        execution_context=execution_context,
        state_root=block.header.state_root,
        receipts=computation.vm_state.receipts,
    )
    computation, block, _ = vm_state1.apply_transaction(
        tx2,
        block,
    )
    access_logs2 = computation.vm_state.access_logs
    post_vm_state = computation.vm_state

    # Check AccessLogs
    witness_db = ChainDB(MemoryDB(access_logs2.writes))
    state_db = witness_db.get_state_db(block.header.state_root, read_only=True)
    assert state_db.get_balance(recipient2) == amount
    with pytest.raises(KeyError):
        _ = state_db.get_balance(recipient1)

    # Check block data are correct
    assert block.header.state_root == result_block.header.state_root
    assert block.header.gas_limit == result_block.header.gas_limit
    assert block.header.gas_used == result_block.header.gas_used
    assert block.header.transaction_root == result_block.header.transaction_root
    assert block.header.receipt_root == result_block.header.receipt_root

    # Make sure that vm_state1 hasn't been changed
    assert post_vm_state.state_root == result_block.header.state_root

    # (3) Testing using witness as db data
    # Witness_db
    block2 = copy.deepcopy(block0)

    witness_db = ChainDB(MemoryDB(access_logs1.reads))
    prev_hashes = vm.get_prev_hashes(
        last_block_hash=prev_block_hash,
        db=vm.chaindb,
    )
    execution_context = block2.header.create_execution_context(prev_hashes)
    # Apply the first transaction
    vm_state2 = SpuriousDragonVMState(
        chaindb=witness_db,
        execution_context=execution_context,
        state_root=block2.header.state_root,
        receipts=[],
    )
    computation, block, _ = vm_state2.apply_transaction(
        tx1,
        block2,
    )

    # Update witness_db
    recent_trie_nodes = merge(access_logs2.reads, access_logs1.writes)
    witness_db = ChainDB(MemoryDB(recent_trie_nodes))
    execution_context = block.header.create_execution_context(prev_hashes)
    # Apply the second transaction
    vm_state2 = SpuriousDragonVMState(
        chaindb=witness_db,
        execution_context=execution_context,
        state_root=block.header.state_root,
        receipts=computation.vm_state.receipts,
    )
    computation, block, _ = vm_state2.apply_transaction(
        tx2,
        block,
    )

    # After applying
    assert block.header.state_root == computation.vm_state.state_root
    assert block.header.transaction_root == result_block.header.transaction_root
    assert block.header.receipt_root == result_block.header.receipt_root
    assert block.hash == result_block.hash

    # (3) Testing using witness_db and block_header to reconstruct vm_state
    prev_hashes = vm.get_prev_hashes(
        last_block_hash=prev_block_hash,
        db=vm.chaindb,
    )
    execution_context = block.header.create_execution_context(prev_hashes)
    vm_state3 = SpuriousDragonVMState(
        chaindb=witness_db,
        execution_context=execution_context,
        state_root=block.header.state_root,
    )
    assert vm_state3.state_root == post_vm_state.state_root
    assert vm_state3.state_root == result_block.header.state_root