Documentation
¶
Overview ¶
This file exists solely to anchor the `go generate` directive that produces pkg/core/cbor_gen.go. The generator is the main package at pkg/core/gen/; it reads the type list there and emits tuple-mode CBOR codecs per ADR-009 §2.
Re-run whenever any target type's fields change:
go generate ./pkg/core/...
Index ¶
- Constants
- Variables
- func BitmaskBitLen(bm [32]byte) int
- func BitmaskIsZero(bm [32]byte) bool
- func BitmaskOnesCount(bm [32]byte) int
- func BitmaskToBigInt(bm [32]byte) *big.Int
- func CanonicalSort(anchor [32]byte, entries []BlockEntry)
- func ComputeAccountID(uri string) [32]byte
- func ComputeEntriesDigest(entries []BlockEntry) [32]byte
- func ComputeEntryHash(e BlockEntry) [32]byte
- func DecodePayload(entry BlockEntry) (interface{}, error)
- func EncodeSessionChallengeOp(op *SessionChallengeOp) []byte
- func EncodeSessionCloseOp(op *SessionCloseOp) []byte
- func First8Hex(id NodeID) string
- func GetBitmaskBit(bm [32]byte, i int) bool
- func IsSwapTxID(txID string) bool
- func IsURI(s string) bool
- func IsValidTreasury(name string) bool
- func MakeSwapTxID(baseTxID string, assetOut AssetID, minAmountOut *big.Int) string
- func NodeURI(id NodeID) string
- func ParseURI(uri string) (network, kind, path string, err error)
- func PoolURI(base string) string
- func ServiceURI(kind, path string) string
- func SetBitmaskBit(bm *[32]byte, i int)
- func TreasuryURI(name string) string
- func URIKind(uriOrAddress string) string
- func URIToAddress(uri string) (common.Address, error)
- func UserURI(address string) string
- func ValidateAssetURI(uri AssetURI) error
- func ValidateEntryOrder(anchor [32]byte, entries []BlockEntry) error
- func ValidateURI(uri string) error
- func WithdrawalDeadline(sealedAt int64) int64
- type AccountSnapshot
- type AccountType
- type AssetID
- type AssetTransfer
- type AssetURI
- type AssetURIParts
- type Attestation
- type Block
- type BlockEntry
- func (e *BlockEntry) AccountID() [32]byte
- func (e *BlockEntry) ConsumesNonce() bool
- func (e *BlockEntry) DecodeBurnReceipt() (*BurnReceipt, error)
- func (e *BlockEntry) DecodeMintReceipt() (*MintReceipt, error)
- func (e *BlockEntry) DecodeOp() (interface{}, error)
- func (e *BlockEntry) DecodeRepegOp() (*RepegOp, error)
- func (e *BlockEntry) DecodeSwapOp() (*SwapOp, error)
- func (e *BlockEntry) DecodeTransferOp() (*TransferOp, error)
- func (e *BlockEntry) DecodeWithdrawalOp() (*WithdrawalOp, error)
- func (e *BlockEntry) Hash() [32]byte
- func (e *BlockEntry) IsSwap() bool
- func (e *BlockEntry) IsTransfer() bool
- func (e *BlockEntry) IsWithdrawal() bool
- func (t *BlockEntry) MarshalCBOR(w io.Writer) error
- func (t *BlockEntry) UnmarshalCBOR(r io.Reader) (err error)
- type BlockEntryRef
- type BlockHeader
- type BlockState
- type BurnReceipt
- type DepositDestination
- type DepositStatus
- type EntryType
- type FaucetReader
- type FaucetWriter
- type FinalizedWithdrawal
- type FinalizedWithdrawalHeader
- type FraudEvidenceSubmitter
- type MintReceipt
- type NodeID
- type RegistryReader
- type RegistryWriter
- type RepegOp
- type SessionChallengeOp
- type SessionCloseOp
- type SignerRotationFinalizer
- type Slot
- type SlotState
- type SwapOp
- type TokenReader
- type TransferOp
- type VaultDepositor
- type VaultWithdrawalFinalizer
- type WithdrawalFraudEvidence
- type WithdrawalOp
- type WithdrawalOutcome
Constants ¶
const ( // MaxBlockAge bounds how stale a finalized block may be and still be // signed/submitted (freshness cutoff on the signing path). It also anchors // the withdrawal validity window: a block older than MaxBlockAge is never // re-signed, so no fresh authorization can be minted past that point. MaxBlockAge = 7 * 24 * time.Hour // ExecutionMargin is the slack added on top of MaxBlockAge to cover the time // a fresh authorization needs to be signed, submitted, and confirmed on L1. // It bounds the per-attempt liveness budget on XRPL (see LedgerBudget). ExecutionMargin = 2 * time.Hour // WithdrawalValidityWindow is the total lifetime of a withdrawal // authorization measured from the source block's SealedAt. Any signed // digest is dead once SealedAt + WithdrawalValidityWindow has passed. WithdrawalValidityWindow = MaxBlockAge + ExecutionMargin )
Withdrawal-authorization time bounds.
Every withdrawal digest signed by the custody quorum embeds a `deadline` (unix seconds) past which the authorization is void — on EVM/Solana it is a consensus-enforced execution check, on XRPL it caps `LastLedgerSequence`, and clearnet uses it to decide when a reverted/unbroadcast withdrawal may be safely re-credited. Because the deadline is a *digest input*, these values are compile-time constants: they cannot ride the config registry (ADR-017) without opening a digest-divergence window across a rolling restart. Changing them is therefore a coordinated binary upgrade, not a runtime config change.
The values are provisional pre-mainnet. They are defined ONCE here in the SDK (clearnet imports the SDK) so custody and clearnet cannot drift.
const ( URIScheme = "yellow" DefaultNetwork = "ynet" )
URI scheme and default network for Yellow Network resources (ADR-007 §4).
const BLSPubKeyG2Len = 128
BLSPubKeyG2Len is the serialized length of a BN254 G2 pubkey (4×32 bytes).
const BloomByteLength = 256
Event bloom filter for per-block log filtering (data_layer.md §5.2). 2048-bit (256-byte) bloom with 3 hash functions, matching Ethereum's log bloom.
Only the length constant lives in the SDK — Block.EventBloom is [BloomByteLength]byte. The add/test helpers (BloomAdd, BloomTest, BlockEventBloom) stay in clearnet; they operate on clearnet-internal Events.
const DefaultIssuer = "custody"
Variables ¶
var ( ErrNonCanonicalOrder = errors.New("block: entries not in canonical order") ErrNonConsecutiveNonce = errors.New("block: same-account entries must have consecutive nonces") ErrEntriesDigestMismatch = errors.New("block: entries digest does not match header") )
Block validation errors (extracted from clearnet block_params.go — used by Block entry/digest verification above).
var ValidTreasuries = []string{"emission"}
ValidTreasuries is the compile-time allowlist of protocol-treasury names (ADR-010 §1). Treasuries are consensus-critical state-machine inputs, not operator configuration: declaring them in the network manifest would diverge SMT roots across operators the first time distribution fires. The set is therefore hardcoded here. Adding a new treasury requires a follow-up ADR, an entry in this list, a registered minimum balance (ADR-010 §6), and an authorized ledger helper for its outbound flow (ADR-010 §3).
Functions ¶
func BitmaskBitLen ¶
BitmaskBitLen returns the position of the highest set bit + 1 (0 if empty).
func BitmaskIsZero ¶
BitmaskIsZero returns true if no bits are set in the bitmask.
func BitmaskOnesCount ¶
BitmaskOnesCount returns the number of set bits in the bitmask.
func BitmaskToBigInt ¶
BitmaskToBigInt returns a big.Int representing the bitmask. The resulting big.Int uses big-endian byte order, so the little-endian bitmask bytes are reversed.
func CanonicalSort ¶
func CanonicalSort(anchor [32]byte, entries []BlockEntry)
CanonicalSort sorts entries in deterministic order (ADR-005 §2.3, data-structures.md §5.3.3). Primary: AccountID (= keccak256(URI)) by XOR distance from Anchor, ascending. Secondary: Nonce ascending within the same account.
func ComputeAccountID ¶
ComputeAccountID derives the canonical 32-byte AccountID from an account URI or raw address (ADR-007 §4). The input is normalized to a canonical lowercase before hashing, so a caller that accidentally hands in a non-canonical form still produces the canonical AccountID. That covers two footguns at once:
- Non-URI heterogeneous protocol fields such as BlockEntry.Account (which may carry either a canonical URI for service/pool accounts or a raw user address for user-owned accounts). Non-URI input is auto-wrapped in UserURI() first.
- Mixed-case URI input (e.g. a URI produced by an external tool that didn't enforce the rule). Post-lowercasing eliminates the divergence before the hash is taken.
func ComputeEntriesDigest ¶
func ComputeEntriesDigest(entries []BlockEntry) [32]byte
ComputeEntriesDigest computes the flat hash over all entry hashes (ADR-005 §2.2).
EntriesDigest = keccak256(EntryHash_1 || EntryHash_2 || ... || EntryHash_n)
func ComputeEntryHash ¶
func ComputeEntryHash(e BlockEntry) [32]byte
ComputeEntryHash computes the hash of a single entry (ADR-005 §2.2).
EntryHash = keccak256(canonical-CBOR(BlockEntry))
The preimage is the cbor-gen tuple encoding of the entry struct (ADR-009 §4, CBOR migration plan §7 Wave 2b). `EntriesDigest` continues to be the flat keccak-concat of these per-entry hashes — only the per-entry preimage layout changed in Wave 2b.
func DecodePayload ¶
func DecodePayload(entry BlockEntry) (interface{}, error)
DecodePayload decodes a BlockEntry's binary payload into the typed operation struct based on entry.Type. Returns one of:
*TransferOp, *SwapOp, *WithdrawalOp, *RepegOp, *SessionCloseOp, *SessionChallengeOp
Returns an error for unknown entry types or malformed payloads.
func EncodeSessionChallengeOp ¶
func EncodeSessionChallengeOp(op *SessionChallengeOp) []byte
EncodeSessionChallengeOp serializes a SessionChallengeOp.
func EncodeSessionCloseOp ¶
func EncodeSessionCloseOp(op *SessionCloseOp) []byte
EncodeSessionCloseOp serializes a SessionCloseOp.
func First8Hex ¶
First8Hex returns the first 8 hex characters of id. Used to synthesize human-readable Slot labels when a peer did not supply one (docs/plans/logical_node.md §5.4).
func GetBitmaskBit ¶
GetBitmaskBit returns true if bit i is set in the bitmask.
func IsSwapTxID ¶
IsSwapTxID returns true if the TxID represents a swap handoff TransferOp.
func IsValidTreasury ¶
IsValidTreasury reports whether a treasury name is in the compile-time allowlist. A URI that parses as kind=`treasury` but whose name is absent from this list MUST be rejected by every account-materialization path (ADR-010 §1).
func MakeSwapTxID ¶
MakeSwapTxID creates the TransferOp TxID used for the user->pool swap handoff. TransferOp has no AssetOut field, so the pool cluster recovers the user-authorized output asset and slippage floor from this stable prefix after validating the sealed user block.
func NodeURI ¶
NodeURI returns the canonical URI for a validator node account.
yellow://ynet/node/<64-char lowercase hex nodeid>
func ParseURI ¶
ParseURI splits a canonical URI into its components.
"yellow://ynet/pool/eth" → ("ynet", "pool", "eth", nil)
func PoolURI ¶
PoolURI returns the canonical URI for a liquidity pool (ADR-007 §4). All pools are YELLOW-quoted (ADR-006), so the URI contains only the lowercase base asset. Example: yellow://ynet/pool/eth
func ServiceURI ¶
ServiceURI returns the canonical URI for a named service.
yellow://ynet/<kind>/<path>
func SetBitmaskBit ¶
SetBitmaskBit sets bit i (0-indexed, little-endian bit order) in a [32]byte bitmask. Bit i is stored at byte i/8, bit position i%8 within that byte.
func TreasuryURI ¶
TreasuryURI returns the canonical URI for a protocol treasury (ADR-010 §1). The name is drawn from the compile-time ValidTreasuries allowlist. Initial set: `emission`. Example: yellow://ynet/treasury/emission.
func URIKind ¶
URIKind extracts the kind segment from a URI or address. For non-URI inputs (raw hex addresses), returns "user". Returns "" if parsing fails on an actual URI.
func URIToAddress ¶
URIToAddress maps a canonical yellow:// URI into the 20-byte address slot used by EIP-712 schemas that cannot carry a string recipient. The mapping is the first 20 bytes of keccak256(uri), paralleling the pool-anchor preimage rule while fitting the Transfer(address to, ...) type.
func UserURI ¶
UserURI returns the canonical URI for a user account.
yellow://ynet/user/0xd8da6bf26964af9d7eed9e03e53415d37aa96045
func ValidateAssetURI ¶ added in v0.5.0
ValidateAssetURI checks only core-level asset URI shape. It does not inspect issuer-specific asset id structure.
func ValidateEntryOrder ¶
func ValidateEntryOrder(anchor [32]byte, entries []BlockEntry) error
ValidateEntryOrder checks that entries are in canonical order (ADR-005 §2.3). Returns nil if ordering is valid.
func ValidateURI ¶
ValidateURI enforces ADR-007 §4 URI conventions:
- The URI uses the yellow:// scheme.
- Parsing yields a non-empty network and kind.
- The network matches DefaultNetwork ("ynet") — multi-network support is a future extension; every URI in-flight today lives on ynet.
- The kind is one of the enumerated ADR-007 §3 values.
- Every URI component is lowercase (ADR-007 §4: "All URI components are lowercase").
Returns a descriptive error on the first violation; nil on success. Callers at system boundaries (gateway request parsing, store loads, manifest reads) should call ValidateURI on any URI they receive from an external source before trusting it. Internal constructors (UserURI, PoolURI, etc.) produce canonical URIs by construction and do not need re-validation at their call sites.
func WithdrawalDeadline ¶ added in v0.4.0
WithdrawalDeadline returns the unix-second time bound for a withdrawal whose source block sealed at sealedAt (also unix seconds). This is the single value threaded into every chain's withdrawal digest and enforced on-chain.
Types ¶
type AccountSnapshot ¶
type AccountSnapshot struct {
AccountID [32]byte `json:"AccountID"` // keccak256(Address)
PrevBlockRef [32]byte `json:"PrevBlockRef"` // Account.LastBlockHash before this block (back-pointer)
PostNonce uint64 `json:"PostNonce"` // Account.Nonce after all entries for this account
}
AccountSnapshot preserves per-account chain continuity within a Block (ADR-005 §2.4).
func (*AccountSnapshot) MarshalCBOR ¶
func (t *AccountSnapshot) MarshalCBOR(w io.Writer) error
func (*AccountSnapshot) UnmarshalCBOR ¶
func (t *AccountSnapshot) UnmarshalCBOR(r io.Reader) (err error)
type AccountType ¶
type AccountType uint8
AccountType identifies the entity kind (ADR-007 §3).
const ( AccountTypeUnknown AccountType = 0x00 // Sentinel: URI kind not recognised (D-003, 2026-04-21). AccountTypeUser AccountType = 0x01 // Externally owned AccountTypeNative AccountType = 0x02 // On-cluster deterministic handlers (pools, vaults) AccountTypeVirtual AccountType = 0x03 // Off-chain operator, NFT-identified AccountTypeContract AccountType = 0x04 // User-deployed bytecode (future) )
func KindToAccountType ¶
func KindToAccountType(kind string) (AccountType, error)
KindToAccountType maps a URI kind segment to its AccountType (ADR-007 §3). Returns an error on unknown kinds — this was previously a silent User-default which masked malformed URIs (D-003 resolution, 2026-04-21).
The returned AccountType on error is AccountTypeUnknown (0), so code that ignores the error still surfaces an obviously-bogus type rather than a plausible User account.
func (AccountType) String ¶
func (t AccountType) String() string
String returns the human-readable name of the AccountType.
type AssetID ¶
type AssetID string
AssetID is a unique identifier for a token (§2). Symbols (e.g. "USDT", "ETH") are mapped to L1 (ChainID, TokenAddress) pairs via the AssetResolver interface at runtime. TODO: Consider removing AssetID and using AssetURI for protocol asset identity once the issuer asset URI migration reaches transfers/swaps.
type AssetTransfer ¶
AssetTransfer represents a single asset-amount pair in a multi-asset operation (§5.3.5).
func CanonicalAssetTransfers ¶
func CanonicalAssetTransfers(in []AssetTransfer) ([]AssetTransfer, error)
CanonicalAssetTransfers validates, copies, sorts, and de-duplicates a TransferOp asset list.
func (*AssetTransfer) MarshalCBOR ¶
func (t *AssetTransfer) MarshalCBOR(w io.Writer) error
func (*AssetTransfer) UnmarshalCBOR ¶
func (t *AssetTransfer) UnmarshalCBOR(r io.Reader) (err error)
type AssetURI ¶ added in v0.5.0
type AssetURI string
AssetURI identifies an issuer-defined asset in protocol payloads.
Core treats the asset id as opaque issuer-owned data. Chain-specific structure such as family, chain id, and token address belongs outside core.
func NewAssetURI ¶ added in v0.5.0
NewAssetURI builds a canonical asset URI:
yellow://ynet/asset/<issuer>/<asset-id>
If issuer is empty, DefaultIssuer is used. The issuer is lowercased; the issuer-owned asset id is preserved as supplied.
type AssetURIParts ¶ added in v0.5.0
func ParseAssetURI ¶ added in v0.5.0
func ParseAssetURI(uri AssetURI) (AssetURIParts, error)
ParseAssetURI splits an asset URI into network, issuer, and issuer-owned asset id components.
type Attestation ¶
type Attestation struct {
ThresholdSig []byte `json:"ThresholdSig"` // Aggregated BLS signature (G1 point)
Bitmask [32]byte `json:"Bitmask"` // Bitmask indicating which validators signed (up to 256 bits, SS5.3).
Validators [][]byte `json:"Validators"` // BLS public keys (G2) of signing validators — 128 bytes each once WS-A.2 lands.
}
Attestation holds the BLS threshold signature proving cluster consensus (ADR-005 §5.3). Embedded in every Block. Verified off-chain by clearing layer and custody layer.
§7 coordination: Validators is []BLSPubKey (variable-length byte slices) so entries can hold full 128-byte BN254 G2 public keys (WS-A.2). Legacy NodeID-only entries remain parseable as 32-byte slices; WS-A.2 populates real G2 keys from core.Slot.BLSPubKey.
func (*Attestation) MarshalCBOR ¶
func (t *Attestation) MarshalCBOR(w io.Writer) error
func (*Attestation) UnmarshalCBOR ¶
func (t *Attestation) UnmarshalCBOR(r io.Reader) (err error)
type Block ¶
type Block struct {
// --- Header (covered by BLS signature) ---
Anchor [32]byte `json:"Anchor"` // AccountID of the first transaction (DHT center)
SealedAt int64 `json:"SealedAt"` // Unix timestamp when block was sealed
Entries []BlockEntry `json:"Entries"` // Ordered operations (canonical sort, §2.3)
StateRoot [32]byte `json:"StateRoot"` // Flat SMT root after applying ALL entries in order
EntriesDigest [32]byte `json:"EntriesDigest"` // Flat hash binding entries to BLS signature (§2.2)
K uint64 `json:"K"` // DQE-computed cluster size for aggregate VaR (§5.2). Semantic bound of 256; wire type widened to uint64 for cbor-gen compatibility.
Attestation Attestation `json:"Attestation"` // Single BLS threshold signature for the block (un-embedded so cbor-gen tuple emitter produces stable output)
Accounts []AccountSnapshot `json:"Accounts"` // Per-account chain continuity metadata
EventBloom [BloomByteLength]byte `json:"event_bloom,omitempty"` // Per-block event bloom filter (data_layer.md §5.2)
AggregateVaR *big.Int `json:"aggregate_var,omitempty"` // Advisory VaR projection; validators recompute (§6.6)
SealReason string `json:"seal_reason,omitempty"` // "idle" | "window" | "entries" | "value"
}
Block is an ordered batch of operations from accounts within a DHT neighborhood, attested by a single BLS threshold signature (ADR-005 §2).
func (*Block) Hash ¶
Hash returns keccak256(SigningMessage) — the block identifier (ADR-005 §2.1). After sealing, Account.LastBlockHash = Hash() for each account in Accounts.
Formula unchanged under Wave 2b; only the preimage layout moved from the 106-byte hand-rolled concat to canonical CBOR of `BlockHeader`.
func (*Block) SigningMessage ¶
SigningMessage returns the canonical CBOR preimage covered by the BLS signature (ADR-009 §4, CBOR migration plan §7 Wave 2b).
Preimage shape: canonical CBOR of `BlockHeader{Anchor, SealedAt, StateRoot, EntriesDigest, K, Accounts}`. `Accounts` (per-account `PrevBlockRef` + `PostNonce`) is newly bound under the signature (Q6).
Byte output is frozen by goldens under `testdata/goldens/preimages/` (see `scripts/ci/check-preimage-goldens.sh`); any change to the field set or encoding rules trips the CI guard and requires a version-byte bump per ADR-009 §5.
func (*Block) ValidateEntriesDigest ¶
ValidateEntriesDigest recomputes EntriesDigest and checks it matches the block header.
type BlockEntry ¶
type BlockEntry struct {
Type EntryType `json:"Type"` // Transfer | Swap | Withdrawal | Mint | Burn | Repeg (LP ops use Transfer per §8.3)
Account string `json:"Account"` // Account whose state is mutated
Nonce uint64 `json:"Nonce"` // Account nonce consumed by this entry
Payload []byte `json:"Payload"` // Canonical CBOR of the typed op (§5.3)
}
BlockEntry is an individual operation within a Block (ADR-005 §2).
func (*BlockEntry) AccountID ¶
func (e *BlockEntry) AccountID() [32]byte
AccountID returns keccak256(e.Account).
func (*BlockEntry) ConsumesNonce ¶
func (e *BlockEntry) ConsumesNonce() bool
ConsumesNonce reports whether applying this entry advances the account nonce. Receipt-driven entries (OpMint deposit credits, OpBurn withdrawal-execution burns) leave the account nonce unchanged — the authoritative trigger is the custody-signed receipt, not a user-signed transaction. Used by block validation to compute the correct pre-block nonce from snap.PostNonce when verifying entry order.
func (*BlockEntry) DecodeBurnReceipt ¶
func (e *BlockEntry) DecodeBurnReceipt() (*BurnReceipt, error)
DecodeBurnReceipt decodes the payload as a BurnReceipt (the on-block payload for OpBurn entries — the receipt IS the operation).
func (*BlockEntry) DecodeMintReceipt ¶
func (e *BlockEntry) DecodeMintReceipt() (*MintReceipt, error)
DecodeMintReceipt decodes the payload as a MintReceipt (the on-block payload for OpMint entries — the receipt IS the operation).
func (*BlockEntry) DecodeOp ¶
func (e *BlockEntry) DecodeOp() (interface{}, error)
DecodeOp decodes the entry payload into its typed operation struct. Returns one of *TransferOp, *SwapOp, *WithdrawalOp, *RepegOp, *SessionCloseOp, or *SessionChallengeOp.
func (*BlockEntry) DecodeRepegOp ¶
func (e *BlockEntry) DecodeRepegOp() (*RepegOp, error)
DecodeRepegOp decodes the payload as a RepegOp. Returns an error if the entry type is not OpRepeg or the payload is malformed.
func (*BlockEntry) DecodeSwapOp ¶
func (e *BlockEntry) DecodeSwapOp() (*SwapOp, error)
DecodeSwapOp decodes the payload as a SwapOp. Returns an error if the entry type is not OpSwap or the payload is malformed.
func (*BlockEntry) DecodeTransferOp ¶
func (e *BlockEntry) DecodeTransferOp() (*TransferOp, error)
DecodeTransferOp decodes the payload as a TransferOp. Returns an error if the entry type is not OpTransfer or the payload is malformed.
func (*BlockEntry) DecodeWithdrawalOp ¶
func (e *BlockEntry) DecodeWithdrawalOp() (*WithdrawalOp, error)
DecodeWithdrawalOp decodes the payload as a WithdrawalOp. Returns an error if the entry type is not OpWithdrawal or the payload is malformed.
func (*BlockEntry) Hash ¶
func (e *BlockEntry) Hash() [32]byte
Hash returns keccak256(Type || Account || Nonce || Payload) for this entry.
func (*BlockEntry) IsSwap ¶
func (e *BlockEntry) IsSwap() bool
IsSwap returns true if the entry type is OpSwap.
func (*BlockEntry) IsTransfer ¶
func (e *BlockEntry) IsTransfer() bool
IsTransfer returns true if the entry type is OpTransfer.
func (*BlockEntry) IsWithdrawal ¶
func (e *BlockEntry) IsWithdrawal() bool
IsWithdrawal returns true if the entry type is OpWithdrawal.
func (*BlockEntry) MarshalCBOR ¶
func (t *BlockEntry) MarshalCBOR(w io.Writer) error
func (*BlockEntry) UnmarshalCBOR ¶
func (t *BlockEntry) UnmarshalCBOR(r io.Reader) (err error)
type BlockEntryRef ¶
type BlockEntryRef struct {
BlockHash [32]byte // keccak256(SigningMessage) of the sealed block
EntryIndex uint64 // Position of the entry in Block.Entries (widened from uint16 for cbor-gen compat, Wave 2 pre)
}
BlockEntryRef identifies a specific entry within a sealed block. This is the composite key used throughout the escrow lifecycle: recording, challenge, finalization, and BurnReceipt handling.
func RefFromBlock ¶
func RefFromBlock(block *Block, entryIndex uint64) BlockEntryRef
RefFromBlock creates a BlockEntryRef from a sealed block and entry index.
func (BlockEntryRef) Key ¶
func (r BlockEntryRef) Key() string
Key returns a full-hex deduplication key for map lookups.
func (*BlockEntryRef) MarshalCBOR ¶
func (t *BlockEntryRef) MarshalCBOR(w io.Writer) error
func (BlockEntryRef) String ¶
func (r BlockEntryRef) String() string
String returns a compact hex:index representation for logging.
func (*BlockEntryRef) UnmarshalCBOR ¶
func (t *BlockEntryRef) UnmarshalCBOR(r io.Reader) (err error)
type BlockHeader ¶
type BlockHeader struct {
Anchor [32]byte // AccountID of the first transaction (DHT center)
SealedAt int64 // Unix timestamp when block was sealed
StateRoot [32]byte // Flat SMT root after applying ALL entries in order
EntriesDigest [32]byte // Flat hash binding entries to BLS signature (§2.2)
K uint64 // DQE-computed cluster size; semantic bound 256
Accounts []AccountSnapshot // Per-account chain continuity metadata (Q6)
}
BlockHeader is the signing-preimage projection of a sealed Block (docs/specs/protocol/data-structures.md §5.3). It pulls out the fields the BLS signature actually commits to — the six-tuple that becomes the canonical CBOR preimage now that Wave 2b has rewritten `Block.SigningMessage()` around the cbor-gen codec of this struct.
`Accounts` is newly included in the preimage (Q6 in the CBOR migration plan / ADR-009 §4) so per-account chain continuity (PrevBlockRef / PostNonce) commits under the BLS signature — closing the latent forgery surface where the legacy 106-byte preimage did not bind chain-continuity metadata. `K` is `uint64` on the Go side for cbor-gen compatibility (W2-pre widen); the semantic bound is still 256 (DQE cap).
Field order on this struct IS the wire encoding (cbor-gen tuple mode, ADR-009 §2). Append-only evolution: any insert/reorder/rename bumps the global schema-family version byte (ADR-009 §5).
func (*BlockHeader) MarshalCBOR ¶
func (t *BlockHeader) MarshalCBOR(w io.Writer) error
func (*BlockHeader) UnmarshalCBOR ¶
func (t *BlockHeader) UnmarshalCBOR(r io.Reader) (err error)
type BlockState ¶
type BlockState uint8
BlockState represents the lifecycle phase of a pending block (ADR-005 §4.4).
const ( BlockOpen BlockState = iota // Proposer received first tx, block initialized BlockFilling // Accepting additional transactions BlockSealed // Sealed, BLS signing complete )
type BurnReceipt ¶
type BurnReceipt struct {
WithdrawalID [32]byte // keccak256(accountId, blockHash, entryIndex, assetURI, amount, recipient, nonce)
BlockEntryRef // Block hash + entry index of the escrow entry
TxID string // Chain-native transaction/reference id (empty unless applicable)
Signatures [][]byte // k-of-n provider ECDSA signatures over the receipt digest
Status WithdrawalOutcome // Terminal outcome: Executed, Expired, or failed with reason
}
BurnReceipt is returned by the custody layer after L1 execution of a withdrawal (ADR-005 §9.1, receipt-model amendment 2026-05-12). Provider ECDSA signatures (k-of-n against the configured custody signer directory — manifest custody.signers/threshold; future Registry-backed source) confirm the withdrawal was executed on-chain; the cluster validates the receipt and applies the second leg of the burn (DR 2010 / CR 1020).
func (*BurnReceipt) EncodePayload ¶
func (v *BurnReceipt) EncodePayload() []byte
EncodePayload serializes a BurnReceipt into a BlockEntry payload.
func (*BurnReceipt) MarshalCBOR ¶
func (t *BurnReceipt) MarshalCBOR(w io.Writer) error
func (*BurnReceipt) UnmarshalCBOR ¶
func (t *BurnReceipt) UnmarshalCBOR(r io.Reader) (err error)
type DepositDestination ¶ added in v0.2.0
DepositDestination identifies who a deposit credits. Account is the L1 / clearnet account; Ref is the opaque ADR-015 sub-account reference, carried alongside the account as side-data (a zero Ref means no sub-account). The reference is never interpreted on-chain — it is emitted so deposits are filterable per (Account, Ref); an observer folds it into the account URI. Chains without a reference channel (BTC) reject a non-zero Ref.
type DepositStatus ¶
type DepositStatus int
DepositStatus is the tri-state result of VerifyDeposit, distinguishing a deposit that settled, one that is still in flight, and one that never landed (or was dropped/reorged out).
const ( // DepositAbsent: no matching deposit transaction is on chain or in the // mempool (never broadcast, dropped, reorged out, or reverted/failed). DepositAbsent DepositStatus = iota // DepositPending: the deposit transaction is observed but not yet final — // in the mempool, or with fewer than the requested confirmations. DepositPending // DepositConfirmed: the deposit transaction is final to the requested depth. DepositConfirmed )
func (DepositStatus) String ¶
func (s DepositStatus) String() string
type EntryType ¶
type EntryType uint8
EntryType identifies the kind of state operation in a BlockEntry (ADR-005 §5.3.5).
const ( OpTransfer EntryType = iota + 1 // SS5.3.5 — Transfer: debit sender, credit receiver (also LP operations per SS8.3) OpSwap // SS8.1 — Swap: AMM execution result OpWithdrawal // SS7.3.1 — Withdrawal: fund lock for L1 OpBurn // ADR-005 §9.1 receipt-model — Withdrawal execution burn: DR 1020 / CR 2010 driven by a custody-signed BurnReceipt. Payload = canonical CBOR of the BurnReceipt. OpMint // ADR-005 §9.1 receipt-model — Deposit credit: DR 1010 / CR 2010 driven by a custody-signed MintReceipt. Payload = canonical CBOR of the MintReceipt. OpRepeg // SS8.1.2 — PriceScale adjustment OpSessionClose // service_sessions.md §4 — Cooperative or unilateral session close OpSessionChallenge // service_sessions.md §4 — Session dispute challenge )
type FaucetReader ¶
type FaucetReader interface {
DripAmount(ctx context.Context) (*big.Int, error)
Cooldown(ctx context.Context) (*big.Int, error)
Owner(ctx context.Context) (common.Address, error)
LastDrip(ctx context.Context, addr common.Address) (*big.Int, error)
}
FaucetReader provides read access to the testnet faucet's parameters.
type FaucetWriter ¶
type FaucetWriter interface {
Drip(ctx context.Context) error
DripTo(ctx context.Context, recipient common.Address) error
}
FaucetWriter provides write access to the testnet faucet drip.
type FinalizedWithdrawal ¶
type FinalizedWithdrawal struct {
WithdrawalID [32]byte `json:"WithdrawalID"`
BlockHash [32]byte `json:"BlockHash"`
EntryIndex uint64 `json:"EntryIndex"`
FinalizedAt int64 `json:"FinalizedAt"`
Attestation Attestation `json:"Attestation"`
Block Block `json:"Block"`
}
FinalizedWithdrawal is the positive clearing-layer finality object consumed by custody after the challenge window expires. Attestation signs SigningMessage(); Block is carried so custody providers can bind the ID to the exact withdrawal payload without maintaining clearing state.
func (*FinalizedWithdrawal) Header ¶
func (fw *FinalizedWithdrawal) Header() FinalizedWithdrawalHeader
func (*FinalizedWithdrawal) MarshalCBOR ¶
func (t *FinalizedWithdrawal) MarshalCBOR(w io.Writer) error
func (*FinalizedWithdrawal) SigningMessage ¶
func (fw *FinalizedWithdrawal) SigningMessage() []byte
SigningMessage returns the canonical CBOR preimage covered by the BLS finality signature (ADR-009 §4). It is not the same preimage as Block and excludes Attestation so the signature cannot be self-referential. Returns nil for a nil receiver so callers can distinguish "no message" from an all-zero preimage.
Preimage shape: canonical CBOR of FinalizedWithdrawalHeader{WithdrawalID, BlockHash, EntryIndex, FinalizedAt}. Frozen by the FinalizedWithdrawalHeader case in TestGoldens_Preimages; any change is a schema-family bump.
func (*FinalizedWithdrawal) UnmarshalCBOR ¶
func (t *FinalizedWithdrawal) UnmarshalCBOR(r io.Reader) (err error)
type FinalizedWithdrawalHeader ¶
type FinalizedWithdrawalHeader struct {
WithdrawalID [32]byte
BlockHash [32]byte
EntryIndex uint64
FinalizedAt int64
}
FinalizedWithdrawalHeader is the deterministic preimage projection for a FinalizedWithdrawal. It intentionally excludes Attestation and Block while binding the block hash and entry location that custody must verify.
func (*FinalizedWithdrawalHeader) MarshalCBOR ¶
func (t *FinalizedWithdrawalHeader) MarshalCBOR(w io.Writer) error
func (*FinalizedWithdrawalHeader) UnmarshalCBOR ¶
func (t *FinalizedWithdrawalHeader) UnmarshalCBOR(r io.Reader) (err error)
type FraudEvidenceSubmitter ¶
type FraudEvidenceSubmitter interface {
SubmitWithdrawalFraudEvidence(ctx context.Context, evidence WithdrawalFraudEvidence) error
}
FraudEvidenceSubmitter provides write access to the on-chain Slasher.
type MintReceipt ¶
type MintReceipt struct {
TxID string // Issuer-defined transaction/event id
Account string // Clearnet account URI to credit
AssetURI AssetURI // Issuer asset URI
Amount decimal.Decimal // Deposit amount in protocol token units, must be > 0
Signatures [][]byte // k-of-n provider ECDSA signatures over the receipt digest
}
MintReceipt is issued by the custody layer after an L1 deposit confirms (ADR-005 §9.1, receipt-model amendment 2026-05-12). Provider ECDSA signatures (k-of-n against the configured custody signer directory — manifest custody.signers/threshold; future Registry-backed source) attest that the deposit landed and reached the configured confirmation depth; the cluster validates the receipt and credits the user account (DR 1010 / CR 2010).
Idempotency is keyed by (AssetURI, TxID) so a re-issued receipt cannot produce a second credit. Clearnet does not watch the chain — receipts are the only deposit ingress.
func (*MintReceipt) EncodePayload ¶
func (v *MintReceipt) EncodePayload() []byte
EncodePayload serializes a MintReceipt into a BlockEntry payload.
func (*MintReceipt) MarshalCBOR ¶
func (t *MintReceipt) MarshalCBOR(w io.Writer) error
func (*MintReceipt) UnmarshalCBOR ¶
func (t *MintReceipt) UnmarshalCBOR(r io.Reader) (err error)
type NodeID ¶
type NodeID [32]byte
NodeID is a 256-bit identity in the Kademlia space (§3.1). A Node MAY operate multiple NodeIDs, each with its own collateral and BLS key pair.
type RegistryReader ¶
type RegistryReader interface {
GetNodeByID(ctx context.Context, nodeID [32]byte) (*Slot, error)
GetNodes(ctx context.Context, offset, limit *big.Int) ([]*Slot, error)
TotalNodes(ctx context.Context) (*big.Int, error)
GetActiveNodes(ctx context.Context, offset, limit *big.Int) ([]*Slot, error)
ActiveCount(ctx context.Context) (uint32, error)
FloorPrice(ctx context.Context) (*big.Int, error)
GetNodeId(ctx context.Context, tokenId uint32) ([32]byte, error)
UnbondingPeriod(ctx context.Context) (uint64, error)
}
RegistryReader provides read access to the L1 node registry.
Naming follows the on-chain `IRegistry` surface:
- `TotalNodes` / `GetNodes` enumerate active + unbonding; active-only callers use `ActiveCount` plus `GetActiveNodes` (which filters `deactivatedAt == 0` on the Go side).
- `FloorPrice` is the activation-time floor at the next cardinality.
- `GetNodeId(tokenId)` resolves an NFT to the currently-locked nodeId.
type RegistryWriter ¶
type RegistryWriter interface {
Lock(ctx context.Context, blsPubkeyG1 [2]*big.Int, blsPubkeyG2 [4]*big.Int, popSignature [2]*big.Int, maxPrice *big.Int) (uint32, error)
Unlock(ctx context.Context, tokenId uint32) error
Release(ctx context.Context, tokenId uint32) error
Fund(ctx context.Context, tokenId uint32, amount *big.Int) error
}
RegistryWriter provides write access to the L1 node registry.
`Lock` is a high-level onboarding helper: it calls `Registry.register`, which mints a NodeID NFT directly into Registry escrow and locks collateral. The `popSignature` parameter is accepted for source-compat but ignored on chain (ADR-008 2026-05-08: PoP verification moved to off-chain tooling).
type RepegOp ¶
type RepegOp struct {
PoolID string // Target pool
OldPriceScale *big.Int // PriceScale before the repeg
NewPriceScale *big.Int // PriceScale after the repeg
OldVirtPrice *big.Int // VirtualPrice before the repeg
NewVirtPrice *big.Int // VirtualPrice after the repeg
Epoch uint64 // Epoch number when the repeg occurred
PriceEMA *big.Int // Post-repeg PriceEMA (data_layer.md §4.2)
}
RepegOp is the payload for a PriceScale repegging block entry (SS8.1.2). Issued by the pool cluster after a profit-gated PriceScale adjustment.
type SessionChallengeOp ¶
type SessionChallengeOp struct {
SessionID [32]byte // Session being challenged
PreviousVersion uint64 // Version being replaced
NewVersion uint64 // Challenger's version (must be higher)
NewDeadline int64 // Unix timestamp when challenge window expires
}
SessionChallengeOp is the payload for a session dispute challenge (service_sessions.md §5.1).
func DecodeSessionChallengeOp ¶
func DecodeSessionChallengeOp(data []byte) (*SessionChallengeOp, error)
DecodeSessionChallengeOp deserializes a SessionChallengeOp.
func (*SessionChallengeOp) Decode ¶
func (op *SessionChallengeOp) Decode(payload []byte) error
Decode deserializes a SessionChallengeOp from a block entry payload.
func (*SessionChallengeOp) Encode ¶
func (op *SessionChallengeOp) Encode() []byte
Encode serializes the SessionChallengeOp into a block entry payload.
func (*SessionChallengeOp) MarshalCBOR ¶
func (t *SessionChallengeOp) MarshalCBOR(w io.Writer) error
func (*SessionChallengeOp) UnmarshalCBOR ¶
func (t *SessionChallengeOp) UnmarshalCBOR(r io.Reader) (err error)
type SessionCloseOp ¶
type SessionCloseOp struct {
SessionID [32]byte // keccak256(userAccountID || serviceAccountID || nonce)
Version uint64 // Latest co-signed version
UserAmount decimal.Decimal // Final user allocation
ServiceAmount decimal.Decimal // Final service allocation
Cooperative bool // True if both parties signed
}
SessionCloseOp is the payload for a session close block entry (service_sessions.md §3.3). Emitted during cooperative or unilateral session settlement.
func DecodeSessionCloseOp ¶
func DecodeSessionCloseOp(data []byte) (*SessionCloseOp, error)
DecodeSessionCloseOp deserializes a SessionCloseOp.
func (*SessionCloseOp) Decode ¶
func (op *SessionCloseOp) Decode(payload []byte) error
Decode deserializes a SessionCloseOp from a block entry payload.
func (*SessionCloseOp) Encode ¶
func (op *SessionCloseOp) Encode() []byte
Encode serializes the SessionCloseOp into a block entry payload.
func (*SessionCloseOp) MarshalCBOR ¶
func (t *SessionCloseOp) MarshalCBOR(w io.Writer) error
func (*SessionCloseOp) UnmarshalCBOR ¶
func (t *SessionCloseOp) UnmarshalCBOR(r io.Reader) (err error)
type SignerRotationFinalizer ¶
type SignerRotationFinalizer interface {
Pack(ctx context.Context, opID [32]byte, newSigners []string, newThreshold int) ([]byte, error)
Validate(ctx context.Context, opID [32]byte, packed []byte, newSigners []string, newThreshold int) error
Sign(ctx context.Context, packed []byte) ([]byte, error)
Submit(ctx context.Context, packed []byte, signatures [][]byte) (string, error)
VerifyRotation(ctx context.Context, newSigners []string, newThreshold int) (txID string, done bool, err error)
}
SignerRotationFinalizer rotates the vault's authorized signer set. It is the same build→sign→merge→submit→verify shape as VaultWithdrawalFinalizer, but the signed payload commits to the new signer set + threshold + the chain's local replay token (EVM signerNonce, XRPL account sequence, Solana program nonce) rather than a withdrawal. Signature collection (mesh) and submitter selection stay with the caller; the implementation owns the node's signer and the chain-specific authorization supplied at construction.
newSigners is the chain-native encoding of the incoming set — EVM/XRPL addresses, BTC 33-byte compressed pubkeys (hex), Solana ed25519 pubkeys (hex) — matching custody's RotationRequest. newThreshold is the new k-of-n quorum.
opID is the caller's unique identifier for this rotation operation (custody's RotationRequest.RequestID). In-place chains bind replay protection on-chain (EVM signerNonce, XRPL account sequence, Solana program nonce) and accept opID only to keep one uniform signature — they do not embed it in the packed payload. BTC has no on-chain op record: it embeds opID as an OP_RETURN marker in the sweep so an external watcher can attribute the swept transaction to this rotation. Pass a zero opID when the caller has no watcher to satisfy.
In-place chains (EVM, XRPL, Solana) mutate on-chain signer state at a fixed vault address. BTC has no in-place form: its P2WSH vault address is a function of the signer set, so rotation is a sweep of every old-vault UTXO into the newly-derived vault. The BTC implementation hides that behind the same interface via a vault store supplied at construction (it pivots to the new vault on confirmation); to callers all four chains rotate identically.
- Pack returns the canonical bytes to be signed for this rotation.
- Validate re-derives the trust-bound shape and asserts the packed bytes match — the Byzantine-packer defense; every node runs it before Sign.
- Sign produces this node's signature over the packed bytes.
- Submit merges the collected signatures against the live (outgoing) signer set and broadcasts the rotation. Idempotent against an already-applied rotation.
- VerifyRotation reads canonical chain state to answer "is the set now the requested one?" — binary (done or not), the signal each node uses to close the dual-sign window and drop the outgoing key. It is keyed on the new signer set (not opID), so it stays a direct state read on every chain.
type Slot ¶
type Slot struct {
ID NodeID `json:"id"`
Label string `json:"label"`
BLSPubKey []byte `json:"bls_pubkey,omitempty"`
// Registry position
TokenID *big.Int `json:"-"`
Index uint64 `json:"-"` // widened from uint32 for cbor-gen compat (Wave 2 pre)
// Economic weight + lifecycle
Owner string `json:"-"` // EOA (hex) that owns the NFT per Registry.ownerOf(tokenId)
Collateral *big.Int `json:"-"`
ActivatedAt uint64 `json:"-"`
DeactivatedAt uint64 `json:"-"`
State SlotState `json:"-"`
LastHeartbeat int64 `json:"-"`
MissedBeats uint64 `json:"-"` // widened from uint32 for cbor-gen compat (Wave 2 pre)
}
Slot is a logical node: one per NFT locked on Registry. Carries the slot's public identity (NodeID, Label, BLSPubKey) plus its Registry position and economic/lifecycle metadata.
type SlotState ¶
type SlotState uint8
SlotState is the lifecycle state of a Registry slot (ADR-005 §3.3).
const ( // SlotStateWarmup: slot is syncing state, not eligible to sign (§3.3). SlotStateWarmup SlotState = iota // SlotStateActive: slot is fully operational and may sign blocks. SlotStateActive // SlotStateUnbonding: slot has unregistered. Cannot sign new blocks but // remains in the Kademlia tree for the full UnbondingWindow so fraud // proofs may still be submitted against its collateral (ADR-005 §3.3). SlotStateUnbonding // SlotStateEvicted: slot has been fully removed from the Kademlia tree. SlotStateEvicted // SlotStateDisabled: slot missed heartbeats and is temporarily disabled (bitmask = 0). SlotStateDisabled )
type SwapOp ¶
type SwapOp struct {
TxID string // Original transaction ID
AssetIn AssetID // Input asset (what the user paid)
AssetOut AssetID // Output asset (what the user receives)
AmountIn decimal.Decimal // Amount of input asset consumed
AmountOut decimal.Decimal // Amount of output asset produced (after fee)
PoolID string // Pool that executed the swap
Fee decimal.Decimal // Fee deducted (in output asset)
FeeRate uint64 // Dynamic fee rate applied (bps) — §5.3
PriceEMA decimal.Decimal // Post-swap EMA price (1e18 fixed-point, data_layer.md §4.2)
SpotPrice decimal.Decimal // Post-swap spot price (1e18 fixed-point, data_layer.md §4.2)
}
SwapOp is the payload for a swap execution block entry (§7.1). Issued by the pool cluster after executing the AMM swap. Consumed by the user's cluster to credit the output asset.
type TokenReader ¶
type TokenReader interface {
BalanceOf(ctx context.Context, token string, account string) (*big.Int, error)
}
TokenReader provides read access to ERC-20 token balances. token is the token contract address (hex); account is the holder address (hex).
type TransferOp ¶
type TransferOp struct {
TxID string // Original transaction ID
To string // Recipient address
Assets []AssetTransfer // Assets transferred, sorted by AssetID (§7.2)
}
TransferOp is the payload for a transfer block entry (§5.3.5). Issued by the sender's cluster after debiting the sender. Consumed by the recipient's cluster to credit the recipient.
func NewSingleAssetTransferOp ¶
func NewSingleAssetTransferOp(txID, to string, asset AssetID, amount decimal.Decimal) *TransferOp
NewSingleAssetTransferOp creates a TransferOp with a single asset (common case).
func (*TransferOp) Decode ¶
func (op *TransferOp) Decode(payload []byte) error
Decode deserializes a TransferOp from a block entry payload.
func (*TransferOp) Encode ¶
func (op *TransferOp) Encode() []byte
Encode serializes the TransferOp into a block entry payload (canonical CBOR, ADR-009 §4).
func (*TransferOp) MarshalCBOR ¶
func (t *TransferOp) MarshalCBOR(w io.Writer) error
func (*TransferOp) UnmarshalCBOR ¶
func (t *TransferOp) UnmarshalCBOR(r io.Reader) (err error)
type VaultDepositor ¶
type VaultDepositor interface {
SubmitDeposit(ctx context.Context, assetAddress string, amount decimal.Decimal, dest DepositDestination) (string, error)
// VerifyDeposit reports whether the deposit identified by txID (returned by
// SubmitDeposit) is present and final on chain — a pure read for replay/audit.
// minConf is the confirmation depth required for DepositConfirmed; chains
// with no numeric depth (Solana) map it onto a commitment level instead.
VerifyDeposit(ctx context.Context, txID string, minConf uint64) (DepositStatus, error)
}
VaultDepositor moves funds into the L1 vault. The implementation owns the depositor's signing identity (a sign.Signer supplied at construction) and executes the deposit on its chain: a contract call (EVM), a funding tx to a derived address (BTC), or a memo-tagged Payment (XRPL). It expects a chain-local asset address/key, protocol-unit amount, and crediting destination. An empty assetAddress denotes the native asset at this API boundary; chain implementations normalize it to their protocol native marker.
type VaultWithdrawalFinalizer ¶
type VaultWithdrawalFinalizer interface {
Pack(ctx context.Context, op *WithdrawalOp, withdrawalID [32]byte, deadline int64) ([]byte, error)
Validate(ctx context.Context, packed []byte, op *WithdrawalOp, withdrawalID [32]byte, deadline int64) error
Sign(ctx context.Context, packed []byte) ([]byte, error)
Submit(ctx context.Context, packed []byte, signatures [][]byte) (string, error)
VerifyExecution(ctx context.Context, withdrawalID [32]byte) (txID string, executed bool, err error)
}
VaultWithdrawalFinalizer turns an authorized withdrawal into an on-chain release, as a sequence each custody node runs over a caller-orchestrated quorum. The implementation owns the node's signer and the chain-specific authorization (vault address, signer set, fee policy, ticket source) supplied at construction.
- Pack returns the canonical bytes to be signed for this withdrawal.
- Validate re-derives the trust-bound shape from the op and asserts the packed bytes match — the defense against a Byzantine packer; every node runs it before Sign.
- Sign produces this node's signature over the packed bytes.
- Submit merges the packed bytes with the collected quorum signatures into a submittable artifact and broadcasts it. It filters the signatures against the live on-chain signer set and is idempotent against a withdrawal a peer has already executed.
- VerifyExecution reads canonical chain state to answer "already executed?" for the retry/finalize loop.
deadline (unix seconds) is threaded into Pack/Validate: it is a digest input on every chain, so the packed bytes — and thus the signature — bind it. Sign/Submit are unchanged; the packed body already carries it.
type WithdrawalFraudEvidence ¶
type WithdrawalFraudEvidence struct {
ChallengedObject []byte
AnchorHeader []byte
AnchorSignature []byte
EntryIndex uint64
SMTProof [][32]byte
SMTBitmask *big.Int
BalanceKey [32]byte
ProvenBalance *big.Int
}
WithdrawalFraudEvidence is the frozen two-object Slasher evidence shape (protocol/security.md §11): challenged signed withdrawal Block bytes plus the immediate pre-withdrawal signed header and one balance SMT proof.
type WithdrawalOp ¶
type WithdrawalOp struct {
AssetURI AssetURI // Issuer asset URI — needed for ledger finalization and custody routing
Amount decimal.Decimal // Withdrawal amount in token units
Recipient string // L1 recipient address (chain-native format)
UserSignature []byte // User's ECDSA authorization of the withdrawal
}
WithdrawalOp is the payload for a withdrawal block entry (SS7.3.1). Issued by the user's cluster after locking funds for L1 withdrawal. Delivered to the custody layer after the clearing-side challenge window.
Removed fields (now in block header or derived at vault level):
- WithdrawalID: derived at vault level as keccak256(accountId, blockHash, entryIndex, assetURI, recipient, amount, nonce)
- Nonce: in BlockEntry.Nonce
- K: in Block.K
- SignedAt: in Block.SealedAt
- SignerNodeIDs: recoverable from Block.Attestation.Bitmask + cluster lookup
func (*WithdrawalOp) Decode ¶
func (op *WithdrawalOp) Decode(payload []byte) error
Decode deserializes a WithdrawalOp from a block entry payload.
func (*WithdrawalOp) Encode ¶
func (op *WithdrawalOp) Encode() []byte
Encode serializes the WithdrawalOp into a block entry payload.
func (*WithdrawalOp) MarshalCBOR ¶
func (t *WithdrawalOp) MarshalCBOR(w io.Writer) error
func (*WithdrawalOp) UnmarshalCBOR ¶
func (t *WithdrawalOp) UnmarshalCBOR(r io.Reader) (err error)
type WithdrawalOutcome ¶ added in v0.4.0
type WithdrawalOutcome uint8
WithdrawalOutcome is the terminal status of a withdrawal, carried in a BurnReceipt. It lets clearnet tell a withdrawal that executed on L1 (settle the burn) apart from one that did not leave the vault (authorize a safe re-credit, with an empty TxID). The status byte is bound into the receipt digest, so a quorum cannot be tricked into swapping one outcome for another.
const ( // WithdrawalExecuted means the withdrawal was executed on the target chain; // TxID is set and the clearing layer settles the burn. WithdrawalExecuted WithdrawalOutcome = 1 // WithdrawalExpired means the authorization passed its deadline unspent and // can never execute (time-bound expiry); the clearing layer may re-credit. WithdrawalExpired WithdrawalOutcome = 2 // WithdrawalInvalidFormat means the withdrawal has not passed custody's // input validation (e.g. malformed address, or other pre-flight rejection); WithdrawalInvalidFormat WithdrawalOutcome = 3 // unauthorized signers WithdrawalUnauthorized WithdrawalOutcome = 4 // WithdrawalInvalidDecimals means the withdrawal amount cannot be represented // in the target chain's base units. // TODO: Replace this status with explicit remainder semantics once // BurnReceipt carries the unexecuted amount. WithdrawalInvalidDecimals WithdrawalOutcome = 5 )