Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update bls multisigner #4318

Merged
merged 11 commits into from
Jul 29, 2022
6 changes: 6 additions & 0 deletions cmd/node/config/enableEpochs.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down
9 changes: 9 additions & 0 deletions common/crypto/interface.go
Original file line number Diff line number Diff line change
@@ -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
}
6 changes: 6 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions config/epochConfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 16 additions & 0 deletions config/tomlConfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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" },
Expand Down Expand Up @@ -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{
{
Expand Down
15 changes: 8 additions & 7 deletions consensus/mock/consensusDataContainerMock.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
Expand Down Expand Up @@ -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 -
Expand Down Expand Up @@ -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 -
Expand Down
13 changes: 7 additions & 6 deletions consensus/mock/mockTestInitializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down
6 changes: 3 additions & 3 deletions consensus/spos/bls/blsSubroundsFactory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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) {
Expand Down
6 changes: 3 additions & 3 deletions consensus/spos/bls/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions consensus/spos/bls/subroundBlock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand All @@ -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) {
Expand Down
16 changes: 15 additions & 1 deletion consensus/spos/bls/subroundEndRound.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
raduchis marked this conversation as resolved.
Show resolved Hide resolved
func (sr *subroundEndRound) getSigningData() (pubKeys [][]byte, sigShares [][]byte) {
return nil, nil
}

func (sr *subroundEndRound) doEndRoundJobByLeader() bool {
bitmap := sr.GenerateBitmap(SrSignature)
err := sr.checkSignaturesValidity(bitmap)
Expand All @@ -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
Expand Down
11 changes: 6 additions & 5 deletions consensus/spos/bls/subroundEndRound_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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()
Expand All @@ -199,7 +200,7 @@ func TestSubroundEndRound_NewSubroundEndRoundNilMultisignerShouldFail(t *testing
currentPid,
&statusHandler.AppStatusHandlerStub{},
)
container.SetMultiSigner(nil)
container.SetMultiSignerContainer(nil)
srEndRound, err := bls.NewSubroundEndRound(
sr,
extend,
Expand All @@ -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) {
Expand Down Expand Up @@ -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")
Expand Down
41 changes: 32 additions & 9 deletions consensus/spos/bls/subroundSignature.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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",
Expand Down
Loading