コード例 #1
0
ファイル: test_log_handler.py プロジェクト: tmyk104117/py-evm
def test_log_handler_mk_filter_params(contract):
    log_handler = LogHandler(contract.web3)
    filter_params = log_handler.mk_filter_params(1, 2)
    assert 'fromBlock' in filter_params
    assert 'toBlock' in filter_params
    filter_params_with_address = log_handler.mk_filter_params(
        1, 2, contract.address)
    assert contract.address == filter_params_with_address['address']
    topics = [encode_hex(test_event_signature)]
    filter_params_with_address = log_handler.mk_filter_params(
        1, 2, contract.address, topics)
    assert topics == filter_params_with_address['topics']
コード例 #2
0
def test_log_handler_get_new_logs_without_forks(contract):
    w3 = contract.web3
    log_handler = LogHandler(w3)
    counter = itertools.count()
    contract.transact(default_tx_detail).emit_log(next(counter))
    mine(w3, 1)
    logs_block2 = log_handler.get_new_logs(address=contract.address)
    assert len(logs_block2) == 1
    assert int(logs_block2[0]['data'], 16) == 0
    assert log_handler.get_new_logs() == tuple()
    contract.transact(default_tx_detail).emit_log(next(counter))
    mine(w3, 1)
    logs_block3 = log_handler.get_new_logs(address=contract.address)
    assert len(logs_block3) == 1
    assert int(logs_block3[0]['data'], 16) == 1
    assert log_handler.get_new_logs() == tuple()
    contract.transact(default_tx_detail).emit_log(next(counter))
    mine(w3, 1)
    contract.transact(default_tx_detail).emit_log(next(counter))
    mine(w3, 1)
    logs_block4_5 = log_handler.get_new_logs(address=contract.address)
    assert len(logs_block4_5) == 2
    assert int(logs_block4_5[0]['data'], 16) == 2
    assert int(logs_block4_5[1]['data'], 16) == 3
    assert log_handler.get_new_logs() == tuple()
コード例 #3
0
def test_log_handler_get_new_logs_with_forks(contract):
    w3 = contract.web3
    log_handler = LogHandler(w3)
    counter = itertools.count()
    snapshot_id = take_snapshot(w3)
    current_block_number = w3.eth.blockNumber
    contract.transact(default_tx_detail).emit_log(next(counter))
    mine(w3, 1)
    revert_to_snapshot(w3, snapshot_id)
    assert w3.eth.blockNumber == current_block_number
    contract.transact(default_tx_detail).emit_log(next(counter))
    mine(w3, 1)
    contract.transact(default_tx_detail).emit_log(next(counter))
    mine(w3, 1)
    logs = log_handler.get_new_logs()
    # assert len(logs) == 2
    assert int(logs[0]['data'], 16) == 1
    assert int(logs[1]['data'], 16) == 2
    assert log_handler.get_new_logs() == tuple()
コード例 #4
0
def test_shard_tracker_fetch_candidate_head(vmc, mock_score, mock_is_new_head,
                                            expected_score,
                                            expected_is_new_head):
    shard_id = 0
    log_handler = LogHandler(vmc.web3)
    shard_tracker = ShardTracker(shard_id, log_handler, vmc.address)
    mock_collation_added_logs = [{
        'header': [None] * 10,
        'score': mock_score[i],
        'is_new_head': mock_is_new_head[i],
    } for i in range(len(mock_score))]
    # mock collation_added_logs
    shard_tracker.new_logs = mock_collation_added_logs
    for i in range(len(mock_score)):
        log = shard_tracker.fetch_candidate_head()
        assert log['score'] == expected_score[i]
        assert log['is_new_head'] == expected_is_new_head[i]
    with pytest.raises(NextLogUnavailable):
        log = shard_tracker.fetch_candidate_head()
コード例 #5
0
def test_vmc_contract_calls(vmc):  # noqa: F811
    shard_id = 0
    validator_index = 0
    primary_key = test_keys[validator_index]
    primary_addr = primary_key.public_key.to_canonical_address()
    default_gas = vmc.config['DEFAULT_GAS']

    log_handler = LogHandler(vmc.web3)
    shard_tracker = ShardTracker(shard_id, log_handler, vmc.address)
    vmc.set_shard_tracker(shard_id, shard_tracker)
    # test `mk_build_transaction_detail` ######################################
    build_transaction_detail = vmc.mk_build_transaction_detail(
        nonce=0,
        gas=10000,
    )
    assert 'nonce' in build_transaction_detail
    assert 'gas' in build_transaction_detail
    assert 'chainId' in build_transaction_detail
    with pytest.raises(ValueError):
        build_transaction_detail = vmc.mk_build_transaction_detail(
            nonce=None,
            gas=10000,
        )
    with pytest.raises(ValueError):
        build_transaction_detail = vmc.mk_build_transaction_detail(
            nonce=0,
            gas=None,
        )

    # test `mk_contract_tx_detail` ######################################
    tx_detail = vmc.mk_contract_tx_detail(
        sender_address=ZERO_ADDR,
        gas=vmc.config['DEFAULT_GAS'],
    )
    assert 'from' in tx_detail
    assert 'gas' in tx_detail
    with pytest.raises(ValueError):
        tx_detail = vmc.mk_contract_tx_detail(
            sender_address=ZERO_ADDR,
            gas=None,
        )
    with pytest.raises(ValueError):
        tx_detail = vmc.mk_contract_tx_detail(
            sender_address=None,
            gas=vmc.config['DEFAULT_GAS'],
        )

    # test the deployment of vmc ######################################
    # deploy vmc if it is not deployed yet.
    if not is_vmc_deployed(vmc):
        logger.debug('is_vmc_deployed(vmc) == True')
        # import test_key
        import_key(vmc, primary_key)
        deploy_initiating_contracts(vmc, primary_key)
        mine(vmc, 1)

    assert is_vmc_deployed(vmc)

    lookahead_blocks = vmc.config['LOOKAHEAD_PERIODS'] * vmc.config[
        'PERIOD_LENGTH']
    # test `deposit` and `get_eligible_proposer` ######################################
    # now we require 1 validator.
    # if there is currently no validator, we deposit one.
    # else, there should only be one validator, for easier testing.
    num_validators = vmc.call(
        vmc.mk_contract_tx_detail(sender_address=primary_addr,
                                  gas=default_gas)).num_validators()
    if num_validators == 0:
        # deposit as the first validator
        validator_addr = send_deposit_tx(vmc)
        # TODO: error occurs when we don't mine so many blocks
        mine(vmc, lookahead_blocks)
        assert vmc.get_eligible_proposer(shard_id) == validator_addr

    # assert the current_block_number >= LOOKAHEAD_PERIODS * PERIOD_LENGTH
    # to ensure that `get_eligible_proposer` works
    current_block_number = vmc.web3.eth.blockNumber
    if current_block_number < lookahead_blocks:
        mine(vmc, lookahead_blocks - current_block_number)
    assert vmc.web3.eth.blockNumber >= lookahead_blocks

    num_validators = vmc.call(
        vmc.mk_contract_tx_detail(sender_address=primary_addr,
                                  gas=default_gas)).num_validators()
    assert num_validators == 1
    assert vmc.get_eligible_proposer(shard_id) != ZERO_ADDR
    logger.debug("vmc_handler.num_validators()=%s", num_validators)

    # test `add_header` ######################################
    # create a testing collation header, whose parent is the genesis
    header0_1 = mk_testing_colhdr(vmc, shard_id, GENESIS_COLHDR_HASH, 1)
    # if a header is added before its parent header is added, `add_header` should fail
    # TransactionFailed raised when assertions fail
    with pytest.raises(TransactionFailed):
        header_parent_not_added = mk_testing_colhdr(
            vmc,
            shard_id,
            header0_1.hash,
            1,
        )
        add_header_constant_call(vmc, header_parent_not_added)
    # when a valid header is added, the `add_header` call should succeed
    vmc.add_header(header0_1)
    mine(vmc, vmc.config['PERIOD_LENGTH'])
    # if a header is added before, the second trial should fail
    with pytest.raises(TransactionFailed):
        add_header_constant_call(vmc, header0_1)
    # when a valid header is added, the `add_header` call should succeed
    header0_2 = mk_testing_colhdr(vmc, shard_id, header0_1.hash, 2)
    vmc.add_header(header0_2)

    mine(vmc, vmc.config['PERIOD_LENGTH'])
    # confirm the score of header1 and header2 are correct or not
    colhdr0_1_score = vmc.call(
        vmc.mk_contract_tx_detail(sender_address=primary_addr,
                                  gas=default_gas)).get_collation_header_score(
                                      shard_id, header0_1.hash)
    assert colhdr0_1_score == 1
    colhdr0_2_score = vmc.call(
        vmc.mk_contract_tx_detail(sender_address=primary_addr,
                                  gas=default_gas)).get_collation_header_score(
                                      shard_id, header0_2.hash)
    assert colhdr0_2_score == 2
    # confirm the logs are correct
    assert vmc.get_next_log(shard_id)['score'] == 2
    assert vmc.get_next_log(shard_id)['score'] == 1
    with pytest.raises(NextLogUnavailable):
        vmc.get_next_log(shard_id)

    # filter logs in multiple shards
    vmc.set_shard_tracker(1, ShardTracker(1, LogHandler(vmc.web3),
                                          vmc.address))
    header1_1 = mk_testing_colhdr(vmc, 1, GENESIS_COLHDR_HASH, 1)
    vmc.add_header(header1_1)
    mine(vmc, 1)
    header0_3 = mk_testing_colhdr(vmc, shard_id, header0_2.hash, 3)
    vmc.add_header(header0_3)
    mine(vmc, 1)
    assert vmc.get_next_log(0)['score'] == 3
    # ensure that `get_next_log(0)` does not affect `get_next_log(1)`
    assert vmc.get_next_log(1)['score'] == 1
    logs = vmc.web3.eth.getLogs({
        "fromBlock":
        0,
        "toBlock":
        vmc.web3.eth.blockNumber,
        "topics": [
            encode_hex(ShardTracker.COLLATION_ADDED_TOPIC),
        ]
    })
    assert len(logs) == 4

    vmc.tx_to_shard(
        test_keys[1].public_key.to_canonical_address(),
        shard_id,
        100000,
        1,
        b'',
        value=1234567,
    )
    mine(vmc, 1)
    receipt_value = vmc.call(
        vmc.mk_contract_tx_detail(sender_address=primary_addr,
                                  gas=default_gas)).receipts__value(0)
    # the receipt value should be equaled to the transaction value
    assert receipt_value == 1234567

    # test `withdraw` ######################################
    send_withdraw_tx(vmc, validator_index)
    mine(vmc, 1)
    # if the only validator withdraws, because there is no validator anymore, the result of
    # `num_validators` must be 0.
    num_validators = vmc.call(
        vmc.mk_contract_tx_detail(sender_address=primary_addr,
                                  gas=default_gas)).num_validators()
    assert num_validators == 0
コード例 #6
0
def test_smc_contract_calls(smc_handler):  # noqa: F811
    web3 = smc_handler.web3
    shard_id = 0
    validator_index = 0
    primary_key = test_keys[validator_index]
    primary_addr = primary_key.public_key.to_canonical_address()
    default_gas = smc_handler.config['DEFAULT_GAS']

    shard_0_tracker = ShardTracker(shard_id, LogHandler(web3),
                                   smc_handler.address)

    lookahead_blocks = (smc_handler.config['LOOKAHEAD_PERIODS'] *
                        smc_handler.config['PERIOD_LENGTH'])
    # test `deposit` and `get_eligible_proposer` ######################################
    # now we require 1 validator.
    # if there is currently no validator, we deposit one.
    # else, there should only be one validator, for easier testing.
    num_validators = smc_handler.call(
        make_call_context(sender_address=primary_addr,
                          gas=default_gas)).num_validators()
    if num_validators == 0:
        # deposit as the first validator
        smc_handler.deposit()
        # TODO: error occurs when we don't mine so many blocks
        mine(web3, lookahead_blocks)
        assert smc_handler.get_eligible_proposer(
            shard_id) == smc_handler.sender_address

    # assert the current_block_number >= LOOKAHEAD_PERIODS * PERIOD_LENGTH
    # to ensure that `get_eligible_proposer` works
    current_block_number = web3.eth.blockNumber
    if current_block_number < lookahead_blocks:
        mine(web3, lookahead_blocks - current_block_number)
    assert web3.eth.blockNumber >= lookahead_blocks

    num_validators = smc_handler.call(
        make_call_context(sender_address=primary_addr,
                          gas=default_gas)).num_validators()
    assert num_validators == 1
    assert smc_handler.get_eligible_proposer(shard_id) != ZERO_ADDR
    logger.debug("smc_handler.num_validators()=%s", num_validators)

    # test `add_header` ######################################
    # create a testing collation header, whose parent is the genesis
    header0_1 = make_testing_colhdr(smc_handler, shard_id, GENESIS_COLHDR_HASH,
                                    1)
    # if a header is added before its parent header is added, `add_header` should fail
    # TransactionFailed raised when assertions fail
    with pytest.raises(TransactionFailed):
        header_parent_not_added = make_testing_colhdr(
            smc_handler,
            shard_id,
            header0_1.hash,
            1,
        )
        add_header_constant_call(smc_handler, header_parent_not_added)
    # when a valid header is added, the `add_header` call should succeed
    smc_handler.add_header(header0_1)
    mine(web3, smc_handler.config['PERIOD_LENGTH'])
    # if a header is added before, the second trial should fail
    with pytest.raises(TransactionFailed):
        add_header_constant_call(smc_handler, header0_1)
    # when a valid header is added, the `add_header` call should succeed
    header0_2 = make_testing_colhdr(smc_handler, shard_id, header0_1.hash, 2)
    smc_handler.add_header(header0_2)

    mine(web3, smc_handler.config['PERIOD_LENGTH'])
    # confirm the score of header1 and header2 are correct or not
    colhdr0_1_score = smc_handler.call(
        make_call_context(sender_address=primary_addr,
                          gas=default_gas)).get_collation_header_score(
                              shard_id, header0_1.hash)
    assert colhdr0_1_score == 1
    colhdr0_2_score = smc_handler.call(
        make_call_context(sender_address=primary_addr,
                          gas=default_gas)).get_collation_header_score(
                              shard_id, header0_2.hash)
    assert colhdr0_2_score == 2
    # confirm the logs are correct
    assert shard_0_tracker.get_next_log()['score'] == 2
    assert shard_0_tracker.get_next_log()['score'] == 1
    with pytest.raises(NextLogUnavailable):
        shard_0_tracker.get_next_log()

    # filter logs in multiple shards
    shard_1_tracker = ShardTracker(1, LogHandler(web3), smc_handler.address)
    header1_1 = make_testing_colhdr(smc_handler, 1, GENESIS_COLHDR_HASH, 1)
    smc_handler.add_header(header1_1)
    mine(web3, 1)
    header0_3 = make_testing_colhdr(smc_handler, shard_id, header0_2.hash, 3)
    smc_handler.add_header(header0_3)
    mine(web3, 1)
    assert shard_0_tracker.get_next_log()['score'] == 3
    assert shard_1_tracker.get_next_log()['score'] == 1
    logs = web3.eth.getLogs({
        "fromBlock": 0,
        "toBlock": web3.eth.blockNumber,
        "topics": [
            encode_hex(COLLATION_ADDED_TOPIC),
        ]
    })
    assert len(logs) == 4

    smc_handler.tx_to_shard(
        test_keys[1].public_key.to_canonical_address(),
        shard_id,
        100000,
        1,
        b'',
        value=1234567,
    )
    mine(web3, 1)
    receipt_value = smc_handler.call(
        make_call_context(sender_address=primary_addr,
                          gas=default_gas)).receipts__value(0)
    # the receipt value should be equaled to the transaction value
    assert receipt_value == 1234567

    # test `withdraw` ######################################
    smc_handler.withdraw(validator_index)
    mine(web3, 1)
    # if the only validator withdraws, because there is no validator anymore, the result of
    # `num_validators` must be 0.
    num_validators = smc_handler.call(
        make_call_context(sender_address=primary_addr,
                          gas=default_gas)).num_validators()
    assert num_validators == 0