def _do_checkpoint(self, state, s, e, ledger_id, view_no,
                       audit_txn_root_hash):
        # TODO CheckpointState/Checkpoint is not a namedtuple anymore
        # 1. check if updateNamedTuple works for the new message type
        # 2. choose another name

        # TODO: This is hack of hacks, should be removed when refactoring is complete
        if not self.is_master and audit_txn_root_hash is None:
            audit_txn_root_hash = "7RJ5bkAKRy2CCvarRij2jiHC16SVPjHcrpVdNsboiQGv"

        state = updateNamedTuple(state, digest=audit_txn_root_hash, digests=[])
        self._checkpoint_state[s, e] = state
        self._logger.info(
            "{} sending Checkpoint {} view {} checkpointState digest {}. Ledger {} "
            "txn root hash {}. Committed state root hash {} Uncommitted state root hash {}"
            .format(
                self, (s, e), view_no, state.digest, ledger_id,
                self._db_manager.get_txn_root_hash(ledger_id),
                self._db_manager.get_state_root_hash(ledger_id,
                                                     committed=True),
                self._db_manager.get_state_root_hash(ledger_id,
                                                     committed=False)))
        checkpoint = Checkpoint(self._data.inst_id, view_no, s, e,
                                state.digest)
        self._network.send(checkpoint)
        self._data.checkpoints.append(checkpoint)
Example #2
0
 def evilSendPrePrepareRequest(self, ppReq: PrePrepare):
     logger.debug(
         "EVIL: Creating pre-prepare message for request : {}".format(
             ppReq))
     ppReq = updateNamedTuple(ppReq, digest=ppReq.digest + 'random')
     self.sentPrePrepares[self.viewNo, self.lastPrePrepareSeqNo] = ppReq
     self.send(ppReq, TPCStat.PrePrepareSent)
 def _mark_checkpoint_stable(self, seqNo):
     previousCheckpoints = []
     for (s, e), state in self._checkpoint_state.items():
         if e == seqNo:
             # TODO CheckpointState/Checkpoint is not a namedtuple anymore
             # 1. check if updateNamedTuple works for the new message type
             # 2. choose another name
             state = updateNamedTuple(state, isStable=True)
             self._checkpoint_state[s, e] = state
             self._set_stable_checkpoint(e)
             break
         else:
             previousCheckpoints.append((s, e))
     else:
         self._logger.debug("{} could not find {} in checkpoints".format(
             self, seqNo))
         return
     self.set_watermarks(low_watermark=seqNo)
     for k in previousCheckpoints:
         self._logger.trace("{} removing previous checkpoint {}".format(
             self, k))
         self._checkpoint_state.pop(k)
     self._remove_stashed_checkpoints(till_3pc_key=(self.view_no, seqNo))
     self._bus.send(
         CheckpointStabilized(self._data.inst_id, (self.view_no, seqNo)))
     self._logger.info("{} marked stable checkpoint {}".format(
         self, (s, e)))
 def badMethod(self, ledgerId):
     nonlocal malignedOnce
     pp = origMethod(ledgerId)
     if not malignedOnce:
         pp = updateNamedTuple(pp, digest=pp.digest + '123')
         malignedOnce = True
     return pp
Example #5
0
def test_process_oredered(checkpoint_service, ordered, pre_prepare, tconf):
    with pytest.raises(
            LogicError,
            match="CheckpointService | Can't process Ordered msg because "
            "ppSeqNo {} not in preprepared".format(ordered.ppSeqNo)):
        checkpoint_service.process_ordered(ordered)
    checkpoint_service._data.preprepared.append(
        preprepare_to_batch_id(pre_prepare))
    checkpoint_service.process_ordered(ordered)
    _check_checkpoint(checkpoint_service, 1, tconf.CHK_FREQ, pre_prepare)

    pre_prepare.ppSeqNo = tconf.CHK_FREQ
    ordered.ppSeqNo = pre_prepare.ppSeqNo
    checkpoint_service._data.preprepared.append(
        preprepare_to_batch_id(pre_prepare))
    state = updateNamedTuple(
        checkpoint_service._checkpoint_state[1, tconf.CHK_FREQ],
        digests=["digest"] * (tconf.CHK_FREQ - 1))
    checkpoint_service._checkpoint_state[1, tconf.CHK_FREQ] = state
    checkpoint_service.process_ordered(ordered)
    _check_checkpoint(checkpoint_service,
                      1,
                      tconf.CHK_FREQ,
                      pre_prepare,
                      check_shared_data=True)

    pre_prepare.ppSeqNo += 1
    ordered.ppSeqNo = pre_prepare.ppSeqNo
    checkpoint_service._data.preprepared.append(
        preprepare_to_batch_id(pre_prepare))
    checkpoint_service.process_ordered(ordered)
    _check_checkpoint(checkpoint_service, tconf.CHK_FREQ + 1,
                      tconf.CHK_FREQ * 2, pre_prepare)
 def badMethod(self, ledgerId):
     nonlocal malignedOnce
     pp = origMethod(ledgerId)
     if not malignedOnce:
         pp = updateNamedTuple(pp, digest=pp.digest + '123')
         malignedOnce = True
     return pp
def test_validate_prepare_wrong_audit_root(r, pre_prepare, prepare):
    r.processPrePrepare(pre_prepare, PRIMARY_NAME)
    prepare = updateNamedTuple(prepare, auditTxnRootHash=generate_state_root())
    with pytest.raises(SuspiciousNode,
                       match=str(
                           Suspicions.PR_AUDIT_TXN_ROOT_HASH_WRONG.code)):
        r.validatePrepare(prepare, NON_PRIMARY_NAME)
def test_process_checkpoint(checkpoint_service, checkpoint, pre_prepare, tconf,
                            ordered, validators, is_master):
    global caught_msg
    caught_msg = None
    checkpoint_service._bus.subscribe(Cleanup, catch_msg)
    quorum = checkpoint_service._data.quorums.checkpoint.value
    n = len(validators)
    assert quorum == n - getMaxFailures(n) - 1
    senders = ["sender{}".format(i) for i in range(quorum + 1)]
    key = (1, tconf.CHK_FREQ)
    old_key = (-1, 0)

    checkpoint_service._stash_checkpoint(
        Checkpoint(1, checkpoint.viewNo, 1, 1, "1"), "frm")
    checkpoint_service._stash_checkpoint(
        Checkpoint(1, checkpoint.viewNo + 1, 1, 1, "1"), "frm")

    checkpoint_service._checkpoint_state[old_key] = CheckpointState(
        1, ["digest"] * (tconf.CHK_FREQ - 1), None, {}, False)
    checkpoint_service._checkpoint_state[key] = CheckpointState(
        key[1] - 1, ["digest"] * (tconf.CHK_FREQ - 1), None, {}, False)
    pre_prepare.ppSeqNo = key[1]
    ordered.ppSeqNo = pre_prepare.ppSeqNo
    checkpoint_service._data.preprepared.append(pre_prepare)
    checkpoint_service.process_ordered(ordered)
    _check_checkpoint(checkpoint_service,
                      key[0],
                      key[1],
                      pre_prepare,
                      check_shared_data=True)
    state = updateNamedTuple(checkpoint_service._checkpoint_state[key],
                             digest=checkpoint.digest)
    checkpoint_service._checkpoint_state[key] = state

    for sender in senders[:quorum - 1]:
        assert checkpoint_service.process_checkpoint(checkpoint, sender)
        assert checkpoint_service._checkpoint_state[key].receivedDigests[
            sender] == checkpoint.digest

    assert not checkpoint_service._checkpoint_state[key].isStable
    # send the last checkpoint to stable it
    assert checkpoint_service.process_checkpoint(checkpoint,
                                                 senders[quorum - 1])
    assert checkpoint_service._checkpoint_state[key].isStable

    # check _remove_stashed_checkpoints()
    assert checkpoint.viewNo not in checkpoint_service._stashed_recvd_checkpoints
    assert checkpoint.viewNo + 1 in checkpoint_service._stashed_recvd_checkpoints

    # check watermarks
    assert checkpoint_service._data.low_watermark == checkpoint.seqNoEnd

    # check that a Cleanup msg has been sent
    assert isinstance(caught_msg, Cleanup)
    assert caught_msg.cleanup_till_3pc == (checkpoint.viewNo,
                                           checkpoint.seqNoEnd)

    # check that old checkpoint_states has been removed
    assert old_key not in checkpoint_service._checkpoint_state
Example #9
0
    def addToCheckpoint(self, ppSeqNo, digest):
        for (s, e) in self.checkpoints.keys():
            if s <= ppSeqNo <= e:
                state = self.checkpoints[s, e]  # type: CheckpointState
                state.digests.append(digest)
                state = updateNamedTuple(state, seqNo=ppSeqNo)
                self.checkpoints[s, e] = state
                break
        else:
            state = self._newCheckpointState(ppSeqNo, digest)
            s, e = ppSeqNo, ppSeqNo + self.config.CHK_FREQ

        if len(state.digests) == self.config.CHK_FREQ:
            state = updateNamedTuple(state, digest=serialize(state.digests),
                                     digests=[])
            self.checkpoints[s, e] = state
            self.send(Checkpoint(self.instId, self.viewNo, ppSeqNo,
                                 state.digest))
Example #10
0
    def addToCheckpoint(self, ppSeqNo, digest):
        for (s, e) in self.checkpoints.keys():
            if s <= ppSeqNo <= e:
                state = self.checkpoints[s, e]  # type: CheckpointState
                state.digests.append(digest)
                state = updateNamedTuple(state, seqNo=ppSeqNo)
                self.checkpoints[s, e] = state
                break
        else:
            state = self._newCheckpointState(ppSeqNo, digest)
            s, e = ppSeqNo, ppSeqNo + self.config.CHK_FREQ

        if len(state.digests) == self.config.CHK_FREQ:
            state = updateNamedTuple(state,
                                     digest=serialize(state.digests),
                                     digests=[])
            self.checkpoints[s, e] = state
            self.send(
                Checkpoint(self.instId, self.viewNo, ppSeqNo, state.digest))
Example #11
0
 def evilSendPrePrepareRequest(self, ppReq: PrePrepare):
     # reqDigest = ReqDigest(reqDigest.identifier, reqDigest.reqId, "random")
     # tm = time.time()
     # prePrepare = PrePrepare(self.instId, self.viewNo,
     #                         self.lastPrePrepareSeqNo+1, *reqDigest, tm)
     logger.debug(
         "EVIL: Creating pre-prepare message for request : {}".format(
             ppReq))
     ppReq = updateNamedTuple(ppReq, digest=ppReq.digest + 'random')
     self.sentPrePrepares[self.viewNo, self.lastPrePrepareSeqNo] = ppReq
     self.send(ppReq, TPCStat.PrePrepareSent)
def test_validate_prepare_wrong_state_root(o, pre_prepare, prepare):
    handler = Mock()
    o._bus.subscribe(RaisedSuspicion, handler)
    o.process_preprepare(pre_prepare, PRIMARY_NAME)
    prepare = updateNamedTuple(prepare, stateRootHash=generate_state_root())
    o._validate_prepare(prepare, NON_PRIMARY_NAME)
    check_suspicious(
        handler,
        RaisedSuspicion(inst_id=o._data.inst_id,
                        ex=SuspiciousNode(NON_PRIMARY_NAME,
                                          Suspicions.PR_STATE_WRONG, prepare)))
def test_process_preprepare_on_old_view_pre_prepares_reply(
        external_bus, internal_bus, orderer, is_primary, initial_view_no,
        pre_prepares):
    # !!!SETUP!!!
    orderer._data.view_no = initial_view_no + 1
    new_view = create_new_view(
        initial_view_no=initial_view_no,
        stable_cp=200,
        batches=create_batches_from_preprepares(pre_prepares))
    orderer._data.new_view_votes.add_new_view(new_view,
                                              orderer._data.primary_name)
    orderer._data.prev_view_prepare_cert = new_view.batches[-1].pp_seq_no

    # !!!EXECUTE!!!
    rep = OldViewPrePrepareReply(0, [pp._asdict() for pp in pre_prepares])
    orderer._network.process_incoming(
        rep, generateName("node1", orderer._data.inst_id))

    # !!!CHECK!!!
    if not orderer.is_master:
        # no re-ordering is expected on non-master
        assert orderer._data.preprepared == []
        assert orderer._data.prepared == []
        return

    # check that PPs were added
    assert orderer._data.preprepared == [
        BatchID(view_no=initial_view_no + 1,
                pp_view_no=pp.viewNo,
                pp_seq_no=pp.ppSeqNo,
                pp_digest=pp.digest) for pp in pre_prepares
    ]

    # check that sent_preprepares is updated in case of Primary and prePrepares in case of non-primary
    updated_prepares_collection = orderer.prePrepares if not is_primary else orderer.sent_preprepares
    non_updated_prepares_collection = orderer.sent_preprepares if not is_primary else orderer.prePrepares
    for pp in pre_prepares:
        new_pp = updateNamedTuple(pp,
                                  viewNo=initial_view_no + 1,
                                  originalViewNo=pp.viewNo)
        assert (initial_view_no + 1,
                new_pp.ppSeqNo) in updated_prepares_collection
        assert updated_prepares_collection[(initial_view_no + 1,
                                            new_pp.ppSeqNo)] == new_pp
    assert not non_updated_prepares_collection

    # check that Prepare is sent in case of non primary
    if not is_primary:
        check_prepares_sent(external_bus, pre_prepares, initial_view_no + 1)
    else:
        assert len(external_bus.sent_messages) == 0

    # we don't have a quorum of Prepares yet
    assert orderer._data.prepared == []
 def send_bad(self, msg, frm):
     if msg.msg_type == PREPREPARE:
         resp = self.replicas[msg.params['instId']].getPrePrepare(
             msg.params['viewNo'], msg.params['ppSeqNo'])
         resp = updateNamedTuple(resp, digest='11908ffq')
         self.sendToNodes(MessageRep(**{
             f.MSG_TYPE.nm: msg.msg_type,
             f.PARAMS.nm: msg.params,
             f.MSG.nm: resp
         }), names=[frm, ])
     else:
         return orig_method(msg, frm)
def test_validate_prepare_wrong_digest(o, pre_prepare, prepare):
    handler = Mock()
    o._bus.subscribe(RaisedSuspicion, handler)
    o.process_preprepare(pre_prepare, PRIMARY_NAME)
    prepare = updateNamedTuple(prepare, digest='fake_digest')
    o._validate_prepare(prepare, NON_PRIMARY_NAME)
    check_suspicious(
        handler,
        RaisedSuspicion(inst_id=o._data.inst_id,
                        ex=SuspiciousNode(NON_PRIMARY_NAME,
                                          Suspicions.PR_DIGEST_WRONG,
                                          prepare)))
 def add_to_pre_prepare(self, pre_prepare):
     if pre_prepare.ledgerId != TOKEN_LEDGER_ID and \
             self.fees_tracker.fees_in_current_batch > 0:
         # Make sovtoken ledger and state root part of pre-prepare
         extra = {
             f.PLUGIN_FIELDS.nm: {
                 FEES: {
                     FEE_TXNS_IN_BATCH: self.fees_tracker.fees_in_current_batch,
                     f.STATE_ROOT.nm: self.master_replica._ordering_service.get_state_root_hash(
                         TOKEN_LEDGER_ID),
                     f.TXN_ROOT.nm: self.master_replica._ordering_service.get_txn_root_hash(
                         TOKEN_LEDGER_ID)
                 }
             }
         }
         pre_prepare = updateNamedTuple(pre_prepare, **extra)
     return pre_prepare
 def add_to_ordered(self, ordered, pre_prepare):
     if pre_prepare.ledgerId != TOKEN_LEDGER_ID and \
             self._has_plugin_fields(pre_prepare):
         pre_prepare_fees_data = pre_prepare.plugin_fields.get(FEES, {})
         if pre_prepare_fees_data:
             # the plugins_fields member created here is an exact copy of the one found in the pre_prepare msg
             extra = {
                 f.PLUGIN_FIELDS.nm: {
                     FEES: {
                         FEE_TXNS_IN_BATCH: pre_prepare_fees_data.get(
                             FEE_TXNS_IN_BATCH),
                         f.STATE_ROOT.nm: pre_prepare_fees_data.get(
                             f.STATE_ROOT.nm),
                         f.TXN_ROOT.nm: pre_prepare_fees_data.get(f.TXN_ROOT.nm)
                     }
                 }
             }
             ordered = updateNamedTuple(ordered, **extra)
     return ordered
 def add_to_prepare(self, prepare, pre_prepare):
     if pre_prepare.ledgerId != TOKEN_LEDGER_ID and \
             self._has_plugin_fields(pre_prepare):
         # Make sovtoken ledger and state root part of pre-prepare
         pre_prepare_fees_data = pre_prepare.plugin_fields.get(FEES, {})
         if pre_prepare_fees_data:
             extra = {
                 f.PLUGIN_FIELDS.nm: {
                     FEES: {
                         FEE_TXNS_IN_BATCH: pre_prepare_fees_data.get(
                             FEE_TXNS_IN_BATCH),
                         f.STATE_ROOT.nm: pre_prepare_fees_data.get(
                             f.STATE_ROOT.nm),
                         f.TXN_ROOT.nm: pre_prepare_fees_data.get(f.TXN_ROOT.nm)
                     }
                 }
             }
             prepare = updateNamedTuple(prepare, **extra)
     return prepare
Example #19
0
 def markCheckPointStable(self, seqNo):
     previousCheckpoints = []
     for (s, e), state in self.checkpoints.items():
         if e == seqNo:
             state = updateNamedTuple(state, isStable=True)
             self.checkpoints[s, e] = state
             break
         else:
             previousCheckpoints.append((s, e))
     else:
         logger.error("{} could not find {} in checkpoints".
                      format(self, seqNo))
         return
     self.h = seqNo
     for k in previousCheckpoints:
         logger.debug("{} removing previous checkpoint {}".format(self, k))
         self.checkpoints.pop(k)
     self.gc(seqNo)
     logger.debug("{} marked stable checkpoint {}".format(self, (s, e)))
     self.processStashedMsgsForNewWaterMarks()
Example #20
0
 def markCheckPointStable(self, seqNo):
     previousCheckpoints = []
     for (s, e), state in self.checkpoints.items():
         if e == seqNo:
             state = updateNamedTuple(state, isStable=True)
             self.checkpoints[s, e] = state
             break
         else:
             previousCheckpoints.append((s, e))
     else:
         logger.error("{} could not find {} in checkpoints".format(
             self, seqNo))
         return
     self.h = seqNo
     for k in previousCheckpoints:
         logger.debug("{} removing previous checkpoint {}".format(self, k))
         self.checkpoints.pop(k)
     self.gc(seqNo)
     logger.debug("{} marked stable checkpoint {}".format(self, (s, e)))
     self.processStashedMsgsForNewWaterMarks()
Example #21
0
    def _add_to_checkpoint(self, ppSeqNo, digest, ledger_id, view_no):
        for (s, e) in self._checkpoint_state.keys():
            if s <= ppSeqNo <= e:
                state = self._checkpoint_state[s, e]  # type: CheckpointState
                state.digests.append(digest)
                state = updateNamedTuple(state, seqNo=ppSeqNo)
                self._checkpoint_state[s, e] = state
                break
        else:
            s, e = ppSeqNo, math.ceil(
                ppSeqNo / self._config.CHK_FREQ) * self._config.CHK_FREQ
            self._logger.debug("{} adding new checkpoint state for {}".format(
                self, (s, e)))
            state = CheckpointState(ppSeqNo, [
                digest,
            ], None, {}, False)
            self._checkpoint_state[s, e] = state

        if state.seqNo == e:
            if len(state.digests) == self._config.CHK_FREQ:
                self._do_checkpoint(state, s, e, ledger_id, view_no)
            self._process_stashed_checkpoints((s, e), view_no)
Example #22
0
 def _do_checkpoint(self, state, s, e, ledger_id, view_no):
     # TODO CheckpointState/Checkpoint is not a namedtuple anymore
     # 1. check if updateNamedTuple works for the new message type
     # 2. choose another name
     state = updateNamedTuple(state,
                              digest=sha256(
                                  serialize_msg_for_signing(
                                      state.digests)).hexdigest(),
                              digests=[])
     self._checkpoint_state[s, e] = state
     self._logger.info(
         "{} sending Checkpoint {} view {} checkpointState digest {}. Ledger {} "
         "txn root hash {}. Committed state root hash {} Uncommitted state root hash {}"
         .format(
             self, (s, e), view_no, state.digest, ledger_id,
             self._db_manager.get_txn_root_hash(ledger_id),
             self._db_manager.get_state_root_hash(ledger_id,
                                                  committed=True),
             self._db_manager.get_state_root_hash(ledger_id,
                                                  committed=False)))
     checkpoint = Checkpoint(self._data.inst_id, view_no, s, e,
                             state.digest)
     self._network.send(checkpoint)
     self._data.checkpoints.append(checkpoint)
def test_validate_prepare_wrong_txn_root(o, pre_prepare, prepare):
    o.process_preprepare(pre_prepare, PRIMARY_NAME)
    prepare = updateNamedTuple(prepare, txnRootHash=generate_state_root())
    with pytest.raises(SuspiciousNode,
                       match=str(Suspicions.PR_TXN_WRONG.code)):
        o.l_validatePrepare(prepare, NON_PRIMARY_NAME)
 def evilSendPrePrepareRequest(self, ppReq: PrePrepare):
     logger.debug("EVIL: Creating pre-prepare message for request : {}".
                  format(ppReq))
     ppReq = updateNamedTuple(ppReq, digest=ppReq.digest + 'random')
     self.sentPrePrepares[self.viewNo, self.lastPrePrepareSeqNo] = ppReq
     self.send(ppReq, TPCStat.PrePrepareSent)
def test_process_preprepare_on_new_view_checkpoint_applied(
        internal_bus, external_bus, orderer, is_primary, all_ordered,
        initial_view_no, pre_prepares, stored_old_view_pre_prepares):
    # !!!SETUP!!!
    orderer._data.view_no = initial_view_no + 1
    batches = create_batches_from_preprepares(pre_prepares)
    orderer._data.prev_view_prepare_cert = batches[-1].pp_seq_no

    new_view = create_new_view(initial_view_no=initial_view_no,
                               stable_cp=200,
                               batches=batches)

    # emulate that we received all PrePrepares before View Change
    orderer._update_old_view_preprepares(stored_old_view_pre_prepares)

    # emulate that we've already ordered the PrePrepares
    if all_ordered and stored_old_view_pre_prepares:
        orderer.last_ordered_3pc = (initial_view_no,
                                    stored_old_view_pre_prepares[-1].ppSeqNo)

    # !!!EXECUTE!!!
    # send NewViewCheckpointsApplied
    internal_bus.send(
        NewViewCheckpointsApplied(view_no=initial_view_no + 1,
                                  view_changes=new_view.viewChanges,
                                  checkpoint=new_view.checkpoint,
                                  batches=new_view.batches))

    # !!!CHECK!!!
    if not orderer.is_master:
        # no re-ordering is expected on non-master
        assert orderer._data.preprepared == []
        assert orderer._data.prepared == []
        return

    # check that PPs were added
    stored_batch_ids = [
        preprepare_to_batch_id(pp) for pp in stored_old_view_pre_prepares
    ]
    assert orderer._data.preprepared == [
        BatchID(view_no=initial_view_no + 1,
                pp_view_no=initial_view_no,
                pp_seq_no=batch_id.pp_seq_no,
                pp_digest=batch_id.pp_digest) for batch_id in new_view.batches
        if batch_id in stored_batch_ids
    ]

    # check that sentPrePrepares is updated in case of Primary and prePrepares in case of non-primary
    updated_prepares_collection = orderer.prePrepares if not is_primary else orderer.sent_preprepares
    non_updated_prepares_collection = orderer.sent_preprepares if not is_primary else orderer.prePrepares
    for pp in stored_old_view_pre_prepares:
        new_pp = updateNamedTuple(pp,
                                  viewNo=initial_view_no + 1,
                                  originalViewNo=pp.viewNo)
        assert (initial_view_no + 1,
                new_pp.ppSeqNo) in updated_prepares_collection
        assert updated_prepares_collection[(initial_view_no + 1,
                                            new_pp.ppSeqNo)] == new_pp
    assert not non_updated_prepares_collection

    # check that Prepare is sent in case of non primary
    if not is_primary:
        check_prepares_sent(external_bus, stored_old_view_pre_prepares,
                            initial_view_no + 1)
    else:
        #  only MessageReqs are sent
        assert len(external_bus.sent_messages
                   ) == len(pre_prepares) - len(stored_old_view_pre_prepares)

    # we don't have a quorum of Prepares yet
    assert orderer._data.prepared == []

    # check that missing PrePrepares have been requested
    expected_requested_batches = [
        batch_id for batch_id in new_view.batches
        if batch_id not in stored_batch_ids
    ]
    check_request_old_view_preprepares_sent(external_bus,
                                            expected_requested_batches)
def test_validate_prepare_wrong_digest(r, pre_prepare, prepare):
    r.processPrePrepare(pre_prepare, PRIMARY_NAME)
    prepare = updateNamedTuple(prepare, digest='fake_digest')
    with pytest.raises(SuspiciousNode,
                       match=str(Suspicions.PR_DIGEST_WRONG.code)):
        r.validatePrepare(prepare, NON_PRIMARY_NAME)
def test_validate_prepare_wrong_state_root(r, pre_prepare, prepare):
    r.processPrePrepare(pre_prepare, PRIMARY_NAME)
    prepare = updateNamedTuple(prepare, stateRootHash=generate_state_root())
    with pytest.raises(SuspiciousNode,
                       match=str(Suspicions.PR_STATE_WRONG.code)):
        r.validatePrepare(prepare, NON_PRIMARY_NAME)