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

Peer authentication sender factory #4414

Merged
merged 8 commits into from
Sep 1, 2022
2 changes: 1 addition & 1 deletion heartbeat/sender/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type hardforkHandler interface {
Close()
}

type peerAuthenticationHandler interface {
type peerAuthenticationSenderHandler interface {
senderHandler
hardforkHandler
}
Expand Down
125 changes: 35 additions & 90 deletions heartbeat/sender/peerAuthenticationSenderFactory.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package sender

import (
"fmt"
"time"

"github.com/ElrondNetwork/covalent-indexer-go/process"
"github.com/ElrondNetwork/elrond-go-core/core/check"
"github.com/ElrondNetwork/elrond-go-core/marshal"
crypto "github.com/ElrondNetwork/elrond-go-crypto"
"github.com/ElrondNetwork/elrond-go/heartbeat"
)
Expand All @@ -25,105 +22,53 @@ type argPeerAuthenticationSenderFactory struct {
redundancyHandler heartbeat.NodeRedundancyHandler
}

type peerAuthenticationSenderFactory struct {
messenger heartbeat.P2PMessenger
marshaller marshal.Marshalizer
topic string
timeBetweenSends time.Duration
timeBetweenSendsWhenError time.Duration
thresholdBetweenSends float64
nodesCoordinator heartbeat.NodesCoordinator
peerSignatureHandler crypto.PeerSignatureHandler
hardforkTrigger heartbeat.HardforkTrigger
hardforkTimeBetweenSends time.Duration
hardforkTriggerPubKey []byte
keysHolder heartbeat.KeysHolder
timeBetweenChecks time.Duration
shardCoordinator process.ShardCoordinator
privKey crypto.PrivateKey
redundancyHandler heartbeat.NodeRedundancyHandler
}

func newPeerAuthenticationSenderFactory(args argPeerAuthenticationSenderFactory) (*peerAuthenticationSenderFactory, error) {
return &peerAuthenticationSenderFactory{
messenger: args.messenger,
marshaller: args.marshaller,
topic: args.topic,
timeBetweenSends: args.timeBetweenSends,
timeBetweenSendsWhenError: args.timeBetweenSendsWhenError,
thresholdBetweenSends: args.thresholdBetweenSends,
nodesCoordinator: args.nodesCoordinator,
peerSignatureHandler: args.peerSignatureHandler,
hardforkTrigger: args.hardforkTrigger,
hardforkTimeBetweenSends: args.hardforkTimeBetweenSends,
hardforkTriggerPubKey: args.hardforkTriggerPubKey,
keysHolder: args.keysHolder,
timeBetweenChecks: args.timeBetweenChecks,
shardCoordinator: args.shardCoordinator,
privKey: args.privKey,
redundancyHandler: args.redundancyHandler,
}, nil
}

func (pasf *peerAuthenticationSenderFactory) create() (peerAuthenticationHandler, error) {
isMultikey := check.IfNil(pasf.privKey)
isRegular := check.IfNil(pasf.keysHolder)
if isMultikey && isRegular {
return nil, fmt.Errorf("%w for peerAuthenticationSenderFactory, received both validator key and multikey holder", heartbeat.ErrInvalidConfiguration)
func createPeerAuthenticationSender(args argPeerAuthenticationSenderFactory) (peerAuthenticationSenderHandler, error) {
pk := args.privKey.GeneratePublic()
pkBytes, err := pk.ToByteArray()
if err != nil {
return nil, err
}

if !isMultikey && !isRegular {
return nil, fmt.Errorf("%w for peerAuthenticationSenderFactory, could not determine node's type", heartbeat.ErrInvalidConfiguration)
_, _, err = args.nodesCoordinator.GetValidatorWithPublicKey(pkBytes)
if err == nil {
return createRegularSender(args)
Copy link
Contributor

Choose a reason for hiding this comment

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

please add a check here for len(keysMap) and allow to create the regular peer only if that len is 0. Otherwise we should output error

}

if isMultikey {
return pasf.createMultikeyPeerAuthenticationSender()
keysMap := args.keysHolder.GetManagedKeysByCurrentNode()
if len(keysMap) == 0 {
return createRegularSender(args)
}

return pasf.createPeerAuthenticationSender()
return createMultikeySender(args)
}

func (pasf *peerAuthenticationSenderFactory) createPeerAuthenticationSender() (*peerAuthenticationSender, error) {
args := argPeerAuthenticationSender{
argBaseSender: argBaseSender{
messenger: pasf.messenger,
marshaller: pasf.marshaller,
topic: pasf.topic,
timeBetweenSends: pasf.timeBetweenSends,
timeBetweenSendsWhenError: pasf.timeBetweenSendsWhenError,
thresholdBetweenSends: pasf.thresholdBetweenSends,
},
nodesCoordinator: pasf.nodesCoordinator,
peerSignatureHandler: pasf.peerSignatureHandler,
privKey: pasf.privKey,
redundancyHandler: pasf.redundancyHandler,
hardforkTrigger: pasf.hardforkTrigger,
hardforkTimeBetweenSends: pasf.hardforkTimeBetweenSends,
hardforkTriggerPubKey: pasf.hardforkTriggerPubKey,
func createRegularSender(args argPeerAuthenticationSenderFactory) (*peerAuthenticationSender, error) {
argsSender := argPeerAuthenticationSender{
argBaseSender: args.argBaseSender,
nodesCoordinator: args.nodesCoordinator,
peerSignatureHandler: args.peerSignatureHandler,
privKey: args.privKey,
redundancyHandler: args.redundancyHandler,
hardforkTrigger: args.hardforkTrigger,
hardforkTimeBetweenSends: args.hardforkTimeBetweenSends,
hardforkTriggerPubKey: args.hardforkTriggerPubKey,
}

return newPeerAuthenticationSender(args)
return newPeerAuthenticationSender(argsSender)
}

func (pasf *peerAuthenticationSenderFactory) createMultikeyPeerAuthenticationSender() (*multikeyPeerAuthenticationSender, error) {
args := argMultikeyPeerAuthenticationSender{
argBaseSender: argBaseSender{
messenger: pasf.messenger,
marshaller: pasf.marshaller,
topic: pasf.topic,
timeBetweenSends: pasf.timeBetweenSends,
timeBetweenSendsWhenError: pasf.timeBetweenSendsWhenError,
thresholdBetweenSends: pasf.thresholdBetweenSends,
},
nodesCoordinator: pasf.nodesCoordinator,
peerSignatureHandler: pasf.peerSignatureHandler,
hardforkTrigger: pasf.hardforkTrigger,
hardforkTimeBetweenSends: pasf.hardforkTimeBetweenSends,
hardforkTriggerPubKey: pasf.hardforkTriggerPubKey,
keysHolder: pasf.keysHolder,
timeBetweenChecks: pasf.timeBetweenChecks,
shardCoordinator: pasf.shardCoordinator,
func createMultikeySender(args argPeerAuthenticationSenderFactory) (*multikeyPeerAuthenticationSender, error) {
argsSender := argMultikeyPeerAuthenticationSender{
argBaseSender: args.argBaseSender,
nodesCoordinator: args.nodesCoordinator,
peerSignatureHandler: args.peerSignatureHandler,
hardforkTrigger: args.hardforkTrigger,
hardforkTimeBetweenSends: args.hardforkTimeBetweenSends,
hardforkTriggerPubKey: args.hardforkTriggerPubKey,
keysHolder: args.keysHolder,
timeBetweenChecks: args.timeBetweenChecks,
shardCoordinator: args.shardCoordinator,
}

return newMultikeyPeerAuthenticationSender(args)
return newMultikeyPeerAuthenticationSender(argsSender)
}
109 changes: 68 additions & 41 deletions heartbeat/sender/peerAuthenticationSenderFactory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ package sender

import (
"errors"
"fmt"
"testing"
"time"

"github.com/ElrondNetwork/elrond-go-core/core/check"
"github.com/ElrondNetwork/elrond-go/heartbeat"
"github.com/ElrondNetwork/elrond-go-crypto"
"github.com/ElrondNetwork/elrond-go-crypto/signing"
"github.com/ElrondNetwork/elrond-go-crypto/signing/mcl"
"github.com/ElrondNetwork/elrond-go/heartbeat/mock"
"github.com/ElrondNetwork/elrond-go/sharding/nodesCoordinator"
"github.com/ElrondNetwork/elrond-go/testscommon"
"github.com/ElrondNetwork/elrond-go/testscommon/cryptoMocks"
"github.com/ElrondNetwork/elrond-go/testscommon/shardingMocks"
Expand All @@ -30,64 +34,87 @@ func createMockPeerAuthenticationSenderFactoryArgs() argPeerAuthenticationSender
}
}

func Test_peerAuthenticationSenderFactory_Create(t *testing.T) {
func TestPeerAuthenticationSenderFactory_Create(t *testing.T) {
t.Parallel()

t.Run("both configs should error", func(t *testing.T) {
t.Run("ToByteArray fails should error", func(t *testing.T) {
t.Parallel()

peerAuthFactory, err := newPeerAuthenticationSenderFactory(createMockPeerAuthenticationSenderFactoryArgs())
assert.Nil(t, err)
assert.NotNil(t, peerAuthFactory)

peerAuth, err := peerAuthFactory.create()
assert.True(t, check.IfNil(peerAuth))
assert.True(t, errors.Is(err, heartbeat.ErrInvalidConfiguration))
args := createMockPeerAuthenticationSenderFactoryArgs()
args.privKey = &cryptoMocks.PrivateKeyStub{
GeneratePublicStub: func() crypto.PublicKey {
return &cryptoMocks.PublicKeyStub{
ToByteArrayStub: func() ([]byte, error) {
return nil, expectedErr
},
}
},
}
peerAuthSender, err := createPeerAuthenticationSender(args)
assert.Equal(t, expectedErr, err)
assert.True(t, check.IfNil(peerAuthSender))
})
t.Run("none of the configs should error", func(t *testing.T) {
t.Run("validator should create regular sender", func(t *testing.T) {
t.Parallel()

args := createMockPeerAuthenticationSenderFactoryArgs()
args.keysHolder = nil
args.privKey = nil
peerAuthFactory, err := newPeerAuthenticationSenderFactory(args)
args.nodesCoordinator = &shardingMocks.NodesCoordinatorStub{
GetValidatorWithPublicKeyCalled: func(publicKey []byte) (validator nodesCoordinator.Validator, shardId uint32, err error) {
return nil, 0, nil
},
}
peerAuthSender, err := createPeerAuthenticationSender(args)
assert.Nil(t, err)
assert.NotNil(t, peerAuthFactory)

peerAuth, err := peerAuthFactory.create()
assert.True(t, check.IfNil(peerAuth))
assert.True(t, errors.Is(err, heartbeat.ErrInvalidConfiguration))
assert.False(t, check.IfNil(peerAuthSender))
assert.Equal(t, "*sender.peerAuthenticationSender", fmt.Sprintf("%T", peerAuthSender))
})
t.Run("should create validator peer authentication", func(t *testing.T) {
t.Run("regular observer should create regular sender", func(t *testing.T) {
t.Parallel()

args := createMockPeerAuthenticationSenderFactoryArgs()
args.keysHolder = nil
peerAuthFactory, err := newPeerAuthenticationSenderFactory(args)
assert.Nil(t, err)
assert.NotNil(t, peerAuthFactory)

peerAuth, err := peerAuthFactory.create()
args.nodesCoordinator = &shardingMocks.NodesCoordinatorStub{
GetValidatorWithPublicKeyCalled: func(publicKey []byte) (validator nodesCoordinator.Validator, shardId uint32, err error) {
return nil, 0, errors.New("not validator")
},
}
args.keysHolder = &testscommon.KeysHolderStub{
GetManagedKeysByCurrentNodeCalled: func() map[string]crypto.PrivateKey {
return make(map[string]crypto.PrivateKey)
},
}
peerAuthSender, err := createPeerAuthenticationSender(args)
assert.Nil(t, err)
assert.False(t, check.IfNil(peerAuth))

_, ok := peerAuth.(*peerAuthenticationSender)
assert.True(t, ok)
assert.False(t, check.IfNil(peerAuthSender))
assert.Equal(t, "*sender.peerAuthenticationSender", fmt.Sprintf("%T", peerAuthSender))
})
t.Run("should create multikey peer authentication", func(t *testing.T) {
t.Run("not validator with keys managed should create multikey sender", func(t *testing.T) {
t.Parallel()

args := createMockPeerAuthenticationSenderFactoryArgs()
args.privKey = nil
peerAuthFactory, err := newPeerAuthenticationSenderFactory(args)
assert.Nil(t, err)
assert.NotNil(t, peerAuthFactory)

peerAuth, err := peerAuthFactory.create()
args.nodesCoordinator = &shardingMocks.NodesCoordinatorStub{
GetValidatorWithPublicKeyCalled: func(publicKey []byte) (validator nodesCoordinator.Validator, shardId uint32, err error) {
return nil, 0, errors.New("not validator")
},
}
args.keysHolder = &testscommon.KeysHolderStub{
GetManagedKeysByCurrentNodeCalled: func() map[string]crypto.PrivateKey {
keygen := signing.NewKeyGenerator(&mcl.SuiteBLS12{})
sk1, pk1 := keygen.GeneratePair()
pk1Bytes, err := pk1.ToByteArray()
assert.Nil(t, err)
sk2, pk2 := keygen.GeneratePair()
pk2Bytes, err := pk2.ToByteArray()
assert.Nil(t, err)
keysMap := make(map[string]crypto.PrivateKey)
keysMap[string(pk1Bytes)] = sk1
keysMap[string(pk2Bytes)] = sk2
return keysMap
},
}
peerAuthSender, err := createPeerAuthenticationSender(args)
assert.Nil(t, err)
assert.False(t, check.IfNil(peerAuth))

_, ok := peerAuth.(*multikeyPeerAuthenticationSender)
assert.True(t, ok)
assert.False(t, check.IfNil(peerAuthSender))
assert.Equal(t, "*sender.multikeyPeerAuthenticationSender", fmt.Sprintf("%T", peerAuthSender))
})

}
9 changes: 2 additions & 7 deletions heartbeat/sender/sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func NewSender(args ArgSender) (*sender, error) {
return nil, err
}

peerAuthSenderFactory, err := newPeerAuthenticationSenderFactory(argPeerAuthenticationSenderFactory{
pas, err := createPeerAuthenticationSender(argPeerAuthenticationSenderFactory{
argBaseSender: argBaseSender{
messenger: args.Messenger,
marshaller: args.Marshaller,
Expand All @@ -75,11 +75,6 @@ func NewSender(args ArgSender) (*sender, error) {
return nil, err
}

pas, err := peerAuthSenderFactory.create()
if err != nil {
return nil, err
}

hbs, err := newHeartbeatSender(argHeartbeatSender{
argBaseSender: argBaseSender{
messenger: args.Messenger,
Expand All @@ -105,7 +100,7 @@ func NewSender(args ArgSender) (*sender, error) {
}

func checkSenderArgs(args ArgSender) error {
// Only check base sender args, as further checks are done on factory Create, based on the type of sender
// Only check base sender args, as further checks are done on constructors, based on the type of sender
baseSenderArgs := argBaseSender{
messenger: args.Messenger,
marshaller: args.Marshaller,
Expand Down