class ViewChange(MessageBase): typename = VIEW_CHANGE schema = ( (f.VIEW_NO.nm, NonNegativeNumberField()), (f.STABLE_CHECKPOINT.nm, NonNegativeNumberField()), (f.PREPARED.nm, IterableField(BatchIDField()) ), # list of tuples (view_no, pp_view_no, pp_seq_no, pp_digest) (f.PREPREPARED.nm, IterableField(BatchIDField()) ), # list of tuples (view_no, pp_view_no, pp_seq_no, pp_digest) (f.CHECKPOINTS.nm, IterableField(AnyField()) ) # list of Checkpoints TODO: should we change to tuples? ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) checkpoints = [] for chk in self.checkpoints: if isinstance(chk, dict): checkpoints.append(Checkpoint(**chk)) if checkpoints: self.checkpoints = checkpoints # The field `prepared` can to be a list of BatchIDs or of dicts. # If its a list of dicts then we need to deserialize it. if self.prepared and isinstance(self.prepared[0], dict): self.prepared = [ BatchID(**bid) for bid in self.prepared if isinstance(bid, dict) ] # The field `preprepared` can to be a list of BatchIDs or of dicts. # If its a list of dicts then we need to deserialize it. if self.preprepared and isinstance(self.preprepared[0], dict): self.preprepared = [ BatchID(**bid) for bid in self.preprepared if isinstance(bid, dict) ] def _asdict(self): result = super()._asdict() checkpoints = [] for chk in self.checkpoints: if isinstance(chk, dict): continue checkpoints.append(chk._asdict()) if checkpoints: result[f.CHECKPOINTS.nm] = checkpoints # The field `prepared` can to be a list of BatchIDs or of dicts. # If its a list of BatchID then we need to serialize it. if self.prepared and isinstance(self.prepared[0], BatchID): result[f.PREPARED.nm] = [bid._asdict() for bid in self.prepared] # The field `preprepared` can to be a list of BatchIDs or of dicts. # If its a list of BatchID then we need to serialize it. if self.preprepared and isinstance(self.preprepared[0], BatchID): result[f.PREPREPARED.nm] = [ bid._asdict() for bid in self.preprepared ] return result
class ViewChange(MessageBase): typename = VIEW_CHANGE schema = ( (f.VIEW_NO.nm, NonNegativeNumberField()), (f.STABLE_CHECKPOINT.nm, NonNegativeNumberField()), (f.PREPARED.nm, IterableField(BatchIDField())), # list of tuples (view_no, pp_seq_no, pp_digest) (f.PREPREPARED.nm, IterableField(BatchIDField())), # list of tuples (view_no, pp_seq_no, pp_digest) (f.CHECKPOINTS.nm, IterableField(AnyField())) # list of Checkpoints TODO: should we change to tuples? )
class NewView(MessageBase): typename = NEW_VIEW schema = ( (f.VIEW_NO.nm, NonNegativeNumberField()), (f.VIEW_CHANGES.nm, IterableField(ViewChangeField())), # list of tuples (node_name, view_change_digest) (f.CHECKPOINT.nm, AnyField()), # Checkpoint to be selected as stable (TODO: or tuple?) (f.BATCHES.nm, IterableField(BatchIDField())) # list of tuples (view_no, pp_view_no, pp_seq_no, pp_digest) # that should get into new view ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if isinstance(self.checkpoint, dict): self.checkpoint = Checkpoint(**self.checkpoint) # The field `batches` can to be a list of BatchIDs or of dicts. # If it's not a list of dicts then we don't need to deserialize it. if not self.batches or not isinstance(self.batches[0], dict): return self.batches = [BatchID(**bid) for bid in self.batches if isinstance(bid, dict)] def _asdict(self): result = super()._asdict() chk = self.checkpoint if not isinstance(chk, dict): result[f.CHECKPOINT.nm] = chk._asdict() # The field `batches` can to be a list of BatchIDs or of dicts. # If its a list of dicts then we don't need to serialize it. if not self.batches or not isinstance(self.batches[0], BatchID): return result result[f.BATCHES.nm] = [bid._asdict() for bid in self.batches] return result
class NewView(MessageBase): typename = NEW_VIEW schema = ( (f.VIEW_NO.nm, NonNegativeNumberField()), (f.VIEW_CHANGES.nm, IterableField(ViewChangeField())), # list of tuples (node_name, view_change_digest) (f.CHECKPOINT.nm, AnyField()), # Checkpoint to be selected as stable (TODO: or tuple?) (f.BATCHES.nm, IterableField(BatchIDField())) # list of tuples (view_no, pp_seq_no, pp_digest) # that should get into new view )
class OldViewPrePrepareRequest(MessageBase): typename = OLD_VIEW_PREPREPARE_REQ schema = ( (f.INST_ID.nm, NonNegativeNumberField()), (f.BATCH_IDS.nm, IterableField(BatchIDField())), )
from plenum.common.messages.fields import BatchIDField validator = BatchIDField() def test_valid(): assert not validator.validate((1, 1, "digest")) assert not validator.validate((0, 1, "digest")) assert not validator.validate((100, 0, "d")) def test_invalid_view_no(): assert validator.validate((-1, 1, "digest")) assert validator.validate(("aaa", 1, "digest")) def test_invalid_pp_seq_no(): assert validator.validate((1, -1, "digest")) assert validator.validate((1, "aaa", "digest")) def test_invalid_digest(): assert validator.validate((1, 1, "")) assert validator.validate((1, 1, 1))