Skip to main content

state — shystore

Package shystore implements the shystore-v1 ABCI state machine.

Import path: github.com/NickCarducci/Shyware-SDK/domain/state/shystore

Architecture

StoreState embeds submission.TwoListBase for the two-list invariant and adds shystore-specific domain state: bucket metadata and reveal event records.

List 1 (secrets): "bucketID:secretID" → sealed payload ciphertext. No identity.
List 2 (participants): "bucketID:identityHash" → owner identity. No payload.

secretID = H(secretNonce) is random and shares no derivation path with identityHash. No join key between the two lists is ever written to canonical state.

Initialization

state, err := shystore.NewStoreState(ctx, db, kmsKeyID, logger)
state.SetIdentityVerifier(v) // configure IDV provider

NewStoreStateWithOptions accepts StoreStateOptions for custom beacon and posture configuration.

Lifecycle

StepTx type constantFunction
Open a bucketstate.NewBucket(bucketID, allowedCategories)
Store a secretStoreTxTypeSecretStore = 1ExecuteTxexecuteSecretStore
Reveal a secretStoreTxTypeSecretReveal = 2ExecuteTxexecuteSecretReveal
Rotate a secretStoreTxTypeSecretRotate = 3ExecuteTxexecuteSecretRotate
Close a bucketStoreTxTypeBucketClose = 4ExecuteTxexecuteBucketClose
Adverse actionStoreTxTypeAdverseAction = 6ExecuteTxexecuteStoreAdverseAction

Transaction dispatch

func (s *StoreState) ValidateTx(t *tx.Tx) error // stateless checks
func (s *StoreState) ExecuteTx(t *tx.Tx) ([]abcitypes.Event, error) // stateful commit

ValidateTx is called during CheckTx (mempool). ExecuteTx is called during FinalizeBlock. Both route on t.Type.

Bucket management

err := state.NewBucket(bucketID, []string{"auth_seed_totp", "health_record"})
rec := state.GetBucket(bucketID) // → *BucketRecord{BucketID, AllowedCategories}

AllowedCategories narrows which SecretStoreData.Category values are accepted in this bucket, enforcing shyconfig store.secret_categories.

Two-party adverse action

StoreTxTypeAdverseAction carries a StoreAdverseActionData with ActionType of "suppress" or "restore". Both EligibilityAuth and ReconciliationAuth Ed25519 signatures must be present. The resulting StoreActionRecord is written to an append-only authority-action log and never deleted.

  • suppress — blocks SecretReveal for the identity in this bucket; List 1 and List 2 entries persist
  • restore — clears the suppression; optionally links to the prior suppress via ReferencedActionID

Query surface

func (s *StoreState) Query(path string, _ []byte, _ int64, _ bool) ([]byte, error)

The query surface is deliberately narrow — no path returns a list of all secrets or a per-participant aggregate. Enumeration protection ("structural") means no system-defined query yields a cross-participant mapping.

Count-match invariant

BucketClose calls TwoListBase.ClosePeriod, which enforces |L1| == |L2| before committing the KMS-signed ClosureRecord. A ClosureRecord is not a final count-match audit — rolling reconciliation (reveal, rotate) may continue until the operator explicitly closes.