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

[RFC-201/205] Staking and validator storage rework #1442

Merged
merged 27 commits into from
May 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4dd4745
Use rework branch on core-contracts
goran-ethernal Apr 6, 2023
5528422
EVM-578: Deploy new contracts for staking and supernets (#1368)
goran-ethernal Apr 19, 2023
a9d5796
Rebase fix
goran-ethernal Apr 20, 2023
d57faa2
[RFC-201/205]: EVM-596-Change whitelist and register commands (#1404)
goran-ethernal Apr 21, 2023
560e1f0
[RFC-201/205]: EVM-603-Register supernet and child chain (#1406)
goran-ethernal Apr 21, 2023
38788d8
[RFC-201/205]: EVM-606-Change stake command (#1408)
goran-ethernal Apr 24, 2023
8585cf5
[RFC-201/205]: EVM-608-Supernet command (#1409)
goran-ethernal Apr 24, 2023
5b8b458
[RFC201/205]: EVM-613-Change validator info command (#1421)
goran-ethernal Apr 24, 2023
a36277e
[RFC-201/205]: EVM-582-Validate validator set delta (#1423)
goran-ethernal Apr 25, 2023
1e742a8
[RFC-201/205]: EVM-580-Update validator set in stake manager (#1431)
goran-ethernal Apr 26, 2023
1d8a63f
[RFC-201/205]: EVM-619-Commit-epoch-on-new-ValidatorSet-contract (#1436)
goran-ethernal Apr 27, 2023
a27c59f
[RFC-201/205]: EVM-622-Save full validator set in db (#1445)
goran-ethernal Apr 28, 2023
0115395
[RFC-201/205]: EVM-579-Change deployment steps in e2e tests (#1446)
goran-ethernal Apr 28, 2023
a0fa765
Merge branch 'develop' into feat/validator-storage-rework
Stefan-Ethernal Apr 28, 2023
46f1fbf
[RFC-201/205]: Reward token configuration (#1453)
goran-ethernal Apr 28, 2023
f19e7d5
Return chainId in KOSK signature
goran-ethernal Apr 28, 2023
1fa9674
Fix KOSK signature
goran-ethernal Apr 28, 2023
f664e5b
[RFC-201/205] E2E test fixing (#1452)
igorcrevar May 2, 2023
4d68e68
Merge commit '852f44a27e99efc405979220f1f3ab6299e484c2' into feat/val…
goran-ethernal May 2, 2023
900ad3f
Update stake in genesis based on finalized stake on StakeManager
goran-ethernal May 2, 2023
7785969
Lint fix
goran-ethernal May 2, 2023
414221a
Remove init function from consensus_test.go
Stefan-Ethernal May 3, 2023
d207743
Small code cleanup
goran-ethernal May 3, 2023
0c31697
Reward config fix
goran-ethernal May 3, 2023
b38fca0
E2E test for custom reward token
goran-ethernal May 3, 2023
a315f23
Lint fix
goran-ethernal May 3, 2023
f3e2ba5
New stake manager UTs
goran-ethernal May 3, 2023
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
2 changes: 0 additions & 2 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,3 @@
[submodule "core-contracts"]
path = core-contracts
url = https://github.com/0xPolygon/core-contracts
shallow = true
branch = feat-polybft-release
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ test-e2e-polybft:
# We can not build with race because of a bug in boltdb dependency
go build -o artifacts/polygon-edge .
env EDGE_BINARY=${PWD}/artifacts/polygon-edge E2E_TESTS=true E2E_LOGS=true \
go test -v -timeout=45m ./e2e-polybft/e2e/...
go test -v -timeout=1h30m ./e2e-polybft/e2e/...

.PHONY: test-property-polybft
test-property-polybft:
Expand Down
48 changes: 3 additions & 45 deletions command/bridge/deposit/erc20/deposit_erc20.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ func runCommand(cmd *cobra.Command, _ []string) {

if dp.testMode {
// mint tokens to depositor, so he is able to send them
mintTxn, err := createMintTxn(types.Address(depositorAddr), types.Address(depositorAddr), aggregateAmount)
mintTxn, err := helper.CreateMintTxn(types.Address(depositorAddr),
types.StringToAddress(dp.TokenAddr), aggregateAmount)
if err != nil {
outputter.SetError(fmt.Errorf("mint transaction creation failed: %w", err))

Expand All @@ -165,7 +166,7 @@ func runCommand(cmd *cobra.Command, _ []string) {
}

// approve root erc20 predicate
approveTxn, err := createApproveERC20PredicateTxn(aggregateAmount,
approveTxn, err := helper.CreateApproveERC20Txn(aggregateAmount,
types.StringToAddress(dp.PredicateAddr),
types.StringToAddress(dp.TokenAddr))
if err != nil {
Expand Down Expand Up @@ -253,49 +254,6 @@ func createDepositTxn(sender, receiver types.Address, amount *big.Int) (*ethgo.T
}, nil
}

// createMintTxn encodes parameters for mint function on rootchain token contract
func createMintTxn(sender, receiver types.Address, amount *big.Int) (*ethgo.Transaction, error) {
mintFn := &contractsapi.MintRootERC20Fn{
To: receiver,
Amount: amount,
}

input, err := mintFn.EncodeAbi()
if err != nil {
return nil, fmt.Errorf("failed to encode provided parameters: %w", err)
}

addr := ethgo.Address(types.StringToAddress(dp.TokenAddr))

return &ethgo.Transaction{
From: ethgo.Address(sender),
To: &addr,
Input: input,
}, nil
}

// createApproveERC20PredicateTxn sends approve transaction
// to ERC20 token for ERC20 predicate so that it is able to spend given tokens
func createApproveERC20PredicateTxn(amount *big.Int,
rootERC20Predicate, rootERC20Token types.Address) (*ethgo.Transaction, error) {
approveFnParams := &contractsapi.ApproveRootERC20Fn{
Spender: rootERC20Predicate,
Amount: amount,
}

input, err := approveFnParams.EncodeAbi()
if err != nil {
return nil, fmt.Errorf("failed to encode parameters for RootERC20.approve. error: %w", err)
}

addr := ethgo.Address(rootERC20Token)

return &ethgo.Transaction{
To: &addr,
Input: input,
}, nil
}

type depositERC20Result struct {
Sender string `json:"sender"`
Receivers []string `json:"receivers"`
Expand Down
16 changes: 15 additions & 1 deletion command/genesis/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ func setFlags(cmd *cobra.Command) {
&params.validators,
validatorsFlag,
[]string{},
"validators defined by user (format: <P2P multi address>:<ECDSA address>:<public BLS key>:<BLS signature>)",
"validators defined by user (format: <P2P multi address>:<ECDSA address>:<public BLS key>)",
)

cmd.Flags().StringArrayVar(
Expand Down Expand Up @@ -232,6 +232,20 @@ func setFlags(cmd *cobra.Command) {
"",
"configuration of native token in format <name:symbol:decimals count>",
)

cmd.Flags().StringVar(
&params.rewardTokenCode,
rewardTokenCodeFlag,
"",
"hex encoded reward token byte code",
)

cmd.Flags().StringVar(
&params.rewardWallet,
rewardWalletFlag,
"",
"configuration of reward wallet in format <address:amount>",
)
}

// Access Control Lists
Expand Down
34 changes: 34 additions & 0 deletions command/genesis/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"math"
"math/big"
"os"
"strconv"
"strings"
Expand Down Expand Up @@ -37,6 +38,8 @@ const (
maxValidatorCount = "max-validator-count"
mintableTokenFlag = "mintable-native-token"
nativeTokenConfigFlag = "native-token-config"
rewardTokenCodeFlag = "reward-token-code"
rewardWalletFlag = "reward-wallet"

defaultNativeTokenName = "Polygon"
defaultNativeTokenSymbol = "MATIC"
Expand All @@ -59,6 +62,7 @@ var (
errInvalidEpochSize = errors.New("epoch size must be greater than 1")
errInvalidTokenParams = errors.New("native token params were not submitted in proper" +
" format <name:symbol:decimals count>")
errRewardWalletAmountZero = errors.New("reward wallet amount can not be zero or negative")
)

type genesisParams struct {
Expand Down Expand Up @@ -121,6 +125,10 @@ type genesisParams struct {
mintableNativeToken bool
nativeTokenConfigRaw string
nativeTokenConfig *polybft.TokenConfig

// rewards
rewardTokenCode string
rewardWallet string
}

func (p *genesisParams) validateFlags() error {
Expand All @@ -140,6 +148,10 @@ func (p *genesisParams) validateFlags() error {
if err := p.extractNativeTokenMetadata(); err != nil {
return err
}

if err := p.validateRewardWallet(); err != nil {
return err
}
}

// Check if the genesis file already exists
Expand Down Expand Up @@ -440,6 +452,28 @@ func (p *genesisParams) predeployStakingSC() (*chain.GenesisAccount, error) {
return stakingAccount, nil
}

// validateRewardWallet validates reward wallet flag
func (p *genesisParams) validateRewardWallet() error {
if p.rewardWallet == "" {
return errors.New("reward wallet address must be defined")
}

if p.rewardWallet == types.AddressToString(types.ZeroAddress) {
return errors.New("reward wallet address must not be zero address")
}

premineInfo, err := parsePremineInfo(p.rewardWallet)
if err != nil {
return err
}

if premineInfo.amount.Cmp(big.NewInt(0)) < 1 {
return errRewardWalletAmountZero
}

return nil
}

// extractNativeTokenMetadata parses provided native token metadata (such as name, symbol and decimals count)
func (p *genesisParams) extractNativeTokenMetadata() error {
if p.nativeTokenConfigRaw == "" {
Expand Down
85 changes: 60 additions & 25 deletions command/genesis/polybft_params.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package genesis

import (
"encoding/hex"
"errors"
"fmt"
"math/big"
Expand Down Expand Up @@ -58,7 +59,6 @@ const (

ecdsaAddressLength = 40
blsKeyLength = 256
blsSignatureLength = 128
)

var (
Expand All @@ -79,6 +79,30 @@ func (p *genesisParams) generatePolyBftChainConfig(o command.OutputFormatter) er
premineBalances[premineInfo.address] = premineInfo
}

walletPremineInfo, err := parsePremineInfo(p.rewardWallet)
if err != nil {
return fmt.Errorf("invalid reward wallet configuration provided '%s' : %w", p.rewardWallet, err)
}

var (
rewardTokenByteCode []byte
rewardTokenAddr = contracts.NativeERC20TokenContract
)

if p.rewardTokenCode == "" {
// native token is used as a reward token, and reward wallet is not a zero address
// so we need to add that address to premine map
premineBalances[walletPremineInfo.address] = walletPremineInfo
} else {
bytes, err := hex.DecodeString(p.rewardTokenCode)
if err != nil {
return fmt.Errorf("could not decode reward token byte code '%s' : %w", p.rewardTokenCode, err)
}

rewardTokenByteCode = bytes
rewardTokenAddr = contracts.RewardTokenContract
}

initialValidators, err := p.getValidatorAccounts(premineBalances)
if err != nil {
return fmt.Errorf("failed to retrieve genesis validators: %w", err)
Expand Down Expand Up @@ -109,6 +133,12 @@ func (p *genesisParams) generatePolyBftChainConfig(o command.OutputFormatter) er
InitialTrieRoot: types.StringToHash(p.initialStateRoot),
MintableNativeToken: p.mintableNativeToken,
NativeTokenConfig: p.nativeTokenConfig,
MaxValidatorSetSize: p.maxNumValidators,
RewardConfig: &polybft.RewardsConfig{
TokenAddress: rewardTokenAddr,
WalletAddress: walletPremineInfo.address,
WalletAmount: walletPremineInfo.amount,
},
}

// Disable london hardfork if burn contract address is not provided
Expand All @@ -120,8 +150,7 @@ func (p *genesisParams) generatePolyBftChainConfig(o command.OutputFormatter) er
chainConfig := &chain.Chain{
Name: p.name,
Params: &chain.Params{
ChainID: int64(p.chainID),
Forks: enabledForks,
Forks: enabledForks,
Engine: map[string]interface{}{
string(server.PolyBFTConsensus): polyBftConfig,
},
Expand All @@ -137,7 +166,7 @@ func (p *genesisParams) generatePolyBftChainConfig(o command.OutputFormatter) er
}

// deploy genesis contracts
allocs, err := p.deployContracts(totalStake)
allocs, err := p.deployContracts(totalStake, rewardTokenByteCode, polyBftConfig)
if err != nil {
return err
}
Expand Down Expand Up @@ -270,18 +299,15 @@ func (p *genesisParams) generatePolyBftChainConfig(o command.OutputFormatter) er
return helper.WriteGenesisConfigToDisk(chainConfig, params.genesisPath)
}

func (p *genesisParams) deployContracts(totalStake *big.Int) (map[types.Address]*chain.GenesisAccount, error) {
func (p *genesisParams) deployContracts(totalStake *big.Int,
rewardTokenByteCode []byte,
polybftConfig *polybft.PolyBFTConfig) (map[types.Address]*chain.GenesisAccount, error) {
type contractInfo struct {
artifact *artifact.Artifact
address types.Address
}

genesisContracts := []*contractInfo{
{
// ChildValidatorSet contract
artifact: contractsapi.ChildValidatorSet,
address: contracts.ValidatorSetContract,
},
{
// State receiver contract
artifact: contractsapi.StateReceiver,
Expand Down Expand Up @@ -332,6 +358,14 @@ func (p *genesisParams) deployContracts(totalStake *big.Int) (map[types.Address]
artifact: contractsapi.L2StateSender,
address: contracts.L2StateSenderContract,
},
{
artifact: contractsapi.ValidatorSet,
address: contracts.ValidatorSetContract,
},
{
artifact: contractsapi.RewardPool,
address: contracts.RewardPoolContract,
},
}

if !params.mintableNativeToken {
Expand All @@ -342,7 +376,7 @@ func (p *genesisParams) deployContracts(totalStake *big.Int) (map[types.Address]
&contractInfo{artifact: contractsapi.NativeERC20Mintable, address: contracts.NativeERC20TokenContract})
}

allocations := make(map[types.Address]*chain.GenesisAccount, len(genesisContracts))
allocations := make(map[types.Address]*chain.GenesisAccount, len(genesisContracts)+1)

for _, contract := range genesisContracts {
allocations[contract.address] = &chain.GenesisAccount{
Expand All @@ -351,8 +385,14 @@ func (p *genesisParams) deployContracts(totalStake *big.Int) (map[types.Address]
}
}

// ChildValidatorSet must have funds pre-allocated, because of withdrawal workflow
allocations[contracts.ValidatorSetContract].Balance = totalStake
if rewardTokenByteCode != nil {
// if reward token is provided in genesis then, add it to allocations
// to RewardTokenContract address and update polybftConfig
allocations[contracts.RewardTokenContract] = &chain.GenesisAccount{
Balance: big.NewInt(0),
Code: rewardTokenByteCode,
}
}

return allocations, nil
}
Expand Down Expand Up @@ -388,9 +428,9 @@ func (p *genesisParams) getValidatorAccounts(
validators := make([]*polybft.Validator, len(p.validators))
for i, validator := range p.validators {
parts := strings.Split(validator, ":")
if len(parts) != 4 {
if len(parts) != 3 {
return nil, fmt.Errorf("expected 4 parts provided in the following format "+
"<P2P multi address:ECDSA address:public BLS key:BLS signature>, but got %d part(s)",
"<P2P multi address:ECDSA address:public BLS key>, but got %d part(s)",
len(parts))
}

Expand All @@ -408,18 +448,13 @@ func (p *genesisParams) getValidatorAccounts(
return nil, fmt.Errorf("invalid BLS key: %s", parts[2])
}

if len(parts[3]) != blsSignatureLength {
return nil, fmt.Errorf("invalid BLS signature: %s", parts[3])
}

addr := types.StringToAddress(trimmedAddress)
validators[i] = &polybft.Validator{
MultiAddr: parts[0],
Address: addr,
BlsKey: trimmedBLSKey,
BlsSignature: parts[3],
Balance: getPremineAmount(addr, premineBalances, command.DefaultPremineBalance),
Stake: getPremineAmount(addr, stakeMap, command.DefaultStake),
MultiAddr: parts[0],
Address: addr,
BlsKey: trimmedBLSKey,
Balance: getPremineAmount(addr, premineBalances, command.DefaultPremineBalance),
Stake: getPremineAmount(addr, stakeMap, command.DefaultStake),
}
}

Expand Down
Loading