void recover_public_ledger_entry()

in src/node/node_state.h [726:848]


    void recover_public_ledger_entry(const std::vector<uint8_t>& ledger_entry)
    {
      std::lock_guard<std::mutex> guard(lock);

      std::shared_ptr<kv::Store> store;
      if (sm.check(State::readingPublicLedger))
      {
        // In recovery, use the main store to deserialise public entries
        store = network.tables;
      }
      else if (sm.check(State::verifyingSnapshot))
      {
        store = startup_snapshot_info->store;
      }
      else
      {
        LOG_FAIL_FMT(
          "Node should be in state {} or {} to recover public ledger entry",
          State::readingPublicLedger,
          State::verifyingSnapshot);
        return;
      }

      LOG_INFO_FMT(
        "Deserialising public ledger entry ({})", ledger_entry.size());

      auto r = store->deserialize(ledger_entry, ConsensusType::CFT, true);
      auto result = r->apply();
      if (result == kv::ApplyResult::FAIL)
      {
        LOG_FAIL_FMT("Failed to deserialise entry in public ledger");
        recover_public_ledger_end_unsafe();
        return;
      }

      // Not synchronised because consensus isn't effectively running then
      for (auto& hook : r->get_hooks())
      {
        hook->call(consensus.get());
      }

      // If the ledger entry is a signature, it is safe to compact the store
      if (result == kv::ApplyResult::PASS_SIGNATURE)
      {
        // If the ledger entry is a signature, it is safe to compact the store
        store->compact(ledger_idx);
        auto tx = store->create_tx();
        GenesisGenerator g(network, tx);
        auto last_sig = tx.ro(network.signatures)->get();

        if (!last_sig.has_value())
        {
          throw std::logic_error("Signature missing");
        }

        LOG_DEBUG_FMT(
          "Read signature at {} for view {}", ledger_idx, last_sig->view);
        // Initial transactions, before the first signature, must have
        // happened in the first signature's view (eg - if the first
        // signature is at seqno 20 in view 4, then transactions 1->19 must
        // also have been in view 4). The brief justification is that while
        // the first node may start in an arbitrarily high view (it does not
        // necessarily start in view 1), it cannot _change_ view before a
        // valid signature.
        const auto view_start_idx =
          view_history.empty() ? 1 : last_recovered_signed_idx + 1;
        CCF_ASSERT_FMT(
          last_sig->view >= 0, "last_sig->view is invalid, {}", last_sig->view);
        for (auto i = view_history.size();
             i < static_cast<size_t>(last_sig->view);
             ++i)
        {
          view_history.push_back(view_start_idx);
        }
        last_recovered_signed_idx = ledger_idx;

        if (
          startup_snapshot_info && startup_snapshot_info->has_evidence &&
          startup_snapshot_info->evidence_seqno.has_value() &&
          static_cast<consensus::Index>(last_sig->commit_seqno) >=
            startup_snapshot_info->evidence_seqno.value())
        {
          startup_snapshot_info->is_evidence_committed = true;
        }

        if (sm.check(State::readingPublicLedger))
        {
          // Inform snapshotter of all signature entries so that this node can
          // continue generating snapshots at the correct interval once the
          // recovery is complete
          snapshotter->record_committable(ledger_idx);
          snapshotter->commit(ledger_idx, false);
        }
      }
      else if (
        result == kv::ApplyResult::PASS_SNAPSHOT_EVIDENCE &&
        startup_snapshot_info)
      {
        auto tx = store->create_read_only_tx();
        auto snapshot_evidence = tx.ro(network.snapshot_evidence);

        if (
          startup_snapshot_info->evidence_seqno.has_value() &&
          ledger_idx == startup_snapshot_info->evidence_seqno.value())
        {
          auto evidence = snapshot_evidence->get();
          if (!evidence.has_value())
          {
            throw std::logic_error("Invalid snapshot evidence");
          }

          if (evidence->hash == crypto::Sha256Hash(startup_snapshot_info->raw))
          {
            LOG_DEBUG_FMT(
              "Snapshot evidence for snapshot found at {}",
              startup_snapshot_info->evidence_seqno.value());
            startup_snapshot_info->has_evidence = true;
          }
        }
      }

      read_ledger_idx(++ledger_idx);
    }