Skip to content

Commit

Permalink
Expose ValidatorInfo struct (#1162)
Browse files Browse the repository at this point in the history
  • Loading branch information
Stefan-Ethernal authored Jan 26, 2023
1 parent 28f106a commit f0275ea
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 52 deletions.
12 changes: 10 additions & 2 deletions command/sidechain/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"math/big"
"os"

"github.com/0xPolygon/polygon-edge/consensus/polybft"
"github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi"
"github.com/0xPolygon/polygon-edge/consensus/polybft/wallet"
"github.com/0xPolygon/polygon-edge/contracts"
Expand Down Expand Up @@ -42,7 +43,7 @@ func GetAccountFromDir(dir string) (*wallet.Account, error) {
}

// GetValidatorInfo queries ChildValidatorSet smart contract and retrieves validator info for given address
func GetValidatorInfo(validatorAddr ethgo.Address, txRelayer txrelayer.TxRelayer) (map[string]interface{}, error) {
func GetValidatorInfo(validatorAddr ethgo.Address, txRelayer txrelayer.TxRelayer) (*polybft.ValidatorInfo, error) {
getValidatorMethod := contractsapi.ChildValidatorSet.Abi.GetMethod("getValidator")

encode, err := getValidatorMethod.Encode([]interface{}{validatorAddr})
Expand Down Expand Up @@ -76,7 +77,14 @@ func GetValidatorInfo(validatorAddr ethgo.Address, txRelayer txrelayer.TxRelayer
return nil, fmt.Errorf("could not convert validator info result to a map")
}

return decodedValidatorInfoMap, nil
return &polybft.ValidatorInfo{
Address: validatorAddr.Address(),
Stake: decodedValidatorInfoMap["stake"].(*big.Int), //nolint:forcetypeassert
TotalStake: decodedValidatorInfoMap["totalStake"].(*big.Int), //nolint:forcetypeassert
Commission: decodedValidatorInfoMap["commission"].(*big.Int), //nolint:forcetypeassert
WithdrawableRewards: decodedValidatorInfoMap["withdrawableRewards"].(*big.Int), //nolint:forcetypeassert
Active: decodedValidatorInfoMap["active"].(bool), //nolint:forcetypeassert
}, nil
}

// GetDelegatorReward queries delegator reward for given validator and delegator addresses
Expand Down
15 changes: 7 additions & 8 deletions command/sidechain/validators/validator_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package validators

import (
"fmt"
"math/big"

"github.com/0xPolygon/polygon-edge/command"
"github.com/0xPolygon/polygon-edge/command/helper"
Expand Down Expand Up @@ -60,18 +59,18 @@ func runCommand(cmd *cobra.Command, _ []string) error {

validatorAddr := validatorAccount.Ecdsa.Address()

responseMap, err := sidechainHelper.GetValidatorInfo(validatorAddr, txRelayer)
validatorInfo, err := sidechainHelper.GetValidatorInfo(validatorAddr, txRelayer)
if err != nil {
return fmt.Errorf("failed to get validator info for %s: %w", validatorAddr, err)
}

outputter.WriteCommandResult(&validatorsInfoResult{
address: validatorAccount.Ecdsa.Address().String(),
stake: responseMap["stake"].(*big.Int).Uint64(), //nolint:forcetypeassert
totalStake: responseMap["totalStake"].(*big.Int).Uint64(), //nolint:forcetypeassert
commission: responseMap["commission"].(*big.Int).Uint64(), //nolint:forcetypeassert
withdrawableRewards: responseMap["withdrawableRewards"].(*big.Int).Uint64(), //nolint:forcetypeassert
active: responseMap["active"].(bool), //nolint:forcetypeassert
address: validatorInfo.Address.String(),
stake: validatorInfo.Stake.Uint64(),
totalStake: validatorInfo.TotalStake.Uint64(),
commission: validatorInfo.Commission.Uint64(),
withdrawableRewards: validatorInfo.WithdrawableRewards.Uint64(),
active: validatorInfo.Active,
})

return nil
Expand Down
11 changes: 11 additions & 0 deletions consensus/polybft/system_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ import (
"github.com/umbracle/ethgo/contract"
)

// ValidatorInfo is data transfer object which holds validator information,
// provided by smart contract
type ValidatorInfo struct {
Address ethgo.Address
Stake *big.Int
TotalStake *big.Int
Commission *big.Int
WithdrawableRewards *big.Int
Active bool
}

// SystemState is an interface to interact with the consensus system contracts in the chain
type SystemState interface {
// GetValidatorSet retrieves current validator set from the smart contract
Expand Down
29 changes: 13 additions & 16 deletions e2e-polybft/bridge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -626,43 +626,40 @@ func TestE2E_Bridge_ChangeVotingPower(t *testing.T) {
// waiting two epochs, so that some rewards get accumulated
require.NoError(t, cluster.WaitForBlock(10, 1*time.Minute))

queryValidators := func(handler func(idx int, validatorInfo *validatorInfo)) {
queryValidators := func(handler func(idx int, validatorInfo *polybft.ValidatorInfo)) {
for i, validatorAddr := range votingPowerChangeValidators {
// query validator info
validatorInfoRaw, err := sidechain.GetValidatorInfo(validatorAddr, l2Relayer)
validatorInfo, err := sidechain.GetValidatorInfo(validatorAddr, l2Relayer)
require.NoError(t, err)

rewards := validatorInfoRaw["withdrawableRewards"].(*big.Int) //nolint:forcetypeassert
totalStake := validatorInfoRaw["totalStake"].(*big.Int) //nolint:forcetypeassert

handler(i, &validatorInfo{address: validatorAddr, rewards: rewards, totalStake: totalStake})
handler(i, validatorInfo)
}
}

originalValidatorStorage := make(map[ethgo.Address]*validatorInfo, votingPowerChanges)
originalValidatorStorage := make(map[ethgo.Address]*polybft.ValidatorInfo, votingPowerChanges)

queryValidators(func(idx int, validator *validatorInfo) {
queryValidators(func(idx int, validator *polybft.ValidatorInfo) {
t.Logf("[Validator#%d] Voting power (original)=%d, rewards=%d\n",
idx+1, validator.totalStake, validator.rewards)
idx+1, validator.TotalStake, validator.WithdrawableRewards)

originalValidatorStorage[validator.address] = validator
originalValidatorStorage[validator.Address] = validator

// stake rewards
require.NoError(t, cluster.Servers[idx].Stake(validator.rewards.Uint64()))
require.NoError(t, cluster.Servers[idx].Stake(validator.WithdrawableRewards.Uint64()))
})

// wait a two more epochs, so that stake is registered and two more checkpoints are sent.
// Blocks are still produced, although voting power is slightly changed.
require.NoError(t, cluster.WaitForBlock(finalBlockNumber, 1*time.Minute))

queryValidators(func(idx int, validator *validatorInfo) {
t.Logf("[Validator#%d] Voting power (after stake)=%d\n", idx+1, validator.totalStake)
queryValidators(func(idx int, validator *polybft.ValidatorInfo) {
t.Logf("[Validator#%d] Voting power (after stake)=%d\n", idx+1, validator.TotalStake)

previousValidatorInfo := originalValidatorStorage[validator.address]
stakedAmount := new(big.Int).Add(previousValidatorInfo.rewards, previousValidatorInfo.totalStake)
previousValidatorInfo := originalValidatorStorage[validator.Address]
stakedAmount := new(big.Int).Add(previousValidatorInfo.WithdrawableRewards, previousValidatorInfo.TotalStake)

// assert that total stake has increased by staked amount
require.Equal(t, stakedAmount, validator.totalStake)
require.Equal(t, stakedAmount, validator.TotalStake)
})

l1Sender := ethgo.Address(manifest.RootchainConfig.AdminAddress)
Expand Down
28 changes: 13 additions & 15 deletions e2e-polybft/consensus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,8 @@ func TestE2E_Consensus_RegisterValidator(t *testing.T) {
require.NoError(t, err)

// assert registered validator's stake
stake := newValidatorInfo["totalStake"].(*big.Int) //nolint:forcetypeassert
t.Logf("New validator stake=%s\n", stake.String())
require.Equal(t, newValidatorStake, stake)
t.Logf("New validator stake=%d\n", newValidatorInfo.TotalStake)
require.Equal(t, newValidatorStake, newValidatorInfo.TotalStake)

// wait 3 more epochs, so that rewards get accumulated to the registered validator account
cluster.WaitForBlock(20, 2*time.Minute)
Expand All @@ -193,9 +192,8 @@ func TestE2E_Consensus_RegisterValidator(t *testing.T) {
require.NoError(t, err)

// assert registered validator's rewards
rewards := newValidatorInfo["withdrawableRewards"].(*big.Int) //nolint:forcetypeassert
t.Logf("New validator rewards=%s\n", rewards)
require.True(t, rewards.Cmp(big.NewInt(0)) > 0)
t.Logf("New validator rewards=%d\n", newValidatorInfo.WithdrawableRewards)
require.True(t, newValidatorInfo.WithdrawableRewards.Cmp(big.NewInt(0)) > 0)
}

func TestE2E_Consensus_Delegation_Undelegation(t *testing.T) {
Expand Down Expand Up @@ -336,11 +334,11 @@ func TestE2E_Consensus_Validator_Unstake(t *testing.T) {
// wait for one epoch to accumulate validator rewards
require.NoError(t, cluster.WaitForBlock(5, 20*time.Second))

validatorInfoRaw, err := sidechain.GetValidatorInfo(validatorAddr, txRelayer)
validatorInfo, err := sidechain.GetValidatorInfo(validatorAddr, txRelayer)
require.NoError(t, err)

initialStake := validatorInfoRaw["totalStake"].(*big.Int) //nolint:forcetypeassert
t.Logf("Stake (before unstake)=%s\n", initialStake.String())
initialStake := validatorInfo.TotalStake
t.Logf("Stake (before unstake)=%d\n", initialStake)

// unstake entire balance (which should remove validator from the validator set in next epoch)
require.NoError(t, srv.Unstake(initialStake.Uint64()))
Expand All @@ -354,12 +352,12 @@ func TestE2E_Consensus_Validator_Unstake(t *testing.T) {
// assert that validator isn't present in new validator set
require.Equal(t, 4, validatorSet.Len())

validatorInfoRaw, err = sidechain.GetValidatorInfo(validatorAddr, txRelayer)
validatorInfo, err = sidechain.GetValidatorInfo(validatorAddr, txRelayer)
require.NoError(t, err)

reward := validatorInfoRaw["withdrawableRewards"].(*big.Int) //nolint:forcetypeassert
reward := validatorInfo.WithdrawableRewards
t.Logf("Rewards=%d\n", reward)
t.Logf("Stake (after unstake)=%d\n", validatorInfoRaw["totalStake"].(*big.Int)) //nolint:forcetypeassert
t.Logf("Stake (after unstake)=%d\n", validatorInfo.TotalStake)
require.Greater(t, reward.Uint64(), uint64(0))

oldValidatorBalance, err := srv.JSONRPC().Eth().GetBalance(validatorAcc.Ecdsa.Address(), ethgo.Latest)
Expand All @@ -385,7 +383,7 @@ func TestE2E_Consensus_Validator_Unstake(t *testing.T) {

// query rootchain validator set and make sure that validator which unstaked all the funds isn't present in validator set anymore
// (execute it multiple times if needed, because it is unknown in advance how much time it is going to take until checkpoint is submitted)
rootchainValidators := []*validatorInfo{}
rootchainValidators := []*polybft.ValidatorInfo{}
err = cluster.Bridge.WaitUntil(time.Second, 10*time.Second, func() (bool, error) {
rootchainValidators, err = getRootchainValidators(l1Relayer, checkpointManagerAddr, rootchainSender)
if err != nil {
Expand All @@ -398,8 +396,8 @@ func TestE2E_Consensus_Validator_Unstake(t *testing.T) {
require.Equal(t, 4, len(rootchainValidators))

for _, validator := range rootchainValidators {
if validator.address == validatorAddr {
t.Fatalf("not expected to find validator %v in the current validator set", validator.address)
if validator.Address == validatorAddr {
t.Fatalf("not expected to find validator %v in the current validator set", validator.Address)
}
}
}
17 changes: 6 additions & 11 deletions e2e-polybft/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"math/big"

"github.com/0xPolygon/polygon-edge/consensus/polybft"
"github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi"
"github.com/0xPolygon/polygon-edge/helper/hex"
"github.com/0xPolygon/polygon-edge/txrelayer"
Expand All @@ -29,14 +30,8 @@ func (s *e2eStateProvider) Txn(ethgo.Address, ethgo.Key, []byte) (contract.Txn,
return nil, errors.New("send txn is not supported")
}

type validatorInfo struct {
address ethgo.Address
rewards *big.Int
totalStake *big.Int
}

// getRootchainValidators queries rootchain validator set
func getRootchainValidators(relayer txrelayer.TxRelayer, checkpointManagerAddr, sender ethgo.Address) ([]*validatorInfo, error) {
func getRootchainValidators(relayer txrelayer.TxRelayer, checkpointManagerAddr, sender ethgo.Address) ([]*polybft.ValidatorInfo, error) {
validatorsCountRaw, err := ABICall(relayer, contractsapi.CheckpointManager,
checkpointManagerAddr, sender, "currentValidatorSetLength")
if err != nil {
Expand All @@ -49,7 +44,7 @@ func getRootchainValidators(relayer txrelayer.TxRelayer, checkpointManagerAddr,
}

currentValidatorSetMethod := contractsapi.CheckpointManager.Abi.GetMethod("currentValidatorSet")
validators := make([]*validatorInfo, validatorsCount)
validators := make([]*polybft.ValidatorInfo, validatorsCount)

for i := 0; i < int(validatorsCount); i++ {
validatorRaw, err := ABICall(relayer, contractsapi.CheckpointManager,
Expand All @@ -74,9 +69,9 @@ func getRootchainValidators(relayer txrelayer.TxRelayer, checkpointManagerAddr,
}

//nolint:forcetypeassert
validators[i] = &validatorInfo{
address: results["_address"].(ethgo.Address),
totalStake: results["votingPower"].(*big.Int),
validators[i] = &polybft.ValidatorInfo{
Address: results["_address"].(ethgo.Address),
TotalStake: results["votingPower"].(*big.Int),
}
}

Expand Down

0 comments on commit f0275ea

Please sign in to comment.