Files
node/vms/platformvm/state/metadata_validator.go
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

229 lines
6.0 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package state
import (
"time"
"github.com/luxfi/constants"
"github.com/luxfi/database"
"github.com/luxfi/ids"
"github.com/luxfi/math/set"
)
var _ validatorState = (*metadata)(nil)
type validatorMetadata struct {
UpDuration time.Duration
LastUpdated uint64 // Unix time in seconds
PotentialReward uint64
PotentialDelegateeReward uint64
StakerStartTime uint64
txID ids.ID
lastUpdated time.Time
}
// parseValidatorMetadata overlays metadata's persisted fields (native
// validatorMetadata wire) from bytes. Empty bytes means nothing was persisted
// for this staker — the caller pre-populates tx-derived defaults
// (StakerStartTime/LastUpdated), which are kept as-is. lastUpdated is always
// derived from the resulting LastUpdated.
func parseValidatorMetadata(bytes []byte, metadata *validatorMetadata) error {
if len(bytes) > 0 {
if err := unmarshalValidatorMetadata(bytes, metadata); err != nil {
return err
}
}
metadata.lastUpdated = time.Unix(int64(metadata.LastUpdated), 0)
return nil
}
type validatorState interface {
// LoadValidatorMetadata sets the [metadata] of [vdrID] on [netID].
// GetUptime and SetUptime will return an error if the [vdrID] and
// [netID] hasn't been loaded. This call will not result in a write to
// disk.
LoadValidatorMetadata(
vdrID ids.NodeID,
netID ids.ID,
metadata *validatorMetadata,
)
// GetUptime returns the current uptime measurements of [vdrID] on
// [netID].
GetUptime(
vdrID ids.NodeID,
netID ids.ID,
) (upDuration time.Duration, lastUpdated time.Time, err error)
// SetUptime updates the uptime measurements of [vdrID] on [netID].
// Unless these measurements are deleted first, the next call to
// WriteUptimes will write this update to disk.
SetUptime(
vdrID ids.NodeID,
netID ids.ID,
upDuration time.Duration,
lastUpdated time.Time,
) error
// GetDelegateeReward returns the current rewards accrued to [vdrID] on
// [netID].
GetDelegateeReward(
netID ids.ID,
vdrID ids.NodeID,
) (amount uint64, err error)
// SetDelegateeReward updates the rewards accrued to [vdrID] on [netID].
// Unless these measurements are deleted first, the next call to
// WriteUptimes will write this update to disk.
SetDelegateeReward(
netID ids.ID,
vdrID ids.NodeID,
amount uint64,
) error
// DeleteValidatorMetadata removes in-memory references to the metadata of
// [vdrID] on [netID]. If there were staged updates from a prior call to
// SetUptime or SetDelegateeReward, the updates will be dropped. This call
// will not result in a write to disk.
DeleteValidatorMetadata(vdrID ids.NodeID, netID ids.ID)
// WriteValidatorMetadata writes all staged updates from prior calls to
// SetUptime or SetDelegateeReward.
WriteValidatorMetadata(
dbPrimary database.KeyValueWriter,
dbNet database.KeyValueWriter,
) error
}
type metadata struct {
metadata map[ids.NodeID]map[ids.ID]*validatorMetadata // vdrID -> netID -> metadata
// updatedMetadata tracks the updates since WriteValidatorMetadata was last called
updatedMetadata map[ids.NodeID]set.Set[ids.ID] // vdrID -> netIDs
}
func newValidatorState() validatorState {
return &metadata{
metadata: make(map[ids.NodeID]map[ids.ID]*validatorMetadata),
updatedMetadata: make(map[ids.NodeID]set.Set[ids.ID]),
}
}
func (m *metadata) LoadValidatorMetadata(
vdrID ids.NodeID,
netID ids.ID,
uptime *validatorMetadata,
) {
chainMetadata, ok := m.metadata[vdrID]
if !ok {
chainMetadata = make(map[ids.ID]*validatorMetadata)
m.metadata[vdrID] = chainMetadata
}
chainMetadata[netID] = uptime
}
func (m *metadata) GetUptime(
vdrID ids.NodeID,
netID ids.ID,
) (time.Duration, time.Time, error) {
metadata, exists := m.metadata[vdrID][netID]
if !exists {
return 0, time.Time{}, database.ErrNotFound
}
return metadata.UpDuration, metadata.lastUpdated, nil
}
func (m *metadata) SetUptime(
vdrID ids.NodeID,
netID ids.ID,
upDuration time.Duration,
lastUpdated time.Time,
) error {
metadata, exists := m.metadata[vdrID][netID]
if !exists {
return database.ErrNotFound
}
metadata.UpDuration = upDuration
metadata.lastUpdated = lastUpdated
m.addUpdatedMetadata(vdrID, netID)
return nil
}
func (m *metadata) GetDelegateeReward(
netID ids.ID,
vdrID ids.NodeID,
) (uint64, error) {
metadata, exists := m.metadata[vdrID][netID]
if !exists {
return 0, database.ErrNotFound
}
return metadata.PotentialDelegateeReward, nil
}
func (m *metadata) SetDelegateeReward(
netID ids.ID,
vdrID ids.NodeID,
amount uint64,
) error {
metadata, exists := m.metadata[vdrID][netID]
if !exists {
return database.ErrNotFound
}
metadata.PotentialDelegateeReward = amount
m.addUpdatedMetadata(vdrID, netID)
return nil
}
func (m *metadata) DeleteValidatorMetadata(vdrID ids.NodeID, netID ids.ID) {
chainMetadata := m.metadata[vdrID]
delete(chainMetadata, netID)
if len(chainMetadata) == 0 {
delete(m.metadata, vdrID)
}
chainUpdatedMetadata := m.updatedMetadata[vdrID]
chainUpdatedMetadata.Remove(netID)
if chainUpdatedMetadata.Len() == 0 {
delete(m.updatedMetadata, vdrID)
}
}
func (m *metadata) WriteValidatorMetadata(
dbPrimary database.KeyValueWriter,
dbNet database.KeyValueWriter,
) error {
for vdrID, updatedNets := range m.updatedMetadata {
for netID := range updatedNets {
metadata := m.metadata[vdrID][netID]
metadata.LastUpdated = uint64(metadata.lastUpdated.Unix())
metadataBytes, err := marshalValidatorMetadata(metadata)
if err != nil {
return err
}
db := dbNet
if netID == constants.PrimaryNetworkID {
db = dbPrimary
}
if err := db.Put(metadata.txID[:], metadataBytes); err != nil {
return err
}
}
delete(m.updatedMetadata, vdrID)
}
return nil
}
func (m *metadata) addUpdatedMetadata(vdrID ids.NodeID, netID ids.ID) {
updatedNetMetadata, ok := m.updatedMetadata[vdrID]
if !ok {
updatedNetMetadata = make(set.Set[ids.ID])
m.updatedMetadata[vdrID] = updatedNetMetadata
}
updatedNetMetadata.Add(netID)
}