Files
proto/p/state/stakers_test.go

272 lines
6.6 KiB
Go

// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package state
import (
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/luxfi/container/iterator"
"github.com/luxfi/database"
"github.com/luxfi/ids"
"github.com/luxfi/proto/p/genesis/genesistest"
"github.com/luxfi/proto/p/txs"
)
func TestBaseStakersPruning(t *testing.T) {
require := require.New(t)
staker := newTestStaker()
delegator := newTestStaker()
delegator.ChainID = staker.ChainID
delegator.NodeID = staker.NodeID
v := newBaseStakers()
v.PutValidator(staker)
_, err := v.GetValidator(staker.ChainID, staker.NodeID)
require.NoError(err)
v.PutDelegator(delegator)
_, err = v.GetValidator(staker.ChainID, staker.NodeID)
require.NoError(err)
v.DeleteValidator(staker)
_, err = v.GetValidator(staker.ChainID, staker.NodeID)
require.ErrorIs(err, database.ErrNotFound)
v.DeleteDelegator(delegator)
require.Empty(v.validators)
v.PutValidator(staker)
_, err = v.GetValidator(staker.ChainID, staker.NodeID)
require.NoError(err)
v.PutDelegator(delegator)
_, err = v.GetValidator(staker.ChainID, staker.NodeID)
require.NoError(err)
v.DeleteDelegator(delegator)
_, err = v.GetValidator(staker.ChainID, staker.NodeID)
require.NoError(err)
v.DeleteValidator(staker)
_, err = v.GetValidator(staker.ChainID, staker.NodeID)
require.ErrorIs(err, database.ErrNotFound)
require.Empty(v.validators)
}
func TestBaseStakersValidator(t *testing.T) {
require := require.New(t)
staker := newTestStaker()
delegator := newTestStaker()
v := newBaseStakers()
v.PutDelegator(delegator)
_, err := v.GetValidator(ids.GenerateTestID(), delegator.NodeID)
require.ErrorIs(err, database.ErrNotFound)
_, err = v.GetValidator(delegator.ChainID, ids.GenerateTestNodeID())
require.ErrorIs(err, database.ErrNotFound)
_, err = v.GetValidator(delegator.ChainID, delegator.NodeID)
require.ErrorIs(err, database.ErrNotFound)
stakerIterator := v.GetStakerIterator()
require.Equal(
[]*Staker{delegator},
iterator.ToSlice(stakerIterator),
)
v.PutValidator(staker)
returnedStaker, err := v.GetValidator(staker.ChainID, staker.NodeID)
require.NoError(err)
require.Equal(staker, returnedStaker)
v.DeleteDelegator(delegator)
stakerIterator = v.GetStakerIterator()
require.Equal(
[]*Staker{staker},
iterator.ToSlice(stakerIterator),
)
v.DeleteValidator(staker)
_, err = v.GetValidator(staker.ChainID, staker.NodeID)
require.ErrorIs(err, database.ErrNotFound)
stakerIterator = v.GetStakerIterator()
require.Empty(
iterator.ToSlice(stakerIterator),
)
}
func TestBaseStakersDelegator(t *testing.T) {
require := require.New(t)
staker := newTestStaker()
delegator := newTestStaker()
v := newBaseStakers()
delegatorIterator := v.GetDelegatorIterator(delegator.ChainID, delegator.NodeID)
require.Empty(
iterator.ToSlice(delegatorIterator),
)
v.PutDelegator(delegator)
delegatorIterator = v.GetDelegatorIterator(delegator.ChainID, ids.GenerateTestNodeID())
require.Empty(
iterator.ToSlice(delegatorIterator),
)
delegatorIterator = v.GetDelegatorIterator(delegator.ChainID, delegator.NodeID)
require.Equal(
[]*Staker{delegator},
iterator.ToSlice(delegatorIterator),
)
v.DeleteDelegator(delegator)
delegatorIterator = v.GetDelegatorIterator(delegator.ChainID, delegator.NodeID)
require.Empty(
iterator.ToSlice(delegatorIterator),
)
v.PutValidator(staker)
v.PutDelegator(delegator)
v.DeleteDelegator(delegator)
delegatorIterator = v.GetDelegatorIterator(staker.ChainID, staker.NodeID)
require.Empty(
iterator.ToSlice(delegatorIterator),
)
}
func TestDiffStakersValidator(t *testing.T) {
require := require.New(t)
staker := newTestStaker()
delegator := newTestStaker()
v := diffStakers{}
v.PutDelegator(delegator)
// validators not available in the diff are marked as unmodified
_, status := v.GetValidator(ids.GenerateTestID(), delegator.NodeID)
require.Equal(unmodified, status)
_, status = v.GetValidator(delegator.ChainID, ids.GenerateTestNodeID())
require.Equal(unmodified, status)
// delegator addition shouldn't change validatorStatus
_, status = v.GetValidator(delegator.ChainID, delegator.NodeID)
require.Equal(unmodified, status)
stakerIterator := v.GetStakerIterator(iterator.Empty[*Staker]{})
require.Equal(
[]*Staker{delegator},
iterator.ToSlice(stakerIterator),
)
require.NoError(v.PutValidator(staker))
returnedStaker, status := v.GetValidator(staker.ChainID, staker.NodeID)
require.Equal(added, status)
require.Equal(staker, returnedStaker)
v.DeleteValidator(staker)
// Validators created and deleted in the same diff are marked as unmodified.
// This means they won't be pushed to baseState if diff.Apply(baseState) is
// called.
_, status = v.GetValidator(staker.ChainID, staker.NodeID)
require.Equal(unmodified, status)
stakerIterator = v.GetStakerIterator(iterator.Empty[*Staker]{})
require.Equal(
[]*Staker{delegator},
iterator.ToSlice(stakerIterator),
)
}
func TestDiffStakersDeleteValidator(t *testing.T) {
require := require.New(t)
staker := newTestStaker()
delegator := newTestStaker()
v := diffStakers{}
_, status := v.GetValidator(ids.GenerateTestID(), delegator.NodeID)
require.Equal(unmodified, status)
v.DeleteValidator(staker)
returnedStaker, status := v.GetValidator(staker.ChainID, staker.NodeID)
require.Equal(deleted, status)
require.Nil(returnedStaker)
}
func TestDiffStakersDelegator(t *testing.T) {
require := require.New(t)
staker := newTestStaker()
delegator := newTestStaker()
v := diffStakers{}
require.NoError(v.PutValidator(staker))
delegatorIterator := v.GetDelegatorIterator(iterator.Empty[*Staker]{}, ids.GenerateTestID(), delegator.NodeID)
require.Empty(
iterator.ToSlice(delegatorIterator),
)
v.PutDelegator(delegator)
delegatorIterator = v.GetDelegatorIterator(iterator.Empty[*Staker]{}, delegator.ChainID, delegator.NodeID)
require.Equal(
[]*Staker{delegator},
iterator.ToSlice(delegatorIterator),
)
v.DeleteDelegator(delegator)
delegatorIterator = v.GetDelegatorIterator(iterator.Empty[*Staker]{}, ids.GenerateTestID(), delegator.NodeID)
require.Empty(
iterator.ToSlice(delegatorIterator),
)
}
func newTestStaker() *Staker {
startTime := time.Now().Round(time.Second)
endTime := startTime.Add(genesistest.DefaultValidatorDuration)
return &Staker{
TxID: ids.GenerateTestID(),
NodeID: ids.GenerateTestNodeID(),
ChainID: ids.GenerateTestID(),
Weight: 1,
StartTime: startTime,
EndTime: endTime,
PotentialReward: 1,
NextTime: endTime,
Priority: txs.PrimaryNetworkDelegatorCurrentPriority,
}
}