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_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_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_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_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)
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_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)