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

192 lines
4.3 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package chain
import (
"context"
"errors"
"time"
"github.com/luxfi/database"
"github.com/luxfi/database/versiondb"
"github.com/luxfi/ids"
"github.com/luxfi/math/set"
"github.com/luxfi/node/vms/example/xsvm/execute"
"github.com/luxfi/runtime"
xsblock "github.com/luxfi/node/vms/example/xsvm/block"
smblock "github.com/luxfi/vm/chain"
)
const maxClockSkew = 10 * time.Second
var (
_ Block = (*block)(nil)
errMissingParent = errors.New("missing parent block")
errMissingChild = errors.New("missing child block")
errParentNotVerified = errors.New("parent block has not been verified")
errFutureTimestamp = errors.New("future timestamp")
errTimestampBeforeParent = errors.New("timestamp before parent")
errWrongHeight = errors.New("wrong height")
)
type Block interface {
smblock.Block
smblock.WithVerifyRuntime
// Timestamp returns the block's timestamp
Timestamp() time.Time
// State intends to return the new chain state following this block's
// acceptance. The new chain state is built (but not persisted) following a
// block's verification to allow block's descendants verification before
// being accepted.
State() (database.Database, error)
}
type block struct {
*xsblock.Stateless
chain *chain
id ids.ID
bytes []byte
state *versiondb.Database
verifiedChildrenIDs set.Set[ids.ID]
}
func (b *block) ID() ids.ID {
return b.id
}
func (b *block) Parent() ids.ID {
return b.Stateless.ParentID
}
func (b *block) ParentID() ids.ID {
return b.Stateless.ParentID
}
func (b *block) Bytes() []byte {
return b.bytes
}
func (b *block) Height() uint64 {
return b.Stateless.Height
}
func (b *block) Timestamp() time.Time {
return b.Time()
}
func (b *block) Status() uint8 {
// Return processing status (implementation detail for consensus)
return 1
}
func (b *block) Verify(ctx context.Context) error {
return b.VerifyWithRuntime(ctx, nil)
}
func (b *block) Accept(context.Context) error {
if err := b.state.Commit(); err != nil {
return err
}
// Following this block's acceptance, make sure that it's direct children
// point to the base state, which now also contains this block's changes.
for childID := range b.verifiedChildrenIDs {
child, exists := b.chain.verifiedBlocks[childID]
if !exists {
return errMissingChild
}
if err := child.state.SetDatabase(b.chain.acceptedState); err != nil {
return err
}
}
b.chain.lastAcceptedID = b.id
delete(b.chain.verifiedBlocks, b.ParentID())
b.state = nil
return nil
}
func (b *block) Reject(context.Context) error {
delete(b.chain.verifiedBlocks, b.id)
b.state = nil
return nil
}
func (b *block) ShouldVerifyWithRuntime(context.Context) (bool, error) {
return execute.ExpectsContext(b.Stateless)
}
func (b *block) VerifyWithRuntime(ctx context.Context, blockContext *runtime.Runtime) error {
timestamp := b.Time()
if time.Until(timestamp) > maxClockSkew {
return errFutureTimestamp
}
// parent block must be verified or accepted
parent, exists := b.chain.verifiedBlocks[b.Stateless.ParentID]
if !exists {
return errMissingParent
}
if b.Stateless.Height != parent.Stateless.Height+1 {
return errWrongHeight
}
parentTimestamp := parent.Time()
if timestamp.Before(parentTimestamp) {
return errTimestampBeforeParent
}
parentState, err := parent.State()
if err != nil {
return err
}
// This block's state is a versionDB built on top of it's parent state. This
// block's changes are pushed atomically to the parent state when accepted.
blkState := versiondb.New(parentState)
err = execute.Block(
ctx,
b.chain.chainRuntime,
blkState,
false, // not bootstrapping - chainState is an interface, not a status enum
blockContext,
b.Stateless,
)
if err != nil {
return err
}
// Make sure to only state the state the first time we verify this block.
if b.state == nil {
b.state = blkState
parent.verifiedChildrenIDs.Add(b.id)
b.chain.verifiedBlocks[b.id] = b
}
return nil
}
func (b *block) State() (database.Database, error) {
if b.id == b.chain.lastAcceptedID {
return b.chain.acceptedState, nil
}
// If this block isn't processing, then the child should never have had
// verify called on it.
if b.state == nil {
return nil, errParentNotVerified
}
return b.state, nil
}