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
| Step | Tx type constant | Function |
|---|---|---|
| Open a bucket | — | state.NewBucket(bucketID, allowedCategories) |
| Store a secret | StoreTxTypeSecretStore = 1 | ExecuteTx → executeSecretStore |
| Reveal a secret | StoreTxTypeSecretReveal = 2 | ExecuteTx → executeSecretReveal |
| Rotate a secret | StoreTxTypeSecretRotate = 3 | ExecuteTx → executeSecretRotate |
| Close a bucket | StoreTxTypeBucketClose = 4 | ExecuteTx → executeBucketClose |
| Adverse action | StoreTxTypeAdverseAction = 6 | ExecuteTx → executeStoreAdverseAction |
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
SecretRevealfor 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.