def test_instant_release_notary(smc_handler):  # noqa: F811
    w3 = smc_handler.web3

    notary_0 = NotaryAccount(0)

    # Register notary 0
    smc_handler.register_notary(private_key=notary_0.private_key)
    mine(w3, 1)
    does_notary_exist = smc_handler.does_notary_exist(
        notary_0.checksum_address)
    assert does_notary_exist
    notary_pool_length = smc_handler.notary_pool_len()
    assert notary_pool_length == 1

    # Fast foward
    fast_forward(smc_handler, 1)

    # Deregister notary 0
    smc_handler.deregister_notary(private_key=notary_0.private_key)
    mine(w3, 1)
    notary_pool_length = smc_handler.notary_pool_len()
    assert notary_pool_length == 0

    # Instant release notary 0
    tx_hash = smc_handler.release_notary(private_key=notary_0.private_key)
    mine(w3, 1)
    # Check registry remain the same and the transaction consume all gas
    # and no logs has been emitted
    does_notary_exist = smc_handler.does_notary_exist(
        notary_0.checksum_address)
    assert does_notary_exist
    assert len(w3.eth.getTransactionReceipt(tx_hash)['logs']) == 0
def test_normal_release_notary(smc_handler):  # noqa: F811
    w3 = smc_handler.web3

    notary_0 = NotaryAccount(0)

    # Register notary 0
    smc_handler.register_notary(private_key=notary_0.private_key)
    mine(w3, 1)
    does_notary_exist = smc_handler.does_notary_exist(
        notary_0.checksum_address)
    assert does_notary_exist
    notary_pool_length = smc_handler.notary_pool_len()
    assert notary_pool_length == 1

    # Fast foward
    fast_forward(smc_handler, 1)

    # Deregister notary 0
    smc_handler.deregister_notary(private_key=notary_0.private_key)
    mine(w3, 1)
    notary_pool_length = smc_handler.notary_pool_len()
    assert notary_pool_length == 0

    # Fast foward to end of lock up
    fast_forward(smc_handler, smc_handler.config['NOTARY_LOCKUP_LENGTH'] + 1)

    # Release notary 0
    smc_handler.release_notary(private_key=notary_0.private_key)
    mine(w3, 1)
    does_notary_exist = smc_handler.does_notary_exist(
        notary_0.checksum_address)
    assert not does_notary_exist
def test_submit_vote_without_add_header_first(smc_handler):  # noqa: F811
    w3 = smc_handler.web3
    # We only vote in shard 0 for ease of testing
    shard_id = 0

    # Register notary 0~8 and fast forward to next period
    batch_register(smc_handler, 0, 8)
    fast_forward(smc_handler, 1)
    current_period = w3.eth.blockNumber // smc_handler.config['PERIOD_LENGTH']
    assert current_period == 1

    CHUNK_ROOT_1_0 = b'\x10' * 32
    # Get the first notary in the sample list in this period and vote
    sample_index = 0
    pool_index = sampling(smc_handler, shard_id)[sample_index]
    tx_hash = smc_handler.submit_vote(
        shard_id=shard_id,
        period=current_period,
        chunk_root=CHUNK_ROOT_1_0,
        index=sample_index,
        private_key=NotaryAccount(index=pool_index).private_key,
    )
    mine(w3, 1)
    # Check that transaction failed and vote count remains the same
    # and no logs has been emitted
    assert len(w3.eth.getTransactionReceipt(tx_hash)['logs']) == 0
    assert smc_handler.get_vote_count(shard_id) == 0
    assert not smc_handler.has_notary_voted(shard_id, sample_index)
def test_normal_deregister(smc_handler):  # noqa: F811
    w3 = smc_handler.web3

    notary_0 = NotaryAccount(0)

    # Register notary 0
    smc_handler.register_notary(private_key=notary_0.private_key)
    mine(w3, 1)
    does_notary_exist = smc_handler.does_notary_exist(
        notary_0.checksum_address)
    assert does_notary_exist
    notary_pool_length = smc_handler.notary_pool_len()
    assert notary_pool_length == 1

    # Fast foward
    fast_forward(smc_handler, 1)

    # Deregister notary 0
    smc_handler.deregister_notary(private_key=notary_0.private_key)
    current_period = w3.eth.blockNumber // smc_handler.config['PERIOD_LENGTH']
    mine(w3, 1)
    does_notary_exist = smc_handler.does_notary_exist(
        notary_0.checksum_address)
    assert does_notary_exist
    notary_deregistered_period, notary_pool_index = smc_handler.get_notary_info(
        notary_0.checksum_address)
    assert notary_deregistered_period == current_period
    notary_pool_length = smc_handler.notary_pool_len()
    assert notary_pool_length == 0
def test_deregister_then_register(smc_handler):  # noqa: F811
    w3 = smc_handler.web3

    notary_0 = NotaryAccount(0)

    # Register notary 0 and fast forward to next period
    smc_handler.register_notary(private_key=notary_0.private_key)
    fast_forward(smc_handler, 1)

    # Deregister notary 0 first
    # NOTE: Deregistration would also invoke update_notary_sample_size function
    smc_handler.deregister_notary(private_key=notary_0.private_key)
    mine(w3, 1)
    # Check that current_period_notary_sample_size is updated
    current_period_notary_sample_size = smc_handler.current_period_notary_sample_size(
    )
    assert current_period_notary_sample_size == 1

    notary_1 = NotaryAccount(1)

    # Then register notary 1
    smc_handler.register_notary(private_key=notary_1.private_key)
    mine(w3, 1)

    _, notary_1_pool_index = smc_handler.get_notary_info(
        notary_1.checksum_address)
    assert notary_1_pool_index == 0
    # Check that next_period_notary_sample_size remains the same
    next_period_notary_sample_size = smc_handler.next_period_notary_sample_size(
    )
    assert (notary_1_pool_index + 1) == next_period_notary_sample_size
def test_get_member_of_committee_with_updated_sample_size(
        smc_handler):  # noqa: F811
    w3 = smc_handler.web3

    # Register notary 0~8 and fast forward to next period
    batch_register(smc_handler, 0, 8)
    fast_forward(smc_handler, 1)

    # Update notary sample size
    update_notary_sample_size(smc_handler)
    # Check that sample-size-related values match
    current_period = w3.eth.blockNumber // smc_handler.config['PERIOD_LENGTH']
    notary_sample_size_updated_period = smc_handler.notary_sample_size_updated_period(
    )
    assert notary_sample_size_updated_period == current_period
    current_period_notary_sample_size = smc_handler.current_period_notary_sample_size(
    )
    assert current_period_notary_sample_size == 9
    next_period_notary_sample_size = smc_handler.next_period_notary_sample_size(
    )
    assert next_period_notary_sample_size == 9

    shard_0_committee_list = get_committee_list(smc_handler, 0)
    for (i, notary) in enumerate(shard_0_committee_list):
        assert smc_handler.get_member_of_committee(0, i) == notary
def test_get_member_of_committee_without_updating_sample_size(
        smc_handler):  # noqa: F811
    w3 = smc_handler.web3

    # Register notary 0~5 and fast forward to next period
    batch_register(smc_handler, 0, 5)
    fast_forward(smc_handler, 1)

    # Register notary 6~8
    batch_register(smc_handler, 6, 8)

    # Check that sample-size-related values match
    current_period = w3.eth.blockNumber // smc_handler.config['PERIOD_LENGTH']
    notary_sample_size_updated_period = smc_handler.notary_sample_size_updated_period(
    )
    assert notary_sample_size_updated_period == current_period
    current_period_notary_sample_size = smc_handler.current_period_notary_sample_size(
    )
    assert current_period_notary_sample_size == 6
    next_period_notary_sample_size = smc_handler.next_period_notary_sample_size(
    )
    assert next_period_notary_sample_size == 9

    # Fast forward to next period
    fast_forward(smc_handler, 1)
    current_period = w3.eth.blockNumber // smc_handler.config['PERIOD_LENGTH']
    notary_sample_size_updated_period = smc_handler.notary_sample_size_updated_period(
    )
    assert notary_sample_size_updated_period == current_period - 1

    shard_0_committee_list = get_committee_list(smc_handler, 0)
    # Check that get_committee_list did generate committee list
    assert len(shard_0_committee_list) > 0
    for (i, notary) in enumerate(shard_0_committee_list):
        assert smc_handler.get_member_of_committee(0, i) == notary
def test_submit_vote_with_invalid_args(smc_handler, period, shard_id,
                                       chunk_root, sample_index):
    w3 = smc_handler.web3

    # Register notary 0~8 and fast forward to next period
    batch_register(smc_handler, 0, 8)
    fast_forward(smc_handler, 1)
    current_period = w3.eth.blockNumber // smc_handler.config['PERIOD_LENGTH']
    assert current_period == 1

    # Add correct collation record
    smc_handler.add_header(
        shard_id=0,
        period=current_period,
        chunk_root=b'\x10' * 32,
        private_key=NotaryAccount(index=0).private_key,
    )
    mine(w3, 1)

    pool_index = sampling(smc_handler, 0)[0]
    # Vote with provided incorrect arguments
    tx_hash = smc_handler.submit_vote(
        shard_id=shard_id,
        period=period,
        chunk_root=chunk_root,
        index=sample_index,
        private_key=NotaryAccount(index=pool_index).private_key,
    )
    mine(w3, 1)
    # Check that transaction failed and vote count remains the same
    # and no logs has been emitted
    assert len(w3.eth.getTransactionReceipt(tx_hash)['logs']) == 0
    assert smc_handler.get_vote_count(shard_id) == 0
    assert not smc_handler.has_notary_voted(shard_id, sample_index)
def test_submit_vote_then_deregister(smc_handler):  # noqa: F811
    w3 = smc_handler.web3
    # We only vote in shard 0 for ease of testing
    shard_id = 0

    # Register notary 0~8 and fast forward to next period
    batch_register(smc_handler, 0, 8)
    fast_forward(smc_handler, 1)
    current_period = w3.eth.blockNumber // smc_handler.config['PERIOD_LENGTH']
    assert current_period == 1

    # Add collation record
    CHUNK_ROOT_1_0 = b'\x10' * 32
    smc_handler.add_header(
        shard_id=shard_id,
        period=current_period,
        chunk_root=CHUNK_ROOT_1_0,
        private_key=NotaryAccount(index=0).private_key,
    )
    mine(w3, 1)

    sample_index = 0
    pool_index = sampling(smc_handler, shard_id)[sample_index]
    smc_handler.submit_vote(
        shard_id=shard_id,
        period=current_period,
        chunk_root=CHUNK_ROOT_1_0,
        index=sample_index,
        private_key=NotaryAccount(index=pool_index).private_key,
    )
    mine(w3, 1)

    # Check that vote has been casted successfully
    assert smc_handler.get_vote_count(shard_id) == 1
    assert smc_handler.has_notary_voted(shard_id, sample_index)

    # The notary deregisters
    smc_handler.deregister_notary(
        private_key=NotaryAccount(pool_index).private_key)
    mine(w3, 1)
    # Check that vote was not effected by deregistration
    assert smc_handler.get_vote_count(shard_id) == 1
    assert smc_handler.has_notary_voted(shard_id, sample_index)

    # Notary 9 registers and takes retired notary's place in pool
    smc_handler.register_notary(private_key=NotaryAccount(9).private_key)
    # Attempt to vote
    tx_hash = smc_handler.submit_vote(
        shard_id=shard_id,
        period=current_period,
        chunk_root=CHUNK_ROOT_1_0,
        index=sample_index,
        private_key=NotaryAccount(index=9).private_key,
    )
    mine(w3, 1)

    # Check that transaction failed and vote count remains the same
    # and no logs has been emitted
    assert len(w3.eth.getTransactionReceipt(tx_hash)['logs']) == 0
    assert smc_handler.get_vote_count(shard_id) == 1
def test_committee_change_with_deregister_then_register(
        smc_handler):  # noqa: F811
    w3 = smc_handler.web3

    # Register notary 0~8 and fast forward to next period
    batch_register(smc_handler, 0, 8)
    fast_forward(smc_handler, 1)

    # Update notary sample size
    update_notary_sample_size(smc_handler)

    notary_pool_list = get_notary_pool_list(smc_handler)
    # Choose the first sampled notary and deregister it
    notary = get_committee_list(smc_handler, 0)[0]
    notary_index = notary_pool_list.index(notary)
    smc_handler.deregister_notary(
        private_key=NotaryAccount(notary_index).private_key)
    mine(w3, 1)
    # Check that first slot in committee is now empty
    assert smc_handler.get_member_of_committee(0, 0) == b'\x00' * 20

    # Register notary 9
    smc_handler.register_notary(private_key=NotaryAccount(9).private_key)
    mine(w3, 1)
    # Check that first slot in committee is replaced by notary 9
    assert smc_handler.get_member_of_committee(
        0, 0) == NotaryAccount(9).canonical_address
def test_get_sample_result(smc_handler):  # noqa: F811
    w3 = smc_handler.web3

    # Register notary 0~8 and fast forward to next period
    batch_register(smc_handler, 0, 8)
    fast_forward(smc_handler, 1)

    # Update notary sample size
    current_period = w3.eth.blockNumber // smc_handler.config['PERIOD_LENGTH']
    update_notary_sample_size(smc_handler)

    # Get all committee of current period
    committee_group = []
    for shard_id in range(smc_handler.config['SHARD_COUNT']):
        committee_group.append(get_committee_list(smc_handler, shard_id))

    # Get sampling result for notary 0
    notary_0 = NotaryAccount(0)
    _, notary_0_pool_index = smc_handler.get_notary_info(
        notary_0.checksum_address)
    notary_0_sampling_result = get_sample_result(smc_handler,
                                                 notary_0_pool_index)

    for (period, shard_id, sampling_index) in notary_0_sampling_result:
        assert period == current_period
        # Check that notary is correctly sampled in get_committee_list
        assert committee_group[shard_id][
            sampling_index] == notary_0.canonical_address
        # Check that notary is correctly sampled in SMC
        assert smc_handler.get_member_of_committee(shard_id, sampling_index) \
            == notary_0.canonical_address
Exemple #12
0
def test_normal_add_header(smc_handler):  # noqa: F811
    w3 = smc_handler.web3

    # Register notary 0~2 and fast forward to next period
    batch_register(smc_handler, 0, 2)
    fast_forward(smc_handler, 1)
    current_period = w3.eth.blockNumber // smc_handler.config['PERIOD_LENGTH']
    assert current_period == 1
    # Check that collation records of shard 0 and shard 1 have not been updated before
    assert smc_handler.records_updated_period(0) == 0
    assert smc_handler.records_updated_period(1) == 0

    CHUNK_ROOT_1_0 = b'\x10' * 32
    smc_handler.add_header(
        shard_id=0,
        period=1,
        chunk_root=CHUNK_ROOT_1_0,
        private_key=NotaryAccount(index=0).private_key,
    )
    mine(w3=w3, num_blocks=1)
    # Check that collation record of shard 0 has been updated
    assert smc_handler.records_updated_period(0) == 1
    assert smc_handler.get_collation_chunk_root(shard_id=0,
                                                period=1) == CHUNK_ROOT_1_0

    fast_forward(smc_handler, 1)
    current_period = w3.eth.blockNumber // smc_handler.config['PERIOD_LENGTH']
    assert current_period == 2

    CHUNK_ROOT_2_0 = b'\x20' * 32
    smc_handler.add_header(
        shard_id=0,
        period=2,
        chunk_root=CHUNK_ROOT_2_0,
        private_key=NotaryAccount(index=0).private_key,
    )
    mine(w3=w3, num_blocks=1)
    # Check that collation record of shard 0 has been updated
    assert smc_handler.records_updated_period(0) == 2
    assert smc_handler.get_collation_chunk_root(shard_id=0,
                                                period=2) == CHUNK_ROOT_2_0
    # Check that collation record of shard 1 has never been updated
    assert smc_handler.records_updated_period(1) == 0

    CHUNK_ROOT_2_1 = b'\x21' * 32
    smc_handler.add_header(
        shard_id=1,
        period=2,
        chunk_root=CHUNK_ROOT_2_1,
        private_key=NotaryAccount(index=0).private_key,
    )
    mine(w3=w3, num_blocks=1)
    # Check that collation record of shard 1 has been updated
    assert smc_handler.records_updated_period(1) == 2
    assert smc_handler.get_collation_chunk_root(shard_id=1,
                                                period=2) == CHUNK_ROOT_2_1
def test_deregister_and_new_notary_register(smc_handler):  # noqa: F811
    w3 = smc_handler.web3

    notary_0 = NotaryAccount(0)

    # Register notary 0
    smc_handler.register_notary(private_key=notary_0.private_key)
    mine(w3, 1)
    notary_pool_length = smc_handler.notary_pool_len()
    assert notary_pool_length == 1

    notary_2 = NotaryAccount(2)

    # Register notary 1~3
    batch_register(smc_handler, 1, 3)

    notary_pool_length = smc_handler.notary_pool_len()
    assert notary_pool_length == 4
    # Check that empty_slots_stack is empty
    empty_slots_stack_top = smc_handler.empty_slots_stack_top()
    assert empty_slots_stack_top == 0

    # Fast foward
    fast_forward(smc_handler, 1)

    # Deregister notary 2
    smc_handler.deregister_notary(private_key=notary_2.private_key)
    mine(w3, 1)
    notary_pool_length = smc_handler.notary_pool_len()
    assert notary_pool_length == 3

    # Check that empty_slots_stack is not empty
    empty_slots_stack_top = smc_handler.empty_slots_stack_top()
    assert empty_slots_stack_top == 1
    _, notary_2_pool_index = smc_handler.get_notary_info(
        notary_2.checksum_address)
    empty_slots = smc_handler.empty_slots_stack(0)
    # Check that the top empty_slots entry point to notary 2
    assert empty_slots == notary_2_pool_index

    notary_4 = NotaryAccount(4)

    # Register notary 4
    smc_handler.register_notary(private_key=notary_4.private_key)
    mine(w3, 1)

    notary_pool_length = smc_handler.notary_pool_len()
    assert notary_pool_length == 4
    # Check that empty_slots_stack is empty
    empty_slots_stack_top = smc_handler.empty_slots_stack_top()
    assert empty_slots_stack_top == 0
    _, notary_4_pool_index = smc_handler.get_notary_info(
        notary_4.checksum_address)
    # Check that notary fill in notary 2's spot
    assert notary_4_pool_index == notary_2_pool_index
Exemple #14
0
def test_add_header_wrong_shard(smc_handler):  # noqa: F811
    w3 = smc_handler.web3
    shard_count = smc_handler.config['SHARD_COUNT']

    # Register notary 0~2 and fast forward to next period
    batch_register(smc_handler, 0, 2)
    fast_forward(smc_handler, 1)
    current_period = w3.eth.blockNumber // smc_handler.config['PERIOD_LENGTH']
    assert current_period == 1

    BLANK_CHUNK_ROOT = b'\x00' * 32
    CHUNK_ROOT_1_0 = b'\x10' * 32
    # Attempt to add collation record with illegal shard_id specified
    tx_hash = smc_handler.add_header(
        shard_id=shard_count + 1,
        period=1,
        chunk_root=CHUNK_ROOT_1_0,
        private_key=NotaryAccount(index=0).private_key,
    )
    mine(w3, 1)
    # Check that collation record of shard 0 has not been updated and transaction consume all gas
    # and no logs has been emitted
    assert smc_handler.records_updated_period(0) == 0
    assert smc_handler.get_collation_chunk_root(shard_id=0,
                                                period=1) == BLANK_CHUNK_ROOT
    assert len(w3.eth.getTransactionReceipt(tx_hash)['logs']) == 0

    # Second attempt to add collation record with illegal shard_id specified
    tx_hash = smc_handler.add_header(
        shard_id=-1,
        period=1,
        chunk_root=CHUNK_ROOT_1_0,
        private_key=NotaryAccount(index=0).private_key,
    )
    mine(w3, 1)
    # Check that collation record of shard 0 has not been updated and transaction consume all gas
    # and no logs has been emitted
    assert smc_handler.records_updated_period(0) == 0
    assert smc_handler.get_collation_chunk_root(shard_id=0,
                                                period=1) == BLANK_CHUNK_ROOT
    assert len(w3.eth.getTransactionReceipt(tx_hash)['logs']) == 0

    # Add correct collation record
    smc_handler.add_header(
        shard_id=0,
        period=1,
        chunk_root=CHUNK_ROOT_1_0,
        private_key=NotaryAccount(index=0).private_key,
    )
    mine(w3=w3, num_blocks=1)
    # Check that collation record of shard 0 has been updated
    assert smc_handler.records_updated_period(0) == 1
    assert smc_handler.get_collation_chunk_root(shard_id=0,
                                                period=1) == CHUNK_ROOT_1_0
def test_series_of_deregister_starting_from_bottom_of_the_stack(
        smc_handler):  # noqa: F811
    w3 = smc_handler.web3

    notary_0 = NotaryAccount(0)
    notary_1 = NotaryAccount(1)
    notary_2 = NotaryAccount(2)

    # Register notary 0~2
    batch_register(smc_handler, 0, 2)

    # Fast forward to next period
    fast_forward(smc_handler, 1)

    # Deregister from notary 0 to notary 2
    # Deregister notary 0
    smc_handler.deregister_notary(private_key=notary_0.private_key)
    mine(w3, 1)
    _, notary_0_pool_index = smc_handler.get_notary_info(
        notary_0.checksum_address)
    next_period_notary_sample_size = smc_handler.next_period_notary_sample_size(
    )
    # Check that next_period_notary_sample_size remains the same
    assert next_period_notary_sample_size == 3
    # Deregister notary 1
    smc_handler.deregister_notary(private_key=notary_1.private_key)
    mine(w3, 1)
    _, notary_1_pool_index = smc_handler.get_notary_info(
        notary_1.checksum_address)
    next_period_notary_sample_size = smc_handler.next_period_notary_sample_size(
    )
    # Check that next_period_notary_sample_size remains the same
    assert next_period_notary_sample_size == 3
    # Deregister notary 2
    smc_handler.deregister_notary(private_key=notary_2.private_key)
    mine(w3, 1)
    # Check that current_period_notary_sample_size is updated
    current_period_notary_sample_size = smc_handler.current_period_notary_sample_size(
    )
    assert current_period_notary_sample_size == 3
    _, notary_2_pool_index = smc_handler.get_notary_info(
        notary_2.checksum_address)
    next_period_notary_sample_size = smc_handler.next_period_notary_sample_size(
    )
    assert next_period_notary_sample_size == 3

    # Fast forward to next period
    fast_forward(smc_handler, 1)

    # Update notary sample size
    update_notary_sample_size(smc_handler)
    current_period_notary_sample_size = smc_handler.current_period_notary_sample_size(
    )
    assert current_period_notary_sample_size == next_period_notary_sample_size
def test_series_of_deregister_starting_from_top_of_the_stack(
        smc_handler):  # noqa: F811
    w3 = smc_handler.web3

    notary_0 = NotaryAccount(0)
    notary_1 = NotaryAccount(1)
    notary_2 = NotaryAccount(2)

    # Register notary 0~2
    batch_register(smc_handler, 0, 2)
    next_period_notary_sample_size = smc_handler.next_period_notary_sample_size(
    )
    assert next_period_notary_sample_size == 3

    # Fast forward to next period
    fast_forward(smc_handler, 1)

    # Deregister from notary 2 to notary 0
    # Deregister notary 2
    smc_handler.deregister_notary(private_key=notary_2.private_key)
    mine(w3, 1)
    # Check that current_period_notary_sample_size is updated
    current_period_notary_sample_size = smc_handler.current_period_notary_sample_size(
    )
    assert current_period_notary_sample_size == 3
    # Check that next_period_notary_sample_size remains the samev
    next_period_notary_sample_size = smc_handler.next_period_notary_sample_size(
    )
    assert next_period_notary_sample_size == 3
    # Deregister notary 1
    smc_handler.deregister_notary(private_key=notary_1.private_key)
    mine(w3, 1)
    # Check that next_period_notary_sample_size remains the same
    next_period_notary_sample_size = smc_handler.next_period_notary_sample_size(
    )
    assert next_period_notary_sample_size == 3
    # Deregister notary 0
    smc_handler.deregister_notary(private_key=notary_0.private_key)
    mine(w3, 1)
    # Check that next_period_notary_sample_size remains the same
    next_period_notary_sample_size = smc_handler.next_period_notary_sample_size(
    )
    assert next_period_notary_sample_size == 3

    # Fast forward to next period
    fast_forward(smc_handler, 1)

    # Update notary sample size
    update_notary_sample_size(smc_handler)
    current_period_notary_sample_size = smc_handler.current_period_notary_sample_size(
    )
    assert current_period_notary_sample_size == next_period_notary_sample_size
def test_get_member_of_committee_with_non_member(smc_handler):  # noqa: F811
    # Register notary 0~8 and fast forward to next period
    batch_register(smc_handler, 0, 8)
    fast_forward(smc_handler, 1)

    # Update notary sample size
    update_notary_sample_size(smc_handler)

    notary_pool_list = get_notary_pool_list(smc_handler)
    shard_0_committee_list = get_committee_list(smc_handler, 0)
    for (i, notary) in enumerate(shard_0_committee_list):
        notary_index = notary_pool_list.index(notary)
        next_notary_index = notary_index + 1 \
            if notary_index < len(notary_pool_list) - 1 else 0
        next_notary = notary_pool_list[next_notary_index]
        assert not (smc_handler.get_member_of_committee(0, i) == next_notary)
Exemple #18
0
def test_double_add_header(smc_handler):  # noqa: F811
    w3 = smc_handler.web3

    # Register notary 0~2 and fast forward to next period
    batch_register(smc_handler, 0, 2)
    fast_forward(smc_handler, 1)
    current_period = w3.eth.blockNumber // smc_handler.config['PERIOD_LENGTH']
    assert current_period == 1

    CHUNK_ROOT_1_0 = b'\x10' * 32
    smc_handler.add_header(
        shard_id=0,
        period=1,
        chunk_root=CHUNK_ROOT_1_0,
        private_key=NotaryAccount(index=0).private_key,
    )
    mine(w3=w3, num_blocks=1)
    # Check that collation record of shard 0 has been updated
    assert smc_handler.records_updated_period(0) == 1
    assert smc_handler.get_collation_chunk_root(shard_id=0,
                                                period=1) == CHUNK_ROOT_1_0

    # Attempt to add collation record again with same collation record
    tx_hash = smc_handler.add_header(
        shard_id=0,
        period=1,
        chunk_root=CHUNK_ROOT_1_0,
        private_key=NotaryAccount(index=0).private_key,
    )
    mine(w3, 1)
    # Check that transaction consume all gas and no logs has been emitted
    assert len(w3.eth.getTransactionReceipt(tx_hash)['logs']) == 0

    # Attempt to add collation record again with different chunk root
    tx_hash = smc_handler.add_header(
        shard_id=0,
        period=1,
        chunk_root=b'\x56' * 32,
        private_key=NotaryAccount(index=0).private_key,
    )
    mine(w3, 1)
    # Check that collation record of shard 0 remains the same and transaction consume all gas
    # and no logs has been emitted
    assert smc_handler.records_updated_period(0) == 1
    assert smc_handler.get_collation_chunk_root(shard_id=0,
                                                period=1) == CHUNK_ROOT_1_0
    assert len(w3.eth.getTransactionReceipt(tx_hash)['logs']) == 0
Exemple #19
0
def test_submit_vote_by_notary_sampled_multiple_times(
        smc_handler):  # noqa: F811
    w3 = smc_handler.web3
    # We only vote in shard 0 for ease of testing
    shard_id = 0

    # Here we only register 5 notaries so it's guaranteed that at least
    # one notary is going to be sampled twice.
    # Register notary 0~4 and fast forward to next period
    batch_register(smc_handler, 0, 4)
    fast_forward(smc_handler, 1)
    current_period = w3.eth.blockNumber // smc_handler.config['PERIOD_LENGTH']
    assert current_period == 1

    # Add collation record
    CHUNK_ROOT_1_0 = b'\x10' * 32
    smc_handler.add_header(
        shard_id=shard_id,
        period=current_period,
        chunk_root=CHUNK_ROOT_1_0,
        private_key=NotaryAccount(index=0).private_key,
    )
    mine(w3, 1)

    # Find the notary that's sampled more than one time
    for pool_index in range(5):
        sample_index_list = [
            sample_index
            for (_, _shard_id,
                 sample_index) in get_sample_result(smc_handler, pool_index)
            if _shard_id == shard_id
        ]
        if len(sample_index_list) > 1:
            vote_count = len(sample_index_list)
            for sample_index in sample_index_list:
                smc_handler.submit_vote(
                    shard_id=shard_id,
                    period=current_period,
                    chunk_root=CHUNK_ROOT_1_0,
                    index=sample_index,
                    private_key=NotaryAccount(index=pool_index).private_key,
                )
                mine(w3, 1)
            # Check that every vote is successfully casted even by the same notary
            assert smc_handler.get_vote_count(shard_id) == vote_count
            break
def test_committee_lists_generated_are_different(smc_handler):  # noqa: F811
    # Register notary 0~8 and fast forward to next period
    batch_register(smc_handler, 0, 8)
    fast_forward(smc_handler, 1)

    # Update notary sample size
    update_notary_sample_size(smc_handler)

    shard_0_committee_list = get_committee_list(smc_handler, 0)
    shard_1_committee_list = get_committee_list(smc_handler, 1)
    assert shard_0_committee_list != shard_1_committee_list

    # Fast forward to next period
    fast_forward(smc_handler, 1)

    # Update notary sample size
    update_notary_sample_size(smc_handler)

    new_shard_0_committee_list = get_committee_list(smc_handler, 0)
    assert new_shard_0_committee_list != shard_0_committee_list
Exemple #21
0
def test_submit_vote_by_non_eligible_notary(smc_handler):  # noqa: F811
    w3 = smc_handler.web3
    # We only vote in shard 0 for ease of testing
    shard_id = 0

    # Register notary 0~8 and fast forward to next period
    batch_register(smc_handler, 0, 8)
    fast_forward(smc_handler, 1)
    current_period = w3.eth.blockNumber // smc_handler.config['PERIOD_LENGTH']
    assert current_period == 1

    # Add collation record
    CHUNK_ROOT_1_0 = b'\x10' * 32
    smc_handler.add_header(
        shard_id=shard_id,
        period=current_period,
        chunk_root=CHUNK_ROOT_1_0,
        private_key=NotaryAccount(index=0).private_key,
    )
    mine(w3, 1)

    sample_index = 0
    pool_index = sampling(smc_handler, shard_id)[sample_index]
    wrong_pool_index = 0 if pool_index != 0 else 1
    tx_hash = smc_handler.submit_vote(
        shard_id=shard_id,
        period=current_period,
        chunk_root=CHUNK_ROOT_1_0,
        index=sample_index,
        # Vote by non-eligible notary
        private_key=NotaryAccount(wrong_pool_index).private_key,
    )
    mine(w3, 1)
    # Check that transaction failed and vote count remains the same
    # and no logs has been emitted
    assert len(w3.eth.getTransactionReceipt(tx_hash)['logs']) == 0
    assert smc_handler.get_vote_count(shard_id) == 0
    assert not smc_handler.has_notary_voted(shard_id, sample_index)
def test_deregister_then_register(smc_handler):  # noqa: F811
    w3 = smc_handler.web3

    notary_0 = NotaryAccount(0)

    # Register notary 0
    smc_handler.register_notary(private_key=notary_0.private_key)
    mine(w3, 1)
    does_notary_exist = smc_handler.does_notary_exist(
        notary_0.checksum_address)
    assert does_notary_exist
    notary_pool_length = smc_handler.notary_pool_len()
    assert notary_pool_length == 1

    # Fast foward
    fast_forward(smc_handler, 1)

    # Deregister notary 0
    smc_handler.deregister_notary(private_key=notary_0.private_key)
    current_period = w3.eth.blockNumber // smc_handler.config['PERIOD_LENGTH']
    mine(w3, 1)
    does_notary_exist = smc_handler.does_notary_exist(
        notary_0.checksum_address)
    assert does_notary_exist
    notary_deregistered_period, notary_pool_index = smc_handler.get_notary_info(
        notary_0.checksum_address)
    assert notary_deregistered_period == current_period
    notary_pool_length = smc_handler.notary_pool_len()
    assert notary_pool_length == 0

    # Register again right away
    tx_hash = smc_handler.register_notary(private_key=notary_0.private_key)
    mine(w3, 1)
    # Check pool remain the same and the transaction consume all gas
    # and no logs has been emitted
    notary_pool_length = smc_handler.notary_pool_len()
    assert notary_pool_length == 0
    assert len(w3.eth.getTransactionReceipt(tx_hash)['logs']) == 0
def test_status_checking_functions(smc_handler,
                                   smc_testing_config):  # noqa: F811
    w3 = smc_handler.web3
    config = smc_testing_config
    shard_tracker = ShardTracker(
        w3=w3,
        config=config,
        shard_id=0,
        smc_handler_address=smc_handler.address,
    )

    # Register nine notaries
    batch_register(smc_handler, 0, 8)
    # Check that registration log was/was not emitted accordingly
    assert shard_tracker.is_notary_registered(
        notary=NotaryAccount(0).checksum_address)
    assert shard_tracker.is_notary_registered(
        notary=NotaryAccount(5).checksum_address)
    assert not shard_tracker.is_notary_registered(
        notary=NotaryAccount(9).checksum_address)
    fast_forward(smc_handler, 1)

    # Check that add header log has not been emitted yet
    current_period = w3.eth.blockNumber // config['PERIOD_LENGTH']
    assert not shard_tracker.is_new_header_added(period=current_period)
    # Add header in multiple shards
    CHUNK_ROOT_1_0 = b'\x10' * 32
    smc_handler.add_header(
        shard_id=0,
        period=current_period,
        chunk_root=CHUNK_ROOT_1_0,
        private_key=NotaryAccount(0).private_key,
    )
    CHUNK_ROOT_1_7 = b'\x17' * 32
    smc_handler.add_header(
        shard_id=7,
        period=current_period,
        chunk_root=CHUNK_ROOT_1_7,
        private_key=NotaryAccount(7).private_key,
    )
    CHUNK_ROOT_1_3 = b'\x13' * 32
    smc_handler.add_header(
        shard_id=3,
        period=current_period,
        chunk_root=CHUNK_ROOT_1_3,
        private_key=NotaryAccount(3).private_key,
    )
    mine(w3, 1)
    # Check that add header log was successfully emitted
    assert shard_tracker.is_new_header_added(period=current_period)

    # Check that there has not been enough votes yet in shard 0
    assert not shard_tracker.has_enough_vote(period=current_period)
    # Submit three votes in shard 0 and one vote in shard 7
    for sample_index in range(3):
        pool_index = sampling(smc_handler, 0)[sample_index]
        smc_handler.submit_vote(
            shard_id=0,
            period=current_period,
            chunk_root=CHUNK_ROOT_1_0,
            index=sample_index,
            private_key=NotaryAccount(pool_index).private_key,
        )
        mine(w3, 1)
    sample_index = 0
    pool_index = sampling(smc_handler, 7)[sample_index]
    smc_handler.submit_vote(
        shard_id=7,
        period=current_period,
        chunk_root=CHUNK_ROOT_1_7,
        index=sample_index,
        private_key=NotaryAccount(pool_index).private_key,
    )
    mine(w3, 1)
    # Check that there has not been enough votes yet in shard 0
    # Only three votes in shard 0 while four is required
    assert not shard_tracker.has_enough_vote(period=current_period)
    # Cast the fourth vote
    sample_index = 3
    pool_index = sampling(smc_handler, 0)[sample_index]
    smc_handler.submit_vote(
        shard_id=0,
        period=current_period,
        chunk_root=CHUNK_ROOT_1_0,
        index=sample_index,
        private_key=NotaryAccount(pool_index).private_key,
    )
    mine(w3, 1)
    # Check that there are enough votes now in shard 0
    assert shard_tracker.has_enough_vote(period=current_period)
    # Proceed to next period
    fast_forward(smc_handler, 1)

    # Go back and check the status of header and vote counts in last period
    current_period = w3.eth.blockNumber // config['PERIOD_LENGTH']
    assert shard_tracker.is_new_header_added(period=(current_period - 1))
    assert shard_tracker.has_enough_vote(period=(current_period - 1))

    # Deregister
    smc_handler.deregister_notary(private_key=NotaryAccount(0).private_key)
    mine(w3, 1)
    # Check that deregistration log was/was not emitted accordingly
    assert shard_tracker.is_notary_deregistered(
        NotaryAccount(0).checksum_address)
    assert not shard_tracker.is_notary_deregistered(
        NotaryAccount(5).checksum_address)

    # Fast foward to end of lock up
    fast_forward(smc_handler, smc_handler.config['NOTARY_LOCKUP_LENGTH'] + 1)
    # Release
    smc_handler.release_notary(private_key=NotaryAccount(0).private_key)
    mine(w3, 1)
    # Check that log was successfully emitted
    assert shard_tracker.is_notary_released(NotaryAccount(0).checksum_address)
Exemple #24
0
def test_normal_submit_vote(smc_handler):  # noqa: F811
    w3 = smc_handler.web3
    # We only vote in shard 0 for ease of testing
    shard_id = 0

    # Register notary 0~8 and fast forward to next period
    batch_register(smc_handler, 0, 8)
    fast_forward(smc_handler, 1)
    current_period = w3.eth.blockNumber // smc_handler.config['PERIOD_LENGTH']
    assert current_period == 1

    # Add collation record
    CHUNK_ROOT_1_0 = b'\x10' * 32
    smc_handler.add_header(
        shard_id=shard_id,
        period=current_period,
        chunk_root=CHUNK_ROOT_1_0,
        private_key=NotaryAccount(index=0).private_key,
    )
    mine(w3, 1)

    # Get the first notary in the sample list in this period
    sample_index = 0
    pool_index = sampling(smc_handler, shard_id)[sample_index]
    # Check that voting record does not exist prior to voting
    assert smc_handler.get_vote_count(shard_id) == 0
    assert not smc_handler.has_notary_voted(shard_id, sample_index)
    # First notary vote
    smc_handler.submit_vote(
        shard_id=shard_id,
        period=current_period,
        chunk_root=CHUNK_ROOT_1_0,
        index=sample_index,
        private_key=NotaryAccount(index=pool_index).private_key,
    )
    mine(w3, 1)
    # Check that vote has been casted successfully
    assert smc_handler.get_vote_count(shard_id) == 1
    assert smc_handler.has_notary_voted(shard_id, sample_index)

    # Check that collation is not elected and forward to next period
    assert not smc_handler.get_collation_is_elected(shard_id=shard_id,
                                                    period=current_period)
    fast_forward(smc_handler, 1)
    current_period = w3.eth.blockNumber // smc_handler.config['PERIOD_LENGTH']
    assert current_period == 2

    # Add collation record
    CHUNK_ROOT_2_0 = b'\x20' * 32
    smc_handler.add_header(
        shard_id=shard_id,
        period=current_period,
        chunk_root=CHUNK_ROOT_2_0,
        private_key=NotaryAccount(index=0).private_key,
    )
    mine(w3, 1)

    # Check that vote count is zero
    assert smc_handler.get_vote_count(shard_id) == 0
    # Keep voting until the collation is elected.
    for (sample_index,
         pool_index) in enumerate(sampling(smc_handler, shard_id)):
        if smc_handler.get_collation_is_elected(shard_id=shard_id,
                                                period=current_period):
            assert smc_handler.get_vote_count(
                shard_id) == smc_handler.config['QUORUM_SIZE']
            break
        # Check that voting record does not exist prior to voting
        assert not smc_handler.has_notary_voted(shard_id, sample_index)
        # Vote
        smc_handler.submit_vote(
            shard_id=shard_id,
            period=current_period,
            chunk_root=CHUNK_ROOT_2_0,
            index=sample_index,
            private_key=NotaryAccount(index=pool_index).private_key,
        )
        mine(w3, 1)
        # Check that vote has been casted successfully
        assert smc_handler.has_notary_voted(shard_id, sample_index)
    # Check that the collation is indeed elected.
    assert smc_handler.get_collation_is_elected(shard_id=shard_id,
                                                period=current_period)
Exemple #25
0
def test_log_emission(smc_handler):  # noqa: F811
    w3 = smc_handler.web3
    log_handler = LogHandler(w3, smc_handler.config['PERIOD_LENGTH'])
    shard_tracker = ShardTracker(
        config=smc_handler.config,
        shard_id=0,
        log_handler=log_handler,
        smc_handler_address=smc_handler.address,
    )
    notary = NotaryAccount(0)

    # Register
    smc_handler.register_notary(private_key=notary.private_key)
    mine(w3, 1)
    # Check that log was successfully emitted
    log = shard_tracker.get_register_notary_logs()[0]
    assert getattr(log, 'index_in_notary_pool') == 0 and \
        getattr(log, 'notary') == notary.checksum_address
    fast_forward(smc_handler, 1)

    # Add header
    CHUNK_ROOT_1_0 = b'\x10' * 32
    smc_handler.add_header(
        shard_id=0,
        period=1,
        chunk_root=CHUNK_ROOT_1_0,
        private_key=notary.private_key,
    )
    mine(w3, 1)
    # Check that log was successfully emitted
    log = shard_tracker.get_add_header_logs()[0]
    assert getattr(log, 'period') == 1 and getattr(log, 'shard_id') == 0 and \
        getattr(log, 'chunk_root') == CHUNK_ROOT_1_0

    # Submit vote
    sample_index = 0
    pool_index = sampling(smc_handler, 0)[sample_index]
    smc_handler.submit_vote(
        shard_id=0,
        period=1,
        chunk_root=CHUNK_ROOT_1_0,
        index=sample_index,
        private_key=NotaryAccount(pool_index).private_key,
    )
    mine(w3, 1)
    # Check that log was successfully emitted
    log = shard_tracker.get_submit_vote_logs()[0]
    assert getattr(log, 'period') == 1 and getattr(log, 'shard_id') == 0 and \
        getattr(log, 'chunk_root') == CHUNK_ROOT_1_0 and \
        getattr(log, 'notary') == NotaryAccount(pool_index).checksum_address
    fast_forward(smc_handler, 1)

    # Deregister
    smc_handler.deregister_notary(private_key=notary.private_key)
    mine(w3, 1)
    # Check that log was successfully emitted
    log = shard_tracker.get_deregister_notary_logs()[0]
    assert getattr(log, 'index_in_notary_pool') == 0 and \
        getattr(log, 'notary') == notary.checksum_address and \
        getattr(log, 'deregistered_period') == 2
    # Fast foward to end of lock up
    fast_forward(smc_handler, smc_handler.config['NOTARY_LOCKUP_LENGTH'] + 1)

    # Release
    smc_handler.release_notary(private_key=notary.private_key)
    mine(w3, 1)
    # Check that log was successfully emitted
    log = shard_tracker.get_release_notary_logs()[0]
    assert getattr(log, 'index_in_notary_pool') == 0 and \
        getattr(log, 'notary') == notary.checksum_address

    # Test fetching logs in past period
    assert shard_tracker.get_register_notary_logs(from_period=0, to_period=0)
    assert shard_tracker.get_add_header_logs(from_period=1, to_period=1)
    assert shard_tracker.get_submit_vote_logs(from_period=1, to_period=1)
    assert shard_tracker.get_deregister_notary_logs(from_period=2, to_period=2)
    assert shard_tracker.get_release_notary_logs(
        from_period=(3 + smc_handler.config['NOTARY_LOCKUP_LENGTH']),
        to_period=(3 + smc_handler.config['NOTARY_LOCKUP_LENGTH'])
    )
def test_normal_update_notary_sample_size(smc_handler):  # noqa: F811
    w3 = smc_handler.web3

    notary_0 = NotaryAccount(0)

    # Register notary 0
    smc_handler.register_notary(private_key=notary_0.private_key)
    mine(w3, 1)
    _, notary_0_pool_index = smc_handler.get_notary_info(
        notary_0.checksum_address)
    assert notary_0_pool_index == 0
    next_period_notary_sample_size = smc_handler.next_period_notary_sample_size(
    )
    assert (notary_0_pool_index + 1) == next_period_notary_sample_size

    notary_1 = NotaryAccount(1)

    # Register notary 1
    smc_handler.register_notary(private_key=notary_1.private_key)
    mine(w3, 1)

    _, notary_1_pool_index = smc_handler.get_notary_info(
        notary_1.checksum_address)
    assert notary_1_pool_index == 1
    next_period_notary_sample_size = smc_handler.next_period_notary_sample_size(
    )
    assert (notary_1_pool_index + 1) == next_period_notary_sample_size

    # Check that it's not yet the time to update notary sample size,
    # i.e., current period is the same as latest period the notary sample size was updated.
    current_period = w3.eth.blockNumber // smc_handler.config['PERIOD_LENGTH']
    notary_sample_size_updated_period = smc_handler.notary_sample_size_updated_period(
    )
    assert current_period == notary_sample_size_updated_period

    # Check that current_period_notary_sample_size has not been updated before
    current_period_notary_sample_size = smc_handler.current_period_notary_sample_size(
    )
    assert 0 == current_period_notary_sample_size

    # Try updating notary sample size
    update_notary_sample_size(smc_handler)
    # Check that current_period_notary_sample_size is not updated,
    # i.e., updating notary sample size failed.
    assert 0 == current_period_notary_sample_size

    # fast forward to next period
    fast_forward(smc_handler, 1)

    # Register notary 2
    # NOTE: Registration would also invoke update_notary_sample_size function
    notary_2 = NotaryAccount(2)
    smc_handler.register_notary(private_key=notary_2.private_key)
    mine(w3, 1)

    # Check that current_period_notary_sample_size is updated,
    # i.e., it is assigned the value of next_period_notary_sample_size.
    current_period_notary_sample_size = smc_handler.current_period_notary_sample_size(
    )
    assert next_period_notary_sample_size == current_period_notary_sample_size

    # Check that notary sample size is updated in this period
    current_period = w3.eth.blockNumber // smc_handler.config['PERIOD_LENGTH']
    notary_sample_size_updated_period = smc_handler.notary_sample_size_updated_period(
    )
    assert current_period == notary_sample_size_updated_period