Documentation
¶
Overview ¶
Package keyvm implements the K-Chain: an AUTH-ONLY service VM for distributed key management. K authorizes and coordinates key ceremonies; it never holds, stores, reconstructs, or transmits secret key material or threshold shares. See state.go for the structurally-enforced zero-secret invariant. Mutating operations take effect only through fee-settled consensus blocks (block.go), priced by a per-algorithm gas schedule (gas.go) and burned from the payer's on-chain balance via the native fee settlement primitive (github.com/luxfi/ chains/fee).
Index ¶
- Constants
- Variables
- func FeeFor(tx *Transaction) (uint64, error)
- func GasFor(tx *Transaction) (fee.Gas, error)
- func MinScheduledFee() uint64
- func SupportedAlgorithm(algo string) bool
- type AuthPolicy
- type AuthorizePayload
- type BalanceArgs
- type BalanceReply
- type Block
- func (b *Block) Accept(ctx context.Context) error
- func (b *Block) Bytes() []byte
- func (b *Block) Height() uint64
- func (b *Block) ID() ids.ID
- func (b *Block) Parent() ids.ID
- func (b *Block) ParentID() ids.ID
- func (b *Block) Reject(ctx context.Context) error
- func (b *Block) Status() uint8
- func (b *Block) Timestamp() time.Time
- func (b *Block) Verify(ctx context.Context) error
- type CeremonyRecord
- type CeremonyView
- type Factory
- type FeeScheduleArgs
- type FeeScheduleEntry
- type FeeScheduleReply
- type Genesis
- type GetCeremonyArgs
- type GetCeremonyReply
- type GetKeyArgs
- type GetKeyReply
- type HealthArgs
- type HealthReply
- type KeyRecord
- type KeyView
- type ListKeysArgs
- type ListKeysReply
- type RegisterKeyPayload
- type RevokePayload
- type Service
- func (s *Service) Balance(r *http.Request, args *BalanceArgs, reply *BalanceReply) error
- func (s *Service) FeeSchedule(r *http.Request, args *FeeScheduleArgs, reply *FeeScheduleReply) error
- func (s *Service) GetCeremony(r *http.Request, args *GetCeremonyArgs, reply *GetCeremonyReply) error
- func (s *Service) GetKey(r *http.Request, args *GetKeyArgs, reply *GetKeyReply) error
- func (s *Service) Health(r *http.Request, args *HealthArgs, reply *HealthReply) error
- func (s *Service) ListKeys(r *http.Request, args *ListKeysArgs, reply *ListKeysReply) error
- func (s *Service) SubmitTransaction(r *http.Request, args *SubmitTransactionArgs, reply *SubmitTransactionReply) error
- type SetPolicyPayload
- type SubmitTransactionArgs
- type SubmitTransactionReply
- type Transaction
- type VM
- func (vm *VM) Balance(acct fee.Account) (uint64, error)
- func (vm *VM) BuildBlock(ctx context.Context) (chain.Block, error)
- func (vm *VM) Burned() (uint64, error)
- func (vm *VM) Ceremony(id ids.ID) (*CeremonyRecord, bool)
- func (vm *VM) Connected(ctx context.Context, nodeID ids.NodeID, ver *chain.VersionInfo) error
- func (vm *VM) CreateHandlers(ctx context.Context) (map[string]http.Handler, error)
- func (vm *VM) CreateStaticHandlers(ctx context.Context) (map[string]http.Handler, error)
- func (vm *VM) Disconnected(ctx context.Context, nodeID ids.NodeID) error
- func (vm *VM) FeePolicy() nodefee.Policy
- func (vm *VM) GetBlock(ctx context.Context, blockID ids.ID) (chain.Block, error)
- func (vm *VM) GetBlockIDAtHeight(ctx context.Context, height uint64) (ids.ID, error)
- func (vm *VM) HealthCheck(ctx context.Context) (chain.HealthResult, error)
- func (vm *VM) Initialize(ctx context.Context, init vmcore.Init) error
- func (vm *VM) KeyByID(id ids.ID) (*KeyRecord, bool)
- func (vm *VM) KeyByName(name string) (*KeyRecord, bool)
- func (vm *VM) Keys() []*KeyRecord
- func (vm *VM) LastAccepted(ctx context.Context) (ids.ID, error)
- func (vm *VM) NewHTTPHandler(ctx context.Context) (http.Handler, error)
- func (vm *VM) ParseBlock(ctx context.Context, blockBytes []byte) (chain.Block, error)
- func (vm *VM) SetPreference(ctx context.Context, id ids.ID) error
- func (vm *VM) SetState(ctx context.Context, state uint32) error
- func (vm *VM) Shutdown(ctx context.Context) error
- func (vm *VM) SubmitTx(tx *Transaction) (ids.ID, error)
- func (vm *VM) Version(ctx context.Context) (string, error)
- func (vm *VM) WaitForEvent(ctx context.Context) (vmcore.Message, error)
Constants ¶
const ( StatusActive = "active" StatusRevoked = "revoked" )
Key lifecycle states.
const ( CeremonyDKG = "dkg" // distributed key generation (result: public key + commitments) CeremonySign = "sign" // threshold signing (result: aggregate signature) )
Ceremony types K may authorize on the committee. K authorizes and records the PUBLIC result; it performs none of the secret-bearing computation.
const ( CeremonyAuthorized = "authorized" // K authorized it; committee may proceed CeremonyFulfilled = "fulfilled" // committee returned a public result CeremonyRejected = "rejected" // policy denied or committee failed )
Ceremony lifecycle states.
const ( TxRegisterKey uint8 = 1 // record a key's PUBLIC material + commitments + policy TxSetPolicy uint8 = 2 // update a key's authorization policy TxAuthorize uint8 = 3 // authorize (trigger) a committee ceremony: dkg/sign/reshare TxRevokeKey uint8 = 4 // revoke a key )
Transaction types. Each is a MUTATING operation that may only take effect through a fee-settled consensus block — never through a synchronous RPC.
const ( // Version of the K-Chain VM. Version = "2.0.0" // VMName is the human-readable name of the K-Chain VM. VMName = "keyvm" // Database namespaces. Key/ceremony records are JSON; balances live under // the fee ledger's own namespace (github.com/luxfi/chains/fee). KeyPrefix = "key:" CeremonyPrefix = "ceremony:" BlockPrefix = "block:" )
const GasPrice = fee.Gas(1_000)
GasPrice is nLUX per unit of gas. It is chosen so the cheapest priced operation still settles >= node/vms/types/fee.MinTxFeeFloor (1 mLUX), unifying the new per-operation settlement with the pre-existing admission floor. gas_test.go asserts that relationship for every (operation, algorithm) pair so the two fee surfaces can never silently drift apart.
Variables ¶
var ( ErrInvalidTxType = errors.New("keyvm: invalid transaction type") ErrInvalidPayload = errors.New("keyvm: invalid transaction payload") ErrUnknownAlgorithm = errors.New("keyvm: unsupported algorithm") ErrInvalidThreshold = errors.New("keyvm: invalid threshold (need 0 < t <= n)") ErrInvalidCeremony = errors.New("keyvm: invalid ceremony type") ErrUnsignedTx = errors.New("keyvm: transaction missing payer auth/signature") ErrPayerMismatch = errors.New("keyvm: payer does not match auth public key") ErrBadSignature = errors.New("keyvm: invalid payer signature") ErrKeyNotFound = errors.New("keyvm: key not found") ErrKeyExists = errors.New("keyvm: key already exists") ErrKeyRevoked = errors.New("keyvm: key is revoked") // ErrBadNonce rejects a replayed or out-of-order transaction. A payer's // transactions MUST carry strictly increasing nonces starting at 1; this is // what stops a captured signed transaction from being resubmitted to drain // the payer's balance through repeated fee burns. ErrBadNonce = errors.New("keyvm: bad or replayed nonce") )
Sentinel errors. Every one denies an operation — the package fails secure.
var VMID = ids.ID{'k', 'e', 'y', 'v', 'm'}
VMID is the K-Chain VM identifier (matches constants.KeyVMID).
Functions ¶
func FeeFor ¶ added in v1.4.6
func FeeFor(tx *Transaction) (uint64, error)
FeeFor returns the nLUX fee a transaction settles: GasFor(tx) * GasPrice.
func GasFor ¶ added in v1.4.6
func GasFor(tx *Transaction) (fee.Gas, error)
GasFor returns the metered gas for a transaction, pricing by operation and — for committee-dispatching operations — by algorithm. It fails closed on an unknown operation type or an unknown/missing algorithm for an operation that requires one.
func MinScheduledFee ¶ added in v1.4.6
func MinScheduledFee() uint64
MinScheduledFee is the smallest fee any valid operation can settle (the cheapest base operation at GasPrice). gas_test.go asserts it is >= node/vms/types/fee.MinTxFeeFloor.
func SupportedAlgorithm ¶ added in v1.4.6
SupportedAlgorithm reports whether algo is priced (and therefore accepted) by the K-Chain gas schedule.
Types ¶
type AuthPolicy ¶ added in v1.4.6
type AuthPolicy struct {
// Admins may change this policy and revoke the key.
Admins []fee.Account `json:"admins"`
// Authorized may request ceremonies (sign/dkg/reshare) on this key.
Authorized []fee.Account `json:"authorized"`
// MaxOpsPerEpoch bounds authorized ceremonies per epoch (0 = unlimited).
MaxOpsPerEpoch uint32 `json:"maxOpsPerEpoch"`
// RequireQuorum is the minimum committee acknowledgement K records before a
// ceremony is considered fulfillable (informational on K; enforced by the
// committee). 0 means "use the key's threshold".
RequireQuorum uint32 `json:"requireQuorum"`
// ExpiresAt is a unix timestamp after which no ceremony is authorized; 0 = no expiry.
ExpiresAt int64 `json:"expiresAt"`
}
AuthPolicy is the access-control rule set for a key: who may administer it and who may invoke ceremonies on it, under what temporal/rate conditions. It is pure PUBLIC policy — addresses and limits, never secrets.
type AuthorizePayload ¶ added in v1.4.6
type AuthorizePayload struct {
Ceremony string `json:"ceremony"` // CeremonyDKG | CeremonySign | CeremonyReshare
Message []byte `json:"message"`
}
AuthorizePayload triggers a committee ceremony. Message is the PUBLIC digest to be signed (for sign ceremonies); empty for dkg/reshare.
type BalanceArgs ¶ added in v1.4.6
type BalanceArgs struct {
Address string `json:"address"`
}
BalanceArgs selects an account by hex address.
type BalanceReply ¶ added in v1.4.6
type BalanceReply struct {
BalanceNLUX uint64 `json:"balanceNLux"`
BurnedNLUX uint64 `json:"burnedNLux"`
}
BalanceReply returns the account balance and total burned supply, both nLUX.
type Block ¶
type Block struct {
// contains filtered or unexported fields
}
Block is a K-Chain block: an ordered batch of fee-settled key operations.
func (*Block) Accept ¶
Accept settles and applies the block atomically. For each transaction it METERS the operation's gas, BURNS the fee from the payer (debit + supply reduction), then APPLIES the state effect — all written through the VM's versiondb, which is committed exactly once. Any failure aborts the whole block (no partial application, no unpaid operation): the versiondb is rolled back and the caches are reloaded from the unchanged base DB.
func (*Block) Reject ¶
Reject discards the block and returns its transactions to the mempool so they can be retried in a later block.
func (*Block) Verify ¶
Verify checks the block can be accepted WITHOUT mutating state: the parent exists, every transaction is well-formed and authenticated, and every payer can afford its fee — including the cumulative fees of multiple transactions from the same payer within this block. A block that fails any check is never accepted (fail closed); verifying a block never moves funds.
type CeremonyRecord ¶ added in v1.4.6
type CeremonyRecord struct {
ID ids.ID `json:"id"`
KeyID ids.ID `json:"keyId"`
Type string `json:"type"`
Requester fee.Account `json:"requester"`
Message []byte `json:"message"` // PUBLIC digest to sign (sign ceremonies)
Result []byte `json:"result"` // PUBLIC result (signature / new public key)
Status string `json:"status"`
CreatedAt int64 `json:"createdAt"`
}
CeremonyRecord is K's record of an authorized DKG/sign/reshare ceremony. K stores the authorization decision and the ceremony's PUBLIC inputs/outputs (the digest to be signed; the resulting aggregate signature or public key). It never stores shares or partial secrets.
type CeremonyView ¶ added in v1.4.6
type CeremonyView struct {
ID string `json:"id"`
KeyID string `json:"keyId"`
Type string `json:"type"`
Requester string `json:"requester"`
Message string `json:"message"` // base64 public digest
Result string `json:"result"` // base64 public result
Status string `json:"status"`
CreatedAt int64 `json:"createdAt"`
}
CeremonyView is the PUBLIC view of a ceremony record.
type Factory ¶
Factory builds K-Chain VM instances. Unlike the prior design it allocates no GPU/accel session: an auth-only VM performs no key generation or batch cryptography on its hot path, so there is nothing to accelerate and one fewer failure mode / native dependency.
func NewDefaultFactory ¶
func NewDefaultFactory() *Factory
NewDefaultFactory builds a factory with default configuration.
func NewFactory ¶
NewFactory builds a factory with the given configuration.
type FeeScheduleEntry ¶ added in v1.4.6
type FeeScheduleEntry struct {
Operation string `json:"operation"`
Algorithm string `json:"algorithm"`
Gas uint64 `json:"gas"`
FeeNLUX uint64 `json:"feeNLux"`
}
FeeScheduleEntry prices one (operation, algorithm) pair.
type FeeScheduleReply ¶ added in v1.4.6
type FeeScheduleReply struct {
GasPrice uint64 `json:"gasPriceNLuxPerGas"`
Entries []FeeScheduleEntry `json:"entries"`
}
FeeScheduleReply returns the per-algorithm gas/fee schedule and the price.
type Genesis ¶
type Genesis struct {
Version int `json:"version"`
Message string `json:"message"`
Timestamp int64 `json:"timestamp"`
Alloc map[string]uint64 `json:"alloc"`
}
Genesis is the K-Chain genesis: a funding allocation (address hex -> nLUX) and metadata. Initial keys are registered via consensus transactions, not genesis, so genesis carries no key material.
type GetCeremonyArgs ¶ added in v1.4.6
type GetCeremonyArgs struct {
ID string `json:"id"`
}
GetCeremonyArgs selects a ceremony by ID.
type GetCeremonyReply ¶ added in v1.4.6
type GetCeremonyReply struct {
Ceremony CeremonyView `json:"ceremony"`
}
GetCeremonyReply returns the ceremony view.
type GetKeyArgs ¶ added in v1.4.6
GetKeyArgs selects a key by ID or Name (ID takes precedence).
type GetKeyReply ¶ added in v1.4.6
type GetKeyReply struct {
Key KeyView `json:"key"`
}
GetKeyReply returns the public key view.
type HealthReply ¶
type HealthReply struct {
Healthy bool `json:"healthy"`
Details map[string]string `json:"details"`
}
HealthReply reports VM health.
type KeyRecord ¶ added in v1.4.6
type KeyRecord struct {
ID ids.ID `json:"id"`
Name string `json:"name"`
Algorithm string `json:"algorithm"`
PublicKey []byte `json:"publicKey"` // PUBLIC key bytes
Threshold uint32 `json:"threshold"` // t in t-of-n
Commitments [][]byte `json:"commitments"` // PUBLIC VSS commitments, NOT shares
Committee []ids.NodeID `json:"committee"` // off-K share holders (public IDs)
Policy AuthPolicy `json:"policy"`
Owner fee.Account `json:"owner"`
Status string `json:"status"`
CreatedAt int64 `json:"createdAt"`
UpdatedAt int64 `json:"updatedAt"`
}
KeyRecord is the ONLY per-key state K stores. Every field is PUBLIC. There is deliberately no PrivateKey, no Share, no Seed — K holds the public key and the VSS COMMITMENTS (public curve points that let anyone verify a share without learning it), the committee that holds the shares off-K, and the policy.
type KeyView ¶ added in v1.4.6
type KeyView struct {
ID string `json:"id"`
Name string `json:"name"`
Algorithm string `json:"algorithm"`
PublicKey string `json:"publicKey"` // base64
Threshold uint32 `json:"threshold"`
Commitments []string `json:"commitments"` // base64 public VSS commitments
Committee []string `json:"committee"`
Owner string `json:"owner"`
Status string `json:"status"`
CreatedAt int64 `json:"createdAt"`
UpdatedAt int64 `json:"updatedAt"`
}
KeyView is the PUBLIC JSON view of a key record. It exposes the public key and commitments; there is no field for a private key or share because none exists.
type ListKeysArgs ¶
ListKeysArgs filters the key listing.
type ListKeysReply ¶
ListKeysReply returns matching key views.
type RegisterKeyPayload ¶ added in v1.4.6
type RegisterKeyPayload struct {
Name string `json:"name"`
PublicKey []byte `json:"publicKey"`
Threshold uint32 `json:"threshold"`
Commitments [][]byte `json:"commitments"`
Committee []ids.NodeID `json:"committee"`
Policy AuthPolicy `json:"policy"`
}
RegisterKeyPayload records the PUBLIC result of an off-K DKG (or anchors a new key): its public key, threshold parameters, VSS commitments, the committee that holds the shares off-K, and the initial policy. No shares appear here.
type RevokePayload ¶ added in v1.4.6
type RevokePayload struct {
Reason string `json:"reason"`
}
RevokePayload revokes a key.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service is the K-Chain JSON-RPC surface. Mutating operations are submitted as CLIENT-SIGNED transactions (the client holds its own key; K never does) and take effect only through fee-settled consensus blocks. Everything else is a read-only query of PUBLIC state. There is no synchronous key creation, no encryption endpoint, and no "fee" integer in any request — the prior design's secret-bearing, fee-as-JSON-integer surface is gone.
func (*Service) Balance ¶ added in v1.4.6
func (s *Service) Balance(r *http.Request, args *BalanceArgs, reply *BalanceReply) error
Balance returns an account's spendable balance and the chain's burned supply.
func (*Service) FeeSchedule ¶ added in v1.4.6
func (s *Service) FeeSchedule(r *http.Request, args *FeeScheduleArgs, reply *FeeScheduleReply) error
FeeSchedule returns the chain's per-operation, per-algorithm fee schedule so clients can compute the exact burn before submitting a transaction.
func (*Service) GetCeremony ¶ added in v1.4.6
func (s *Service) GetCeremony(r *http.Request, args *GetCeremonyArgs, reply *GetCeremonyReply) error
GetCeremony returns an authorized/fulfilled ceremony record.
func (*Service) GetKey ¶ added in v1.4.6
func (s *Service) GetKey(r *http.Request, args *GetKeyArgs, reply *GetKeyReply) error
GetKey returns a key record by ID or name.
func (*Service) Health ¶
func (s *Service) Health(r *http.Request, args *HealthArgs, reply *HealthReply) error
Health reports VM health.
func (*Service) ListKeys ¶
func (s *Service) ListKeys(r *http.Request, args *ListKeysArgs, reply *ListKeysReply) error
ListKeys lists keys, optionally filtered by algorithm and status.
func (*Service) SubmitTransaction ¶ added in v1.4.6
func (s *Service) SubmitTransaction(r *http.Request, args *SubmitTransactionArgs, reply *SubmitTransactionReply) error
SubmitTransaction parses, authenticates, admission-checks, and enqueues a signed transaction.
type SetPolicyPayload ¶ added in v1.4.6
type SetPolicyPayload struct {
Policy AuthPolicy `json:"policy"`
}
SetPolicyPayload replaces a key's authorization policy.
type SubmitTransactionArgs ¶ added in v1.4.6
type SubmitTransactionArgs struct {
Tx string `json:"tx"`
}
SubmitTransactionArgs carries a hex-encoded, client-signed transaction (Transaction.Bytes()). The client builds and signs it offline with its own ML-DSA-65 key; K only verifies the signature and settles the fee.
type SubmitTransactionReply ¶ added in v1.4.6
type SubmitTransactionReply struct {
TxID string `json:"txId"`
}
SubmitTransactionReply returns the accepted transaction's ID. The fee is settled when the transaction's block is accepted, not here.
type Transaction ¶
type Transaction struct {
Type uint8
Algorithm string // key algorithm (drives per-algorithm gas); "" for policy-only ops
Payer fee.Account // fee payer + authorization subject (public address)
KeyID ids.ID // target key (RegisterKey derives it; others reference it)
GasLimit uint64 // payer-declared gas ceiling for this tx
Nonce uint64 // payer replay/uniqueness nonce
Payload []byte // op-specific PUBLIC encoding
Auth []byte // payer ML-DSA-65 PUBLIC key
Sig []byte // payer signature over SigningBytes()
// contains filtered or unexported fields
}
Transaction is a K-Chain consensus transaction. Its header is deterministic binary; Payload is an opaque, PUBLIC, op-specific JSON blob; Auth is the payer's ML-DSA-65 public key and Sig the payer's signature over the signing bytes. Nothing here is or can become secret material.
func ParseTransaction ¶
func ParseTransaction(data []byte) (*Transaction, error)
ParseTransaction decodes a transaction from its wire encoding.
func (*Transaction) Apply ¶ added in v1.4.6
func (tx *Transaction) Apply(vm *VM, now int64) error
Apply mutates VM state for an already-verified, already-paid transaction. It runs inside block.Accept, writing through the VM's versiondb so the effect commits atomically with the fee burn. now is the accepting block's unix time. It re-runs checkAuth (defense in depth) before mutating.
func (*Transaction) Bytes ¶
func (tx *Transaction) Bytes() []byte
Bytes is the full wire encoding: SigningBytes followed by Auth and Sig.
func (*Transaction) ID ¶
func (tx *Transaction) ID() ids.ID
ID returns the transaction's content hash (over the full Bytes).
func (*Transaction) SigningBytes ¶ added in v1.4.6
func (tx *Transaction) SigningBytes() []byte
SigningBytes is the deterministic encoding the payer signs. It binds every semantically meaningful field — including Payer — but excludes Auth and Sig. Because Payer is bound here and authenticate() requires Payer == addressOf(Auth), an attacker cannot swap in a different public key.
func (*Transaction) SyntacticVerify ¶ added in v1.4.6
func (tx *Transaction) SyntacticVerify() error
SyntacticVerify checks the transaction is well-formed and priceable, without any state. It rejects unknown types, unpriceable algorithms, and undecodable or out-of-range payloads — all fail-closed.
type VM ¶
VM implements the K-Chain auth-only Virtual Machine.
STRUCTURAL ZERO-SECRET NOTE: every field below is either runtime plumbing or a cache of PUBLIC records (KeyRecord / CeremonyRecord). There is deliberately no key cache of private keys, no share store, and no GPU crypto session — the previous design's *mlkem.PrivateKey cache, KeyShare store, and accel session are gone. authonly_test.go proves no reachable field can hold a secret.
func (*VM) BuildBlock ¶
BuildBlock drains the mempool into a new block extending the last accepted block. The block is not yet verified or accepted — settlement happens in Verify/Accept.
func (*VM) Ceremony ¶ added in v1.4.6
func (vm *VM) Ceremony(id ids.ID) (*CeremonyRecord, bool)
Ceremony returns a copy of a ceremony record.
func (*VM) CreateHandlers ¶
func (*VM) CreateStaticHandlers ¶
func (*VM) FeePolicy ¶ added in v1.2.6
FeePolicy exposes the chain's declared admission policy for diagnostics and the boot-time Validate gate.
func (*VM) GetBlockIDAtHeight ¶
func (*VM) HealthCheck ¶
func (*VM) Initialize ¶
Initialize wires the VM: database, ledger, fee policy, caches, genesis seeding, and the JSON-RPC service.
func (*VM) ParseBlock ¶
ParseBlock decodes a block from bytes.
func (*VM) Shutdown ¶
Shutdown stops the VM. There is no secret material to zero — by construction the VM never held any.
func (*VM) SubmitTx ¶ added in v1.4.6
func (vm *VM) SubmitTx(tx *Transaction) (ids.ID, error)
SubmitTx validates, authenticates, and admission-checks a transaction, then enqueues it and signals the engine to build a block. The fee is SETTLED later, in block Accept — never here. Returns the transaction ID.