Documentation
¶
Overview ¶
Package fhevm implements the F-Chain: the coordination plane for confidential compute (LP-8200, LP-167). F records the PUBLIC coordinates of encrypted values — a handle, the digest of the off-chain ciphertext body, its owner, the capabilities granted over it, and the threshold decryptions asked for and answered — and it records nothing else. It holds no ciphertext body, no FHE secret key, and no decryption share; see state.go for the structurally-enforced invariant.
The FHE runtime itself is github.com/luxfi/chains/mpcvm/fhe, and F reuses it rather than restating it: F's records embed the runtime's types, and F's public parameters come from the runtime's threshold configuration. What F does NOT reuse is the runtime's Registry, and the reason is consensus. The Registry stamps records with time.Now(), which is right for the off-chain daemon it was written for and wrong here: two validators replaying one block would store different bytes, so they would return different answers to the same query and neither would be wrong to. So F owns its persistence, and every timestamp it writes comes from the accepting block.
F COMMITS NO STATE ROOT, so nothing in consensus would catch that divergence if it happened. What stands in its place is replay_test.go, which replays a chain onto independently-built nodes running different clocks and requires their databases to be byte-identical. Putting a root in consensus needs a state layer per in-flight block, which this VM does not have — see LLM.md, where the same missing layer is why a child of a verified-but-unaccepted block cannot be verified.
Mutating operations take effect only through fee-settled consensus blocks (block.go), priced by a per-scheme 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 SupportedScheme(scheme string) bool
- func ValidateCommittee(c []fhe.CommitteeMember, threshold int, publicKey []byte) error
- type AdvancePayload
- type Attestation
- type AttestationView
- 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 CiphertextRecord
- type CiphertextView
- type Config
- type DecryptRecord
- type DecryptView
- type EpochRecord
- type Factory
- type FeeScheduleArgs
- type FeeScheduleEntry
- type FeeScheduleReply
- type FulfillPayload
- type Genesis
- type GetCiphertextArgs
- type GetCiphertextReply
- type GetDecryptArgs
- type GetDecryptReply
- type GetPermitArgs
- type GetPermitReply
- type GrantPayload
- type HealthArgs
- type HealthReply
- type ListCiphertextsArgs
- type ListCiphertextsReply
- type PermitRecord
- type PermitView
- type RegisterPayload
- type RequestPayload
- 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) GetCiphertext(r *http.Request, args *GetCiphertextArgs, reply *GetCiphertextReply) error
- func (s *Service) GetCommittee(r *http.Request, args *fhe.GetCommitteeArgs, reply *fhe.GetCommitteeReply) error
- func (s *Service) GetDecrypt(r *http.Request, args *GetDecryptArgs, reply *GetDecryptReply) error
- func (s *Service) GetPermit(r *http.Request, args *GetPermitArgs, reply *GetPermitReply) error
- func (s *Service) GetPublicParams(r *http.Request, args *fhe.GetPublicParamsArgs, ...) error
- func (s *Service) Health(r *http.Request, args *HealthArgs, reply *HealthReply) error
- func (s *Service) ListCiphertexts(r *http.Request, args *ListCiphertextsArgs, reply *ListCiphertextsReply) error
- func (s *Service) SubmitTransaction(r *http.Request, args *SubmitTransactionArgs, reply *SubmitTransactionReply) error
- 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) Ciphertext(handle [32]byte) (*CiphertextRecord, bool)
- func (vm *VM) Ciphertexts() []*CiphertextRecord
- 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) CurrentEpoch() uint64
- func (vm *VM) Decrypt(id [32]byte) (*DecryptRecord, bool)
- func (vm *VM) Disconnected(ctx context.Context, nodeID ids.NodeID) error
- func (vm *VM) Epoch(n uint64) (*EpochRecord, bool)
- 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) 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) Permit(id [32]byte) (*PermitRecord, bool)
- 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" )
Permit lifecycle states. A permit is the only revocable thing on F: a registration is a fact about a ciphertext that exists, and a fact does not stop being true, whereas the authority to act on it can be withdrawn at any time. Access is therefore controlled entirely by granting and revoking permits, and there is no second place to look.
const ( TxRegisterCiphertext uint8 = 1 // record a ciphertext's PUBLIC handle + metadata TxGrantPermit uint8 = 2 // owner grants a capability over a handle TxRevokePermit uint8 = 3 // owner withdraws a capability it granted TxRequestDecrypt uint8 = 4 // permitted grantee asks the committee to decrypt TxFulfillDecrypt uint8 = 5 // committee member attests the PUBLIC result TxAdvanceEpoch uint8 = 6 // committee installs its successor )
Transaction types. Each is a MUTATING operation that may only take effect through a fee-settled consensus block — never through a synchronous RPC. Together they are the whole life of a confidential value on F: it is registered, capabilities over it are granted and revoked, its decryption is requested, and the committee answers; the committee that answers is itself rotated by the sixth.
const ( // MaxPayload bounds an operation's encoding. It is set by the largest // legitimate payload — a MaxCommittee-member epoch proposal, whose members // each carry an ML-DSA-65 public key — with room to spare. MaxPayload = 128 * 1024 // MaxScheme bounds the scheme name. Scheme names are short labels // ("ckks-n14"); anything longer is a channel, not a name. MaxScheme = 32 // MaxCommittee bounds a threshold committee. It bounds the epoch payload, // and with it the public-key parsing an UNAUTHENTICATED transaction can // demand before its own signature is checked. MaxCommittee = 32 // MaxCiphertextSize bounds the off-chain body a registration may describe. // The body is not stored here, but a size nobody could ever serve describes // nothing. MaxCiphertextSize = 1 << 30 )
Size bounds. Every one of these is a byte channel onto a chain that keeps what it is given, so each is bounded before anything is decoded and priced once it is.
const ( // Version of the F-Chain VM. Version = "1.0.0" // VMName is the human-readable name of the F-Chain VM. VMName = "fhevm" // Database namespaces. Records are JSON; balances live under the fee // ledger's own namespace (github.com/luxfi/chains/fee). CiphertextPrefix = "ct:" PermitPrefix = "pm:" DecryptPrefix = "dr:" EpochPrefix = "ep:" BlockPrefix = "block:" // MaxMempool bounds the queue. Admission is open to anyone who can pay, so // without a bound the queue is whatever an adversary chooses to make it. MaxMempool = 4096 )
const DefaultRequestWindow = int64(3600)
DefaultRequestWindow is how long a decryption request stays answerable when the requester names no expiry. A request that no committee can still answer is dead weight in state, and an unbounded one would be answerable by a future committee that never saw the permit that authorized it.
const GasPerByte = fee.Gas(16)
GasPerByte prices the bytes a transaction puts on the chain FOREVER: its payload and its scheme, the two fields whose length the payer chooses. It follows Ethereum's non-zero calldata rate for the same reason — storage is the cost a base fee cannot express — and it is what stops a ciphertext body riding onto F for the price of the handle that was supposed to replace it. The fixed part of a transaction (header, public key, signature) is bounded by construction and is covered by the operation's base cost.
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 per-operation settlement with the pre-existing admission floor. gas_test.go asserts that relationship for every (operation, scheme) pair so the two fee surfaces can never silently drift apart.
const MaxBlockSize = 2 << 20 // 2 MiB
MaxBlockSize bounds a block on the wire. Without it a peer decides how much this node parses, hashes and allocates before anything about the block has been checked: an 8 MB message carrying 1,524 transactions parsed to completion, because MaxBlockTxs was applied by Verify and Verify runs after the parse. Both bounds belong here, at the first byte, and neither implies the other — this one bounds the bytes read, MaxBlockTxs bounds the signatures verified, and a small block can still declare a great many tiny transactions.
const MaxBlockTxs = 1024
MaxBlockTxs bounds how many transactions one block carries. Without it a proposer's block size is whatever the mempool happens to hold.
const MaxFutureSkew = 60 * time.Second
MaxFutureSkew is how far ahead of the verifying node's clock a block's timestamp may be. Chain time drives every expiry F enforces, so without a cap a proposer stamping year 36812 would expire every permit and every pending request at once.
Variables ¶
var ( // ErrNotOnTip refuses a block that does not extend the chain: one whose // parent is neither the accepted tip nor a block verified above it. Such a // block is well formed and still unusable — accepting one rewinds the chain // to its parent's height. ErrNotOnTip = errors.New("fhevm: block does not extend the accepted tip") ErrInvalidBlock = errors.New("fhevm: malformed block") ErrMempoolFull = errors.New("fhevm: mempool is full") ErrInvalidTxType = errors.New("fhevm: invalid transaction type") ErrInvalidPayload = errors.New("fhevm: invalid transaction payload") ErrUnknownScheme = errors.New("fhevm: unsupported FHE scheme") ErrInvalidThreshold = errors.New("fhevm: invalid threshold (need 0 < t <= n)") ErrInvalidCommittee = errors.New("fhevm: invalid committee") ErrHandleMismatch = errors.New("fhevm: subject does not match its payload") ErrUnsignedTx = errors.New("fhevm: transaction missing payer auth/signature") ErrPayerMismatch = errors.New("fhevm: payer does not match auth public key") ErrBadSignature = errors.New("fhevm: invalid payer signature") ErrCiphertextExists = errors.New("fhevm: ciphertext already registered") ErrCiphertextNotFound = errors.New("fhevm: ciphertext not found") ErrPermitNotFound = errors.New("fhevm: permit not found") ErrPermitRevoked = errors.New("fhevm: permit is revoked") ErrPermitExpired = errors.New("fhevm: permit expired") ErrPermitInvalid = errors.New("fhevm: permit does not authorize this operation") ErrRequestNotFound = errors.New("fhevm: decrypt request not found") ErrRequestClosed = errors.New("fhevm: decrypt request already answered") ErrRequestExpired = errors.New("fhevm: decrypt request expired") ErrEpochNotFound = errors.New("fhevm: epoch not found") ErrEpochMismatch = errors.New("fhevm: epoch is not the next one") ErrNotCommittee = errors.New("fhevm: payer is not a committee member") // 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("fhevm: bad or replayed nonce") // ErrDuplicateEffect rejects a second transaction that would bring about an // effect another transaction in flight already claims. See // Transaction.effect. ErrDuplicateEffect = errors.New("fhevm: effect already claimed by a pending transaction") )
Sentinel errors. Every one denies an operation — the package fails secure.
var VMID = constants.FHEVMID
VMID identifies F-Chain: coordination of confidential compute — ciphertext handles, access permits, and threshold decryption (LP-8200, LP-167). It is constants.FHEVMID and nothing else.
A vmID is an immutable one-way door: it is baked into the CreateChainTx at genesis, it is the plugin binary's filename, and it is what the P-Chain stores forever. Every declaration of it must agree, so there is exactly one — this alias — and it points at the single source of truth in luxfi/constants, which node/node/vms.go already lists in OptionalVMs under the plugin name "fhevm".
Functions ¶
func FeeFor ¶
func FeeFor(tx *Transaction) (uint64, error)
FeeFor returns the nLUX fee a transaction settles: GasFor(tx) * GasPrice.
func GasFor ¶
func GasFor(tx *Transaction) (fee.Gas, error)
GasFor returns the metered gas for a transaction, pricing by operation and — for committee-dispatching operations — by scheme. It fails closed on an unknown operation type or an unknown/missing scheme for an operation that requires one.
func MinScheduledFee ¶
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 SupportedScheme ¶
SupportedScheme reports whether scheme is priced (and therefore accepted) by the F-Chain gas schedule.
func ValidateCommittee ¶
func ValidateCommittee(c []fhe.CommitteeMember, threshold int, publicKey []byte) error
ValidateCommittee checks a committee is installable: non-empty, canonically ordered by node ID, free of duplicates, with a real threshold and with every member carrying a parseable ML-DSA-65 public key. The last check is what stops F being wedged by an epoch whose members can never sign an attestation — the committee that cannot speak can never be replaced either. Genesis and TxAdvanceEpoch both go through here, so the two can never disagree.
Types ¶
type AdvancePayload ¶
type AdvancePayload struct {
Epoch uint64 `json:"epoch"`
Committee []fhe.CommitteeMember `json:"committee"`
Threshold int `json:"threshold"`
PublicKey []byte `json:"publicKey"`
}
AdvancePayload proposes the next epoch's committee and the network public key it jointly generated. Every approving member sends the identical proposal; the epoch installs when Threshold of the CURRENT committee have.
type Attestation ¶
Attestation is one committee member's vote for one 32-byte value. It backs both of F's threshold decisions — which plaintext handle a decryption produced, and which committee the next epoch has — because both are the same question: did Threshold distinct members say the same thing?
type AttestationView ¶
AttestationView names one committee member and the value it attested.
type BalanceArgs ¶
type BalanceArgs struct {
Address string `json:"address"`
}
BalanceArgs selects an account by hex address.
type BalanceReply ¶
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 an F-Chain block: an ordered batch of fee-settled confidential- compute 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. Its transactions were never removed from the mempool — BuildBlock selects from the mempool rather than draining it — so there is nothing to give back and nothing that can be lost by an engine that drops a block without rejecting it.
func (*Block) Verify ¶
Verify checks the block can be accepted WITHOUT mutating state: it sits correctly on its parent in height and time, and every transaction is well-formed, authenticated, correctly ordered and paid for. A block that fails any check is never accepted (fail closed); verifying a block never moves funds.
Verify does NOT decide authorization. That verdict depends on state earlier transactions in the same block may change, so a block-time verdict can differ from the application-time one — and a block every validator certifies and no validator can apply halts the chain. Authorization is decided once, in Accept, where failing it reverts the one transaction instead of the block.
type CiphertextRecord ¶
type CiphertextRecord struct {
fhe.CiphertextMeta // Handle, Owner, Type, Level, Epoch, RegisteredAt, Size, ChainID
Scheme string `json:"scheme"` // FHE scheme + ring dimension (drives gas)
Digest [32]byte `json:"digest"` // hash of the off-chain ciphertext body
}
CiphertextRecord is F's record of one registered encrypted value. The body it describes is off-chain; Digest binds this record to it, and Handle — derived from Digest and Scheme — is the name every other operation and every off-chain consumer uses to refer to it.
type CiphertextView ¶
type CiphertextView struct {
Handle string `json:"handle"`
Owner string `json:"owner"`
Scheme string `json:"scheme"`
Digest string `json:"digest"`
Type uint8 `json:"type"`
Level int `json:"level"`
Epoch uint64 `json:"epoch"`
Size uint32 `json:"size"`
RegisteredAt int64 `json:"registeredAt"`
ChainID string `json:"chainId"`
}
CiphertextView is the PUBLIC view of a registered encrypted value. It carries the digest of the ciphertext body so a client can check a body it fetched from off-chain storage; it does not carry the body, because F never has it.
type Config ¶
type Config struct {
NetworkID uint32 `json:"networkId"`
}
Config is the F-Chain VM's chain configuration, parsed from the node's per-chain config bytes. It carries only what cannot be derived: the network this chain belongs to.
type DecryptRecord ¶
type DecryptRecord struct {
fhe.DecryptRequest // RequestID, CiphertextHandle, Requester, Callback, ..., Status, ResultHandle
PermitID [32]byte `json:"permitId"`
Attestations []Attestation `json:"attestations"`
}
DecryptRecord is a threshold-decryption request and the committee's answer to it. F does not decrypt: the committee combines its shares off-chain and each member ATTESTS the resulting public handle here. The request completes when Threshold distinct members attest the SAME result, which is why Attestations is a list of (member, result) pairs and not a single field — a lone member posting a wrong result buys nothing but its own burnt fee, and cannot stall the honest majority.
type DecryptView ¶
type DecryptView struct {
RequestID string `json:"requestId"`
Handle string `json:"handle"`
Requester string `json:"requester"`
PermitID string `json:"permitId"`
Callback string `json:"callback"`
Selector string `json:"selector"`
Epoch uint64 `json:"epoch"`
Status string `json:"status"`
ResultHandle string `json:"resultHandle,omitempty"`
Attestations []AttestationView `json:"attestations"`
Threshold int `json:"threshold"`
Expiry int64 `json:"expiry"`
CreatedAt int64 `json:"createdAt"`
CompletedAt int64 `json:"completedAt,omitempty"`
SourceChain string `json:"sourceChain"`
}
DecryptView is the PUBLIC view of a threshold-decryption request. It has no plaintext field: the plaintext goes to the requester's callback off-chain, and F records only the handle the committee agreed the decryption produced.
type EpochRecord ¶
type EpochRecord struct {
fhe.EpochInfo // Epoch, StartTime, EndTime, Committee, Threshold, PublicKey, Status
Attestations []Attestation `json:"attestations"` // approvals of the NEXT epoch, tallied here
}
EpochRecord is the committee that holds the FHE key shares for one epoch, together with the network public key they jointly generated. Epoch 0 comes from genesis; every later epoch is installed by TxAdvanceEpoch once Threshold members of the CURRENT committee attest the same successor.
type FeeScheduleEntry ¶
type FeeScheduleEntry struct {
Operation string `json:"operation"`
Scheme string `json:"scheme"`
Gas uint64 `json:"gas"`
FeeNLUX uint64 `json:"feeNLux"`
}
FeeScheduleEntry prices one (operation, scheme) pair.
type FeeScheduleReply ¶
type FeeScheduleReply struct {
GasPrice uint64 `json:"gasPriceNLuxPerGas"`
Entries []FeeScheduleEntry `json:"entries"`
}
FeeScheduleReply returns the per-scheme gas/fee schedule and the price.
type FulfillPayload ¶
type FulfillPayload struct {
Result [32]byte `json:"result"`
}
FulfillPayload is one committee member's attestation of the PUBLIC handle a threshold decryption produced. The plaintext itself is delivered off-chain to the callback; F records only which handle the committee agreed on.
type Genesis ¶
type Genesis struct {
Version int `json:"version"`
Message string `json:"message"`
Timestamp int64 `json:"timestamp"`
Alloc map[string]uint64 `json:"alloc"`
Committee []fhe.CommitteeMember `json:"committee"`
Threshold int `json:"threshold"`
PublicKey []byte `json:"publicKey"`
}
Genesis is the F-Chain genesis: a funding allocation (address hex -> nLUX) and the epoch-0 threshold committee. There is no ciphertext in genesis — ciphertexts are registered through consensus transactions — so genesis carries nothing encrypted.
type GetCiphertextArgs ¶
type GetCiphertextArgs struct {
Handle string `json:"handle"` // hex-encoded 32 bytes
}
GetCiphertextArgs selects a ciphertext by handle.
type GetCiphertextReply ¶
type GetCiphertextReply struct {
Ciphertext CiphertextView `json:"ciphertext"`
}
GetCiphertextReply returns the public ciphertext view.
type GetDecryptArgs ¶
type GetDecryptArgs struct {
RequestID string `json:"requestId"` // hex-encoded 32 bytes
}
GetDecryptArgs selects a decryption request by ID.
type GetDecryptReply ¶
type GetDecryptReply struct {
Request DecryptView `json:"request"`
}
GetDecryptReply returns the public request view.
type GetPermitArgs ¶
type GetPermitArgs struct {
PermitID string `json:"permitId"` // hex-encoded 32 bytes
}
GetPermitArgs selects a permit by ID.
type GetPermitReply ¶
type GetPermitReply struct {
Permit PermitView `json:"permit"`
}
GetPermitReply returns the public permit view.
type GrantPayload ¶
type GrantPayload struct {
Grantee fee.Account `json:"grantee"`
Operations uint32 `json:"operations"`
Expiry int64 `json:"expiry"` // unix seconds; 0 = no expiry
}
GrantPayload grants a capability over one handle to one grantee until Expiry. Operations is a bitmask of fhe.PermitOp* values.
type HealthReply ¶
type HealthReply struct {
Healthy bool `json:"healthy"`
Details map[string]string `json:"details"`
}
HealthReply reports VM health.
type ListCiphertextsArgs ¶
ListCiphertextsArgs filters the ciphertext listing.
type ListCiphertextsReply ¶
type ListCiphertextsReply struct {
Ciphertexts []CiphertextView `json:"ciphertexts"`
Total int `json:"total"`
}
ListCiphertextsReply returns matching ciphertext views.
type PermitRecord ¶
type PermitRecord struct {
fhe.Permit // PermitID, Handle, Grantee, Grantor, Operations, Expiry, CreatedAt, Attestation, ChainID
Status string `json:"status"`
}
PermitRecord is a capability: the grantor lets the grantee perform a set of operations on one handle until Expiry. It is the only thing that authorizes a decryption request, so it is checked at admission, in consensus, and again at application.
type PermitView ¶
type PermitView struct {
PermitID string `json:"permitId"`
Handle string `json:"handle"`
Grantor string `json:"grantor"`
Grantee string `json:"grantee"`
Operations uint32 `json:"operations"`
Expiry int64 `json:"expiry"`
Status string `json:"status"`
CreatedAt int64 `json:"createdAt"`
ChainID string `json:"chainId"`
}
PermitView is the PUBLIC view of a capability grant.
type RegisterPayload ¶
type RegisterPayload struct {
Digest [32]byte `json:"digest"`
Type uint8 `json:"type"` // FHE plaintext type tag (bool, uint8, …)
Level int `json:"level"` // remaining multiplicative level
Size uint32 `json:"size"` // ciphertext body size in bytes
}
RegisterPayload records an encrypted value's PUBLIC coordinates. Digest is the hash of the ciphertext BODY, which lives in off-chain storage — F stores the hash so anyone can check a fetched body against the chain, and never the body itself.
type RequestPayload ¶
type RequestPayload struct {
PermitID [32]byte `json:"permitId"`
Callback [20]byte `json:"callback"`
Selector [4]byte `json:"selector"`
Expiry int64 `json:"expiry"` // unix seconds; 0 = the chain's default window
}
RequestPayload asks the committee to threshold-decrypt a handle under the authority of a permit the requester holds. Callback and Selector name where the answer should be delivered on the source chain.
type RevokePayload ¶
type RevokePayload struct {
Reason string `json:"reason"`
}
RevokePayload withdraws a permit.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service is the F-Chain JSON-RPC surface. Mutating operations are submitted as CLIENT-SIGNED transactions and take effect only through fee-settled consensus blocks. Everything else is a read-only query of PUBLIC state. There is no endpoint that decrypts, none that returns a ciphertext body, and no "fee" integer in any request — a fee is never an unbacked number a caller writes down, it is gas metered and burned from the payer's on-chain balance inside consensus.
Two of the methods report the FHE RUNTIME's configuration rather than F's ledger — the public parameters and the seated committee — and those answer in the runtime's own reply types (github.com/luxfi/chains/mpcvm/fhe), so a client that understands the runtime understands F. The rest describe F's ledger and answer in F's own views. That is the whole rule: runtime types for runtime facts, F's views for F's records.
func (*Service) Balance ¶
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 ¶
func (s *Service) FeeSchedule(r *http.Request, args *FeeScheduleArgs, reply *FeeScheduleReply) error
FeeSchedule returns the chain's per-operation, per-scheme fee schedule so clients can compute the exact burn before submitting a transaction.
func (*Service) GetCiphertext ¶
func (s *Service) GetCiphertext(r *http.Request, args *GetCiphertextArgs, reply *GetCiphertextReply) error
GetCiphertext returns a ciphertext record by handle.
func (*Service) GetCommittee ¶
func (s *Service) GetCommittee(r *http.Request, args *fhe.GetCommitteeArgs, reply *fhe.GetCommitteeReply) error
GetCommittee returns the threshold committee for an epoch (the seated one by default). These are the members whose attestations answer a decryption request and install the next epoch.
func (*Service) GetDecrypt ¶
func (s *Service) GetDecrypt(r *http.Request, args *GetDecryptArgs, reply *GetDecryptReply) error
GetDecrypt returns a decryption request and the committee's answer so far.
func (*Service) GetPermit ¶
func (s *Service) GetPermit(r *http.Request, args *GetPermitArgs, reply *GetPermitReply) error
GetPermit returns a permit record by ID.
func (*Service) GetPublicParams ¶
func (s *Service) GetPublicParams(r *http.Request, args *fhe.GetPublicParamsArgs, reply *fhe.GetPublicParamsReply) error
GetPublicParams returns the FHE parameters this network encrypts under, together with the seated epoch's threshold and network public key. The parameters come from the runtime's own threshold configuration, so a client encrypting for F and a node evaluating for F agree by construction.
func (*Service) Health ¶
func (s *Service) Health(r *http.Request, args *HealthArgs, reply *HealthReply) error
Health reports VM health.
func (*Service) ListCiphertexts ¶
func (s *Service) ListCiphertexts(r *http.Request, args *ListCiphertextsArgs, reply *ListCiphertextsReply) error
ListCiphertexts lists registered ciphertexts, optionally filtered.
func (*Service) SubmitTransaction ¶
func (s *Service) SubmitTransaction(r *http.Request, args *SubmitTransactionArgs, reply *SubmitTransactionReply) error
SubmitTransaction parses, authenticates, admission-checks, and enqueues a signed transaction.
type SubmitTransactionArgs ¶
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; F only verifies the signature and settles the fee.
type SubmitTransactionReply ¶
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
Scheme string // FHE scheme + ring dimension (drives per-scheme gas); "" for scheme-independent ops
Payer fee.Account // fee payer + authorization subject (public address)
Subject [32]byte // the object this operation acts on or creates (see below)
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 an F-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 ciphertext, plaintext, or a key share.
func ParseTransaction ¶
func ParseTransaction(data []byte) (*Transaction, error)
ParseTransaction decodes a transaction from its wire encoding: the leading signing object, then the appended Auth/Sig object. Canonical: rejects trailing bytes.
func (*Transaction) Apply ¶
func (tx *Transaction) Apply(vm *VM, now int64) (bool, error)
Apply is where authorization is DECIDED and where state changes. It runs inside block.Accept, writing through the VM's versiondb so an effect commits atomically with the fee burn. now is the accepting block's unix time — every timestamp F stores comes from here, never from a validator's clock.
It reports whether the transaction took effect. A transaction that fails checkAuth REVERTS: applied is false, err is nil, state is untouched, and the caller still burns the fee and consumes the nonce. This is the only place the verdict is reached, so every validator reaches it from the same committed state in the same order. Deciding it earlier, in Verify, would let a block pass consensus on state that an earlier transaction in the same block then changes — and a block every validator certifies and no validator can apply halts the chain.
A non-nil err means the write itself failed, which no validator can proceed past; block.Accept rolls the whole block back.
func (*Transaction) Bytes ¶
func (tx *Transaction) Bytes() []byte
Bytes is the full wire encoding: the content object followed by an appended zap object carrying 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 ¶
func (tx *Transaction) SigningBytes(chain ids.ID) []byte
SigningBytes is the preimage the payer signs: the transaction's content bound to the chain it is meant for. Clients build it with the chain id they are transacting on; a node verifies with its own, so the two agree only on the chain the payer chose.
func (*Transaction) SyntacticVerify ¶
func (tx *Transaction) SyntacticVerify() error
SyntacticVerify checks the transaction is well-formed and priceable, without any state. It rejects unknown types, unpriceable schemes, undecodable or out-of-range payloads, and any Subject that disagrees with what the payload derives — all fail-closed.
type VM ¶
type VM struct {
// contains filtered or unexported fields
}
VM implements the F-Chain Virtual Machine.
Every field below is either runtime plumbing or a cache of PUBLIC records (CiphertextRecord / PermitRecord / DecryptRecord / EpochRecord). There is deliberately no ciphertext store, no key-share store, and no FHE evaluation session: F coordinates confidential compute, it does not perform it.
func (*VM) BuildBlock ¶
BuildBlock proposes a block from the mempool. It SELECTS rather than drains: a transaction stays queued until the block carrying it is accepted, so an engine that discards a proposal — which it may do without ever calling Reject — cannot take the queue with it.
Selection runs the same batch.admit that Verify runs, and simply skips what does not fit. A proposer therefore cannot build a block its own Verify would reject, and one unfit transaction no longer takes the rest down with it.
func (*VM) Ciphertext ¶
func (vm *VM) Ciphertext(handle [32]byte) (*CiphertextRecord, bool)
Ciphertext returns a copy of a ciphertext record.
func (*VM) Ciphertexts ¶
func (vm *VM) Ciphertexts() []*CiphertextRecord
Ciphertexts returns copies of all ciphertext records.
func (*VM) CreateHandlers ¶
func (*VM) CreateStaticHandlers ¶
func (*VM) CurrentEpoch ¶
CurrentEpoch returns the sitting epoch number.
func (*VM) Decrypt ¶
func (vm *VM) Decrypt(id [32]byte) (*DecryptRecord, bool)
Decrypt returns a copy of a decryption request record.
func (*VM) Epoch ¶
func (vm *VM) Epoch(n uint64) (*EpochRecord, bool)
Epoch returns a copy of an epoch record.
func (*VM) FeePolicy ¶
FeePolicy exposes the chain's declared admission policy for diagnostics and the boot-time Validate gate.
func (*VM) GetBlockIDAtHeight ¶
GetBlockIDAtHeight answers from the height index Accept writes in the same commit as the block itself, so the index cannot name a block the chain did not accept.
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) Permit ¶
func (vm *VM) Permit(id [32]byte) (*PermitRecord, bool)
Permit returns a copy of a permit record.
func (*VM) Shutdown ¶
Shutdown stops the VM. There is no secret material to zero — by construction the VM never held any.
func (*VM) SubmitTx ¶
func (vm *VM) SubmitTx(tx *Transaction) (ids.ID, error)
SubmitTx admits a transaction to this node's mempool. Admission is a FILTER, not a consensus rule: it refuses what this node can already tell will not work, so the queue stays useful. The rules consensus actually enforces live in batch.admit, and the fee is SETTLED later, in block Accept — never here.
The nonce rule is the same one consensus applies, counted over what is already queued. It used to be the looser "greater than the last committed one", which let a payer queue a gap: admission took it, Verify refused the block for it, and since a Verify-failed block is dropped rather than rejected, the queue behind it went with it.