Skip to content

Commit

Permalink
validate malfeasance proof before saving to db (#4535)
Browse files Browse the repository at this point in the history
## Motivation
Closes #4527
  • Loading branch information
countvonzero committed Jun 17, 2023
1 parent 2f7e73e commit 5a38fdc
Show file tree
Hide file tree
Showing 14 changed files with 265 additions and 162 deletions.
5 changes: 4 additions & 1 deletion activation/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/spacemeshos/go-spacemesh/datastore"
"github.com/spacemeshos/go-spacemesh/events"
"github.com/spacemeshos/go-spacemesh/log"
"github.com/spacemeshos/go-spacemesh/malfeasance"
"github.com/spacemeshos/go-spacemesh/metrics"
"github.com/spacemeshos/go-spacemesh/p2p"
"github.com/spacemeshos/go-spacemesh/p2p/pubsub"
Expand Down Expand Up @@ -384,7 +385,9 @@ func (h *Handler) storeAtx(ctx context.Context, atx *types.VerifiedActivationTx)
Data: &atxProof,
},
}
if err := h.cdb.AddMalfeasanceProof(atx.SmesherID, proof, dbtx); err != nil {
if err := malfeasance.ValidateAndSave(ctx, h.log, h.cdb, dbtx, h.edVerifier, nil, &types.MalfeasanceGossip{
MalfeasanceProof: *proof,
}); err != nil && !errors.Is(err, malfeasance.ErrKnownProof) {
return fmt.Errorf("adding malfeasance proof: %w", err)
}
h.log.WithContext(ctx).With().Warning("smesher produced more than one atx in the same epoch",
Expand Down
7 changes: 1 addition & 6 deletions datastore/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ func (db *CachedDB) GetMalfeasanceProof(id types.NodeID) (*types.MalfeasanceProo
return proof, err
}

func (db *CachedDB) AddMalfeasanceProof(id types.NodeID, proof *types.MalfeasanceProof, dbtx *sql.Tx) error {
func (db *CachedDB) AddMalfeasanceProof(id types.NodeID, proof *types.MalfeasanceProof, exec sql.Executor) error {
if id == types.EmptyNodeID {
log.Fatal("invalid argument to AddMalfeasanceProof")
}
Expand All @@ -132,11 +132,6 @@ func (db *CachedDB) AddMalfeasanceProof(id types.NodeID, proof *types.Malfeasanc
db.logger.Fatal("failed to encode MalfeasanceProof")
}

var exec sql.Executor = db
if dbtx != nil {
exec = dbtx
}

db.mu.Lock()
defer db.mu.Unlock()
if err = identities.SetMalicious(exec, id, encoded); err != nil {
Expand Down
4 changes: 2 additions & 2 deletions datastore/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func TestMalfeasanceProof_Honest(t *testing.T) {
},
},
}
require.NoError(t, cdb.AddMalfeasanceProof(nodeID2, proof, nil))
require.NoError(t, cdb.AddMalfeasanceProof(nodeID2, proof, cdb))
bad, err = cdb.IsMalicious(nodeID2)
require.NoError(t, err)
require.True(t, bad)
Expand All @@ -112,7 +112,7 @@ func TestMalfeasanceProof_Dishonest(t *testing.T) {
}

nodeID1 := types.NodeID{1}
require.NoError(t, cdb.AddMalfeasanceProof(nodeID1, proof, nil))
require.NoError(t, cdb.AddMalfeasanceProof(nodeID1, proof, cdb))
require.Equal(t, 1, cdb.MalfeasanceCacheSize())

got, err := cdb.GetMalfeasanceProof(nodeID1)
Expand Down
26 changes: 10 additions & 16 deletions hare/hare.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/spacemeshos/go-spacemesh/datastore"
"github.com/spacemeshos/go-spacemesh/hare/config"
"github.com/spacemeshos/go-spacemesh/log"
"github.com/spacemeshos/go-spacemesh/malfeasance"
"github.com/spacemeshos/go-spacemesh/p2p/pubsub"
"github.com/spacemeshos/go-spacemesh/signing"
"github.com/spacemeshos/go-spacemesh/sql"
Expand Down Expand Up @@ -80,6 +81,10 @@ func (m defaultMesh) Ballot(bid types.BallotID) (*types.Ballot, error) {
return ballots.Get(m, bid)
}

func (m defaultMesh) Cache() *datastore.CachedDB {
return m.CachedDB
}

// Opt for configuring beacon protocol.
type Opt func(*Hare)

Expand Down Expand Up @@ -120,7 +125,8 @@ type Hare struct {

factory consensusFactory

nodeID types.NodeID
nodeID types.NodeID
sigVerifier malfeasance.SigVerifier

ctx context.Context
cancel context.CancelFunc
Expand Down Expand Up @@ -184,6 +190,7 @@ func New(
}

h.nodeID = nid
h.sigVerifier = edVerifier
h.ctx, h.cancel = context.WithCancel(context.Background())

for _, opt := range opts {
Expand Down Expand Up @@ -625,21 +632,8 @@ func (h *Hare) malfeasanceLoop(ctx context.Context) {
if gossip.Eligibility == nil {
h.WithContext(ctx).Fatal("missing hare eligibility")
}
if malicious, err := h.msh.IsMalicious(gossip.Eligibility.NodeID); err != nil {
h.With().Error("failed to check identity",
log.Context(ctx),
gossip.Eligibility.NodeID,
log.Err(err),
)
continue
} else if malicious {
h.With().Debug("known malicious identity",
log.Context(ctx),
gossip.Eligibility.NodeID,
)
continue
}
if err := h.msh.AddMalfeasanceProof(gossip.Eligibility.NodeID, &gossip.MalfeasanceProof, nil); err != nil {
if err := malfeasance.ValidateAndSave(
ctx, h.Log, h.msh.Cache(), h.msh.Cache(), h.sigVerifier, nil, gossip); err != nil && !errors.Is(err, malfeasance.ErrKnownProof) {
h.With().Error("failed to save MalfeasanceProof",
log.Context(ctx),
gossip.Eligibility.NodeID,
Expand Down
52 changes: 30 additions & 22 deletions hare/hare_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,31 +222,40 @@ func TestHare_malfeasanceLoop(t *testing.T) {
lid := types.LayerID(11)
round := uint32(3)

sig, err := signing.NewEdSigner()
require.NoError(t, err)
cdb := datastore.NewCachedDB(sql.InMemory(), h.Log)
createIdentity(t, cdb.Database, sig)
proof := &types.HareProof{
Messages: [2]types.HareProofMsg{
{
InnerMsg: types.HareMetadata{
Layer: lid,
Round: round,
MsgHash: types.RandomHash(),
},
SmesherID: sig.NodeID(),
Signature: types.RandomEdSignature(),
},
{
InnerMsg: types.HareMetadata{
Layer: lid,
Round: round,
MsgHash: types.RandomHash(),
},
SmesherID: sig.NodeID(),
Signature: types.RandomEdSignature(),
},
},
}
proof.Messages[0].Signature = sig.Sign(signing.HARE, proof.Messages[0].SignedBytes())
proof.Messages[1].Signature = sig.Sign(signing.HARE, proof.Messages[1].SignedBytes())
gossip := types.MalfeasanceGossip{
MalfeasanceProof: types.MalfeasanceProof{
Layer: lid,
Proof: types.Proof{
Type: types.HareEquivocation,
Data: &types.HareProof{
Messages: [2]types.HareProofMsg{
{
InnerMsg: types.HareMetadata{
Layer: lid,
Round: round,
MsgHash: types.RandomHash(),
},
Signature: types.RandomEdSignature(),
},
{
InnerMsg: types.HareMetadata{
Layer: lid,
Round: round,
MsgHash: types.RandomHash(),
},
Signature: types.RandomEdSignature(),
},
},
},
Data: proof,
},
},
Eligibility: &types.HareEligibilityGossip{
Expand All @@ -263,8 +272,7 @@ func TestHare_malfeasanceLoop(t *testing.T) {
data, err := codec.Encode(&gossip)
require.NoError(t, err)
done := make(chan struct{})
mockMesh.EXPECT().IsMalicious(gossip.Eligibility.NodeID).Return(false, nil)
mockMesh.EXPECT().AddMalfeasanceProof(gossip.Eligibility.NodeID, &gossip.MalfeasanceProof, nil).Return(nil)
mockMesh.EXPECT().Cache().Return(cdb).AnyTimes()
mpubsub.EXPECT().Publish(gomock.Any(), pubsub.MalfeasanceProof, data).DoAndReturn(
func(_ context.Context, _ string, _ []byte) error {
close(done)
Expand Down
5 changes: 2 additions & 3 deletions hare/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"context"

"github.com/spacemeshos/go-spacemesh/common/types"
"github.com/spacemeshos/go-spacemesh/sql"
"github.com/spacemeshos/go-spacemesh/datastore"
)

//go:generate mockgen -package=mocks -destination=./mocks/mocks.go -source=./interfaces.go
Expand Down Expand Up @@ -34,9 +34,8 @@ type mesh interface {
GetAtxHeader(types.ATXID) (*types.ActivationTxHeader, error)
Proposals(types.LayerID) ([]*types.Proposal, error)
Ballot(types.BallotID) (*types.Ballot, error)
IsMalicious(types.NodeID) (bool, error)
AddMalfeasanceProof(types.NodeID, *types.MalfeasanceProof, *sql.Tx) error
GetMalfeasanceProof(nodeID types.NodeID) (*types.MalfeasanceProof, error)
Cache() *datastore.CachedDB
}

type weakCoin interface {
Expand Down
45 changes: 15 additions & 30 deletions hare/mocks/mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 5a38fdc

Please sign in to comment.