def test_view_change_data_multiple(view_change_service, data): # view 0 -> 1 data.view_no = 0 cp1 = Checkpoint(instId=0, viewNo=0, seqNoStart=0, seqNoEnd=10, digest='empty') data.checkpoints.add(cp1) data.stable_checkpoint = 0 data.prepared = [BatchID(0, 1, "digest1"), BatchID(0, 2, "digest2")] data.preprepared = [ BatchID(0, 1, "digest1"), BatchID(0, 2, "digest2"), BatchID(0, 3, "digest3") ] view_change_service.start_view_change() assert data.prepared == [] assert data.preprepared == [] assert data.view_no == 1 msg = get_view_change(view_change_service) assert msg.viewNo == 1 assert msg.prepared == [(0, 1, "digest1"), (0, 2, "digest2")] assert msg.preprepared == [(0, 1, "digest1"), (0, 2, "digest2"), (0, 3, "digest3")] assert msg.stableCheckpoint == 0 assert msg.checkpoints == [cp1] # view 1 -> 2 data.view_no = 1 cp2 = Checkpoint(instId=0, viewNo=1, seqNoStart=10, seqNoEnd=20, digest='empty') data.checkpoints.add(cp2) data.stable_checkpoint = 0 data.prepared = [BatchID(1, 11, "digest11"), BatchID(1, 12, "digest12")] data.preprepared = [ BatchID(1, 11, "digest11"), BatchID(1, 12, "digest12"), BatchID(1, 13, "digest13") ] view_change_service.start_view_change() assert data.prepared == [] assert data.preprepared == [] assert data.view_no == 2 msg = get_view_change(view_change_service) assert msg.viewNo == 2 assert msg.prepared == [(0, 1, "digest1"), (0, 2, "digest2"), (1, 11, "digest11"), (1, 12, "digest12")] assert msg.preprepared == [(0, 1, "digest1"), (0, 2, "digest2"), (0, 3, "digest3"), (1, 11, "digest11"), (1, 12, "digest12"), (1, 13, "digest13")] assert msg.stableCheckpoint == 0 assert msg.checkpoints == [cp1, cp2]
def test_view_change_data(view_change_service, data): data.view_no = 1 data.checkpoints.clear() cp = Checkpoint(instId=0, viewNo=1, seqNoStart=0, seqNoEnd=10, digest=cp_digest(10)) data.checkpoints.add(cp) data.stable_checkpoint = 10 data.prepared = [BatchID(0, 1, "digest1"), BatchID(0, 2, "digest2")] data.preprepared = [ BatchID(0, 1, "digest1"), BatchID(0, 2, "digest2"), BatchID(0, 3, "digest3") ] view_change_service._bus.send(NeedViewChange()) assert data.view_no == 2 msg = get_view_change(view_change_service) assert msg.viewNo == 2 assert msg.prepared == [(0, 1, "digest1"), (0, 2, "digest2")] assert msg.preprepared == [(0, 1, "digest1"), (0, 2, "digest2"), (0, 3, "digest3")] assert msg.stableCheckpoint == 10 assert msg.checkpoints == [cp]
def test_view_change_data(view_change_service, data): data.view_no = 1 cp = Checkpoint(instId=0, viewNo=1, seqNoStart=0, seqNoEnd=10, digest='empty') data.checkpoints.add(cp) data.stable_checkpoint = 10 data.prepared = [BatchID(0, 1, "digest1"), BatchID(0, 2, "digest2")] data.preprepared = [ BatchID(0, 1, "digest1"), BatchID(0, 2, "digest2"), BatchID(0, 3, "digest3") ] view_change_service.start_view_change() assert data.prepared == [] assert data.preprepared == [] assert data.view_no == 2 msg = get_view_change(view_change_service) assert msg.viewNo == 2 assert msg.prepared == [(0, 1, "digest1"), (0, 2, "digest2")] assert msg.preprepared == [(0, 1, "digest1"), (0, 2, "digest2"), (0, 3, "digest3")] assert msg.stableCheckpoint == 10 assert msg.checkpoints == [cp]
def test_view_change_data_multiple_respects_checkpoint(view_change_service, data): # view 0 -> 1 data.view_no = 0 cp1 = Checkpoint(instId=0, viewNo=0, seqNoStart=0, seqNoEnd=10, digest=cp_digest(10)) data.checkpoints.add(cp1) data.stable_checkpoint = 0 data.prepared = [BatchID(0, 1, "digest1"), BatchID(0, 2, "digest2")] data.preprepared = [ BatchID(0, 1, "digest1"), BatchID(0, 2, "digest2"), BatchID(0, 3, "digest3") ] view_change_service._bus.send(NeedViewChange()) assert data.view_no == 1 msg = get_view_change(view_change_service) assert msg.viewNo == 1 assert msg.prepared == [(0, 1, "digest1"), (0, 2, "digest2")] assert msg.preprepared == [(0, 1, "digest1"), (0, 2, "digest2"), (0, 3, "digest3")] assert msg.stableCheckpoint == 0 assert msg.checkpoints == [data.initial_checkpoint, cp1] # view 1 -> 2 data.view_no = 1 cp2 = Checkpoint(instId=0, viewNo=1, seqNoStart=0, seqNoEnd=20, digest=cp_digest(20)) data.checkpoints.add(cp2) data.stable_checkpoint = 10 # Here we simulate checkpoint stabilization logic of CheckpointService, which # clears all checkpoints below stabilized one data.checkpoints.remove(data.initial_checkpoint) data.prepared = [BatchID(1, 11, "digest11"), BatchID(1, 12, "digest12")] data.preprepared = [ BatchID(1, 11, "digest11"), BatchID(1, 12, "digest12"), BatchID(1, 13, "digest13") ] view_change_service._bus.send(NeedViewChange()) assert data.view_no == 2 msg = get_view_change(view_change_service) assert msg.viewNo == 2 assert msg.prepared == [(1, 11, "digest11"), (1, 12, "digest12")] assert msg.preprepared == [(1, 11, "digest11"), (1, 12, "digest12"), (1, 13, "digest13")] assert msg.stableCheckpoint == 10 assert msg.checkpoints == [cp1, cp2]
def test_update_shared_data_on_mew_view_checkpoint_applied(internal_bus, orderer): orderer._data.preprepared = [] orderer._data.prepared = [] old_data = copy_shared_data(orderer._data) initial_view_no = 3 new_view = create_new_view(initial_view_no=initial_view_no, stable_cp=200) internal_bus.send(NewViewCheckpointsApplied(view_no=initial_view_no + 1, view_changes=new_view.viewChanges, checkpoint=new_view.checkpoint, batches=new_view.batches)) new_data = copy_shared_data(orderer._data) check_service_changed_only_owned_fields_in_shared_data(OrderingService, old_data, new_data) # preprepared are created for new view if orderer.is_master: assert orderer._data.preprepared assert orderer._data.preprepared == [BatchID(view_no=initial_view_no + 1, pp_seq_no=batch_id.pp_seq_no, pp_digest=batch_id.pp_digest) for batch_id in new_view.batches] assert orderer._data.prepared == [] else: assert orderer._data.preprepared == [] assert orderer._data.prepared == []
def check(vc: ViewChange): if pp_seq_no <= vc.stableCheckpoint: return False for _some_bid in vc.prepared: some_bid = BatchID(*_some_bid) if some_bid.pp_seq_no == pp_seq_no: return False return True
def check(vc: ViewChange): for _some_bid in vc.preprepared: some_bid = BatchID(*_some_bid) if some_bid.pp_seq_no != bid.pp_seq_no: continue if some_bid.pp_digest != bid.pp_digest: continue if some_bid.view_no >= bid.view_no: return True return False
def test_view_change_replaces_prepare(view_change_service, data): data.view_no = 0 data.prepared = [BatchID(0, 1, "digest1"), BatchID(0, 2, "digest2")] # view no 0->1 view_change_service._bus.send(NeedViewChange()) assert data.view_no == 1 msg = get_view_change(view_change_service) assert msg.viewNo == 1 assert msg.prepared == [(0, 1, "digest1"), (0, 2, "digest2")] # view no 1->2 # replace by different viewNo and digest data.prepared = [BatchID(1, 1, "digest11"), BatchID(1, 2, "digest22")] view_change_service._bus.send(NeedViewChange()) assert data.view_no == 2 msg = get_view_change(view_change_service) assert msg.viewNo == 2 assert msg.prepared == [(1, 1, "digest11"), (1, 2, "digest22")] # view no 2->3 # replace by different viewNo only data.prepared = [BatchID(2, 2, "digest22"), BatchID(2, 3, "digest3")] view_change_service._bus.send(NeedViewChange()) assert data.view_no == 3 msg = get_view_change(view_change_service) assert msg.viewNo == 3 assert msg.prepared == [(1, 1, "digest11"), (2, 2, "digest22"), (2, 3, "digest3")]
def _try_find_batch_for_pp_seq_no(self, vcs, pp_seq_no): for vc in vcs: for _bid in vc.prepared: bid = BatchID(*_bid) if bid.pp_seq_no != pp_seq_no: continue if not self._is_batch_prepared(bid, vcs): continue if not self._is_batch_preprepared(bid, vcs): continue return bid return None
def check(vc: ViewChange): if bid.pp_seq_no <= vc.stableCheckpoint: return False for _some_bid in vc.prepared: some_bid = BatchID(*_some_bid) if some_bid.pp_seq_no != bid.pp_seq_no: continue # not ( (v' < v) OR (v'==v and d'==d) ) if some_bid.view_no > bid.view_no: return False if some_bid.view_no >= bid.view_no and some_bid.pp_digest != bid.pp_digest: return False return True
def test_view_change_keeps_preprepare(view_change_service, data): data.view_no = 0 data.preprepared = [BatchID(0, 1, "digest1"), BatchID(0, 2, "digest2")] # view no 0->1 view_change_service.start_view_change() assert data.view_no == 1 assert data.preprepared == [] msg = get_view_change(view_change_service) assert msg.viewNo == 1 assert msg.preprepared == [(0, 1, "digest1"), (0, 2, "digest2")] # view no 1->2 # do not replace since different viewNo and digest data.preprepared = [BatchID(1, 1, "digest11"), BatchID(1, 2, "digest22")] view_change_service.start_view_change() assert data.view_no == 2 assert data.preprepared == [] msg = get_view_change(view_change_service) assert msg.viewNo == 2 assert msg.preprepared == [(0, 1, "digest1"), (0, 2, "digest2"), (1, 1, "digest11"), (1, 2, "digest22")] # view no 2->3 # replace by different viewNo only data.preprepared = [BatchID(2, 2, "digest22"), BatchID(2, 3, "digest3")] view_change_service.start_view_change() assert data.view_no == 3 assert data.preprepared == [] msg = get_view_change(view_change_service) assert msg.viewNo == 3 assert msg.preprepared == [(0, 1, "digest1"), (0, 2, "digest2"), (1, 1, "digest11"), (2, 2, "digest22"), (2, 3, "digest3")]
def create_batches(view_no): return [ BatchID(view_no, 11, "d1"), BatchID(view_no, 12, "d2"), BatchID(view_no, 13, "d3") ]