зеркало из https://github.com/microsoft/CCF.git
194 строки
6.4 KiB
C++
194 строки
6.4 KiB
C++
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the Apache 2.0 License.
|
|
#pragma once
|
|
|
|
#include "ccf/receipt.h"
|
|
#include "ccf/tx_id.h"
|
|
#include "consensus/ledger_enclave_types.h"
|
|
#include "kv/store.h"
|
|
#include "node/history.h"
|
|
#include "tls/base64.h"
|
|
|
|
#include <chrono>
|
|
#include <memory>
|
|
|
|
namespace ccf::historical
|
|
{
|
|
struct TxReceipt
|
|
{
|
|
std::vector<uint8_t> signature = {};
|
|
HistoryTree::Hash root = {};
|
|
std::shared_ptr<ccf::HistoryTree::Path> path = {};
|
|
ccf::NodeId node_id = {};
|
|
|
|
TxReceipt(
|
|
const std::vector<uint8_t>& s_,
|
|
const HistoryTree::Hash& r_,
|
|
std::shared_ptr<ccf::HistoryTree::Path> p_,
|
|
const NodeId& n_) :
|
|
signature(s_),
|
|
root(r_),
|
|
path(p_),
|
|
node_id(n_)
|
|
{}
|
|
|
|
void describe(ccf::Receipt& r, bool include_root = false)
|
|
{
|
|
r.signature = tls::b64_from_raw(signature);
|
|
if (include_root)
|
|
{
|
|
r.root = root.to_string();
|
|
}
|
|
if (path)
|
|
{
|
|
for (const auto& node : *path)
|
|
{
|
|
ccf::Receipt::Element n;
|
|
if (node.direction == ccf::HistoryTree::Path::Direction::PATH_LEFT)
|
|
{
|
|
n.left = node.hash.to_string();
|
|
}
|
|
else
|
|
{
|
|
n.right = node.hash.to_string();
|
|
}
|
|
r.proof.emplace_back(std::move(n));
|
|
}
|
|
r.leaf = path->leaf().to_string();
|
|
}
|
|
else
|
|
{
|
|
r.leaf = root.to_string();
|
|
}
|
|
r.node_id = node_id;
|
|
}
|
|
};
|
|
|
|
using TxReceiptPtr = std::shared_ptr<TxReceipt>;
|
|
using StorePtr = std::shared_ptr<kv::Store>;
|
|
|
|
struct State
|
|
{
|
|
/// Read-only historical store at transaction_id
|
|
StorePtr store = nullptr;
|
|
/// Receipt for ledger entry at transaction_id
|
|
TxReceiptPtr receipt = nullptr;
|
|
/// View and Sequence Number for the State
|
|
ccf::TxID transaction_id;
|
|
|
|
State(
|
|
const StorePtr& store_,
|
|
const TxReceiptPtr& receipt_,
|
|
const ccf::TxID& transaction_id_) :
|
|
store(store_),
|
|
receipt(receipt_),
|
|
transaction_id(transaction_id_)
|
|
{}
|
|
|
|
bool operator==(const State& other)
|
|
{
|
|
return store == other.store && receipt == other.receipt &&
|
|
transaction_id == other.transaction_id;
|
|
};
|
|
};
|
|
|
|
using StatePtr = std::shared_ptr<State>;
|
|
|
|
/** This is a caller-defined key for each historical query request. For
|
|
* instance, you may wish to use callerID or sessionID to allow a single
|
|
* active request per caller or session, or maintain an LRU to cap the total
|
|
* number of active requests.
|
|
*/
|
|
using RequestHandle = size_t;
|
|
|
|
using ExpiryDuration = std::chrono::seconds;
|
|
|
|
/** Stores the progress of historical query requests.
|
|
*
|
|
* A request will generally need to be made multiple times (with the same
|
|
* handle and range) before the response is available, as the historical state
|
|
* is asynchronously retrieved from the ledger and then validated. If the same
|
|
* handle is used for a new range, the state for the old range will be
|
|
* discarded. State is also discarded after the handle's expiry duration, or
|
|
* when drop_request is called for a given handle. The management of requests
|
|
* (how many unique handles are concurrently active, how they are correlated
|
|
* across HTTP requests, how the active quota is divided between callers) is
|
|
* left to the calling system.
|
|
*/
|
|
class AbstractStateCache
|
|
{
|
|
public:
|
|
virtual ~AbstractStateCache() = default;
|
|
|
|
/** Set the default time after which a request's state will be deleted, and
|
|
* will not be accessible without retrieving it again from the ledger. Any
|
|
* call to get_store_XXX which doesn't pass an explicit seconds_until_expiry
|
|
* will reset the timer to this default duration.
|
|
*/
|
|
virtual void set_default_expiry_duration(
|
|
ExpiryDuration seconds_until_expiry) = 0;
|
|
|
|
/** Retrieve a Store containing the state written at the given seqno.
|
|
*
|
|
* See @c get_store_range for a description of the caching behaviour. This
|
|
* is equivalent to get_store_at(handle, seqno, seqno), but returns nullptr
|
|
* if the state is currently unavailable.
|
|
*/
|
|
virtual StorePtr get_store_at(
|
|
RequestHandle handle,
|
|
ccf::SeqNo seqno,
|
|
ExpiryDuration seconds_until_expiry) = 0;
|
|
|
|
/** Same as @c get_store_at but uses default expiry value.
|
|
* @see get_store_at
|
|
*/
|
|
virtual StorePtr get_store_at(RequestHandle handle, ccf::SeqNo seqno) = 0;
|
|
|
|
/** Retrieve a full state at a given seqno, including the Store, the TxID
|
|
* assigned by consensus, and an offline-verifiable receipt for the Tx.
|
|
*/
|
|
virtual StatePtr get_state_at(RequestHandle handle, ccf::SeqNo seqno) = 0;
|
|
|
|
virtual StatePtr get_state_at(
|
|
RequestHandle handle,
|
|
ccf::SeqNo seqno,
|
|
ExpiryDuration seconds_until_expiry) = 0;
|
|
|
|
/** Retrieve a range of Stores containing the state written at the given
|
|
* indices.
|
|
*
|
|
* If this is not currently available, this function returns an empty vector
|
|
* and begins fetching the ledger entry asynchronously. This will generally
|
|
* be true for the first call for a given seqno, and it may take some time
|
|
* to completely fetch and validate. The call should be repeated later with
|
|
* the same arguments to retrieve the requested entries. This state is kept
|
|
* until it is deleted for one of the following reasons:
|
|
* - A call to @c drop_request
|
|
* - @c seconds_until_expiry seconds elapse without calling this function
|
|
* - This handle is used to request a different seqno or range
|
|
*
|
|
* The range is inclusive of both start_seqno and end_seqno. If a non-empty
|
|
* vector is returned, it will always contain the full requested range; the
|
|
* vector will be of length (end_seqno - start_seqno + 1) and will contain
|
|
* no nullptrs.
|
|
*/
|
|
virtual std::vector<StorePtr> get_store_range(
|
|
RequestHandle handle,
|
|
ccf::SeqNo start_seqno,
|
|
ccf::SeqNo end_seqno,
|
|
ExpiryDuration seconds_until_expiry) = 0;
|
|
|
|
/** Same as @c get_store_range but uses default expiry value.
|
|
* @see get_store_range
|
|
*/
|
|
virtual std::vector<StorePtr> get_store_range(
|
|
RequestHandle handle, ccf::SeqNo start_seqno, ccf::SeqNo end_seqno) = 0;
|
|
|
|
/** Drop state for the given handle.
|
|
*
|
|
* May be used to free up space once a historical query has been resolved,
|
|
* more aggressively than waiting for the requests to expire.
|
|
*/
|
|
virtual bool drop_request(RequestHandle handle) = 0;
|
|
};
|
|
} |