Skip to content

sgns::securecrdt::SecureCrdt

Mandatory wrapper for reading/writing registered SecureCrdt keys. More...

#include <SecureCrdt.hpp>

Inherits from std::enable_shared_from_this< SecureCrdt >

Public Types

Name
enum class uint8_t Error { UNREGISTERED_KEY = 0, NO_VALUE_PROPOSED, INVALID_SIGNATURE, UNAUTHORIZED_SIGNER, SIGNATURE_LIMIT_EXCEEDED, MALFORMED_VALUE, QUORUM_THRESHOLD_BELOW_FLOOR, UNREGISTERED_CANDIDATE_DOMAIN, CANDIDATE_CONTEXT_MISMATCH, UNAUTHORIZED_CANDIDATE_SIGNER, CANDIDATE_LIMIT_EXCEEDED, DUPLICATE_CANDIDATE_APPROVAL, CANDIDATE_AUTHORIZATION_PENDING}
Error codes returned by SecureCrdt's write/read operations.
using std::function< void(const CandidateId &, const CandidateApprovalRecord &)> CandidateCallback

Public Functions

Name
SecureCrdt(std::shared_ptr< sgns::crdt::GlobalDB > db, std::string topic, std::shared_ptr< SecureCrdtRegistry > registry =nullptr)
Constructs a SecureCrdt wrapper over an existing GlobalDB instance.
SecureCrdtRegistry & Registry()
Returns this node's isolated policy registry.
outcome::result< void > ProposeValue(const sgns::crdt::HierarchicalKey & base_key, const std::vector< uint8_t > & payload)
Proposes a value for a registered base_key. Runs the SAME codec/semantic check the remote filter callback runs on a base_key element (DeserializeFromBytes + Verify) BEFORE ever calling Put – closes the local/remote asymmetry gap (T-09-10). Proposing a value has no signature requirement by itself; it only becomes trusted once quorum-worth of sig-entries exist (D-04), so this is not a bypass of D-03.
outcome::result< void > AddSignature(const sgns::crdt::HierarchicalKey & base_key, const std::string & signer_address, const std::vector< uint8_t > & signature)
Adds a signature over the CURRENT value at base_key. Fetches the value fresh via GlobalDB::Get each call (never a cached/stale value, closing the replay threat T-09-07) and verifies it via multisig::VerifyPayloadSignature before ever calling Put – an invalid signature is never persisted (D-03 local-write gate).
outcome::result< std::optional< sgns::base::Buffer > > ReadIfQuorum(const sgns::crdt::HierarchicalKey & base_key)
Returns the current value at base_key only once the required number of valid unique signatures from the registered signer set are present (D-04 quorum re-derivation); returns std::nullopt if quorum is not yet met.
outcome::result< CandidateId > SubmitCandidateApproval(const CandidateApprovalRecord & record)
outcome::result< std::vector< CandidateApprovalRecord > > ReadCandidateApprovals(const CandidateId & id)
outcome::result< std::vector< CandidateId > > ListCandidates(const std::string & domain, const std::string & predecessor_hash, bool current_only =true)
bool RegisterCandidateCallback(const std::string & domain, CandidateCallback callback, const void * owner_token)
void UnregisterCandidateCallbackIf(const std::string & domain, const void * owner_token)
bool RegisterFilters()
Self-registration entry point: registers the element filter (D-03 second, independent enforcement layer for remote- originated deltas) for every currently-registered SecureCrdtRegistry entry. Must be called once after construction (e.g. from a New(...)-style factory), mirroring ValidatorRegistry::RegisterFilter's call-from-factory convention.
void UnregisterFiltersFor(const std::string & escaped_base_key)
Removes the ingest element filter RegisterFilters installed for escaped_base_key's pattern – teardown counterpart of RegisterFilters for ONE registry entry (G-WR-01: no stale filter callback, with its captured policy entry, may outlive the policy owner on a GlobalDB that keeps running).

Detailed Description

class sgns::securecrdt::SecureCrdt;

Mandatory wrapper for reading/writing registered SecureCrdt keys.

   `ProposeValue`/`AddSignature` are the only sanctioned callers of
   `GlobalDB::Put` for a registered key (D-03). `ReadIfQuorum` never
   writes and always re-derives trust from the current base_key value
   plus all `sig/<addr>` children (D-04) -- no "final" marker key is
   ever written or read by this class.

Public Types Documentation

enum Error

Enumerator Value Description
UNREGISTERED_KEY 0 base_key has no SecureCrdtRegistry entry
NO_VALUE_PROPOSED AddSignature/ReadIfQuorum called before any ProposeValue.
INVALID_SIGNATURE signature failed VerifyPayloadSignature against the current value
UNAUTHORIZED_SIGNER signer is noncanonical or absent from the current signer-set snapshot
SIGNATURE_LIMIT_EXCEEDED a new signature child would exceed the current authorized-set bound
MALFORMED_VALUE payload failed DeserializeFromBytes/Verify (codec/semantic check)
QUORUM_THRESHOLD_BELOW_FLOOR configured quorum_threshold below ceil(0.51*signer_set_size)
UNREGISTERED_CANDIDATE_DOMAIN
CANDIDATE_CONTEXT_MISMATCH
UNAUTHORIZED_CANDIDATE_SIGNER
CANDIDATE_LIMIT_EXCEEDED
DUPLICATE_CANDIDATE_APPROVAL
CANDIDATE_AUTHORIZATION_PENDING Local trust prerequisites are not durably confirmed yet.

Error codes returned by SecureCrdt's write/read operations.

using CandidateCallback

using sgns::securecrdt::SecureCrdt::CandidateCallback =  std::function<void( const CandidateId &, const CandidateApprovalRecord & )>;

Public Functions Documentation

function SecureCrdt

SecureCrdt(
    std::shared_ptr< sgns::crdt::GlobalDB > db,
    std::string topic,
    std::shared_ptr< SecureCrdtRegistry > registry =nullptr
)

Constructs a SecureCrdt wrapper over an existing GlobalDB instance.

Parameters:

  • db GlobalDB instance to Put/Get/Query against.
  • topic CRDT broadcast/listen topic to use for all Put calls (no new networking – reuses whatever topic the caller's GlobalDB is already wired to).
  • registry Optional registry injection for composition/tests. A fresh registry is created when omitted.

function Registry

SecureCrdtRegistry & Registry()

Returns this node's isolated policy registry.

function ProposeValue

outcome::result< void > ProposeValue(
    const sgns::crdt::HierarchicalKey & base_key,
    const std::vector< uint8_t > & payload
)

Proposes a value for a registered base_key. Runs the SAME codec/semantic check the remote filter callback runs on a base_key element (DeserializeFromBytes + Verify) BEFORE ever calling Put – closes the local/remote asymmetry gap (T-09-10). Proposing a value has no signature requirement by itself; it only becomes trusted once quorum-worth of sig-entries exist (D-04), so this is not a bypass of D-03.

Parameters:

  • base_key Registered CRDT key to propose a value for.
  • payload Raw payload bytes to persist.

Return: outcome::success on success, Error::UNREGISTERED_KEY if base_key has no registry entry, Error::MALFORMED_VALUE if the codec/semantic check fails (Put is never called in that case).

function AddSignature

outcome::result< void > AddSignature(
    const sgns::crdt::HierarchicalKey & base_key,
    const std::string & signer_address,
    const std::vector< uint8_t > & signature
)

Adds a signature over the CURRENT value at base_key. Fetches the value fresh via GlobalDB::Get each call (never a cached/stale value, closing the replay threat T-09-07) and verifies it via multisig::VerifyPayloadSignature before ever calling Put – an invalid signature is never persisted (D-03 local-write gate).

Parameters:

  • base_key Registered CRDT key the signature is claimed over.
  • signer_address Address claimed to have produced signature.
  • signature Raw signature bytes.

Return: outcome::success on success, Error::UNREGISTERED_KEY if base_key has no registry entry, Error::NO_VALUE_PROPOSED if no value exists yet at base_key, Error::INVALID_SIGNATURE if verification fails (Put is never called in that case).

function ReadIfQuorum

outcome::result< std::optional< sgns::base::Buffer > > ReadIfQuorum(
    const sgns::crdt::HierarchicalKey & base_key
)

Returns the current value at base_key only once the required number of valid unique signatures from the registered signer set are present (D-04 quorum re-derivation); returns std::nullopt if quorum is not yet met.

Parameters:

  • base_key Registered CRDT key to read.

Return: outcome::success(bytes) if quorum is met, outcome::success(nullopt) if the key does not exist yet or quorum is not yet met, or Error::UNREGISTERED_KEY if base_key has no registry entry.

Note: This method deliberately does NOT deserialize, semantically- verify, or Apply() the returned bytes. Once quorum is confirmed, the CALLER is responsible for instantiating its own ISignedCRDTData implementer via DeserializeFromBytes(*result) and calling Verify()+Apply() on it. SecureCrdt stays generic across all registered types and never assumes which concrete ISignedCRDTData subclass or Apply() side effect applies to a given base_key – that knowledge lives only with the registered type's own owner (e.g. Phase 10 TrustedPeerRegistry, Phase 11 BurnConfig, Phase 12 ValidatorRegistry migration).

function SubmitCandidateApproval

outcome::result< CandidateId > SubmitCandidateApproval(
    const CandidateApprovalRecord & record
)

function ReadCandidateApprovals

outcome::result< std::vector< CandidateApprovalRecord > > ReadCandidateApprovals(
    const CandidateId & id
)

function ListCandidates

outcome::result< std::vector< CandidateId > > ListCandidates(
    const std::string & domain,
    const std::string & predecessor_hash,
    bool current_only =true
)

function RegisterCandidateCallback

bool RegisterCandidateCallback(
    const std::string & domain,
    CandidateCallback callback,
    const void * owner_token
)

function UnregisterCandidateCallbackIf

void UnregisterCandidateCallbackIf(
    const std::string & domain,
    const void * owner_token
)

function RegisterFilters

bool RegisterFilters()

Self-registration entry point: registers the element filter (D-03 second, independent enforcement layer for remote- originated deltas) for every currently-registered SecureCrdtRegistry entry. Must be called once after construction (e.g. from a New(...)-style factory), mirroring ValidatorRegistry::RegisterFilter's call-from-factory convention.

Return: true if all filter registrations succeeded.

function UnregisterFiltersFor

void UnregisterFiltersFor(
    const std::string & escaped_base_key
)

Removes the ingest element filter RegisterFilters installed for escaped_base_key's pattern – teardown counterpart of RegisterFilters for ONE registry entry (G-WR-01: no stale filter callback, with its captured policy entry, may outlive the policy owner on a GlobalDB that keeps running).

Parameters:

  • escaped_base_key Regex-escaped base key pattern exactly as registered with SecureCrdtRegistry (the caller of Register passed the same escaping).

The removed pattern is built by the SAME construction helper RegisterFilters uses ("/?" + escaped_base_key + "(/sig(/.*)?)?"), so removal can never drift from installation. Removing a pattern that was never installed is a safe no-op (CRDTDataFilter::UnregisterElementFilter is an erase-remove over the pattern registry).


Updated on 2026-10-06 at 13:34:20 +0000