def __init__(self, node: 'plenum.server.node.Node', instId: int,
                 config=None,
                 isMaster: bool = False,
                 bls_bft_replica: BlsBftReplica = None,
                 metrics: MetricsCollector = NullMetricsCollector(),
                 get_current_time=None,
                 get_time_for_3pc_batch=None):
        """
        Create a new replica.

        :param node: Node on which this replica is located
        :param instId: the id of the protocol instance the replica belongs to
        :param isMaster: is this a replica of the master protocol instance
        """
        HasActionQueue.__init__(self)
        self.get_current_time = get_current_time or time.perf_counter
        self.get_time_for_3pc_batch = get_time_for_3pc_batch or node.utc_epoch
        self.stats = Stats(TPCStat)
        self.config = config or getConfig()
        self.metrics = metrics

        self.inBoxRouter = Router(
            (ReqKey, self.readyFor3PC),
            (PrePrepare, self.process_three_phase_msg),
            (Prepare, self.process_three_phase_msg),
            (Commit, self.process_three_phase_msg),
            (Checkpoint, self.process_checkpoint),
        )

        self.threePhaseRouter = Replica3PRouter(
            self,
            (PrePrepare, self.processPrePrepare),
            (Prepare, self.processPrepare),
            (Commit, self.processCommit)
        )

        self.node = node
        self.instId = instId
        self.name = self.generateName(node.name, self.instId)
        self.logger = getlogger(self.name)
        self.validator = ReplicaValidator(self)
        self.stasher = ReplicaStasher(self)

        self.outBox = deque()
        """
        This queue is used by the replica to send messages to its node. Replica
        puts messages that are consumed by its node
        """

        self.inBox = deque()
        """
        This queue is used by the replica to receive messages from its node.
        Node puts messages that are consumed by the replica
        """

        self.inBoxStash = deque()
        """
        If messages need to go back on the queue, they go here temporarily and
        are put back on the queue on a state change
        """

        self.isMaster = isMaster

        # Indicates name of the primary replica of this protocol instance.
        # None in case the replica does not know who the primary of the
        # instance is
        self._primaryName = None  # type: Optional[str]

        # PRE-PREPAREs timestamps stored by non primary replica to check
        # obsolescence of incoming PrePrepares. Pre-prepares with the same
        # 3PC key are not merged since we need to keep incoming timestamps
        # for each new PP from every nodes separately.
        # Dictionary:
        #   key: Tuple[pp.viewNo, pp.seqNo]
        #   value: Dict[Tuple[PrePrepare, sender], timestamp]
        self.pre_prepare_tss = defaultdict(dict)

        # PRE-PREPAREs that are waiting to be processed but do not have the
        # corresponding request finalised. Happens when replica has not been
        # forwarded the request by the node but is getting 3 phase messages.
        # The value is a list since a malicious entry might send PRE-PREPARE
        # with a different digest and since we dont have the request finalised
        # yet, we store all PRE-PPREPAREs
        # type: List[Tuple[PrePrepare, str, Set[Tuple[str, int]]]]
        self.prePreparesPendingFinReqs = []

        # PrePrepares waiting for previous PrePrepares, key being tuple of view
        # number and pre-prepare sequence numbers and value being tuple of
        # PrePrepare and sender
        # TODO: Since pp_seq_no will start from 1 in each view, the comparator
        # of SortedDict needs to change
        self.prePreparesPendingPrevPP = SortedDict(lambda k: (k[0], k[1]))

        # PREPAREs that are stored by non primary replica for which it has not
        #  got any PRE-PREPARE. Dictionary that stores a tuple of view no and
        #  prepare sequence number as key and a deque of PREPAREs as value.
        # This deque is attempted to be flushed on receiving every
        # PRE-PREPARE request.
        self.preparesWaitingForPrePrepare = {}
        # type: Dict[Tuple[int, int], deque]

        # COMMITs that are stored for which there are no PRE-PREPARE or PREPARE
        # received
        self.commitsWaitingForPrepare = {}
        # type: Dict[Tuple[int, int], deque]

        # Dictionary of sent PRE-PREPARE that are stored by primary replica
        # which it has broadcasted to all other non primary replicas
        # Key of dictionary is a 2 element tuple with elements viewNo,
        # pre-prepare seqNo and value is the received PRE-PREPARE
        self.sentPrePrepares = SortedDict(lambda k: (k[0], k[1]))
        # type: Dict[Tuple[int, int], PrePrepare]

        # Dictionary of received PRE-PREPAREs. Key of dictionary is a 2
        # element tuple with elements viewNo, pre-prepare seqNo and value
        # is the received PRE-PREPARE
        self.prePrepares = SortedDict(lambda k: (k[0], k[1]))
        # type: Dict[Tuple[int, int], PrePrepare]

        # Dictionary of received Prepare requests. Key of dictionary is a 2
        # element tuple with elements viewNo, seqNo and value is a 2 element
        # tuple containing request digest and set of sender node names(sender
        # replica names in case of multiple protocol instances)
        # (viewNo, seqNo) -> ((identifier, reqId), {senders})
        self.prepares = Prepares()
        # type: Dict[Tuple[int, int], Tuple[Tuple[str, int], Set[str]]]

        self.commits = Commits()
        # type: Dict[Tuple[int, int], Tuple[Tuple[str, int], Set[str]]]

        # Set of tuples to keep track of ordered requests. Each tuple is
        # (viewNo, ppSeqNo).
        self.ordered = OrderedTracker()

        # Dictionary to keep track of the which replica was primary during each
        # view. Key is the view no and value is the name of the primary
        # replica during that view
        self.primaryNames = OrderedDict()  # type: OrderedDict[int, str]

        # Commits which are not being ordered since commits with lower
        # sequence numbers have not been ordered yet. Key is the
        # viewNo and value a map of pre-prepare sequence number to commit
        # type: Dict[int,Dict[int,Commit]]
        self.stashed_out_of_order_commits = {}

        self.checkpoints = SortedDict(lambda k: k[1])

        # Stashed checkpoints for each view. The key of the outermost
        # dictionary is the view_no, value being a dictionary with key as the
        # range of the checkpoint and its value again being a mapping between
        # senders and their sent checkpoint
        self.stashedRecvdCheckpoints = {}  # type: Dict[int, Dict[Tuple,

        # Flag being used for preterm exit from the loop in the method
        # `processStashedMsgsForNewWaterMarks`. See that method for details.
        self.consumedAllStashedMsgs = True

        # Low water mark
        self._h = 0  # type: int
        # Set high water mark (`H`) too
        self.h = 0  # type: int

        self._lastPrePrepareSeqNo = self.h  # type: int

        # Queues used in PRE-PREPARE for each ledger,
        self.requestQueues = {}  # type: Dict[int, OrderedSet]

        self._freshness_checker = FreshnessChecker(freshness_timeout=self.config.STATE_FRESHNESS_UPDATE_INTERVAL)

        for ledger_id in self.ledger_ids:
            self.register_ledger(ledger_id)

        self.batches = OrderedDict()  # type: OrderedDict[Tuple[int, int]]
        # Tuple[int, float, bytes]]

        # TODO: Need to have a timer for each ledger
        self.lastBatchCreated = self.get_current_time()

        # self.lastOrderedPPSeqNo = 0
        # Three phase key for the last ordered batch
        self._last_ordered_3pc = (0, 0)

        # 3 phase key for the last prepared certificate before view change
        # started, applicable only to master instance
        self.last_prepared_before_view_change = None

        # Tracks for which keys PRE-PREPAREs have been requested.
        # Cleared in `gc`
        # type: Dict[Tuple[int, int], Optional[Tuple[str, str, str]]]
        self.requested_pre_prepares = {}

        # Tracks for which keys PREPAREs have been requested.
        # Cleared in `gc`
        # type: Dict[Tuple[int, int], Optional[Tuple[str, str, str]]]
        self.requested_prepares = {}

        # Tracks for which keys COMMITs have been requested.
        # Cleared in `gc`
        # type: Dict[Tuple[int, int], Optional[Tuple[str, str, str]]]
        self.requested_commits = {}

        # Time of the last PRE-PREPARE which satisfied all validation rules
        # (time, digest, roots were all correct). This time is not to be
        # reverted even if the PRE-PREPAREs are not ordered. This implies that
        # the next primary would have seen all accepted PRE-PREPAREs or another
        # view change will happen
        self.last_accepted_pre_prepare_time = None

        # Keeps a map of PRE-PREPAREs which did not satisfy timestamp
        # criteria, they can be accepted if >f PREPAREs are encountered.
        # This is emptied on view change. With each PRE-PREPARE, a flag is
        # stored which indicates whether there are sufficient acceptable
        # PREPAREs or not
        self.pre_prepares_stashed_for_incorrect_time = OrderedDict()

        self._bls_bft_replica = bls_bft_replica
        self._state_root_serializer = state_roots_serializer

        # Did we log a message about getting request while absence of primary
        self.warned_no_primary = False

        # Defines if there was a batch after last catchup
        self.first_batch_after_catchup = False

        HookManager.__init__(self, ReplicaHooks.get_all_vals())
def __init__ ( self , node : 'plenum.server.node.Node' , instId : int , config = None , isMaster : bool = False , bls_bft_replica : BlsBftReplica = None , metrics : MetricsCollector = NullMetricsCollector ( ) , get_current_time = None , get_time_for_3pc_batch = None ) : HasActionQueue . __init__ ( self ) self . get_current_time = get_current_time or time . perf_counter self . get_time_for_3pc_batch = get_time_for_3pc_batch or node . utc_epoch self . stats = Stats ( TPCStat ) self . config = config or getConfig ( ) self . metrics = metrics self . inBoxRouter = Router ( ( ReqKey , self . readyFor3PC ) , ( PrePrepare , self . process_three_phase_msg ) , ( Prepare , self . process_three_phase_msg ) , ( Commit , self . process_three_phase_msg ) , ( Checkpoint , self . process_checkpoint ) , ) self . threePhaseRouter = Replica3PRouter ( self , ( PrePrepare , self . processPrePrepare ) , ( Prepare , self . processPrepare ) , ( Commit , self . processCommit ) ) self . node = node self . instId = instId self . name = self . generateName ( node . name , self . instId ) self . logger = getlogger ( self . name ) self . validator = ReplicaValidator ( self ) self . stasher = ReplicaStasher ( self ) self . outBox = deque ( ) self . inBox = deque ( ) self . inBoxStash = deque ( ) self . isMaster = isMaster self . _primaryName = None self . pre_prepare_tss = defaultdict ( dict ) self . prePreparesPendingFinReqs = [ ] self . prePreparesPendingPrevPP = SortedDict ( lambda k : ( k [ 0 ] , k [ 1 ] ) ) self . preparesWaitingForPrePrepare = { } self . commitsWaitingForPrepare = { } self . sentPrePrepares = SortedDict ( lambda k : ( k [ 0 ] , k [ 1 ] ) ) self . prePrepares = SortedDict ( lambda k : ( k [ 0 ] , k [ 1 ] ) ) self . prepares = Prepares ( ) self . commits = Commits ( ) self . ordered = OrderedTracker ( ) self . primaryNames = OrderedDict ( ) self . stashed_out_of_order_commits = { } self . checkpoints = SortedDict ( lambda k : k [ 1 ] ) self . stashedRecvdCheckpoints = { } self . consumedAllStashedMsgs = True self . _h = 0 self . h = 0 self . _lastPrePrepareSeqNo = self . h self . requestQueues = { } self . _freshness_checker = FreshnessChecker ( freshness_timeout = self . config . STATE_FRESHNESS_UPDATE_INTERVAL ) for ledger_id in self . ledger_ids : self . register_ledger ( ledger_id ) self . batches = OrderedDict ( ) self . lastBatchCreated = self . get_current_time ( ) self . _last_ordered_3pc = ( 0 , 0 ) self . last_prepared_before_view_change = None self . requested_pre_prepares = { } self . requested_prepares = { } self . requested_commits = { } self . last_accepted_pre_prepare_time = None self . pre_prepares_stashed_for_incorrect_time = OrderedDict ( ) self . _bls_bft_replica = bls_bft_replica self . _state_root_serializer = state_roots_serializer self . warned_no_primary = False self . first_batch_after_catchup = False HookManager . __init__ ( self , ReplicaHooks . get_all_vals ( ) )
Create a new replica.

        :param node: Node on which this replica is located
        :param instId: the id of the protocol instance the replica belongs to
        :param isMaster: is this a replica of the master protocol instance