diff --git a/cmd/node/config/enableEpochs.toml b/cmd/node/config/enableEpochs.toml index aaddfdbf513..f7ca5cda302 100644 --- a/cmd/node/config/enableEpochs.toml +++ b/cmd/node/config/enableEpochs.toml @@ -218,6 +218,12 @@ # MiniBlockPartialExecutionEnableEpoch represents the epoch when mini block partial execution will be enabled MiniBlockPartialExecutionEnableEpoch = 3 + # BLSMultiSignerEnableEpoch represents the activation epoch for different types of BLS multi-signers + BLSMultiSignerEnableEpoch = [ + { EnableEpoch = 0, Type = "no-KOSK"}, + { EnableEpoch = 3, Type = "KOSK"} + ] + # MaxNodesChangeEnableEpoch holds configuration for changing the maximum number of nodes and the enabling epoch MaxNodesChangeEnableEpoch = [ { EpochEnable = 0, MaxNumNodes = 36, NodesToShufflePerShard = 4 }, diff --git a/common/crypto/interface.go b/common/crypto/interface.go new file mode 100644 index 00000000000..3e7f1bbeb6f --- /dev/null +++ b/common/crypto/interface.go @@ -0,0 +1,9 @@ +package crypto + +import crypto "github.com/ElrondNetwork/elrond-go-crypto" + +// MultiSignerContainer defines the container for different versioned multiSigner instances +type MultiSignerContainer interface { + GetMultiSigner(epoch uint32) (crypto.MultiSigner, error) + IsInterfaceNil() bool +} diff --git a/config/config.go b/config/config.go index db6d63c55d3..c13d8691261 100644 --- a/config/config.go +++ b/config/config.go @@ -270,6 +270,12 @@ type MaxNodesChangeConfig struct { NodesToShufflePerShard uint32 } +// MultiSignerConfig defines a config tuple for a BLS multi-signer that activates in a certain epoch +type MultiSignerConfig struct { + EnableEpoch uint32 + Type string +} + // GeneralSettingsConfig will hold the general settings for a node type GeneralSettingsConfig struct { StatusPollingIntervalSec int diff --git a/config/epochConfig.go b/config/epochConfig.go index 1df8e5b5931..d5d1495a630 100644 --- a/config/epochConfig.go +++ b/config/epochConfig.go @@ -85,6 +85,7 @@ type EnableEpochs struct { HeartbeatDisableEpoch uint32 MiniBlockPartialExecutionEnableEpoch uint32 ESDTMetadataContinuousCleanupEnableEpoch uint32 + BLSMultiSignerEnableEpoch []MultiSignerConfig } // GasScheduleByEpochs represents a gas schedule toml entry that will be applied from the provided epoch diff --git a/config/tomlConfig_test.go b/config/tomlConfig_test.go index 19e7654b3ac..f69812168b5 100644 --- a/config/tomlConfig_test.go +++ b/config/tomlConfig_test.go @@ -671,6 +671,11 @@ func TestEnableEpochConfig(t *testing.T) { { EpochEnable = 45, MaxNumNodes = 3200, NodesToShufflePerShard = 80 } ] + BLSMultiSignerEnableEpoch = [ + {EnableEpoch = 0, Type = "no-KOSK"}, + {EnableEpoch = 3, Type = "KOSK"} + ] + [GasSchedule] GasScheduleByEpochs = [ { StartEpoch = 46, FileName = "gasScheduleV1.toml" }, @@ -748,7 +753,18 @@ func TestEnableEpochConfig(t *testing.T) { ManagedCryptoAPIsEnableEpoch: 54, HeartbeatDisableEpoch: 55, ESDTMetadataContinuousCleanupEnableEpoch: 56, + BLSMultiSignerEnableEpoch: []MultiSignerConfig{ + { + EnableEpoch: 0, + Type: "no-KOSK", + }, + { + EnableEpoch: 3, + Type: "KOSK", + }, + }, }, + GasSchedule: GasScheduleConfig{ GasScheduleByEpochs: []GasScheduleByEpochs{ { diff --git a/consensus/mock/consensusDataContainerMock.go b/consensus/mock/consensusDataContainerMock.go index adbeaaf2c86..6b21faf0e9c 100644 --- a/consensus/mock/consensusDataContainerMock.go +++ b/consensus/mock/consensusDataContainerMock.go @@ -5,6 +5,7 @@ import ( "github.com/ElrondNetwork/elrond-go-core/hashing" "github.com/ElrondNetwork/elrond-go-core/marshal" crypto "github.com/ElrondNetwork/elrond-go-crypto" + cryptoCommon "github.com/ElrondNetwork/elrond-go/common/crypto" "github.com/ElrondNetwork/elrond-go/consensus" "github.com/ElrondNetwork/elrond-go/epochStart" "github.com/ElrondNetwork/elrond-go/ntp" @@ -25,7 +26,7 @@ type ConsensusCoreMock struct { marshalizer marshal.Marshalizer blsPrivateKey crypto.PrivateKey blsSingleSigner crypto.SingleSigner - multiSigner crypto.MultiSigner + multiSignerContainer cryptoCommon.MultiSignerContainer roundHandler consensus.RoundHandler shardCoordinator sharding.Coordinator syncTimer ntp.SyncTimer @@ -84,9 +85,9 @@ func (ccm *ConsensusCoreMock) Marshalizer() marshal.Marshalizer { return ccm.marshalizer } -// MultiSigner - -func (ccm *ConsensusCoreMock) MultiSigner() crypto.MultiSigner { - return ccm.multiSigner +// MultiSignerContainer - +func (ccm *ConsensusCoreMock) MultiSignerContainer() cryptoCommon.MultiSignerContainer { + return ccm.multiSignerContainer } // RoundHandler - @@ -154,9 +155,9 @@ func (ccm *ConsensusCoreMock) SetMarshalizer(marshalizer marshal.Marshalizer) { ccm.marshalizer = marshalizer } -// SetMultiSigner - -func (ccm *ConsensusCoreMock) SetMultiSigner(multiSigner crypto.MultiSigner) { - ccm.multiSigner = multiSigner +// SetMultiSignerContainer - +func (ccm *ConsensusCoreMock) SetMultiSignerContainer(multiSignerContainer cryptoCommon.MultiSignerContainer) { + ccm.multiSignerContainer = multiSignerContainer } // SetRoundHandler - diff --git a/consensus/mock/mockTestInitializer.go b/consensus/mock/mockTestInitializer.go index 18a3c006025..306398bfdf3 100644 --- a/consensus/mock/mockTestInitializer.go +++ b/consensus/mock/mockTestInitializer.go @@ -98,17 +98,17 @@ func InitBlockProcessorHeaderV2Mock() *BlockProcessorMock { // InitMultiSignerMock - func InitMultiSignerMock() *cryptoMocks.MultisignerMock { - multiSigner := cryptoMocks.NewMultiSigner(21) - multiSigner.VerifySignatureShareCalled = func(index uint16, sig []byte, msg []byte, bitmap []byte) error { + multiSigner := cryptoMocks.NewMultiSigner() + multiSigner.VerifySignatureShareCalled = func(publicKey []byte, message []byte, sig []byte) error { return nil } - multiSigner.VerifyCalled = func(msg []byte, bitmap []byte) error { + multiSigner.VerifyAggregatedSigCalled = func(pubKeysSigners [][]byte, message []byte, aggSig []byte) error { return nil } - multiSigner.AggregateSigsCalled = func(bitmap []byte) ([]byte, error) { + multiSigner.AggregateSigsCalled = func(pubKeysSigners [][]byte, signatures [][]byte) ([]byte, error) { return []byte("aggregatedSig"), nil } - multiSigner.CreateSignatureShareCalled = func(msg []byte, bitmap []byte) ([]byte, error) { + multiSigner.CreateSignatureShareCalled = func(privateKeyBytes []byte, message []byte) ([]byte, error) { return []byte("partialSign"), nil } return multiSigner @@ -204,6 +204,7 @@ func InitConsensusCoreWithMultiSigner(multiSigner crypto.MultiSigner) *Consensus fallbackHeaderValidator := &testscommon.FallBackHeaderValidatorStub{} nodeRedundancyHandler := &NodeRedundancyHandlerStub{} scheduledProcessor := &consensusMocks.ScheduledProcessorStub{} + multiSignerContainer := cryptoMocks.NewMultiSignerContainerMock(multiSigner) container := &ConsensusCoreMock{ blockChain: blockChain, @@ -216,7 +217,7 @@ func InitConsensusCoreWithMultiSigner(multiSigner crypto.MultiSigner) *Consensus marshalizer: marshalizerMock, blsPrivateKey: blsPrivateKeyMock, blsSingleSigner: blsSingleSignerMock, - multiSigner: multiSigner, + multiSignerContainer: multiSignerContainer, roundHandler: roundHandlerMock, shardCoordinator: shardCoordinatorMock, syncTimer: syncTimerMock, diff --git a/consensus/spos/bls/blsSubroundsFactory_test.go b/consensus/spos/bls/blsSubroundsFactory_test.go index a973653ef15..92a00a1956c 100644 --- a/consensus/spos/bls/blsSubroundsFactory_test.go +++ b/consensus/spos/bls/blsSubroundsFactory_test.go @@ -275,13 +275,13 @@ func TestFactory_NewFactoryNilMarshalizerShouldFail(t *testing.T) { assert.Equal(t, spos.ErrNilMarshalizer, err) } -func TestFactory_NewFactoryNilMultiSignerShouldFail(t *testing.T) { +func TestFactory_NewFactoryNilMultiSignerContainerShouldFail(t *testing.T) { t.Parallel() consensusState := initConsensusState() container := mock.InitConsensusCore() worker := initWorker() - container.SetMultiSigner(nil) + container.SetMultiSignerContainer(nil) fct, err := bls.NewSubroundsFactory( container, @@ -293,7 +293,7 @@ func TestFactory_NewFactoryNilMultiSignerShouldFail(t *testing.T) { ) assert.Nil(t, fct) - assert.Equal(t, spos.ErrNilMultiSigner, err) + assert.Equal(t, spos.ErrNilMultiSignerContainer, err) } func TestFactory_NewFactoryNilRoundHandlerShouldFail(t *testing.T) { diff --git a/consensus/spos/bls/export_test.go b/consensus/spos/bls/export_test.go index bf48ba1aef7..a17808324e4 100644 --- a/consensus/spos/bls/export_test.go +++ b/consensus/spos/bls/export_test.go @@ -8,7 +8,7 @@ import ( "github.com/ElrondNetwork/elrond-go-core/data" "github.com/ElrondNetwork/elrond-go-core/hashing" "github.com/ElrondNetwork/elrond-go-core/marshal" - crypto "github.com/ElrondNetwork/elrond-go-crypto" + cryptoCommon "github.com/ElrondNetwork/elrond-go/common/crypto" "github.com/ElrondNetwork/elrond-go/consensus" "github.com/ElrondNetwork/elrond-go/consensus/spos" "github.com/ElrondNetwork/elrond-go/ntp" @@ -61,8 +61,8 @@ func (fct *factory) Marshalizer() marshal.Marshalizer { } // MultiSigner gets the multi signer object -func (fct *factory) MultiSigner() crypto.MultiSigner { - return fct.consensusCore.MultiSigner() +func (fct *factory) MultiSignerContainer() cryptoCommon.MultiSignerContainer { + return fct.consensusCore.MultiSignerContainer() } // RoundHandler gets the roundHandler object diff --git a/consensus/spos/bls/subroundBlock_test.go b/consensus/spos/bls/subroundBlock_test.go index 21130cb280b..e430309f722 100644 --- a/consensus/spos/bls/subroundBlock_test.go +++ b/consensus/spos/bls/subroundBlock_test.go @@ -216,7 +216,7 @@ func TestSubroundBlock_NewSubroundBlockNilMarshalizerShouldFail(t *testing.T) { assert.Equal(t, spos.ErrNilMarshalizer, err) } -func TestSubroundBlock_NewSubroundBlockNilMultisignerShouldFail(t *testing.T) { +func TestSubroundBlock_NewSubroundBlockNilMultiSignerContainerShouldFail(t *testing.T) { t.Parallel() container := mock.InitConsensusCore() @@ -225,10 +225,10 @@ func TestSubroundBlock_NewSubroundBlockNilMultisignerShouldFail(t *testing.T) { ch := make(chan bool, 1) sr, _ := defaultSubroundForSRBlock(consensusState, ch, container, &statusHandler.AppStatusHandlerStub{}) - container.SetMultiSigner(nil) + container.SetMultiSignerContainer(nil) srBlock, err := defaultSubroundBlockFromSubround(sr) assert.Nil(t, srBlock) - assert.Equal(t, spos.ErrNilMultiSigner, err) + assert.Equal(t, spos.ErrNilMultiSignerContainer, err) } func TestSubroundBlock_NewSubroundBlockNilRoundHandlerShouldFail(t *testing.T) { diff --git a/consensus/spos/bls/subroundEndRound.go b/consensus/spos/bls/subroundEndRound.go index dcec40eb6de..7f0e0feeefc 100644 --- a/consensus/spos/bls/subroundEndRound.go +++ b/consensus/spos/bls/subroundEndRound.go @@ -182,6 +182,11 @@ func (sr *subroundEndRound) doEndRoundJob(_ context.Context) bool { return sr.doEndRoundJobByLeader() } +// TODO: this method should return the signers pubKeys and their signatures +func (sr *subroundEndRound) getSigningData() (pubKeys [][]byte, sigShares [][]byte) { + return nil, nil +} + func (sr *subroundEndRound) doEndRoundJobByLeader() bool { bitmap := sr.GenerateBitmap(SrSignature) err := sr.checkSignaturesValidity(bitmap) @@ -190,8 +195,17 @@ func (sr *subroundEndRound) doEndRoundJobByLeader() bool { return false } + multiSigner, err := sr.MultiSignerContainer().GetMultiSigner(sr.Header.GetEpoch()) + if err != nil { + log.Error("doEndRoundJobByLeader.GetMultiSigner", "error", err.Error()) + return false + } + + // TODO: get the signatures from consensus state + pubKeysSigners, sigShares := sr.getSigningData() + // Aggregate sig and add it to the block - sig, err := sr.MultiSigner().AggregateSigs(bitmap) + sig, err := multiSigner.AggregateSigs(pubKeysSigners, sigShares) if err != nil { log.Debug("doEndRoundJobByLeader.AggregateSigs", "error", err.Error()) return false diff --git a/consensus/spos/bls/subroundEndRound_test.go b/consensus/spos/bls/subroundEndRound_test.go index e102e356863..1ba8e208196 100644 --- a/consensus/spos/bls/subroundEndRound_test.go +++ b/consensus/spos/bls/subroundEndRound_test.go @@ -14,6 +14,7 @@ import ( "github.com/ElrondNetwork/elrond-go/consensus/spos" "github.com/ElrondNetwork/elrond-go/consensus/spos/bls" "github.com/ElrondNetwork/elrond-go/dataRetriever/blockchain" + "github.com/ElrondNetwork/elrond-go/testscommon/cryptoMocks" "github.com/ElrondNetwork/elrond-go/testscommon/statusHandler" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -177,7 +178,7 @@ func TestSubroundEndRound_NewSubroundEndRoundNilConsensusStateShouldFail(t *test assert.Equal(t, spos.ErrNilConsensusState, err) } -func TestSubroundEndRound_NewSubroundEndRoundNilMultisignerShouldFail(t *testing.T) { +func TestSubroundEndRound_NewSubroundEndRoundNilMultiSignerContainerShouldFail(t *testing.T) { t.Parallel() container := mock.InitConsensusCore() @@ -199,7 +200,7 @@ func TestSubroundEndRound_NewSubroundEndRoundNilMultisignerShouldFail(t *testing currentPid, &statusHandler.AppStatusHandlerStub{}, ) - container.SetMultiSigner(nil) + container.SetMultiSignerContainer(nil) srEndRound, err := bls.NewSubroundEndRound( sr, extend, @@ -209,7 +210,7 @@ func TestSubroundEndRound_NewSubroundEndRoundNilMultisignerShouldFail(t *testing ) assert.Nil(t, srEndRound) - assert.Equal(t, spos.ErrNilMultiSigner, err) + assert.Equal(t, spos.ErrNilMultiSignerContainer, err) } func TestSubroundEndRound_NewSubroundEndRoundNilRoundHandlerShouldFail(t *testing.T) { @@ -322,11 +323,11 @@ func TestSubroundEndRound_DoEndRoundJobErrAggregatingSigShouldFail(t *testing.T) container := mock.InitConsensusCore() sr := *initSubroundEndRoundWithContainer(container, &statusHandler.AppStatusHandlerStub{}) multiSignerMock := mock.InitMultiSignerMock() - multiSignerMock.AggregateSigsCalled = func(bitmap []byte) ([]byte, error) { + multiSignerMock.AggregateSigsCalled = func(pubKeysSigners [][]byte, signatures [][]byte) ([]byte, error) { return nil, crypto.ErrNilHasher } - container.SetMultiSigner(multiSignerMock) + container.SetMultiSignerContainer(cryptoMocks.NewMultiSignerContainerMock(multiSignerMock)) sr.Header = &block.Header{} sr.SetSelfPubKey("A") diff --git a/consensus/spos/bls/subroundSignature.go b/consensus/spos/bls/subroundSignature.go index 5c0ff748f51..3563771734a 100644 --- a/consensus/spos/bls/subroundSignature.go +++ b/consensus/spos/bls/subroundSignature.go @@ -68,8 +68,20 @@ func (sr *subroundSignature) doSignatureJob(_ context.Context) bool { if !sr.CanDoSubroundJob(sr.Current()) { return false } + if check.IfNil(sr.Header) { + log.Error("doSignatureJob", "error", spos.ErrNilHeader) + return false + } + + multiSigner, err := sr.MultiSignerContainer().GetMultiSigner(sr.Header.GetEpoch()) + if err != nil { + log.Error("doSignatureJob.GetMultiSigner", "error", err.Error()) + return false + } - signatureShare, err := sr.MultiSigner().CreateSignatureShare(sr.GetData(), nil) + // TODO: keep private key as byte array in consensus + privateKey, _ := sr.PrivateKey().ToByteArray() + signatureShare, err := multiSigner.CreateSignatureShare(privateKey, sr.GetData()) if err != nil { log.Debug("doSignatureJob.CreateSignatureShare", "error", err.Error()) return false @@ -160,25 +172,36 @@ func (sr *subroundSignature) receivedSignature(_ context.Context, cnsDta *consen return false } - currentMultiSigner := sr.MultiSigner() - err = currentMultiSigner.VerifySignatureShare(uint16(index), cnsDta.SignatureShare, sr.GetData(), nil) + if check.IfNil(sr.Header) { + log.Error("receivedSignature", "error", spos.ErrNilHeader) + return false + } + + currentMultiSigner, err := sr.MultiSignerContainer().GetMultiSigner(sr.Header.GetEpoch()) if err != nil { - log.Debug("receivedSignature.VerifySignatureShare", - "node", pkForLogs, - "index", index, - "error", err.Error()) + log.Error("receivedSignature.GetMultiSigner", "error", err.Error()) return false } - err = currentMultiSigner.StoreSignatureShare(uint16(index), cnsDta.SignatureShare) + err = currentMultiSigner.VerifySignatureShare([]byte(node), sr.GetData(), cnsDta.SignatureShare) if err != nil { - log.Debug("receivedSignature.StoreSignatureShare", + log.Debug("receivedSignature.VerifySignatureShare", "node", pkForLogs, "index", index, "error", err.Error()) return false } + // TODO: store here the signature in consensus state + //err = currentMultiSigner.StoreSignatureShare(uint16(index), cnsDta.SignatureShare) + //if err != nil { + // log.Debug("receivedSignature.StoreSignatureShare", + // "node", pkForLogs, + // "index", index, + // "error", err.Error()) + // return false + //} + err = sr.SetJobDone(node, sr.Current(), true) if err != nil { log.Debug("receivedSignature.SetJobDone", diff --git a/consensus/spos/bls/subroundSignature_test.go b/consensus/spos/bls/subroundSignature_test.go index 7af1080c00b..1e4240a09a3 100644 --- a/consensus/spos/bls/subroundSignature_test.go +++ b/consensus/spos/bls/subroundSignature_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/ElrondNetwork/elrond-go-core/data" + "github.com/ElrondNetwork/elrond-go-core/data/block" "github.com/ElrondNetwork/elrond-go/consensus" "github.com/ElrondNetwork/elrond-go/consensus/mock" "github.com/ElrondNetwork/elrond-go/consensus/spos" @@ -129,7 +130,7 @@ func TestSubroundSignature_NewSubroundSignatureNilHasherShouldFail(t *testing.T) assert.Equal(t, spos.ErrNilHasher, err) } -func TestSubroundSignature_NewSubroundSignatureNilMultisignerShouldFail(t *testing.T) { +func TestSubroundSignature_NewSubroundSignatureNilMultiSignerContainerShouldFail(t *testing.T) { t.Parallel() container := mock.InitConsensusCore() @@ -151,7 +152,7 @@ func TestSubroundSignature_NewSubroundSignatureNilMultisignerShouldFail(t *testi currentPid, &statusHandler.AppStatusHandlerStub{}, ) - container.SetMultiSigner(nil) + container.SetMultiSignerContainer(nil) srSignature, err := bls.NewSubroundSignature( sr, extend, @@ -159,7 +160,7 @@ func TestSubroundSignature_NewSubroundSignatureNilMultisignerShouldFail(t *testi ) assert.Nil(t, srSignature) - assert.Equal(t, spos.ErrNilMultiSigner, err) + assert.Equal(t, spos.ErrNilMultiSignerContainer, err) } func TestSubroundSignature_NewSubroundSignatureNilRoundHandlerShouldFail(t *testing.T) { @@ -268,6 +269,7 @@ func TestSubroundSignature_DoSignatureJob(t *testing.T) { container := mock.InitConsensusCore() sr := *initSubroundSignatureWithContainer(container) + sr.Header = &block.Header{} sr.Data = nil r := sr.DoSignatureJob() assert.False(t, r) @@ -281,7 +283,7 @@ func TestSubroundSignature_DoSignatureJob(t *testing.T) { return nil, err } - container.SetMultiSigner(multiSignerMock) + container.SetMultiSignerContainer(cryptoMocks.NewMultiSignerContainerMock(multiSignerMock)) r = sr.DoSignatureJob() assert.False(t, r) @@ -291,7 +293,7 @@ func TestSubroundSignature_DoSignatureJob(t *testing.T) { multiSignerMock.CreateSignatureShareCalled = func(msg []byte, bitmap []byte) ([]byte, error) { return []byte("SIG"), nil } - container.SetMultiSigner(multiSignerMock) + container.SetMultiSignerContainer(cryptoMocks.NewMultiSignerContainerMock(multiSignerMock)) r = sr.DoSignatureJob() assert.True(t, r) @@ -325,6 +327,7 @@ func TestSubroundSignature_ReceivedSignature(t *testing.T) { currentPid, ) + sr.Header = &block.Header{} sr.Data = nil r := sr.ReceivedSignature(cnsMsg) assert.False(t, r) @@ -363,15 +366,12 @@ func TestSubroundSignature_ReceivedSignatureVerifyShareFailed(t *testing.T) { t.Parallel() errVerify := errors.New("signature share verification failed") - multiSigner := cryptoMocks.NewMultiSigner(21) - multiSigner.VerifySignatureShareCalled = func(index uint16, sig []byte, msg []byte, bitmap []byte) error { + multiSigner := cryptoMocks.NewMultiSigner() + verifyCalled := false + multiSigner.VerifySignatureShareCalled = func(publicKey []byte, message []byte, sig []byte) error { + verifyCalled = true return errVerify } - storeSigShareCalled := false - multiSigner.StoreSignatureShareCalled = func(index uint16, sig []byte) error { - storeSigShareCalled = true - return nil - } container := mock.InitConsensusCoreWithMultiSigner(multiSigner) sr := *initSubroundSignatureWithContainer(container) @@ -423,81 +423,11 @@ func TestSubroundSignature_ReceivedSignatureVerifyShareFailed(t *testing.T) { } } } - r = sr.ReceivedSignature(cnsMsg) - assert.False(t, r) - assert.False(t, storeSigShareCalled) -} - -func TestSubroundSignature_ReceivedSignatureStoreShareFailed(t *testing.T) { - t.Parallel() - - errStore := errors.New("signature share store failed") - multiSigner := cryptoMocks.NewMultiSigner(21) - verifySigShareCalled := false - multiSigner.VerifySignatureShareCalled = func(index uint16, sig []byte, msg []byte, bitmap []byte) error { - verifySigShareCalled = true - return nil - } - storeSigShareCalled := false - multiSigner.StoreSignatureShareCalled = func(index uint16, sig []byte) error { - storeSigShareCalled = true - return errStore - } - - container := mock.InitConsensusCoreWithMultiSigner(multiSigner) - sr := *initSubroundSignatureWithContainer(container) - - signature := []byte("signature") - cnsMsg := consensus.NewConsensusMessage( - sr.Data, - signature, - nil, - nil, - []byte(sr.ConsensusGroup()[1]), - []byte("sig"), - int(bls.MtSignature), - 0, - chainID, - nil, - nil, - nil, - currentPid, - ) - sr.Data = nil - r := sr.ReceivedSignature(cnsMsg) - assert.False(t, r) - - sr.Data = []byte("Y") - r = sr.ReceivedSignature(cnsMsg) - assert.False(t, r) - - sr.Data = []byte("X") - r = sr.ReceivedSignature(cnsMsg) - assert.False(t, r) - - sr.SetSelfPubKey(sr.ConsensusGroup()[0]) - - cnsMsg.PubKey = []byte("X") - r = sr.ReceivedSignature(cnsMsg) - assert.False(t, r) - - cnsMsg.PubKey = []byte(sr.ConsensusGroup()[1]) - maxCount := len(sr.ConsensusGroup()) * 2 / 3 - count := 0 - for i := 0; i < len(sr.ConsensusGroup()); i++ { - if sr.ConsensusGroup()[i] != string(cnsMsg.PubKey) { - _ = sr.SetJobDone(sr.ConsensusGroup()[i], bls.SrSignature, true) - count++ - if count == maxCount { - break - } - } - } + sr.Header = &block.Header{Epoch: 0} r = sr.ReceivedSignature(cnsMsg) assert.False(t, r) - assert.True(t, storeSigShareCalled) - assert.True(t, verifySigShareCalled) + assert.True(t, verifyCalled) } func TestSubroundSignature_SignaturesCollected(t *testing.T) { diff --git a/consensus/spos/bls/subroundStartRound.go b/consensus/spos/bls/subroundStartRound.go index a18fe9d893e..f04e62df6d0 100644 --- a/consensus/spos/bls/subroundStartRound.go +++ b/consensus/spos/bls/subroundStartRound.go @@ -170,7 +170,7 @@ func (sr *subroundStartRound) initCurrentRound() bool { sr.indexRoundIfNeeded(pubKeys) - selfIndex, err := sr.SelfConsensusGroupIndex() + _, err = sr.SelfConsensusGroupIndex() if err != nil { log.Debug("not in consensus group") sr.AppStatusHandler().SetStringValue(common.MetricConsensusState, "not in consensus group") @@ -181,14 +181,15 @@ func (sr *subroundStartRound) initCurrentRound() bool { sr.AppStatusHandler().SetStringValue(common.MetricConsensusState, "participant") } - err = sr.MultiSigner().Reset(pubKeys, uint16(selfIndex)) - if err != nil { - log.Debug("initCurrentRound.Reset", "error", err.Error()) - - sr.RoundCanceled = true - - return false - } + // TODO: reset here signatures/signers data in consensus + //err = sr.MultiSignerContainer().Reset(pubKeys, uint16(selfIndex)) + //if err != nil { + // log.Debug("initCurrentRound.Reset", "error", err.Error()) + // + // sr.RoundCanceled = true + // + // return false + //} startTime := sr.RoundTimeStamp maxTime := sr.RoundHandler().TimeDuration() * time.Duration(sr.processingThresholdPercentage) / 100 diff --git a/consensus/spos/bls/subroundStartRound_test.go b/consensus/spos/bls/subroundStartRound_test.go index 128c9e2a918..f2d296eb3b5 100644 --- a/consensus/spos/bls/subroundStartRound_test.go +++ b/consensus/spos/bls/subroundStartRound_test.go @@ -145,7 +145,7 @@ func TestSubroundStartRound_NewSubroundStartRoundNilConsensusStateShouldFail(t * assert.Equal(t, spos.ErrNilConsensusState, err) } -func TestSubroundStartRound_NewSubroundStartRoundNilMultiSignerShouldFail(t *testing.T) { +func TestSubroundStartRound_NewSubroundStartRoundNilMultiSignerContainerShouldFail(t *testing.T) { t.Parallel() container := mock.InitConsensusCore() @@ -154,11 +154,11 @@ func TestSubroundStartRound_NewSubroundStartRoundNilMultiSignerShouldFail(t *tes ch := make(chan bool, 1) sr, _ := defaultSubround(consensusState, ch, container) - container.SetMultiSigner(nil) + container.SetMultiSignerContainer(nil) srStartRound, err := defaultSubroundStartRoundFromSubround(sr) assert.Nil(t, srStartRound) - assert.Equal(t, spos.ErrNilMultiSigner, err) + assert.Equal(t, spos.ErrNilMultiSignerContainer, err) } func TestSubroundStartRound_NewSubroundStartRoundNilRoundHandlerShouldFail(t *testing.T) { @@ -385,24 +385,6 @@ func TestSubroundStartRound_InitCurrentRoundShouldReturnTrueWhenIsNotInTheConsen assert.True(t, r) } -func TestSubroundStartRound_InitCurrentRoundShouldReturnFalseWhenCreateErr(t *testing.T) { - t.Parallel() - - multiSignerMock := mock.InitMultiSignerMock() - err := errors.New("error") - multiSignerMock.ResetCalled = func(pubKeys []string, index uint16) error { - return err - } - - container := mock.InitConsensusCore() - container.SetMultiSigner(multiSignerMock) - - srStartRound := *initSubroundStartRoundWithContainer(container) - - r := srStartRound.InitCurrentRound() - assert.False(t, r) -} - func TestSubroundStartRound_InitCurrentRoundShouldReturnFalseWhenTimeIsOut(t *testing.T) { t.Parallel() diff --git a/consensus/spos/consensusCore.go b/consensus/spos/consensusCore.go index a4cc7d313fb..d661de836d2 100644 --- a/consensus/spos/consensusCore.go +++ b/consensus/spos/consensusCore.go @@ -5,6 +5,7 @@ import ( "github.com/ElrondNetwork/elrond-go-core/hashing" "github.com/ElrondNetwork/elrond-go-core/marshal" crypto "github.com/ElrondNetwork/elrond-go-crypto" + cryptoCommon "github.com/ElrondNetwork/elrond-go/common/crypto" "github.com/ElrondNetwork/elrond-go/consensus" "github.com/ElrondNetwork/elrond-go/epochStart" "github.com/ElrondNetwork/elrond-go/ntp" @@ -25,7 +26,7 @@ type ConsensusCore struct { marshalizer marshal.Marshalizer blsPrivateKey crypto.PrivateKey blsSingleSigner crypto.SingleSigner - multiSigner crypto.MultiSigner + multiSignerContainer cryptoCommon.MultiSignerContainer roundHandler consensus.RoundHandler shardCoordinator sharding.Coordinator nodesCoordinator nodesCoordinator.NodesCoordinator @@ -50,7 +51,7 @@ type ConsensusCoreArgs struct { Marshalizer marshal.Marshalizer BlsPrivateKey crypto.PrivateKey BlsSingleSigner crypto.SingleSigner - MultiSigner crypto.MultiSigner + MultiSignerContainer cryptoCommon.MultiSignerContainer RoundHandler consensus.RoundHandler ShardCoordinator sharding.Coordinator NodesCoordinator nodesCoordinator.NodesCoordinator @@ -78,7 +79,7 @@ func NewConsensusCore( marshalizer: args.Marshalizer, blsPrivateKey: args.BlsPrivateKey, blsSingleSigner: args.BlsSingleSigner, - multiSigner: args.MultiSigner, + multiSignerContainer: args.MultiSignerContainer, roundHandler: args.RoundHandler, shardCoordinator: args.ShardCoordinator, nodesCoordinator: args.NodesCoordinator, @@ -140,9 +141,9 @@ func (cc *ConsensusCore) Marshalizer() marshal.Marshalizer { return cc.marshalizer } -// MultiSigner gets the MultiSigner stored in the ConsensusCore -func (cc *ConsensusCore) MultiSigner() crypto.MultiSigner { - return cc.multiSigner +// MultiSignerContainer gets the MultiSignerContainer stored in the ConsensusCore +func (cc *ConsensusCore) MultiSignerContainer() cryptoCommon.MultiSignerContainer { + return cc.multiSignerContainer } //RoundHandler gets the RoundHandler stored in the ConsensusCore diff --git a/consensus/spos/consensusCoreValidator.go b/consensus/spos/consensusCoreValidator.go index 67e5d35d385..04071540569 100644 --- a/consensus/spos/consensusCoreValidator.go +++ b/consensus/spos/consensusCoreValidator.go @@ -28,7 +28,11 @@ func ValidateConsensusCore(container ConsensusCoreHandler) error { if check.IfNil(container.Marshalizer()) { return ErrNilMarshalizer } - if check.IfNil(container.MultiSigner()) { + if check.IfNil(container.MultiSignerContainer()) { + return ErrNilMultiSignerContainer + } + multiSigner, _ := container.MultiSignerContainer().GetMultiSigner(0) + if check.IfNil(multiSigner) { return ErrNilMultiSigner } if check.IfNil(container.RoundHandler()) { diff --git a/consensus/spos/consensusCoreValidator_test.go b/consensus/spos/consensusCoreValidator_test.go index 1fa5cf60782..33cde1a5982 100644 --- a/consensus/spos/consensusCoreValidator_test.go +++ b/consensus/spos/consensusCoreValidator_test.go @@ -19,7 +19,7 @@ func initConsensusDataContainer() *ConsensusCore { chronologyHandlerMock := mock.InitChronologyHandlerMock() blsPrivateKeyMock := &mock.PrivateKeyMock{} blsSingleSignerMock := &mock.SingleSignerMock{} - multiSignerMock := cryptoMocks.NewMultiSigner(21) + multiSignerMock := cryptoMocks.NewMultiSigner() hasherMock := &hashingMocks.HasherMock{} marshalizerMock := mock.MarshalizerMock{} roundHandlerMock := &mock.RoundHandlerMock{} @@ -31,6 +31,7 @@ func initConsensusDataContainer() *ConsensusCore { headerSigVerifier := &mock.HeaderSigVerifierStub{} fallbackHeaderValidator := &testscommon.FallBackHeaderValidatorStub{} nodeRedundancyHandler := &mock.NodeRedundancyHandlerStub{} + multiSignerContainer := cryptoMocks.NewMultiSignerContainerMock(multiSignerMock) return &ConsensusCore{ blockChain: blockChain, @@ -42,7 +43,7 @@ func initConsensusDataContainer() *ConsensusCore { marshalizer: marshalizerMock, blsPrivateKey: blsPrivateKeyMock, blsSingleSigner: blsSingleSignerMock, - multiSigner: multiSignerMock, + multiSignerContainer: multiSignerContainer, roundHandler: roundHandlerMock, shardCoordinator: shardCoordinatorMock, syncTimer: syncTimerMock, @@ -121,11 +122,22 @@ func TestConsensusContainerValidator_ValidateNilMarshalizerShouldFail(t *testing assert.Equal(t, ErrNilMarshalizer, err) } +func TestConsensusContainerValidator_ValidateNilMultiSignerContainerShouldFail(t *testing.T) { + t.Parallel() + + container := initConsensusDataContainer() + container.multiSignerContainer = nil + + err := ValidateConsensusCore(container) + + assert.Equal(t, ErrNilMultiSignerContainer, err) +} + func TestConsensusContainerValidator_ValidateNilMultiSignerShouldFail(t *testing.T) { t.Parallel() container := initConsensusDataContainer() - container.multiSigner = nil + container.multiSignerContainer = cryptoMocks.NewMultiSignerContainerMock(nil) err := ValidateConsensusCore(container) diff --git a/consensus/spos/consensusCore_test.go b/consensus/spos/consensusCore_test.go index 3940da8e737..082ceec0733 100644 --- a/consensus/spos/consensusCore_test.go +++ b/consensus/spos/consensusCore_test.go @@ -6,6 +6,7 @@ import ( "github.com/ElrondNetwork/elrond-go/consensus/mock" "github.com/ElrondNetwork/elrond-go/consensus/spos" "github.com/ElrondNetwork/elrond-go/testscommon/consensus" + "github.com/ElrondNetwork/elrond-go/testscommon/cryptoMocks" "github.com/stretchr/testify/assert" ) @@ -24,7 +25,7 @@ func createDefaultConsensusCoreArgs() *spos.ConsensusCoreArgs { Marshalizer: consensusCoreMock.Marshalizer(), BlsPrivateKey: consensusCoreMock.PrivateKey(), BlsSingleSigner: consensusCoreMock.SingleSigner(), - MultiSigner: consensusCoreMock.MultiSigner(), + MultiSignerContainer: consensusCoreMock.MultiSignerContainer(), RoundHandler: consensusCoreMock.RoundHandler(), ShardCoordinator: consensusCoreMock.ShardCoordinator(), NodesCoordinator: consensusCoreMock.NodesCoordinator(), @@ -164,11 +165,25 @@ func TestConsensusCore_WithNilBlsSingleSignerShouldFail(t *testing.T) { assert.Equal(t, spos.ErrNilBlsSingleSigner, err) } +func TestConsensusCore_WithNilMultiSignerContainerShouldFail(t *testing.T) { + t.Parallel() + + args := createDefaultConsensusCoreArgs() + args.MultiSignerContainer = nil + + consensusCore, err := spos.NewConsensusCore( + args, + ) + + assert.Nil(t, consensusCore) + assert.Equal(t, spos.ErrNilMultiSignerContainer, err) +} + func TestConsensusCore_WithNilMultiSignerShouldFail(t *testing.T) { t.Parallel() args := createDefaultConsensusCoreArgs() - args.MultiSigner = nil + args.MultiSignerContainer = cryptoMocks.NewMultiSignerContainerMock(nil) consensusCore, err := spos.NewConsensusCore( args, diff --git a/consensus/spos/errors.go b/consensus/spos/errors.go index 33def746ddb..40e4ff8371b 100644 --- a/consensus/spos/errors.go +++ b/consensus/spos/errors.go @@ -22,6 +22,9 @@ var ErrNilSignature = errors.New("signature is nil") // ErrNilMultiSigner is raised when a valid multiSigner is expected but nil used var ErrNilMultiSigner = errors.New("multiSigner is nil") +// ErrNilMultiSignerContainer is raised when a valid multiSigner container is expected, but nil used +var ErrNilMultiSignerContainer = errors.New("multiSigner container is nil") + // ErrNilConsensusState is raised when a valid consensus is expected but nil used var ErrNilConsensusState = errors.New("consensus state is nil") diff --git a/consensus/spos/interface.go b/consensus/spos/interface.go index 991fd8468bd..170d47490eb 100644 --- a/consensus/spos/interface.go +++ b/consensus/spos/interface.go @@ -9,6 +9,7 @@ import ( "github.com/ElrondNetwork/elrond-go-core/hashing" "github.com/ElrondNetwork/elrond-go-core/marshal" crypto "github.com/ElrondNetwork/elrond-go-crypto" + cryptoCommon "github.com/ElrondNetwork/elrond-go/common/crypto" "github.com/ElrondNetwork/elrond-go/consensus" "github.com/ElrondNetwork/elrond-go/epochStart" "github.com/ElrondNetwork/elrond-go/ntp" @@ -36,8 +37,8 @@ type ConsensusCoreHandler interface { Hasher() hashing.Hasher // Marshalizer gets the Marshalizer stored in the ConsensusCore Marshalizer() marshal.Marshalizer - // MultiSigner gets the MultiSigner stored in the ConsensusCore - MultiSigner() crypto.MultiSigner + // MultiSignerContainer gets the MultiSigner container from the ConsensusCore + MultiSignerContainer() cryptoCommon.MultiSignerContainer // RoundHandler gets the RoundHandler stored in the ConsensusCore RoundHandler() consensus.RoundHandler // ShardCoordinator gets the ShardCoordinator stored in the ConsensusCore diff --git a/consensus/spos/subround_test.go b/consensus/spos/subround_test.go index f3b78f8ae23..f2adc42ffcb 100644 --- a/consensus/spos/subround_test.go +++ b/consensus/spos/subround_test.go @@ -10,6 +10,7 @@ import ( "github.com/ElrondNetwork/elrond-go/consensus/mock" "github.com/ElrondNetwork/elrond-go/consensus/spos" "github.com/ElrondNetwork/elrond-go/consensus/spos/bls" + "github.com/ElrondNetwork/elrond-go/testscommon/cryptoMocks" "github.com/ElrondNetwork/elrond-go/testscommon/statusHandler" "github.com/stretchr/testify/assert" ) @@ -357,13 +358,13 @@ func TestSubround_NilContainerMarshalizerShouldFail(t *testing.T) { assert.Equal(t, spos.ErrNilMarshalizer, err) } -func TestSubround_NilContainerMultisignerShouldFail(t *testing.T) { +func TestSubround_NilContainerMultiSignerShouldFail(t *testing.T) { t.Parallel() consensusState := initConsensusState() ch := make(chan bool, 1) container := mock.InitConsensusCore() - container.SetMultiSigner(nil) + container.SetMultiSignerContainer(cryptoMocks.NewMultiSignerContainerMock(nil)) sr, err := spos.NewSubround( -1, diff --git a/consensus/spos/worker.go b/consensus/spos/worker.go index 3c3cf391822..62d687d794a 100644 --- a/consensus/spos/worker.go +++ b/consensus/spos/worker.go @@ -19,6 +19,7 @@ import ( crypto "github.com/ElrondNetwork/elrond-go-crypto" "github.com/ElrondNetwork/elrond-go/common" "github.com/ElrondNetwork/elrond-go/consensus" + errorsErd "github.com/ElrondNetwork/elrond-go/errors" "github.com/ElrondNetwork/elrond-go/ntp" "github.com/ElrondNetwork/elrond-go/p2p" "github.com/ElrondNetwork/elrond-go/process" @@ -411,8 +412,8 @@ func (wrk *Worker) shouldBlacklistPeer(err error) bool { errors.Is(err, ErrMessageForPastRound) || errors.Is(err, ErrMessageForFutureRound) || errors.Is(err, ErrNodeIsNotInEligibleList) || - errors.Is(err, crypto.ErrPIDMismatch) || - errors.Is(err, crypto.ErrSignatureMismatch) || + errors.Is(err, errorsErd.ErrPIDMismatch) || + errors.Is(err, errorsErd.ErrSignatureMismatch) || errors.Is(err, nodesCoordinator.ErrEpochNodesConfigDoesNotExist) || errors.Is(err, ErrMessageTypeLimitReached) { return false diff --git a/epochStart/bootstrap/disabled/disabledMultiSigner.go b/epochStart/bootstrap/disabled/disabledMultiSigner.go index 46c5cff28ff..dd7c5e4d7b6 100644 --- a/epochStart/bootstrap/disabled/disabledMultiSigner.go +++ b/epochStart/bootstrap/disabled/disabledMultiSigner.go @@ -1,9 +1,5 @@ package disabled -import ( - "github.com/ElrondNetwork/elrond-go-crypto" -) - type multiSigner struct { } @@ -12,54 +8,24 @@ func NewMultiSigner() *multiSigner { return &multiSigner{} } -// Create returns a nil instance and a nil error -func (m *multiSigner) Create(_ []string, _ uint16) (crypto.MultiSigner, error) { - return nil, nil -} - -// SetAggregatedSig returns nil -func (m *multiSigner) SetAggregatedSig([]byte) error { - return nil -} - -// Verify returns nil -func (m *multiSigner) Verify(_ []byte, _ []byte) error { - return nil -} - -// Reset returns nil and does nothing -func (m *multiSigner) Reset(_ []string, _ uint16) error { - return nil -} - // CreateSignatureShare returns nil byte slice and nil error func (m *multiSigner) CreateSignatureShare(_ []byte, _ []byte) ([]byte, error) { return nil, nil } -// StoreSignatureShare returns nil -func (m *multiSigner) StoreSignatureShare(_ uint16, _ []byte) error { - return nil -} - -// SignatureShare returns nil byte slice and a nil error -func (m *multiSigner) SignatureShare(_ uint16) ([]byte, error) { - return nil, nil -} - // VerifySignatureShare returns nil -func (m *multiSigner) VerifySignatureShare(_ uint16, _ []byte, _ []byte, _ []byte) error { +func (m *multiSigner) VerifySignatureShare(_ []byte, _ []byte, _ []byte) error { return nil } // AggregateSigs returns nil byte slice and nil error -func (m *multiSigner) AggregateSigs(_ []byte) ([]byte, error) { +func (m *multiSigner) AggregateSigs(_ [][]byte, _ [][]byte) ([]byte, error) { return nil, nil } -// CreateAndAddSignatureShareForKey will return an empty slice and a nil error -func (m *multiSigner) CreateAndAddSignatureShareForKey(_ []byte, _ crypto.PrivateKey, _ []byte) ([]byte, error) { - return make([]byte, 0), nil +// VerifyAggregatedSig returns nil +func (m *multiSigner) VerifyAggregatedSig(_ [][]byte, _ []byte, _ []byte) error { + return nil } // IsInterfaceNil returns true if there is no value under the interface diff --git a/epochStart/bootstrap/disabled/disabledMultiSignerContainer.go b/epochStart/bootstrap/disabled/disabledMultiSignerContainer.go new file mode 100644 index 00000000000..cb5a735fe13 --- /dev/null +++ b/epochStart/bootstrap/disabled/disabledMultiSignerContainer.go @@ -0,0 +1,24 @@ +package disabled + +import crypto "github.com/ElrondNetwork/elrond-go-crypto" + +type disabledMultiSignerContainer struct { + multiSigner crypto.MultiSigner +} + +// NewMultiSignerContainer creates a disabled multi signer container +func NewMultiSignerContainer() *disabledMultiSignerContainer { + return &disabledMultiSignerContainer{ + multiSigner: NewMultiSigner(), + } +} + +// GetMultiSigner returns a disabled multi signer as this is a disabled component +func (dmsc *disabledMultiSignerContainer) GetMultiSigner(_ uint32) (crypto.MultiSigner, error) { + return dmsc.multiSigner, nil +} + +// IsInterfaceNil returns true if the underlying object is nil +func (dmsc *disabledMultiSignerContainer) IsInterfaceNil() bool { + return dmsc == nil +} diff --git a/epochStart/bootstrap/factory/epochStartInterceptorsContainerFactory.go b/epochStart/bootstrap/factory/epochStartInterceptorsContainerFactory.go index da2a2f6a977..5ec8801a3bc 100644 --- a/epochStart/bootstrap/factory/epochStartInterceptorsContainerFactory.go +++ b/epochStart/bootstrap/factory/epochStartInterceptorsContainerFactory.go @@ -58,7 +58,7 @@ func NewEpochStartInterceptorsContainer(args ArgsEpochStartInterceptorContainer) } cryptoComponents := args.CryptoComponents.Clone().(process.CryptoComponentsHolder) - err := cryptoComponents.SetMultiSigner(disabled.NewMultiSigner()) + err := cryptoComponents.SetMultiSignerContainer(disabled.NewMultiSignerContainer()) if err != nil { return nil, err } diff --git a/epochStart/mock/cryptoComponentsMock.go b/epochStart/mock/cryptoComponentsMock.go index afbcb00a382..1d65646728c 100644 --- a/epochStart/mock/cryptoComponentsMock.go +++ b/epochStart/mock/cryptoComponentsMock.go @@ -1,21 +1,23 @@ package mock import ( + "errors" "sync" "github.com/ElrondNetwork/elrond-go-crypto" + cryptoCommon "github.com/ElrondNetwork/elrond-go/common/crypto" ) // CryptoComponentsMock - type CryptoComponentsMock struct { - PubKey crypto.PublicKey - BlockSig crypto.SingleSigner - TxSig crypto.SingleSigner - MultiSig crypto.MultiSigner - PeerSignHandler crypto.PeerSignatureHandler - BlKeyGen crypto.KeyGenerator - TxKeyGen crypto.KeyGenerator - mutCrypto sync.RWMutex + PubKey crypto.PublicKey + BlockSig crypto.SingleSigner + TxSig crypto.SingleSigner + MultiSigContainer cryptoCommon.MultiSignerContainer + PeerSignHandler crypto.PeerSignatureHandler + BlKeyGen crypto.KeyGenerator + TxKeyGen crypto.KeyGenerator + mutCrypto sync.RWMutex } // PublicKey - @@ -33,20 +35,32 @@ func (ccm *CryptoComponentsMock) TxSingleSigner() crypto.SingleSigner { return ccm.TxSig } -// MultiSigner - -func (ccm *CryptoComponentsMock) MultiSigner() crypto.MultiSigner { +// GetMultiSigner - +func (ccm *CryptoComponentsMock) GetMultiSigner(epoch uint32) (crypto.MultiSigner, error) { ccm.mutCrypto.RLock() defer ccm.mutCrypto.RUnlock() - return ccm.MultiSig + if ccm.MultiSigContainer == nil { + return nil, errors.New("multisigner container is nil") + } + + return ccm.MultiSigContainer.GetMultiSigner(epoch) +} + +// MultiSignerContainer - +func (ccm *CryptoComponentsMock) MultiSignerContainer() cryptoCommon.MultiSignerContainer { + ccm.mutCrypto.RLock() + defer ccm.mutCrypto.RUnlock() + + return ccm.MultiSigContainer } -// SetMultiSigner - -func (ccm *CryptoComponentsMock) SetMultiSigner(m crypto.MultiSigner) error { +// SetMultiSignerContainer - +func (ccm *CryptoComponentsMock) SetMultiSignerContainer(msc cryptoCommon.MultiSignerContainer) error { ccm.mutCrypto.Lock() - ccm.MultiSig = m - ccm.mutCrypto.Unlock() + defer ccm.mutCrypto.Unlock() + ccm.MultiSigContainer = msc return nil } @@ -68,14 +82,14 @@ func (ccm *CryptoComponentsMock) TxSignKeyGen() crypto.KeyGenerator { // Clone - func (ccm *CryptoComponentsMock) Clone() interface{} { return &CryptoComponentsMock{ - PubKey: ccm.PubKey, - BlockSig: ccm.BlockSig, - TxSig: ccm.TxSig, - MultiSig: ccm.MultiSig, - PeerSignHandler: ccm.PeerSignHandler, - BlKeyGen: ccm.BlKeyGen, - TxKeyGen: ccm.TxKeyGen, - mutCrypto: sync.RWMutex{}, + PubKey: ccm.PubKey, + BlockSig: ccm.BlockSig, + TxSig: ccm.TxSig, + MultiSigContainer: ccm.MultiSigContainer, + PeerSignHandler: ccm.PeerSignHandler, + BlKeyGen: ccm.BlKeyGen, + TxKeyGen: ccm.TxKeyGen, + mutCrypto: sync.RWMutex{}, } } diff --git a/errors/errors.go b/errors/errors.go index 0c2c4238eaf..be6d5c12853 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -478,3 +478,36 @@ var ErrNilTxsSender = errors.New("nil transactions sender has been provided") // ErrNilProcessStatusHandler signals that a nil process status handler was provided var ErrNilProcessStatusHandler = errors.New("nil process status handler") + +// ErrSignerNotSupported signals that a not supported signer was provided +var ErrSignerNotSupported = errors.New("signer not supported") + +// ErrMissingMultiSignerConfig signals that the multisigner config is missing +var ErrMissingMultiSignerConfig = errors.New("multisigner configuration missing") + +// ErrMissingMultiSigner signals that there is no multisigner instance available +var ErrMissingMultiSigner = errors.New("multisigner instance missing") + +// ErrMissingEpochZeroMultiSignerConfig signals that the multisigner config for epoch zero is missing +var ErrMissingEpochZeroMultiSignerConfig = errors.New("multisigner configuration missing for epoch zero") + +// ErrNilMultiSignerContainer signals that the multisigner container is nil +var ErrNilMultiSignerContainer = errors.New("multisigner container is nil") + +// ErrNilCacher signals that a nil cacher has been provided +var ErrNilCacher = errors.New("nil cacher") + +// ErrNilSingleSigner is raised when a valid singleSigner is expected but nil used +var ErrNilSingleSigner = errors.New("singleSigner is nil") + +// ErrPIDMismatch signals that the pid from the message is different from the cached pid associated to a certain pk +var ErrPIDMismatch = errors.New("pid mismatch") + +// ErrSignatureMismatch signals that the signature from the message is different from the cached signature associated to a certain pk +var ErrSignatureMismatch = errors.New("signature mismatch") + +// ErrInvalidPID signals that given PID is invalid +var ErrInvalidPID = errors.New("invalid PID") + +// ErrInvalidSignature signals that the given signature is invalid +var ErrInvalidSignature = errors.New("invalid signature") diff --git a/factory/consensus/consensusComponents.go b/factory/consensus/consensusComponents.go index bba4c1a221c..156c13505c9 100644 --- a/factory/consensus/consensusComponents.go +++ b/factory/consensus/consensusComponents.go @@ -230,7 +230,7 @@ func (ccf *consensusComponentsFactory) Create() (*consensusComponents, error) { Marshalizer: ccf.coreComponents.InternalMarshalizer(), BlsPrivateKey: ccf.cryptoComponents.PrivateKey(), BlsSingleSigner: ccf.cryptoComponents.BlockSigner(), - MultiSigner: ccf.cryptoComponents.MultiSigner(), + MultiSignerContainer: ccf.cryptoComponents.MultiSignerContainer(), RoundHandler: ccf.processComponents.RoundHandler(), ShardCoordinator: ccf.processComponents.ShardCoordinator(), NodesCoordinator: ccf.processComponents.NodesCoordinator(), diff --git a/factory/crypto/cryptoComponents.go b/factory/crypto/cryptoComponents.go index 58b9928ba2c..e2bfd98150f 100644 --- a/factory/crypto/cryptoComponents.go +++ b/factory/crypto/cryptoComponents.go @@ -6,21 +6,16 @@ import ( "fmt" "github.com/ElrondNetwork/elrond-go-core/core/check" - "github.com/ElrondNetwork/elrond-go-core/hashing" - "github.com/ElrondNetwork/elrond-go-core/hashing/blake2b" - "github.com/ElrondNetwork/elrond-go-core/hashing/sha256" "github.com/ElrondNetwork/elrond-go-crypto" "github.com/ElrondNetwork/elrond-go-crypto/signing" disabledCrypto "github.com/ElrondNetwork/elrond-go-crypto/signing/disabled" - disabledMultiSig "github.com/ElrondNetwork/elrond-go-crypto/signing/disabled/multisig" disabledSig "github.com/ElrondNetwork/elrond-go-crypto/signing/disabled/singlesig" "github.com/ElrondNetwork/elrond-go-crypto/signing/ed25519" "github.com/ElrondNetwork/elrond-go-crypto/signing/ed25519/singlesig" "github.com/ElrondNetwork/elrond-go-crypto/signing/mcl" - mclMultiSig "github.com/ElrondNetwork/elrond-go-crypto/signing/mcl/multisig" mclSig "github.com/ElrondNetwork/elrond-go-crypto/signing/mcl/singlesig" - "github.com/ElrondNetwork/elrond-go-crypto/signing/multisig" logger "github.com/ElrondNetwork/elrond-go-logger" + cryptoCommon "github.com/ElrondNetwork/elrond-go/common/crypto" "github.com/ElrondNetwork/elrond-go/config" "github.com/ElrondNetwork/elrond-go/consensus" "github.com/ElrondNetwork/elrond-go/errors" @@ -40,6 +35,7 @@ type CryptoComponentsFactoryArgs struct { ValidatorKeyPemFileName string SkIndex int Config config.Config + EnableEpochs config.EnableEpochs CoreComponentsHolder factory.CoreComponentsHolder ActivateBLSPubKeyMessageVerification bool KeyLoader factory.KeyLoaderHandler @@ -52,6 +48,7 @@ type cryptoComponentsFactory struct { validatorKeyPemFileName string skIndex int config config.Config + enableEpochs config.EnableEpochs coreComponentsHolder factory.CoreComponentsHolder activateBLSPubKeyMessageVerification bool keyLoader factory.KeyLoaderHandler @@ -70,13 +67,13 @@ type cryptoParams struct { // cryptoComponents struct holds the crypto components type cryptoComponents struct { - txSingleSigner crypto.SingleSigner - blockSingleSigner crypto.SingleSigner - multiSigner crypto.MultiSigner - peerSignHandler crypto.PeerSignatureHandler - blockSignKeyGen crypto.KeyGenerator - txSignKeyGen crypto.KeyGenerator - messageSignVerifier vm.MessageSignVerifier + txSingleSigner crypto.SingleSigner + blockSingleSigner crypto.SingleSigner + multiSignerContainer cryptoCommon.MultiSignerContainer + peerSignHandler crypto.PeerSignatureHandler + blockSignKeyGen crypto.KeyGenerator + txSignKeyGen crypto.KeyGenerator + messageSignVerifier vm.MessageSignVerifier cryptoParams } @@ -104,6 +101,7 @@ func NewCryptoComponentsFactory(args CryptoComponentsFactoryArgs) (*cryptoCompon keyLoader: args.KeyLoader, isInImportMode: args.IsInImportMode, importModeNoSigCheck: args.ImportModeNoSigCheck, + enableEpochs: args.EnableEpochs, } return ccf, nil @@ -134,12 +132,7 @@ func (ccf *cryptoComponentsFactory) Create() (*cryptoComponents, error) { return nil, err } - multisigHasher, err := ccf.getMultiSigHasherFromConfig() - if err != nil { - return nil, err - } - - multiSigner, err := ccf.createMultiSigner(multisigHasher, cp, blockSignKeyGen, ccf.importModeNoSigCheck) + multiSigner, err := ccf.createMultiSignerContainer(blockSignKeyGen, ccf.importModeNoSigCheck) if err != nil { return nil, err } @@ -171,14 +164,14 @@ func (ccf *cryptoComponentsFactory) Create() (*cryptoComponents, error) { log.Debug("block sign pubkey", "value", cp.publicKeyString) return &cryptoComponents{ - txSingleSigner: txSingleSigner, - blockSingleSigner: interceptSingleSigner, - multiSigner: multiSigner, - peerSignHandler: peerSigHandler, - blockSignKeyGen: blockSignKeyGen, - txSignKeyGen: txSignKeyGen, - messageSignVerifier: messageSignVerifier, - cryptoParams: *cp, + txSingleSigner: txSingleSigner, + blockSingleSigner: interceptSingleSigner, + multiSignerContainer: multiSigner, + peerSignHandler: peerSigHandler, + blockSignKeyGen: blockSignKeyGen, + txSignKeyGen: txSignKeyGen, + messageSignVerifier: messageSignVerifier, + cryptoParams: *cp, }, nil } @@ -199,45 +192,18 @@ func (ccf *cryptoComponentsFactory) createSingleSigner(importModeNoSigCheck bool } } -func (ccf *cryptoComponentsFactory) getMultiSigHasherFromConfig() (hashing.Hasher, error) { - if ccf.consensusType == consensus.BlsConsensusType && ccf.config.MultisigHasher.Type != "blake2b" { - return nil, errors.ErrMultiSigHasherMissmatch - } - - switch ccf.config.MultisigHasher.Type { - case "sha256": - return sha256.NewSha256(), nil - case "blake2b": - if ccf.consensusType == consensus.BlsConsensusType { - return blake2b.NewBlake2bWithSize(multisig.BlsHashSize) - } - return blake2b.NewBlake2b(), nil - } - - return nil, errors.ErrMissingMultiHasherConfig -} - -func (ccf *cryptoComponentsFactory) createMultiSigner( - hasher hashing.Hasher, - cp *cryptoParams, +func (ccf *cryptoComponentsFactory) createMultiSignerContainer( blSignKeyGen crypto.KeyGenerator, importModeNoSigCheck bool, -) (crypto.MultiSigner, error) { - if importModeNoSigCheck { - log.Warn("using disabled multi signer because the node is running in import-db 'turbo mode'") - return &disabledMultiSig.DisabledMultiSig{}, nil - } +) (cryptoCommon.MultiSignerContainer, error) { - switch ccf.consensusType { - case consensus.BlsConsensusType: - blsSigner := &mclMultiSig.BlsMultiSigner{Hasher: hasher} - return multisig.NewBLSMultisig(blsSigner, []string{string(cp.publicKeyBytes)}, cp.privateKey, blSignKeyGen, uint16(0)) - case disabledSigChecking: - log.Warn("using disabled multi signer") - return &disabledMultiSig.DisabledMultiSig{}, nil - default: - return nil, errors.ErrInvalidConsensusConfig + args := MultiSigArgs{ + MultiSigHasherType: ccf.config.MultisigHasher.Type, + BlSignKeyGen: blSignKeyGen, + ConsensusType: ccf.consensusType, + ImportModeNoSigCheck: importModeNoSigCheck, } + return NewMultiSignerContainer(args, ccf.enableEpochs.BLSMultiSignerEnableEpoch) } func (ccf *cryptoComponentsFactory) getSuite() (crypto.Suite, error) { diff --git a/factory/crypto/cryptoComponentsHandler.go b/factory/crypto/cryptoComponentsHandler.go index b1295348150..2b2c5f4eb04 100644 --- a/factory/crypto/cryptoComponentsHandler.go +++ b/factory/crypto/cryptoComponentsHandler.go @@ -5,7 +5,8 @@ import ( "sync" "github.com/ElrondNetwork/elrond-go-core/core/check" - "github.com/ElrondNetwork/elrond-go-crypto" + crypto "github.com/ElrondNetwork/elrond-go-crypto" + cryptoCommon "github.com/ElrondNetwork/elrond-go/common/crypto" "github.com/ElrondNetwork/elrond-go/errors" "github.com/ElrondNetwork/elrond-go/factory" "github.com/ElrondNetwork/elrond-go/vm" @@ -90,7 +91,7 @@ func (mcc *managedCryptoComponents) CheckSubcomponents() error { if check.IfNil(mcc.cryptoComponents.blockSingleSigner) { return errors.ErrNilBlockSigner } - if check.IfNil(mcc.cryptoComponents.multiSigner) { + if check.IfNil(mcc.cryptoComponents.multiSignerContainer) { return errors.ErrNilMultiSigner } if check.IfNil(mcc.cryptoComponents.peerSignHandler) { @@ -193,41 +194,52 @@ func (mcc *managedCryptoComponents) BlockSigner() crypto.SingleSigner { return mcc.cryptoComponents.blockSingleSigner } -// MultiSigner returns the block multi-signer -func (mcc *managedCryptoComponents) MultiSigner() crypto.MultiSigner { +// MultiSignerContainer returns the multiSigner container holding the multiSigner versions +func (mcc *managedCryptoComponents) MultiSignerContainer() cryptoCommon.MultiSignerContainer { mcc.mutCryptoComponents.RLock() defer mcc.mutCryptoComponents.RUnlock() - if mcc.cryptoComponents == nil { return nil } - return mcc.cryptoComponents.multiSigner + return mcc.cryptoComponents.multiSignerContainer } -// PeerSignatureHandler returns the peer signature handler -func (mcc *managedCryptoComponents) PeerSignatureHandler() crypto.PeerSignatureHandler { +// SetMultiSignerContainer sets the multiSigner container in the crypto components +func (mcc *managedCryptoComponents) SetMultiSignerContainer(ms cryptoCommon.MultiSignerContainer) error { + mcc.mutCryptoComponents.Lock() + mcc.multiSignerContainer = ms + mcc.mutCryptoComponents.Unlock() + + return nil +} + +// GetMultiSigner returns the multiSigner configured in the multiSigner container for the given epoch +func (mcc *managedCryptoComponents) GetMultiSigner(epoch uint32) (crypto.MultiSigner, error) { mcc.mutCryptoComponents.RLock() defer mcc.mutCryptoComponents.RUnlock() if mcc.cryptoComponents == nil { - return nil + return nil, errors.ErrNilCryptoComponentsHolder } - return mcc.cryptoComponents.peerSignHandler + if mcc.multiSignerContainer == nil { + return nil, errors.ErrNilMultiSignerContainer + } + + return mcc.MultiSignerContainer().GetMultiSigner(epoch) } -// SetMultiSigner sets the block multi-signer -func (mcc *managedCryptoComponents) SetMultiSigner(ms crypto.MultiSigner) error { - mcc.mutCryptoComponents.Lock() - defer mcc.mutCryptoComponents.Unlock() +// PeerSignatureHandler returns the peer signature handler +func (mcc *managedCryptoComponents) PeerSignatureHandler() crypto.PeerSignatureHandler { + mcc.mutCryptoComponents.RLock() + defer mcc.mutCryptoComponents.RUnlock() if mcc.cryptoComponents == nil { - return errors.ErrNilCryptoComponents + return nil } - mcc.cryptoComponents.multiSigner = ms - return nil + return mcc.cryptoComponents.peerSignHandler } // BlockSignKeyGen returns the block signer key generator @@ -271,14 +283,14 @@ func (mcc *managedCryptoComponents) Clone() interface{} { cryptoComp := (*cryptoComponents)(nil) if mcc.cryptoComponents != nil { cryptoComp = &cryptoComponents{ - txSingleSigner: mcc.TxSingleSigner(), - blockSingleSigner: mcc.BlockSigner(), - multiSigner: mcc.MultiSigner(), - peerSignHandler: mcc.PeerSignatureHandler(), - blockSignKeyGen: mcc.BlockSignKeyGen(), - txSignKeyGen: mcc.TxSignKeyGen(), - messageSignVerifier: mcc.MessageSignVerifier(), - cryptoParams: mcc.cryptoParams, + txSingleSigner: mcc.TxSingleSigner(), + blockSingleSigner: mcc.BlockSigner(), + multiSignerContainer: mcc.MultiSignerContainer(), + peerSignHandler: mcc.PeerSignatureHandler(), + blockSignKeyGen: mcc.BlockSignKeyGen(), + txSignKeyGen: mcc.TxSignKeyGen(), + messageSignVerifier: mcc.MessageSignVerifier(), + cryptoParams: mcc.cryptoParams, } } diff --git a/factory/crypto/cryptoComponentsHandler_test.go b/factory/crypto/cryptoComponentsHandler_test.go index 27a38025e6c..a47390492f7 100644 --- a/factory/crypto/cryptoComponentsHandler_test.go +++ b/factory/crypto/cryptoComponentsHandler_test.go @@ -3,10 +3,10 @@ package crypto_test import ( "testing" + "github.com/ElrondNetwork/elrond-go/errors" "github.com/ElrondNetwork/elrond-go/factory" cryptoComp "github.com/ElrondNetwork/elrond-go/factory/crypto" componentsMock "github.com/ElrondNetwork/elrond-go/testscommon/components" - "github.com/ElrondNetwork/elrond-go/testscommon/cryptoMocks" "github.com/stretchr/testify/require" ) @@ -41,7 +41,7 @@ func TestManagedCryptoComponents_CreateShouldWork(t *testing.T) { require.NoError(t, err) require.Nil(t, managedCryptoComponents.TxSingleSigner()) require.Nil(t, managedCryptoComponents.BlockSigner()) - require.Nil(t, managedCryptoComponents.MultiSigner()) + require.Nil(t, managedCryptoComponents.MultiSignerContainer()) require.Nil(t, managedCryptoComponents.BlockSignKeyGen()) require.Nil(t, managedCryptoComponents.TxSignKeyGen()) require.Nil(t, managedCryptoComponents.MessageSignVerifier()) @@ -50,7 +50,10 @@ func TestManagedCryptoComponents_CreateShouldWork(t *testing.T) { require.NoError(t, err) require.NotNil(t, managedCryptoComponents.TxSingleSigner()) require.NotNil(t, managedCryptoComponents.BlockSigner()) - require.NotNil(t, managedCryptoComponents.MultiSigner()) + require.NotNil(t, managedCryptoComponents.MultiSignerContainer()) + multiSigner, errGet := managedCryptoComponents.MultiSignerContainer().GetMultiSigner(0) + require.NotNil(t, multiSigner) + require.Nil(t, errGet) require.NotNil(t, managedCryptoComponents.BlockSignKeyGen()) require.NotNil(t, managedCryptoComponents.TxSignKeyGen()) require.NotNil(t, managedCryptoComponents.MessageSignVerifier()) @@ -68,21 +71,6 @@ func TestManagedCryptoComponents_CheckSubcomponents(t *testing.T) { require.NoError(t, err) } -func TestManagedCryptoComponents_SetMultiSigner(t *testing.T) { - t.Parallel() - if testing.Short() { - t.Skip("this is not a short test") - } - - managedCryptoComponents := getManagedCryptoComponents(t) - - ms := &cryptoMocks.MultisignerMock{} - err := managedCryptoComponents.SetMultiSigner(ms) - require.NoError(t, err) - - require.Equal(t, managedCryptoComponents.MultiSigner(), ms) -} - func TestManagedCryptoComponents_Close(t *testing.T) { t.Parallel() if testing.Short() { @@ -93,7 +81,9 @@ func TestManagedCryptoComponents_Close(t *testing.T) { err := managedCryptoComponents.Close() require.NoError(t, err) - require.Nil(t, managedCryptoComponents.MultiSigner()) + multiSigner, errGet := managedCryptoComponents.GetMultiSigner(0) + require.Nil(t, multiSigner) + require.Equal(t, errors.ErrNilCryptoComponentsHolder, errGet) } func getManagedCryptoComponents(t *testing.T) factory.CryptoComponentsHandler { diff --git a/factory/crypto/cryptoComponents_test.go b/factory/crypto/cryptoComponents_test.go index 3030e74402c..5453469f275 100644 --- a/factory/crypto/cryptoComponents_test.go +++ b/factory/crypto/cryptoComponents_test.go @@ -12,7 +12,6 @@ import ( cryptoComp "github.com/ElrondNetwork/elrond-go/factory/crypto" "github.com/ElrondNetwork/elrond-go/factory/mock" componentsMock "github.com/ElrondNetwork/elrond-go/testscommon/components" - "github.com/ElrondNetwork/elrond-go/testscommon/hashingMocks" "github.com/stretchr/testify/require" ) @@ -206,62 +205,6 @@ func TestCryptoComponentsFactory_CreateSingleSignerOK(t *testing.T) { require.NotNil(t, singleSigner) } -func TestCryptoComponentsFactory_GetMultiSigHasherFromConfigInvalidHasherShouldErr(t *testing.T) { - t.Parallel() - if testing.Short() { - t.Skip("this is not a short test") - } - - coreComponents := componentsMock.GetCoreComponents() - args := componentsMock.GetCryptoArgs(coreComponents) - args.Config.Consensus.Type = "" - args.Config.MultisigHasher.Type = "" - ccf, err := cryptoComp.NewCryptoComponentsFactory(args) - require.NotNil(t, ccf) - require.Nil(t, err) - - multiSigHasher, err := ccf.GetMultiSigHasherFromConfig() - require.Nil(t, multiSigHasher) - require.Equal(t, errErd.ErrMissingMultiHasherConfig, err) -} - -func TestCryptoComponentsFactory_GetMultiSigHasherFromConfigMismatchConsensusTypeMultiSigHasher(t *testing.T) { - t.Parallel() - if testing.Short() { - t.Skip("this is not a short test") - } - - coreComponents := componentsMock.GetCoreComponents() - args := componentsMock.GetCryptoArgs(coreComponents) - args.Config.MultisigHasher.Type = "sha256" - ccf, err := cryptoComp.NewCryptoComponentsFactory(args) - require.NotNil(t, ccf) - require.Nil(t, err) - - multiSigHasher, err := ccf.GetMultiSigHasherFromConfig() - require.Nil(t, multiSigHasher) - require.Equal(t, errErd.ErrMultiSigHasherMissmatch, err) -} - -func TestCryptoComponentsFactory_GetMultiSigHasherFromConfigOK(t *testing.T) { - t.Parallel() - if testing.Short() { - t.Skip("this is not a short test") - } - - coreComponents := componentsMock.GetCoreComponents() - args := componentsMock.GetCryptoArgs(coreComponents) - args.Config.Consensus.Type = "bls" - args.Config.MultisigHasher.Type = "blake2b" - ccf, err := cryptoComp.NewCryptoComponentsFactory(args) - require.NotNil(t, ccf) - require.Nil(t, err) - - multiSigHasher, err := ccf.GetMultiSigHasherFromConfig() - require.Nil(t, err) - require.NotNil(t, multiSigHasher) -} - func TestCryptoComponentsFactory_CreateMultiSignerInvalidConsensusTypeShouldErr(t *testing.T) { t.Parallel() if testing.Short() { @@ -275,8 +218,7 @@ func TestCryptoComponentsFactory_CreateMultiSignerInvalidConsensusTypeShouldErr( require.NotNil(t, ccf) require.Nil(t, err) - cp := ccf.CreateDummyCryptoParams() - multiSigner, err := ccf.CreateMultiSigner(&hashingMocks.HasherMock{}, cp, &mock.KeyGenMock{}, false) + multiSigner, err := ccf.CreateMultiSignerContainer(&mock.KeyGenMock{}, false) require.Nil(t, multiSigner) require.Equal(t, errErd.ErrInvalidConsensusConfig, err) } @@ -295,10 +237,8 @@ func TestCryptoComponentsFactory_CreateMultiSignerOK(t *testing.T) { suite, _ := ccf.GetSuite() blockSignKeyGen := signing.NewKeyGenerator(suite) - cp, _ := ccf.CreateCryptoParams(blockSignKeyGen) - multisigHasher, _ := ccf.GetMultiSigHasherFromConfig() - multiSigner, err := ccf.CreateMultiSigner(multisigHasher, cp, blockSignKeyGen, false) + multiSigner, err := ccf.CreateMultiSignerContainer(blockSignKeyGen, false) require.Nil(t, err) require.NotNil(t, multiSigner) } diff --git a/factory/crypto/export_test.go b/factory/crypto/export_test.go index 23c178c98a2..9e006c825f3 100644 --- a/factory/crypto/export_test.go +++ b/factory/crypto/export_test.go @@ -1,8 +1,8 @@ package crypto import ( - "github.com/ElrondNetwork/elrond-go-core/hashing" crypto "github.com/ElrondNetwork/elrond-go-crypto" + cryptoCommon "github.com/ElrondNetwork/elrond-go/common/crypto" ) // GetSkPk - @@ -15,11 +15,6 @@ func (ccf *cryptoComponentsFactory) CreateSingleSigner(importModeNoSigCheck bool return ccf.createSingleSigner(importModeNoSigCheck) } -// GetMultiSigHasherFromConfig - -func (ccf *cryptoComponentsFactory) GetMultiSigHasherFromConfig() (hashing.Hasher, error) { - return ccf.getMultiSigHasherFromConfig() -} - // CreateDummyCryptoParams func (ccf *cryptoComponentsFactory) CreateDummyCryptoParams() *cryptoParams { return &cryptoParams{} @@ -30,11 +25,12 @@ func (ccf *cryptoComponentsFactory) CreateCryptoParams(blockSignKeyGen crypto.Ke return ccf.createCryptoParams(blockSignKeyGen) } -// CreateMultiSigner - -func (ccf *cryptoComponentsFactory) CreateMultiSigner( - h hashing.Hasher, cp *cryptoParams, blSignKeyGen crypto.KeyGenerator, importModeNoSigCheck bool, -) (crypto.MultiSigner, error) { - return ccf.createMultiSigner(h, cp, blSignKeyGen, importModeNoSigCheck) +// CreateMultiSignerContainer - +func (ccf *cryptoComponentsFactory) CreateMultiSignerContainer( + blSignKeyGen crypto.KeyGenerator, + importModeNoSigCheck bool, +) (cryptoCommon.MultiSignerContainer, error) { + return ccf.createMultiSignerContainer(blSignKeyGen, importModeNoSigCheck) } // GetSuite - diff --git a/factory/crypto/multiSignerContainer.go b/factory/crypto/multiSignerContainer.go new file mode 100644 index 00000000000..b886bfa0ad4 --- /dev/null +++ b/factory/crypto/multiSignerContainer.go @@ -0,0 +1,156 @@ +package crypto + +import ( + "sort" + "sync" + + "github.com/ElrondNetwork/elrond-go-core/core/check" + "github.com/ElrondNetwork/elrond-go-core/hashing" + "github.com/ElrondNetwork/elrond-go-core/hashing/blake2b" + "github.com/ElrondNetwork/elrond-go-core/hashing/sha256" + crypto "github.com/ElrondNetwork/elrond-go-crypto" + disabledMultiSig "github.com/ElrondNetwork/elrond-go-crypto/signing/disabled/multisig" + mclMultiSig "github.com/ElrondNetwork/elrond-go-crypto/signing/mcl/multisig" + "github.com/ElrondNetwork/elrond-go-crypto/signing/multisig" + "github.com/ElrondNetwork/elrond-go/config" + "github.com/ElrondNetwork/elrond-go/consensus" + "github.com/ElrondNetwork/elrond-go/errors" +) + +const ( + blsNoKOSK = "no-KOSK" + blsKOSK = "KOSK" +) + +type epochMultiSigner struct { + epoch uint32 + multiSigner crypto.MultiSigner +} + +type container struct { + multiSigners []*epochMultiSigner + mutSigners sync.RWMutex +} + +// MultiSigArgs holds the arguments for creating the multiSignerContainer container +type MultiSigArgs struct { + MultiSigHasherType string + BlSignKeyGen crypto.KeyGenerator + ConsensusType string + ImportModeNoSigCheck bool +} + +// NewMultiSignerContainer creates the multiSignerContainer container +func NewMultiSignerContainer(args MultiSigArgs, multiSignerConfig []config.MultiSignerConfig) (*container, error) { + if len(multiSignerConfig) == 0 { + return nil, errors.ErrMissingMultiSignerConfig + } + + c := &container{ + multiSigners: make([]*epochMultiSigner, len(multiSignerConfig)), + } + + sortedMultiSignerConfig := sortMultiSignerConfig(multiSignerConfig) + if sortedMultiSignerConfig[0].EnableEpoch != 0 { + return nil, errors.ErrMissingEpochZeroMultiSignerConfig + } + + for i, mConfig := range sortedMultiSignerConfig { + multiSigner, err := createMultiSigner(mConfig.Type, args) + if err != nil { + return nil, err + } + + c.multiSigners[i] = &epochMultiSigner{ + multiSigner: multiSigner, + epoch: mConfig.EnableEpoch, + } + } + + return c, nil +} + +// GetMultiSigner returns the multiSigner configured for the given epoch +func (c *container) GetMultiSigner(epoch uint32) (crypto.MultiSigner, error) { + c.mutSigners.RLock() + defer c.mutSigners.RUnlock() + + for i := len(c.multiSigners) - 1; i >= 0; i-- { + if epoch >= c.multiSigners[i].epoch { + return c.multiSigners[i].multiSigner, nil + } + } + return nil, errors.ErrMissingMultiSigner +} + +// IsInterfaceNil returns true if the underlying object is nil +func (c *container) IsInterfaceNil() bool { + return c == nil +} + +func createMultiSigner(multiSigType string, args MultiSigArgs) (crypto.MultiSigner, error) { + if args.ImportModeNoSigCheck { + log.Warn("using disabled multi signer because the node is running in import-db 'turbo mode'") + return &disabledMultiSig.DisabledMultiSig{}, nil + } + + switch args.ConsensusType { + case consensus.BlsConsensusType: + hasher, err := getMultiSigHasherFromConfig(args) + if err != nil { + return nil, err + } + blsSigner, err := createLowLevelSigner(multiSigType, hasher) + if err != nil { + return nil, err + } + return multisig.NewBLSMultisig(blsSigner, args.BlSignKeyGen) + case disabledSigChecking: + log.Warn("using disabled multi signer") + return &disabledMultiSig.DisabledMultiSig{}, nil + default: + return nil, errors.ErrInvalidConsensusConfig + } +} + +func createLowLevelSigner(multiSigType string, hasher hashing.Hasher) (crypto.LowLevelSignerBLS, error) { + if check.IfNil(hasher) { + return nil, errors.ErrNilHasher + } + + switch multiSigType { + case blsNoKOSK: + return &mclMultiSig.BlsMultiSigner{Hasher: hasher}, nil + case blsKOSK: + return &mclMultiSig.BlsMultiSignerKOSK{}, nil + default: + return nil, errors.ErrSignerNotSupported + } +} + +func getMultiSigHasherFromConfig(args MultiSigArgs) (hashing.Hasher, error) { + if args.ConsensusType == consensus.BlsConsensusType && args.MultiSigHasherType != "blake2b" { + return nil, errors.ErrMultiSigHasherMissmatch + } + + switch args.MultiSigHasherType { + case "sha256": + return sha256.NewSha256(), nil + case "blake2b": + if args.ConsensusType == consensus.BlsConsensusType { + return blake2b.NewBlake2bWithSize(mclMultiSig.HasherOutputSize) + } + return blake2b.NewBlake2b(), nil + } + + return nil, errors.ErrMissingMultiHasherConfig +} + +func sortMultiSignerConfig(multiSignerConfig []config.MultiSignerConfig) []config.MultiSignerConfig { + sortedMultiSignerConfig := append([]config.MultiSignerConfig{}, multiSignerConfig...) + sort.Slice(sortedMultiSignerConfig, func(i, j int) bool { + return sortedMultiSignerConfig[i].EnableEpoch < sortedMultiSignerConfig[j].EnableEpoch + }) + + return sortedMultiSignerConfig +} diff --git a/factory/crypto/multiSignerContainer_test.go b/factory/crypto/multiSignerContainer_test.go new file mode 100644 index 00000000000..1d3b52d0941 --- /dev/null +++ b/factory/crypto/multiSignerContainer_test.go @@ -0,0 +1,334 @@ +package crypto + +import ( + "math/rand" + "testing" + + "github.com/ElrondNetwork/elrond-go-core/core/check" + disabledMultiSig "github.com/ElrondNetwork/elrond-go-crypto/signing/disabled/multisig" + mclMultiSig "github.com/ElrondNetwork/elrond-go-crypto/signing/mcl/multisig" + "github.com/ElrondNetwork/elrond-go/config" + "github.com/ElrondNetwork/elrond-go/consensus" + "github.com/ElrondNetwork/elrond-go/errors" + "github.com/ElrondNetwork/elrond-go/testscommon/cryptoMocks" + "github.com/ElrondNetwork/elrond-go/testscommon/hashingMocks" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_NewMultiSignerContainer(t *testing.T) { + t.Parallel() + + args := createDefaultMultiSignerArgs() + multiSigConfig := createDefaultMultiSignerConfig() + + t.Run("nil multiSigner config should err", func(t *testing.T) { + multiSigContainer, err := NewMultiSignerContainer(args, nil) + + require.Nil(t, multiSigContainer) + require.Equal(t, errors.ErrMissingMultiSignerConfig, err) + }) + t.Run("missing epoch 0 config should err", func(t *testing.T) { + multiSigConfigClone := append([]config.MultiSignerConfig{}, multiSigConfig...) + multiSigConfigClone[0].EnableEpoch = 1 + multiSigContainer, err := NewMultiSignerContainer(args, multiSigConfigClone) + + require.Nil(t, multiSigContainer) + require.Equal(t, errors.ErrMissingEpochZeroMultiSignerConfig, err) + }) + t.Run("invalid multiSigner type should err", func(t *testing.T) { + multiSigConfigClone := append([]config.MultiSignerConfig{}, multiSigConfig...) + multiSigConfigClone[1].Type = "invalid type" + multiSigContainer, err := NewMultiSignerContainer(args, multiSigConfigClone) + + require.Nil(t, multiSigContainer) + require.Equal(t, errors.ErrSignerNotSupported, err) + }) + t.Run("valid params", func(t *testing.T) { + multiSigContainer, err := NewMultiSignerContainer(args, multiSigConfig) + + require.Nil(t, err) + require.NotNil(t, multiSigContainer) + }) +} + +func TestContainer_GetMultiSigner(t *testing.T) { + t.Parallel() + + args := createDefaultMultiSignerArgs() + multiSigConfig := createDefaultMultiSignerConfig() + + t.Run("missing epoch config should err (can only happen if epoch 0 is missing)", func(t *testing.T) { + multiSigContainer, _ := NewMultiSignerContainer(args, multiSigConfig) + multiSigContainer.multiSigners[0].epoch = 1 + + multiSigner, err := multiSigContainer.GetMultiSigner(0) + require.Nil(t, multiSigner) + require.Equal(t, errors.ErrMissingMultiSigner, err) + }) + t.Run("get multi signer OK", func(t *testing.T) { + multiSigContainer, _ := NewMultiSignerContainer(args, multiSigConfig) + + for i := uint32(0); i < 10; i++ { + multiSigner, err := multiSigContainer.GetMultiSigner(i) + require.Nil(t, err) + require.Equal(t, multiSigContainer.multiSigners[0].multiSigner, multiSigner) + } + for i := uint32(10); i < 30; i++ { + multiSigner, err := multiSigContainer.GetMultiSigner(i) + require.Nil(t, err) + require.Equal(t, multiSigContainer.multiSigners[1].multiSigner, multiSigner) + } + }) +} + +func TestContainer_IsInterfaceNil(t *testing.T) { + t.Parallel() + + var msc *container + assert.True(t, check.IfNil(msc)) + + args := createDefaultMultiSignerArgs() + multiSigConfig := createDefaultMultiSignerConfig() + + msc, _ = NewMultiSignerContainer(args, multiSigConfig) + assert.False(t, check.IfNil(msc)) +} + +func TestContainer_createMultiSigner(t *testing.T) { + t.Parallel() + + t.Run("create disabled multi signer", func(t *testing.T) { + args := createDefaultMultiSignerArgs() + args.ImportModeNoSigCheck = true + multiSigType := "KOSK" + multiSigner, err := createMultiSigner(multiSigType, args) + require.Nil(t, err) + _, ok := multiSigner.(*disabledMultiSig.DisabledMultiSig) + require.True(t, ok) + }) + t.Run("invalid consensus config", func(t *testing.T) { + args := createDefaultMultiSignerArgs() + args.ConsensusType = "invalid" + multiSigType := "KOSK" + multiSigner, err := createMultiSigner(multiSigType, args) + require.Nil(t, multiSigner) + require.Equal(t, errors.ErrInvalidConsensusConfig, err) + }) + t.Run("bls consensus type invalid hasher config", func(t *testing.T) { + args := createDefaultMultiSignerArgs() + args.ConsensusType = consensus.BlsConsensusType + args.MultiSigHasherType = "sha256" + multiSigType := "KOSK" + multiSigner, err := createMultiSigner(multiSigType, args) + require.Nil(t, multiSigner) + require.Equal(t, errors.ErrMultiSigHasherMissmatch, err) + }) + t.Run("bls consensus type signer not supported", func(t *testing.T) { + args := createDefaultMultiSignerArgs() + args.ConsensusType = consensus.BlsConsensusType + args.MultiSigHasherType = "blake2b" + multiSigType := "not supported" + multiSigner, err := createMultiSigner(multiSigType, args) + require.Nil(t, multiSigner) + require.Equal(t, errors.ErrSignerNotSupported, err) + }) + t.Run("bls consensus type KOSK OK", func(t *testing.T) { + args := createDefaultMultiSignerArgs() + args.ConsensusType = consensus.BlsConsensusType + args.MultiSigHasherType = "blake2b" + multiSigType := blsKOSK + multiSigner, err := createMultiSigner(multiSigType, args) + require.Nil(t, err) + require.NotNil(t, multiSigner) + }) + t.Run("bls consensus type no-KOSK OK", func(t *testing.T) { + args := createDefaultMultiSignerArgs() + args.ConsensusType = consensus.BlsConsensusType + args.MultiSigHasherType = "blake2b" + multiSigType := blsNoKOSK + multiSigner, err := createMultiSigner(multiSigType, args) + require.Nil(t, err) + require.NotNil(t, multiSigner) + }) + t.Run("disabledSigChecking", func(t *testing.T) { + args := createDefaultMultiSignerArgs() + args.ConsensusType = disabledSigChecking + multiSigType := blsNoKOSK + multiSigner, err := createMultiSigner(multiSigType, args) + require.Nil(t, err) + require.NotNil(t, multiSigner) + + _, ok := multiSigner.(*disabledMultiSig.DisabledMultiSig) + require.True(t, ok) + }) +} + +func TestContainer_createLowLevelSigner(t *testing.T) { + t.Parallel() + + hasher := &hashingMocks.HasherMock{} + t.Run("nil hasher should err", func(t *testing.T) { + llSig, err := createLowLevelSigner(blsKOSK, nil) + require.Nil(t, llSig) + require.Equal(t, errors.ErrNilHasher, err) + }) + t.Run("not supported multiSig type should err", func(t *testing.T) { + llSig, err := createLowLevelSigner("not supported", hasher) + require.Nil(t, llSig) + require.Equal(t, errors.ErrSignerNotSupported, err) + }) + t.Run("multiSig of type no KOSK", func(t *testing.T) { + llSig, err := createLowLevelSigner(blsNoKOSK, hasher) + require.Nil(t, err) + _, ok := llSig.(*mclMultiSig.BlsMultiSigner) + require.True(t, ok) + }) + t.Run("multiSig of type KOSK", func(t *testing.T) { + llSig, err := createLowLevelSigner(blsKOSK, hasher) + require.Nil(t, err) + _, ok := llSig.(*mclMultiSig.BlsMultiSignerKOSK) + require.True(t, ok) + }) +} + +func TestContainer_getMultiSigHasherFromConfig(t *testing.T) { + t.Parallel() + + t.Run("mismatch config consensus type and hasher type", func(t *testing.T) { + args := createDefaultMultiSignerArgs() + args.ConsensusType = consensus.BlsConsensusType + args.MultiSigHasherType = "sha256" + hasher, err := getMultiSigHasherFromConfig(args) + require.Nil(t, hasher) + require.Equal(t, errors.ErrMultiSigHasherMissmatch, err) + }) + t.Run("sha256 config", func(t *testing.T) { + args := createDefaultMultiSignerArgs() + args.ConsensusType = "dummy config" + args.MultiSigHasherType = "sha256" + hasher, err := getMultiSigHasherFromConfig(args) + require.Nil(t, err) + require.NotNil(t, hasher) + }) + t.Run("invalid hasher config", func(t *testing.T) { + args := createDefaultMultiSignerArgs() + args.ConsensusType = "dummy config" + args.MultiSigHasherType = "unknown" + hasher, err := getMultiSigHasherFromConfig(args) + require.Nil(t, hasher) + require.Equal(t, errors.ErrMissingMultiHasherConfig, err) + }) + t.Run("blake2b config and bls consensus", func(t *testing.T) { + args := createDefaultMultiSignerArgs() + args.ConsensusType = consensus.BlsConsensusType + args.MultiSigHasherType = "blake2b" + hasher, err := getMultiSigHasherFromConfig(args) + require.Nil(t, err) + require.NotNil(t, hasher) + }) + t.Run("blake2b config and non-bls consensus", func(t *testing.T) { + args := createDefaultMultiSignerArgs() + args.ConsensusType = "dummy config" + args.MultiSigHasherType = "blake2b" + hasher, err := getMultiSigHasherFromConfig(args) + require.Nil(t, err) + require.NotNil(t, hasher) + }) +} + +func TestContainer_sortMultiSignerConfig(t *testing.T) { + multiSignersOrderedConfig := []config.MultiSignerConfig{ + { + EnableEpoch: 2, + Type: "KOSK", + }, + { + EnableEpoch: 10, + Type: "no-KOSK", + }, + { + EnableEpoch: 100, + Type: "BN", + }, + { + EnableEpoch: 200, + Type: "DUMMY", + }, + } + + for i := 0; i < 20; i++ { + shuffledConfig := append([]config.MultiSignerConfig{}, multiSignersOrderedConfig...) + rand.Shuffle(len(shuffledConfig), func(i, j int) { + shuffledConfig[i], shuffledConfig[j] = shuffledConfig[j], shuffledConfig[i] + }) + sortedConfig := sortMultiSignerConfig(shuffledConfig) + require.Equal(t, multiSignersOrderedConfig, sortedConfig) + } +} + +func Test_getMultiSigHasherFromConfigInvalidHasherShouldErr(t *testing.T) { + t.Parallel() + if testing.Short() { + t.Skip("this is not a short test") + } + + args := createDefaultMultiSignerArgs() + args.ConsensusType = "" + args.MultiSigHasherType = "" + + multiSigHasher, err := getMultiSigHasherFromConfig(args) + require.Nil(t, multiSigHasher) + require.Equal(t, errors.ErrMissingMultiHasherConfig, err) +} + +func Test_getMultiSigHasherFromConfigMismatchConsensusTypeMultiSigHasher(t *testing.T) { + t.Parallel() + if testing.Short() { + t.Skip("this is not a short test") + } + + args := createDefaultMultiSignerArgs() + args.MultiSigHasherType = "sha256" + + multiSigHasher, err := getMultiSigHasherFromConfig(args) + require.Nil(t, multiSigHasher) + require.Equal(t, errors.ErrMultiSigHasherMissmatch, err) +} + +func Test_getMultiSigHasherFromConfigOK(t *testing.T) { + t.Parallel() + if testing.Short() { + t.Skip("this is not a short test") + } + + args := createDefaultMultiSignerArgs() + args.ConsensusType = "bls" + args.MultiSigHasherType = "blake2b" + + multiSigHasher, err := getMultiSigHasherFromConfig(args) + require.Nil(t, err) + require.NotNil(t, multiSigHasher) +} + +func createDefaultMultiSignerArgs() MultiSigArgs { + return MultiSigArgs{ + MultiSigHasherType: "blake2b", + BlSignKeyGen: &cryptoMocks.KeyGenStub{}, + ConsensusType: "bls", + ImportModeNoSigCheck: false, + } +} + +func createDefaultMultiSignerConfig() []config.MultiSignerConfig { + return []config.MultiSignerConfig{ + { + EnableEpoch: 0, + Type: "no-KOSK", + }, + { + EnableEpoch: 10, + Type: "KOSK", + }, + } +} diff --git a/factory/interface.go b/factory/interface.go index 64c4b25253c..1070434270c 100644 --- a/factory/interface.go +++ b/factory/interface.go @@ -16,6 +16,7 @@ import ( crypto "github.com/ElrondNetwork/elrond-go-crypto" "github.com/ElrondNetwork/elrond-go/cmd/node/factory" "github.com/ElrondNetwork/elrond-go/common" + cryptoCommon "github.com/ElrondNetwork/elrond-go/common/crypto" "github.com/ElrondNetwork/elrond-go/common/statistics" "github.com/ElrondNetwork/elrond-go/consensus" "github.com/ElrondNetwork/elrond-go/dataRetriever" @@ -155,9 +156,10 @@ type CryptoComponentsHolder interface { CryptoParamsHolder TxSingleSigner() crypto.SingleSigner BlockSigner() crypto.SingleSigner - MultiSigner() crypto.MultiSigner + SetMultiSignerContainer(container cryptoCommon.MultiSignerContainer) error + MultiSignerContainer() cryptoCommon.MultiSignerContainer + GetMultiSigner(epoch uint32) (crypto.MultiSigner, error) PeerSignatureHandler() crypto.PeerSignatureHandler - SetMultiSigner(ms crypto.MultiSigner) error BlockSignKeyGen() crypto.KeyGenerator TxSignKeyGen() crypto.KeyGenerator MessageSignVerifier() vm.MessageSignVerifier diff --git a/factory/mock/cryptoComponentsMock.go b/factory/mock/cryptoComponentsMock.go index 8ece29b3749..6e200f40e26 100644 --- a/factory/mock/cryptoComponentsMock.go +++ b/factory/mock/cryptoComponentsMock.go @@ -1,27 +1,29 @@ package mock import ( + "errors" "sync" "github.com/ElrondNetwork/elrond-go-crypto" + cryptoCommon "github.com/ElrondNetwork/elrond-go/common/crypto" "github.com/ElrondNetwork/elrond-go/vm" ) // CryptoComponentsMock - type CryptoComponentsMock struct { - PubKey crypto.PublicKey - PrivKey crypto.PrivateKey - PubKeyString string - PrivKeyBytes []byte - PubKeyBytes []byte - BlockSig crypto.SingleSigner - TxSig crypto.SingleSigner - MultiSig crypto.MultiSigner - PeerSignHandler crypto.PeerSignatureHandler - BlKeyGen crypto.KeyGenerator - TxKeyGen crypto.KeyGenerator - MsgSigVerifier vm.MessageSignVerifier - mutMultiSig sync.RWMutex + PubKey crypto.PublicKey + PrivKey crypto.PrivateKey + PubKeyString string + PrivKeyBytes []byte + PubKeyBytes []byte + BlockSig crypto.SingleSigner + TxSig crypto.SingleSigner + MultiSigContainer cryptoCommon.MultiSignerContainer + PeerSignHandler crypto.PeerSignatureHandler + BlKeyGen crypto.KeyGenerator + TxKeyGen crypto.KeyGenerator + MsgSigVerifier vm.MessageSignVerifier + mutMultiSig sync.RWMutex } // PublicKey - @@ -59,29 +61,41 @@ func (ccm *CryptoComponentsMock) TxSingleSigner() crypto.SingleSigner { return ccm.TxSig } -// MultiSigner - -func (ccm *CryptoComponentsMock) MultiSigner() crypto.MultiSigner { +// MultiSignerContainer - +func (ccm *CryptoComponentsMock) MultiSignerContainer() cryptoCommon.MultiSignerContainer { ccm.mutMultiSig.RLock() defer ccm.mutMultiSig.RUnlock() - return ccm.MultiSig + return ccm.MultiSigContainer } -// PeerSignatureHandler - -func (ccm *CryptoComponentsMock) PeerSignatureHandler() crypto.PeerSignatureHandler { +// SetMultiSignerContainer - +func (ccm *CryptoComponentsMock) SetMultiSignerContainer(ms cryptoCommon.MultiSignerContainer) error { + ccm.mutMultiSig.Lock() + ccm.MultiSigContainer = ms + ccm.mutMultiSig.Unlock() + + return nil +} + +// GetMultiSigner - +func (ccm *CryptoComponentsMock) GetMultiSigner(epoch uint32) (crypto.MultiSigner, error) { ccm.mutMultiSig.RLock() defer ccm.mutMultiSig.RUnlock() - return ccm.PeerSignHandler + if ccm.MultiSigContainer == nil { + return nil, errors.New("nil multi sig container") + } + + return ccm.MultiSigContainer.GetMultiSigner(epoch) } -// SetMultiSigner - -func (ccm *CryptoComponentsMock) SetMultiSigner(ms crypto.MultiSigner) error { - ccm.mutMultiSig.Lock() - ccm.MultiSig = ms - ccm.mutMultiSig.Unlock() +// PeerSignatureHandler - +func (ccm *CryptoComponentsMock) PeerSignatureHandler() crypto.PeerSignatureHandler { + ccm.mutMultiSig.RLock() + defer ccm.mutMultiSig.RUnlock() - return nil + return ccm.PeerSignHandler } // BlockSignKeyGen - @@ -102,19 +116,19 @@ func (ccm *CryptoComponentsMock) MessageSignVerifier() vm.MessageSignVerifier { // Clone - func (ccm *CryptoComponentsMock) Clone() interface{} { return &CryptoComponentsMock{ - PubKey: ccm.PubKey, - PrivKey: ccm.PrivKey, - PubKeyString: ccm.PubKeyString, - PrivKeyBytes: ccm.PrivKeyBytes, - PubKeyBytes: ccm.PubKeyBytes, - BlockSig: ccm.BlockSig, - TxSig: ccm.TxSig, - MultiSig: ccm.MultiSig, - PeerSignHandler: ccm.PeerSignHandler, - BlKeyGen: ccm.BlKeyGen, - TxKeyGen: ccm.TxKeyGen, - MsgSigVerifier: ccm.MsgSigVerifier, - mutMultiSig: sync.RWMutex{}, + PubKey: ccm.PubKey, + PrivKey: ccm.PrivKey, + PubKeyString: ccm.PubKeyString, + PrivKeyBytes: ccm.PrivKeyBytes, + PubKeyBytes: ccm.PubKeyBytes, + BlockSig: ccm.BlockSig, + TxSig: ccm.TxSig, + MultiSigContainer: ccm.MultiSigContainer, + PeerSignHandler: ccm.PeerSignHandler, + BlKeyGen: ccm.BlKeyGen, + TxKeyGen: ccm.TxKeyGen, + MsgSigVerifier: ccm.MsgSigVerifier, + mutMultiSig: sync.RWMutex{}, } } diff --git a/factory/peerSignatureHandler/export_test.go b/factory/peerSignatureHandler/export_test.go index 89ecb48ff94..6132b794ed1 100644 --- a/factory/peerSignatureHandler/export_test.go +++ b/factory/peerSignatureHandler/export_test.go @@ -2,13 +2,13 @@ package peerSignatureHandler import ( "github.com/ElrondNetwork/elrond-go-core/core" - "github.com/ElrondNetwork/elrond-go-crypto" + "github.com/ElrondNetwork/elrond-go/errors" ) func (psh *peerSignatureHandler) GetPIDAndSig(entry interface{}) (core.PeerID, []byte, error) { pidSig, ok := entry.(*pidSignature) if !ok { - return "", nil, crypto.ErrWrongTypeAssertion + return "", nil, errors.ErrWrongTypeAssertion } return pidSig.pid, pidSig.signature, nil diff --git a/factory/peerSignatureHandler/peerSignatureHandler.go b/factory/peerSignatureHandler/peerSignatureHandler.go index b169d140720..6fa1f622915 100644 --- a/factory/peerSignatureHandler/peerSignatureHandler.go +++ b/factory/peerSignatureHandler/peerSignatureHandler.go @@ -6,6 +6,7 @@ import ( "github.com/ElrondNetwork/elrond-go-core/core" "github.com/ElrondNetwork/elrond-go-core/core/check" "github.com/ElrondNetwork/elrond-go-crypto" + "github.com/ElrondNetwork/elrond-go/errors" "github.com/ElrondNetwork/elrond-go/storage" ) @@ -29,10 +30,10 @@ func NewPeerSignatureHandler( keygen crypto.KeyGenerator, ) (*peerSignatureHandler, error) { if check.IfNil(pkPIDSignature) { - return nil, crypto.ErrNilCacher + return nil, errors.ErrNilCacher } if check.IfNil(singleSigner) { - return nil, crypto.ErrNilSingleSigner + return nil, errors.ErrNilSingleSigner } if check.IfNil(keygen) { return nil, crypto.ErrNilKeyGenerator @@ -52,10 +53,10 @@ func (psh *peerSignatureHandler) VerifyPeerSignature(pk []byte, pid core.PeerID, return crypto.ErrInvalidPublicKey } if len(pid) == 0 { - return crypto.ErrInvalidPID + return errors.ErrInvalidPID } if len(signature) == 0 { - return crypto.ErrInvalidSignature + return errors.ErrInvalidSignature } senderPubKey, err := psh.keygen.PublicKeyFromByteArray(pk) @@ -77,11 +78,11 @@ func (psh *peerSignatureHandler) VerifyPeerSignature(pk []byte, pid core.PeerID, } if retrievedPID != pid { - return crypto.ErrPIDMismatch + return errors.ErrPIDMismatch } if !bytes.Equal(retrievedSig, signature) { - return crypto.ErrSignatureMismatch + return errors.ErrSignatureMismatch } return nil diff --git a/factory/peerSignatureHandler/peerSignatureHandler_test.go b/factory/peerSignatureHandler/peerSignatureHandler_test.go index b4f47b0dd3f..3ab7717221b 100644 --- a/factory/peerSignatureHandler/peerSignatureHandler_test.go +++ b/factory/peerSignatureHandler/peerSignatureHandler_test.go @@ -7,6 +7,7 @@ import ( "github.com/ElrondNetwork/elrond-go-core/core" "github.com/ElrondNetwork/elrond-go-core/core/check" "github.com/ElrondNetwork/elrond-go-crypto" + errorsErd "github.com/ElrondNetwork/elrond-go/errors" "github.com/ElrondNetwork/elrond-go/factory/peerSignatureHandler" "github.com/ElrondNetwork/elrond-go/testscommon" "github.com/ElrondNetwork/elrond-go/testscommon/cryptoMocks" @@ -23,7 +24,7 @@ func TestNewPeerSignatureHandler_NilCacherShouldErr(t *testing.T) { ) assert.True(t, check.IfNil(peerSigHandler)) - assert.Equal(t, crypto.ErrNilCacher, err) + assert.Equal(t, errorsErd.ErrNilCacher, err) } func TestNewPeerSignatureHandler_NilSingleSignerShouldErr(t *testing.T) { @@ -36,7 +37,7 @@ func TestNewPeerSignatureHandler_NilSingleSignerShouldErr(t *testing.T) { ) assert.True(t, check.IfNil(peerSigHandler)) - assert.Equal(t, crypto.ErrNilSingleSigner, err) + assert.Equal(t, errorsErd.ErrNilSingleSigner, err) } func TestNewPeerSignatureHandler_NilKeyGenShouldErr(t *testing.T) { @@ -88,7 +89,7 @@ func TestPeerSignatureHandler_VerifyPeerSignatureInvalidPID(t *testing.T) { ) err := peerSigHandler.VerifyPeerSignature([]byte("public key"), "", []byte("signature")) - assert.Equal(t, crypto.ErrInvalidPID, err) + assert.Equal(t, errorsErd.ErrInvalidPID, err) } func TestPeerSignatureHandler_VerifyPeerSignatureInvalidSignature(t *testing.T) { @@ -101,7 +102,7 @@ func TestPeerSignatureHandler_VerifyPeerSignatureInvalidSignature(t *testing.T) ) err := peerSigHandler.VerifyPeerSignature([]byte("public key"), "dummy peer", nil) - assert.Equal(t, crypto.ErrInvalidSignature, err) + assert.Equal(t, errorsErd.ErrInvalidSignature, err) } func TestPeerSignatureHandler_VerifyPeerSignatureCantGetPubKeyBytes(t *testing.T) { @@ -303,7 +304,7 @@ func TestPeerSignatureHandler_VerifyPeerSignatureDifferentPid(t *testing.T) { cache.Put(pk, cacheEntry, len(pid)+len(sig)) err := peerSigHandler.VerifyPeerSignature(pk, newPid, sig) - assert.Equal(t, crypto.ErrPIDMismatch, err) + assert.Equal(t, errorsErd.ErrPIDMismatch, err) assert.False(t, verifyCalled) } @@ -343,7 +344,7 @@ func TestPeerSignatureHandler_VerifyPeerSignatureDifferentSig(t *testing.T) { cache.Put(pk, cacheEntry, len(pid)+len(sig)) err := peerSigHandler.VerifyPeerSignature(pk, pid, newSig) - assert.Equal(t, crypto.ErrSignatureMismatch, err) + assert.Equal(t, errorsErd.ErrSignatureMismatch, err) assert.False(t, verifyCalled) } diff --git a/factory/processing/processComponents.go b/factory/processing/processComponents.go index 28d2956f7ad..7cfa11b3346 100644 --- a/factory/processing/processComponents.go +++ b/factory/processing/processComponents.go @@ -239,7 +239,7 @@ func (pcf *processComponentsFactory) Create() (*processComponents, error) { Marshalizer: pcf.coreData.InternalMarshalizer(), Hasher: pcf.coreData.Hasher(), NodesCoordinator: pcf.nodesCoordinator, - MultiSigVerifier: pcf.crypto.MultiSigner(), + MultiSigContainer: pcf.crypto.MultiSignerContainer(), SingleSigVerifier: pcf.crypto.BlockSigner(), KeyGen: pcf.crypto.BlockSignKeyGen(), FallbackHeaderValidator: fallbackHeaderValidator, diff --git a/go.mod b/go.mod index bbbd8650f88..be1758ad536 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/ElrondNetwork/covalent-indexer-go v1.0.6 github.com/ElrondNetwork/elastic-indexer-go v1.2.34-partial-execution github.com/ElrondNetwork/elrond-go-core v1.1.16-0.20220708085217-ccc0c5ac9076 - github.com/ElrondNetwork/elrond-go-crypto v1.0.1 + github.com/ElrondNetwork/elrond-go-crypto v1.1.1-0.20220725093518-7a5126e0f2e3 github.com/ElrondNetwork/elrond-go-logger v1.0.7 github.com/ElrondNetwork/elrond-vm-common v1.3.13 github.com/ElrondNetwork/go-libp2p-pubsub v0.6.1-rc1 diff --git a/go.sum b/go.sum index 53a80afa690..cdcfb5a0a8e 100644 --- a/go.sum +++ b/go.sum @@ -64,8 +64,8 @@ github.com/ElrondNetwork/elrond-go-core v1.1.16-0.20220414130405-e3cc29bc7711/go github.com/ElrondNetwork/elrond-go-core v1.1.16-0.20220708085217-ccc0c5ac9076 h1:/tNU9ydW91/rZAFTDXSDhLSPEcBs9w6+g+4NF6uqMeo= github.com/ElrondNetwork/elrond-go-core v1.1.16-0.20220708085217-ccc0c5ac9076/go.mod h1:Yz8JK5sGBctw7+gU8j2mZHbzQ09Ek4XHJ4Uinq1N6nM= github.com/ElrondNetwork/elrond-go-crypto v1.0.0/go.mod h1:DGiR7/j1xv729Xg8SsjYaUzWXL5svMd44REXjWS/gAc= -github.com/ElrondNetwork/elrond-go-crypto v1.0.1 h1:xJUUshIZQ7h+rG7Art/9QHVyaPRV1wEjrxXYBdpmRlM= -github.com/ElrondNetwork/elrond-go-crypto v1.0.1/go.mod h1:uunsvweBrrhVojL8uiQSaTPsl3YIQ9iBqtYGM6xs4s0= +github.com/ElrondNetwork/elrond-go-crypto v1.1.1-0.20220725093518-7a5126e0f2e3 h1:xzsgiXav4lRJjLfs05B90m2cgeFHjLyhGox8vXBZG9A= +github.com/ElrondNetwork/elrond-go-crypto v1.1.1-0.20220725093518-7a5126e0f2e3/go.mod h1:uunsvweBrrhVojL8uiQSaTPsl3YIQ9iBqtYGM6xs4s0= github.com/ElrondNetwork/elrond-go-logger v1.0.4/go.mod h1:e5D+c97lKUfFdAzFX7rrI2Igl/z4Y0RkKYKWyzprTGk= github.com/ElrondNetwork/elrond-go-logger v1.0.5/go.mod h1:cBfgx0ST/CJx8jrxJSC5aiSrvkGzcnF7sK06RD8mFxQ= github.com/ElrondNetwork/elrond-go-logger v1.0.7 h1:Ldl1rVS0RGKc1IsW8jIaGCb6Zwei04gsMvyjL05X6mE= diff --git a/integrationTests/consensus/testInitializer.go b/integrationTests/consensus/testInitializer.go index 24794094647..638ce53ffda 100644 --- a/integrationTests/consensus/testInitializer.go +++ b/integrationTests/consensus/testInitializer.go @@ -252,7 +252,6 @@ func createConsensusOnlyNode( shardCoordinator sharding.Coordinator, nodesCoordinator nodesCoordinator.NodesCoordinator, shardId uint32, - selfId uint32, consensusSize uint32, roundTime uint64, privKey crypto.PrivateKey, @@ -378,8 +377,7 @@ func createConsensusOnlyNode( inPubKeys[shardId] = append(inPubKeys[shardId], string(sPubKey)) } - testMultiSig := cryptoMocks.NewMultiSigner(consensusSize) - _ = testMultiSig.Reset(inPubKeys[shardId], uint16(selfId)) + testMultiSig := cryptoMocks.NewMultiSigner() peerSigCache, _ := storageUnit.NewCache(storageUnit.CacheConfig{Type: storageUnit.LRUCache, Capacity: 1000}) peerSigHandler, _ := peerSignatureHandler.NewPeerSignatureHandler(peerSigCache, singleBlsSigner, testKeyGen) @@ -414,7 +412,7 @@ func createConsensusOnlyNode( cryptoComponents.PubKey = privKey.GeneratePublic() cryptoComponents.BlockSig = singleBlsSigner cryptoComponents.TxSig = singlesigner - cryptoComponents.MultiSig = testMultiSig + cryptoComponents.MultiSigContainer = cryptoMocks.NewMultiSignerContainerMock(testMultiSig) cryptoComponents.BlKeyGen = testKeyGen cryptoComponents.PeerSignHandler = peerSigHandler @@ -535,7 +533,6 @@ func createNodes( shardCoordinator, nodesCoord, testNodeObject.shardId, - uint32(i), uint32(consensusSize), roundTime, kp.sk, diff --git a/integrationTests/mock/cryptoComponentsStub.go b/integrationTests/mock/cryptoComponentsStub.go index 5979f703b9e..f855b8e9e50 100644 --- a/integrationTests/mock/cryptoComponentsStub.go +++ b/integrationTests/mock/cryptoComponentsStub.go @@ -1,27 +1,29 @@ package mock import ( + "errors" "sync" "github.com/ElrondNetwork/elrond-go-crypto" + cryptoCommon "github.com/ElrondNetwork/elrond-go/common/crypto" "github.com/ElrondNetwork/elrond-go/vm" ) // CryptoComponentsStub - type CryptoComponentsStub struct { - PubKey crypto.PublicKey - PrivKey crypto.PrivateKey - PubKeyString string - PrivKeyBytes []byte - PubKeyBytes []byte - BlockSig crypto.SingleSigner - TxSig crypto.SingleSigner - MultiSig crypto.MultiSigner - PeerSignHandler crypto.PeerSignatureHandler - BlKeyGen crypto.KeyGenerator - TxKeyGen crypto.KeyGenerator - MsgSigVerifier vm.MessageSignVerifier - mutMultiSig sync.RWMutex + PubKey crypto.PublicKey + PrivKey crypto.PrivateKey + PubKeyString string + PrivKeyBytes []byte + PubKeyBytes []byte + BlockSig crypto.SingleSigner + TxSig crypto.SingleSigner + MultiSigContainer cryptoCommon.MultiSignerContainer + PeerSignHandler crypto.PeerSignatureHandler + BlKeyGen crypto.KeyGenerator + TxKeyGen crypto.KeyGenerator + MsgSigVerifier vm.MessageSignVerifier + mutMultiSig sync.RWMutex } // Create - @@ -74,31 +76,43 @@ func (ccs *CryptoComponentsStub) TxSingleSigner() crypto.SingleSigner { return ccs.TxSig } -// MultiSigner - -func (ccs *CryptoComponentsStub) MultiSigner() crypto.MultiSigner { +// PeerSignatureHandler - +func (ccs *CryptoComponentsStub) PeerSignatureHandler() crypto.PeerSignatureHandler { ccs.mutMultiSig.RLock() defer ccs.mutMultiSig.RUnlock() - return ccs.MultiSig + return ccs.PeerSignHandler } -// PeerSignatureHandler - -func (ccs *CryptoComponentsStub) PeerSignatureHandler() crypto.PeerSignatureHandler { +// MultiSignerContainer - +func (ccs *CryptoComponentsStub) MultiSignerContainer() cryptoCommon.MultiSignerContainer { ccs.mutMultiSig.RLock() defer ccs.mutMultiSig.RUnlock() - return ccs.PeerSignHandler + return ccs.MultiSigContainer } -// SetMultiSigner - -func (ccs *CryptoComponentsStub) SetMultiSigner(ms crypto.MultiSigner) error { +// SetMultiSignerContainer - +func (ccs *CryptoComponentsStub) SetMultiSignerContainer(ms cryptoCommon.MultiSignerContainer) error { ccs.mutMultiSig.Lock() - ccs.MultiSig = ms + ccs.MultiSigContainer = ms ccs.mutMultiSig.Unlock() return nil } +// GetMultiSigner - +func (ccs *CryptoComponentsStub) GetMultiSigner(epoch uint32) (crypto.MultiSigner, error) { + ccs.mutMultiSig.RLock() + defer ccs.mutMultiSig.RUnlock() + + if ccs.MultiSigContainer == nil { + return nil, errors.New("nil multi sig container") + } + + return ccs.MultiSigContainer.GetMultiSigner(epoch) +} + // BlockSignKeyGen - func (ccs *CryptoComponentsStub) BlockSignKeyGen() crypto.KeyGenerator { return ccs.BlKeyGen @@ -117,19 +131,19 @@ func (ccs *CryptoComponentsStub) MessageSignVerifier() vm.MessageSignVerifier { // Clone - func (ccs *CryptoComponentsStub) Clone() interface{} { return &CryptoComponentsStub{ - PubKey: ccs.PubKey, - PrivKey: ccs.PrivKey, - PubKeyString: ccs.PubKeyString, - PrivKeyBytes: ccs.PrivKeyBytes, - PubKeyBytes: ccs.PubKeyBytes, - BlockSig: ccs.BlockSig, - TxSig: ccs.TxSig, - MultiSig: ccs.MultiSig, - PeerSignHandler: ccs.PeerSignHandler, - BlKeyGen: ccs.BlKeyGen, - TxKeyGen: ccs.TxKeyGen, - MsgSigVerifier: ccs.MsgSigVerifier, - mutMultiSig: sync.RWMutex{}, + PubKey: ccs.PubKey, + PrivKey: ccs.PrivKey, + PubKeyString: ccs.PubKeyString, + PrivKeyBytes: ccs.PrivKeyBytes, + PubKeyBytes: ccs.PubKeyBytes, + BlockSig: ccs.BlockSig, + TxSig: ccs.TxSig, + MultiSigContainer: ccs.MultiSigContainer, + PeerSignHandler: ccs.PeerSignHandler, + BlKeyGen: ccs.BlKeyGen, + TxKeyGen: ccs.TxKeyGen, + MsgSigVerifier: ccs.MsgSigVerifier, + mutMultiSig: sync.RWMutex{}, } } diff --git a/integrationTests/multiShard/hardFork/hardFork_test.go b/integrationTests/multiShard/hardFork/hardFork_test.go index 315a4d32c1b..66c6eaa82bc 100644 --- a/integrationTests/multiShard/hardFork/hardFork_test.go +++ b/integrationTests/multiShard/hardFork/hardFork_test.go @@ -22,6 +22,7 @@ import ( "github.com/ElrondNetwork/elrond-go/integrationTests/vm/arwen" vmFactory "github.com/ElrondNetwork/elrond-go/process/factory" "github.com/ElrondNetwork/elrond-go/state" + "github.com/ElrondNetwork/elrond-go/testscommon/cryptoMocks" "github.com/ElrondNetwork/elrond-go/testscommon/genesisMocks" "github.com/ElrondNetwork/elrond-go/update/factory" "github.com/ElrondNetwork/elrond-go/vm/systemSmartContracts/defaults" @@ -564,7 +565,7 @@ func createHardForkExporter( cryptoComponents := integrationTests.GetDefaultCryptoComponents() cryptoComponents.BlockSig = node.OwnAccount.BlockSingleSigner cryptoComponents.TxSig = node.OwnAccount.SingleSigner - cryptoComponents.MultiSig = node.MultiSigner + cryptoComponents.MultiSigContainer = cryptoMocks.NewMultiSignerContainerMock(node.MultiSigner) cryptoComponents.BlKeyGen = node.OwnAccount.KeygenBlockSign cryptoComponents.TxKeyGen = node.OwnAccount.KeygenTxSign diff --git a/integrationTests/multisig/blsMultisig_test.go b/integrationTests/multisig/blsMultisig_test.go index ed7a001ddb8..31cef69fa84 100644 --- a/integrationTests/multisig/blsMultisig_test.go +++ b/integrationTests/multisig/blsMultisig_test.go @@ -1,8 +1,6 @@ package multisig import ( - "bytes" - "errors" "fmt" "testing" @@ -16,123 +14,37 @@ import ( "github.com/stretchr/testify/assert" ) -func createMultiSignersBls( - numOfSigners uint16, +func createKeysAndMultiSignerBls( grSize uint16, hasher hashing.Hasher, suite crypto.Suite, -) ([]string, []crypto.MultiSigner) { +) ([][]byte, [][]byte, crypto.MultiSigner) { kg := signing.NewKeyGenerator(suite) - - var pubKeyBytes []byte - - privKeys := make([]crypto.PrivateKey, grSize) - pubKeys := make([]crypto.PublicKey, grSize) - pubKeysStr := make([]string, grSize) + privKeys := make([][]byte, grSize) + pubKeys := make([][]byte, grSize) for i := uint16(0); i < grSize; i++ { sk, pk := kg.GeneratePair() - privKeys[i] = sk - pubKeys[i] = pk - - pubKeyBytes, _ = pk.ToByteArray() - pubKeysStr[i] = string(pubKeyBytes) + privKeys[i], _ = sk.ToByteArray() + pubKeys[i], _ = pk.ToByteArray() } - - multiSigners := make([]crypto.MultiSigner, numOfSigners) llSigner := &llsig.BlsMultiSigner{Hasher: hasher} - for i := uint16(0); i < numOfSigners; i++ { - multiSigners[i], _ = multisig.NewBLSMultisig(llSigner, pubKeysStr, privKeys[i], kg, i) - } + multiSigner, _ := multisig.NewBLSMultisig(llSigner, kg) - return pubKeysStr, multiSigners + return privKeys, pubKeys, multiSigner } -func createSignaturesShares(numOfSigners uint16, multiSigners []crypto.MultiSigner, message []byte) [][]byte { - sigShares := make([][]byte, numOfSigners) - for i := uint16(0); i < numOfSigners; i++ { - sigShares[i], _ = multiSigners[i].CreateSignatureShare(message, []byte("")) +func createSignaturesShares(privKeys [][]byte, multiSigner crypto.MultiSigner, message []byte) [][]byte { + sigShares := make([][]byte, len(privKeys)) + for i := uint16(0); i < uint16(len(privKeys)); i++ { + sigShares[i], _ = multiSigner.CreateSignatureShare(privKeys[i], message) } return sigShares } -func setSignatureSharesAllSignersBls(multiSigners []crypto.MultiSigner, sigs [][]byte) error { - grSize := uint16(len(multiSigners)) - var err error - - for i := uint16(0); i < grSize; i++ { - for j := uint16(0); j < grSize; j++ { - err = multiSigners[j].StoreSignatureShare(i, sigs[i]) - if err != nil { - return err - } - } - } - - return nil -} - -func verifySigAllSignersBls( - multiSigners []crypto.MultiSigner, - message []byte, - signature []byte, - pubKeys []string, - bitmap []byte, - grSize uint16, -) error { - - var err error - var muSig crypto.MultiSigner - - for i := uint16(0); i < grSize; i++ { - muSig, err = multiSigners[i].Create(pubKeys, i) - if err != nil { - return err - } - - multiSigners[i] = muSig - err = multiSigners[i].SetAggregatedSig(signature) - if err != nil { - return err - } - - err = multiSigners[i].Verify(message, bitmap) - if err != nil { - return err - } - } - - return nil -} - -func aggregateSignatureSharesAllSignersBls(multiSigners []crypto.MultiSigner, bitmap []byte, grSize uint16) ( - signature []byte, - err error, -) { - aggSig, err := multiSigners[0].AggregateSigs(bitmap) - - if err != nil { - return nil, err - } - - for i := uint16(1); i < grSize; i++ { - aggSig2, err1 := multiSigners[i].AggregateSigs(bitmap) - - if err1 != nil { - return nil, err1 - } - - if !bytes.Equal(aggSig, aggSig2) { - return nil, errors.New("aggregated signatures not equal") - } - } - - return aggSig, nil -} - func TestMultiSig_Bls(t *testing.T) { if testing.Short() { t.Skip("this is not a short test") @@ -140,37 +52,24 @@ func TestMultiSig_Bls(t *testing.T) { t.Parallel() - consensusGroupSize := uint16(6) - numOfSigners := uint16(6) + numSigners := uint16(6) message := "message" - - bitmapSize := consensusGroupSize/8 + 1 - // set bitmap to select all members - bitmap := make([]byte, bitmapSize) - byteMask := 0xFF - for i := uint16(0); i < bitmapSize; i++ { - bitmap[i] = byte((((1 << consensusGroupSize) - 1) >> i) & byteMask) - } - hashSize := 16 hasher, _ := blake2b.NewBlake2bWithSize(hashSize) suite := mcl.NewSuiteBLS12() - pubKeysStr, multiSigners := createMultiSignersBls(numOfSigners, consensusGroupSize, hasher, suite) + privKeys, pubKeys, multiSigner := createKeysAndMultiSignerBls(numSigners, hasher, suite) numOfTimesToRepeatTests := 100 for currentIdx := 0; currentIdx < numOfTimesToRepeatTests; currentIdx++ { message = fmt.Sprintf("%s%d", message, currentIdx) - signatures := createSignaturesShares(numOfSigners, multiSigners, []byte(message)) - - err := setSignatureSharesAllSignersBls(multiSigners, signatures) - assert.Nil(t, err) + signatures := createSignaturesShares(privKeys, multiSigner, []byte(message)) - aggSig, err := aggregateSignatureSharesAllSignersBls(multiSigners, bitmap, consensusGroupSize) + aggSig, err := multiSigner.AggregateSigs(pubKeys, signatures) assert.Nil(t, err) assert.NotNil(t, aggSig) - err = verifySigAllSignersBls(multiSigners, []byte(message), aggSig, pubKeysStr, bitmap, consensusGroupSize) + err = multiSigner.VerifyAggregatedSig(pubKeys, []byte(message), aggSig) assert.Nil(t, err) } } diff --git a/integrationTests/testProcessorNode.go b/integrationTests/testProcessorNode.go index 2577f90e020..81b0592791b 100644 --- a/integrationTests/testProcessorNode.go +++ b/integrationTests/testProcessorNode.go @@ -141,7 +141,7 @@ var TestAddressPubkeyConverter, _ = pubkeyConverter.NewBech32PubkeyConverter(32, var TestValidatorPubkeyConverter, _ = pubkeyConverter.NewHexPubkeyConverter(96) // TestMultiSig represents a mock multisig -var TestMultiSig = cryptoMocks.NewMultiSigner(1) +var TestMultiSig = cryptoMocks.NewMultiSigner() // TestKeyGenForAccounts represents a mock key generator for balances var TestKeyGenForAccounts = signing.NewKeyGenerator(ed25519.NewEd25519()) @@ -1223,7 +1223,7 @@ func (tpn *TestProcessorNode) initInterceptors(heartbeatPk string) { cryptoComponents.PubKey = nil cryptoComponents.BlockSig = tpn.OwnAccount.BlockSingleSigner cryptoComponents.TxSig = tpn.OwnAccount.SingleSigner - cryptoComponents.MultiSig = TestMultiSig + cryptoComponents.MultiSigContainer = cryptoMocks.NewMultiSignerContainerMock(TestMultiSig) cryptoComponents.BlKeyGen = tpn.OwnAccount.KeygenBlockSign cryptoComponents.TxKeyGen = tpn.OwnAccount.KeygenTxSign @@ -2355,7 +2355,7 @@ func (tpn *TestProcessorNode) initNode() { cryptoComponents.PubKey = tpn.NodeKeys.Pk cryptoComponents.TxSig = tpn.OwnAccount.SingleSigner cryptoComponents.BlockSig = tpn.OwnAccount.SingleSigner - cryptoComponents.MultiSig = tpn.MultiSigner + cryptoComponents.MultiSigContainer = cryptoMocks.NewMultiSignerContainerMock(tpn.MultiSigner) cryptoComponents.BlKeyGen = tpn.OwnAccount.KeygenTxSign cryptoComponents.TxKeyGen = TestKeyGenForAccounts @@ -2530,8 +2530,7 @@ func (tpn *TestProcessorNode) ProposeBlock(round uint64, nonce uint64) (data.Bod log.Warn("blockHeader.SetPrevRandSeed", "error", err.Error()) return nil, nil, nil } - - sig, _ := TestMultiSig.AggregateSigs(nil) + sig := []byte("aggregated signature") err = blockHeader.SetSignature(sig) if err != nil { log.Warn("blockHeader.SetSignature", "error", err.Error()) @@ -2897,7 +2896,7 @@ func (tpn *TestProcessorNode) createHeartbeatWithHardforkTrigger() { cryptoComponents.PubKey = tpn.NodeKeys.Pk cryptoComponents.TxSig = tpn.OwnAccount.SingleSigner cryptoComponents.BlockSig = tpn.OwnAccount.SingleSigner - cryptoComponents.MultiSig = tpn.MultiSigner + cryptoComponents.MultiSigContainer = cryptoMocks.NewMultiSignerContainerMock(tpn.MultiSigner) cryptoComponents.BlKeyGen = tpn.OwnAccount.KeygenTxSign cryptoComponents.TxKeyGen = TestKeyGenForAccounts cryptoComponents.PeerSignHandler = psh @@ -3130,18 +3129,18 @@ func GetDefaultDataComponents() *mock.DataComponentsStub { // GetDefaultCryptoComponents - func GetDefaultCryptoComponents() *mock.CryptoComponentsStub { return &mock.CryptoComponentsStub{ - PubKey: &mock.PublicKeyMock{}, - PrivKey: &mock.PrivateKeyMock{}, - PubKeyString: "pubKey", - PrivKeyBytes: []byte("privKey"), - PubKeyBytes: []byte("pubKey"), - BlockSig: &mock.SignerMock{}, - TxSig: &mock.SignerMock{}, - MultiSig: TestMultiSig, - PeerSignHandler: &mock.PeerSignatureHandler{}, - BlKeyGen: &mock.KeyGenMock{}, - TxKeyGen: &mock.KeyGenMock{}, - MsgSigVerifier: &testscommon.MessageSignVerifierMock{}, + PubKey: &mock.PublicKeyMock{}, + PrivKey: &mock.PrivateKeyMock{}, + PubKeyString: "pubKey", + PrivKeyBytes: []byte("privKey"), + PubKeyBytes: []byte("pubKey"), + BlockSig: &mock.SignerMock{}, + TxSig: &mock.SignerMock{}, + MultiSigContainer: cryptoMocks.NewMultiSignerContainerMock(TestMultiSig), + PeerSignHandler: &mock.PeerSignatureHandler{}, + BlKeyGen: &mock.KeyGenMock{}, + TxKeyGen: &mock.KeyGenMock{}, + MsgSigVerifier: &testscommon.MessageSignVerifierMock{}, } } diff --git a/integrationTests/testProcessorNodeWithCoordinator.go b/integrationTests/testProcessorNodeWithCoordinator.go index 3dc8c5b3e6d..199f85ac10a 100644 --- a/integrationTests/testProcessorNodeWithCoordinator.go +++ b/integrationTests/testProcessorNodeWithCoordinator.go @@ -34,20 +34,6 @@ type nodeKeys struct { BlockSignPkBytes []byte } -func pubKeysMapFromKeysMap(ncp map[uint32][]*nodeKeys) map[uint32][]string { - keysMap := make(map[uint32][]string) - - for shardId, keys := range ncp { - shardKeys := make([]string, len(keys)) - for i, nk := range keys { - shardKeys[i] = string(nk.BlockSignPkBytes) - } - keysMap[shardId] = shardKeys - } - - return keysMap -} - // CreateProcessorNodesWithNodesCoordinator creates a map of nodes with a valid nodes coordinator implementation // keeping the consistency of generated keys func CreateProcessorNodesWithNodesCoordinator( @@ -96,7 +82,7 @@ func CreateProcessorNodesWithNodesCoordinator( IsFullArchive: false, } - nodesCoordinator, err := nodesCoordinator.NewIndexHashedNodesCoordinator(argumentsNodesCoordinator) + nc, err := nodesCoordinator.NewIndexHashedNodesCoordinator(argumentsNodesCoordinator) if err != nil { fmt.Println("error creating node coordinator") } @@ -104,7 +90,7 @@ func CreateProcessorNodesWithNodesCoordinator( tpn := newTestProcessorNodeWithCustomNodesCoordinator( numShards, shardId, - nodesCoordinator, + nc, i, ncp, nodesSetup, @@ -230,15 +216,11 @@ func newTestProcessorNodeWithCustomNodesCoordinator( blsHasher, _ := blake2b.NewBlake2bWithSize(hashing.BlsHashSize) llsig := &multisig2.BlsMultiSigner{Hasher: blsHasher} - pubKeysMap := pubKeysMapFromKeysMap(ncp) kp := ncp[nodeShardId][keyIndex] var err error tpn.MultiSigner, err = multisig.NewBLSMultisig( llsig, - pubKeysMap[nodeShardId], - tpn.NodeKeys.Sk, kp.BlockSignKeyGen, - uint16(keyIndex), ) if err != nil { fmt.Printf("error generating multisigner: %s\n", err) diff --git a/integrationTests/testProcessorNodeWithMultisigner.go b/integrationTests/testProcessorNodeWithMultisigner.go index cd91776e0c7..b21552ab139 100644 --- a/integrationTests/testProcessorNodeWithMultisigner.go +++ b/integrationTests/testProcessorNodeWithMultisigner.go @@ -33,6 +33,7 @@ import ( "github.com/ElrondNetwork/elrond-go/storage/lrucache" "github.com/ElrondNetwork/elrond-go/storage/storageUnit" "github.com/ElrondNetwork/elrond-go/testscommon" + "github.com/ElrondNetwork/elrond-go/testscommon/cryptoMocks" "github.com/ElrondNetwork/elrond-go/testscommon/dblookupext" "github.com/ElrondNetwork/elrond-go/testscommon/nodeTypeProviderMock" "github.com/ElrondNetwork/elrond-go/testscommon/shardingMocks" @@ -87,14 +88,9 @@ func NewTestProcessorNodeWithCustomNodesCoordinator( blsHasher, _ := blake2b.NewBlake2bWithSize(hashing.BlsHashSize) llsig := &mclmultisig.BlsMultiSigner{Hasher: blsHasher} - pubKeysMap := PubKeysMapFromKeysMap(cp.Keys) - tpn.MultiSigner, _ = multisig.NewBLSMultisig( llsig, - pubKeysMap[nodeShardId], - tpn.NodeKeys.Sk, cp.KeyGen, - 0, ) if tpn.MultiSigner == nil { fmt.Println("Error generating multisigner") @@ -281,14 +277,9 @@ func CreateNodeWithBLSAndTxKeys( blsHasher, _ := blake2b.NewBlake2bWithSize(hashing.BlsHashSize) llsig := &mclmultisig.BlsMultiSigner{Hasher: blsHasher} - pubKeysMap := PubKeysMapFromKeysMap(cp.Keys) - tpn.MultiSigner, _ = multisig.NewBLSMultisig( llsig, - pubKeysMap[shardId], - tpn.NodeKeys.Sk, cp.KeyGen, - 0, ) if tpn.MultiSigner == nil { fmt.Println("Error generating multisigner") @@ -545,7 +536,7 @@ func CreateNodesWithNodesCoordinatorAndHeaderSigVerifier( Marshalizer: TestMarshalizer, Hasher: TestHasher, NodesCoordinator: nodesCoordinatorInstance, - MultiSigVerifier: TestMultiSig, + MultiSigContainer: cryptoMocks.NewMultiSignerContainerMock(TestMultiSig), SingleSigVerifier: signer, KeyGen: keyGen, FallbackHeaderValidator: &testscommon.FallBackHeaderValidatorStub{}, @@ -653,7 +644,7 @@ func CreateNodesWithNodesCoordinatorKeygenAndSingleSigner( Marshalizer: TestMarshalizer, Hasher: TestHasher, NodesCoordinator: nodesCoord, - MultiSigVerifier: TestMultiSig, + MultiSigContainer: cryptoMocks.NewMultiSignerContainerMock(TestMultiSig), SingleSigVerifier: singleSigner, KeyGen: keyGenForBlocks, FallbackHeaderValidator: &testscommon.FallBackHeaderValidatorStub{}, @@ -766,17 +757,17 @@ func DoConsensusSigningOnBlock( blockHeaderHash, _ := core.CalculateHash(TestMarshalizer, TestHasher, blockHeader) - var msig crypto.MultiSigner - msigProposer, _ := consensusNodes[0].MultiSigner.Create(pubKeys, 0) - _, _ = msigProposer.CreateSignatureShare(blockHeaderHash, bitmap) + pubKeysBytes := make([][]byte, len(consensusNodes)) + sigShares := make([][]byte, len(consensusNodes)) + msig := consensusNodes[0].MultiSigner - for i := 1; i < len(consensusNodes); i++ { - msig, _ = consensusNodes[i].MultiSigner.Create(pubKeys, uint16(i)) - sigShare, _ := msig.CreateSignatureShare(blockHeaderHash, bitmap) - _ = msigProposer.StoreSignatureShare(uint16(i), sigShare) + for i := 0; i < len(consensusNodes); i++ { + pubKeysBytes[i] = []byte(pubKeys[i]) + sk, _ := consensusNodes[i].NodeKeys.Sk.ToByteArray() + sigShares[i], _ = msig.CreateSignatureShare(sk, blockHeaderHash) } - sig, _ := msigProposer.AggregateSigs(bitmap) + sig, _ := msig.AggregateSigs(pubKeysBytes, sigShares) err = blockHeader.SetSignature(sig) if err != nil { log.Error("blockHeader.SetSignature", "error", err) diff --git a/node/mock/factory/cryptoComponentsStub.go b/node/mock/factory/cryptoComponentsStub.go index 1ed49ddc5b6..40e94e95775 100644 --- a/node/mock/factory/cryptoComponentsStub.go +++ b/node/mock/factory/cryptoComponentsStub.go @@ -1,27 +1,29 @@ package factory import ( + "errors" "sync" "github.com/ElrondNetwork/elrond-go-crypto" + cryptoCommon "github.com/ElrondNetwork/elrond-go/common/crypto" "github.com/ElrondNetwork/elrond-go/vm" ) // CryptoComponentsMock - type CryptoComponentsMock struct { - PubKey crypto.PublicKey - PrivKey crypto.PrivateKey - PubKeyString string - PrivKeyBytes []byte - PubKeyBytes []byte - BlockSig crypto.SingleSigner - TxSig crypto.SingleSigner - MultiSig crypto.MultiSigner - PeerSignHandler crypto.PeerSignatureHandler - BlKeyGen crypto.KeyGenerator - TxKeyGen crypto.KeyGenerator - MsgSigVerifier vm.MessageSignVerifier - mutMultiSig sync.RWMutex + PubKey crypto.PublicKey + PrivKey crypto.PrivateKey + PubKeyString string + PrivKeyBytes []byte + PubKeyBytes []byte + BlockSig crypto.SingleSigner + TxSig crypto.SingleSigner + MultiSigContainer cryptoCommon.MultiSignerContainer + PeerSignHandler crypto.PeerSignatureHandler + BlKeyGen crypto.KeyGenerator + TxKeyGen crypto.KeyGenerator + MsgSigVerifier vm.MessageSignVerifier + mutMultiSig sync.RWMutex } // Create - @@ -74,29 +76,41 @@ func (ccm *CryptoComponentsMock) TxSingleSigner() crypto.SingleSigner { return ccm.TxSig } -// MultiSigner - -func (ccm *CryptoComponentsMock) MultiSigner() crypto.MultiSigner { +// MultiSignerContainer - +func (ccm *CryptoComponentsMock) MultiSignerContainer() cryptoCommon.MultiSignerContainer { ccm.mutMultiSig.RLock() defer ccm.mutMultiSig.RUnlock() - return ccm.MultiSig + return ccm.MultiSigContainer } -// PeerSignatureHandler - -func (ccm *CryptoComponentsMock) PeerSignatureHandler() crypto.PeerSignatureHandler { +// SetMultiSignerContainer - +func (ccm *CryptoComponentsMock) SetMultiSignerContainer(ms cryptoCommon.MultiSignerContainer) error { + ccm.mutMultiSig.Lock() + ccm.MultiSigContainer = ms + ccm.mutMultiSig.Unlock() + + return nil +} + +// GetMultiSigner - +func (ccm *CryptoComponentsMock) GetMultiSigner(epoch uint32) (crypto.MultiSigner, error) { ccm.mutMultiSig.RLock() defer ccm.mutMultiSig.RUnlock() - return ccm.PeerSignHandler + if ccm.MultiSigContainer == nil { + return nil, errors.New("nil multi sig container") + } + + return ccm.MultiSigContainer.GetMultiSigner(epoch) } -// SetMultiSigner - -func (ccm *CryptoComponentsMock) SetMultiSigner(ms crypto.MultiSigner) error { - ccm.mutMultiSig.Lock() - ccm.MultiSig = ms - ccm.mutMultiSig.Unlock() +// PeerSignatureHandler - +func (ccm *CryptoComponentsMock) PeerSignatureHandler() crypto.PeerSignatureHandler { + ccm.mutMultiSig.RLock() + defer ccm.mutMultiSig.RUnlock() - return nil + return ccm.PeerSignHandler } // BlockSignKeyGen - @@ -117,19 +131,19 @@ func (ccm *CryptoComponentsMock) MessageSignVerifier() vm.MessageSignVerifier { // Clone - func (ccm *CryptoComponentsMock) Clone() interface{} { return &CryptoComponentsMock{ - PubKey: ccm.PubKey, - PrivKey: ccm.PrivKey, - PubKeyString: ccm.PubKeyString, - PrivKeyBytes: ccm.PrivKeyBytes, - PubKeyBytes: ccm.PubKeyBytes, - BlockSig: ccm.BlockSig, - TxSig: ccm.TxSig, - MultiSig: ccm.MultiSig, - PeerSignHandler: ccm.PeerSignHandler, - BlKeyGen: ccm.BlKeyGen, - TxKeyGen: ccm.TxKeyGen, - MsgSigVerifier: ccm.MsgSigVerifier, - mutMultiSig: sync.RWMutex{}, + PubKey: ccm.PubKey, + PrivKey: ccm.PrivKey, + PubKeyString: ccm.PubKeyString, + PrivKeyBytes: ccm.PrivKeyBytes, + PubKeyBytes: ccm.PubKeyBytes, + BlockSig: ccm.BlockSig, + TxSig: ccm.TxSig, + MultiSigContainer: ccm.MultiSigContainer, + PeerSignHandler: ccm.PeerSignHandler, + BlKeyGen: ccm.BlKeyGen, + TxKeyGen: ccm.TxKeyGen, + MsgSigVerifier: ccm.MsgSigVerifier, + mutMultiSig: sync.RWMutex{}, } } diff --git a/node/nodeRunner.go b/node/nodeRunner.go index dc34c2a7146..1e0d3f82801 100644 --- a/node/nodeRunner.go +++ b/node/nodeRunner.go @@ -1313,6 +1313,7 @@ func (nr *nodeRunner) CreateManagedCryptoComponents( KeyLoader: &core.KeyLoader{}, ImportModeNoSigCheck: configs.ImportDbConfig.ImportDbNoSigCheckFlag, IsInImportMode: configs.ImportDbConfig.IsImportDBMode, + EnableEpochs: configs.EpochConfig.EnableEpochs, } cryptoComponentsFactory, err := cryptoComp.NewCryptoComponentsFactory(cryptoComponentsHandlerArgs) diff --git a/node/nodeTesting_test.go b/node/nodeTesting_test.go index 3554b5557bd..6982b386990 100644 --- a/node/nodeTesting_test.go +++ b/node/nodeTesting_test.go @@ -388,18 +388,18 @@ func TestGenerateAndSendBulkTransactions_ShouldWork(t *testing.T) { func getDefaultCryptoComponents() *factoryMock.CryptoComponentsMock { return &factoryMock.CryptoComponentsMock{ - PubKey: &mock.PublicKeyMock{}, - PrivKey: &mock.PrivateKeyStub{}, - PubKeyString: "pubKey", - PrivKeyBytes: []byte("privKey"), - PubKeyBytes: []byte("pubKey"), - BlockSig: &mock.SingleSignerMock{}, - TxSig: &mock.SingleSignerMock{}, - MultiSig: cryptoMocks.NewMultiSigner(1), - PeerSignHandler: &mock.PeerSignatureHandler{}, - BlKeyGen: &mock.KeyGenMock{}, - TxKeyGen: &mock.KeyGenMock{}, - MsgSigVerifier: &testscommon.MessageSignVerifierMock{}, + PubKey: &mock.PublicKeyMock{}, + PrivKey: &mock.PrivateKeyStub{}, + PubKeyString: "pubKey", + PrivKeyBytes: []byte("privKey"), + PubKeyBytes: []byte("pubKey"), + BlockSig: &mock.SingleSignerMock{}, + TxSig: &mock.SingleSignerMock{}, + MultiSigContainer: cryptoMocks.NewMultiSignerContainerMock(cryptoMocks.NewMultiSigner()), + PeerSignHandler: &mock.PeerSignatureHandler{}, + BlKeyGen: &mock.KeyGenMock{}, + TxKeyGen: &mock.KeyGenMock{}, + MsgSigVerifier: &testscommon.MessageSignVerifierMock{}, } } diff --git a/p2p/libp2p/p2pSigner.go b/p2p/libp2p/p2pSigner.go index 3be693c95fb..e2c600ea4ec 100644 --- a/p2p/libp2p/p2pSigner.go +++ b/p2p/libp2p/p2pSigner.go @@ -35,7 +35,7 @@ func (signer *p2pSigner) Verify(payload []byte, pid core.PeerID, signature []byt return err } if !sigOk { - return crypto.ErrInvalidSignature + return crypto.ErrSigNotValid } return nil diff --git a/p2p/libp2p/p2pSigner_test.go b/p2p/libp2p/p2pSigner_test.go index e373c00a082..3e4ad3ad5b0 100644 --- a/p2p/libp2p/p2pSigner_test.go +++ b/p2p/libp2p/p2pSigner_test.go @@ -75,7 +75,7 @@ func TestP2pSigner_Verify(t *testing.T) { sig[len(sig)-1] = sig[0] ^ sig[1] ^ sig[2] err = signer.Verify(payload, core.PeerID(libp2pPid), sig) - assert.Equal(t, crypto.ErrInvalidSignature, err) + assert.Equal(t, crypto.ErrSigNotValid, err) }) t.Run("sign and verify should work", func(t *testing.T) { t.Parallel() diff --git a/process/errors.go b/process/errors.go index fb8b91e27f9..e996919da1c 100644 --- a/process/errors.go +++ b/process/errors.go @@ -1133,3 +1133,6 @@ var ErrNilProcessedMiniBlocksTracker = errors.New("nil processed mini blocks tra // ErrNilESDTGlobalSettingsHandler signals that nil global settings handler was provided var ErrNilESDTGlobalSettingsHandler = errors.New("nil esdt global settings handler") + +// ErrNilMultiSignerContainer signals that the given multisigner container is nil +var ErrNilMultiSignerContainer = errors.New("nil multiSigner container") diff --git a/process/factory/interceptorscontainer/baseInterceptorsContainerFactory.go b/process/factory/interceptorscontainer/baseInterceptorsContainerFactory.go index 8a3abe780c0..edfd14372e3 100644 --- a/process/factory/interceptorscontainer/baseInterceptorsContainerFactory.go +++ b/process/factory/interceptorscontainer/baseInterceptorsContainerFactory.go @@ -100,7 +100,11 @@ func checkBaseParams( if coreComponents.MinTransactionVersion() == 0 { return process.ErrInvalidTransactionVersion } - if check.IfNil(cryptoComponents.MultiSigner()) { + multiSigner, err := cryptoComponents.GetMultiSigner(0) + if err != nil { + return err + } + if check.IfNil(multiSigner) { return process.ErrNilMultiSigVerifier } if check.IfNil(cryptoComponents.BlockSignKeyGen()) { diff --git a/process/factory/interceptorscontainer/metaInterceptorsContainerFactory_test.go b/process/factory/interceptorscontainer/metaInterceptorsContainerFactory_test.go index dbaeaee69b2..81e0d785d79 100644 --- a/process/factory/interceptorscontainer/metaInterceptorsContainerFactory_test.go +++ b/process/factory/interceptorscontainer/metaInterceptorsContainerFactory_test.go @@ -13,6 +13,7 @@ import ( "github.com/ElrondNetwork/elrond-go/process/mock" "github.com/ElrondNetwork/elrond-go/storage" "github.com/ElrondNetwork/elrond-go/testscommon" + "github.com/ElrondNetwork/elrond-go/testscommon/cryptoMocks" dataRetrieverMock "github.com/ElrondNetwork/elrond-go/testscommon/dataRetriever" "github.com/ElrondNetwork/elrond-go/testscommon/p2pmocks" "github.com/ElrondNetwork/elrond-go/testscommon/shardingMocks" @@ -230,7 +231,7 @@ func TestNewMetaInterceptorsContainerFactory_NilMultiSignerShouldErr(t *testing. t.Parallel() coreComp, cryptoComp := createMockComponentHolders() - cryptoComp.MultiSig = nil + cryptoComp.MultiSigContainer = cryptoMocks.NewMultiSignerContainerMock(nil) args := getArgumentsMeta(coreComp, cryptoComp) icf, err := interceptorscontainer.NewMetaInterceptorsContainerFactory(args) diff --git a/process/factory/interceptorscontainer/shardInterceptorsContainerFactory_test.go b/process/factory/interceptorscontainer/shardInterceptorsContainerFactory_test.go index 826c6fbb2d9..01bcf64252f 100644 --- a/process/factory/interceptorscontainer/shardInterceptorsContainerFactory_test.go +++ b/process/factory/interceptorscontainer/shardInterceptorsContainerFactory_test.go @@ -269,7 +269,7 @@ func TestNewShardInterceptorsContainerFactory_NilMultiSignerShouldErr(t *testing t.Parallel() coreComp, cryptoComp := createMockComponentHolders() - cryptoComp.MultiSig = nil + cryptoComp.MultiSigContainer = cryptoMocks.NewMultiSignerContainerMock(nil) args := getArgumentsShard(coreComp, cryptoComp) icf, err := interceptorscontainer.NewShardInterceptorsContainerFactory(args) @@ -685,12 +685,13 @@ func createMockComponentHolders() (*mock.CoreComponentsMock, *mock.CryptoCompone TxVersionCheckField: versioning.NewTxVersionChecker(1), HardforkTriggerPubKeyField: providedHardforkPubKey, } + multiSigner := cryptoMocks.NewMultiSigner() cryptoComponents := &mock.CryptoComponentsMock{ - BlockSig: &mock.SignerMock{}, - TxSig: &mock.SignerMock{}, - MultiSig: cryptoMocks.NewMultiSigner(21), - BlKeyGen: &mock.SingleSignKeyGenMock{}, - TxKeyGen: &mock.SingleSignKeyGenMock{}, + BlockSig: &mock.SignerMock{}, + TxSig: &mock.SignerMock{}, + MultiSigContainer: cryptoMocks.NewMultiSignerContainerMock(multiSigner), + BlKeyGen: &mock.SingleSignKeyGenMock{}, + TxKeyGen: &mock.SingleSignKeyGenMock{}, } return coreComponents, cryptoComponents diff --git a/process/headerCheck/errors.go b/process/headerCheck/errors.go index 443cea6dc84..152e5c62dfa 100644 --- a/process/headerCheck/errors.go +++ b/process/headerCheck/errors.go @@ -17,3 +17,9 @@ var ErrInvalidChainID = errors.New("invalid chain ID") // ErrNilHeaderVersionHandler signals that the provided header version handler is nil var ErrNilHeaderVersionHandler = errors.New("nil header version handler") + +// ErrIndexOutOfBounds signals that the given index is outside of expected bounds +var ErrIndexOutOfBounds = errors.New("index is out of bounds") + +// ErrIndexNotSelected signals that the given index is not selected +var ErrIndexNotSelected = errors.New("index is not selected") diff --git a/process/headerCheck/headerSignatureVerify.go b/process/headerCheck/headerSignatureVerify.go index 6a6fd78d59a..e424ef68677 100644 --- a/process/headerCheck/headerSignatureVerify.go +++ b/process/headerCheck/headerSignatureVerify.go @@ -10,6 +10,7 @@ import ( "github.com/ElrondNetwork/elrond-go-core/marshal" crypto "github.com/ElrondNetwork/elrond-go-crypto" logger "github.com/ElrondNetwork/elrond-go-logger" + cryptoCommon "github.com/ElrondNetwork/elrond-go/common/crypto" "github.com/ElrondNetwork/elrond-go/process" "github.com/ElrondNetwork/elrond-go/sharding/nodesCoordinator" ) @@ -23,7 +24,7 @@ type ArgsHeaderSigVerifier struct { Marshalizer marshal.Marshalizer Hasher hashing.Hasher NodesCoordinator nodesCoordinator.NodesCoordinator - MultiSigVerifier crypto.MultiSigVerifier + MultiSigContainer cryptoCommon.MultiSignerContainer SingleSigVerifier crypto.SingleSigner KeyGen crypto.KeyGenerator FallbackHeaderValidator process.FallbackHeaderValidator @@ -34,7 +35,7 @@ type HeaderSigVerifier struct { marshalizer marshal.Marshalizer hasher hashing.Hasher nodesCoordinator nodesCoordinator.NodesCoordinator - multiSigVerifier crypto.MultiSigVerifier + multiSigContainer cryptoCommon.MultiSignerContainer singleSigVerifier crypto.SingleSigner keyGen crypto.KeyGenerator fallbackHeaderValidator process.FallbackHeaderValidator @@ -51,7 +52,7 @@ func NewHeaderSigVerifier(arguments *ArgsHeaderSigVerifier) (*HeaderSigVerifier, marshalizer: arguments.Marshalizer, hasher: arguments.Hasher, nodesCoordinator: arguments.NodesCoordinator, - multiSigVerifier: arguments.MultiSigVerifier, + multiSigContainer: arguments.MultiSigContainer, singleSigVerifier: arguments.SingleSigVerifier, keyGen: arguments.KeyGen, fallbackHeaderValidator: arguments.FallbackHeaderValidator, @@ -71,7 +72,14 @@ func checkArgsHeaderSigVerifier(arguments *ArgsHeaderSigVerifier) error { if check.IfNil(arguments.Marshalizer) { return process.ErrNilMarshalizer } - if check.IfNil(arguments.MultiSigVerifier) { + if check.IfNil(arguments.MultiSigContainer) { + return process.ErrNilMultiSignerContainer + } + multiSigner, err := arguments.MultiSigContainer.GetMultiSigner(0) + if err != nil { + return err + } + if check.IfNil(multiSigner) { return process.ErrNilMultiSigVerifier } if check.IfNil(arguments.NodesCoordinator) { @@ -87,50 +95,70 @@ func checkArgsHeaderSigVerifier(arguments *ArgsHeaderSigVerifier) error { return nil } -// VerifySignature will check if signature is correct -func (hsv *HeaderSigVerifier) VerifySignature(header data.HeaderHandler) error { +func isIndexInBitmap(index uint16, bitmap []byte) error { + indexOutOfBounds := index >= uint16(len(bitmap)*8) + if indexOutOfBounds { + return ErrIndexOutOfBounds + } + + indexNotInBitmap := bitmap[index/8]&(1< 0 { - epoch = epoch - 1 + // TODO: remove if start of epochForConsensus block needs to be validated by the new epochForConsensus nodes + epochForConsensus := header.GetEpoch() + if header.IsStartOfEpochBlock() && epochForConsensus > 0 { + epochForConsensus = epochForConsensus - 1 } consensusPubKeys, err := hsv.nodesCoordinator.GetConsensusValidatorsPublicKeys( randSeed, header.GetRound(), header.GetShardID(), - epoch, + epochForConsensus, ) if err != nil { - return err + return nil, err } err = hsv.verifyConsensusSize(consensusPubKeys, header) if err != nil { - return err + return nil, err } - verifier, err := hsv.multiSigVerifier.Create(consensusPubKeys, 0) - if err != nil { - return err + pubKeysSigners := make([][]byte, 0, len(consensusPubKeys)) + for i := range consensusPubKeys { + err = isIndexInBitmap(uint16(i), bitmap) + if err != nil { + continue + } + pubKeysSigners = append(pubKeysSigners, []byte(consensusPubKeys[i])) } - err = verifier.SetAggregatedSig(header.GetSignature()) + return pubKeysSigners, nil +} + +// VerifySignature will check if signature is correct +func (hsv *HeaderSigVerifier) VerifySignature(header data.HeaderHandler) error { + multiSigVerifier, err := hsv.multiSigContainer.GetMultiSigner(header.GetEpoch()) if err != nil { return err } - // get marshalled block header without signature and bitmap - // as this is the message that was signed headerCopy, err := hsv.copyHeaderWithoutSig(header) if err != nil { return err @@ -141,7 +169,12 @@ func (hsv *HeaderSigVerifier) VerifySignature(header data.HeaderHandler) error { return err } - return verifier.Verify(hash, bitmap) + pubKeysSigners, err := hsv.getConsensusSigners(header) + if err != nil { + return err + } + + return multiSigVerifier.VerifyAggregatedSig(pubKeysSigners, hash, header.GetSignature()) } func (hsv *HeaderSigVerifier) verifyConsensusSize(consensusPubKeys []string, header data.HeaderHandler) error { diff --git a/process/headerCheck/headerSignatureVerify_test.go b/process/headerCheck/headerSignatureVerify_test.go index 2f0401375cf..7d01fbe656c 100644 --- a/process/headerCheck/headerSignatureVerify_test.go +++ b/process/headerCheck/headerSignatureVerify_test.go @@ -25,7 +25,7 @@ func createHeaderSigVerifierArgs() *ArgsHeaderSigVerifier { Marshalizer: &mock.MarshalizerMock{}, Hasher: &hashingMocks.HasherMock{}, NodesCoordinator: &shardingMocks.NodesCoordinatorMock{}, - MultiSigVerifier: cryptoMocks.NewMultiSigner(21), + MultiSigContainer: cryptoMocks.NewMultiSignerContainerMock(cryptoMocks.NewMultiSigner()), SingleSigVerifier: &mock.SignerMock{}, KeyGen: &mock.SingleSignKeyGenMock{}, FallbackHeaderValidator: &testscommon.FallBackHeaderValidatorStub{}, @@ -78,7 +78,7 @@ func TestNewHeaderSigVerifier_NilMultiSigShouldErr(t *testing.T) { t.Parallel() args := createHeaderSigVerifierArgs() - args.MultiSigVerifier = nil + args.MultiSigContainer = cryptoMocks.NewMultiSignerContainerMock(nil) hdrSigVerifier, err := NewHeaderSigVerifier(args) require.Nil(t, hdrSigVerifier) @@ -148,13 +148,13 @@ func TestHeaderSigVerifier_VerifyRandSeedOk(t *testing.T) { } pkAddr := []byte("aaa00000000000000000000000000000") - nodesCoordinator := &shardingMocks.NodesCoordinatorMock{ + nc := &shardingMocks.NodesCoordinatorMock{ ComputeValidatorsGroupCalled: func(randomness []byte, round uint64, shardId uint32, epoch uint32) (validators []nodesCoordinator.Validator, err error) { v, _ := nodesCoordinator.NewValidator(pkAddr, 1, defaultChancesSelection) return []nodesCoordinator.Validator{v}, nil }, } - args.NodesCoordinator = nodesCoordinator + args.NodesCoordinator = nc hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.Header{} @@ -183,13 +183,13 @@ func TestHeaderSigVerifier_VerifyRandSeedShouldErrWhenVerificationFails(t *testi } pkAddr := []byte("aaa00000000000000000000000000000") - nodesCoordinator := &shardingMocks.NodesCoordinatorMock{ + nc := &shardingMocks.NodesCoordinatorMock{ ComputeValidatorsGroupCalled: func(randomness []byte, round uint64, shardId uint32, epoch uint32) (validators []nodesCoordinator.Validator, err error) { v, _ := nodesCoordinator.NewValidator(pkAddr, 1, defaultChancesSelection) return []nodesCoordinator.Validator{v}, nil }, } - args.NodesCoordinator = nodesCoordinator + args.NodesCoordinator = nc hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.Header{} @@ -229,13 +229,13 @@ func TestHeaderSigVerifier_VerifyRandSeedAndLeaderSignatureVerifyShouldErrWhenVa } pkAddr := []byte("aaa00000000000000000000000000000") - nodesCoordinator := &shardingMocks.NodesCoordinatorMock{ + nc := &shardingMocks.NodesCoordinatorMock{ ComputeValidatorsGroupCalled: func(randomness []byte, round uint64, shardId uint32, epoch uint32) (validators []nodesCoordinator.Validator, err error) { v, _ := nodesCoordinator.NewValidator(pkAddr, 1, defaultChancesSelection) return []nodesCoordinator.Validator{v}, nil }, } - args.NodesCoordinator = nodesCoordinator + args.NodesCoordinator = nc hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.Header{} @@ -268,13 +268,13 @@ func TestHeaderSigVerifier_VerifyRandSeedAndLeaderSignatureVerifyLeaderSigShould } pkAddr := []byte("aaa00000000000000000000000000000") - nodesCoordinator := &shardingMocks.NodesCoordinatorMock{ + nc := &shardingMocks.NodesCoordinatorMock{ ComputeValidatorsGroupCalled: func(randomness []byte, round uint64, shardId uint32, epoch uint32) (validators []nodesCoordinator.Validator, err error) { v, _ := nodesCoordinator.NewValidator(pkAddr, 1, defaultChancesSelection) return []nodesCoordinator.Validator{v}, nil }, } - args.NodesCoordinator = nodesCoordinator + args.NodesCoordinator = nc hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.Header{ LeaderSignature: leaderSig, @@ -304,13 +304,13 @@ func TestHeaderSigVerifier_VerifyRandSeedAndLeaderSignatureOk(t *testing.T) { } pkAddr := []byte("aaa00000000000000000000000000000") - nodesCoordinator := &shardingMocks.NodesCoordinatorMock{ + nc := &shardingMocks.NodesCoordinatorMock{ ComputeValidatorsGroupCalled: func(randomness []byte, round uint64, shardId uint32, epoch uint32) (validators []nodesCoordinator.Validator, err error) { v, _ := nodesCoordinator.NewValidator(pkAddr, 1, defaultChancesSelection) return []nodesCoordinator.Validator{v}, nil }, } - args.NodesCoordinator = nodesCoordinator + args.NodesCoordinator = nc hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.Header{} @@ -350,13 +350,13 @@ func TestHeaderSigVerifier_VerifyLeaderSignatureVerifyShouldErrWhenValidationFai } pkAddr := []byte("aaa00000000000000000000000000000") - nodesCoordinator := &shardingMocks.NodesCoordinatorMock{ + nc := &shardingMocks.NodesCoordinatorMock{ ComputeValidatorsGroupCalled: func(randomness []byte, round uint64, shardId uint32, epoch uint32) (validators []nodesCoordinator.Validator, err error) { v, _ := nodesCoordinator.NewValidator(pkAddr, 1, defaultChancesSelection) return []nodesCoordinator.Validator{v}, nil }, } - args.NodesCoordinator = nodesCoordinator + args.NodesCoordinator = nc hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.Header{} @@ -389,13 +389,13 @@ func TestHeaderSigVerifier_VerifyLeaderSignatureVerifyLeaderSigShouldErr(t *test } pkAddr := []byte("aaa00000000000000000000000000000") - nodesCoordinator := &shardingMocks.NodesCoordinatorMock{ + nc := &shardingMocks.NodesCoordinatorMock{ ComputeValidatorsGroupCalled: func(randomness []byte, round uint64, shardId uint32, epoch uint32) (validators []nodesCoordinator.Validator, err error) { v, _ := nodesCoordinator.NewValidator(pkAddr, 1, defaultChancesSelection) return []nodesCoordinator.Validator{v}, nil }, } - args.NodesCoordinator = nodesCoordinator + args.NodesCoordinator = nc hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.Header{ LeaderSignature: leaderSig, @@ -425,13 +425,13 @@ func TestHeaderSigVerifier_VerifyLeaderSignatureOk(t *testing.T) { } pkAddr := []byte("aaa00000000000000000000000000000") - nodesCoordinator := &shardingMocks.NodesCoordinatorMock{ + nc := &shardingMocks.NodesCoordinatorMock{ ComputeValidatorsGroupCalled: func(randomness []byte, round uint64, shardId uint32, epoch uint32) (validators []nodesCoordinator.Validator, err error) { v, _ := nodesCoordinator.NewValidator(pkAddr, 1, defaultChancesSelection) return []nodesCoordinator.Validator{v}, nil }, } - args.NodesCoordinator = nodesCoordinator + args.NodesCoordinator = nc hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.Header{} @@ -482,13 +482,13 @@ func TestHeaderSigVerifier_VerifySignatureWrongSizeBitmapShouldErr(t *testing.T) args := createHeaderSigVerifierArgs() pkAddr := []byte("aaa00000000000000000000000000000") - nodesCoordinator := &shardingMocks.NodesCoordinatorMock{ + nc := &shardingMocks.NodesCoordinatorMock{ ComputeValidatorsGroupCalled: func(randomness []byte, round uint64, shardId uint32, epoch uint32) (validators []nodesCoordinator.Validator, err error) { v, _ := nodesCoordinator.NewValidator(pkAddr, 1, defaultChancesSelection) return []nodesCoordinator.Validator{v}, nil }, } - args.NodesCoordinator = nodesCoordinator + args.NodesCoordinator = nc hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.Header{ @@ -504,13 +504,13 @@ func TestHeaderSigVerifier_VerifySignatureNotEnoughSigsShouldErr(t *testing.T) { args := createHeaderSigVerifierArgs() pkAddr := []byte("aaa00000000000000000000000000000") - nodesCoordinator := &shardingMocks.NodesCoordinatorMock{ + nc := &shardingMocks.NodesCoordinatorMock{ ComputeValidatorsGroupCalled: func(randomness []byte, round uint64, shardId uint32, epoch uint32) (validators []nodesCoordinator.Validator, err error) { v, _ := nodesCoordinator.NewValidator(pkAddr, 1, defaultChancesSelection) return []nodesCoordinator.Validator{v, v, v, v, v}, nil }, } - args.NodesCoordinator = nodesCoordinator + args.NodesCoordinator = nc hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.Header{ @@ -527,23 +527,19 @@ func TestHeaderSigVerifier_VerifySignatureOk(t *testing.T) { wasCalled := false args := createHeaderSigVerifierArgs() pkAddr := []byte("aaa00000000000000000000000000000") - nodesCoordinator := &shardingMocks.NodesCoordinatorMock{ + nc := &shardingMocks.NodesCoordinatorMock{ ComputeValidatorsGroupCalled: func(randomness []byte, round uint64, shardId uint32, epoch uint32) (validators []nodesCoordinator.Validator, err error) { v, _ := nodesCoordinator.NewValidator(pkAddr, 1, defaultChancesSelection) return []nodesCoordinator.Validator{v}, nil }, } - args.NodesCoordinator = nodesCoordinator + args.NodesCoordinator = nc - args.MultiSigVerifier = &cryptoMocks.MultisignerMock{ - CreateCalled: func(pubKeys []string, index uint16) (signer crypto.MultiSigner, err error) { - return &cryptoMocks.MultisignerMock{ - VerifyCalled: func(msg []byte, bitmap []byte) error { - wasCalled = true - return nil - }}, nil - }, - } + args.MultiSigContainer = cryptoMocks.NewMultiSignerContainerMock(&cryptoMocks.MultisignerMock{ + VerifyAggregatedSigCalled: func(pubKeysSigners [][]byte, message []byte, aggSig []byte) error { + wasCalled = true + return nil + }}) hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.Header{ @@ -561,7 +557,7 @@ func TestHeaderSigVerifier_VerifySignatureNotEnoughSigsShouldErrWhenFallbackThre wasCalled := false args := createHeaderSigVerifierArgs() pkAddr := []byte("aaa00000000000000000000000000000") - nodesCoordinator := &shardingMocks.NodesCoordinatorMock{ + nc := &shardingMocks.NodesCoordinatorMock{ ComputeValidatorsGroupCalled: func(randomness []byte, round uint64, shardId uint32, epoch uint32) (validators []nodesCoordinator.Validator, err error) { v, _ := nodesCoordinator.NewValidator(pkAddr, 1, defaultChancesSelection) return []nodesCoordinator.Validator{v, v, v, v, v}, nil @@ -573,18 +569,15 @@ func TestHeaderSigVerifier_VerifySignatureNotEnoughSigsShouldErrWhenFallbackThre }, } multiSigVerifier := &cryptoMocks.MultisignerMock{ - CreateCalled: func(pubKeys []string, index uint16) (signer crypto.MultiSigner, err error) { - return &cryptoMocks.MultisignerMock{ - VerifyCalled: func(msg []byte, bitmap []byte) error { - wasCalled = true - return nil - }}, nil + VerifyAggregatedSigCalled: func(pubKeysSigners [][]byte, message []byte, aggSig []byte) error { + wasCalled = true + return nil }, } - args.NodesCoordinator = nodesCoordinator + args.NodesCoordinator = nc args.FallbackHeaderValidator = fallbackHeaderValidator - args.MultiSigVerifier = multiSigVerifier + args.MultiSigContainer = cryptoMocks.NewMultiSignerContainerMock(multiSigVerifier) hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.MetaBlock{ @@ -602,7 +595,7 @@ func TestHeaderSigVerifier_VerifySignatureOkWhenFallbackThresholdCouldBeApplied( wasCalled := false args := createHeaderSigVerifierArgs() pkAddr := []byte("aaa00000000000000000000000000000") - nodesCoordinator := &shardingMocks.NodesCoordinatorMock{ + nc := &shardingMocks.NodesCoordinatorMock{ ComputeValidatorsGroupCalled: func(randomness []byte, round uint64, shardId uint32, epoch uint32) (validators []nodesCoordinator.Validator, err error) { v, _ := nodesCoordinator.NewValidator(pkAddr, 1, defaultChancesSelection) return []nodesCoordinator.Validator{v, v, v, v, v}, nil @@ -614,18 +607,14 @@ func TestHeaderSigVerifier_VerifySignatureOkWhenFallbackThresholdCouldBeApplied( }, } multiSigVerifier := &cryptoMocks.MultisignerMock{ - CreateCalled: func(pubKeys []string, index uint16) (signer crypto.MultiSigner, err error) { - return &cryptoMocks.MultisignerMock{ - VerifyCalled: func(msg []byte, bitmap []byte) error { - wasCalled = true - return nil - }}, nil - }, - } + VerifyAggregatedSigCalled: func(pubKeysSigners [][]byte, message []byte, aggSig []byte) error { + wasCalled = true + return nil + }} - args.NodesCoordinator = nodesCoordinator + args.NodesCoordinator = nc args.FallbackHeaderValidator = fallbackHeaderValidator - args.MultiSigVerifier = multiSigVerifier + args.MultiSigContainer = cryptoMocks.NewMultiSignerContainerMock(multiSigVerifier) hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.MetaBlock{ diff --git a/process/interceptors/factory/argInterceptedDataFactory.go b/process/interceptors/factory/argInterceptedDataFactory.go index 3222230eba0..51323031c12 100644 --- a/process/interceptors/factory/argInterceptedDataFactory.go +++ b/process/interceptors/factory/argInterceptedDataFactory.go @@ -33,7 +33,7 @@ type interceptedDataCryptoComponentsHolder interface { BlockSignKeyGen() crypto.KeyGenerator TxSingleSigner() crypto.SingleSigner BlockSigner() crypto.SingleSigner - MultiSigner() crypto.MultiSigner + GetMultiSigner(epoch uint32) (crypto.MultiSigner, error) PublicKey() crypto.PublicKey IsInterfaceNil() bool } diff --git a/process/interceptors/factory/interceptedMetaHeaderDataFactory_test.go b/process/interceptors/factory/interceptedMetaHeaderDataFactory_test.go index 0ea3eacb074..955a5fff81f 100644 --- a/process/interceptors/factory/interceptedMetaHeaderDataFactory_test.go +++ b/process/interceptors/factory/interceptedMetaHeaderDataFactory_test.go @@ -73,11 +73,11 @@ func createMockComponentHolders() (*mock.CoreComponentsMock, *mock.CryptoCompone HardforkTriggerPubKeyField: []byte("provided hardfork pub key"), } cryptoComponents := &mock.CryptoComponentsMock{ - BlockSig: createMockSigner(), - TxSig: createMockSigner(), - MultiSig: cryptoMocks.NewMultiSigner(21), - BlKeyGen: createMockKeyGen(), - TxKeyGen: createMockKeyGen(), + BlockSig: createMockSigner(), + TxSig: createMockSigner(), + MultiSigContainer: cryptoMocks.NewMultiSignerContainerMock(cryptoMocks.NewMultiSigner()), + BlKeyGen: createMockKeyGen(), + TxKeyGen: createMockKeyGen(), } return coreComponents, cryptoComponents diff --git a/process/interface.go b/process/interface.go index cfa19ce68cb..4e65b4b13d2 100644 --- a/process/interface.go +++ b/process/interface.go @@ -19,6 +19,7 @@ import ( "github.com/ElrondNetwork/elrond-go-core/marshal" "github.com/ElrondNetwork/elrond-go-crypto" "github.com/ElrondNetwork/elrond-go/common" + cryptoCommon "github.com/ElrondNetwork/elrond-go/common/crypto" "github.com/ElrondNetwork/elrond-go/epochStart" "github.com/ElrondNetwork/elrond-go/p2p" "github.com/ElrondNetwork/elrond-go/process/block/bootstrapStorage" @@ -1146,8 +1147,9 @@ type CryptoComponentsHolder interface { BlockSignKeyGen() crypto.KeyGenerator TxSingleSigner() crypto.SingleSigner BlockSigner() crypto.SingleSigner - MultiSigner() crypto.MultiSigner - SetMultiSigner(ms crypto.MultiSigner) error + GetMultiSigner(epoch uint32) (crypto.MultiSigner, error) + MultiSignerContainer() cryptoCommon.MultiSignerContainer + SetMultiSignerContainer(ms cryptoCommon.MultiSignerContainer) error PeerSignatureHandler() crypto.PeerSignatureHandler PublicKey() crypto.PublicKey Clone() interface{} diff --git a/process/mock/cryptoComponentsMock.go b/process/mock/cryptoComponentsMock.go index 7c74300b2e1..60bd0918dca 100644 --- a/process/mock/cryptoComponentsMock.go +++ b/process/mock/cryptoComponentsMock.go @@ -1,21 +1,23 @@ package mock import ( + "errors" "sync" "github.com/ElrondNetwork/elrond-go-crypto" + cryptoCommon "github.com/ElrondNetwork/elrond-go/common/crypto" ) // CryptoComponentsMock - type CryptoComponentsMock struct { - BlockSig crypto.SingleSigner - TxSig crypto.SingleSigner - MultiSig crypto.MultiSigner - PeerSignHandler crypto.PeerSignatureHandler - BlKeyGen crypto.KeyGenerator - TxKeyGen crypto.KeyGenerator - PubKey crypto.PublicKey - mutMultiSig sync.RWMutex + BlockSig crypto.SingleSigner + TxSig crypto.SingleSigner + MultiSigContainer cryptoCommon.MultiSignerContainer + PeerSignHandler crypto.PeerSignatureHandler + BlKeyGen crypto.KeyGenerator + TxKeyGen crypto.KeyGenerator + PubKey crypto.PublicKey + mutMultiSig sync.RWMutex } // BlockSigner - @@ -28,18 +30,32 @@ func (ccm *CryptoComponentsMock) TxSingleSigner() crypto.SingleSigner { return ccm.TxSig } -// MultiSigner - -func (ccm *CryptoComponentsMock) MultiSigner() crypto.MultiSigner { +// GetMultiSigner - +func (ccm *CryptoComponentsMock) GetMultiSigner(epoch uint32) (crypto.MultiSigner, error) { ccm.mutMultiSig.RLock() defer ccm.mutMultiSig.RUnlock() - return ccm.MultiSig + + if ccm.MultiSigContainer == nil { + return nil, errors.New("multisigner container is nil") + } + + return ccm.MultiSigContainer.GetMultiSigner(epoch) } -// SetMultiSigner - -func (ccm *CryptoComponentsMock) SetMultiSigner(multiSigner crypto.MultiSigner) error { +// MultiSignerContainer - +func (ccm *CryptoComponentsMock) MultiSignerContainer() cryptoCommon.MultiSignerContainer { + ccm.mutMultiSig.RLock() + defer ccm.mutMultiSig.RUnlock() + + return ccm.MultiSigContainer +} + +// SetMultiSignerContainer - +func (ccm *CryptoComponentsMock) SetMultiSignerContainer(msc cryptoCommon.MultiSignerContainer) error { ccm.mutMultiSig.Lock() - ccm.MultiSig = multiSigner - ccm.mutMultiSig.Unlock() + defer ccm.mutMultiSig.Unlock() + + ccm.MultiSigContainer = msc return nil } @@ -69,14 +85,14 @@ func (ccm *CryptoComponentsMock) PublicKey() crypto.PublicKey { // Clone - func (ccm *CryptoComponentsMock) Clone() interface{} { return &CryptoComponentsMock{ - BlockSig: ccm.BlockSig, - TxSig: ccm.TxSig, - MultiSig: ccm.MultiSig, - PeerSignHandler: ccm.PeerSignHandler, - BlKeyGen: ccm.BlKeyGen, - TxKeyGen: ccm.TxKeyGen, - PubKey: ccm.PubKey, - mutMultiSig: sync.RWMutex{}, + BlockSig: ccm.BlockSig, + TxSig: ccm.TxSig, + MultiSigContainer: ccm.MultiSigContainer, + PeerSignHandler: ccm.PeerSignHandler, + BlKeyGen: ccm.BlKeyGen, + TxKeyGen: ccm.TxKeyGen, + PubKey: ccm.PubKey, + mutMultiSig: sync.RWMutex{}, } } diff --git a/testscommon/components/components.go b/testscommon/components/components.go index b1bd96064aa..a073c097e7a 100644 --- a/testscommon/components/components.go +++ b/testscommon/components/components.go @@ -240,6 +240,9 @@ func GetCryptoArgs(coreComponents factory.CoreComponentsHolder) cryptoComp.Crypt KeyLoader: &mock.KeyLoaderStub{ LoadKeyCalled: DummyLoadSkPkFromPemFile([]byte(DummySk), DummyPk, nil), }, + EnableEpochs: config.EnableEpochs{ + BLSMultiSignerEnableEpoch: []config.MultiSignerConfig{{EnableEpoch: 0, Type: "no-KOSK"}}, + }, } return args diff --git a/testscommon/components/default.go b/testscommon/components/default.go index 6aeea857dcc..e4fe5d55e63 100644 --- a/testscommon/components/default.go +++ b/testscommon/components/default.go @@ -53,18 +53,18 @@ func GetDefaultCoreComponents() *mock.CoreComponentsMock { // GetDefaultCryptoComponents - func GetDefaultCryptoComponents() *mock.CryptoComponentsMock { return &mock.CryptoComponentsMock{ - PubKey: &mock.PublicKeyMock{}, - PrivKey: &mock.PrivateKeyStub{}, - PubKeyString: "pubKey", - PrivKeyBytes: []byte("privKey"), - PubKeyBytes: []byte("pubKey"), - BlockSig: &mock.SinglesignMock{}, - TxSig: &mock.SinglesignMock{}, - MultiSig: &cryptoMocks.MultisignerStub{}, - PeerSignHandler: &mock.PeerSignatureHandler{}, - BlKeyGen: &mock.KeyGenMock{}, - TxKeyGen: &mock.KeyGenMock{}, - MsgSigVerifier: &testscommon.MessageSignVerifierMock{}, + PubKey: &mock.PublicKeyMock{}, + PrivKey: &mock.PrivateKeyStub{}, + PubKeyString: "pubKey", + PrivKeyBytes: []byte("privKey"), + PubKeyBytes: []byte("pubKey"), + BlockSig: &mock.SinglesignMock{}, + TxSig: &mock.SinglesignMock{}, + MultiSigContainer: cryptoMocks.NewMultiSignerContainerMock(&cryptoMocks.MultisignerMock{}), + PeerSignHandler: &mock.PeerSignatureHandler{}, + BlKeyGen: &mock.KeyGenMock{}, + TxKeyGen: &mock.KeyGenMock{}, + MsgSigVerifier: &testscommon.MessageSignVerifierMock{}, } } diff --git a/testscommon/cryptoMocks/multiSignerContainerMock.go b/testscommon/cryptoMocks/multiSignerContainerMock.go new file mode 100644 index 00000000000..f76dbd8236d --- /dev/null +++ b/testscommon/cryptoMocks/multiSignerContainerMock.go @@ -0,0 +1,23 @@ +package cryptoMocks + +import crypto "github.com/ElrondNetwork/elrond-go-crypto" + +// MultiSignerContainerMock - +type MultiSignerContainerMock struct { + MultiSigner crypto.MultiSigner +} + +// NewMultiSignerContainerMock - +func NewMultiSignerContainerMock(multiSigner crypto.MultiSigner) *MultiSignerContainerMock { + return &MultiSignerContainerMock{MultiSigner: multiSigner} +} + +// GetMultiSigner - +func (mscm *MultiSignerContainerMock) GetMultiSigner(_ uint32) (crypto.MultiSigner, error) { + return mscm.MultiSigner, nil +} + +// IsInterfaceNil - +func (mscm *MultiSignerContainerMock) IsInterfaceNil() bool { + return mscm == nil +} diff --git a/testscommon/cryptoMocks/multisignerMock.go b/testscommon/cryptoMocks/multisignerMock.go index 5b02490eed3..913475e46a6 100644 --- a/testscommon/cryptoMocks/multisignerMock.go +++ b/testscommon/cryptoMocks/multisignerMock.go @@ -1,154 +1,56 @@ package cryptoMocks import ( - "github.com/ElrondNetwork/elrond-go-crypto" + "bytes" ) const signatureSize = 48 // MultisignerMock is used to mock the multisignature scheme type MultisignerMock struct { - aggSig []byte - sigs [][]byte - pubkeys []string - selfId uint16 - - VerifyCalled func(msg []byte, bitmap []byte) error - CommitmentHashCalled func(index uint16) ([]byte, error) - CreateSignatureShareCalled func(msg []byte, bitmap []byte) ([]byte, error) - VerifySignatureShareCalled func(index uint16, sig []byte, msg []byte, bitmap []byte) error - AggregateSigsCalled func(bitmap []byte) ([]byte, error) - SignatureShareCalled func(index uint16) ([]byte, error) - CreateCalled func(pubKeys []string, index uint16) (crypto.MultiSigner, error) - ResetCalled func(pubKeys []string, index uint16) error - CreateAndAddSignatureShareForKeyCalled func(message []byte, privateKey crypto.PrivateKey, pubKeyBytes []byte) ([]byte, error) - StoreSignatureShareCalled func(index uint16, sig []byte) error + CreateSignatureShareCalled func(privateKeyBytes []byte, message []byte) ([]byte, error) + VerifySignatureShareCalled func(publicKey []byte, message []byte, sig []byte) error + AggregateSigsCalled func(pubKeysSigners [][]byte, signatures [][]byte) ([]byte, error) + VerifyAggregatedSigCalled func(pubKeysSigners [][]byte, message []byte, aggSig []byte) error } // NewMultiSigner - -func NewMultiSigner(consensusSize uint32) *MultisignerMock { - multisigner := &MultisignerMock{} - multisigner.sigs = make([][]byte, consensusSize) - multisigner.pubkeys = make([]string, consensusSize) - - multisigner.aggSig = make([]byte, signatureSize) - copy(multisigner.aggSig, "aggregated signature") - - return multisigner -} - -// Create - -func (mm *MultisignerMock) Create(pubKeys []string, index uint16) (crypto.MultiSigner, error) { - if mm.CreateCalled != nil { - return mm.CreateCalled(pubKeys, index) - } - - multiSig := NewMultiSigner(uint32(len(pubKeys))) - - multiSig.selfId = index - multiSig.pubkeys = pubKeys - - return multiSig, nil -} - -// Reset - -func (mm *MultisignerMock) Reset(pubKeys []string, index uint16) error { - if mm.ResetCalled != nil { - return mm.ResetCalled(pubKeys, index) - } - - mm.sigs = make([][]byte, len(pubKeys)) - mm.pubkeys = make([]string, len(pubKeys)) - mm.selfId = index - mm.pubkeys = pubKeys - - for i := 0; i < len(pubKeys); i++ { - mm.sigs[i] = mm.aggSig - } - - mm.selfId = index - mm.pubkeys = pubKeys - - return nil -} - -// SetAggregatedSig - -func (mm *MultisignerMock) SetAggregatedSig(aggSig []byte) error { - mm.aggSig = aggSig - - return nil +func NewMultiSigner() *MultisignerMock { + return &MultisignerMock{} } -// Verify - -func (mm *MultisignerMock) Verify(msg []byte, bitmap []byte) error { - if mm.VerifyCalled != nil { - return mm.VerifyCalled(msg, bitmap) - } - - return nil -} - -// CreateSignatureShare creates a partial signature -func (mm *MultisignerMock) CreateSignatureShare(msg []byte, bitmap []byte) ([]byte, error) { +// CreateSignatureShare - +func (mm *MultisignerMock) CreateSignatureShare(privateKeyBytes []byte, message []byte) ([]byte, error) { if mm.CreateSignatureShareCalled != nil { - return mm.CreateSignatureShareCalled(msg, bitmap) + return mm.CreateSignatureShareCalled(privateKeyBytes, message) } - return mm.aggSig, nil -} - -// StoreSignatureShare - -func (mm *MultisignerMock) StoreSignatureShare(index uint16, sig []byte) error { - if mm.StoreSignatureShareCalled != nil { - return mm.StoreSignatureShareCalled(index, sig) - } - - if index >= uint16(len(mm.pubkeys)) { - return crypto.ErrIndexOutOfBounds - } - - mm.sigs[index] = sig - return nil + return bytes.Repeat([]byte("0xAA"), signatureSize), nil } // VerifySignatureShare - -func (mm *MultisignerMock) VerifySignatureShare(index uint16, sig []byte, msg []byte, bitmap []byte) error { +func (mm *MultisignerMock) VerifySignatureShare(publicKey []byte, message []byte, sig []byte) error { if mm.VerifySignatureShareCalled != nil { - return mm.VerifySignatureShareCalled(index, sig, msg, bitmap) + return mm.VerifySignatureShareCalled(publicKey, message, sig) } - return nil } // AggregateSigs - -func (mm *MultisignerMock) AggregateSigs(bitmap []byte) ([]byte, error) { +func (mm *MultisignerMock) AggregateSigs(pubKeysSigners [][]byte, signatures [][]byte) ([]byte, error) { if mm.AggregateSigsCalled != nil { - return mm.AggregateSigsCalled(bitmap) - } - - return mm.aggSig, nil -} - -// SignatureShare - -func (mm *MultisignerMock) SignatureShare(index uint16) ([]byte, error) { - if mm.SignatureShareCalled != nil { - return mm.SignatureShareCalled(index) - } - - if index >= uint16(len(mm.sigs)) { - return nil, crypto.ErrIndexOutOfBounds + return mm.AggregateSigsCalled(pubKeysSigners, signatures) } - return mm.sigs[index], nil + return bytes.Repeat([]byte("0xAA"), signatureSize), nil } -// CreateAndAddSignatureShareForKey - -func (mm *MultisignerMock) CreateAndAddSignatureShareForKey(message []byte, privateKey crypto.PrivateKey, pubKeyBytes []byte) ([]byte, error) { - if mm.CreateAndAddSignatureShareForKeyCalled != nil { - return mm.CreateAndAddSignatureShareForKeyCalled(message, privateKey, pubKeyBytes) +// VerifyAggregatedSig - +func (mm *MultisignerMock) VerifyAggregatedSig(pubKeysSigners [][]byte, message []byte, aggSig []byte) error { + if mm.VerifyAggregatedSigCalled != nil { + return mm.VerifyAggregatedSigCalled(pubKeysSigners, message, aggSig) } - - return nil, nil + return nil } // IsInterfaceNil - diff --git a/testscommon/cryptoMocks/multisignerStub.go b/testscommon/cryptoMocks/multisignerStub.go deleted file mode 100644 index 4f2d4291bf2..00000000000 --- a/testscommon/cryptoMocks/multisignerStub.go +++ /dev/null @@ -1,112 +0,0 @@ -package cryptoMocks - -import crypto "github.com/ElrondNetwork/elrond-go-crypto" - -// MultisignerStub - -type MultisignerStub struct { - CreateCalled func(pubKeys []string, index uint16) (crypto.MultiSigner, error) - SetAggregatedSigCalled func(bytes []byte) error - VerifyCalled func(msg []byte, bitmap []byte) error - ResetCalled func(pubKeys []string, index uint16) error - CreateSignatureShareCalled func(msg []byte, bitmap []byte) ([]byte, error) - StoreSignatureShareCalled func(index uint16, sig []byte) error - SignatureShareCalled func(index uint16) ([]byte, error) - VerifySignatureShareCalled func(index uint16, sig []byte, msg []byte, bitmap []byte) error - AggregateSigsCalled func(bitmap []byte) ([]byte, error) - CreateAndAddSignatureShareForKeyCalled func(message []byte, privateKey crypto.PrivateKey, pubKeyBytes []byte) ([]byte, error) -} - -// Create - -func (mss *MultisignerStub) Create(pubKeys []string, index uint16) (crypto.MultiSigner, error) { - if mss.CreateCalled != nil { - return mss.CreateCalled(pubKeys, index) - } - - return nil, nil -} - -// SetAggregatedSig - -func (mss *MultisignerStub) SetAggregatedSig(bytes []byte) error { - if mss.SetAggregatedSigCalled != nil { - return mss.SetAggregatedSigCalled(bytes) - } - - return nil -} - -// Verify - -func (mss *MultisignerStub) Verify(msg []byte, bitmap []byte) error { - if mss.VerifyCalled != nil { - return mss.VerifyCalled(msg, bitmap) - } - - return nil -} - -// Reset - -func (mss *MultisignerStub) Reset(pubKeys []string, index uint16) error { - if mss.ResetCalled != nil { - return mss.ResetCalled(pubKeys, index) - } - - return nil -} - -// CreateSignatureShare - -func (mss *MultisignerStub) CreateSignatureShare(msg []byte, bitmap []byte) ([]byte, error) { - if mss.CreateSignatureShareCalled != nil { - return mss.CreateSignatureShareCalled(msg, bitmap) - } - - return nil, nil -} - -// StoreSignatureShare - -func (mss *MultisignerStub) StoreSignatureShare(index uint16, sig []byte) error { - if mss.StoreSignatureShareCalled != nil { - return mss.StoreSignatureShareCalled(index, sig) - } - - return nil -} - -// SignatureShare - -func (mss *MultisignerStub) SignatureShare(index uint16) ([]byte, error) { - if mss.SignatureShareCalled != nil { - return mss.SignatureShareCalled(index) - } - - return nil, nil -} - -// VerifySignatureShare - -func (mss *MultisignerStub) VerifySignatureShare(index uint16, sig []byte, msg []byte, bitmap []byte) error { - if mss.VerifySignatureShareCalled != nil { - return mss.VerifySignatureShareCalled(index, sig, msg, bitmap) - } - - return nil -} - -// AggregateSigs - -func (mss *MultisignerStub) AggregateSigs(bitmap []byte) ([]byte, error) { - if mss.AggregateSigsCalled != nil { - return mss.AggregateSigsCalled(bitmap) - } - - return nil, nil -} - -// CreateAndAddSignatureShareForKey - -func (mss *MultisignerStub) CreateAndAddSignatureShareForKey(message []byte, privateKey crypto.PrivateKey, pubKeyBytes []byte) ([]byte, error) { - if mss.CreateAndAddSignatureShareForKeyCalled != nil { - return mss.CreateAndAddSignatureShareForKeyCalled(message, privateKey, pubKeyBytes) - } - - return nil, nil -} - -// IsInterfaceNil - -func (mss *MultisignerStub) IsInterfaceNil() bool { - return mss == nil -} diff --git a/update/factory/exportHandlerFactory.go b/update/factory/exportHandlerFactory.go index 6accd55e2a2..c6bd0f4408b 100644 --- a/update/factory/exportHandlerFactory.go +++ b/update/factory/exportHandlerFactory.go @@ -159,7 +159,11 @@ func NewExportHandlerFactory(args ArgsExporter) (*exportHandlerFactory, error) { if check.IfNil(args.ExistingResolvers) { return nil, update.ErrNilResolverContainer } - if check.IfNil(args.CryptoComponents.MultiSigner()) { + multiSigner, err := args.CryptoComponents.GetMultiSigner(0) + if err != nil { + return nil, err + } + if check.IfNil(multiSigner) { return nil, update.ErrNilMultiSigner } if check.IfNil(args.NodesCoordinator) { @@ -219,7 +223,7 @@ func NewExportHandlerFactory(args ArgsExporter) (*exportHandlerFactory, error) { if args.NumConcurrentTrieSyncers < 1 { return nil, update.ErrInvalidNumConcurrentTrieSyncers } - err := trie.CheckTrieSyncerVersion(args.TrieSyncerVersion) + err = trie.CheckTrieSyncerVersion(args.TrieSyncerVersion) if err != nil { return nil, err } diff --git a/update/factory/fullSyncInterceptors.go b/update/factory/fullSyncInterceptors.go index 45ae6c24bd5..e76380f957c 100644 --- a/update/factory/fullSyncInterceptors.go +++ b/update/factory/fullSyncInterceptors.go @@ -248,7 +248,11 @@ func checkBaseParams( if check.IfNil(cryptoComponents.BlockSigner()) { return process.ErrNilSingleSigner } - if check.IfNil(cryptoComponents.MultiSigner()) { + multiSigner, err := cryptoComponents.GetMultiSigner(0) + if err != nil { + return err + } + if check.IfNil(multiSigner) { return process.ErrNilMultiSigVerifier } if check.IfNil(shardCoordinator) {