Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove fallback validator height indexing #2801

Merged
merged 6 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
214 changes: 57 additions & 157 deletions vms/platformvm/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,28 +47,26 @@ var (
errValidatorSetAlreadyPopulated = errors.New("validator set already populated")
errIsNotSubnet = errors.New("is not a subnet")

BlockIDPrefix = []byte("blockID")
BlockPrefix = []byte("block")
ValidatorsPrefix = []byte("validators")
CurrentPrefix = []byte("current")
PendingPrefix = []byte("pending")
ValidatorPrefix = []byte("validator")
DelegatorPrefix = []byte("delegator")
SubnetValidatorPrefix = []byte("subnetValidator")
SubnetDelegatorPrefix = []byte("subnetDelegator")
NestedValidatorWeightDiffsPrefix = []byte("validatorDiffs")
NestedValidatorPublicKeyDiffsPrefix = []byte("publicKeyDiffs")
FlatValidatorWeightDiffsPrefix = []byte("flatValidatorDiffs")
FlatValidatorPublicKeyDiffsPrefix = []byte("flatPublicKeyDiffs")
TxPrefix = []byte("tx")
RewardUTXOsPrefix = []byte("rewardUTXOs")
UTXOPrefix = []byte("utxo")
SubnetPrefix = []byte("subnet")
SubnetOwnerPrefix = []byte("subnetOwner")
TransformedSubnetPrefix = []byte("transformedSubnet")
SupplyPrefix = []byte("supply")
ChainPrefix = []byte("chain")
SingletonPrefix = []byte("singleton")
BlockIDPrefix = []byte("blockID")
BlockPrefix = []byte("block")
ValidatorsPrefix = []byte("validators")
CurrentPrefix = []byte("current")
PendingPrefix = []byte("pending")
ValidatorPrefix = []byte("validator")
DelegatorPrefix = []byte("delegator")
SubnetValidatorPrefix = []byte("subnetValidator")
SubnetDelegatorPrefix = []byte("subnetDelegator")
ValidatorWeightDiffsPrefix = []byte("flatValidatorDiffs")
ValidatorPublicKeyDiffsPrefix = []byte("flatPublicKeyDiffs")
TxPrefix = []byte("tx")
RewardUTXOsPrefix = []byte("rewardUTXOs")
UTXOPrefix = []byte("utxo")
SubnetPrefix = []byte("subnet")
SubnetOwnerPrefix = []byte("subnetOwner")
TransformedSubnetPrefix = []byte("transformedSubnet")
SupplyPrefix = []byte("supply")
ChainPrefix = []byte("chain")
SingletonPrefix = []byte("singleton")

TimestampKey = []byte("timestamp")
CurrentSupplyKey = []byte("current supply")
Expand Down Expand Up @@ -209,17 +207,9 @@ type State interface {
* | | '-. subnetDelegator
* | | '-. list
* | | '-- txID -> nil
* | |-. nested weight diffs TODO: Remove once only the flat db is needed
* | | '-. height+subnet
* | | '-. list
* | | '-- nodeID -> weightChange
* | |-. nested pub key diffs TODO: Remove once only the flat db is needed
* | | '-. height
* | | '-. list
* | | '-- nodeID -> compressed public key
* | |-. flat weight diffs
* | |-. weight diffs
* | | '-- subnet+height+nodeID -> weightChange
* | '-. flat pub key diffs
* | '-. pub key diffs
* | '-- subnet+height+nodeID -> uncompressed public key or nil
* |-. blockIDs
* | '-- height -> blockID
Expand Down Expand Up @@ -293,10 +283,8 @@ type state struct {
pendingSubnetDelegatorBaseDB database.Database
pendingSubnetDelegatorList linkeddb.LinkedDB

nestedValidatorWeightDiffsDB database.Database
nestedValidatorPublicKeyDiffsDB database.Database
flatValidatorWeightDiffsDB database.Database
flatValidatorPublicKeyDiffsDB database.Database
validatorWeightDiffsDB database.Database
validatorPublicKeyDiffsDB database.Database

addedTxs map[ids.ID]*txAndStatus // map of txID -> {*txs.Tx, Status}
txCache cache.Cacher[ids.ID, *txAndStatus] // txID -> {*txs.Tx, Status}. If the entry is nil, it isn't in the database
Expand Down Expand Up @@ -338,8 +326,9 @@ type state struct {
currentSupply, persistedCurrentSupply uint64
// [lastAccepted] is the most recently accepted block.
lastAccepted, persistedLastAccepted ids.ID
indexedHeights *heightRange
singletonDB database.Database
// TODO: Remove indexedHeights once v1.11.3 has been released.
indexedHeights *heightRange
singletonDB database.Database
}

// heightRange is used to track which heights are safe to use the native DB
Expand Down Expand Up @@ -373,11 +362,6 @@ func (v *ValidatorWeightDiff) Add(negative bool, amount uint64) error {
return nil
}

type heightWithSubnet struct {
Height uint64 `serialize:"true"`
SubnetID ids.ID `serialize:"true"`
}

type txBytesAndStatus struct {
Tx []byte `serialize:"true"`
Status status.Status `serialize:"true"`
Expand Down Expand Up @@ -490,10 +474,8 @@ func newState(
pendingSubnetValidatorBaseDB := prefixdb.New(SubnetValidatorPrefix, pendingValidatorsDB)
pendingSubnetDelegatorBaseDB := prefixdb.New(SubnetDelegatorPrefix, pendingValidatorsDB)

nestedValidatorWeightDiffsDB := prefixdb.New(NestedValidatorWeightDiffsPrefix, validatorsDB)
nestedValidatorPublicKeyDiffsDB := prefixdb.New(NestedValidatorPublicKeyDiffsPrefix, validatorsDB)
flatValidatorWeightDiffsDB := prefixdb.New(FlatValidatorWeightDiffsPrefix, validatorsDB)
flatValidatorPublicKeyDiffsDB := prefixdb.New(FlatValidatorPublicKeyDiffsPrefix, validatorsDB)
validatorWeightDiffsDB := prefixdb.New(ValidatorWeightDiffsPrefix, validatorsDB)
validatorPublicKeyDiffsDB := prefixdb.New(ValidatorPublicKeyDiffsPrefix, validatorsDB)

txCache, err := metercacher.New(
"tx_cache",
Expand Down Expand Up @@ -591,29 +573,27 @@ func newState(
currentStakers: newBaseStakers(),
pendingStakers: newBaseStakers(),

validatorsDB: validatorsDB,
currentValidatorsDB: currentValidatorsDB,
currentValidatorBaseDB: currentValidatorBaseDB,
currentValidatorList: linkeddb.NewDefault(currentValidatorBaseDB),
currentDelegatorBaseDB: currentDelegatorBaseDB,
currentDelegatorList: linkeddb.NewDefault(currentDelegatorBaseDB),
currentSubnetValidatorBaseDB: currentSubnetValidatorBaseDB,
currentSubnetValidatorList: linkeddb.NewDefault(currentSubnetValidatorBaseDB),
currentSubnetDelegatorBaseDB: currentSubnetDelegatorBaseDB,
currentSubnetDelegatorList: linkeddb.NewDefault(currentSubnetDelegatorBaseDB),
pendingValidatorsDB: pendingValidatorsDB,
pendingValidatorBaseDB: pendingValidatorBaseDB,
pendingValidatorList: linkeddb.NewDefault(pendingValidatorBaseDB),
pendingDelegatorBaseDB: pendingDelegatorBaseDB,
pendingDelegatorList: linkeddb.NewDefault(pendingDelegatorBaseDB),
pendingSubnetValidatorBaseDB: pendingSubnetValidatorBaseDB,
pendingSubnetValidatorList: linkeddb.NewDefault(pendingSubnetValidatorBaseDB),
pendingSubnetDelegatorBaseDB: pendingSubnetDelegatorBaseDB,
pendingSubnetDelegatorList: linkeddb.NewDefault(pendingSubnetDelegatorBaseDB),
nestedValidatorWeightDiffsDB: nestedValidatorWeightDiffsDB,
nestedValidatorPublicKeyDiffsDB: nestedValidatorPublicKeyDiffsDB,
flatValidatorWeightDiffsDB: flatValidatorWeightDiffsDB,
flatValidatorPublicKeyDiffsDB: flatValidatorPublicKeyDiffsDB,
validatorsDB: validatorsDB,
currentValidatorsDB: currentValidatorsDB,
currentValidatorBaseDB: currentValidatorBaseDB,
currentValidatorList: linkeddb.NewDefault(currentValidatorBaseDB),
currentDelegatorBaseDB: currentDelegatorBaseDB,
currentDelegatorList: linkeddb.NewDefault(currentDelegatorBaseDB),
currentSubnetValidatorBaseDB: currentSubnetValidatorBaseDB,
currentSubnetValidatorList: linkeddb.NewDefault(currentSubnetValidatorBaseDB),
currentSubnetDelegatorBaseDB: currentSubnetDelegatorBaseDB,
currentSubnetDelegatorList: linkeddb.NewDefault(currentSubnetDelegatorBaseDB),
pendingValidatorsDB: pendingValidatorsDB,
pendingValidatorBaseDB: pendingValidatorBaseDB,
pendingValidatorList: linkeddb.NewDefault(pendingValidatorBaseDB),
pendingDelegatorBaseDB: pendingDelegatorBaseDB,
pendingDelegatorList: linkeddb.NewDefault(pendingDelegatorBaseDB),
pendingSubnetValidatorBaseDB: pendingSubnetValidatorBaseDB,
pendingSubnetValidatorList: linkeddb.NewDefault(pendingSubnetValidatorBaseDB),
pendingSubnetDelegatorBaseDB: pendingSubnetDelegatorBaseDB,
pendingSubnetDelegatorList: linkeddb.NewDefault(pendingSubnetDelegatorBaseDB),
validatorWeightDiffsDB: validatorWeightDiffsDB,
validatorPublicKeyDiffsDB: validatorPublicKeyDiffsDB,

addedTxs: make(map[ids.ID]*txAndStatus),
txDB: prefixdb.New(TxPrefix, baseDB),
Expand Down Expand Up @@ -1053,16 +1033,14 @@ func (s *state) ApplyValidatorWeightDiffs(
endHeight uint64,
subnetID ids.ID,
) error {
diffIter := s.flatValidatorWeightDiffsDB.NewIteratorWithStartAndPrefix(
diffIter := s.validatorWeightDiffsDB.NewIteratorWithStartAndPrefix(
marshalStartDiffKey(subnetID, startHeight),
subnetID[:],
)
defer diffIter.Release()

prevHeight := startHeight + 1
// TODO: Remove the index continuity checks once we are guaranteed nodes can
// not rollback to not support the new indexing mechanism.
for diffIter.Next() && s.indexedHeights != nil && s.indexedHeights.LowerBound <= endHeight {
for diffIter.Next() {
if err := ctx.Err(); err != nil {
return err
}
Expand Down Expand Up @@ -1100,50 +1078,7 @@ func (s *state) ApplyValidatorWeightDiffs(
return err
}
}
if err := diffIter.Error(); err != nil {
return err
}

// TODO: Remove this once it is assumed that all subnet validators have
// adopted the new indexing.
for height := prevHeight - 1; height >= endHeight; height-- {
Comment on lines -1107 to -1109
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this does potentially change the values returned for heights that were processed before the new indexing existed. However - those heights are less than the current heights required by the proposervm for all chains (XPC)

if err := ctx.Err(); err != nil {
return err
}

prefixStruct := heightWithSubnet{
Height: height,
SubnetID: subnetID,
}
prefixBytes, err := block.GenesisCodec.Marshal(block.CodecVersion, prefixStruct)
if err != nil {
return err
}

rawDiffDB := prefixdb.New(prefixBytes, s.nestedValidatorWeightDiffsDB)
diffDB := linkeddb.NewDefault(rawDiffDB)
diffIter := diffDB.NewIterator()
defer diffIter.Release()

for diffIter.Next() {
nodeID, err := ids.ToNodeID(diffIter.Key())
if err != nil {
return err
}

weightDiff := ValidatorWeightDiff{}
_, err = block.GenesisCodec.Unmarshal(diffIter.Value(), &weightDiff)
if err != nil {
return err
}

if err := applyWeightDiff(validators, nodeID, &weightDiff); err != nil {
return err
}
}
}

return nil
return diffIter.Error()
}

func applyWeightDiff(
Expand Down Expand Up @@ -1189,7 +1124,7 @@ func (s *state) ApplyValidatorPublicKeyDiffs(
startHeight uint64,
endHeight uint64,
) error {
diffIter := s.flatValidatorPublicKeyDiffsDB.NewIteratorWithStartAndPrefix(
diffIter := s.validatorPublicKeyDiffsDB.NewIteratorWithStartAndPrefix(
marshalStartDiffKey(constants.PrimaryNetworkID, startHeight),
constants.PrimaryNetworkID[:],
)
Expand Down Expand Up @@ -1891,10 +1826,6 @@ func (s *state) GetBlockIDAtHeight(height uint64) (ids.ID, error) {
}

func (s *state) writeCurrentStakers(updateValidators bool, height uint64, codecVersion uint16) error {
heightBytes := database.PackUInt64(height)
rawNestedPublicKeyDiffDB := prefixdb.New(heightBytes, s.nestedValidatorPublicKeyDiffsDB)
nestedPKDiffDB := linkeddb.NewDefault(rawNestedPublicKeyDiffDB)

for subnetID, validatorDiffs := range s.currentStakers.validatorDiffs {
delete(s.currentStakers.validatorDiffs, subnetID)

Expand All @@ -1906,17 +1837,6 @@ func (s *state) writeCurrentStakers(updateValidators bool, height uint64, codecV
delegatorDB = s.currentDelegatorList
}

prefixStruct := heightWithSubnet{
Height: height,
SubnetID: subnetID,
}
prefixBytes, err := block.GenesisCodec.Marshal(block.CodecVersion, prefixStruct)
if err != nil {
return fmt.Errorf("failed to create prefix bytes: %w", err)
}
rawNestedWeightDiffDB := prefixdb.New(prefixBytes, s.nestedValidatorWeightDiffsDB)
nestedWeightDiffDB := linkeddb.NewDefault(rawNestedWeightDiffDB)

// Record the change in weight and/or public key for each validator.
for nodeID, validatorDiff := range validatorDiffs {
// Copy [nodeID] so it doesn't get overwritten next iteration.
Expand All @@ -1936,7 +1856,7 @@ func (s *state) writeCurrentStakers(updateValidators bool, height uint64, codecV
// Record that the public key for the validator is being
// added. This means the prior value for the public key was
// nil.
err := s.flatValidatorPublicKeyDiffsDB.Put(
err := s.validatorPublicKeyDiffsDB.Put(
marshalDiffKey(constants.PrimaryNetworkID, height, nodeID),
nil,
)
Expand Down Expand Up @@ -1985,22 +1905,13 @@ func (s *state) writeCurrentStakers(updateValidators bool, height uint64, codecV
// Note: We store the uncompressed public key here as it is
// significantly more efficient to parse when applying
// diffs.
err := s.flatValidatorPublicKeyDiffsDB.Put(
err := s.validatorPublicKeyDiffsDB.Put(
marshalDiffKey(constants.PrimaryNetworkID, height, nodeID),
bls.PublicKeyToUncompressedBytes(staker.PublicKey),
)
if err != nil {
return err
}

// TODO: Remove this once we no longer support version
// rollbacks.
//
// Note: We store the compressed public key here.
pkBytes := bls.PublicKeyToCompressedBytes(staker.PublicKey)
if err := nestedPKDiffDB.Put(nodeID.Bytes(), pkBytes); err != nil {
return err
}
}

if err := validatorDB.Delete(staker.TxID[:]); err != nil {
Expand All @@ -2025,23 +1936,14 @@ func (s *state) writeCurrentStakers(updateValidators bool, height uint64, codecV
continue
}

err = s.flatValidatorWeightDiffsDB.Put(
err = s.validatorWeightDiffsDB.Put(
marshalDiffKey(subnetID, height, nodeID),
marshalWeightDiff(weightDiff),
)
if err != nil {
return err
}

// TODO: Remove this once we no longer support version rollbacks.
weightDiffBytes, err := block.GenesisCodec.Marshal(block.CodecVersion, weightDiff)
if err != nil {
return fmt.Errorf("failed to serialize validator weight diff: %w", err)
}
if err := nestedWeightDiffDB.Put(nodeID.Bytes(), weightDiffBytes); err != nil {
return err
}

// TODO: Move the validator set management out of the state package
if !updateValidators {
continue
Expand Down Expand Up @@ -2347,7 +2249,6 @@ func (s *state) writeMetadata() error {
}
s.persistedLastAccepted = s.lastAccepted
}

if s.indexedHeights != nil {
indexedHeightsBytes, err := block.GenesisCodec.Marshal(block.CodecVersion, s.indexedHeights)
if err != nil {
Expand All @@ -2357,6 +2258,5 @@ func (s *state) writeMetadata() error {
return fmt.Errorf("failed to write indexed range: %w", err)
}
}

return nil
}
Loading
Loading