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

stabilization-equivalent-proofs #6686

Open
wants to merge 41 commits into
base: feat/equivalent-messages
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
be02d30
use EpochNotifier instead of EpochStartNotifier to transition to the …
AdoAdoAdo Dec 19, 2024
97b9e06
trigger consensus version change as validator
AdoAdoAdo Dec 19, 2024
ccdd6cb
temp change of equivalent messages enable epoch to shorten transition…
AdoAdoAdo Dec 20, 2024
75e042a
fixes integration tests
AdoAdoAdo Dec 20, 2024
6092d21
Merge branch 'feat/equivalent-messages' into equivalent-proofs-feat-s…
AdoAdoAdo Dec 20, 2024
5cd3d46
fixes integration tests
AdoAdoAdo Dec 20, 2024
330eb4a
fixes check proof on first block after genesis
AdoAdoAdo Dec 23, 2024
7832305
fix header finality check for equivalent proofs
AdoAdoAdo Dec 23, 2024
60584a0
adapt integration tests
AdoAdoAdo Dec 23, 2024
a8fb6f1
adapt integration tests
AdoAdoAdo Dec 23, 2024
df47f28
fixes & debug logs
AdoAdoAdo Dec 23, 2024
492631c
fix eqv proofs epoch cfg for chain simulator tests
AdoAdoAdo Jan 8, 2025
84c0b98
fix interceptor save unit test
AdoAdoAdo Jan 8, 2025
700f252
fixes header prev proof verification
AdoAdoAdo Jan 8, 2025
b03af58
avoid deadlock when switching consensus
AdoAdoAdo Jan 8, 2025
b1be55c
remove check on first block after activation
ssd04 Jan 9, 2025
f695092
integrate header proof round
ssd04 Jan 9, 2025
13d6458
add test for equivalent proof on shard block sync
ssd04 Jan 9, 2025
bbbeb98
Merge pull request #6697 from multiversx/check-proof-on-activation-bl…
AdoAdoAdo Jan 9, 2025
5f650fb
adapt fork detector and highest probable nonce for equivalent proofs
AdoAdoAdo Jan 9, 2025
b7d1990
Merge branch 'equivalent-proofs-feat-stabilization' of github.com:mul…
AdoAdoAdo Jan 9, 2025
2211c74
add the round to the header info
AdoAdoAdo Jan 9, 2025
f1a55a9
update tests
AdoAdoAdo Jan 9, 2025
958bf29
update more tests
AdoAdoAdo Jan 9, 2025
1235b89
added checks on proofs parameters like epoch, nonce and shard
sstanculeanu Jan 9, 2025
d4243bc
fixes after review
sstanculeanu Jan 10, 2025
681f506
small refactor + extended checks
sstanculeanu Jan 10, 2025
68ec7b7
integrate fork detector process received proof
AdoAdoAdo Jan 13, 2025
a1cf4c8
further fixes after review
sstanculeanu Jan 13, 2025
3db5c03
fixed typo
sstanculeanu Jan 13, 2025
5495467
Merge pull request #6698 from multiversx/check_proof_validity
sstanculeanu Jan 13, 2025
9c0a622
fix base fork detector process received block
AdoAdoAdo Jan 13, 2025
be77f2d
fix fork detector with equivalent proofs
AdoAdoAdo Jan 14, 2025
c3333bb
Merge remote-tracking branch 'origin/equivalent-proofs-feat-stabiliza…
AdoAdoAdo Jan 14, 2025
828708c
fix intercepted proof checks
AdoAdoAdo Jan 14, 2025
747cd55
fixes after review
AdoAdoAdo Jan 14, 2025
6e25ca3
fix check for accepting a proof on interceptor
AdoAdoAdo Jan 14, 2025
25276b1
remove v1 consensus callbacks from worker after v2 activation
AdoAdoAdo Jan 15, 2025
f61ee57
consensus v2 fixes
AdoAdoAdo Jan 15, 2025
6a11dbe
move setting of prev proof in processor and fix rating update
AdoAdoAdo Jan 15, 2025
0abb837
fix checkProofsForShardData and shard transition trigger
AdoAdoAdo Jan 15, 2025
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
4 changes: 2 additions & 2 deletions cmd/node/config/enableEpochs.toml
Original file line number Diff line number Diff line change
Expand Up @@ -319,10 +319,10 @@
CryptoOpcodesV2EnableEpoch = 4

# EquivalentMessagesEnableEpoch represents the epoch when the equivalent messages are enabled
EquivalentMessagesEnableEpoch = 4
EquivalentMessagesEnableEpoch = 8 # the chain simulator tests for staking v4 fail if this is set earlier, as they test the transition in epochs 4-7

# FixedOrderInConsensusEnableEpoch represents the epoch when the fixed order in consensus is enabled
FixedOrderInConsensusEnableEpoch = 4
FixedOrderInConsensusEnableEpoch = 8 # the chain simulator tests for staking v4 fail if this is set earlier, as they test the transition in epochs 4-7

# BLSMultiSignerEnableEpoch represents the activation epoch for different types of BLS multi-signers
BLSMultiSignerEnableEpoch = [
Expand Down
5 changes: 5 additions & 0 deletions common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,8 @@ func IsFlagEnabledAfterEpochsStartBlock(header data.HeaderHandler, enableEpochsH
isEpochStartBlock := IsEpochChangeBlockForFlagActivation(header, enableEpochsHandler, flag)
return isFlagEnabled && !isEpochStartBlock
}

// ShouldBlockHavePrevProof returns true if the block should have a proof
func ShouldBlockHavePrevProof(header data.HeaderHandler, enableEpochsHandler EnableEpochsHandler, flag core.EnableEpochFlag) bool {
return IsFlagEnabledAfterEpochsStartBlock(header, enableEpochsHandler, flag) && header.GetNonce() > 1
}
33 changes: 9 additions & 24 deletions consensus/spos/bls/proxy/subroundsHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package proxy
import (
"github.com/multiversx/mx-chain-core-go/core"
"github.com/multiversx/mx-chain-core-go/core/check"
"github.com/multiversx/mx-chain-core-go/data"
logger "github.com/multiversx/mx-chain-logger-go"

"github.com/multiversx/mx-chain-go/common"
Expand Down Expand Up @@ -57,6 +56,14 @@ type SubroundsHandler struct {
currentConsensusType consensusStateMachineType
}

// EpochConfirmed is called when the epoch is confirmed (this is registered as callback)
func (s *SubroundsHandler) EpochConfirmed(epoch uint32, _ uint64) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing comment

err := s.initSubroundsForEpoch(epoch)
if err != nil {
log.Error("SubroundsHandler.EpochStartAction: cannot initialize subrounds", "error", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
log.Error("SubroundsHandler.EpochStartAction: cannot initialize subrounds", "error", err)
log.Error("SubroundsHandler.EpochConfirmed: cannot initialize subrounds", "error", err)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}
}

const (
consensusNone consensusStateMachineType = iota
consensusV1
Expand Down Expand Up @@ -85,7 +92,7 @@ func NewSubroundsHandler(args *SubroundsHandlerArgs) (*SubroundsHandler, error)
currentConsensusType: consensusNone,
}

subroundHandler.consensusCoreHandler.EpochStartRegistrationHandler().RegisterHandler(subroundHandler)
subroundHandler.consensusCoreHandler.EpochNotifier().RegisterNotifyHandler(subroundHandler)

return subroundHandler, nil
}
Expand Down Expand Up @@ -189,28 +196,6 @@ func (s *SubroundsHandler) initSubroundsForEpoch(epoch uint32) error {
return nil
}

// EpochStartAction is called when the epoch starts
func (s *SubroundsHandler) EpochStartAction(hdr data.HeaderHandler) {
if check.IfNil(hdr) {
log.Error("SubroundsHandler.EpochStartAction: nil header")
return
}

err := s.initSubroundsForEpoch(hdr.GetEpoch())
if err != nil {
log.Error("SubroundsHandler.EpochStartAction: cannot initialize subrounds", "error", err)
}
}

// EpochStartPrepare prepares the subrounds handler for the epoch start
func (s *SubroundsHandler) EpochStartPrepare(_ data.HeaderHandler, _ data.BodyHandler) {
}

// NotifyOrder returns the order of the subrounds handler
func (s *SubroundsHandler) NotifyOrder() uint32 {
return common.ConsensusHandlerOrder
}

// IsInterfaceNil returns true if there is no value under the interface
func (s *SubroundsHandler) IsInterfaceNil() bool {
return s == nil
Expand Down
51 changes: 28 additions & 23 deletions consensus/spos/bls/proxy/subroundsHandler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
crypto "github.com/multiversx/mx-chain-crypto-go"
"github.com/stretchr/testify/require"

chainCommon "github.com/multiversx/mx-chain-go/common"
mock2 "github.com/multiversx/mx-chain-go/consensus/mock"
"github.com/multiversx/mx-chain-go/testscommon"
"github.com/multiversx/mx-chain-go/testscommon/bootstrapperStubs"
Expand All @@ -17,6 +16,7 @@ import (
"github.com/multiversx/mx-chain-go/testscommon/cryptoMocks"
"github.com/multiversx/mx-chain-go/testscommon/dataRetriever"
"github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock"
epochNotifierMock "github.com/multiversx/mx-chain-go/testscommon/epochNotifier"
mock "github.com/multiversx/mx-chain-go/testscommon/epochstartmock"
outportStub "github.com/multiversx/mx-chain-go/testscommon/outport"
"github.com/multiversx/mx-chain-go/testscommon/shardingMocks"
Expand All @@ -29,6 +29,7 @@ func getDefaultArgumentsSubroundHandler() (*SubroundsHandlerArgs, *consensus.Con
epochsEnable := &enableEpochsHandlerMock.EnableEpochsHandlerStub{}
epochStartNotifier := &mock.EpochStartNotifierStub{}
consensusState := &consensus.ConsensusStateMock{}
epochNotifier := &epochNotifierMock.EpochNotifierStub{}
worker := &consensus.SposWorkerMock{
RemoveAllReceivedMessagesCallsCalled: func() {},
GetConsensusStateChangedChannelsCalled: func() chan bool {
Expand Down Expand Up @@ -78,6 +79,7 @@ func getDefaultArgumentsSubroundHandler() (*SubroundsHandlerArgs, *consensus.Con
consensusCore.SetSigningHandler(&consensus.SigningHandlerStub{})
consensusCore.SetEnableEpochsHandler(epochsEnable)
consensusCore.SetEquivalentProofsPool(&dataRetriever.ProofsPoolMock{})
consensusCore.SetEpochNotifier(epochNotifier)
handlerArgs.ConsensusCoreHandler = consensusCore

return handlerArgs, consensusCore
Expand Down Expand Up @@ -221,12 +223,14 @@ func TestSubroundsHandler_initSubroundsForEpoch(t *testing.T) {
sh, err := NewSubroundsHandler(handlerArgs)
require.Nil(t, err)
require.NotNil(t, sh)
// first call on register to EpochNotifier
require.Equal(t, int32(1), startCalled.Load())
sh.currentConsensusType = consensusNone

err = sh.initSubroundsForEpoch(0)
require.Nil(t, err)
require.Equal(t, consensusV1, sh.currentConsensusType)
require.Equal(t, int32(1), startCalled.Load())
require.Equal(t, int32(2), startCalled.Load())
})
t.Run("equivalent messages not enabled, with previous consensus type consensusV1", func(t *testing.T) {
t.Parallel()
Expand All @@ -251,12 +255,15 @@ func TestSubroundsHandler_initSubroundsForEpoch(t *testing.T) {
sh, err := NewSubroundsHandler(handlerArgs)
require.Nil(t, err)
require.NotNil(t, sh)
// first call on register to EpochNotifier
require.Equal(t, int32(1), startCalled.Load())
sh.currentConsensusType = consensusV1

err = sh.initSubroundsForEpoch(0)
require.Nil(t, err)
require.Equal(t, consensusV1, sh.currentConsensusType)
require.Equal(t, int32(0), startCalled.Load())
require.Equal(t, int32(1), startCalled.Load())

})
t.Run("equivalent messages enabled, with previous consensus type consensusNone", func(t *testing.T) {
t.Parallel()
Expand All @@ -280,12 +287,14 @@ func TestSubroundsHandler_initSubroundsForEpoch(t *testing.T) {
sh, err := NewSubroundsHandler(handlerArgs)
require.Nil(t, err)
require.NotNil(t, sh)
// first call on register to EpochNotifier
require.Equal(t, int32(1), startCalled.Load())
sh.currentConsensusType = consensusNone

err = sh.initSubroundsForEpoch(0)
require.Nil(t, err)
require.Equal(t, consensusV2, sh.currentConsensusType)
require.Equal(t, int32(1), startCalled.Load())
require.Equal(t, int32(2), startCalled.Load())
})
t.Run("equivalent messages enabled, with previous consensus type consensusV1", func(t *testing.T) {
t.Parallel()
Expand All @@ -309,12 +318,14 @@ func TestSubroundsHandler_initSubroundsForEpoch(t *testing.T) {
sh, err := NewSubroundsHandler(handlerArgs)
require.Nil(t, err)
require.NotNil(t, sh)
// first call on register to EpochNotifier
require.Equal(t, int32(1), startCalled.Load())
sh.currentConsensusType = consensusV1

err = sh.initSubroundsForEpoch(0)
require.Nil(t, err)
require.Equal(t, consensusV2, sh.currentConsensusType)
require.Equal(t, int32(1), startCalled.Load())
require.Equal(t, int32(2), startCalled.Load())
})
t.Run("equivalent messages enabled, with previous consensus type consensusV2", func(t *testing.T) {
t.Parallel()
Expand All @@ -339,12 +350,14 @@ func TestSubroundsHandler_initSubroundsForEpoch(t *testing.T) {
sh, err := NewSubroundsHandler(handlerArgs)
require.Nil(t, err)
require.NotNil(t, sh)
// first call on register to EpochNotifier
require.Equal(t, int32(1), startCalled.Load())
sh.currentConsensusType = consensusV2

err = sh.initSubroundsForEpoch(0)
require.Nil(t, err)
require.Equal(t, consensusV2, sh.currentConsensusType)
require.Equal(t, int32(0), startCalled.Load())
require.Equal(t, int32(1), startCalled.Load())
})
}

Expand Down Expand Up @@ -375,27 +388,17 @@ func TestSubroundsHandler_Start(t *testing.T) {
sh, err := NewSubroundsHandler(handlerArgs)
require.Nil(t, err)
require.NotNil(t, sh)
// first call on init of EpochNotifier
require.Equal(t, int32(1), startCalled.Load())
sh.currentConsensusType = consensusNone

err = sh.Start(0)
require.Nil(t, err)
require.Equal(t, consensusV1, sh.currentConsensusType)
require.Equal(t, int32(1), startCalled.Load())
require.Equal(t, int32(2), startCalled.Load())
})
}

func TestSubroundsHandler_NotifyOrder(t *testing.T) {
t.Parallel()

handlerArgs, _ := getDefaultArgumentsSubroundHandler()
sh, err := NewSubroundsHandler(handlerArgs)
require.Nil(t, err)
require.NotNil(t, sh)

order := sh.NotifyOrder()
require.Equal(t, uint32(chainCommon.ConsensusHandlerOrder), order)
}

func TestSubroundsHandler_IsInterfaceNil(t *testing.T) {
t.Parallel()

Expand All @@ -417,7 +420,7 @@ func TestSubroundsHandler_IsInterfaceNil(t *testing.T) {
})
}

func TestSubroundsHandler_EpochStartAction(t *testing.T) {
func TestSubroundsHandler_EpochConfirmed(t *testing.T) {
t.Parallel()

t.Run("nil handler does not panic", func(t *testing.T) {
Expand All @@ -431,7 +434,7 @@ func TestSubroundsHandler_EpochStartAction(t *testing.T) {
handlerArgs, _ := getDefaultArgumentsSubroundHandler()
sh, err := NewSubroundsHandler(handlerArgs)
require.Nil(t, err)
sh.EpochStartAction(&testscommon.HeaderHandlerStub{})
sh.EpochConfirmed(0, 0)
})

// tested through initSubroundsForEpoch
Expand All @@ -458,11 +461,13 @@ func TestSubroundsHandler_EpochStartAction(t *testing.T) {
sh, err := NewSubroundsHandler(handlerArgs)
require.Nil(t, err)
require.NotNil(t, sh)
// first call on register to EpochNotifier
require.Equal(t, int32(1), startCalled.Load())

sh.currentConsensusType = consensusNone
sh.EpochStartAction(&testscommon.HeaderHandlerStub{})
sh.EpochConfirmed(0, 0)
require.Nil(t, err)
require.Equal(t, consensusV1, sh.currentConsensusType)
require.Equal(t, int32(1), startCalled.Load())
require.Equal(t, int32(2), startCalled.Load())
})
}
1 change: 1 addition & 0 deletions consensus/spos/bls/v1/blsSubroundsFactory.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ func (fct *factory) generateBlockSubround() error {
fct.worker.AddReceivedMessageCall(bls.MtBlockBodyAndHeader, subroundBlockInstance.receivedBlockBodyAndHeader)
fct.worker.AddReceivedMessageCall(bls.MtBlockBody, subroundBlockInstance.receivedBlockBody)
fct.worker.AddReceivedMessageCall(bls.MtBlockHeader, subroundBlockInstance.receivedBlockHeader)
fct.worker.AddReceivedHeaderHandler(subroundBlockInstance.receivedFullHeader)
fct.consensusCore.Chronology().AddSubround(subroundBlockInstance)

return nil
Expand Down
3 changes: 3 additions & 0 deletions consensus/spos/bls/v1/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ import "errors"

// ErrNilSentSignatureTracker defines the error for setting a nil SentSignatureTracker
var ErrNilSentSignatureTracker = errors.New("nil sent signature tracker")

// ErrEquivalentMessagesFlagEnabledWithConsensusV1 defines the error for running with the equivalent messages flag enabled under v1 consensus
var ErrEquivalentMessagesFlagEnabledWithConsensusV1 = errors.New("equivalent messages flag enabled with consensus v1")
26 changes: 26 additions & 0 deletions consensus/spos/bls/v1/subroundBlock.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package v1

import (
"bytes"
"context"
"time"

Expand Down Expand Up @@ -334,6 +335,10 @@ func (sr *subroundBlock) createHeader() (data.HeaderHandler, error) {
return nil, err
}

if sr.EnableEpochsHandler().IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, hdr.GetEpoch()) {
return nil, ErrEquivalentMessagesFlagEnabledWithConsensusV1
}

err = hdr.SetPrevHash(prevHash)
if err != nil {
return nil, err
Expand Down Expand Up @@ -491,6 +496,27 @@ func (sr *subroundBlock) receivedBlockBody(ctx context.Context, cnsDta *consensu
return blockProcessedWithSuccess
}

func (sr *subroundBlock) receivedFullHeader(headerHandler data.HeaderHandler) {
if sr.ShardCoordinator().SelfId() != headerHandler.GetShardID() {
log.Debug("subroundBlock.ReceivedFullHeader early exit", "headerShardID", headerHandler.GetShardID(), "selfShardID", sr.ShardCoordinator().SelfId())
return
}

if !sr.EnableEpochsHandler().IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, headerHandler.GetEpoch()) {
log.Debug("subroundBlock.ReceivedFullHeader early exit", "flagNotEnabled in header epoch", headerHandler.GetEpoch())
return
}

log.Debug("subroundBlock.ReceivedFullHeader", "nonce", headerHandler.GetNonce(), "epoch", headerHandler.GetEpoch())

lastCommittedBlockHash := sr.Blockchain().GetCurrentBlockHeaderHash()
if bytes.Equal(lastCommittedBlockHash, headerHandler.GetPrevHash()) {
// Need to switch to consensus v2
log.Debug("subroundBlock.ReceivedFullHeader switching epoch")
go sr.EpochNotifier().CheckEpoch(headerHandler)
}
}

// receivedBlockHeader method is called when a block header is received through the block header channel.
// If the block header is valid, then the validatorRoundStates map corresponding to the node which sent it,
// is set on true for the subround Block
Expand Down
1 change: 1 addition & 0 deletions consensus/spos/bls/v2/subroundEndRound.go
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,7 @@ func (sr *subroundEndRound) createAndBroadcastProof(signature []byte, bitmap []b
HeaderEpoch: sr.GetHeader().GetEpoch(),
HeaderNonce: sr.GetHeader().GetNonce(),
HeaderShardId: sr.GetHeader().GetShardID(),
HeaderRound: sr.GetHeader().GetRound(),
}

err := sr.BroadcastMessenger().BroadcastEquivalentProof(headerProof, []byte(sr.SelfPubKey()))
Expand Down
9 changes: 9 additions & 0 deletions consensus/spos/consensusCore.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"github.com/multiversx/mx-chain-core-go/data"
"github.com/multiversx/mx-chain-core-go/hashing"
"github.com/multiversx/mx-chain-core-go/marshal"

"github.com/multiversx/mx-chain-go/common"
cryptoCommon "github.com/multiversx/mx-chain-go/common/crypto"
"github.com/multiversx/mx-chain-go/consensus"
Expand Down Expand Up @@ -41,6 +42,7 @@ type ConsensusCore struct {
signingHandler consensus.SigningHandler
enableEpochsHandler common.EnableEpochsHandler
equivalentProofsPool consensus.EquivalentProofsPool
epochNotifier process.EpochNotifier
}

// ConsensusCoreArgs store all arguments that are needed to create a ConsensusCore object
Expand Down Expand Up @@ -69,6 +71,7 @@ type ConsensusCoreArgs struct {
SigningHandler consensus.SigningHandler
EnableEpochsHandler common.EnableEpochsHandler
EquivalentProofsPool consensus.EquivalentProofsPool
EpochNotifier process.EpochNotifier
}

// NewConsensusCore creates a new ConsensusCore instance
Expand Down Expand Up @@ -100,6 +103,7 @@ func NewConsensusCore(
signingHandler: args.SigningHandler,
enableEpochsHandler: args.EnableEpochsHandler,
equivalentProofsPool: args.EquivalentProofsPool,
epochNotifier: args.EpochNotifier,
}

err := ValidateConsensusCore(consensusCore)
Expand Down Expand Up @@ -180,6 +184,11 @@ func (cc *ConsensusCore) EpochStartRegistrationHandler() epochStart.Registration
return cc.epochStartRegistrationHandler
}

// EpochNotifier returns the epoch notifier
func (cc *ConsensusCore) EpochNotifier() process.EpochNotifier {
return cc.epochNotifier
}

// PeerHonestyHandler will return the peer honesty handler which will be used in subrounds
func (cc *ConsensusCore) PeerHonestyHandler() consensus.PeerHonestyHandler {
return cc.peerHonestyHandler
Expand Down
3 changes: 3 additions & 0 deletions consensus/spos/consensusCoreValidator.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ func ValidateConsensusCore(container ConsensusCoreHandler) error {
if check.IfNil(container.EquivalentProofsPool()) {
return ErrNilEquivalentProofPool
}
if check.IfNil(container.EpochNotifier()) {
return ErrNilEpochNotifier
}

return nil
}
Loading
Loading