Documentation
¶
Overview ¶
Package bridgevmroot computes the bridgevm_state_root in native Go, byte-identical to the lux-private GPU bridgevm_transition kernel (ops/bridgevm/cuda/bridgevm_transition.cu + bridgevm_kernels_common.cuh) and every backend's CPU oracle. It is the native-Go authority the licensed GPU accelerator mirrors: the same five family leaf preimages, the same per-family skip predicates, the same ascending-i compacted-occupied ordering, the same RFC-6962 tagged binary Merkle fold for the five variable-length sub-roots, and the same fixed-shape keccak256 composition for the final bridgevm_state_root.
It is the symmetric peer of vms/xvm/state/xvmroot (xvm execution_root): same crypto, same combiner, same value-struct decoupling. Where xvmroot has three families (utxo / asset / tx), bridgevm has five (signer_set / liquidity / inbox / outbox / daily_limit).
The root is a pure function of the canonical leaf FIELD VALUES, not of any in-memory struct. So this package consumes the accelerator's state-snapshot layout directly — SignerLeaf, LiquidityLeaf, MessageLeaf, DailyLeaf mirror the GPU structs' hashed fields exactly, in the exact preimage order. The leaves are the POST-transition values (the GPU's K1 mutates signer status / resets daily limits before hashing); callers supply the already-mutated field values, exactly as the GPU hashes them.
The leaf/node/empty Merkle combiner lives in github.com/luxfi/crypto/merkle (RFC-6962: leaf=keccak256(0x00‖d), node=keccak256(0x01‖L‖R), lone-right promotion, empty=keccak256("")). The un-tagged keccak256 (Ethereum Keccak-256, 0x01 pad — NOT FIPS-202 SHA3, i.e. sha3.NewLegacyKeccak256) used for both the leaf-digest preimage and the bridgevm_state_root compose lives in github.com/luxfi/crypto/hash. Integers are little-endian, matching the kernel's absorb_u32 / absorb_u64.
CRITICAL: the active-bond aggregate is a FULL 128-bit value (BondLo + BondHi with carry) — the GPU was fixed (MED-1 / "FIX 4") to accumulate both limbs and commit BondHi into both the signer leaf and the compose preimage. This package matches that: it accumulates the full 128-bit sum and binds both BondLo and BondHi into the composed root. Dropping BondHi would diverge from the GPU.
Normative spec: lux-private/gpu-kernels/backends/common/lux_merkle_fold.hpp, ops/bridgevm/cuda/bridgevm_transition.cu, and the CPU oracle in backends/vulkan/tests/test_bridgevm_transition_kat.cpp. KAT parity is proven in bridgevmroot_test.go against the values all GPU backends + the CPU oracle produce.
Index ¶
- Constants
- func ActiveBond(signers []SignerLeaf) (bondLo, bondHi uint64, active uint32)
- func Compose(...) [Size]byte
- func DailyLimitRoot(entries []DailyLeaf) [Size]byte
- func InboxRoot(inbox []MessageLeaf) [Size]byte
- func LiquidityRoot(entries []LiquidityLeaf) [Size]byte
- func OutboxRoot(outbox []MessageLeaf) [Size]byte
- func SignerSetRoot(signers []SignerLeaf) [Size]byte
- func StateRoot(parentStateRoot [Size]byte, signers []SignerLeaf, liquidity []LiquidityLeaf, ...) (...)
- type DailyLeaf
- type LiquidityLeaf
- type MessageLeaf
- type SignerLeaf
Constants ¶
const ( SignerStatusActive uint32 = 0x1 SignerStatusJailed uint32 = 0x2 SignerStatusTombstoned uint32 = 0x4 SignerStatusPendingAdd uint32 = 0x8 SignerStatusPendingDrop uint32 = 0x10 SignerStatusExiting uint32 = 0x20 )
Signer status bits — match bridgevm_kernels_common.cuh kSignerStatus*. A signer is folded into signer_set_root iff Occupied != 0; the status bits below only affect the active-bond aggregate (active = Active set, Jailed clear, Tombstoned clear), never inclusion.
const Size = hash.KeccakSize
Size is the byte length of every root and element digest (a keccak256 output).
Variables ¶
This section is empty.
Functions ¶
func ActiveBond ¶
func ActiveBond(signers []SignerLeaf) (bondLo, bondHi uint64, active uint32)
ActiveBond returns the FULL 128-bit aggregate Σ(BondLo : BondHi) over active signers (Active set, Jailed clear, Tombstoned clear), as a (lo, hi) pair with carry, alongside the active-signer count. This is the GPU's post-FIX-4 accumulation: BondHi is carried, never dropped. Used by Compose and surfaced for callers that need the epoch counters. Occupied == 0 slots do not contribute.
func Compose ¶
func Compose( parentStateRoot, signerSetRoot, liquidityRoot, inboxRoot, outboxRoot, dailyLimitRoot [Size]byte, epoch, bondLo, bondHi uint64, active uint32, ) [Size]byte
Compose returns the bridgevm_state_root from the parent root, the five sub-roots, and the epoch counters, using the fixed-shape un-tagged keccak256 composition (this is NOT a Merkle node):
bridgevm_state_root = keccak256(
parentStateRoot ‖ signerSetRoot ‖ liquidityRoot ‖ inboxRoot ‖
outboxRoot ‖ dailyLimitRoot ‖ epoch_u64_le ‖ bondLo_u64_le ‖
bondHi_u64_le ‖ active_u32_le )
epoch is the finalized current epoch (target epoch on a closing round, else the unchanged current epoch). bondLo/bondHi are the full 128-bit active-bond aggregate; active is the active-signer count.
func DailyLimitRoot ¶
DailyLimitRoot is the tagged binary Merkle root over the active daily-limit entries' leaf digests, in ascending slot index. An entry with Status == 0 is skipped.
func InboxRoot ¶
func InboxRoot(inbox []MessageLeaf) [Size]byte
InboxRoot is the tagged binary Merkle root over the live inbox messages' leaf digests, in ascending slot index. A free slot (Status == 0 && MsgID all-zero) is skipped.
func LiquidityRoot ¶
func LiquidityRoot(entries []LiquidityLeaf) [Size]byte
LiquidityRoot is the tagged binary Merkle root over the active liquidity entries' leaf digests, in ascending slot index. An entry with Status == 0 is skipped.
func OutboxRoot ¶
func OutboxRoot(outbox []MessageLeaf) [Size]byte
OutboxRoot is the tagged binary Merkle root over the live outbox messages' leaf digests, in ascending slot index. A free slot (Status == 0 && MsgID all-zero) is skipped.
func SignerSetRoot ¶
func SignerSetRoot(signers []SignerLeaf) [Size]byte
SignerSetRoot is the tagged binary Merkle root over the occupied signers' leaf digests, in ascending slot index. A signer with Occupied == 0 is skipped. An empty occupied set yields keccak256("") (merkle.EmptyRoot).
func StateRoot ¶
func StateRoot( parentStateRoot [Size]byte, signers []SignerLeaf, liquidity []LiquidityLeaf, inbox []MessageLeaf, outbox []MessageLeaf, daily []DailyLeaf, epoch uint64, ) (stateRoot, signerSetRoot, liquidityRoot, inboxRoot, outboxRoot, dailyLimitRoot [Size]byte, bondLo, bondHi uint64, active uint32)
StateRoot computes the full bridgevm_state_root over the round's POST-transition state: the five sub-roots (signer_set, liquidity, inbox, outbox, daily_limit) folded as RFC-6962 tagged binary Merkle trees, the full 128-bit active-bond aggregate computed over the signer set, then composed with the parent state root and finalized epoch. It is byte-identical to lux_<backend>_bridgevm_transition.
epoch is the finalized current epoch the GPU writes into the compose preimage (target_epoch = desc.epoch + closing_flag, used as current_epoch on a closing round; otherwise the carried current_epoch). The caller resolves it from the round descriptor exactly as the kernel does.
Types ¶
type DailyLeaf ¶
type DailyLeaf struct {
AssetID uint32
Status uint32
DailyCapLo uint64
DailyCapHi uint64
UsedTodayLo uint64
UsedTodayHi uint64
}
DailyLeaf is one bridgevm daily-limit entry in the accelerator's state-snapshot layout, holding the POST-reset field values. Its fields are hashed, in this exact order, into the leaf preimage:
AssetID ‖ Status ‖ DailyCapLo ‖ DailyCapHi ‖ UsedTodayLo ‖ UsedTodayHi ‖ index (integers little-endian)
An entry with Status == 0 is skipped, matching the kernel's status-occupied check.
type LiquidityLeaf ¶
type LiquidityLeaf struct {
ProviderAddr [20]byte
AssetID uint32
Status uint32
AmountLo uint64
AmountHi uint64
FeeAccrualLo uint64
FeeAccrualHi uint64
}
LiquidityLeaf is one bridgevm liquidity entry in the accelerator's state-snapshot layout. Its fields are hashed, in this exact order, into the leaf preimage:
ProviderAddr[20] ‖ 0u32 ‖ AssetID ‖ Status ‖ AmountLo ‖ AmountHi ‖ FeeAccrualLo ‖ FeeAccrualHi ‖ index (integers little-endian)
An entry with Status == 0 is skipped, matching the kernel's status-occupied check. The 0u32 after ProviderAddr is the GPU struct's _pad_addr.
type MessageLeaf ¶
type MessageLeaf struct {
MsgID [32]byte
PayloadRoot [32]byte
Nonce uint64
SrcChain uint32
DstChain uint32
Kind uint32
Status uint32
AmountLo uint64
AmountHi uint64
}
MessageLeaf is one bridgevm message (inbox or outbox) in the accelerator's state-snapshot layout. Its fields are hashed, in this exact order, into the leaf preimage:
MsgID[32] ‖ PayloadRoot[32] ‖ Nonce ‖ SrcChain ‖ DstChain ‖ Kind ‖ Status ‖ AmountLo ‖ AmountHi ‖ index (integers little-endian)
A message that is FREE — Status == 0 AND MsgID is all-zero — is skipped, matching the kernel's free-slot predicate. (A nonzero MsgID OR a nonzero Status makes the slot live and folded.) The agg_signature, signers_bitmap, asset_id, signer_count and arrival_height fields of the GPU Message struct are NOT part of the leaf preimage and so are absent here.
type SignerLeaf ¶
type SignerLeaf struct {
SignerID uint64
LuxAddress [20]byte
BondLo uint64
BondHi uint64
OptInHeight uint64
ExitEpoch uint64
SignCount uint64
BLSPubkey [48]byte
CoronaPubkey [32]byte
MLDSAPubkey [32]byte
Status uint32
JailUntilEpoch uint32
SlashCount uint32
Occupied uint32
}
SignerLeaf is one bridgevm signer in the accelerator's state-snapshot layout, holding the POST-transition field values. Its fields are hashed, in this exact order, into the leaf preimage:
SignerID ‖ LuxAddress[20] ‖ 0u32 ‖ BondLo ‖ BondHi ‖ OptInHeight ‖ ExitEpoch ‖ SignCount ‖ BLSPubkey[48] ‖ CoronaPubkey[32] ‖ MLDSAPubkey[32] ‖ Status ‖ JailUntilEpoch ‖ SlashCount ‖ index (integers little-endian)
A signer with Occupied == 0 is skipped (not folded), exactly as the kernel skips unoccupied slots. The 0u32 after LuxAddress is the GPU struct's _pad_addr, committed as four zero bytes.