Skip to content

Commit

Permalink
EVM-396 TOB-EDGE-29: BLS Rogue attack + align Polybft with smart cont…
Browse files Browse the repository at this point in the history
…racts dev branch (0xPolygon#1184)

* all the changes from current core-contracts dev
* two different bls domains
  • Loading branch information
igorcrevar authored Feb 13, 2023
1 parent f3da43a commit 28eda73
Show file tree
Hide file tree
Showing 38 changed files with 384 additions and 210 deletions.
2 changes: 2 additions & 0 deletions command/e2e/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const (
registratorDataDirFlag = "registrator-data-dir"
balanceFlag = "balance"
stakeFlag = "stake"
chainIDFlag = "chain-id"
)

type registerParams struct {
Expand All @@ -21,6 +22,7 @@ type registerParams struct {
jsonRPCAddr string
balance string
stake string
chainID int64
}

func (rp *registerParams) validateFlags() error {
Expand Down
17 changes: 14 additions & 3 deletions command/e2e/register_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ import (
"time"

"github.com/0xPolygon/polygon-edge/chain"
"github.com/0xPolygon/polygon-edge/command"
"github.com/0xPolygon/polygon-edge/command/helper"
"github.com/0xPolygon/polygon-edge/consensus/polybft"
"github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi"
bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer"
"github.com/0xPolygon/polygon-edge/consensus/polybft/wallet"
"github.com/0xPolygon/polygon-edge/contracts"
"github.com/0xPolygon/polygon-edge/crypto"
Expand Down Expand Up @@ -70,6 +73,13 @@ func setFlags(cmd *cobra.Command) {
"stake represents amount which is going to be staked by the new validator account",
)

cmd.Flags().Int64Var(
&params.chainID,
chainIDFlag,
command.DefaultChainID,
"the ID of the chain",
)

helper.RegisterJSONRPCFlag(cmd)
}

Expand Down Expand Up @@ -128,7 +138,7 @@ func runCommand(cmd *cobra.Command, _ []string) error {
{
name: "register",
action: func() asyncTxn {
return registerValidator(newValidatorSender, newValidatorAccount)
return registerValidator(newValidatorSender, newValidatorAccount, params.chainID)
},
postHook: func(receipt *ethgo.Receipt) error {
if receipt.Status != uint64(types.ReceiptSuccess) {
Expand Down Expand Up @@ -474,12 +484,13 @@ func fund(sender *txnSender, addr types.Address) asyncTxn {
return sender.sendTransaction(txn)
}

func registerValidator(sender *txnSender, account *wallet.Account) asyncTxn {
func registerValidator(sender *txnSender, account *wallet.Account, chainID int64) asyncTxn {
if registerFn == nil {
return &asyncTxnImpl{err: errors.New("failed to create register ABI function")}
}

signature, err := account.Bls.Sign([]byte(contracts.PolyBFTRegisterMessage))
signature, err := polybft.MakeKOSKSignature(
account.Bls, types.Address(sender.account.Ecdsa.Address()), chainID, bls.DomainValidatorSet)
if err != nil {
return &asyncTxnImpl{err: err}
}
Expand Down
10 changes: 5 additions & 5 deletions command/genesis/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,12 @@ func ReadValidatorsByPrefix(dir, prefix string) ([]*polybft.Validator, error) {
return nil, err
}

validator := &polybft.Validator{
Address: types.Address(account.Ecdsa.Address()),
BlsKey: hex.EncodeToString(account.Bls.PublicKey().Marshal()),
NodeID: nodeID,
validators[i] = &polybft.Validator{
Address: types.Address(account.Ecdsa.Address()),
BlsPrivateKey: account.Bls,
BlsKey: hex.EncodeToString(account.Bls.PublicKey().Marshal()),
NodeID: nodeID,
}
validators[i] = validator
}

return validators, nil
Expand Down
37 changes: 28 additions & 9 deletions command/polybftmanifest/manifest_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ const (
validatorsFlag = "validators"
validatorsPathFlag = "validators-path"
validatorsPrefixFlag = "validators-prefix"
chainIDFlag = "chain-id"

defaultValidatorPrefixPath = "test-chain-"
defaultManifestPath = "./manifest.json"

nodeIDLength = 53
ecdsaAddressLength = 42
blsKeyLength = 2
blsKeyLength = 258
blsSignatureLength = 130
)

var (
Expand Down Expand Up @@ -73,6 +75,13 @@ func setFlags(cmd *cobra.Command) {
"folder prefix names for polybft validator keys",
)

cmd.Flags().Int64Var(
&params.chainID,
chainIDFlag,
command.DefaultChainID,
"the ID of the chain",
)

cmd.Flags().StringArrayVar(
&params.validators,
validatorsFlag,
Expand Down Expand Up @@ -102,7 +111,7 @@ func runCommand(cmd *cobra.Command, _ []string) {
return
}

manifest := &polybft.Manifest{GenesisValidators: validators}
manifest := &polybft.Manifest{GenesisValidators: validators, ChainID: params.chainID}
if err = manifest.Save(params.manifestPath); err != nil {
outputter.SetError(fmt.Errorf("failed to save manifest file '%s': %w", params.manifestPath, err))

Expand All @@ -118,6 +127,7 @@ type manifestInitParams struct {
validatorsPrefixPath string
premineValidators string
validators []string
chainID int64
}

func (p *manifestInitParams) validateFlags() error {
Expand All @@ -144,9 +154,9 @@ func (p *manifestInitParams) getValidatorAccounts() ([]*polybft.Validator, error
for i, validator := range p.validators {
parts := strings.Split(validator, ":")

if len(parts) != 3 {
return nil, fmt.Errorf("expected 3 parts provided in the following format "+
"<nodeId:ECDSA address:blsKey>, but got %d part(s)",
if len(parts) != 4 {
return nil, fmt.Errorf("expected 4 parts provided in the following format "+
"<nodeId:ECDSA address:blsKey:blsSignature>, but got %d part(s)",
len(parts))
}

Expand All @@ -162,11 +172,16 @@ func (p *manifestInitParams) getValidatorAccounts() ([]*polybft.Validator, error
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])
}

validators[i] = &polybft.Validator{
NodeID: parts[0],
Address: types.StringToAddress(parts[1]),
BlsKey: parts[2],
Balance: balance,
NodeID: parts[0],
Address: types.StringToAddress(parts[1]),
BlsKey: parts[2],
BlsSignature: parts[3],
Balance: balance,
}
}

Expand All @@ -184,6 +199,10 @@ func (p *manifestInitParams) getValidatorAccounts() ([]*polybft.Validator, error
}

for _, v := range validators {
if err = v.InitKOSKSignature(p.chainID); err != nil {
return nil, err
}

v.Balance = balance
}

Expand Down
3 changes: 1 addition & 2 deletions command/rootchain/initcontracts/init_contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
"github.com/0xPolygon/polygon-edge/command/rootchain/helper"
"github.com/0xPolygon/polygon-edge/consensus/polybft"
"github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi"
bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer"
"github.com/0xPolygon/polygon-edge/contracts"
"github.com/0xPolygon/polygon-edge/txrelayer"
"github.com/0xPolygon/polygon-edge/types"
Expand Down Expand Up @@ -269,9 +268,9 @@ func initializeCheckpointManager(
}

initialize := contractsapi.InitializeCheckpointManagerFunction{
ChainID_: big.NewInt(manifest.ChainID),
NewBls: manifest.RootchainConfig.BLSAddress,
NewBn256G2: manifest.RootchainConfig.BN256G2Address,
NewDomain: types.BytesToHash(bls.GetDomain()),
NewValidatorSet: validatorSet,
}

Expand Down
15 changes: 5 additions & 10 deletions command/sidechain/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,13 @@ func GetValidatorInfo(validatorAddr ethgo.Address, txRelayer txrelayer.TxRelayer
return nil, fmt.Errorf("could not convert decoded outputs to map")
}

decodedValidatorInfoMap, ok := decodedOutputsMap["0"].(map[string]interface{})
if !ok {
return nil, fmt.Errorf("could not convert validator info result to a map")
}

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
Stake: decodedOutputsMap["stake"].(*big.Int), //nolint:forcetypeassert
TotalStake: decodedOutputsMap["totalStake"].(*big.Int), //nolint:forcetypeassert
Commission: decodedOutputsMap["commission"].(*big.Int), //nolint:forcetypeassert
WithdrawableRewards: decodedOutputsMap["withdrawableRewards"].(*big.Int), //nolint:forcetypeassert
Active: decodedOutputsMap["active"].(bool), //nolint:forcetypeassert
}, nil
}

Expand Down
1 change: 0 additions & 1 deletion consensus/polybft/checkpoint_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,6 @@ func (c *checkpointManager) abiEncodeCheckpointBlock(blockNumber uint64, blockHa
}

submit := &contractsapi.SubmitFunction{
ChainID: new(big.Int).SetUint64(c.blockchain.GetChainID()),
CheckpointMetadata: &contractsapi.CheckpointMetadata{
BlockHash: blockHash,
BlockRound: new(big.Int).SetUint64(extra.Checkpoint.BlockRound),
Expand Down
3 changes: 2 additions & 1 deletion consensus/polybft/consensus_runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/0xPolygon/go-ibft/messages/proto"
"github.com/0xPolygon/polygon-edge/consensus"
"github.com/0xPolygon/polygon-edge/consensus/polybft/bitmap"
bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer"
"github.com/0xPolygon/polygon-edge/consensus/polybft/wallet"
"github.com/0xPolygon/polygon-edge/contracts"
"github.com/0xPolygon/polygon-edge/crypto"
Expand Down Expand Up @@ -335,7 +336,7 @@ func TestConsensusRuntime_FSM_NotEndOfEpoch_NotEndOfSprint(t *testing.T) {
EpochSize: 10,
SprintSize: 5,
},
Key: wallet.NewKey(validators.getPrivateIdentities()[0]),
Key: wallet.NewKey(validators.getPrivateIdentities()[0], bls.DomainCheckpointManager),
blockchain: blockchainMock,
}
runtime := &consensusRuntime{
Expand Down
52 changes: 13 additions & 39 deletions consensus/polybft/contracts_initializer.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package polybft

import (
"encoding/hex"
"fmt"
"math/big"

"github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi"
bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer"
"github.com/0xPolygon/polygon-edge/contracts"
"github.com/0xPolygon/polygon-edge/state"
"github.com/0xPolygon/polygon-edge/types"
Expand All @@ -25,54 +23,30 @@ var (
)

func getInitChildValidatorSetInput(polyBFTConfig PolyBFTConfig) ([]byte, error) {
validatorAddresses := make([]types.Address, len(polyBFTConfig.InitialValidatorSet))
validatorPubkeys := make([][4]*big.Int, len(polyBFTConfig.InitialValidatorSet))
validatorStakes := make([]*big.Int, len(polyBFTConfig.InitialValidatorSet))
apiValidators := make([]*contractsapi.ValidatorInit, len(polyBFTConfig.InitialValidatorSet))

for i, validator := range polyBFTConfig.InitialValidatorSet {
blsKey, err := hex.DecodeString(validator.BlsKey)
validatorData, err := validator.ToValidatorInitAPIBinding()
if err != nil {
return nil, err
}

pubKey, err := bls.UnmarshalPublicKey(blsKey)
if err != nil {
return nil, err
}

pubKeyBig := pubKey.ToBigInt()

validatorPubkeys[i] = pubKeyBig
validatorAddresses[i] = validator.Address
validatorStakes[i] = new(big.Int).Set(validator.Balance)
apiValidators[i] = validatorData
}

registerMessage, err := bls.MarshalMessageToBigInt([]byte(contracts.PolyBFTRegisterMessage))
if err != nil {
return nil, err
}

params := map[string]interface{}{
"init": map[string]interface{}{
"epochReward": new(big.Int).SetUint64(polyBFTConfig.EpochReward),
"minStake": big.NewInt(minStake),
"minDelegation": big.NewInt(minDelegation),
"epochSize": new(big.Int).SetUint64(polyBFTConfig.EpochSize),
params := &contractsapi.InitializeChildValidatorSetFunction{
Init: &contractsapi.InitStruct{
EpochReward: new(big.Int).SetUint64(polyBFTConfig.EpochReward),
MinStake: big.NewInt(minStake),
MinDelegation: big.NewInt(minDelegation),
EpochSize: new(big.Int).SetUint64(polyBFTConfig.EpochSize),
},
"validatorAddresses": validatorAddresses,
"validatorPubkeys": validatorPubkeys,
"validatorStakes": validatorStakes,
"newBls": contracts.BLSContract, // address of the deployed BLS contract
"newMessage": registerMessage,
"governance": polyBFTConfig.Governance,
}

input, err := contractsapi.ChildValidatorSet.Abi.Methods["initialize"].Encode(params)
if err != nil {
return nil, err
NewBls: contracts.BLSContract,
Governance: polyBFTConfig.Governance,
Validators: apiValidators,
}

return input, nil
return params.EncodeAbi()
}

func initContract(to types.Address, input []byte, contractName string, transition *state.Transition) error {
Expand Down
1 change: 1 addition & 0 deletions consensus/polybft/contractsapi/bindings-gen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func main() {
gensc.ChildValidatorSet,
[]string{
"commitEpoch",
"initialize",
},
[]string{},
},
Expand Down
Loading

0 comments on commit 28eda73

Please sign in to comment.