Skip to content

Commit

Permalink
proposals: dont accept proposals from future (#5065)
Browse files Browse the repository at this point in the history
closes: #4834

no reason to gate ballots, as we request them with sync, so they won't be downloaded
  • Loading branch information
dshulyak committed Sep 22, 2023
1 parent c51f2a1 commit 801073f
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 11 deletions.
11 changes: 6 additions & 5 deletions proposals/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,12 +259,13 @@ func (h *Handler) handleProposal(ctx context.Context, expHash types.Hash32, peer
}
if p.Layer <= types.GetEffectiveGenesis() {
preGenesis.Inc()
return fmt.Errorf("proposal before effective genesis: layer %v", p.Layer)
}
if p.Layer <= h.mesh.ProcessedLayer() {
// old proposals have no use for the node
return fmt.Errorf("proposal before effective genesis: %d/%s", p.Layer, p.ID().String())
} else if p.Layer <= h.mesh.ProcessedLayer() {
tooLate.Inc()
return fmt.Errorf("proposal too late: layer %v", p.Layer)
return fmt.Errorf("proposal too late: %d/%s", p.Layer, p.ID().String())
} else if p.Layer >= h.clock.CurrentLayer()+1 {
tooFuture.Inc()
return fmt.Errorf("proposal from future: %d/%s", p.Layer, p.ID().String())
}

latency := receivedTime.Sub(h.clock.LayerToTime(p.Layer))
Expand Down
28 changes: 22 additions & 6 deletions proposals/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,13 @@ func withTransactions(ids ...types.TransactionID) createProposalOpt {
}
}

func withProposalLayer(layer types.LayerID) createProposalOpt {
return func(p *types.Proposal) {
p.Layer = layer
p.Ballot.Layer = layer
}
}

func createProposal(t *testing.T, opts ...any) *types.Proposal {
t.Helper()
b := types.RandomBallot()
Expand Down Expand Up @@ -844,7 +851,7 @@ func TestBallot_DecodedStoreFailure(t *testing.T) {

func TestProposal_MalformedData(t *testing.T) {
th := createTestHandlerNoopDecoder(t)
p := createProposal(t)
p := createProposal(t, withProposalLayer(th.clock.CurrentLayer()))
data, err := codec.Encode(&p.InnerProposal)
require.NoError(t, err)
require.ErrorIs(t, th.HandleSyncedProposal(context.Background(), p.ID().AsHash32(), p2p.NoPeer, data), errMalformedData)
Expand All @@ -854,7 +861,7 @@ func TestProposal_MalformedData(t *testing.T) {

func TestProposal_BeforeEffectiveGenesis(t *testing.T) {
th := createTestHandlerNoopDecoder(t)
p := createProposal(t)
p := createProposal(t, withProposalLayer(th.clock.CurrentLayer()))
p.Layer = types.GetEffectiveGenesis()
data := encodeProposal(t, p)
got := th.HandleSyncedProposal(context.Background(), p.ID().AsHash32(), p2p.NoPeer, data)
Expand All @@ -868,7 +875,7 @@ func TestProposal_TooOld(t *testing.T) {
th := createTestHandlerNoopDecoder(t)
lid := types.LayerID(11)
th.mockSet.setCurrentLayer(lid)
p := createProposal(t)
p := createProposal(t, withProposalLayer(th.clock.CurrentLayer()))
p.Layer = lid - 1
data := encodeProposal(t, p)
got := th.HandleSyncedProposal(context.Background(), p.ID().AsHash32(), p2p.NoPeer, data)
Expand All @@ -878,9 +885,17 @@ func TestProposal_TooOld(t *testing.T) {
checkProposal(t, th.cdb, p, false)
}

func TestProposal_TooFuture(t *testing.T) {
th := createTestHandlerNoopDecoder(t)
p := createProposal(t, withProposalLayer(th.clock.CurrentLayer()+10))
data := encodeProposal(t, p)
got := th.HandleSyncedProposal(context.Background(), p.ID().AsHash32(), p2p.NoPeer, data)
require.ErrorContains(t, got, "proposal from future")
}

func TestProposal_BadSignature(t *testing.T) {
th := createTestHandlerNoopDecoder(t)
p := createProposal(t)
p := createProposal(t, withProposalLayer(th.clock.CurrentLayer()))
p.Signature = types.EmptyEdSignature
data := encodeProposal(t, p)
got := th.HandleSyncedProposal(context.Background(), p.ID().AsHash32(), p2p.NoPeer, data)
Expand Down Expand Up @@ -918,7 +933,7 @@ func TestProposal_InconsistentSmeshers(t *testing.T) {

func TestProposal_WrongHash(t *testing.T) {
th := createTestHandlerNoopDecoder(t)
p := createProposal(t)
p := createProposal(t, withProposalLayer(th.clock.CurrentLayer()))
data := encodeProposal(t, p)
err := th.HandleSyncedProposal(context.Background(), types.RandomHash(), p2p.NoPeer, data)
require.ErrorIs(t, err, errWrongHash)
Expand All @@ -927,7 +942,7 @@ func TestProposal_WrongHash(t *testing.T) {

func TestProposal_KnownProposal(t *testing.T) {
th := createTestHandlerNoopDecoder(t)
p := createProposal(t)
p := createProposal(t, withProposalLayer(th.clock.CurrentLayer()))
createAtx(t, th.cdb.Database, p.Layer.GetEpoch()-1, p.AtxID, p.SmesherID)
require.NoError(t, ballots.Add(th.cdb, &p.Ballot))
require.NoError(t, proposals.Add(th.cdb, p))
Expand Down Expand Up @@ -1430,6 +1445,7 @@ func TestHandleSyncedProposalActiveSet(t *testing.T) {
th := createTestHandler(t)
pid := p2p.Peer("any")

th.mclock.EXPECT().CurrentLayer().Return(lid).AnyTimes()
th.mm.EXPECT().ProcessedLayer().Return(lid - 2).AnyTimes()
th.mclock.EXPECT().LayerToTime(gomock.Any())
th.mf.EXPECT().RegisterPeerHashes(pid, gomock.Any()).AnyTimes()
Expand Down
1 change: 1 addition & 0 deletions proposals/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ var (
failedInit = processErrors.WithLabelValues("init")
known = processErrors.WithLabelValues("known")
tooLate = processErrors.WithLabelValues("late")
tooFuture = processErrors.WithLabelValues("future")
preGenesis = processErrors.WithLabelValues("genesis")
badSigProposal = processErrors.WithLabelValues("sigp")
badSigBallot = processErrors.WithLabelValues("sigb")
Expand Down

0 comments on commit 801073f

Please sign in to comment.