Documentation
¶
Overview ¶
Copyright IBM Corp. All Rights Reserved. SPDX-License-Identifier: Apache-2.0
Index ¶
- Constants
- func Close(closer Closer)
- func CloseFunc(closer func() error)
- func CloseRWDB(readDB *sql.DB, writeDB WriteDB) error
- func HasMovementsParams(params driver2.QueryMovementsParams) cond.Condition
- func HasTokenDetails(params driver2.QueryTokenDetailsParams, tokenTable common.Table) cond.Condition
- func HasTokens(colTxID, colIdx common.FieldName, ids ...*token.ID) cond.Condition
- func HasTransactionParams(params driver2.QueryTransactionsParams, table common.Table) cond.Condition
- func HasValidationParams(params driver2.QueryValidationRecordsParams, tableName string) cond.Condition
- func IsExpiredToken(tokenRequests, tokenLocks common3.Table, leaseExpiry time.Duration) cond.Condition
- func IsStaleLock(tokenRequests, tokenLocks common3.Table, leaseExpiry time.Duration) cond.Condition
- func RunBalancePreparedComparison(b *testing.B, store *TokenStore)
- func RunGetStatusPreparedComparison(b *testing.B, store *TransactionStore)
- func RunGetTokenRequestPreparedComparison(b *testing.B, store *TransactionStore)
- func RunSpendableTokensIteratorByPreparedComparison(b *testing.B, store *TokenStore)
- func RunTokenStoreBenchmarks(b *testing.B, store *TokenStore)
- func RunUnspentTokensIteratorByPreparedComparison(b *testing.B, store *TokenStore)
- func SeedBenchTokens(b *testing.B, store *TokenStore, n int)
- func TestAWAddMovement(t *testing.T, store transactionsStoreConstructor)
- func TestAWAddMovementContextCancelled(t *testing.T, store transactionsStoreConstructor)
- func TestAWAddTokenRequest(t *testing.T, store transactionsStoreConstructor)
- func TestAWAddTokenRequestContextCancelled(t *testing.T, store transactionsStoreConstructor)
- func TestAWAddTransaction(t *testing.T, store transactionsStoreConstructor)
- func TestAWAddTransactionContextCancelled(t *testing.T, store transactionsStoreConstructor)
- func TestAWAddValidationRecord(t *testing.T, store endorserStoreConstructor)
- func TestAddTransactionEndorsementAck(t *testing.T, store transactionsStoreConstructor)
- func TestAddTransactionEndorsementAckContextCancelled(t *testing.T, store transactionsStoreConstructor)
- func TestCountOpenFindings(t *testing.T, store transactionsStoreConstructor)
- func TestCountOpenFindings_NoOpenFindings(t *testing.T, store transactionsStoreConstructor)
- func TestDeleteTokensContextCancelled(t *testing.T, store tokenStoreConstructor)
- func TestGetStatus(t *testing.T, store transactionsStoreConstructor)
- func TestGetStatusContextCancelled(t *testing.T, store transactionsStoreConstructor)
- func TestGetStatusEndorser(t *testing.T, store endorserStoreConstructor)
- func TestGetTokenRequest(t *testing.T, store transactionsStoreConstructor)
- func TestGetTransactionEndorsementAcks(t *testing.T, store transactionsStoreConstructor)
- func TestGetWalletID(t *testing.T, store walletStoreConstructor)
- func TestGetWalletIDNotFound(t *testing.T, store walletStoreConstructor)
- func TestGetWalletIDs(t *testing.T, store walletStoreConstructor)
- func TestIdentityExists(t *testing.T, store walletStoreConstructor)
- func TestIdentityExistsPropagatesQueryError(t *testing.T, store walletStoreConstructor)
- func TestLoadMeta(t *testing.T, store walletStoreConstructor)
- func TestLock(t *testing.T, store tokenLockStoreConstructor)
- func TestLockContextCancelled(t *testing.T, store tokenLockStoreConstructor)
- func TestQueryMovements(t *testing.T, store transactionsStoreConstructor)
- func TestQueryTokenRequests(t *testing.T, store transactionsStoreConstructor)
- func TestQueryTransactions(t *testing.T, store transactionsStoreConstructor)
- func TestQueryValidations(t *testing.T, store endorserStoreConstructor)
- func TestSetStatus(t *testing.T, store transactionsStoreConstructor)
- func TestSetStatusContextCancelled(t *testing.T, store transactionsStoreConstructor)
- func TestSetStatusEndorser(t *testing.T, store endorserStoreConstructor)
- func TestStoreIdentity(t *testing.T, store walletStoreConstructor)
- func TestStoreIdentityIdempotent(t *testing.T, store walletStoreConstructor)
- func TestUnlockByTxID(t *testing.T, store tokenLockStoreConstructor)
- func TestUnlockByTxIDContextCancelled(t *testing.T, store tokenLockStoreConstructor)
- type AnyUUID
- type BigInt
- type Closer
- type EndorserStore
- func (db *EndorserStore) Close() error
- func (db *EndorserStore) CreateSchema() error
- func (db *EndorserStore) GetSchema() string
- func (db *EndorserStore) GetStatus(ctx context.Context, txID string) (dbdriver.TxStatus, string, error)
- func (db *EndorserStore) NewEndorserStoreTransaction() (dbdriver.EndorserStoreTransaction, error)
- func (db *EndorserStore) QueryValidations(ctx context.Context, params dbdriver.QueryValidationRecordsParams) (dbdriver.ValidationRecordsIterator, error)
- type EndorserStoreTransaction
- func (w *EndorserStoreTransaction) AddValidationRecord(ctx context.Context, txID string, tokenRequest []byte, meta map[string][]byte, ...) error
- func (w *EndorserStoreTransaction) Commit() error
- func (w *EndorserStoreTransaction) Impl() dbdriver.TransactionImpl
- func (w *EndorserStoreTransaction) Rollback()
- func (w *EndorserStoreTransaction) SetStatus(ctx context.Context, txID string, status dbdriver.TxStatus, message string) error
- type IdentityStore
- func NewCachedIdentityStore(readDB *sql.DB, writeDB WriteDB, tables TableNames, ci common3.CondInterpreter, ...) (*IdentityStore, error)
- func NewIdentityStore(readDB *sql.DB, writeDB WriteDB, tables TableNames, ...) (*IdentityStore, error)
- func NewIdentityStoreWithNotifier(readDB *sql.DB, writeDB WriteDB, tables TableNames, ...) (*IdentityStore, error)
- func NewNoCacheIdentityStore(readDB *sql.DB, writeDB WriteDB, tables TableNames, ci common3.CondInterpreter, ...) (*IdentityStore, error)
- func (db *IdentityStore) AddConfiguration(ctx context.Context, wp driver.IdentityConfiguration) error
- func (db *IdentityStore) Close() error
- func (db *IdentityStore) ConfigurationExists(ctx context.Context, id, typ, url string) (bool, error)
- func (db *IdentityStore) ConfigurationsByID(ctx context.Context, id, configurationType string) ([]driver.IdentityConfiguration, error)
- func (db *IdentityStore) CreateSchema() error
- func (db *IdentityStore) GetAuditInfo(ctx context.Context, id []byte) ([]byte, error)
- func (db *IdentityStore) GetConfiguration(ctx context.Context, id, typ, url string) (*driver.IdentityConfiguration, error)
- func (db *IdentityStore) GetConfigurationID(ctx context.Context, id, typ, url string) (string, error)
- func (db *IdentityStore) GetExistingSignerInfo(ctx context.Context, ids ...tdriver.Identity) ([]string, error)
- func (db *IdentityStore) GetSchema() string
- func (db *IdentityStore) GetSignerInfo(ctx context.Context, identity []byte) ([]byte, error)
- func (db *IdentityStore) GetTokenInfo(ctx context.Context, id []byte) ([]byte, []byte, error)
- func (db *IdentityStore) IterateSigners(ctx context.Context, offset, limit int) ([]idriver.SignerEntry, error)
- func (db *IdentityStore) IteratorConfigurations(ctx context.Context, configurationType string) (idriver.IdentityConfigurationIterator, error)
- func (db *IdentityStore) Notifier() (idriver.IdentityConfigurationNotifier, error)
- func (db *IdentityStore) RegisterIdentityDescriptor(ctx context.Context, descriptor *idriver.IdentityDescriptor, ...) error
- func (db *IdentityStore) SignerInfoExists(ctx context.Context, id []byte) (bool, error)
- func (db *IdentityStore) StoreIdentityData(ctx context.Context, id []byte, identityAudit []byte, tokenMetadata []byte, ...) error
- func (db *IdentityStore) StoreSignerInfo(ctx context.Context, id tdriver.Identity, info []byte) error
- type KeystoreStore
- func (db *KeystoreStore) Close() error
- func (db *KeystoreStore) CreateSchema() error
- func (db *KeystoreStore) Delete(key string) error
- func (db *KeystoreStore) Get(key string, state any) error
- func (db *KeystoreStore) GetRaw(key string) ([]byte, error)
- func (db *KeystoreStore) GetSchema() string
- func (db *KeystoreStore) Put(key string, state any) error
- type PersistenceConstructor
- type PreparedStmtHolder
- type StorageConfig
- type TableNameCreator
- type TableNames
- func GetTableNames(prefix string, params ...string) (TableNames, error)
- func GetTableNamesWithConfig(prefix string, cfg StorageConfig, params ...string) (TableNames, error)
- func GetTableNamesWithOverrides(prefix string, overrides TableNamesConfig, params ...string) (TableNames, error)
- func GetTableNamesWithOverridesSkipPrefix(prefix string, overrides TableNamesConfig, params ...string) (TableNames, error)
- type TableNamesConfig
- type TokenLockStore
- func (db *TokenLockStore) Cleanup(ctx context.Context, leaseExpiry time.Duration) error
- func (db *TokenLockStore) Close() error
- func (db *TokenLockStore) CreateSchema() error
- func (db *TokenLockStore) GetSchema() string
- func (db *TokenLockStore) ListLocks(ctx context.Context) ([]driver.LockRecord, error)
- func (db *TokenLockStore) Lock(ctx context.Context, tokenID *token.ID, consumerTxID transaction.ID, ...) error
- func (db *TokenLockStore) LockAt(ctx context.Context, tokenID *token.ID, consumerTxID transaction.ID, _ string, ...) error
- func (db *TokenLockStore) UnlockByTxID(ctx context.Context, consumerTxID transaction.ID) error
- type TokenStore
- func (db *TokenStore) AcquireCleanupLeadership(ctx context.Context) (driver.CleanupLeadership, bool, error)
- func (db *TokenStore) Balance(ctx context.Context, walletID string, typ token.Type) (*big.Int, error)
- func (db *TokenStore) Close() error
- func (db *TokenStore) ContinueTokenDBTransaction(tx driver.Transaction) (driver.TokenStoreTransaction, error)
- func (db *TokenStore) CreateSchema() error
- func (db *TokenStore) DeleteTokens(ctx context.Context, deletedBy string, ids ...*token.ID) error
- func (db *TokenStore) ExistsCertification(ctx context.Context, tokenID *token.ID) bool
- func (db *TokenStore) GetAllTokenInfos(ctx context.Context, ids []*token.ID) ([][]byte, error)
- func (db *TokenStore) GetCertifications(ctx context.Context, ids []*token.ID) ([][]byte, error)
- func (db *TokenStore) GetDeletedTokensPendingSKICleanup(ctx context.Context, olderThan time.Duration, limit int) ([]driver.DeletedToken, error)
- func (db *TokenStore) GetSchema() string
- func (db *TokenStore) GetTokenMetadata(ctx context.Context, ids []*token.ID) ([][]byte, error)
- func (db *TokenStore) GetTokenOutputs(ctx context.Context, ids []*token.ID, callback tdriver.QueryCallbackFunc) error
- func (db *TokenStore) GetTokenOutputsAndMeta(ctx context.Context, ids []*token.ID) ([][]byte, [][]byte, []token.Format, error)
- func (db *TokenStore) GetTokens(ctx context.Context, inputs ...*token.ID) ([]*token.Token, error)
- func (db *TokenStore) HasEnoughSpendableTokens(ctx context.Context, walletID string, typ token.Type, target *big.Int) (bool, error)
- func (db *TokenStore) HasTokenForIdentity(ctx context.Context, ownerIdentity []byte, ownerType string) (bool, error)
- func (db *TokenStore) IsMine(ctx context.Context, txID string, index uint64) (bool, error)
- func (db *TokenStore) IssuedBalance(ctx context.Context, opts tdriver.IssuerBalanceQuery) (*big.Int, error)
- func (db *TokenStore) ListAuditTokens(ctx context.Context, ids ...*token.ID) ([]*token.Token, error)
- func (db *TokenStore) ListHistoryIssuedTokens(ctx context.Context) (*token.IssuedTokens, error)
- func (db *TokenStore) ListUnspentTokens(ctx context.Context) (*token.UnspentTokens, error)
- func (db *TokenStore) ListUnspentTokensBy(ctx context.Context, walletID string, typ token.Type) (*token.UnspentTokens, error)
- func (db *TokenStore) ListUnspentTokensByWallets(ctx context.Context, walletIDs []string, typ token.Type) (map[string]*token.UnspentTokens, error)
- func (db *TokenStore) MarkTokenCleaned(ctx context.Context, txID string, index uint64, cleanedBy string) error
- func (db *TokenStore) NewTokenDBTransaction() (driver.TokenStoreTransaction, error)
- func (db *TokenStore) Notifier() (driver.TokenNotifier, error)
- func (db *TokenStore) PreparedStmtCount() int
- func (db *TokenStore) PublicParams(ctx context.Context) ([]byte, error)
- func (db *TokenStore) PublicParamsByHash(ctx context.Context, rawHash tdriver.PPHash) ([]byte, error)
- func (db *TokenStore) PublicParamsHashes(ctx context.Context) ([]tdriver.PPHash, error)
- func (db *TokenStore) QuerySpendableTokens(ctx context.Context, params driver.SpendableTokensQuery) (tdriver.SpendableTokensIterator, error)
- func (db *TokenStore) QueryTokenDetails(ctx context.Context, params driver.QueryTokenDetailsParams) ([]driver.TokenDetails, error)
- func (db *TokenStore) RedeemedBalance(ctx context.Context, opts tdriver.IssuerBalanceQuery) (*big.Int, error)
- func (db *TokenStore) SetSupportedTokenFormats(formats []token.Format) error
- func (db *TokenStore) SpendableTokensIteratorBy(ctx context.Context, walletID string, typ token.Type) (tdriver.SpendableTokensIterator, error)
- func (db *TokenStore) StoreCertifications(ctx context.Context, certifications map[*token.ID][]byte) error
- func (db *TokenStore) StorePublicParams(ctx context.Context, raw []byte) error
- func (db *TokenStore) StoreToken(ctx context.Context, tr driver.TokenRecord, owners []string) (err error)
- func (db *TokenStore) TransactionExists(ctx context.Context, id string) (bool, error)
- func (db *TokenStore) UnspentLedgerTokensIteratorBy(ctx context.Context) (tdriver.LedgerTokensIterator, error)
- func (db *TokenStore) UnspentTokensIterator(ctx context.Context) (tdriver.UnspentTokensIterator, error)
- func (db *TokenStore) UnspentTokensIteratorBy(ctx context.Context, walletID string, tokenType token.Type) (tdriver.UnspentTokensIterator, error)
- func (db *TokenStore) UnsupportedTokensIteratorBy(ctx context.Context, walletID string, tokenType token.Type) (tdriver.UnsupportedTokensIterator, error)
- func (db *TokenStore) WhoDeletedTokens(ctx context.Context, inputs ...*token.ID) ([]string, []bool, error)
- type TokenTransaction
- func (t *TokenTransaction) Commit() error
- func (t *TokenTransaction) Delete(ctx context.Context, tokenID token.ID, deletedBy string) error
- func (t *TokenTransaction) GetToken(ctx context.Context, tokenID token.ID, includeDeleted bool) (*token.Token, []string, error)
- func (t *TokenTransaction) Rollback() error
- func (t *TokenTransaction) SetSpendable(ctx context.Context, tokenID token.ID, spendable bool) error
- func (t *TokenTransaction) SetSpendableBySupportedTokenFormats(ctx context.Context, formats []token.Format) error
- func (t *TokenTransaction) StoreToken(ctx context.Context, tr driver.TokenRecord, owners []string) error
- type TransactionStore
- func NewAuditTransactionStore(readDB *sql.DB, writeDB WriteDB, tables TableNames, ci common3.CondInterpreter, ...) (*TransactionStore, error)
- func NewOwnerTransactionStore(readDB *sql.DB, writeDB WriteDB, tables TableNames, ci common3.CondInterpreter, ...) (*TransactionStore, error)
- func NewTransactionStoreWithNotifierAndRecovery(readDB *sql.DB, writeDB WriteDB, tables TableNames, ci common3.CondInterpreter, ...) (*TransactionStore, error)
- func (db *TransactionStore) AcquireLeadership(context.Context, int64) (dbdriver.RecoveryLeadership, bool, error)
- func (db *TransactionStore) AcquireRecoveryLeadership(ctx context.Context) (dbdriver.RecoveryLeadership, bool, error)
- func (db *TransactionStore) AddTransactionEndorsementAck(ctx context.Context, txID string, endorser token.Identity, sigma []byte) (err error)
- func (db *TransactionStore) ClaimPendingTransactions(ctx context.Context, params dbdriver.RecoveryClaimParams) ([]*dbdriver.RecoveryClaim, error)
- func (db *TransactionStore) Close() error
- func (db *TransactionStore) CountOpenFindings(ctx context.Context) (map[int]int64, error)
- func (db *TransactionStore) CreateSchema() error
- func (db *TransactionStore) GetSchema() string
- func (db *TransactionStore) GetStatus(ctx context.Context, txID string) (dbdriver.TxStatus, string, error)
- func (db *TransactionStore) GetStatuses(ctx context.Context, txIDs []string) (map[string]dbdriver.TxStatus, error)
- func (db *TransactionStore) GetTokenRequest(ctx context.Context, txID string) ([]byte, error)
- func (db *TransactionStore) GetTokenRequests(ctx context.Context, txIDs []string) (map[string][]byte, error)
- func (db *TransactionStore) GetTransactionEndorsementAcks(ctx context.Context, txID string) (map[string][]byte, error)
- func (db *TransactionStore) NewTransactionStoreTransaction() (dbdriver.TransactionStoreTransaction, error)
- func (db *TransactionStore) Notifier() (dbdriver.TransactionNotifier, error)
- func (s *TransactionStore) PrefixedTableName(name string) string
- func (db *TransactionStore) QueryFindings(ctx context.Context, params dbdriver.QueryFindingsParams) ([]*dbdriver.FindingRecord, error)
- func (db *TransactionStore) QueryMovements(ctx context.Context, params dbdriver.QueryMovementsParams) (res []*dbdriver.MovementRecord, err error)
- func (db *TransactionStore) QueryTokenRequests(ctx context.Context, params dbdriver.QueryTokenRequestsParams) (dbdriver.TokenRequestIterator, error)
- func (db *TransactionStore) QueryTransactions(ctx context.Context, params dbdriver.QueryTransactionsParams, ...) (*driver3.PageIterator[*dbdriver.TransactionRecord], error)
- func (db *TransactionStore) ReleaseRecoveryClaim(context.Context, string, string, string) error
- func (db *TransactionStore) ResolveFindingsNotSeenSince(ctx context.Context, checkers []string, seenAt time.Time) (int64, error)
- func (db *TransactionStore) SetStatus(ctx context.Context, txID string, status dbdriver.TxStatus, message string) error
- func (db *TransactionStore) UpsertFindings(ctx context.Context, findings []dbdriver.FindingRecord, seenAt time.Time) error
- type TransactionStoreTransaction
- func (w *TransactionStoreTransaction) AddMovement(ctx context.Context, rs ...dbdriver.MovementRecord) error
- func (w *TransactionStoreTransaction) AddTokenRequest(ctx context.Context, txID string, tr []byte, ...) error
- func (w *TransactionStoreTransaction) AddTransaction(ctx context.Context, rs ...dbdriver.TransactionRecord) error
- func (w *TransactionStoreTransaction) Commit() error
- func (w *TransactionStoreTransaction) Impl() dbdriver.TransactionImpl
- func (w *TransactionStoreTransaction) Rollback()
- func (w *TransactionStoreTransaction) SetStatus(ctx context.Context, txID string, status dbdriver.TxStatus, message string) error
- type WalletStore
- func (db *WalletStore) Close() error
- func (db *WalletStore) CreateSchema() error
- func (db *WalletStore) GetConfID(ctx context.Context, identity token.Identity) (string, error)
- func (db *WalletStore) GetSchema() string
- func (db *WalletStore) GetWalletID(ctx context.Context, identity token.Identity, roleID int) (driver.WalletID, error)
- func (db *WalletStore) GetWalletIDs(ctx context.Context, roleID int) ([]driver.WalletID, error)
- func (db *WalletStore) IdentityExists(ctx context.Context, identity token.Identity, wID driver.WalletID, roleID int) (bool, error)
- func (db *WalletStore) LoadMeta(ctx context.Context, identity token.Identity, wID driver.WalletID, roleID int) ([]byte, error)
- func (db *WalletStore) StoreIdentity(ctx context.Context, identity token.Identity, eID string, wID driver.WalletID, ...) error
- type WriteDB
Constants ¶
const ( // ConfigKeyTableNames is the absolute configuration key for global SQL table name overrides. // // This key is resolved against the root configuration provider (not a TMS-scoped // configuration), so it applies to all TMS instances on the node and maps directly // to token.storage.tableNames in the configuration file. // // Example YAML: // // token: // storage: // tableNames: // id_signers: identity_signers // tokens: my_tokens ConfigKeyTableNames = "token.storage.tableNames" // ConfigKeySkipPrefix is the absolute configuration key for disabling the // FSC-generated prefix on SQL table names. // // When set to true, table names are produced without any prefix, regardless // of what prefix is supplied at runtime. Default is false. // // Example YAML: // // token: // storage: // skipPrefix: true ConfigKeySkipPrefix = "token.storage.skipPrefix" // ConfigKeyLockStrategy is the absolute configuration key for the // token-lock acquisition strategy used by SQL backends that support more // than one (currently Postgres only; other backends read and ignore it). // // Example YAML: // // token: // storage: // db: // lockStrategy: skipLocked ConfigKeyLockStrategy = "token.storage.db.lockStrategy" // LockStrategyInsert is the default lock strategy: INSERT and catch the // unique-constraint violation on a lost race. Equivalent to leaving // ConfigKeyLockStrategy unset. LockStrategyInsert = "insert" // LockStrategyOnConflict acquires a lock with // INSERT ... ON CONFLICT DO NOTHING RETURNING, avoiding a server-side // unique-violation error on a lost race. LockStrategyOnConflict = "onConflict" // LockStrategySkipLocked behaves like LockStrategyOnConflict for a single // lock, and additionally allows a covering-window batch claim using // FOR UPDATE SKIP LOCKED to avoid colliding with rows a concurrent // claimant is already processing. LockStrategySkipLocked = "skipLocked" )
Variables ¶
This section is empty.
Functions ¶
func CloseRWDB ¶ added in v0.24.0
CloseRWDB closes a store's read and write handles, joining their errors.
It replaces FSC's Close, which takes two *sql.DB and compares them to avoid closing the same pool twice. That comparison cannot survive a decorated write handle, and it is not needed: sql.DB.Close is idempotent, so closing one pool through both handles is harmless.
A handle that is nil is skipped rather than dereferenced, so closing a store that failed part-way through construction reports the errors it has instead of panicking.
func HasMovementsParams ¶
func HasMovementsParams(params driver2.QueryMovementsParams) cond.Condition
func HasTokenDetails ¶
func HasTransactionParams ¶
func HasValidationParams ¶
func HasValidationParams(params driver2.QueryValidationRecordsParams, tableName string) cond.Condition
func IsExpiredToken ¶
func IsStaleLock ¶ added in v0.18.0
IsStaleLock matches the lock rows whose lease has aged out, or whose consuming transaction is Deleted or Orphan. The correlation is on consumer_tx_id, the transaction that is trying to spend the token: (tx_id, idx) identifies the locked token, i.e. the transaction that created it, whose status says nothing about whether the lock is still live. The condition is correlated rather than a partial-key IN on tx_id, so cleanup removes only the matching (tx_id, idx) rows and leaves the other indices of the same transaction locked. See #2018.
The argument order matches IsExpiredToken (tokenRequests first, tokenLocks second) so a swapped call is immediately visible and consistent across this file.
func RunBalancePreparedComparison ¶ added in v0.15.1
func RunBalancePreparedComparison(b *testing.B, store *TokenStore)
RunBalancePreparedComparison benchmarks balance against a version of the same query executed via a statement prepared once outside the timed loop, using the same seed data, worker count, and duration as RunTokenStoreBenchmarks so the numbers are directly comparable.
This exists to answer: "how much would moving to prepared statements help for wallet balance checks?" balance() has a single caller (Balance) that always sets only WalletID/TokenType, matching the same shape as UnspentTokensIteratorBy/SpendableTokensIteratorBy.
func RunGetStatusPreparedComparison ¶ added in v0.16.0
func RunGetStatusPreparedComparison(b *testing.B, store *TransactionStore)
func RunGetTokenRequestPreparedComparison ¶ added in v0.16.0
func RunGetTokenRequestPreparedComparison(b *testing.B, store *TransactionStore)
RunGetStatusPreparedComparison benchmarks GetStatus against a version of the same query executed via a statement prepared once outside the timed loop, using the same worker count and duration as RunTokenStoreBenchmarks so the numbers are directly comparable.
Unlike the token-store queries, GetStatus has exactly one query shape (tx_id = ?, always present) - this benchmark exists to confirm the win holds for that simpler, single-shape case, backing the finality-polling loop in ttx/finality.go. RunGetTokenRequestPreparedComparison benchmarks GetTokenRequest against a version of the same query executed via a statement prepared once outside the timed loop. Same single-shape reasoning as GetStatus.
func RunSpendableTokensIteratorByPreparedComparison ¶ added in v0.15.1
func RunSpendableTokensIteratorByPreparedComparison(b *testing.B, store *TokenStore)
RunSpendableTokensIteratorByPreparedComparison benchmarks SpendableTokensIteratorBy against a version of the same query executed via a statement prepared once outside the timed loop, using the same seed data, worker count, and duration as RunTokenStoreBenchmarks so the numbers are directly comparable.
This exists to answer: "how much would moving to prepared statements help for the selector's spend-fetch query?" (see #1919). The query built by SpendableTokensIteratorBy is dynamic (its shape depends on whether walletID / typ are empty), so this comparison fixes both parameters to non-empty values matching the seeded data, which is the common case in production (see token/services/selector/sherdlock/fetcher.go).
func RunTokenStoreBenchmarks ¶
func RunTokenStoreBenchmarks(b *testing.B, store *TokenStore)
func RunUnspentTokensIteratorByPreparedComparison ¶ added in v0.14.2
func RunUnspentTokensIteratorByPreparedComparison(b *testing.B, store *TokenStore)
RunUnspentTokensIteratorByPreparedComparison benchmarks UnspentTokensIteratorBy against a version of the same query executed via a statement prepared once outside the timed loop, using the same seed data, worker count, and duration as RunTokenStoreBenchmarks so the numbers are directly comparable.
This exists to answer: "how much would moving to prepared statements help for our primary token-selection query?" (see #1183). The query built by UnspentTokensIteratorBy is dynamic (its shape depends on whether walletID / tokenType are empty), so this comparison fixes both parameters to non-empty values matching the seeded data, which is the common case in production.
func SeedBenchTokens ¶
func SeedBenchTokens(b *testing.B, store *TokenStore, n int)
func TestAWAddMovement ¶
func TestAWAddMovementContextCancelled ¶ added in v0.15.1
TestAWAddMovementContextCancelled verifies that a cancelled context is propagated from ExecContext through AddMovement inside a TransactionStoreTransaction.
func TestAWAddTokenRequest ¶
func TestAWAddTokenRequestContextCancelled ¶ added in v0.15.1
TestAWAddTokenRequestContextCancelled verifies that a cancelled context is propagated from ExecContext through AddTokenRequest inside a TransactionStoreTransaction.
func TestAWAddTransaction ¶
func TestAWAddTransactionContextCancelled ¶ added in v0.15.1
TestAWAddTransactionContextCancelled verifies that a cancelled context is propagated from ExecContext through AddTransaction inside a TransactionStoreTransaction.
func TestAddTransactionEndorsementAckContextCancelled ¶ added in v0.15.1
func TestAddTransactionEndorsementAckContextCancelled(t *testing.T, store transactionsStoreConstructor)
TestAddTransactionEndorsementAckContextCancelled verifies that a cancelled context is propagated from ExecContext back to the caller of AddTransactionEndorsementAck.
func TestCountOpenFindings ¶ added in v0.24.0
TestCountOpenFindings verifies the aggregate query groups open findings by severity and excludes resolved ones, and that the rows scan into the returned map keyed by the raw severity value.
func TestCountOpenFindings_NoOpenFindings ¶ added in v0.24.0
TestCountOpenFindings_NoOpenFindings verifies an empty result set (nothing open) returns an empty, non-nil map rather than an error.
func TestDeleteTokensContextCancelled ¶ added in v0.15.1
TestDeleteTokensContextCancelled verifies that a cancelled context is propagated from ExecContext back to the caller of DeleteTokens as a context error.
func TestGetStatus ¶
func TestGetStatusContextCancelled ¶ added in v0.15.1
TestGetStatusContextCancelled verifies that a cancelled context is propagated from QueryContext back to the caller of GetStatus as a context error.
func TestGetStatusEndorser ¶
func TestGetTokenRequest ¶
func TestGetWalletID ¶
func TestGetWalletIDNotFound ¶ added in v0.21.0
TestGetWalletIDNotFound pins the not-found contract of the WalletStoreService: an identity with no stored binding resolves to ("", nil), never an error. The role Registry relies on this to tell a transient storage failure apart from "this identity was never registered" (issue #2063).
func TestGetWalletIDs ¶
func TestIdentityExists ¶
func TestIdentityExistsPropagatesQueryError ¶ added in v0.24.0
TestIdentityExistsPropagatesQueryError asserts that a failed lookup surfaces as an error rather than as a negative answer.
func TestLoadMeta ¶
func TestLockContextCancelled ¶ added in v0.15.1
TestLockContextCancelled verifies that Lock propagates context cancellation from ExecContext back to the caller as a context error.
func TestQueryMovements ¶
func TestQueryTokenRequests ¶
func TestQueryTransactions ¶
func TestQueryValidations ¶
func TestSetStatus ¶
func TestSetStatusContextCancelled ¶ added in v0.15.1
TestSetStatusContextCancelled verifies that a cancelled context is propagated from ExecContext back to the caller of SetStatus as a context error.
func TestSetStatusEndorser ¶
func TestStoreIdentity ¶
func TestUnlockByTxID ¶
func TestUnlockByTxIDContextCancelled ¶ added in v0.15.1
TestUnlockByTxIDContextCancelled verifies that UnlockByTxID propagates context cancellation from ExecContext back to the caller as a context error.
Types ¶
type BigInt ¶
BigInt is a custom wrapper around math/big.Int that implements sql.Scanner for reading NUMERIC values from the DB
type EndorserStore ¶
type EndorserStore struct {
// contains filtered or unexported fields
}
EndorserStore manages validation records for token transaction endorsements
func NewEndorserStore ¶
func NewEndorserStore( readDB *sql.DB, writeDB WriteDB, tables TableNames, ci common3.CondInterpreter, pi common3.PagInterpreter, ) (*EndorserStore, error)
NewEndorserStore creates a new EndorserStore
func (*EndorserStore) Close ¶
func (db *EndorserStore) Close() error
Close closes the database connections
func (*EndorserStore) CreateSchema ¶
func (db *EndorserStore) CreateSchema() error
CreateSchema creates the database schema for the endorser store
func (*EndorserStore) GetSchema ¶
func (db *EndorserStore) GetSchema() string
GetSchema returns the SQL schema for creating the endorser store tables
func (*EndorserStore) GetStatus ¶
func (db *EndorserStore) GetStatus(ctx context.Context, txID string) (dbdriver.TxStatus, string, error)
GetStatus returns the status of a validation record
func (*EndorserStore) NewEndorserStoreTransaction ¶
func (db *EndorserStore) NewEndorserStoreTransaction() (dbdriver.EndorserStoreTransaction, error)
NewEndorserStoreTransaction creates a new transaction for endorser operations
func (*EndorserStore) QueryValidations ¶
func (db *EndorserStore) QueryValidations(ctx context.Context, params dbdriver.QueryValidationRecordsParams) (dbdriver.ValidationRecordsIterator, error)
QueryValidations returns an iterator over validation records matching the given params
type EndorserStoreTransaction ¶
type EndorserStoreTransaction struct {
// contains filtered or unexported fields
}
EndorserStoreTransaction represents a database transaction for endorser operations
func (*EndorserStoreTransaction) AddValidationRecord ¶
func (w *EndorserStoreTransaction) AddValidationRecord(ctx context.Context, txID string, tokenRequest []byte, meta map[string][]byte, ppHash driver2.PPHash) error
AddValidationRecord adds a validation record to the database.
Verification: as for TransactionStoreTransaction.AddTokenRequest, this layer does not interpret tokenRequest — the wire-format check lives in the endorserdb service. What is refused here is a row no later check could act on: an empty transaction id, empty request bytes, or an empty public parameters hash.
func (*EndorserStoreTransaction) Commit ¶
func (w *EndorserStoreTransaction) Commit() error
Commit commits the transaction
func (*EndorserStoreTransaction) Impl ¶
func (w *EndorserStoreTransaction) Impl() dbdriver.TransactionImpl
Impl returns the underlying transaction implementation
func (*EndorserStoreTransaction) Rollback ¶
func (w *EndorserStoreTransaction) Rollback()
Rollback rolls back the transaction. A rollback failure cannot be returned (the interface returns nothing) but is logged rather than dropped, so a transaction that outlived its rollback leaves a trace. sql.ErrTxDone is expected when the transaction has already been committed or rolled back.
type IdentityStore ¶
type IdentityStore struct {
// contains filtered or unexported fields
}
IdentityStore is a SQL-backed implementation of the IdentityStore interface.
func NewCachedIdentityStore ¶
func NewCachedIdentityStore( readDB *sql.DB, writeDB WriteDB, tables TableNames, ci common3.CondInterpreter, errorWrapper driver2.SQLErrorWrapper, ) (*IdentityStore, error)
func NewIdentityStore ¶
func NewIdentityStore( readDB *sql.DB, writeDB WriteDB, tables TableNames, signerInfoCache cache[bool], auditInfoCache cache[[]byte], ci common3.CondInterpreter, errorWrapper driver2.SQLErrorWrapper, ) (*IdentityStore, error)
func NewIdentityStoreWithNotifier ¶
func NewIdentityStoreWithNotifier( readDB *sql.DB, writeDB WriteDB, tables TableNames, signerInfoCache cache[bool], auditInfoCache cache[[]byte], ci common3.CondInterpreter, errorWrapper driver2.SQLErrorWrapper, notifier idriver.IdentityConfigurationNotifier, ) (*IdentityStore, error)
NewIdentityStoreWithNotifier creates a new IdentityStore with a notifier.
func NewNoCacheIdentityStore ¶
func NewNoCacheIdentityStore( readDB *sql.DB, writeDB WriteDB, tables TableNames, ci common3.CondInterpreter, errorWrapper driver2.SQLErrorWrapper, ) (*IdentityStore, error)
func (*IdentityStore) AddConfiguration ¶
func (db *IdentityStore) AddConfiguration(ctx context.Context, wp driver.IdentityConfiguration) error
AddConfiguration stores an identity configuration in the database. It also enqueues an event to the notifier if available.
func (*IdentityStore) Close ¶
func (db *IdentityStore) Close() error
func (*IdentityStore) ConfigurationExists ¶
func (*IdentityStore) ConfigurationsByID ¶ added in v0.14.2
func (db *IdentityStore) ConfigurationsByID(ctx context.Context, id, configurationType string) ([]driver.IdentityConfiguration, error)
ConfigurationsByID returns all configurations with the given id and type, regardless of their url.
func (*IdentityStore) CreateSchema ¶
func (db *IdentityStore) CreateSchema() error
func (*IdentityStore) GetAuditInfo ¶
GetAuditInfo returns the audit info stored for id, or nil if none is stored.
Verification: the row is addressed by identity hash, so the identity stored alongside the audit info is compared against id before the audit info is returned or cached. Audit info is what an auditor uses to attribute a transaction to a party, so handing back audit info belonging to a different identity than the caller asked for would misattribute it. A row whose identity and identity_hash columns disagree is reported rather than returned.
func (*IdentityStore) GetConfiguration ¶
func (db *IdentityStore) GetConfiguration(ctx context.Context, id, typ, url string) (*driver.IdentityConfiguration, error)
GetConfiguration returns the configuration with the given id, type, and url.
func (*IdentityStore) GetConfigurationID ¶ added in v0.18.0
func (db *IdentityStore) GetConfigurationID(ctx context.Context, id, typ, url string) (string, error)
GetConfigurationID returns the conf_id persisted for the configuration with the given id, type, and url. It returns the empty string if that configuration is not stored yet.
The column is read rather than recomputed from driver.IdentityConfiguration.UniqueID on purpose: conf_id is referenced by wallets.conf_id through a foreign key, so for a configuration stored by an earlier release the value on disk is the only one the constraint accepts, even when a newer encoding derives a different UniqueID for the same tuple.
func (*IdentityStore) GetExistingSignerInfo ¶
func (db *IdentityStore) GetExistingSignerInfo(ctx context.Context, ids ...tdriver.Identity) ([]string, error)
GetExistingSignerInfo returns the unique ids of the passed identities for which signer info is stored.
Verification: an empty identity is excluded from the lookup rather than looked up, for the reason given on StoreSignerInfo — its unique id is the shared "<empty>" row key, so consulting it would report a row written for one caller as the signer info of any other empty identity, and identity.Provider.AreMe would answer that the empty identity is mine. It is excluded rather than rejected because this is an existence query over a batch: an empty entry is simply not an identity signer info can exist for, and failing the batch would also lose the answer for the caller's other identities.
func (*IdentityStore) GetSchema ¶
func (db *IdentityStore) GetSchema() string
func (*IdentityStore) GetSignerInfo ¶
GetSignerInfo returns the signer info stored for identity, or nil if none is stored.
Verification: the row is addressed by identity hash, so the identity stored alongside the signer info is compared against the requested one before the info is returned. Signer info is what a key manager resolves into a signer, so returning the info of a different identity than the caller named would route signing to the wrong key. A row whose identity and identity_hash columns disagree is reported rather than returned.
func (*IdentityStore) GetTokenInfo ¶
GetTokenInfo returns the token metadata stored for id, or nil if none is stored.
Verification: as for GetAuditInfo — an empty id is refused, and the identity stored alongside the metadata is compared against id before the metadata is returned. Token metadata is what the owner of a token uses to recognise and spend it, so metadata belonging to a different identity is not a usable substitute for the caller's own.
func (*IdentityStore) IterateSigners ¶
func (db *IdentityStore) IterateSigners(ctx context.Context, offset, limit int) ([]idriver.SignerEntry, error)
IterateSigners returns a page of SignerEntry values from the Signers table, ordered by identity_hash, starting at the given offset and returning at most limit entries.
func (*IdentityStore) IteratorConfigurations ¶
func (db *IdentityStore) IteratorConfigurations(ctx context.Context, configurationType string) (idriver.IdentityConfigurationIterator, error)
IteratorConfigurations returns an iterator to all configurations of the given type.
func (*IdentityStore) Notifier ¶
func (db *IdentityStore) Notifier() (idriver.IdentityConfigurationNotifier, error)
Notifier returns the IdentityNotifier associated with this store.
func (*IdentityStore) RegisterIdentityDescriptor ¶
func (db *IdentityStore) RegisterIdentityDescriptor(ctx context.Context, descriptor *idriver.IdentityDescriptor, alias tdriver.Identity) error
RegisterIdentityDescriptor stores the signer info and audit info of the descriptor's identity and of the given alias, and refreshes the corresponding caches. All writes happen in a single transaction. The operation is idempotent and safe to retry: rows that are already present are left untouched and the missing ones are written, so both a full re-registration and the retry of a registration that was only partially persisted succeed.
func (*IdentityStore) SignerInfoExists ¶
SignerInfoExists returns true if signer info is stored for id.
Verification: as for GetExistingSignerInfo, which this delegates to — an empty id is never looked up, so it reads as "no signer info" and the shared "<empty>" row key stays unconsulted.
func (*IdentityStore) StoreIdentityData ¶
func (db *IdentityStore) StoreIdentityData(ctx context.Context, id []byte, identityAudit []byte, tokenMetadata []byte, tokenMetadataAudit []byte) error
StoreIdentityData binds id to its audit info and token metadata.
Verification: an empty id is refused. Rows are keyed by tdriver.Identity.UniqueID, which maps the empty identity to the constant "<empty>" rather than to a hash, so an empty identity would write to a well-known key that any later empty-identity lookup reads back as its own.
func (*IdentityStore) StoreSignerInfo ¶
func (db *IdentityStore) StoreSignerInfo(ctx context.Context, id tdriver.Identity, info []byte) error
StoreSignerInfo binds id to the signer info a key manager resolves into a signer.
Verification: an empty id is refused, for the reason given on StoreIdentityData — the empty identity does not hash, it maps to the shared "<empty>" row key.
type KeystoreStore ¶
type KeystoreStore struct {
// contains filtered or unexported fields
}
func NewKeystoreStore ¶
func NewKeystoreStore(readDB *sql.DB, writeDB WriteDB, tables TableNames, ci qcommon.CondInterpreter, errorWrapper driver.SQLErrorWrapper) (*KeystoreStore, error)
func (*KeystoreStore) Close ¶
func (db *KeystoreStore) Close() error
func (*KeystoreStore) CreateSchema ¶
func (db *KeystoreStore) CreateSchema() error
func (*KeystoreStore) Delete ¶
func (db *KeystoreStore) Delete(key string) error
func (*KeystoreStore) GetSchema ¶
func (db *KeystoreStore) GetSchema() string
type PersistenceConstructor ¶
type PreparedStmtHolder ¶ added in v0.15.1
type PreparedStmtHolder[K comparable] interface { // Execute prepares (or reuses) the statement cached under key and runs // it. buildQuery is called on every invocation (hit or miss) since it // captures the caller's real argument values via closure; only its // returned SQL text is discarded on a cache hit, the args are always // used. If preparing or running the cached statement fails, Execute // falls back to running the query directly (unprepared, uncached). // Callers are responsible for closing the returned rows. Execute(ctx context.Context, db *sql.DB, key K, buildQuery func() (string, []any, error)) (*sql.Rows, error) // Count returns the number of cached prepared statements. Intended for // tests verifying statement reuse across argument shapes. Count() int // Close closes all cached prepared statements. Close() error }
PreparedStmtHolder caches prepared statements keyed by K, executing a query built by the caller and falling back to an unprepared query if preparing or executing the cached statement fails. It centralizes the get-or-prepare-and-execute logic shared by any query that runs repeatedly with the same SQL shape but different bound argument values (see #1183). TokenStore instantiates one holder per query that benefits from this treatment. Exported as an interface so stores can inject a fake for unit testing.
type StorageConfig ¶
type StorageConfig struct {
// TableNames contains optional short-code overrides for individual table names.
TableNames TableNamesConfig
// SkipPrefix disables the FSC-generated prefix on all table names when true.
// Default is false.
SkipPrefix bool
// LockStrategy selects the token-lock acquisition strategy. One of
// LockStrategyInsert (default), LockStrategyOnConflict, or
// LockStrategySkipLocked. Only acted upon by the Postgres driver.
LockStrategy string
}
StorageConfig holds all SQL storage configuration options that can be read from the configuration provider.
func LoadStorageConfig ¶
func LoadStorageConfig(cfg driver2.Config) (StorageConfig, error)
LoadStorageConfig reads all SQL storage options from cfg. It returns a zero-value StorageConfig (and nil error) when cfg is nil.
On a validation error for one option, it still returns every option parsed successfully so far (with LockStrategy defaulted to LockStrategyInsert), rather than discarding them. Callers that warn-and-continue on error (e.g. postgres/driver.go, sqlite/driver.go) otherwise silently lose TableNames/SkipPrefix to an unrelated typo in lockStrategy - see #2395 Phase 7.
type TableNameCreator ¶
type TableNameCreator struct {
// contains filtered or unexported fields
}
func NewTableNameCreator ¶
func NewTableNameCreator(defaultPrefix string) *TableNameCreator
func (*TableNameCreator) CreateTableName ¶
func (c *TableNameCreator) CreateTableName(tablePrefix, name string, params ...string) (string, error)
func (*TableNameCreator) GetFormatter ¶
func (c *TableNameCreator) GetFormatter(prefix string) (*tableNameFormatter, error)
func (*TableNameCreator) MustGetTableName ¶
func (c *TableNameCreator) MustGetTableName(tablePrefix, name string, params ...string) string
type TableNames ¶
type TableNames struct {
Prefix string
Params []string
Movements string
Transactions string
Requests string
Validations string
TransactionEndorseAck string
Certifications string
Tokens string
Ownership string
PublicParams string
Wallets string
IdentityConfigurations string
IdentityInfo string
Signers string
TokenLocks string
KeyStore string
EIDLeases string
TokenSKICleanups string
Findings string
}
func GetTableNames ¶
func GetTableNames(prefix string, params ...string) (TableNames, error)
GetTableNames returns the SQL table names for the given prefix and params using the default short codes. It is equivalent to calling GetTableNamesWithOverrides with a nil overrides map.
func GetTableNamesWithConfig ¶
func GetTableNamesWithConfig(prefix string, cfg StorageConfig, params ...string) (TableNames, error)
GetTableNamesWithConfig returns the SQL table names using all options from cfg.
func GetTableNamesWithOverrides ¶
func GetTableNamesWithOverrides(prefix string, overrides TableNamesConfig, params ...string) (TableNames, error)
GetTableNamesWithOverrides returns the SQL table names for the given prefix and params, applying any short-code substitutions from overrides before the FSC formatter wraps them with the prefix and params.
The overrides map key is the canonical short code (e.g. "id_signers") and the value is the replacement short code (e.g. "identity_signers"). Unknown keys produce a warning and are ignored; all other fields keep their default values.
func GetTableNamesWithOverridesSkipPrefix ¶
func GetTableNamesWithOverridesSkipPrefix(prefix string, overrides TableNamesConfig, params ...string) (TableNames, error)
GetTableNamesWithOverridesSkipPrefix is like GetTableNamesWithOverrides but omits the FSC-generated prefix from every table name.
type TableNamesConfig ¶
TableNamesConfig maps a short code (e.g. "id_signers") to the replacement short code that will be used when generating the final SQL table name. The FSC-generated prefix and params are still applied around the replacement value.
Unknown keys are warned and ignored. Omitted keys keep their default short codes.
func LoadTableNamesConfig ¶
func LoadTableNamesConfig(cfg driver2.Config) (TableNamesConfig, error)
LoadTableNamesConfig reads the table name overrides from cfg. It returns an empty map (and nil error) when cfg is nil or the config key is absent.
type TokenLockStore ¶
type TokenLockStore struct {
ReadDB *sql.DB
WriteDB WriteDB
Table tokenLockTables
Logger logging.Logger
// contains filtered or unexported fields
}
func NewTokenLockStore ¶
func NewTokenLockStore(readDB *sql.DB, writeDB WriteDB, tables TableNames, ci common3.CondInterpreter, errorWrapper fscdriver.SQLErrorWrapper) (*TokenLockStore, error)
func (*TokenLockStore) Cleanup ¶ added in v0.18.0
Cleanup releases the stale token locks: those whose consuming transaction is Deleted or Orphan, and those whose lease is older than leaseExpiry. Only the affected (tx_id, idx) rows are deleted. The same statement is used by every SQL backend. created_at is declared TIMESTAMPTZ so the comparison with the database-side NOW() expression is always timezone-consistent on Postgres.
func (*TokenLockStore) Close ¶
func (db *TokenLockStore) Close() error
func (*TokenLockStore) CreateSchema ¶
func (db *TokenLockStore) CreateSchema() error
func (*TokenLockStore) GetSchema ¶
func (db *TokenLockStore) GetSchema() string
func (*TokenLockStore) ListLocks ¶ added in v0.24.0
func (db *TokenLockStore) ListLocks(ctx context.Context) ([]driver.LockRecord, error)
ListLocks returns every currently held lock, joined with the status of its consuming transaction. It reuses the same TokenLocks/Requests join as IsStaleLock/Cleanup, so the notion of "consuming transaction" stays consistent across the diagnostic reader and the actual expiry logic. See driver.TokenLockStore.ListLocks and #2395.
func (*TokenLockStore) Lock ¶
func (db *TokenLockStore) Lock(ctx context.Context, tokenID *token.ID, consumerTxID transaction.ID, walletID string) error
Lock locks the token for consumerTxID. walletID identifies the wallet the tokens are selected for; this SQL-backed store does not apply per-wallet rate limiting and so ignores it. A custom TokenLockStore may use walletID to throttle per wallet.
func (*TokenLockStore) LockAt ¶ added in v0.18.0
func (db *TokenLockStore) LockAt(ctx context.Context, tokenID *token.ID, consumerTxID transaction.ID, _ string, createdAt time.Time) error
LockAt is like Lock but records the supplied timestamp as the lock creation time instead of the current time. It is intended for testing (backdating locks to exercise the lease-age expiry path without sleeping).
The lock row is inserted only if the token is still spendable at that instant, in the same statement, so the two outcomes a caller has to tell apart cannot interleave: a primary-key conflict means somebody else holds the lock (ErrTokenAlreadyLocked), and a zero-row insert means the token is no longer a valid candidate (ErrTokenNotSpendable). The foreign key alone is not enough for the second: it only requires the token row to exist, and spending a token soft-deletes it rather than removing the row, so without the predicate a lock can be acquired on a token that was spent since the caller read it - after which the caller returns it to a consumer that cannot load it. See #2395.
func (*TokenLockStore) UnlockByTxID ¶
func (db *TokenLockStore) UnlockByTxID(ctx context.Context, consumerTxID transaction.ID) error
type TokenStore ¶
type TokenStore struct {
// contains filtered or unexported fields
}
func NewTokenStoreWithNotifier ¶
func NewTokenStoreWithNotifier(readDB *sql.DB, writeDB WriteDB, tables TableNames, ci common3.CondInterpreter, notifier driver.TokenNotifier) (*TokenStore, error)
func NewTokenStoreWithNotifierAndCleanup ¶
func NewTokenStoreWithNotifierAndCleanup( readDB *sql.DB, writeDB WriteDB, tables TableNames, ci common3.CondInterpreter, notifier driver.TokenNotifier, cleanupLeaderFactory func(context.Context, WriteDB) (driver.CleanupLeadership, bool, error), ) (*TokenStore, error)
func (*TokenStore) AcquireCleanupLeadership ¶
func (db *TokenStore) AcquireCleanupLeadership(ctx context.Context) (driver.CleanupLeadership, bool, error)
AcquireCleanupLeadership attempts to acquire leadership for keystore cleanup operations. When no leader factory is configured, leadership is granted locally (for non-distributed deployments). In distributed deployments (PostgreSQL), this uses advisory locks to ensure only one instance performs cleanup. AcquireCleanupLeadership returns a leadership handle for cleanup sweeping. When no leader factory is configured, leadership is granted locally.
func (*TokenStore) Balance ¶
func (db *TokenStore) Balance(ctx context.Context, walletID string, typ token.Type) (*big.Int, error)
Balance returns the sum of the amounts of the tokens with type and EID equal to those passed as arguments. The result is returned as a *big.Int to support arbitrary precision and prevent overflow.
func (*TokenStore) Close ¶
func (db *TokenStore) Close() error
func (*TokenStore) ContinueTokenDBTransaction ¶
func (db *TokenStore) ContinueTokenDBTransaction(tx driver.Transaction) (driver.TokenStoreTransaction, error)
func (*TokenStore) CreateSchema ¶
func (db *TokenStore) CreateSchema() error
func (*TokenStore) DeleteTokens ¶
DeleteTokens deletes multiple tokens at the same time (when spent, invalid or expired)
func (*TokenStore) ExistsCertification ¶
func (*TokenStore) GetAllTokenInfos ¶
GetAllTokenInfos retrieves the token information for the passed ids.
func (*TokenStore) GetCertifications ¶
func (*TokenStore) GetDeletedTokensPendingSKICleanup ¶
func (db *TokenStore) GetDeletedTokensPendingSKICleanup(ctx context.Context, olderThan time.Duration, limit int) ([]driver.DeletedToken, error)
GetDeletedTokensPendingSKICleanup returns deleted, owned tokens older than the specified duration that haven't had their SKI keys cleaned up yet (no record in token_ski_cleanups table). Only tokens owned by this node are considered, since this node only holds the secret keys for tokens it owns, not for tokens it merely audited or issued.
func (*TokenStore) GetSchema ¶
func (db *TokenStore) GetSchema() string
func (*TokenStore) GetTokenMetadata ¶
GetTokenMetadata retrieves the token metadata for the passed ids. For each id, the callback is invoked to unmarshal the token metadata
func (*TokenStore) GetTokenOutputs ¶
func (db *TokenStore) GetTokenOutputs(ctx context.Context, ids []*token.ID, callback tdriver.QueryCallbackFunc) error
func (*TokenStore) GetTokenOutputsAndMeta ¶
func (db *TokenStore) GetTokenOutputsAndMeta(ctx context.Context, ids []*token.ID) ([][]byte, [][]byte, []token.Format, error)
GetTokenOutputsAndMeta retrieves both the token output, metadata, and type for the passed ids.
func (*TokenStore) GetTokens ¶
GetTokens returns the owned tokens and their identifier keys for the passed ids.
func (*TokenStore) HasEnoughSpendableTokens ¶ added in v0.26.0
func (db *TokenStore) HasEnoughSpendableTokens(ctx context.Context, walletID string, typ token.Type, target *big.Int) (bool, error)
HasEnoughSpendableTokens reports whether the wallet's total spendable balance of typ is at least target. It deliberately ignores locks: the question it answers is "can this wallet ever pay", not "can it pay right now". The selector uses it as a fast fail, so that a wallet holding dust that could never cover the requested amount fails immediately instead of burning the immediate-retry/backoff budget first.
func (*TokenStore) HasTokenForIdentity ¶
func (db *TokenStore) HasTokenForIdentity(ctx context.Context, ownerIdentity []byte, ownerType string) (bool, error)
HasTokenForIdentity returns true if any token in the Tokens table has the given owner identity and owner type, regardless of whether the token has been spent or not.
func (*TokenStore) IssuedBalance ¶ added in v0.15.1
func (db *TokenStore) IssuedBalance(ctx context.Context, opts tdriver.IssuerBalanceQuery) (*big.Int, error)
IssuedBalance returns the sum of the amounts of the tokens issued by this node, filtered by the passed options. Redeemed tokens are excluded. The result is returned as a *big.Int to support arbitrary precision and prevent overflow.
func (*TokenStore) ListAuditTokens ¶
func (db *TokenStore) ListAuditTokens(ctx context.Context, ids ...*token.ID) ([]*token.Token, error)
ListAuditTokens returns the audited tokens associated to the passed ids
func (*TokenStore) ListHistoryIssuedTokens ¶
func (db *TokenStore) ListHistoryIssuedTokens(ctx context.Context) (*token.IssuedTokens, error)
ListHistoryIssuedTokens returns the list of issued tokens
func (*TokenStore) ListUnspentTokens ¶
func (db *TokenStore) ListUnspentTokens(ctx context.Context) (*token.UnspentTokens, error)
ListUnspentTokens returns the list of unspent tokens
func (*TokenStore) ListUnspentTokensBy ¶
func (db *TokenStore) ListUnspentTokensBy(ctx context.Context, walletID string, typ token.Type) (*token.UnspentTokens, error)
ListUnspentTokensBy returns the list of unspent tokens, filtered by owner and token type
func (*TokenStore) ListUnspentTokensByWallets ¶
func (db *TokenStore) ListUnspentTokensByWallets(ctx context.Context, walletIDs []string, typ token.Type) (map[string]*token.UnspentTokens, error)
ListUnspentTokensByWallets issues a single SELECT with an IN clause on the owning wallet, then partitions the result rows in Go. This avoids the N round-trip cost of calling ListUnspentTokensBy in a loop when a caller (e.g. a bank-node wallet list endpoint) needs balances for many wallets at once. Empty input returns an empty map without querying.
func (*TokenStore) MarkTokenCleaned ¶
func (db *TokenStore) MarkTokenCleaned(ctx context.Context, txID string, index uint64, cleanedBy string) error
MarkTokenCleaned marks a token as having its cryptographic keys cleaned up. This prevents the cleanup service from processing the same token multiple times. The cleanedBy parameter identifies which instance performed the cleanup.
func (*TokenStore) NewTokenDBTransaction ¶
func (db *TokenStore) NewTokenDBTransaction() (driver.TokenStoreTransaction, error)
func (*TokenStore) Notifier ¶
func (db *TokenStore) Notifier() (driver.TokenNotifier, error)
func (*TokenStore) PreparedStmtCount ¶ added in v0.15.1
func (db *TokenStore) PreparedStmtCount() int
PreparedStmtCount returns the number of cached prepared statements for UnspentTokensIteratorBy. Intended for tests verifying statement reuse across argument shapes.
func (*TokenStore) PublicParams ¶
func (db *TokenStore) PublicParams(ctx context.Context) ([]byte, error)
func (*TokenStore) PublicParamsByHash ¶
func (db *TokenStore) PublicParamsByHash(ctx context.Context, rawHash tdriver.PPHash) ([]byte, error)
PublicParamsByHash returns the public parameters whose hash matches the passed one, or nil if none are stored under it.
Verification: the returned parameters are hashed and compared against rawHash — see integrity.CheckPublicParamsHash. Callers fetch by hash in order to re-validate a transaction against the setup it was created under, so parameters that do not hash to the requested hash are reported rather than returned.
func (*TokenStore) PublicParamsHashes ¶ added in v0.21.0
PublicParamsHashes returns the hashes of every public parameters version stored so far, most recently stored first. StorePublicParams never overwrites an existing row, so this is the full history of public parameters this node has observed.
func (*TokenStore) QuerySpendableTokens ¶ added in v0.24.0
func (db *TokenStore) QuerySpendableTokens(ctx context.Context, params driver.SpendableTokensQuery) (tdriver.SpendableTokensIterator, error)
QuerySpendableTokens returns an iterator over the spendable tokens matching params.
func (*TokenStore) QueryTokenDetails ¶
func (db *TokenStore) QueryTokenDetails(ctx context.Context, params driver.QueryTokenDetailsParams) ([]driver.TokenDetails, error)
QueryTokenDetails returns details about owned tokens, regardless if they have been spent or not. Filters work cumulatively and may be left empty. If a token is owned by two enrollmentIDs and there is no filter on enrollmentID, the token will be returned twice (once for each owner).
func (*TokenStore) RedeemedBalance ¶ added in v0.15.1
func (db *TokenStore) RedeemedBalance(ctx context.Context, opts tdriver.IssuerBalanceQuery) (*big.Int, error)
RedeemedBalance returns the sum of the amounts of the tokens redeemed against an issuer known to this node, filtered by the passed options. The result is returned as a *big.Int to support arbitrary precision and prevent overflow.
func (*TokenStore) SetSupportedTokenFormats ¶
func (db *TokenStore) SetSupportedTokenFormats(formats []token.Format) error
func (*TokenStore) SpendableTokensIteratorBy ¶
func (db *TokenStore) SpendableTokensIteratorBy(ctx context.Context, walletID string, typ token.Type) (tdriver.SpendableTokensIterator, error)
SpendableTokensIteratorBy returns the minimum information about the tokens needed for the selector: every spendable token of the wallet and type that no other consumer currently holds a lock on, ascending by amount and unlimited. Callers that need only part of that set should use QuerySpendableTokens.
func (*TokenStore) StoreCertifications ¶
func (*TokenStore) StorePublicParams ¶
func (db *TokenStore) StorePublicParams(ctx context.Context, raw []byte) error
StorePublicParams stores the passed public parameters, keyed by their hash, if they are not stored already.
A read failure is propagated rather than swallowed: PublicParamsByHash recomputes the hash of what it finds, so it is the one place where a row whose raw and raw_hash columns disagree is detectable. Falling through to the INSERT would turn that into an opaque primary-key violation and leave the operator without the reason.
func (*TokenStore) StoreToken ¶
func (db *TokenStore) StoreToken(ctx context.Context, tr driver.TokenRecord, owners []string) (err error)
func (*TokenStore) TransactionExists ¶
func (*TokenStore) UnspentLedgerTokensIteratorBy ¶
func (db *TokenStore) UnspentLedgerTokensIteratorBy(ctx context.Context) (tdriver.LedgerTokensIterator, error)
UnspentLedgerTokensIteratorBy returns an iterator over all unspent ledger tokens
func (*TokenStore) UnspentTokensIterator ¶
func (db *TokenStore) UnspentTokensIterator(ctx context.Context) (tdriver.UnspentTokensIterator, error)
UnspentTokensIterator returns an iterator over all unspent tokens
func (*TokenStore) UnspentTokensIteratorBy ¶
func (db *TokenStore) UnspentTokensIteratorBy(ctx context.Context, walletID string, tokenType token.Type) (tdriver.UnspentTokensIterator, error)
func (*TokenStore) UnsupportedTokensIteratorBy ¶
func (db *TokenStore) UnsupportedTokensIteratorBy(ctx context.Context, walletID string, tokenType token.Type) (tdriver.UnsupportedTokensIterator, error)
UnsupportedTokensIteratorBy returns the minimum information for upgrade about the tokens that are not supported
func (*TokenStore) WhoDeletedTokens ¶
func (db *TokenStore) WhoDeletedTokens(ctx context.Context, inputs ...*token.ID) ([]string, []bool, error)
WhoDeletedTokens returns information about which transaction deleted the passed tokens. The bool array is an indicator used to tell if the token at a given position has been deleted or not
type TokenTransaction ¶
type TokenTransaction struct {
// contains filtered or unexported fields
}
func (*TokenTransaction) Commit ¶
func (t *TokenTransaction) Commit() error
func (*TokenTransaction) Rollback ¶
func (t *TokenTransaction) Rollback() error
func (*TokenTransaction) SetSpendable ¶
func (*TokenTransaction) SetSpendableBySupportedTokenFormats ¶
func (t *TokenTransaction) SetSpendableBySupportedTokenFormats(ctx context.Context, formats []token.Format) error
SetSpendableBySupportedTokenFormats reconciles the spendable flag of every token against formats: tokens whose ledger type is supported become spendable, all others become non-spendable.
Both updates are conditional on the flag actually having to change, so a reconciliation that agrees with the stored state writes no rows. Rewriting the whole table unconditionally - as this used to do, by clearing every flag before setting the supported ones - costs a full-table rewrite and the attendant MVCC bloat on every call, however little has changed.
func (*TokenTransaction) StoreToken ¶
func (t *TokenTransaction) StoreToken(ctx context.Context, tr driver.TokenRecord, owners []string) error
type TransactionStore ¶
type TransactionStore struct {
// contains filtered or unexported fields
}
func NewAuditTransactionStore ¶
func NewAuditTransactionStore(readDB *sql.DB, writeDB WriteDB, tables TableNames, ci common3.CondInterpreter, pi common3.PagInterpreter) (*TransactionStore, error)
func NewOwnerTransactionStore ¶
func NewOwnerTransactionStore(readDB *sql.DB, writeDB WriteDB, tables TableNames, ci common3.CondInterpreter, pi common3.PagInterpreter) (*TransactionStore, error)
func NewTransactionStoreWithNotifierAndRecovery ¶
func NewTransactionStoreWithNotifierAndRecovery( readDB *sql.DB, writeDB WriteDB, tables TableNames, ci common3.CondInterpreter, pi common3.PagInterpreter, notifier dbdriver.TransactionNotifier, recoveryLeaderFactory func(context.Context, WriteDB) (dbdriver.RecoveryLeadership, bool, error), ) (*TransactionStore, error)
func (*TransactionStore) AcquireLeadership ¶ added in v0.24.0
func (db *TransactionStore) AcquireLeadership(context.Context, int64) (dbdriver.RecoveryLeadership, bool, error)
AcquireLeadership returns a leadership handle for an arbitrary caller-chosen lockID, independent of the recovery lock bound at construction. It exists for callers that need their own leader election - such as the ledger drift checks sweep - so they never contend with the recovery sweep for the same lock. The default implementation grants leadership locally: backends that support real distributed locking (e.g. postgres) override it.
func (*TransactionStore) AcquireRecoveryLeadership ¶
func (db *TransactionStore) AcquireRecoveryLeadership(ctx context.Context) (dbdriver.RecoveryLeadership, bool, error)
AcquireRecoveryLeadership returns a leadership handle for recovery sweeping. When no leader factory is configured, leadership is granted locally.
func (*TransactionStore) AddTransactionEndorsementAck ¶
func (db *TransactionStore) AddTransactionEndorsementAck(ctx context.Context, txID string, endorser token.Identity, sigma []byte) (err error)
AddTransactionEndorsementAck records the signature of endorser over the payload it was sent for txID.
Verification: the signature cannot be verified here — the payload it was produced over is not persisted, so the caller is the last holder of it. This layer refuses a vacuous acknowledgement: one with no endorser identity, which would collide with every other such row when read back into a map keyed by endorser, or no signature, which would be indistinguishable from a genuine acknowledgement to every consumer.
func (*TransactionStore) ClaimPendingTransactions ¶
func (db *TransactionStore) ClaimPendingTransactions(ctx context.Context, params dbdriver.RecoveryClaimParams) ([]*dbdriver.RecoveryClaim, error)
ClaimPendingTransactions returns a claimed batch of Pending transactions. The default SQL implementation is permissive and does not persist recovery claims. tx_id and stored_at are projected directly from the requests table — the transactions table is no longer joined since it carries no information the recovery loop needs and adding it would re-introduce a fan-out by movement/output that the caller would have to dedupe by tx_id.
func (*TransactionStore) Close ¶
func (db *TransactionStore) Close() error
func (*TransactionStore) CountOpenFindings ¶ added in v0.24.0
CountOpenFindings returns how many open findings there currently are, per severity. Aggregated in SQL rather than fetched row by row and counted in Go: a node with a large-scale, genuinely open incident is exactly the case this must stay cheap for.
func (*TransactionStore) CreateSchema ¶
func (db *TransactionStore) CreateSchema() error
func (*TransactionStore) GetSchema ¶
func (db *TransactionStore) GetSchema() string
func (*TransactionStore) GetStatuses ¶ added in v0.15.1
func (db *TransactionStore) GetStatuses(ctx context.Context, txIDs []string) (map[string]dbdriver.TxStatus, error)
GetStatuses fetches the status for the given tx ids in a single SELECT. Missing tx ids are absent from the returned map — callers should treat a missing key identically to GetStatus returning Unknown. Empty input returns an empty map without querying.
func (*TransactionStore) GetTokenRequest ¶
func (*TransactionStore) GetTokenRequests ¶
func (db *TransactionStore) GetTokenRequests(ctx context.Context, txIDs []string) (map[string][]byte, error)
GetTokenRequests fetches the token requests for the given tx ids in a single SELECT. Missing tx ids are absent from the returned map — callers should treat a missing key identically to GetTokenRequest returning nil. Empty input returns an empty map without querying.
func (*TransactionStore) GetTransactionEndorsementAcks ¶
func (*TransactionStore) NewTransactionStoreTransaction ¶
func (db *TransactionStore) NewTransactionStoreTransaction() (dbdriver.TransactionStoreTransaction, error)
func (*TransactionStore) Notifier ¶
func (db *TransactionStore) Notifier() (dbdriver.TransactionNotifier, error)
func (*TransactionStore) PrefixedTableName ¶
func (s *TransactionStore) PrefixedTableName(name string) string
PrefixedTableName returns the formatted table name for the given logical name. It falls back to the unformatted name if the prefix or the table parameters cannot produce a valid identifier, rather than panicking: the store is already constructed at this point and a crash here would take the node down.
func (*TransactionStore) QueryFindings ¶ added in v0.24.0
func (db *TransactionStore) QueryFindings(ctx context.Context, params dbdriver.QueryFindingsParams) ([]*dbdriver.FindingRecord, error)
QueryFindings returns the stored findings matching params, worst first.
func (*TransactionStore) QueryMovements ¶
func (db *TransactionStore) QueryMovements(ctx context.Context, params dbdriver.QueryMovementsParams) (res []*dbdriver.MovementRecord, err error)
func (*TransactionStore) QueryTokenRequests ¶
func (db *TransactionStore) QueryTokenRequests(ctx context.Context, params dbdriver.QueryTokenRequestsParams) (dbdriver.TokenRequestIterator, error)
QueryTokenRequests returns an iterator over the token requests matching the passed params.
func (*TransactionStore) QueryTransactions ¶
func (db *TransactionStore) QueryTransactions(ctx context.Context, params dbdriver.QueryTransactionsParams, pagination driver3.Pagination) (*driver3.PageIterator[*dbdriver.TransactionRecord], error)
func (*TransactionStore) ReleaseRecoveryClaim ¶
ReleaseRecoveryClaim clears persisted recovery claim metadata and stores the recovery message. The default SQL implementation is a no-op.
func (*TransactionStore) ResolveFindingsNotSeenSince ¶ added in v0.24.0
func (db *TransactionStore) ResolveFindingsNotSeenSince(ctx context.Context, checkers []string, seenAt time.Time) (int64, error)
ResolveFindingsNotSeenSince closes the open findings of the passed checkers that the latest sweep did not observe.
func (*TransactionStore) UpsertFindings ¶ added in v0.24.0
func (db *TransactionStore) UpsertFindings(ctx context.Context, findings []dbdriver.FindingRecord, seenAt time.Time) error
UpsertFindings records the findings observed by one sweep. See the driver interface for the aging semantics.
type TransactionStoreTransaction ¶
type TransactionStoreTransaction struct {
// contains filtered or unexported fields
}
func (*TransactionStoreTransaction) AddMovement ¶
func (w *TransactionStoreTransaction) AddMovement(ctx context.Context, rs ...dbdriver.MovementRecord) error
func (*TransactionStoreTransaction) AddTokenRequest ¶
func (w *TransactionStoreTransaction) AddTokenRequest(ctx context.Context, txID string, tr []byte, applicationMetadata, publicMetadata map[string][]byte, ppHash driver2.PPHash) error
AddTokenRequest binds txID to the serialized token request tr.
Verification: this layer is a byte store and does not interpret tr — the wire-format and anchor checks live in the ttxdb and auditdb services, which know which of the two token request formats they hold. What is refused here is a row that no later check could act on: an empty transaction id, empty request bytes, or an empty public parameters hash. See docs/security/store_integrity_verification.md.
func (*TransactionStoreTransaction) AddTransaction ¶
func (w *TransactionStoreTransaction) AddTransaction(ctx context.Context, rs ...dbdriver.TransactionRecord) error
func (*TransactionStoreTransaction) Commit ¶
func (w *TransactionStoreTransaction) Commit() error
func (*TransactionStoreTransaction) Impl ¶
func (w *TransactionStoreTransaction) Impl() dbdriver.TransactionImpl
func (*TransactionStoreTransaction) Rollback ¶
func (w *TransactionStoreTransaction) Rollback()
type WalletStore ¶
type WalletStore struct {
// contains filtered or unexported fields
}
func NewWalletStore ¶
func NewWalletStore(readDB *sql.DB, writeDB WriteDB, tables TableNames, ci common3.CondInterpreter) (*WalletStore, error)
func (*WalletStore) Close ¶
func (db *WalletStore) Close() error
func (*WalletStore) CreateSchema ¶
func (db *WalletStore) CreateSchema() error
func (*WalletStore) GetSchema ¶
func (db *WalletStore) GetSchema() string
func (*WalletStore) GetWalletID ¶
func (*WalletStore) GetWalletIDs ¶
func (*WalletStore) IdentityExists ¶
func (db *WalletStore) IdentityExists(ctx context.Context, identity token.Identity, wID driver.WalletID, roleID int) (bool, error)
IdentityExists reports whether the identity-wallet-role binding has been stored. A lookup failure is returned as an error rather than as "not found": the two are not interchangeable, and collapsing them lets a transient connectivity problem read as a definitive negative.
type WriteDB ¶ added in v0.24.0
type WriteDB interface {
fscsql.WriteDB
// Conn returns a single dedicated connection, held until it is closed.
Conn(ctx context.Context) (*sql.Conn, error)
}
WriteDB is the write handle a store executes its statements through. It is FSC's write surface (Begin, BeginTx, Exec, ExecContext, Close) plus Conn, which Postgres needs to pin a session for the duration of an advisory lock.
*sql.DB satisfies it, so this is the type the stores take instead of the concrete pool: it lets a backend decorate the write path without every store knowing about it. SQLite does exactly that, wrapping the pool so a statement rejected with SQLITE_BUSY is retried instead of surfacing to the caller.
Only the statement methods are decorated. Begin and BeginTx hand out a raw *sql.Tx whose statements go straight to the driver, so a transactional write still sees SQLITE_BUSY - a retry there would have to replay the whole transaction, which is the caller's decision, not the pool's.
Source Files
¶
- bigint.go
- common.go
- config.go
- endorser.go
- endorser_test_util.go
- findings.go
- findings_test_util.go
- identity.go
- init.go
- keystore.go
- prepared_stmt_holder.go
- sqlerrors.go
- tablename.go
- tcondition.go
- tokenlock.go
- tokenlock_test_utils.go
- tokens.go
- tokens_balance_bench_util.go
- tokens_bench_test_util.go
- tokens_prepared_bench_util.go
- tokens_spendable_bench_util.go
- tokens_test_util.go
- transactions.go
- transactions_bench_util.go
- transactions_test_util.go
- wallet.go
- wallet_test_utils.go
- writedb.go