Skip to content

Commit

Permalink
Merge branch 'stage' into gm/pass_static_domain_to_runners
Browse files Browse the repository at this point in the history
  • Loading branch information
moshe-blox committed Aug 11, 2024
2 parents d5809fd + dc37c19 commit ef60d3b
Show file tree
Hide file tree
Showing 23 changed files with 297 additions and 102 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/genesis-spec-alignment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Genesis Spec Alignment

on:
push:
branches:
- "**"

jobs:
align:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v3

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: "1.20.x"

- name: Tidy up dependencies
run: go mod tidy

- name: Install Differ
run: cd ./scripts/differ && go install .

- name: Run Differ
run: cd ./scripts/spec-alignment && ./genesis_differ.sh

- name: Upload genesis_output.diff
if: failure()
uses: actions/upload-artifact@v3
with:
name: genesis_output.diff
path: ./scripts/spec-alignment/genesis_output.diff
8 changes: 5 additions & 3 deletions message/validation/fork.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ func (f *ForkingMessageValidation) Validate(ctx context.Context, p peer.ID, pmsg
}

func (f *ForkingMessageValidation) ValidatorForTopic(topic string) func(ctx context.Context, p peer.ID, pmsg *pubsub.Message) pubsub.ValidationResult {
if f.NetworkConfig.PastAlanFork() {
return f.Alan.ValidatorForTopic(topic)
return func(ctx context.Context, p peer.ID, pmsg *pubsub.Message) pubsub.ValidationResult {
if f.NetworkConfig.PastAlanFork() {
return f.Alan.ValidatorForTopic(topic)(ctx, p, pmsg)
}
return f.Genesis.ValidatorForTopic(topic)(ctx, p, pmsg)
}
return f.Genesis.ValidatorForTopic(topic)
}
4 changes: 3 additions & 1 deletion network/p2p/p2p_setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,10 @@ func (n *p2pNetwork) setupPeerServices(logger *zap.Logger) error {
}

filters := func() []connections.HandshakeFilter {
newDomain := n.cfg.Network.DomainType()
newDomainString := "0x" + hex.EncodeToString(newDomain[:])
return []connections.HandshakeFilter{
connections.NetworkIDFilter(domain),
connections.NetworkIDFilter(newDomainString),
}
}

Expand Down
34 changes: 21 additions & 13 deletions network/p2p/p2p_validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
spectypes "github.com/ssvlabs/ssv-spec/types"
spectestingutils "github.com/ssvlabs/ssv-spec/types/testingutils"
"github.com/stretchr/testify/require"
"golang.org/x/exp/slices"

"github.com/ssvlabs/ssv/message/validation"
beaconprotocol "github.com/ssvlabs/ssv/protocol/v2/blockchain/beacon"
Expand Down Expand Up @@ -144,7 +145,7 @@ func TestP2pNetwork_MessageValidation(t *testing.T) {
require.NoError(t, vNet.Close())
}()

time.Sleep(5 * time.Second)
time.Sleep(1 * time.Second)

// Prepare a pool of broadcasters.
mu := sync.Mutex{}
Expand All @@ -153,7 +154,7 @@ func TestP2pNetwork_MessageValidation(t *testing.T) {
broadcasters := pool.New().WithErrors().WithContext(ctx)
broadcaster := func(node *VirtualNode, roles ...spectypes.RunnerRole) {
broadcasters.Go(func(ctx context.Context) error {
for i := 0; i < 50; i++ {
for i := 0; i < 12; i++ {
role := roles[i%len(roles)]

mu.Lock()
Expand All @@ -176,20 +177,32 @@ func TestP2pNetwork_MessageValidation(t *testing.T) {
// - node 1 broadcasts ignored messages.
// - node 2 broadcasts rejected messages.
// - node 3 broadcasts all messages (equal distribution).
broadcaster(vNet.Nodes[0], acceptedRole)
broadcaster(vNet.Nodes[1], ignoredRole)
broadcaster(vNet.Nodes[2], rejectedRole)
broadcaster(vNet.Nodes[3], acceptedRole, ignoredRole, rejectedRole)
messageTypesByNodeIndex := map[int][]spectypes.RunnerRole{
0: {acceptedRole},
1: {ignoredRole},
2: {rejectedRole},
3: {acceptedRole, ignoredRole, rejectedRole},
}

for i := 0; i < nodeCount; i++ {
broadcaster(vNet.Nodes[i], messageTypesByNodeIndex[i]...)
}

// Wait for the broadcasters to finish.
err := broadcasters.Wait()
require.NoError(t, err)
time.Sleep(1 * time.Second)

// Assert that the messages were distributed as expected.
deadline := time.Now().Add(7 * time.Second)
time.Sleep(7 * time.Second)

interval := 100 * time.Millisecond
for i := 0; i < nodeCount; i++ {
// Messages from nodes broadcasting rejected role become rejected once score threshold is reached
if slices.Contains(messageTypesByNodeIndex[i], rejectedRole) {
continue
}

// better lock inside loop than wait interval locked
mtx.Lock()
var errors []error
Expand All @@ -203,12 +216,7 @@ func TestP2pNetwork_MessageValidation(t *testing.T) {
errors = append(errors, fmt.Errorf("node %d rejected %d messages (expected %d)", i, messageValidators[i].TotalRejected, roleBroadcasts[rejectedRole]))
}
mtx.Unlock()
if len(errors) == 0 {
break
}
if time.Now().After(deadline) {
require.Empty(t, errors)
}
require.Empty(t, errors)
time.Sleep(interval)
}

Expand Down
17 changes: 12 additions & 5 deletions network/p2p/test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,14 +155,21 @@ func (ln *LocalNet) NewTestP2pNetwork(ctx context.Context, nodeIndex int, keys t

for _, share := range options.Shares {
for _, sm := range share.Committee {
_, err := nodeStorage.SaveOperatorData(nil, &registrystorage.OperatorData{
ID: sm.Signer,
PublicKey: operatorPubkey,
OwnerAddress: common.BytesToAddress([]byte("testOwnerAddress")),
})
_, ok, err := nodeStorage.GetOperatorData(nil, sm.Signer)
if err != nil {
return nil, err
}

if !ok {
_, err := nodeStorage.SaveOperatorData(nil, &registrystorage.OperatorData{
ID: sm.Signer,
PublicKey: operatorPubkey,
OwnerAddress: common.BytesToAddress([]byte("testOwnerAddress")),
})
if err != nil {
return nil, err
}
}
}
}

Expand Down
10 changes: 4 additions & 6 deletions operator/validator/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -1488,10 +1488,9 @@ func SetupGenesisRunners(ctx context.Context, logger *zap.Logger, options valida
leader := genesisspecqbft.RoundRobinProposer(state, round)
return leader
},
Storage: options.GenesisOptions.Storage.Get(role),
Network: options.GenesisOptions.Network,
Timer: genesisroundtimer.New(ctx, options.NetworkConfig.Beacon, role, nil),
SignatureVerification: true,
Storage: options.GenesisOptions.Storage.Get(role),
Network: options.GenesisOptions.Network,
Timer: genesisroundtimer.New(ctx, options.NetworkConfig.Beacon, role, nil),
}
config.ValueCheckF = valueCheckF
identifier := genesisspectypes.NewMsgID(genesisssvtypes.GetDefaultDomain(), options.SSVShare.Share.ValidatorPubKey[:], role)
Expand Down Expand Up @@ -1528,8 +1527,7 @@ func SetupGenesisRunners(ctx context.Context, logger *zap.Logger, options valida
qbftCtrl := buildController(genesisspectypes.BNRoleSyncCommitteeContribution, syncCommitteeContributionValueCheckF)
runners[role] = genesisrunner.NewSyncCommitteeAggregatorRunner(genesisDomainType, genesisBeaconNetwork, share, qbftCtrl, options.GenesisBeacon, options.GenesisOptions.Network, options.GenesisOptions.Signer, syncCommitteeContributionValueCheckF, 0)
case genesisspectypes.BNRoleValidatorRegistration:
qbftCtrl := buildController(genesisspectypes.BNRoleValidatorRegistration, nil)
runners[role] = genesisrunner.NewValidatorRegistrationRunner(genesisDomainType, genesisBeaconNetwork, share, qbftCtrl, options.GenesisBeacon, options.GenesisOptions.Network, options.GenesisOptions.Signer)
runners[role] = genesisrunner.NewValidatorRegistrationRunner(genesisDomainType, genesisBeaconNetwork, share, options.GenesisBeacon, options.GenesisOptions.Network, options.GenesisOptions.Signer)
case genesisspectypes.BNRoleVoluntaryExit:
runners[role] = genesisrunner.NewVoluntaryExitRunner(genesisDomainType, genesisBeaconNetwork, share, options.GenesisBeacon, options.GenesisOptions.Network, options.GenesisOptions.Signer)
}
Expand Down
23 changes: 8 additions & 15 deletions protocol/genesis/qbft/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,17 @@ type IConfig interface {
GetStorage() qbftstorage.QBFTStore
// GetTimer returns round timer
GetTimer() roundtimer.Timer
// VerifySignatures returns if signature is checked
VerifySignatures() bool
}

type Config struct {
Signer genesisspectypes.SSVSigner
SigningPK []byte
Domain genesisspectypes.DomainType
ValueCheckF genesisspecqbft.ProposedValueCheckF
ProposerF genesisspecqbft.ProposerF
Storage qbftstorage.QBFTStore
Network genesisspecqbft.Network
Timer roundtimer.Timer
SignatureVerification bool
Signer genesisspectypes.SSVSigner
SigningPK []byte
Domain genesisspectypes.DomainType
ValueCheckF genesisspecqbft.ProposedValueCheckF
ProposerF genesisspecqbft.ProposerF
Storage qbftstorage.QBFTStore
Network genesisspecqbft.Network
Timer roundtimer.Timer
}

// GetSigner returns a Signer instance
Expand Down Expand Up @@ -82,7 +79,3 @@ func (c *Config) GetStorage() qbftstorage.QBFTStore {
func (c *Config) GetTimer() roundtimer.Timer {
return c.Timer
}

func (c *Config) VerifySignatures() bool {
return c.SignatureVerification
}
6 changes: 2 additions & 4 deletions protocol/genesis/qbft/instance/commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,8 @@ func BaseCommitValidation(
return errors.Wrap(err, "signed commit invalid")
}

if config.VerifySignatures() {
if err := types.VerifyByOperators(signedCommit.Signature, signedCommit, config.GetSignatureDomainType(), genesisspectypes.QBFTSignatureType, operators); err != nil {
return errors.Wrap(err, "msg signature invalid")
}
if err := types.VerifyByOperators(signedCommit.Signature, signedCommit, config.GetSignatureDomainType(), genesisspectypes.QBFTSignatureType, operators); err != nil {
return errors.Wrap(err, "msg signature invalid")
}

return nil
Expand Down
6 changes: 2 additions & 4 deletions protocol/genesis/qbft/instance/prepare.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,8 @@ func validSignedPrepareForHeightRoundAndRoot(
return errors.New("msg allows 1 signer")
}

if config.VerifySignatures() {
if err := types.VerifyByOperators(signedPrepare.Signature, signedPrepare, config.GetSignatureDomainType(), genesisspectypes.QBFTSignatureType, operators); err != nil {
return errors.Wrap(err, "msg signature invalid")
}
if err := types.VerifyByOperators(signedPrepare.Signature, signedPrepare, config.GetSignatureDomainType(), genesisspectypes.QBFTSignatureType, operators); err != nil {
return errors.Wrap(err, "msg signature invalid")
}

return nil
Expand Down
6 changes: 2 additions & 4 deletions protocol/genesis/qbft/instance/proposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,8 @@ func isValidProposal(
if len(signedProposal.GetSigners()) != 1 {
return errors.New("msg allows 1 signer")
}
if config.VerifySignatures() {
if err := genesisssvtypes.VerifyByOperators(signedProposal.Signature, signedProposal, config.GetSignatureDomainType(), genesisspectypes.QBFTSignatureType, operators); err != nil {
return errors.Wrap(err, "msg signature invalid")
}
if err := genesisssvtypes.VerifyByOperators(signedProposal.Signature, signedProposal, config.GetSignatureDomainType(), genesisspectypes.QBFTSignatureType, operators); err != nil {
return errors.Wrap(err, "msg signature invalid")
}
if !signedProposal.MatchedSigners([]genesisspectypes.OperatorID{proposer(state, config, signedProposal.Message.Round)}) {
return errors.New("proposal leader invalid")
Expand Down
6 changes: 2 additions & 4 deletions protocol/genesis/qbft/instance/round_change.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,10 +260,8 @@ func validRoundChangeForData(
return errors.New("msg allows 1 signer")
}

if config.VerifySignatures() {
if err := types.VerifyByOperators(signedMsg.Signature, signedMsg, config.GetSignatureDomainType(), genesisspectypes.QBFTSignatureType, state.Share.Committee); err != nil {
return errors.Wrap(err, "msg signature invalid")
}
if err := types.VerifyByOperators(signedMsg.Signature, signedMsg, config.GetSignatureDomainType(), genesisspectypes.QBFTSignatureType, state.Share.Committee); err != nil {
return errors.Wrap(err, "msg signature invalid")
}

if err := signedMsg.Message.Validate(); err != nil {
Expand Down
7 changes: 3 additions & 4 deletions protocol/genesis/qbft/testing/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,9 @@ var TestingConfig = func(logger *zap.Logger, keySet *testingutils.TestKeySet, ro
ProposerF: func(state *genesisspecqbft.State, round genesisspecqbft.Round) genesisspectypes.OperatorID {
return 1
},
Storage: TestingStores(logger).Get(role),
Network: testingutils.NewTestingNetwork(),
Timer: roundtimer.NewTestingTimer(),
SignatureVerification: true,
Storage: TestingStores(logger).Get(role),
Network: testingutils.NewTestingNetwork(),
Timer: roundtimer.NewTestingTimer(),
}
}

Expand Down
4 changes: 1 addition & 3 deletions protocol/genesis/ssv/runner/validator_registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"crypto/sha256"
"encoding/hex"
"encoding/json"

spectypes "github.com/ssvlabs/ssv-spec/types"

v1 "github.com/attestantio/go-eth2-client/api/v1"
Expand All @@ -16,7 +17,6 @@ import (
"go.uber.org/zap"

"github.com/ssvlabs/ssv/logging/fields"
"github.com/ssvlabs/ssv/protocol/genesis/qbft/controller"
"github.com/ssvlabs/ssv/protocol/genesis/ssv/runner/metrics"
)

Expand All @@ -35,7 +35,6 @@ func NewValidatorRegistrationRunner(
domainType spectypes.DomainType,
beaconNetwork genesisspectypes.BeaconNetwork,
share *genesisspectypes.Share,
qbftController *controller.Controller,
beacon genesisspecssv.BeaconNode,
network genesisspecssv.Network,
signer genesisspectypes.KeyManager,
Expand All @@ -46,7 +45,6 @@ func NewValidatorRegistrationRunner(
DomainType: domainType,
BeaconNetwork: beaconNetwork,
Share: share,
QBFTController: qbftController,
},

beacon: beacon,
Expand Down
1 change: 0 additions & 1 deletion protocol/genesis/ssv/testing/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ var baseRunner = func(logger *zap.Logger, role genesisspectypes.BeaconRole, valC
networkconfig.TestNetwork.GenesisDomainType,
genesisspectypes.BeaconTestNetwork,
share,
contr,
spectestingutils.NewTestingBeaconNode(),
net,
km,
Expand Down
13 changes: 6 additions & 7 deletions protocol/v2/qbft/instance/prepare.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ func (i *Instance) uponPrepare(logger *zap.Logger, msg *specqbft.ProcessingMessa
return nil // uponPrepare was already called
}

proposedRoot := i.State.ProposalAcceptedForCurrentRound.QBFTMessage.Root
logger.Debug("📬 got prepare message",
fields.Round(i.State.Round),
zap.Any("prepare-signers", i.State.ProposalAcceptedForCurrentRound.SignedMessage.OperatorIDs),
fields.Root(proposedRoot))

if hasQuorumBefore {
return nil // already moved to commit stage
}
Expand All @@ -34,13 +40,6 @@ func (i *Instance) uponPrepare(logger *zap.Logger, msg *specqbft.ProcessingMessa
return nil // no quorum yet
}

proposedRoot := i.State.ProposalAcceptedForCurrentRound.QBFTMessage.Root

logger.Debug("📬 got prepare message",
fields.Round(i.State.Round),
zap.Any("prepare-signers", i.State.ProposalAcceptedForCurrentRound.SignedMessage.OperatorIDs),
fields.Root(proposedRoot))

i.State.LastPreparedValue = i.State.ProposalAcceptedForCurrentRound.SignedMessage.FullData
i.State.LastPreparedRound = i.State.Round

Expand Down
3 changes: 2 additions & 1 deletion protocol/v2/ssv/runner/proposer.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ func (r *ProposerRunner) ProcessPostConsensus(logger *zap.Logger, signedMsg *spe
r.metrics.EndPostConsensus()
logger.Debug("🧩 reconstructed partial post consensus signatures proposer",
zap.Uint64s("signers", getPostConsensusProposerSigners(r.GetState(), root)),
fields.PostConsensusTime(r.metrics.GetPostConsensusTime()))
fields.PostConsensusTime(r.metrics.GetPostConsensusTime()),
fields.Round(r.GetState().RunningInstance.State.Round))
endSubmission := r.metrics.StartBeaconSubmission()

validatorConsensusData := &spectypes.ValidatorConsensusData{}
Expand Down
12 changes: 9 additions & 3 deletions registry/storage/shares.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,18 +240,24 @@ func (s *sharesStorage) unsafeSave(rw basedb.ReadWriter, shares ...*types.SSVSha
return err
}

updateShares := make([]*types.SSVShare, 0, len(shares))
addShares := make([]*types.SSVShare, 0, len(shares))

for _, share := range shares {
key := hex.EncodeToString(share.ValidatorPubKey[:])

// Update validatorStore indices.
if _, ok := s.shares[key]; ok {
s.validatorStore.handleShareUpdated(share)
updateShares = append(updateShares, share)
} else {
s.validatorStore.handleSharesAdded(share)
addShares = append(addShares, share)
}

s.shares[key] = share
}

s.validatorStore.handleSharesUpdated(updateShares...)
s.validatorStore.handleSharesAdded(addShares...)

return nil
}

Expand Down
Loading

0 comments on commit ef60d3b

Please sign in to comment.