Key-Value Store API#

This page presents the API that a CCF application must use to access and mutate the replicated key-value store.

A CCF application should store its data in one or more kv::Map. The name, type, and serialisation of these maps is under the application’s control. Each invocation of an ccf::EndpointRegistry::Endpoint is given a kv::Tx transaction object, through which it can read and write to its kv::Map.

Map#

typedef uint64_t kv::Version#
static constexpr Version kv::NoVersion = 0u#
template<typename K, typename V, typename KSerialiser, typename VSerialiser>
class TypedMap : public kv::GetName#

Defines the schema of a map accessed by a ccf::Tx, exposing associated types. This map is an unordered associative container of key-value pairs. Each key, if defined, is associated with a value, and can be used to efficiently lookup that value.

K defines the type of the Key which indexes each entry, while V is the type of the Value associated with a given Key. KSerialiser and VSerialiser determine how each K and V are serialised and deserialised, so they may be written to the ledger and replicated by the consensus algorithm. Note that equality is always evaluated on the serialised form; if unequal Ks produce the same serialisation, they will coincide within this map. Serialiser which leverages existing JSON serialisation is provided by CCF.

template<typename K, typename V>
using kv::Map = JsonSerialisedMap<K, V>#

Short name for default-serialised maps, using JSON serialisers. Support for custom types can be added through the DECLARE_JSON… macros.

template<typename V, typename VSerialiser, typename Unit = kv::serialisers::ZeroBlitUnitCreator>
class TypedValue : public kv::GetName#

Defines the schema of a single-valued type accessed by a ccf::Tx. This value type is a container for an optional single element of type V. This may be undefined if the value has not been written to the KV, or else it has the value from the current or last-applied transaction.

V defines the type of the contained Value. VSerialiser determines how this V is serialised and deserialised, so it may be written to the ledger and replicated by the consensus algorithm.

This is implemented as a kv::Map from Unit to V, and the serialisation of the unit key is overridable with the Unit template parameter.

template<typename V>
using kv::Value = JsonSerialisedValue<V>#

Short name for default-serialised values, using JSON serialisers. Support for custom types can be added through the DECLARE_JSON… macros.

template<typename K, typename KSerialiser, typename Unit = kv::serialisers::ZeroBlitUnitCreator>
class TypedSet : public kv::GetName#

Defines the schema of a set type accessed by a ccf::Tx. This set is an unordered container of unique keys. Each key is either present or missing within the set, and key presence can be efficiently tested.

K defines the type of each entry in this set. KSerialiser determines how each K is serialised and deserialised, so they may be written to the ledger and replicated by the consensus algorithm. Note that equality is always evaluated on the serialised form; if unequal Ks produce the same serialisation, they will coincide within this set.

This is implemented as a kv::Map from K to Unit, and the serialisation of the unit values is overridable with the Unit template parameter.

template<typename K>
using kv::Set = JsonSerialisedSet<K>#

Short name for default-serialised sets, using JSON serialisers. Support for custom types can be added through the DECLARE_JSON… macros.

Transaction#

class ReadOnlyTx : public kv::BaseTx#

Used to create read-only handles for accessing a Map.

Acquiring a handle will create the map in the KV if it does not yet exist. The returned handles can view state written by previous transactions, and any additional modifications made in this transaction.

Subclassed by kv::Tx

Public Functions

template<class M>
inline M::ReadOnlyHandle *ro(M &m)#

Get a read-only handle from a map instance.

Parameters

m – Map instance

template<class M>
inline M::ReadOnlyHandle *ro(const std::string &map_name)#

Get a read-only handle by map name. Map type must be specified as explicit template parameter.

Parameters

map_name – Name of map

class Tx : public kv::ReadOnlyTx#

Used to create writeable handles for accessing a Map.

Acquiring a handle will create the map in the KV if it does not yet exist. Any writes made by the returned handles will be visible to all other handles created by this transaction. They will only be visible to other transactions after this transaction has completed and been applied. For type-safety, prefer restricted handles returned by ro or wo where possible, rather than the general rw.

See also

kv::ReadOnlyTx

Subclassed by kv::CommittableTx

Public Functions

template<class M>
inline M::Handle *rw(M &m)#

Get a read-write handle from a map instance.

This handle can be used for both reads and writes.

Parameters

m – Map instance

template<class M>
inline M::Handle *rw(const std::string &map_name)#

Get a read-write handle by map name. Map type must be specified as explicit template parameter.

Parameters

map_name – Name of map

template<class M>
inline M::WriteOnlyHandle *wo(M &m)#

Get a write-only handle from a map instance.

Parameters

m – Map instance

template<class M>
inline M::WriteOnlyHandle *wo(const std::string &map_name)#

Get a write-only handle by map name. Map type must be specified as explicit template parameter.

Parameters

map_name – Name of map

Handles#

template<typename K, typename V, typename KSerialiser, typename VSerialiser>
class ReadableMapHandle#

Grants read access to a kv::Map, as part of a kv::Tx.

Subclassed by kv::MapHandle< K, V, KSerialiser, VSerialiser >

Public Functions

inline std::optional<V> get(const K &key)#

Get value for key.

This returns the value for the key as seen by this transaction. If the key has been updated in the current transaction, that update will be reflected in the return of this call. Where the key has not been modified, this returns the state of a snapshot version from the start of the transaction’s execution.

Parameters

key – Key to read

Returns

Optional containing associated value, or empty if the key doesn’t exist

inline std::optional<V> get_globally_committed(const K &key)#

Get globally committed value for key, which has been replicated and acknowledged by consensus protocol.

This reads a globally replicated value for the specified key. The value will have been the most recent replicated value when the transaction began. Consensus may have advanced and committed a more recent version while this transaction executes. This is undetectable to the transaction.

Parameters

key – Key to read

Returns

Optional containing associated value, or empty if the key doesn’t exist in globally committed state

inline bool has(const K &key)#

Test if key is present.

This obeys the same rules as get regarding key visibility, but is more efficient if you do not need the associated value.

Parameters

key – Key to read

Returns

Boolean true iff key exists

inline std::optional<Version> get_version_of_previous_write(const K &key)#

Get version when this key was last written to, by a previous transaction.

Returns nullopt when there is no value, because the key has no value (never existed or has been removed). Note that this is always talking about the version of previously applied state and not the same values as get or has. This current transaction’s pending writes have no version yet, and this method does not talk about them.

Parameters

key – Key to read

Returns

Optional containing version of applied transaction which last wrote at this key, or nullopt if such a version does not exist

template<class F>
inline void foreach(F &&f)#

Iterate over all entries in the map.

The passed functor should have the signature bool(const K& k, const V& v). The iteration order is undefined. Return true to continue iteration, or return false from any invocation to terminate the iteration at that point - the functor will not be invoked again after it returns false.

The set of key-value entries which will be iterated over is determined at the point foreach is called, and does not include any modifications made by the functor. This means:

  • If the functor sets a value V at a new key K’, the functor will not be called for (K’, V)

  • If the functor changes the value at key K from V to V’, the functor will be called with the old value (K, V), not the new value (K, V’)

  • If the functor removes K, the functor will still be called for (K, V)

Calling get will always return the true latest state; the iterator visibility described above only applies to the keys and values passed to this functor.

Template Parameters

F – Functor type. Should usually be derived implicitly from f

Parameters

f – Functor instance, taking (const K& k, const V& v) and returning a bool. Return value determines whether the iteration should continue (true) or stop (false)

template<class F>
inline void foreach_key(F &&f)#

Iterate over all keys in the map.

Similar to foreach but the functor takes a single key argument rather than a key and value. Avoids deserialisation of values.

Template Parameters

F – Functor type. Should usually be derived implicitly from f

Parameters

f – Functor instance, taking (const K& k) and returning a bool. Return value determines whether the iteration should continue (true) or stop (false)

template<class F>
inline void foreach_value(F &&f)#

Iterate over all values in the map.

Similar to foreach but the functor takes a single value argument rather than a key and value. Avoids deserialisation of keys.

Template Parameters

F – Functor type. Should usually be derived implicitly from f

Parameters

f – Functor instance, taking (const V& v) and returning a bool. Return value determines whether the iteration should continue (true) or stop (false)

inline size_t size()#

Returns number of entries in this map.

This is the count of all currently present keys, including both those which were already committed and any modifications (taking into account new additions or removals) that have been made during this transaction.

Returns

Count of entries

template<typename K, typename V, typename KSerialiser, typename VSerialiser>
class WriteableMapHandle#

Grants write access to a kv::Map, as part of a kv::Tx.

Subclassed by kv::MapHandle< K, V, KSerialiser, VSerialiser >

Public Functions

inline void put(const K &key, const V &value)#

Write value at key.

If the key already exists, the previous value will be replaced with the new value.

Parameters
  • key – Key at which to insert

  • value – Associated value to be inserted

inline void remove(const K &key)#

Delete a key-value pair.

It is safe to call this on non-existent keys.

Parameters

key – Key to be removed

inline void clear()#

Delete every key-value pair.

template<typename K, typename V, typename KSerialiser, typename VSerialiser>
class MapHandle : public kv::AbstractHandle, public kv::ReadableMapHandle<K, V, KSerialiser, VSerialiser>, public kv::WriteableMapHandle<K, V, KSerialiser, VSerialiser>#

Grants read and write access to a kv::Map, as part of a kv::Tx.

template<typename V, typename VSerialiser, typename Unit>
class ReadableValueHandle#

Grants read access to a kv::Value, as part of a kv::Tx.

Subclassed by kv::ValueHandle< V, VSerialiser, Unit >

Public Functions

inline std::optional<V> get()#

Get the stored value.

This will return nullopt of the value has never been set, or has been removed.

Returns

Optional containing associated value, or empty if the value doesn’t exist

inline std::optional<V> get_globally_committed()#

Get globally committed value, which has been replicated and acknowledged by consensus protocol.

Returns

Optional containing associated value, or empty if the value doesn’t exist in globally committed state

inline bool has()#

Test if value is defined.

This is equivalent to get().has_value(), but is more efficient as it doesn’t need to deserialise the value.

Returns

Boolean true iff value is defined

inline std::optional<Version> get_version_of_previous_write()#

Get version when this value was last written to, by a previous transaction.

Returns

Optional containing version of applied transaction which last wrote to this value, or nullopt if such a version does not exist

template<typename V, typename VSerialiser, typename Unit>
class WriteableValueHandle#

Grants write access to a kv::Value, as part of a kv::Tx.

Subclassed by kv::ValueHandle< V, VSerialiser, Unit >

Public Functions

inline void put(const V &value)#

Modify this value.

If this value was previously defined, it will be overwritten. Even if the previous value was identical, this produces a serialised write in the ledger.

Parameters

value – New entry to assign to this Value

inline void clear()#

Delete this value, restoring its original undefined state.

template<typename V, typename VSerialiser, typename Unit>
class ValueHandle : public kv::AbstractHandle, public kv::ReadableValueHandle<V, VSerialiser, Unit>, public kv::WriteableValueHandle<V, VSerialiser, Unit>#

Grants read and write access to a kv::Value, as part of a kv::Tx.

template<typename K, typename KSerialiser>
class ReadableSetHandle#

Grants read access to a kv::Set, as part of a kv::Tx.

Subclassed by kv::SetHandle< K, KSerialiser, Unit >

Public Functions

inline bool contains(const K &key)#

Test whether a key is present in the set.

This returns true if the key is present, including if it was added to the set during this transaction.

Parameters

key – Key to test

Returns

Boolean true iff key exists

inline std::optional<Version> get_version_of_previous_write(const K &key)#

Get version when this key was last added to the set.

Returns nullopt if the key is not present.

Parameters

key – Key to read

Returns

Optional containing version of applied transaction which last wrote at this key, or nullopt if such a version does not exist

template<class F>
inline void foreach(F &&f)#

Iterate over all entries in this set.

Template Parameters

F – Functor type. Should usually be derived implicitly from f

Parameters

f – Functor instance, taking (const K& k) and returning a bool. Return value determines whether the iteration should continue (true) or stop (false)

inline size_t size()#

Returns number of entries in this set.

This is the count of all currently present keys, including both those which were already committed and any modifications (taking into account new additions or removals) that have been made during this transaction.

Returns

Count of entries

template<typename K, typename KSerialiser, typename Unit>
class WriteableSetHandle#

Grants write access to a kv::Set, as part of a kv::Tx.

Subclassed by kv::SetHandle< K, KSerialiser, Unit >

Public Functions

inline void insert(const K &key)#

Insert an element into this set.

This will always insert a value, producing a new write and updating future calls to ReadableSetHandle::get_version_of_previous_write, even if this key was already present.

Parameters

key – Key to insert

inline void remove(const K &key)#

Delete an element from this set.

It is safe to call this on non-existent keys.

Parameters

key – Key to delete

inline void clear()#

Delete every element in this set.

template<typename K, typename KSerialiser, typename Unit>
class SetHandle : public kv::AbstractHandle, public kv::ReadableSetHandle<K, KSerialiser>, public kv::WriteableSetHandle<K, KSerialiser, Unit>#

Grants read and write access to a kv::Set, as part of a kv::Tx.

Serialisation#

enum class kv::EntryType : uint8_t#

Values:

enumerator WriteSet#
enumerator Snapshot#
enumerator WriteSetWithClaims#
enumerator WriteSetWithCommitEvidence#
enumerator WriteSetWithCommitEvidenceAndClaims#
enumerator MAX#