mirror of
https://github.com/luxfi/node.git
synced 2026-07-27 03:39:39 +00:00
Two node/bootstrap-layer fixes for a clean rolling validator upgrade. Consensus engine untouched (v1.35.5 boot-seed from v1.32.10 carried forward). [HIGH — correctness] info.isBootstrapped(C) tracks REAL state, not premature true. manager.IsBootstrapped(id) returned true the instant a chain merely EXISTED in m.chains (set right after createChain launched the async, possibly-stalling bootstrap goroutine) — so a C-Chain stalled at genesis (head 0x0) reported info.isBootstrapped(C)=true, masking the stall from any wait-for-healthy gate. Now keys on the SAME sb.Bootstrapped signal the readiness health check uses (m.Nets.IsChainBootstrapped), set only after runInitialSync reaches the named frontier and the VM goes to normal operation (head advanced, eth-RPC live). GetChains().Bootstrapped fixed identically. New per-chain query on nets.Net + chains.Nets (nil-safe). Regression test TestIsBootstrappedTracksRealConvergence. [MEDIUM — robustness] WIPE-path GetAncestors fetch hardened for ≥2 peers at genesis. Applying the proven avalanchego contract (studied in snowman/bootstrap + getter): (a) Ancestors buffers the whole sample and SKIPS empty batches, returning the first NON-EMPTY one — a size-1 channel let a fast empty reply from a genesis peer win the race and starve a peer that actually held the ancestry; (b) sampleAncestorBeacons PREFERS beacons the frontier round found genuinely ahead (they hold the ancestry) — ava's PeerTracker "ask a prover" bias sourced from the replies we already have, no separate tracker. Tests: TestNodeBootstrap_WipePath_MixedGenesisPeers_ObtainsAncestry, TestSampleAncestorBeacons_PrefersAheadBeacons. Build: main+chains+nets+service/info compile CGO_ENABLED=0 (ARC/Dockerfile path); full chains+nets suites green. Co-authored-by: Hanzo Dev <dev@hanzo.ai>
158 lines
3.6 KiB
Go
158 lines
3.6 KiB
Go
// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package version
|
|
|
|
import (
|
|
"github.com/go-json-experiment/json"
|
|
"strconv"
|
|
"time"
|
|
|
|
_ "embed"
|
|
)
|
|
|
|
const (
|
|
Client = "luxd"
|
|
// RPCChainVMProtocol should be bumped anytime changes are made which
|
|
// require the plugin vm to upgrade to latest node release to be
|
|
// compatible.
|
|
RPCChainVMProtocol uint = 42
|
|
)
|
|
|
|
// These variables are set at build time via ldflags from git tag:
|
|
//
|
|
// go build -ldflags "-X github.com/luxfi/node/version.VersionMajor=1 \
|
|
// -X github.com/luxfi/node/version.VersionMinor=22 \
|
|
// -X github.com/luxfi/node/version.VersionPatch=19"
|
|
//
|
|
// Build with scripts/build.sh to automatically inject version from git tags.
|
|
var (
|
|
VersionMajor = ""
|
|
VersionMinor = ""
|
|
VersionPatch = ""
|
|
)
|
|
|
|
// These are globals that describe network upgrades and node versions
|
|
var (
|
|
Current *Semantic
|
|
CurrentApp *Application
|
|
|
|
MinimumCompatibleVersion = &Application{
|
|
Name: Client,
|
|
Major: 1,
|
|
Minor: 13,
|
|
Patch: 0,
|
|
}
|
|
PrevMinimumCompatibleVersion = &Application{
|
|
Name: Client,
|
|
Major: 1,
|
|
Minor: 12,
|
|
Patch: 0,
|
|
}
|
|
|
|
CurrentDatabase = DatabaseVersion1_4_5
|
|
PrevDatabase = DatabaseVersion1_0_0
|
|
|
|
DatabaseVersion1_4_5 = &Semantic{
|
|
Major: 1,
|
|
Minor: 4,
|
|
Patch: 5,
|
|
}
|
|
DatabaseVersion1_0_0 = &Semantic{
|
|
Major: 1,
|
|
Minor: 0,
|
|
Patch: 0,
|
|
}
|
|
|
|
//go:embed compatibility.json
|
|
rpcChainVMProtocolCompatibilityBytes []byte
|
|
// RPCChainVMProtocolCompatibility maps RPCChainVMProtocol versions to the
|
|
// set of node versions that supported that version. This is not used
|
|
// by node, but is useful for downstream libraries.
|
|
RPCChainVMProtocolCompatibility map[uint][]*Semantic
|
|
)
|
|
|
|
// Default version for tests/development when not set via ldflags
|
|
// These should match the latest git tag
|
|
const (
|
|
defaultMajor = 1
|
|
defaultMinor = 32
|
|
defaultPatch = 11
|
|
)
|
|
|
|
func init() {
|
|
// Version is set via ldflags at build time from git tag
|
|
// If not set, use defaults (for tests and go run)
|
|
var major, minor, patch int
|
|
|
|
if VersionMajor != "" {
|
|
var err error
|
|
major, err = strconv.Atoi(VersionMajor)
|
|
if err != nil {
|
|
panic("invalid VersionMajor: " + VersionMajor)
|
|
}
|
|
} else {
|
|
major = defaultMajor
|
|
}
|
|
|
|
if VersionMinor != "" {
|
|
var err error
|
|
minor, err = strconv.Atoi(VersionMinor)
|
|
if err != nil {
|
|
panic("invalid VersionMinor: " + VersionMinor)
|
|
}
|
|
} else {
|
|
minor = defaultMinor
|
|
}
|
|
|
|
if VersionPatch != "" {
|
|
var err error
|
|
patch, err = strconv.Atoi(VersionPatch)
|
|
if err != nil {
|
|
panic("invalid VersionPatch: " + VersionPatch)
|
|
}
|
|
} else {
|
|
patch = defaultPatch
|
|
}
|
|
|
|
Current = &Semantic{
|
|
Major: major,
|
|
Minor: minor,
|
|
Patch: patch,
|
|
}
|
|
CurrentApp = &Application{
|
|
Name: Client,
|
|
Major: Current.Major,
|
|
Minor: Current.Minor,
|
|
Patch: Current.Patch,
|
|
}
|
|
|
|
// Parse RPC compatibility map
|
|
var parsedRPCChainVMCompatibility map[uint][]string
|
|
if err := json.Unmarshal(rpcChainVMProtocolCompatibilityBytes, &parsedRPCChainVMCompatibility); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
RPCChainVMProtocolCompatibility = make(map[uint][]*Semantic)
|
|
for rpcChainVMProtocol, versionStrings := range parsedRPCChainVMCompatibility {
|
|
versions := make([]*Semantic, len(versionStrings))
|
|
for i, versionString := range versionStrings {
|
|
version, err := Parse(versionString)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
versions[i] = version
|
|
}
|
|
RPCChainVMProtocolCompatibility[rpcChainVMProtocol] = versions
|
|
}
|
|
}
|
|
|
|
func GetCompatibility(minCompatibleTime time.Time) Compatibility {
|
|
return NewCompatibility(
|
|
CurrentApp,
|
|
MinimumCompatibleVersion,
|
|
minCompatibleTime,
|
|
PrevMinimumCompatibleVersion,
|
|
)
|
|
}
|