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

En 12197 staking v4 save nodes config #4125

Merged
32 changes: 32 additions & 0 deletions integrationTests/vm/staking/baseTestMetaProcessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/ElrondNetwork/elrond-go/process/mock"
"github.com/ElrondNetwork/elrond-go/sharding/nodesCoordinator"
"github.com/ElrondNetwork/elrond-go/state"
"github.com/ElrondNetwork/elrond-go/testscommon/stakingcommon"
"github.com/ElrondNetwork/elrond-go/vm/systemSmartContracts/defaults"
vmcommon "github.com/ElrondNetwork/elrond-vm-common"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -80,6 +81,13 @@ func newTestMetaProcessor(
maxNodesConfig []config.MaxNodesChangeConfig,
queue [][]byte,
) *TestMetaProcessor {
saveNodesConfig(
stateComponents.AccountsAdapter(),
coreComponents.InternalMarshalizer(),
nc,
maxNodesConfig,
)

gasScheduleNotifier := createGasScheduleNotifier()
blockChainHook := createBlockChainHook(
dataComponents,
Expand Down Expand Up @@ -345,3 +353,27 @@ func generateAddress(identifier uint32) []byte {
uniqueIdentifier := fmt.Sprintf("address-%d", identifier)
return []byte(strings.Repeat("0", addressLength-len(uniqueIdentifier)) + uniqueIdentifier)
}

func saveNodesConfig(
accountsDB state.AccountsAdapter,
marshaller marshal.Marshalizer,
nc nodesCoordinator.NodesCoordinator,
maxNodesConfig []config.MaxNodesChangeConfig,
) {
eligibleMap, _ := nc.GetAllEligibleValidatorsPublicKeys(0)
waitingMap, _ := nc.GetAllWaitingValidatorsPublicKeys(0)
allStakedNodes := int64(len(getAllPubKeys(eligibleMap)) + len(getAllPubKeys(waitingMap)))

maxNumNodes := allStakedNodes
if len(maxNodesConfig) > 0 {
maxNumNodes = int64(maxNodesConfig[0].MaxNumNodes)
}

stakingcommon.SaveNodesConfig(
accountsDB,
marshaller,
allStakedNodes,
1,
maxNumNodes,
)
}
26 changes: 21 additions & 5 deletions integrationTests/vm/staking/stakingV4_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ func TestStakingV4_StakeNewNodes(t *testing.T) {
node := NewTestMetaProcessorWithCustomNodes(cfg)
node.EpochStartTrigger.SetRoundsPerEpoch(4)

// 1. Check initial config is correct
// 1.1 Check initial config is correct
currNodesConfig := node.NodesConfig
require.Len(t, getAllPubKeys(currNodesConfig.eligible), 4)
require.Len(t, getAllPubKeys(currNodesConfig.waiting), 4)
Expand All @@ -491,6 +491,21 @@ func TestStakingV4_StakeNewNodes(t *testing.T) {
require.Empty(t, currNodesConfig.shuffledOut)
require.Empty(t, currNodesConfig.auction)

// NewOwner0 stakes 1 node with top up = 0 before staking v4; should be sent to staking queue
newOwner0 := "newOwner0"
newNodes0 := map[string]*NodesRegisterData{
newOwner0: {
BLSKeys: [][]byte{generateAddress(333)},
TotalStake: big.NewInt(nodePrice),
},
}

// 1.2 Check staked node before staking v4 is sent to staking queue
node.ProcessStake(t, newNodes0)
queue = append(queue, newNodes0[newOwner0].BLSKeys...)
currNodesConfig = node.NodesConfig
require.Len(t, currNodesConfig.queue, 4)

// NewOwner1 stakes 1 node with top up = 2*node price; should be sent to auction list
newOwner1 := "newOwner1"
newNodes1 := map[string]*NodesRegisterData{
Expand All @@ -500,13 +515,13 @@ func TestStakingV4_StakeNewNodes(t *testing.T) {
},
}
// 2. Check config after staking v4 init when a new node is staked
node.Process(t, 5)
node.Process(t, 4)
node.ProcessStake(t, newNodes1)
currNodesConfig = node.NodesConfig
queue = append(queue, newNodes1[newOwner1].BLSKeys...)
require.Empty(t, currNodesConfig.queue)
require.Empty(t, currNodesConfig.leaving)
require.Len(t, currNodesConfig.auction, 4)
require.Len(t, currNodesConfig.auction, 5)
requireSameSliceDifferentOrder(t, currNodesConfig.auction, queue)

// NewOwner2 stakes 2 node with top up = 2*node price; should be sent to auction list
Expand All @@ -523,18 +538,19 @@ func TestStakingV4_StakeNewNodes(t *testing.T) {
currNodesConfig = node.NodesConfig
queue = append(queue, newNodes2[newOwner2].BLSKeys...)
require.Empty(t, currNodesConfig.queue)
requireSliceContainsNumOfElements(t, currNodesConfig.auction, queue, 6)
requireSliceContainsNumOfElements(t, currNodesConfig.auction, queue, 7)

// 3. Epoch = staking v4 distribute auction to waiting
// Only the new 2 owners + owner3 had enough top up to be distributed to waiting.
// Meanwhile; owner1 which had 0 top up, still has his bls keys in auction
// Meanwhile; owner1 which had 0 top up, still has his bls keys in auction, along with newOwner0
node.Process(t, 5)
currNodesConfig = node.NodesConfig
require.Empty(t, currNodesConfig.queue)
requireMapContains(t, currNodesConfig.waiting, newNodes1[newOwner1].BLSKeys)
requireMapContains(t, currNodesConfig.waiting, newNodes2[newOwner2].BLSKeys)
requireMapContains(t, currNodesConfig.waiting, owner3StakingQueue)
requireSliceContains(t, currNodesConfig.auction, owner1StakingQueue)
requireSliceContains(t, currNodesConfig.auction, newNodes0[newOwner0].BLSKeys)
}

// TODO: test unstake with 1 owner -> 1 bls key in auction => numStakedNodes = 0
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,7 @@ func (tmp *TestMetaProcessor) ProcessStake(t *testing.T, nodes map[string]*Nodes
}

//TODO:
// 1. Do the same for unStake/unJail
// 2. Use this func to stake initial nodes instead of hard coding them
// - Do the same for unStake/unJail
func (tmp *TestMetaProcessor) doStake(t *testing.T, vmInput vmcommon.VMInput) {
arguments := &vmcommon.ContractCallInput{
VMInput: vmInput,
Expand Down
31 changes: 6 additions & 25 deletions integrationTests/vm/txsFee/validatorSC_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import (
"github.com/ElrondNetwork/elrond-go-core/data/block"
"github.com/ElrondNetwork/elrond-go-core/data/smartContractResult"
"github.com/ElrondNetwork/elrond-go-core/data/transaction"
"github.com/ElrondNetwork/elrond-go-core/marshal"
"github.com/ElrondNetwork/elrond-go/config"
"github.com/ElrondNetwork/elrond-go/integrationTests/vm"
"github.com/ElrondNetwork/elrond-go/integrationTests/vm/txsFee/utils"
"github.com/ElrondNetwork/elrond-go/process/smartContract/hooks"
"github.com/ElrondNetwork/elrond-go/state"
"github.com/ElrondNetwork/elrond-go/testscommon/stakingcommon"
vmAddr "github.com/ElrondNetwork/elrond-go/vm"
"github.com/ElrondNetwork/elrond-go/vm/systemSmartContracts"
vmcommon "github.com/ElrondNetwork/elrond-vm-common"
Expand Down Expand Up @@ -55,7 +55,7 @@ func TestValidatorsSC_DoStakePutInQueueUnStakeAndUnBondShouldRefund(t *testing.T
require.Nil(t, err)
defer testContextMeta.Close()

saveNodesConfig(t, testContextMeta, 1, 1, 1)
stakingcommon.SaveNodesConfig(testContextMeta.Accounts, testContextMeta.Marshalizer, 1, 1, 1)
testContextMeta.BlockchainHook.(*hooks.BlockChainHookImpl).SetCurrentHeader(&block.MetaBlock{Epoch: 1})
saveDelegationManagerConfig(testContextMeta)

Expand Down Expand Up @@ -118,7 +118,7 @@ func TestValidatorsSC_DoStakePutInQueueUnStakeAndUnBondTokensShouldRefund(t *tes
require.Nil(t, err)
defer testContextMeta.Close()

saveNodesConfig(t, testContextMeta, 1, 1, 1)
stakingcommon.SaveNodesConfig(testContextMeta.Accounts, testContextMeta.Marshalizer, 1, 1, 1)
saveDelegationManagerConfig(testContextMeta)
testContextMeta.BlockchainHook.(*hooks.BlockChainHookImpl).SetCurrentHeader(&block.MetaBlock{Epoch: 1})

Expand Down Expand Up @@ -165,7 +165,7 @@ func testValidatorsSCDoStakeWithTopUpValueTryToUnStakeTokensAndUnBondTokens(t *t
require.Nil(t, err)
defer testContextMeta.Close()

saveNodesConfig(t, testContextMeta, 1, 1, 1)
stakingcommon.SaveNodesConfig(testContextMeta.Accounts, testContextMeta.Marshalizer, 1, 1, 1)
saveDelegationManagerConfig(testContextMeta)
testContextMeta.BlockchainHook.(*hooks.BlockChainHookImpl).SetCurrentHeader(&block.MetaBlock{Epoch: 0})

Expand Down Expand Up @@ -199,7 +199,7 @@ func TestValidatorsSC_ToStakePutInQueueUnStakeAndUnBondShouldRefundUnBondTokens(
require.Nil(t, err)
defer testContextMeta.Close()

saveNodesConfig(t, testContextMeta, 1, 1, 1)
stakingcommon.SaveNodesConfig(testContextMeta.Accounts, testContextMeta.Marshalizer, 1, 1, 1)
saveDelegationManagerConfig(testContextMeta)
testContextMeta.BlockchainHook.(*hooks.BlockChainHookImpl).SetCurrentHeader(&block.MetaBlock{Epoch: 1})

Expand Down Expand Up @@ -252,7 +252,7 @@ func TestValidatorsSC_ToStakePutInQueueUnStakeNodesAndUnBondNodesShouldRefund(t
require.Nil(t, err)
defer testContextMeta.Close()

saveNodesConfig(t, testContextMeta, 1, 1, 1)
stakingcommon.SaveNodesConfig(testContextMeta.Accounts, testContextMeta.Marshalizer, 1, 1, 1)
saveDelegationManagerConfig(testContextMeta)
testContextMeta.BlockchainHook.(*hooks.BlockChainHookImpl).SetCurrentHeader(&block.MetaBlock{Epoch: 1})

Expand Down Expand Up @@ -306,22 +306,3 @@ func executeTxAndCheckResults(
require.Equal(t, vmCodeExpected, recCode)
require.Equal(t, expectedErr, err)
}

func saveNodesConfig(t *testing.T, testContext *vm.VMTestContext, stakedNodes, minNumNodes, maxNumNodes int64) {
protoMarshalizer := &marshal.GogoProtoMarshalizer{}

account, err := testContext.Accounts.LoadAccount(vmAddr.StakingSCAddress)
require.Nil(t, err)
userAccount, _ := account.(state.UserAccountHandler)

nodesConfigData := &systemSmartContracts.StakingNodesConfig{
StakedNodes: stakedNodes,
MinNumNodes: minNumNodes,
MaxNumNodes: maxNumNodes,
}
nodesDataBytes, _ := protoMarshalizer.Marshal(nodesConfigData)

_ = userAccount.DataTrieTracker().SaveKeyValue([]byte("nodesConfig"), nodesDataBytes)
_ = testContext.Accounts.SaveAccount(account)
_, _ = testContext.Accounts.Commit()
}
28 changes: 28 additions & 0 deletions testscommon/stakingcommon/stakingCommon.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,3 +278,31 @@ func CreateEconomicsData() process.EconomicsDataHandler {
economicsData, _ := economicsHandler.NewEconomicsData(argsNewEconomicsData)
return economicsData
}

// SaveNodesConfig saves the nodes config in accounts db under "nodesConfig" key with provided params
func SaveNodesConfig(
accountsDB state.AccountsAdapter,
marshaller marshal.Marshalizer,
stakedNodes,
minNumNodes,
maxNumNodes int64,
) {
nodesConfigData := &systemSmartContracts.StakingNodesConfig{
StakedNodes: stakedNodes,
MinNumNodes: minNumNodes,
MaxNumNodes: maxNumNodes,
}
nodesDataBytes, err := marshaller.Marshal(nodesConfigData)
log.LogIfError(err)

account, err := accountsDB.LoadAccount(vm.StakingSCAddress)
log.LogIfError(err)

userAccount, _ := account.(state.UserAccountHandler)
err = userAccount.DataTrieTracker().SaveKeyValue([]byte("nodesConfig"), nodesDataBytes)
log.LogIfError(err)
err = accountsDB.SaveAccount(account)
log.LogIfError(err)
_, err = accountsDB.Commit()
log.LogIfError(err)
}