Overview
internal/service is the central coordinator of the LockBox sidecar. It orchestrates the crypto layer, LockScript engine, storage layer, and verification layer to implement the five core operations.
Operations
LockAsset
func (s *Service) LockAsset(ctx context.Context, req *LockAssetRequest) (*LockAssetResponse, error)Steps:
- Validate the
LockScriptby compiling it (fail-fast — rejects invalid scripts before writing any state). - Check tier capabilities to determine shard copy count, decoy ratio, and metadata decoy availability.
- Generate a fresh HKDF salt for this asset bundle.
- Encrypt asset data → real shards via
ShardEncryptor. - Generate decoy shards via
DecoyGeneratorat the tier's configured ratio. - Mix real and decoy shards via
ShardMixerto produce an indistinguishable bundle. - Apply metadata decoys if the tier supports them (Premium/Elite).
- Generate a Groth16 ownership proof binding the asset commitment to the owner address.
- Persist the
LockedAssetrecord withTotalShards,RealCount,Salt, andSaltVersion— but not a shard type map.
Returns: LockAssetResponse with the generated assetID, lockTime, and unlockTime.
UnlockAsset
func (s *Service) UnlockAsset(ctx context.Context, req *UnlockAssetRequest) (*UnlockAssetResponse, error)Steps:
- Load the
LockedAssetrecord from storage. - Verify the Groth16 ownership proof. Failure →
ErrUnauthorized. - If the asset has
MultiSigAddresses, verify that at leastMinSignaturesvalid Ed25519 signatures are present in the request. - Compile the stored
LockScriptand execute it in the sandboxed VM with the unlock context. - If the script returns
false→ErrUnlockConditionsNotMet. - Recover real shards via trial decryption (HKDF key at each position; AEAD authentication identifies real shards).
- Reconstruct and return plaintext data; update asset status to
unlocked.
EmergencyUnlock
func (s *Service) EmergencyUnlock(ctx context.Context, req *EmergencyUnlockRequest) (*EmergencyUnlockResponse, error)Available on Premium and Elite tiers only. Bypasses LockScript evaluation. Still requires:
- Valid Groth16 ownership proof.
- Rate-limit check per tier.
Intended for recovery scenarios where normal unlock conditions cannot be satisfied (e.g., lost co-signer keys, expired time-lock with no signature available).
GetAssetStatus
func (s *Service) GetAssetStatus(ctx context.Context, assetID string) (string, error)Returns the current AssetStatus string for the given asset ID. Errors with ErrAssetNotFound if no matching record exists.
ListAssets
func (s *Service) ListAssets(ctx context.Context, ownerAddress iotago.Address) ([]*LockedAsset, error)Returns all LockedAsset records associated with the given owner address, across all statuses.
Key Types
LockAssetRequest
| Field | Type | Notes |
|---|---|---|
OwnerAddress | iotago.Address | IOTA bech32 owner address |
OutputID | iotago.OutputID | UTXO output being locked |
Amount | uint64 | Token amount |
LockDuration | time.Duration | Duration of the lock |
LockScript | string | LockScript program |
MultiSigAddresses | []iotago.Address | Optional co-signers |
MinSignatures | int | m-of-n threshold |
LockedAsset
| Field | Type | Notes |
|---|---|---|
ID | string | 16-byte hex asset ID |
OwnerAddress | iotago.Address | Owner (bech32-serialised for storage) |
Status | AssetStatus | locked, unlocking, unlocked, expired, emergency |
TotalShards | int | Real + decoy shard count |
RealCount | int | Number of real shards |
Salt | []byte | HKDF salt for key derivation recovery |
SaltVersion | uint32 | Salt rotation tracking |
DataLength | int | Original plaintext length (for post-decryption trim) |
Error Types
| Error | Meaning |
|---|---|
ErrAssetNotFound | No asset with the given ID in storage |
ErrUnauthorized | Ownership proof or signature verification failed |
ErrUnlockConditionsNotMet | LockScript returned false |
ErrTierNotSupported | Requested operation not available at current tier |