Files
zeekay 7cf87b230b node-unified is the node
The module already called itself github.com/luxfi/node while containing no node
in Go: cmd/luxd was twenty-one lines that printed the size of a few types, and
the Go column of the matrix measured a VM plugin. A repo that fetches the thing
it claims to be has not replaced it, so the Go sources move in — 1515 files,
the daemon and everything under it — and the build reaches outside this module
for nothing.

Rust and C++ sit beside it unchanged and are still measured against it by the
differential. That is the point of one repo: the reference implementation and
the two ports are the same checkout, so parity is a thing you can run rather
than a thing you assert.

Verified: builds, and the closure carries no lux-private — checked at build time
rather than believed. The daemon starts twelve chains on a local network
(P X C Q Z A B G K M F, plus D through its plugin) and reports healthy.
2026-09-07 16:15:25 -07:00

104 lines
2.7 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package genesis
// Native ZAP wire for the xsvm genesis: the struct IS the wire. One zap object;
// the allocations are a fixed-stride list (28-byte records: 20-byte address +
// u64 balance). There is no codec, no version prefix, no slot map.
//
// Object fixed section (offsets object-relative, little-endian):
//
// Timestamp i64 @ 0
// Allocations 8B @ 8 fixed-stride list ptr (stride 28)
import (
"encoding/binary"
"github.com/luxfi/crypto/hash"
"github.com/luxfi/ids"
"github.com/luxfi/node/vms/example/xsvm/block"
"github.com/luxfi/zap"
)
const (
offGenesisTimestamp = 0
offGenesisAllocs = 8
sizeGenesis = 16
// Allocation record: address 20B @0, balance u64 @20.
allocAddr = 0
allocBalance = 20
allocStride = 28
genShortLen = 20
)
type Genesis struct {
Timestamp int64 `json:"timestamp"`
Allocations []Allocation `json:"allocations"`
}
type Allocation struct {
Address ids.ShortID `json:"address"`
Balance uint64 `json:"balance"`
}
// Marshal encodes the genesis as one native ZAP object.
func (g *Genesis) Marshal() ([]byte, error) {
b := zap.NewBuilder(zap.HeaderSize + sizeGenesis + len(g.Allocations)*allocStride)
var allocOff, allocCount int
if len(g.Allocations) > 0 {
lb := b.StartList(allocStride)
rec := make([]byte, allocStride)
for i := range g.Allocations {
copy(rec[allocAddr:], g.Allocations[i].Address[:])
binary.LittleEndian.PutUint64(rec[allocBalance:], g.Allocations[i].Balance)
lb.AddBytes(rec)
}
// AddBytes counts bytes, not elements — use the real element count.
allocOff, _ = lb.Finish()
allocCount = len(g.Allocations)
}
ob := b.StartObject(sizeGenesis)
ob.SetInt64(offGenesisTimestamp, g.Timestamp)
ob.SetList(offGenesisAllocs, allocOff, allocCount)
ob.FinishAsRoot()
return b.Finish(), nil
}
func Parse(bytes []byte) (*Genesis, error) {
msg, err := zap.Parse(bytes)
if err != nil {
return nil, err
}
obj := msg.Root()
g := &Genesis{
Timestamp: obj.Int64(offGenesisTimestamp),
}
arr := obj.ListStride(offGenesisAllocs, allocStride)
n := arr.Len()
if n > 0 {
g.Allocations = make([]Allocation, n)
for i := 0; i < n; i++ {
e := arr.Object(i, allocStride)
copy(g.Allocations[i].Address[:], e.BytesFixedSlice(allocAddr, genShortLen))
g.Allocations[i].Balance = e.Uint64(allocBalance)
}
}
return g, nil
}
func Block(genesis *Genesis) (*block.Stateless, error) {
bytes, err := genesis.Marshal()
if err != nil {
return nil, err
}
return &block.Stateless{
ParentID: hash.ComputeHash256Array(bytes),
Timestamp: genesis.Timestamp,
}, nil
}