Files
platformvm/state/disk_staker_diff_iterator.go
zeekay ede37547f6 refactor(platformvm): consolidate block code, drop atomic_block, add v0 lift
- Drop atomic_block.go + legacy *_block_test.go (consolidated)
- Add block/v0/ subdir + lift_v0.go for old version handling
- Copyright header: 'Lux Industries, Inc.' → 'Lux Industries Inc' (no comma)
- block_adapter.go: new adapter layer
2026-06-01 15:22:27 -07:00

102 lines
3.1 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package state
import (
"encoding/binary"
"fmt"
"github.com/luxfi/database"
"github.com/luxfi/ids"
)
const (
// startDiffKey = [netID] + [inverseHeight]
startDiffKeyLength = ids.IDLen + database.Uint64Size
// diffKey = [netID] + [inverseHeight] + [nodeID]
diffKeyLength = startDiffKeyLength + ids.NodeIDLen
// diffKeyNodeIDOffset = [netIDLen] + [inverseHeightLen]
diffKeyNodeIDOffset = ids.IDLen + database.Uint64Size
// weightValue = [isNegative] + [weight] + [validationID]
weightValueLength = database.BoolSize + database.Uint64Size + ids.IDLen
)
var (
errUnexpectedDiffKeyLength = fmt.Errorf("expected diff key length %d", diffKeyLength)
errUnexpectedWeightValueLength = fmt.Errorf("expected weight value length %d", weightValueLength)
)
// marshalStartDiffKey is used to determine the starting key when iterating.
//
// Invariant: the result is a prefix of [marshalDiffKey] when called with the
// same arguments.
func marshalStartDiffKey(netID ids.ID, height uint64) []byte {
key := make([]byte, startDiffKeyLength)
copy(key, netID[:])
packIterableHeight(key[ids.IDLen:], height)
return key
}
func marshalDiffKey(netID ids.ID, height uint64, nodeID ids.NodeID) []byte {
key := make([]byte, diffKeyLength)
copy(key, netID[:])
packIterableHeight(key[ids.IDLen:], height)
copy(key[diffKeyNodeIDOffset:], nodeID.Bytes())
return key
}
func unmarshalDiffKey(key []byte) (ids.ID, uint64, ids.NodeID, error) {
if len(key) != diffKeyLength {
return ids.Empty, 0, ids.EmptyNodeID, errUnexpectedDiffKeyLength
}
var (
netID ids.ID
nodeID ids.NodeID
)
copy(netID[:], key)
height := unpackIterableHeight(key[ids.IDLen:])
copy(nodeID[:], key[diffKeyNodeIDOffset:])
return netID, height, nodeID, nil
}
func marshalWeightDiff(diff *ValidatorWeightDiff) []byte {
value := make([]byte, weightValueLength)
if diff.Decrease {
value[0] = database.BoolTrue
}
binary.BigEndian.PutUint64(value[database.BoolSize:], diff.Amount)
copy(value[database.BoolSize+database.Uint64Size:], diff.ValidationID[:])
return value
}
func unmarshalWeightDiff(value []byte) (*ValidatorWeightDiff, error) {
if len(value) != weightValueLength {
return nil, errUnexpectedWeightValueLength
}
var validationID ids.ID
copy(validationID[:], value[database.BoolSize+database.Uint64Size:])
return &ValidatorWeightDiff{
Decrease: value[0] == database.BoolTrue,
Amount: binary.BigEndian.Uint64(value[database.BoolSize:]),
ValidationID: validationID,
}, nil
}
// Note: [height] is encoded as a bit flipped big endian number so that
// iterating lexicographically results in iterating in decreasing heights.
//
// Invariant: [key] has sufficient length
func packIterableHeight(key []byte, height uint64) {
binary.BigEndian.PutUint64(key, ^height)
}
// Because we bit flip the height when constructing the key, we must remember to
// bip flip again here.
//
// Invariant: [key] has sufficient length
func unpackIterableHeight(key []byte) uint64 {
return ^binary.BigEndian.Uint64(key)
}