From 9f827d86a678e1b751dbc7ded97d9d8f84c5e874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Mon, 13 May 2024 14:00:17 +0000 Subject: [PATCH] Fix caching malfeasance info in atxsdata store (#5932) ## Motivation Hare depends on `atxsdata` to check whether a smesher is considered malicious. --- datastore/store.go | 13 +++++++++++-- datastore/store_test.go | 14 ++++++++++++++ malfeasance/handler_test.go | 10 +++++++++- node/node.go | 1 + 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/datastore/store.go b/datastore/store.go index ac44f47dce..e18487cdf0 100644 --- a/datastore/store.go +++ b/datastore/store.go @@ -44,7 +44,8 @@ type CachedDB struct { sql.QueryCache logger log.Log - // cache is optional + // cache is optional in tests. It MUST be set for the 'App' + // for properly checking malfeasance. atxsdata *atxsdata.Data atxCache *lru.Cache[types.ATXID, *types.ActivationTx] @@ -71,7 +72,8 @@ func DefaultConfig() Config { } type cacheOpts struct { - cfg Config + cfg Config + atxsdata *atxsdata.Data } type Opt func(*cacheOpts) @@ -82,6 +84,12 @@ func WithConfig(cfg Config) Opt { } } +func WithConsensusCache(c *atxsdata.Data) Opt { + return func(o *cacheOpts) { + o.atxsdata = c + } +} + // NewCachedDB create an instance of a CachedDB. func NewCachedDB(db Executor, lg log.Log, opts ...Opt) *CachedDB { o := cacheOpts{cfg: DefaultConfig()} @@ -109,6 +117,7 @@ func NewCachedDB(db Executor, lg log.Log, opts ...Opt) *CachedDB { Executor: db, QueryCache: db.QueryCache(), logger: lg, + atxsdata: o.atxsdata, atxCache: atxHdrCache, malfeasanceCache: malfeasanceCache, vrfNonceCache: vrfNonceCache, diff --git a/datastore/store_test.go b/datastore/store_test.go index 2e0459e8ed..d6ab5db639 100644 --- a/datastore/store_test.go +++ b/datastore/store_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/spacemeshos/go-spacemesh/activation/wire" + "github.com/spacemeshos/go-spacemesh/atxsdata" "github.com/spacemeshos/go-spacemesh/codec" "github.com/spacemeshos/go-spacemesh/common/fixture" "github.com/spacemeshos/go-spacemesh/common/types" @@ -406,3 +407,16 @@ func TestBlobStore_GetActiveSet(t *testing.T) { require.NoError(t, err) require.Equal(t, codec.MustEncode(as), got) } + +func Test_MarkingMalicious(t *testing.T) { + db := sql.InMemory() + store := atxsdata.New() + id := types.RandomNodeID() + cdb := datastore.NewCachedDB(db, logtest.New(t), datastore.WithConsensusCache(store)) + + cdb.CacheMalfeasanceProof(id, &mwire.MalfeasanceProof{}) + m, err := cdb.IsMalicious(id) + require.NoError(t, err) + require.True(t, m) + require.True(t, store.IsMalicious(id)) +} diff --git a/malfeasance/handler_test.go b/malfeasance/handler_test.go index 42bc507738..0dcc190e99 100644 --- a/malfeasance/handler_test.go +++ b/malfeasance/handler_test.go @@ -12,6 +12,7 @@ import ( "go.uber.org/mock/gomock" awire "github.com/spacemeshos/go-spacemesh/activation/wire" + "github.com/spacemeshos/go-spacemesh/atxsdata" "github.com/spacemeshos/go-spacemesh/codec" "github.com/spacemeshos/go-spacemesh/common/types" "github.com/spacemeshos/go-spacemesh/datastore" @@ -51,8 +52,9 @@ func TestHandler_HandleMalfeasanceProof_multipleATXs(t *testing.T) { trt := malfeasance.NewMocktortoise(ctrl) postVerifier := malfeasance.NewMockpostVerifier(ctrl) + store := atxsdata.New() h := malfeasance.NewHandler( - datastore.NewCachedDB(db, lg), + datastore.NewCachedDB(db, lg, datastore.WithConsensusCache(store)), lg, "self", []types.NodeID{types.RandomNodeID()}, @@ -103,6 +105,7 @@ func TestHandler_HandleMalfeasanceProof_multipleATXs(t *testing.T) { malProof, err := identities.GetMalfeasanceProof(db, sig.NodeID()) require.ErrorIs(t, err, sql.ErrNotFound) require.Nil(t, malProof) + require.False(t, store.IsMalicious(sig.NodeID())) }) createIdentity(t, db, sig) @@ -130,6 +133,7 @@ func TestHandler_HandleMalfeasanceProof_multipleATXs(t *testing.T) { malProof, err := identities.GetMalfeasanceProof(db, sig.NodeID()) require.ErrorIs(t, err, sql.ErrNotFound) require.Nil(t, malProof) + require.False(t, store.IsMalicious(sig.NodeID())) }) t.Run("different epoch", func(t *testing.T) { @@ -153,6 +157,7 @@ func TestHandler_HandleMalfeasanceProof_multipleATXs(t *testing.T) { malProof, err := identities.GetMalfeasanceProof(db, sig.NodeID()) require.ErrorIs(t, err, sql.ErrNotFound) require.Nil(t, malProof) + require.False(t, store.IsMalicious(sig.NodeID())) }) t.Run("different signer", func(t *testing.T) { @@ -177,6 +182,7 @@ func TestHandler_HandleMalfeasanceProof_multipleATXs(t *testing.T) { malProof, err := identities.GetMalfeasanceProof(db, sig.NodeID()) require.ErrorIs(t, err, sql.ErrNotFound) require.Nil(t, malProof) + require.False(t, store.IsMalicious(sig.NodeID())) }) t.Run("invalid hare eligibility", func(t *testing.T) { @@ -198,6 +204,7 @@ func TestHandler_HandleMalfeasanceProof_multipleATXs(t *testing.T) { data, err := codec.Encode(gossip) require.NoError(t, err) require.Error(t, h.HandleMalfeasanceProof(context.Background(), "peer", data)) + require.False(t, store.IsMalicious(sig.NodeID())) }) t.Run("valid", func(t *testing.T) { @@ -225,6 +232,7 @@ func TestHandler_HandleMalfeasanceProof_multipleATXs(t *testing.T) { require.NotNil(t, malProof.Received()) malProof.SetReceived(time.Time{}) require.Equal(t, gossip.MalfeasanceProof, *malProof) + require.True(t, store.IsMalicious(sig.NodeID())) }) t.Run("proof equivalence", func(t *testing.T) { diff --git a/node/node.go b/node/node.go index 72342ef2fd..9afe38fc02 100644 --- a/node/node.go +++ b/node/node.go @@ -1895,6 +1895,7 @@ func (app *App) setupDBs(ctx context.Context, lg log.Log) error { app.log.With().Info("cache warmup", log.Duration("duration", time.Since(start))) app.cachedDB = datastore.NewCachedDB(sqlDB, app.addLogger(CachedDBLogger, lg), datastore.WithConfig(app.Config.Cache), + datastore.WithConsensusCache(data), ) migrations, err = sql.LocalMigrations()