Skip to content

Commit

Permalink
Merge pull request #28 from NilFoundation/several-validators-v2
Browse files Browse the repository at this point in the history
test: run consensus with several validators
  • Loading branch information
olegrok authored Feb 3, 2025
2 parents b8733c1 + a18fe72 commit 140f4f3
Show file tree
Hide file tree
Showing 12 changed files with 246 additions and 93 deletions.
29 changes: 12 additions & 17 deletions nil/cmd/exporter/internal/fetch_block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (

"github.com/NilFoundation/nil/nil/client/rpc"
"github.com/NilFoundation/nil/nil/common/logging"
"github.com/NilFoundation/nil/nil/internal/db"
"github.com/NilFoundation/nil/nil/internal/types"
"github.com/NilFoundation/nil/nil/services/nilservice"
rpctest "github.com/NilFoundation/nil/nil/services/rpc"
Expand All @@ -17,6 +16,7 @@ import (
type SuiteFetchBlock struct {
suite.Suite

server tests.RpcSuite
nShards uint32
cfg Cfg
context context.Context
Expand Down Expand Up @@ -57,23 +57,18 @@ func (s *SuiteFetchBlock) SetupSuite() {
Client: rpc.NewClient(url, logger),
}

database, err := db.NewBadgerDbInMemory()
s.Require().NoError(err)

cfg := nilservice.NewDefaultConfig()
cfg.NShards = s.nShards
cfg.HttpUrl = url
cfg.CollatorTickPeriodMs = 100

tmpDir := s.T().TempDir()
cfg.ValidatorKeysPath = tmpDir + "/validator-keys.yaml"
cfg.NetworkKeysPath = tmpDir + "/network-keys.yaml"
cfg.MainKeysOutPath = tmpDir + "/main-keys.yaml"

go nilservice.Run(s.context, cfg, database, nil)
tests.WaitBlock(s.T(), s.context, s.cfg.Client, types.MainShardId, 1)
cfg := &nilservice.Config{
NShards: s.nShards,
HttpUrl: url,
CollatorTickPeriodMs: 100,
}
s.server.SetT(s.T())
s.server.ShardsNum = s.nShards
s.server.Context = s.context
s.server.CtxCancel = s.cancel
s.server.Start(cfg)
}

func (s *SuiteFetchBlock) TearDownSuite() {
s.cancel()
s.server.Cancel()
}
40 changes: 23 additions & 17 deletions nil/internal/consensus/ibft/ibft.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/NilFoundation/nil/nil/go-ibft/core"
"github.com/NilFoundation/nil/nil/go-ibft/messages"
protoIBFT "github.com/NilFoundation/nil/nil/go-ibft/messages/proto"
"github.com/NilFoundation/nil/nil/internal/config"
"github.com/NilFoundation/nil/nil/internal/db"
"github.com/NilFoundation/nil/nil/internal/execution"
"github.com/NilFoundation/nil/nil/internal/network"
Expand All @@ -24,6 +25,7 @@ type ConsensusParams struct {
Validator validator
NetManager *network.Manager
PrivateKey *ecdsa.PrivateKey
Validators []config.ValidatorInfo
}

type validator interface {
Expand All @@ -33,15 +35,16 @@ type validator interface {
}

type backendIBFT struct {
ctx context.Context
db db.DB
consensus *core.IBFT
shardId types.ShardId
validator validator
logger zerolog.Logger
nm *network.Manager
transport transport
signer *Signer
ctx context.Context
db db.DB
consensus *core.IBFT
shardId types.ShardId
validator validator
logger zerolog.Logger
nm *network.Manager
transport transport
signer *Signer
validators []config.ValidatorInfo
}

var _ core.Backend = &backendIBFT{}
Expand Down Expand Up @@ -99,20 +102,23 @@ func NewConsensus(cfg *ConsensusParams) *backendIBFT {
}

backend := &backendIBFT{
db: cfg.Db,
shardId: cfg.ShardId,
validator: cfg.Validator,
logger: logger,
nm: cfg.NetManager,
signer: NewSigner(cfg.PrivateKey),
db: cfg.Db,
shardId: cfg.ShardId,
validator: cfg.Validator,
logger: logger,
nm: cfg.NetManager,
signer: NewSigner(cfg.PrivateKey),
validators: cfg.Validators,
}
backend.consensus = core.NewIBFT(l, backend, backend)
return backend
}

func (i *backendIBFT) GetVotingPowers(height uint64) (map[string]*big.Int, error) {
result := make(map[string]*big.Int)
result[string(i.ID())] = big.NewInt(1)
result := make(map[string]*big.Int, len(i.validators))
for _, v := range i.validators {
result[string(v.PublicKey[:])] = big.NewInt(1)
}
return result, nil
}

Expand Down
4 changes: 2 additions & 2 deletions nil/internal/consensus/ibft/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ func (s *Signer) Sign(data []byte) (types.Signature, error) {
}

func (s *Signer) Verify(data []byte, signature types.Signature) bool {
return s.verifyWithKey(s.rawPublicKey, data, signature)
return s.VerifyWithKey(s.rawPublicKey, data, signature)
}

func (s *Signer) verifyWithKey(publicKey []byte, data []byte, signature types.Signature) bool {
func (s *Signer) VerifyWithKey(publicKey []byte, data []byte, signature types.Signature) bool {
return len(signature) >= 64 && crypto.VerifySignature(publicKey, getHash(data), signature[:64])
}

Expand Down
10 changes: 10 additions & 0 deletions nil/internal/consensus/ibft/validators.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package ibft

import (
"github.com/NilFoundation/nil/nil/internal/config"
)

func (i *backendIBFT) calcProposer(height, round uint64) config.ValidatorInfo {
index := (height + round) % uint64(len(i.validators))
return i.validators[index]
}
27 changes: 23 additions & 4 deletions nil/internal/consensus/ibft/verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package ibft

import (
"bytes"
"slices"

"github.com/NilFoundation/nil/nil/common/logging"
"github.com/NilFoundation/nil/nil/go-ibft/messages"
protoIBFT "github.com/NilFoundation/nil/nil/go-ibft/messages/proto"
"github.com/NilFoundation/nil/nil/internal/config"
)

func (i *backendIBFT) IsValidProposal(rawProposal []byte) bool {
Expand All @@ -24,8 +26,24 @@ func (i *backendIBFT) IsValidValidator(msg *protoIBFT.IbftMessage) bool {
return false
}

if !i.signer.Verify(msgNoSig, msg.Signature) {
event := i.logger.Error().Stringer(logging.FieldType, msg.GetType())
index := slices.IndexFunc(i.validators, func(v config.ValidatorInfo) bool {
return bytes.Equal(v.PublicKey[:], msg.From)
})
if index == -1 {
event := i.logger.Error().
Hex("key", msg.From)

if view := msg.GetView(); view != nil {
event = event.Uint64(logging.FieldHeight, view.Height).
Uint64(logging.FieldRound, view.Round)
}
event.Msg("Key not found in validators list")
return false
}

validator := i.validators[index]
if !i.signer.VerifyWithKey(validator.PublicKey[:], msgNoSig, msg.Signature) {
event := i.logger.Error()
if view := msg.GetView(); view != nil {
event = event.Uint64(logging.FieldHeight, view.Height).
Uint64(logging.FieldRound, view.Round)
Expand All @@ -38,7 +56,8 @@ func (i *backendIBFT) IsValidValidator(msg *protoIBFT.IbftMessage) bool {
}

func (i *backendIBFT) IsProposer(id []byte, height, round uint64) bool {
return true
proposer := i.calcProposer(height, round)
return bytes.Equal(proposer.PublicKey[:], id)
}

func (i *backendIBFT) IsValidProposalHash(proposal *protoIBFT.Proposal, hash []byte) bool {
Expand Down Expand Up @@ -66,7 +85,7 @@ func (i *backendIBFT) IsValidProposalHash(proposal *protoIBFT.Proposal, hash []b
}

func (i *backendIBFT) IsValidCommittedSeal(
proposalHash []byte,
_ []byte,
committedSeal *messages.CommittedSeal,
) bool {
return true
Expand Down
29 changes: 19 additions & 10 deletions nil/services/nilservice/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ func NewDefaultConfig() *Config {
GracefulShutdown: true,
Topology: collate.TrivialShardTopologyId,

Validators: make(map[types.ShardId][]config.ValidatorInfo),

Network: network.NewDefaultConfig(),
Telemetry: telemetry.NewDefaultConfig(),
Replay: NewDefaultReplayConfig(),
Expand Down Expand Up @@ -171,25 +173,32 @@ func (c *Config) Validate() error {
return nil
}

func (c *Config) LoadValidatorPrivateKey() (key *ecdsa.PrivateKey, err error) {
defer func() {
if err == nil {
Logger.Trace().
Hex(logging.FieldPublicKey, crypto.FromECDSAPub(&key.PublicKey)).
Msg("Loaded validator key")
}
}()
func (c *Config) loadValidatorKeys() error {
if c.ValidatorKeysPath == "" {
return execution.MainPrivateKey, nil
return nil
}

if c.ValidatorKeysManager == nil {
c.ValidatorKeysManager = keys.NewValidatorKeyManager(c.ValidatorKeysPath)
if err := c.ValidatorKeysManager.InitKey(); err != nil {
return nil, err
return err
}
}

return nil
}

func (c *Config) LoadValidatorPrivateKey() (key *ecdsa.PrivateKey, err error) {
defer func() {
if err == nil {
Logger.Trace().
Hex(logging.FieldPublicKey, crypto.FromECDSAPub(&key.PublicKey)).
Msg("Loaded validator key")
}
}()
if err := c.loadValidatorKeys(); err != nil {
return nil, err
}
return c.ValidatorKeysManager.GetKey()
}

Expand Down
14 changes: 14 additions & 0 deletions nil/services/nilservice/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/NilFoundation/nil/nil/common/concurrent"
"github.com/NilFoundation/nil/nil/common/logging"
"github.com/NilFoundation/nil/nil/internal/collate"
"github.com/NilFoundation/nil/nil/internal/config"
"github.com/NilFoundation/nil/nil/internal/consensus/ibft"
"github.com/NilFoundation/nil/nil/internal/db"
"github.com/NilFoundation/nil/nil/internal/execution"
Expand Down Expand Up @@ -471,6 +472,18 @@ func createShards(
return nil, nil, err
}

if !cfg.SplitShards && len(cfg.Validators) == 0 {
pubkey, err := cfg.ValidatorKeysManager.GetPublicKey()
if err != nil {
return nil, nil, err
}
for i := range cfg.NShards {
cfg.Validators[types.ShardId(i)] = []config.ValidatorInfo{
{PublicKey: config.Pubkey(pubkey)},
}
}
}

for i := range cfg.NShards {
shardId := types.ShardId(i)

Expand Down Expand Up @@ -526,6 +539,7 @@ func createShards(
Validator: collator.Validator(),
NetManager: networkManager,
PrivateKey: pKey,
Validators: cfg.Validators[shardId],
})
if err := consensus.Init(ctx); err != nil {
return nil, nil, err
Expand Down
46 changes: 9 additions & 37 deletions nil/services/synccommittee/core/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,55 +6,31 @@ import (
"testing"
"time"

"github.com/NilFoundation/nil/nil/client/rpc"
"github.com/NilFoundation/nil/nil/internal/collate"
"github.com/NilFoundation/nil/nil/internal/db"
"github.com/NilFoundation/nil/nil/internal/types"
"github.com/NilFoundation/nil/nil/services/nilservice"
rpctest "github.com/NilFoundation/nil/nil/services/rpc"
"github.com/NilFoundation/nil/nil/services/rpc/transport"
"github.com/NilFoundation/nil/nil/services/synccommittee/internal/rollupcontract"
"github.com/rs/zerolog"
"github.com/NilFoundation/nil/nil/tests"
"github.com/stretchr/testify/suite"
)

type SyncCommitteeTestSuite struct {
suite.Suite

server tests.RpcSuite
nShards uint32
syncCommittee *SyncCommittee
nilCancel context.CancelFunc
doneChan chan interface{} // to track when nilservice has finished
ctx context.Context
nilDb db.DB
scDb db.DB
}

func (s *SyncCommitteeTestSuite) waitZerostrate(endpoint string) {
s.T().Helper()
client := rpc.NewClient(endpoint, zerolog.Nop())
const (
zeroStateWaitTimeout = 5 * time.Second
zeroStatePollInterval = time.Second
)
for i := range s.nShards {
s.Require().Eventually(func() bool {
block, err := client.GetBlock(s.ctx, types.ShardId(i), transport.BlockNumber(0), false)
return err == nil && block != nil
}, zeroStateWaitTimeout, zeroStatePollInterval)
}
}

func (s *SyncCommitteeTestSuite) SetupSuite() {
s.nShards = 4
s.ctx = context.Background()

url := rpctest.GetSockPath(s.T())

var err error
s.nilDb, err = db.NewBadgerDbInMemory()
s.Require().NoError(err)

// Setup nilservice
nilserviceCfg := &nilservice.Config{
NShards: s.nShards,
Expand All @@ -63,19 +39,17 @@ func (s *SyncCommitteeTestSuite) SetupSuite() {
CollatorTickPeriodMs: 100,
GasBasePrice: 10,
}
var nilContext context.Context
nilContext, s.nilCancel = context.WithCancel(context.Background())
s.doneChan = make(chan interface{})
go func() {
nilservice.Run(nilContext, nilserviceCfg, s.nilDb, nil)
s.doneChan <- nil
}()

s.waitZerostrate(url)
nilContext, nilCancel := context.WithCancel(s.ctx)
s.server.SetT(s.T())
s.server.Context = nilContext
s.server.CtxCancel = nilCancel
s.server.Start(nilserviceCfg)

cfg := NewDefaultConfig()
cfg.RpcEndpoint = url

var err error
s.scDb, err = db.NewBadgerDbInMemory()
s.Require().NoError(err)
ethClientMock := &rollupcontract.EthClientMock{ChainIDFunc: func(ctx context.Context) (*big.Int, error) { return big.NewInt(0), nil }}
Expand All @@ -84,9 +58,7 @@ func (s *SyncCommitteeTestSuite) SetupSuite() {
}

func (s *SyncCommitteeTestSuite) TearDownSuite() {
s.nilCancel()
<-s.doneChan // Wait for nilservice to shutdown
s.nilDb.Close()
s.server.Cancel()
s.scDb.Close()
}

Expand Down
2 changes: 1 addition & 1 deletion nil/services/txnpool/txnpool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ func (s *SuiteTxnPool) TestNetwork() {
has, err := pool2.IdHashKnown(txn.Hash())
s.Require().NoError(err)
return has
}, 10*time.Second, 100*time.Millisecond)
}, 20*time.Second, 200*time.Millisecond)
}

func TestSuiteTxnpool(t *testing.T) {
Expand Down
Loading

0 comments on commit 140f4f3

Please sign in to comment.