From f294fff6f929d93ad9b9634a916ed759b58244a4 Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Thu, 11 Jul 2024 17:25:27 +0700 Subject: [PATCH 01/22] coding --- server/v2/cometbft/abci_test.go | 107 ++++++++++++++++++++++++ server/v2/cometbft/go.mod | 3 + server/v2/cometbft/go.sum | 2 + server/v2/cometbft/mock/mock_reader.go | 67 +++++++++++++++ server/v2/cometbft/mock/mock_store.go | 111 +++++++++++++++++++++++++ store/v2/root/store.go | 2 +- 6 files changed, 291 insertions(+), 1 deletion(-) create mode 100644 server/v2/cometbft/abci_test.go create mode 100644 server/v2/cometbft/mock/mock_reader.go create mode 100644 server/v2/cometbft/mock/mock_store.go diff --git a/server/v2/cometbft/abci_test.go b/server/v2/cometbft/abci_test.go new file mode 100644 index 000000000000..1753eef6587e --- /dev/null +++ b/server/v2/cometbft/abci_test.go @@ -0,0 +1,107 @@ +package cometbft + +import ( + "context" + "testing" + + appmodulev2 "cosmossdk.io/core/appmodule/v2" + "cosmossdk.io/core/log" + corestore "cosmossdk.io/core/store" + "cosmossdk.io/core/transaction" + am "cosmossdk.io/server/v2/appmanager" + ammstore "cosmossdk.io/server/v2/appmanager/store" + "cosmossdk.io/server/v2/cometbft/mempool" + "cosmossdk.io/server/v2/stf" + "cosmossdk.io/server/v2/stf/branch" + "cosmossdk.io/server/v2/stf/mock" + cometmock "cosmossdk.io/server/v2/cometbft/mock" + "cosmossdk.io/store/v2/storage/pebbledb" + abci "github.com/cometbft/cometbft/abci/types" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/types/known/wrapperspb" +) + +func TestConsensus(t *testing.T) { + mockTx := mock.Tx{ + Sender: []byte("sender"), + Msg: wrapperspb.Bool(true), // msg does not matter at all because our handler does nothing. + GasLimit: 100_000, + } + + s, err := stf.NewSTF( + log.NewNopLogger().With("module", "stf"), + stf.NewMsgRouterBuilder(), + stf.NewMsgRouterBuilder(), + func(ctx context.Context, txs []mock.Tx) error { return nil }, + func(ctx context.Context) error { + return kvSet(t, ctx, "begin-block") + }, + func(ctx context.Context) error { + return kvSet(t, ctx, "end-block") + }, + func(ctx context.Context, tx mock.Tx) error { + return kvSet(t, ctx, "validate") + }, + func(ctx context.Context) ([]appmodulev2.ValidatorUpdate, error) { return nil, nil }, + func(ctx context.Context, tx mock.Tx, success bool) error { + return kvSet(t, ctx, "post-tx-exec") + }, + branch.DefaultNewWriterMap, + ) + + ss := cometmock.NewMockStorage(log.NewNopLogger()) + sc := cometmock.NewMockCommiter(log.NewNopLogger()) + mockStore := cometmock.NewMockStore(ss, sc) + + b := am.Builder[mock.Tx]{ + STF: s, + DB: mockStore, + ValidateTxGasLimit: 100_000, + QueryGasLimit: 100_000, + SimulationGasLimit: 100_000, + } + + am, err := b.Build() + require.NoError(t, err) + + + c := NewConsensus[mock.Tx](am, mempool.NoOpMempool[mock.Tx]{}, mockStore, Config{}, mock.TxCodec{}, nil) + + t.Run("Check tx basic", func(t *testing.T) { + res, err := c.CheckTx(context.Background(), &abci.RequestCheckTx{ + Tx: mockTx.Bytes(), + Type: 0, + }) + require.NotNil(t, res.GasUsed) + require.NoError(t, err) + }) +} + +var actorName = []byte("cookies") + +func kvSet(t *testing.T, ctx context.Context, v string) error { + t.Helper() + executionCtx := stf.GetExecutionContext(ctx) + require.NotNil(t, executionCtx) + state, err := executionCtx.State.GetWriter(actorName) + require.NoError(t, err) + return state.Set([]byte(v), []byte(v)) +} + +func stateHas(t *testing.T, accountState corestore.ReaderMap, key string) { + t.Helper() + state, err := accountState.GetReader(actorName) + require.NoError(t, err) + has, err := state.Has([]byte(key)) + require.NoError(t, err) + require.Truef(t, has, "state did not have key: %s", key) +} + +func stateNotHas(t *testing.T, accountState corestore.ReaderMap, key string) { + t.Helper() + state, err := accountState.GetReader(actorName) + require.NoError(t, err) + has, err := state.Has([]byte(key)) + require.NoError(t, err) + require.Falsef(t, has, "state was not supposed to have key: %s", key) +} diff --git a/server/v2/cometbft/go.mod b/server/v2/cometbft/go.mod index 6e3509c7c406..2977a94f90de 100644 --- a/server/v2/cometbft/go.mod +++ b/server/v2/cometbft/go.mod @@ -10,6 +10,7 @@ replace ( cosmossdk.io/log => ../../../log cosmossdk.io/server/v2 => ../ cosmossdk.io/server/v2/appmanager => ../appmanager + cosmossdk.io/server/v2/stf => ../stf cosmossdk.io/store => ../../../store cosmossdk.io/store/v2 => ../../../store/v2 cosmossdk.io/x/accounts => ../../../x/accounts @@ -28,6 +29,7 @@ require ( cosmossdk.io/errors v1.0.1 cosmossdk.io/server/v2 v2.0.0-00010101000000-000000000000 cosmossdk.io/server/v2/appmanager v0.0.0-00010101000000-000000000000 + cosmossdk.io/server/v2/stf v0.0.0-20240708142107-25e99c54bac1 cosmossdk.io/store/v2 v2.0.0-00010101000000-000000000000 cosmossdk.io/x/auth v0.0.0-00010101000000-000000000000 cosmossdk.io/x/consensus v0.0.0-00010101000000-000000000000 @@ -134,6 +136,7 @@ require ( github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-sqlite3 v1.14.22 // indirect github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect diff --git a/server/v2/cometbft/go.sum b/server/v2/cometbft/go.sum index 19d5bab44988..e95ce1ae38a9 100644 --- a/server/v2/cometbft/go.sum +++ b/server/v2/cometbft/go.sum @@ -332,6 +332,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= diff --git a/server/v2/cometbft/mock/mock_reader.go b/server/v2/cometbft/mock/mock_reader.go new file mode 100644 index 000000000000..26f03694ce87 --- /dev/null +++ b/server/v2/cometbft/mock/mock_reader.go @@ -0,0 +1,67 @@ +package mock + +import ( + corestore "cosmossdk.io/core/store" + // ammstore "cosmossdk.io/server/v2/appmanager/store" + // "cosmossdk.io/server/v2/stf/branch" +) + +// ReaderMap defines an adapter around a RootStore that only exposes read-only +// operations. This is useful for exposing a read-only view of the RootStore at +// a specific version in history, which could also be the latest state. +type ReaderMap struct { + store *MockStore + version uint64 +} + +func NewMockReaderMap(v uint64, rs *MockStore) *ReaderMap { + return &ReaderMap{ + store: rs, + version: v, + } +} + +func (roa *ReaderMap) GetReader(actor []byte) (corestore.Reader, error) { + return NewMockReader(roa.version, roa.store, actor), nil +} + +// Reader represents a read-only adapter for accessing data from the root store. +type MockReader struct { + version uint64 // The version of the data. + store *MockStore // The root store to read data from. + actor []byte // The actor associated with the data. +} + +func NewMockReader(v uint64, rs *MockStore, actor []byte) *MockReader { + return &MockReader{ + version: v, + store: rs, + actor: actor, + } +} + +func (roa *MockReader) Has(key []byte) (bool, error) { + val, err := roa.store.GetStateStorage().Has(roa.actor, roa.version, key) + if err != nil { + return false, err + } + + return val, nil +} + +func (roa *MockReader) Get(key []byte) ([]byte, error) { + result, err := roa.store.GetStateStorage().Get(roa.actor, roa.version, key) + if err != nil { + return nil, err + } + + return result, nil +} + +func (roa *MockReader) Iterator(start, end []byte) (corestore.Iterator, error) { + return roa.store.GetStateStorage().Iterator(roa.actor, roa.version, start, end) +} + +func (roa *MockReader) ReverseIterator(start, end []byte) (corestore.Iterator, error) { + return roa.store.GetStateStorage().ReverseIterator(roa.actor, roa.version, start, end) +} diff --git a/server/v2/cometbft/mock/mock_store.go b/server/v2/cometbft/mock/mock_store.go new file mode 100644 index 000000000000..ddb71f6493be --- /dev/null +++ b/server/v2/cometbft/mock/mock_store.go @@ -0,0 +1,111 @@ +package mock + +import ( + "fmt" + + "cosmossdk.io/core/log" + corestore "cosmossdk.io/core/store" + + // ammstore "cosmossdk.io/server/v2/appmanager/store" + "cosmossdk.io/server/v2/stf/branch" + storev2 "cosmossdk.io/store/v2" + "cosmossdk.io/store/v2/commitment" + dbm "cosmossdk.io/store/v2/db" + "cosmossdk.io/store/v2/proof" + "cosmossdk.io/store/v2/storage" + "cosmossdk.io/store/v2/storage/pebbledb" +) + +type MockStore struct { + Storage storev2.VersionedDatabase + Commiter storev2.Committer +} + +func NewMockStorage(logger log.Logger) storev2.VersionedDatabase { + storageDB, _ := pebbledb.New("dir") + ss := storage.NewStorageStore(storageDB, logger) + return ss +} + +func NewMockCommiter(logger log.Logger) storev2.Committer { + sc, _ := commitment.NewCommitStore(map[string]commitment.Tree{}, dbm.NewMemDB(), logger) + return sc +} + +func NewMockStore(ss storev2.VersionedDatabase, sc storev2.Committer) *MockStore { + return &MockStore{Storage: ss, Commiter: sc} +} + +func (s *MockStore) GetLatestVersion() (uint64, error) { + v, err := s.Storage.GetLatestVersion() + return v, err +} + +func (s *MockStore) StateLatest() (uint64, corestore.ReaderMap, error) { + v, err := s.GetLatestVersion() + if err != nil { + return 0, nil, err + } + + return v, NewMockReaderMap(v, s), nil +} + +func (s *MockStore) Commit(changeset *corestore.Changeset) (corestore.Hash, error) { + _, state, _ := s.StateLatest() + writer := branch.DefaultNewWriterMap(state) + err := writer.ApplyStateChanges(changeset.Changes) + return []byte{}, err +} + +func (s *MockStore) StateAt(version uint64) (corestore.ReaderMap, error) { + info, err := s.Commiter.GetCommitInfo(version) + if err != nil || info == nil { + return nil, fmt.Errorf("failed to get commit info for version %d: %w", version, err) + } + return NewMockReaderMap(version, s), nil +} + +func (s *MockStore) GetStateStorage() storev2.VersionedDatabase { + return s.Storage +} + +func (s *MockStore) GetStateCommitment() storev2.Committer { + return s.Commiter +} + +type Result struct { + key []byte + value []byte + version uint64 + proofOps []proof.CommitmentOp +} + +func (s *MockStore) Query(storeKey []byte, version uint64, key []byte, prove bool) (storev2.QueryResult, error) { + state, err := s.StateAt(version) + reader, err := state.GetReader(storeKey) + value, err := reader.Get(key) + res := storev2.QueryResult{ + Key: key, + Value: value, + Version: version, + } + return res, err +} + +func (s *MockStore) LastCommitID() (proof.CommitID, error) { + v, _, err := s.StateLatest() + return proof.CommitID{ + Version: v, + Hash: []byte{}, + }, err +} + +func (s *MockStore) SetInitialVersion(v uint64) error { + return s.Commiter.SetInitialVersion(v) +} + +func (s *MockStore) WorkingHash(changeset *corestore.Changeset) (corestore.Hash, error) { + return s.Commiter.SetInitialVersion(v) +} + + diff --git a/store/v2/root/store.go b/store/v2/root/store.go index 997f9d0f485e..c5d1b1e5a02b 100644 --- a/store/v2/root/store.go +++ b/store/v2/root/store.go @@ -179,7 +179,7 @@ func (s *Store) Query(storeKey []byte, version uint64, key []byte, prove bool) ( val, err = s.stateCommitment.Get(storeKey, version, key) if err != nil { return store.QueryResult{}, fmt.Errorf("failed to query SC store: %w", err) - } + } } else { val, err = s.stateStorage.Get(storeKey, version, key) if err != nil { From cbd05cec62b3149973f8194570dd2eac8529cf86 Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Tue, 16 Jul 2024 20:47:27 +0700 Subject: [PATCH 02/22] fixing --- server/v2/cometbft/abci_test.go | 52 ++++++++++++++------- server/v2/cometbft/mock/mock_store.go | 9 +++- server/v2/stf/{export_test.go => export.go} | 6 +++ store/v2/storage/pebbledb/db.go | 1 + 4 files changed, 48 insertions(+), 20 deletions(-) rename server/v2/stf/{export_test.go => export.go} (63%) diff --git a/server/v2/cometbft/abci_test.go b/server/v2/cometbft/abci_test.go index 1753eef6587e..36d7422220f3 100644 --- a/server/v2/cometbft/abci_test.go +++ b/server/v2/cometbft/abci_test.go @@ -2,31 +2,36 @@ package cometbft import ( "context" + "fmt" "testing" + "time" appmodulev2 "cosmossdk.io/core/appmodule/v2" "cosmossdk.io/core/log" corestore "cosmossdk.io/core/store" - "cosmossdk.io/core/transaction" am "cosmossdk.io/server/v2/appmanager" - ammstore "cosmossdk.io/server/v2/appmanager/store" "cosmossdk.io/server/v2/cometbft/mempool" + cometmock "cosmossdk.io/server/v2/cometbft/mock" "cosmossdk.io/server/v2/stf" "cosmossdk.io/server/v2/stf/branch" "cosmossdk.io/server/v2/stf/mock" - cometmock "cosmossdk.io/server/v2/cometbft/mock" - "cosmossdk.io/store/v2/storage/pebbledb" - abci "github.com/cometbft/cometbft/abci/types" + abciproto "github.com/cometbft/cometbft/api/cometbft/abci/v1" + + // gogoproto "github.com/cosmos/gogoproto/proto" + // gogotypes "github.com/cosmos/gogoproto/types" + "crypto/sha256" + "github.com/stretchr/testify/require" - "google.golang.org/protobuf/types/known/wrapperspb" ) func TestConsensus(t *testing.T) { - mockTx := mock.Tx{ - Sender: []byte("sender"), - Msg: wrapperspb.Bool(true), // msg does not matter at all because our handler does nothing. - GasLimit: 100_000, - } + // mockTx := mock.Tx{ + // Sender: []byte("sender"), + // Msg: &gogotypes.BoolValue{Value: true}, + // GasLimit: 100_000, + // } + + sum := sha256.Sum256([]byte("test-hash")) s, err := stf.NewSTF( log.NewNopLogger().With("module", "stf"), @@ -64,15 +69,26 @@ func TestConsensus(t *testing.T) { am, err := b.Build() require.NoError(t, err) - c := NewConsensus[mock.Tx](am, mempool.NoOpMempool[mock.Tx]{}, mockStore, Config{}, mock.TxCodec{}, nil) - t.Run("Check tx basic", func(t *testing.T) { - res, err := c.CheckTx(context.Background(), &abci.RequestCheckTx{ - Tx: mockTx.Bytes(), - Type: 0, + // t.Run("Check tx basic", func(t *testing.T) { + // res, err := c.CheckTx(context.Background(), &abciproto.CheckTxRequest{ + // Tx: mockTx.Bytes(), + // Type: 0, + // }) + // require.NotNil(t, res.GasUsed) + // require.NoError(t, err) + // }) + + t.Run("Finalize block", func(t *testing.T) { + res, err := c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ + Txs: nil, + Height: 1, + Time: time.Now(), + Hash: sum[:], }) - require.NotNil(t, res.GasUsed) + fmt.Println(len(sum[:])) + fmt.Println("Finalize ", res, err) require.NoError(t, err) }) } @@ -83,7 +99,7 @@ func kvSet(t *testing.T, ctx context.Context, v string) error { t.Helper() executionCtx := stf.GetExecutionContext(ctx) require.NotNil(t, executionCtx) - state, err := executionCtx.State.GetWriter(actorName) + state, err := stf.GetStateFromContext(executionCtx).GetWriter(actorName) require.NoError(t, err) return state.Set([]byte(v), []byte(v)) } diff --git a/server/v2/cometbft/mock/mock_store.go b/server/v2/cometbft/mock/mock_store.go index ddb71f6493be..c88170717d9d 100644 --- a/server/v2/cometbft/mock/mock_store.go +++ b/server/v2/cometbft/mock/mock_store.go @@ -1,6 +1,7 @@ package mock import ( + "crypto/sha256" "fmt" "cosmossdk.io/core/log" @@ -94,9 +95,10 @@ func (s *MockStore) Query(storeKey []byte, version uint64, key []byte, prove boo func (s *MockStore) LastCommitID() (proof.CommitID, error) { v, _, err := s.StateLatest() + bz := sha256.Sum256([]byte{}) return proof.CommitID{ Version: v, - Hash: []byte{}, + Hash: bz[:], }, err } @@ -105,7 +107,10 @@ func (s *MockStore) SetInitialVersion(v uint64) error { } func (s *MockStore) WorkingHash(changeset *corestore.Changeset) (corestore.Hash, error) { - return s.Commiter.SetInitialVersion(v) + _, state, _ := s.StateLatest() + writer := branch.DefaultNewWriterMap(state) + err := writer.ApplyStateChanges(changeset.Changes) + return []byte{}, err } diff --git a/server/v2/stf/export_test.go b/server/v2/stf/export.go similarity index 63% rename from server/v2/stf/export_test.go rename to server/v2/stf/export.go index b84148abdd9c..64acec3064de 100644 --- a/server/v2/stf/export_test.go +++ b/server/v2/stf/export.go @@ -2,6 +2,8 @@ package stf import ( "context" + + "cosmossdk.io/core/store" ) func GetExecutionContext(ctx context.Context) *executionContext { @@ -11,3 +13,7 @@ func GetExecutionContext(ctx context.Context) *executionContext { } return executionCtx } + +func GetStateFromContext(ctx *executionContext) store.WriterMap { + return ctx.state +} diff --git a/store/v2/storage/pebbledb/db.go b/store/v2/storage/pebbledb/db.go index 4e9df737b57e..2dd2692e823a 100644 --- a/store/v2/storage/pebbledb/db.go +++ b/store/v2/storage/pebbledb/db.go @@ -148,6 +148,7 @@ func (db *Database) Has(storeKey []byte, version uint64, key []byte) (bool, erro } func (db *Database) Get(storeKey []byte, targetVersion uint64, key []byte) ([]byte, error) { + fmt.Println("version", targetVersion, db.earliestVersion) if targetVersion < db.earliestVersion { return nil, storeerrors.ErrVersionPruned{EarliestVersion: db.earliestVersion, RequestedVersion: targetVersion} } From 587023fc8d1ba473ef87118cec477a7f802c58ec Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Fri, 19 Jul 2024 13:44:54 +0700 Subject: [PATCH 03/22] go mod tidy all --- server/v2/cometbft/go.mod | 3 +-- simapp/v2/go.mod | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/server/v2/cometbft/go.mod b/server/v2/cometbft/go.mod index 2977a94f90de..2251f1ea7b32 100644 --- a/server/v2/cometbft/go.mod +++ b/server/v2/cometbft/go.mod @@ -43,6 +43,7 @@ require ( github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 + github.com/stretchr/testify v1.9.0 google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 google.golang.org/grpc v1.64.0 google.golang.org/protobuf v1.34.2 @@ -136,7 +137,6 @@ require ( github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-sqlite3 v1.14.22 // indirect github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect @@ -162,7 +162,6 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect - github.com/stretchr/testify v1.9.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.12 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect diff --git a/simapp/v2/go.mod b/simapp/v2/go.mod index 7f8309ceab17..8a2f4b6be71c 100644 --- a/simapp/v2/go.mod +++ b/simapp/v2/go.mod @@ -63,7 +63,7 @@ require ( cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/server/v2/appmanager v0.0.0-00010101000000-000000000000 // indirect - cosmossdk.io/server/v2/stf v0.0.0-00010101000000-000000000000 // indirect + cosmossdk.io/server/v2/stf v0.0.0-20240708142107-25e99c54bac1 // indirect cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 // indirect cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337 // indirect From 116e283da45c4bc5939147d7c27c4136596b3807 Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Mon, 22 Jul 2024 18:26:04 +0700 Subject: [PATCH 04/22] remove fmt --- store/v2/storage/pebbledb/db.go | 1 - 1 file changed, 1 deletion(-) diff --git a/store/v2/storage/pebbledb/db.go b/store/v2/storage/pebbledb/db.go index 2dd2692e823a..4e9df737b57e 100644 --- a/store/v2/storage/pebbledb/db.go +++ b/store/v2/storage/pebbledb/db.go @@ -148,7 +148,6 @@ func (db *Database) Has(storeKey []byte, version uint64, key []byte) (bool, erro } func (db *Database) Get(storeKey []byte, targetVersion uint64, key []byte) ([]byte, error) { - fmt.Println("version", targetVersion, db.earliestVersion) if targetVersion < db.earliestVersion { return nil, storeerrors.ErrVersionPruned{EarliestVersion: db.earliestVersion, RequestedVersion: targetVersion} } From 462efb0052639880fc907af8747aabef07b32035 Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Mon, 22 Jul 2024 18:26:41 +0700 Subject: [PATCH 05/22] helpers --- server/v2/stf/{export.go => helper.go} | 8 ++++++++ 1 file changed, 8 insertions(+) rename server/v2/stf/{export.go => helper.go} (62%) diff --git a/server/v2/stf/export.go b/server/v2/stf/helper.go similarity index 62% rename from server/v2/stf/export.go rename to server/v2/stf/helper.go index 64acec3064de..9bd63f5bd3fe 100644 --- a/server/v2/stf/export.go +++ b/server/v2/stf/helper.go @@ -4,8 +4,12 @@ import ( "context" "cosmossdk.io/core/store" + "cosmossdk.io/server/v2/stf/mock" ) +// There some field not be exported +// Helpers for cometbft test + func GetExecutionContext(ctx context.Context) *executionContext { executionCtx, ok := ctx.(*executionContext) if !ok { @@ -17,3 +21,7 @@ func GetExecutionContext(ctx context.Context) *executionContext { func GetStateFromContext(ctx *executionContext) store.WriterMap { return ctx.state } + +func SetMsgRouter(s *STF[mock.Tx], msgRouter Router) { + s.msgRouter = msgRouter +} From b17533e290f577f0ee35dbcd04ed853bbdcb44ca Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Mon, 22 Jul 2024 18:27:00 +0700 Subject: [PATCH 06/22] mock store --- server/v2/cometbft/mock/mock_store.go | 59 +++++++++++++++++++-------- 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/server/v2/cometbft/mock/mock_store.go b/server/v2/cometbft/mock/mock_store.go index c88170717d9d..71a9e6728de0 100644 --- a/server/v2/cometbft/mock/mock_store.go +++ b/server/v2/cometbft/mock/mock_store.go @@ -7,14 +7,14 @@ import ( "cosmossdk.io/core/log" corestore "cosmossdk.io/core/store" - // ammstore "cosmossdk.io/server/v2/appmanager/store" - "cosmossdk.io/server/v2/stf/branch" + storev2 "cosmossdk.io/store/v2" "cosmossdk.io/store/v2/commitment" dbm "cosmossdk.io/store/v2/db" "cosmossdk.io/store/v2/proof" "cosmossdk.io/store/v2/storage" - "cosmossdk.io/store/v2/storage/pebbledb" + "cosmossdk.io/store/v2/storage/sqlite" + "cosmossdk.io/store/v2/commitment/iavl" ) type MockStore struct { @@ -23,13 +23,18 @@ type MockStore struct { } func NewMockStorage(logger log.Logger) storev2.VersionedDatabase { - storageDB, _ := pebbledb.New("dir") + storageDB, _ := sqlite.New("dir") ss := storage.NewStorageStore(storageDB, logger) return ss } -func NewMockCommiter(logger log.Logger) storev2.Committer { - sc, _ := commitment.NewCommitStore(map[string]commitment.Tree{}, dbm.NewMemDB(), logger) +func NewMockCommiter(logger log.Logger, actors ...string) storev2.Committer { + treeMap := make(map[string]commitment.Tree) + for _, actor := range actors { + tree := iavl.NewIavlTree(dbm.NewMemDB(), logger, iavl.DefaultConfig()) + treeMap[actor] = tree + } + sc, _ := commitment.NewCommitStore(treeMap, dbm.NewMemDB(), logger) return sc } @@ -38,8 +43,12 @@ func NewMockStore(ss storev2.VersionedDatabase, sc storev2.Committer) *MockStore } func (s *MockStore) GetLatestVersion() (uint64, error) { - v, err := s.Storage.GetLatestVersion() - return v, err + lastCommitID, err := s.LastCommitID() + if err != nil { + return 0, err + } + + return lastCommitID.Version, nil } func (s *MockStore) StateLatest() (uint64, corestore.ReaderMap, error) { @@ -52,10 +61,19 @@ func (s *MockStore) StateLatest() (uint64, corestore.ReaderMap, error) { } func (s *MockStore) Commit(changeset *corestore.Changeset) (corestore.Hash, error) { - _, state, _ := s.StateLatest() - writer := branch.DefaultNewWriterMap(state) - err := writer.ApplyStateChanges(changeset.Changes) - return []byte{}, err + v, _, _ := s.StateLatest() + err := s.Storage.ApplyChangeset(v, changeset) + if err != nil { + return []byte{}, err + } + + err = s.Commiter.WriteChangeset(changeset) + if err != nil { + return []byte{}, err + } + + s.Commiter.Commit(v+1) + return []byte{}, nil } func (s *MockStore) StateAt(version uint64) (corestore.ReaderMap, error) { @@ -94,7 +112,7 @@ func (s *MockStore) Query(storeKey []byte, version uint64, key []byte, prove boo } func (s *MockStore) LastCommitID() (proof.CommitID, error) { - v, _, err := s.StateLatest() + v, err := s.GetStateCommitment().GetLatestVersion() bz := sha256.Sum256([]byte{}) return proof.CommitID{ Version: v, @@ -107,10 +125,17 @@ func (s *MockStore) SetInitialVersion(v uint64) error { } func (s *MockStore) WorkingHash(changeset *corestore.Changeset) (corestore.Hash, error) { - _, state, _ := s.StateLatest() - writer := branch.DefaultNewWriterMap(state) - err := writer.ApplyStateChanges(changeset.Changes) - return []byte{}, err + v, _, _ := s.StateLatest() + err := s.Storage.ApplyChangeset(v, changeset) + if err != nil { + return []byte{}, err + } + + err = s.Commiter.WriteChangeset(changeset) + if err != nil { + return []byte{}, err + } + return []byte{}, nil } From 2375aa7ebf057093db5c673d80e2480c1ad90dde Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Mon, 22 Jul 2024 18:27:12 +0700 Subject: [PATCH 07/22] add some tests --- server/v2/cometbft/abci_test.go | 151 +++++++++++++++++++++++++++----- server/v2/cometbft/go.mod | 1 + 2 files changed, 128 insertions(+), 24 deletions(-) diff --git a/server/v2/cometbft/abci_test.go b/server/v2/cometbft/abci_test.go index 36d7422220f3..97a11acc12ee 100644 --- a/server/v2/cometbft/abci_test.go +++ b/server/v2/cometbft/abci_test.go @@ -2,7 +2,7 @@ package cometbft import ( "context" - "fmt" + "io" "testing" "time" @@ -12,18 +12,54 @@ import ( am "cosmossdk.io/server/v2/appmanager" "cosmossdk.io/server/v2/cometbft/mempool" cometmock "cosmossdk.io/server/v2/cometbft/mock" + "cosmossdk.io/server/v2/cometbft/types" "cosmossdk.io/server/v2/stf" "cosmossdk.io/server/v2/stf/branch" "cosmossdk.io/server/v2/stf/mock" abciproto "github.com/cometbft/cometbft/api/cometbft/abci/v1" + v1 "github.com/cometbft/cometbft/api/cometbft/types/v1" - // gogoproto "github.com/cosmos/gogoproto/proto" - // gogotypes "github.com/cosmos/gogoproto/types" - "crypto/sha256" + "github.com/cosmos/gogoproto/proto" + "encoding/json" + + consensustypes "cosmossdk.io/x/consensus/types" "github.com/stretchr/testify/require" ) +func addMsgHandlerToSTF[T any, PT interface { + *T + proto.Message +}, + U any, UT interface { + *U + proto.Message + }]( + t *testing.T, + s *stf.STF[mock.Tx], + handler func(ctx context.Context, msg PT) (UT, error), +) { + t.Helper() + msgRouterBuilder := stf.NewMsgRouterBuilder() + err := msgRouterBuilder.RegisterHandler( + proto.MessageName(PT(new(T))), + func(ctx context.Context, msg appmodulev2.Message) (msgResp appmodulev2.Message, err error) { + typedReq := msg.(PT) + typedResp, err := handler(ctx, typedReq) + if err != nil { + return nil, err + } + + return typedResp, nil + }, + ) + require.NoError(t, err) + + msgRouter, err := msgRouterBuilder.Build() + require.NoError(t, err) + stf.SetMsgRouter(s, msgRouter) +} + func TestConsensus(t *testing.T) { // mockTx := mock.Tx{ // Sender: []byte("sender"), @@ -31,7 +67,7 @@ func TestConsensus(t *testing.T) { // GasLimit: 100_000, // } - sum := sha256.Sum256([]byte("test-hash")) + // sum := sha256.Sum256([]byte("test-hash")) s, err := stf.NewSTF( log.NewNopLogger().With("module", "stf"), @@ -55,7 +91,7 @@ func TestConsensus(t *testing.T) { ) ss := cometmock.NewMockStorage(log.NewNopLogger()) - sc := cometmock.NewMockCommiter(log.NewNopLogger()) + sc := cometmock.NewMockCommiter(log.NewNopLogger(), string(actorName), "stf") mockStore := cometmock.NewMockStore(ss, sc) b := am.Builder[mock.Tx]{ @@ -64,33 +100,69 @@ func TestConsensus(t *testing.T) { ValidateTxGasLimit: 100_000, QueryGasLimit: 100_000, SimulationGasLimit: 100_000, + InitGenesis: func(ctx context.Context, src io.Reader, txHandler func(json.RawMessage) error) error { + return kvSet(t, ctx, "init-chain") + }, } am, err := b.Build() require.NoError(t, err) - c := NewConsensus[mock.Tx](am, mempool.NoOpMempool[mock.Tx]{}, mockStore, Config{}, mock.TxCodec{}, nil) - - // t.Run("Check tx basic", func(t *testing.T) { - // res, err := c.CheckTx(context.Background(), &abciproto.CheckTxRequest{ - // Tx: mockTx.Bytes(), - // Type: 0, - // }) - // require.NotNil(t, res.GasUsed) - // require.NoError(t, err) - // }) - - t.Run("Finalize block", func(t *testing.T) { - res, err := c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ - Txs: nil, - Height: 1, + c := NewConsensus[mock.Tx](am, mempool.NoOpMempool[mock.Tx]{}, mockStore, Config{}, mock.TxCodec{}, log.NewNopLogger()) + + t.Run("InitChain without update consensus params", func(t *testing.T) { + _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ + Time: time.Now(), + ChainId: "test", + InitialHeight: 1, + }) + require.NoError(t, err) + stateStorageHas(t, mockStore, "init-chain", 1) + stateStorageHas(t, mockStore, "end-block", 1) + }) + + t.Run("InitChain with update consensus params", func(t *testing.T) { + addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *consensustypes.MsgUpdateParams) (*consensustypes.MsgUpdateParams, error) { + kvSet(t, ctx, "exec") + return nil, nil + }) + + _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ + Time: time.Now(), + ChainId: "test", + ConsensusParams: &v1.ConsensusParams{ + Block: &v1.BlockParams{ + MaxGas: 5000000, + }, + }, + InitialHeight: 2, + }) + require.NoError(t, err) + stateStorageHas(t, mockStore, "init-chain", 2) + stateStorageHas(t, mockStore, "exec", 2) + stateStorageHas(t, mockStore, "end-block", 2) + + stateCommitmentNoHas(t, mockStore, "init-chain", 2) + stateStorageHas(t, mockStore, "exec", 2) + stateCommitmentNoHas(t, mockStore, "end-block", 2) + }) + + t.Run("FinalizeBlock genesis block", func(t *testing.T) { + _, err := c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ Time: time.Now(), - Hash: sum[:], + Height: 2, }) - fmt.Println(len(sum[:])) - fmt.Println("Finalize ", res, err) require.NoError(t, err) + stateStorageNoHas(t, mockStore, "begin-block", 2) + stateStorageHas(t, mockStore, "end-block", 2) + + // commit genesis state + stateCommitmentHas(t, mockStore, "init-chain", 2) + stateCommitmentHas(t, mockStore, "exec", 2) + stateCommitmentHas(t, mockStore, "end-block", 2) + }) + } var actorName = []byte("cookies") @@ -104,6 +176,37 @@ func kvSet(t *testing.T, ctx context.Context, v string) error { return state.Set([]byte(v), []byte(v)) } +func stateStorageHas(t *testing.T, store types.Store, key string, version uint64) { + t.Helper() + has, err := store.GetStateStorage().Has(actorName, version, []byte(key)) + require.NoError(t, err) + require.Truef(t, has, "state storage did not have key: %s", key) +} + +func stateStorageNoHas(t *testing.T, store types.Store, key string, version uint64) { + t.Helper() + has, err := store.GetStateStorage().Has(actorName, version, []byte(key)) + require.NoError(t, err) + require.Falsef(t, has, "state storage had key: %s", key) +} + +func stateCommitmentHas(t *testing.T, store types.Store, key string, version uint64) { + t.Helper() + bz, err := store.GetStateCommitment().Get(actorName, version, []byte(key)) + require.NoError(t, err) + require.NotEqual(t, len(bz), 0) + require.Equal(t, bz, []byte(key)) +} + +func stateCommitmentNoHas(t *testing.T, store types.Store, key string, version uint64) { + t.Helper() + bz, err := store.GetStateCommitment().Get(actorName, version, []byte(key)) + // if not committed, should return version does not exist + require.Error(t, err) + require.Contains(t, err.Error(), "version does not exist") + require.Equal(t, len(bz), 0) +} + func stateHas(t *testing.T, accountState corestore.ReaderMap, key string) { t.Helper() state, err := accountState.GetReader(actorName) diff --git a/server/v2/cometbft/go.mod b/server/v2/cometbft/go.mod index 2251f1ea7b32..a0e7d81a570c 100644 --- a/server/v2/cometbft/go.mod +++ b/server/v2/cometbft/go.mod @@ -137,6 +137,7 @@ require ( github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-sqlite3 v1.14.22 // indirect github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect From 44548bef371a4c1e329d8dd472c851ca5a0c9c96 Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Mon, 5 Aug 2024 16:17:58 +0700 Subject: [PATCH 08/22] testing --- server/v2/appmanager/appmanager.go | 3 + server/v2/cometbft/abci.go | 1 + server/v2/cometbft/abci_test.go | 260 ++++++++++++++++++-------- server/v2/cometbft/mock/mock_store.go | 10 +- server/v2/cometbft/utils.go | 2 + server/v2/stf/helper.go | 4 + server/v2/stf/stf.go | 4 +- server/v2/stf/stf_router.go | 2 + 8 files changed, 199 insertions(+), 87 deletions(-) diff --git a/server/v2/appmanager/appmanager.go b/server/v2/appmanager/appmanager.go index f20abad5567c..a4f4a6b4a817 100644 --- a/server/v2/appmanager/appmanager.go +++ b/server/v2/appmanager/appmanager.go @@ -129,6 +129,9 @@ func (a AppManager[T]) Query(ctx context.Context, version uint64, request transa if err != nil { return nil, err } + fmt.Println("queryState", queryState) + fmt.Println("a.config.QueryGasLimit", a.config.QueryGasLimit) + fmt.Println("request", request, request.String()) return a.stf.Query(ctx, queryState, a.config.QueryGasLimit, request) } diff --git a/server/v2/cometbft/abci.go b/server/v2/cometbft/abci.go index 37698e194181..b51428fc502a 100644 --- a/server/v2/cometbft/abci.go +++ b/server/v2/cometbft/abci.go @@ -481,6 +481,7 @@ func (c *Consensus[T]) FinalizeBlock( c.lastCommittedHeight.Store(req.Height) cp, err := c.GetConsensusParams(ctx) // we get the consensus params from the latest state because we committed state above + fmt.Println("GetConsensusParams", cp, err) if err != nil { return nil, err } diff --git a/server/v2/cometbft/abci_test.go b/server/v2/cometbft/abci_test.go index 97a11acc12ee..9e175d6a06ff 100644 --- a/server/v2/cometbft/abci_test.go +++ b/server/v2/cometbft/abci_test.go @@ -2,13 +2,15 @@ package cometbft import ( "context" + "crypto/sha256" + "fmt" "io" + "strings" "testing" "time" appmodulev2 "cosmossdk.io/core/appmodule/v2" "cosmossdk.io/core/log" - corestore "cosmossdk.io/core/store" am "cosmossdk.io/server/v2/appmanager" "cosmossdk.io/server/v2/cometbft/mempool" cometmock "cosmossdk.io/server/v2/cometbft/mock" @@ -27,6 +29,8 @@ import ( "github.com/stretchr/testify/require" ) +var sum = sha256.Sum256([]byte("test-hash")) + func addMsgHandlerToSTF[T any, PT interface { *T proto.Message @@ -60,15 +64,178 @@ func addMsgHandlerToSTF[T any, PT interface { stf.SetMsgRouter(s, msgRouter) } -func TestConsensus(t *testing.T) { - // mockTx := mock.Tx{ - // Sender: []byte("sender"), - // Msg: &gogotypes.BoolValue{Value: true}, - // GasLimit: 100_000, - // } +func addQueryHandlerToSTF[T any, PT interface { + *T + proto.Message +}, + U any, UT interface { + *U + proto.Message + }]( + t *testing.T, + s *stf.STF[mock.Tx], + handler func(ctx context.Context, msg PT) (UT, error), +) { + t.Helper() + queryRouterBuilder := stf.NewMsgRouterBuilder() + err := queryRouterBuilder.RegisterHandler( + proto.MessageName(PT(new(T))), + func(ctx context.Context, msg appmodulev2.Message) (msgResp appmodulev2.Message, err error) { + typedReq := msg.(PT) + typedResp, err := handler(ctx, typedReq) + if err != nil { + return nil, err + } + + return typedResp, nil + }, + ) + require.NoError(t, err) + + queryRouter, err := queryRouterBuilder.Build() + require.NoError(t, err) + stf.SetQueryRouter(s, queryRouter) +} + +func TestConsensus_InitChain_Without_UpdateParam(t *testing.T) { + c, _ := setUpConsensus(t) + mockStore := c.store + _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ + Time: time.Now(), + ChainId: "test", + InitialHeight: 1, + }) + require.NoError(t, err) + stateStorageHas(t, mockStore, "init-chain", 1) + stateStorageHas(t, mockStore, "end-block", 1) + + stateCommitmentNoHas(t, mockStore, "init-chain", 1) + stateCommitmentNoHas(t, mockStore, "end-block", 1) + + _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ + Time: time.Now(), + Height: 1, + }) + require.NoError(t, err) + + stateCommitmentHas(t, mockStore, "init-chain", 1) + stateCommitmentHas(t, mockStore, "end-block", 1) +} + +func TestConsensus_InitChain_With_UpdateParam(t *testing.T) { + c, s := setUpConsensus(t) + mockStore := c.store + addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *consensustypes.MsgUpdateParams) (*consensustypes.MsgUpdateParams, error) { + kvSet(t, ctx, "exec") + return nil, nil + }) + _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ + Time: time.Now(), + ChainId: "test", + ConsensusParams: &v1.ConsensusParams{ + Block: &v1.BlockParams{ + MaxGas: 5000000, + }, + }, + InitialHeight: 1, + }) + require.NoError(t, err) + stateStorageHas(t, mockStore, "init-chain", 1) + stateStorageHas(t, mockStore, "exec", 1) + stateStorageHas(t, mockStore, "end-block", 1) + + stateCommitmentNoHas(t, mockStore, "init-chain", 1) + stateCommitmentNoHas(t, mockStore, "exec", 1) + stateCommitmentNoHas(t, mockStore, "end-block", 1) + + _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ + Time: time.Now(), + Height: 1, + }) + require.NoError(t, err) + + stateCommitmentHas(t, mockStore, "init-chain", 1) + stateCommitmentHas(t, mockStore, "exec", 1) + stateCommitmentHas(t, mockStore, "end-block", 1) +} + +func TestConsensus_InitChain_Invalid_Height(t *testing.T) { + c, _ := setUpConsensus(t) + mockStore := c.store + _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ + Time: time.Now(), + ChainId: "test", + InitialHeight: 2, + }) + require.NoError(t, err) + stateStorageHas(t, mockStore, "init-chain", 2) + stateStorageHas(t, mockStore, "end-block", 2) + + // Shouldn't be able to commit genesis block 2 + _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ + Time: time.Now(), + Height: 2, + }) + require.Error(t, err) + require.True(t, strings.Contains(err.Error(), "unable to commit the changeset")) +} + +func TestConsensus_FinalizeBlock_Invalid_Height(t *testing.T) { + c, _ := setUpConsensus(t) + _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ + Time: time.Now(), + ChainId: "test", + InitialHeight: 1, + }) + require.NoError(t, err) + + _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ + Time: time.Now(), + Height: 1, + }) + require.NoError(t, err) + + _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ + Time: time.Now(), + Height: 3, + }) + require.Error(t, err) + fmt.Println(err) +} + +func TestConsensus_FinalizeBlock_NoTxs(t *testing.T) { + c, s := setUpConsensus(t) + addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsRequest, error) { + kvSet(t, ctx, "query") + return nil, nil + }) + _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ + Time: time.Now(), + ChainId: "test", + InitialHeight: 1, + }) + require.NoError(t, err) + + _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ + Time: time.Now(), + Height: 1, + }) + require.NoError(t, err) + + endBlock := 10 + for i := 2; i < endBlock; i++ { + _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ + Time: time.Now(), + Height: int64(i), + Hash: sum[:], + }) + require.NoError(t, err) + } + fmt.Println(c.lastCommittedHeight) - // sum := sha256.Sum256([]byte("test-hash")) +} +func setUpConsensus(t *testing.T) (*Consensus[mock.Tx], *stf.STF[mock.Tx]) { s, err := stf.NewSTF( log.NewNopLogger().With("module", "stf"), stf.NewMsgRouterBuilder(), @@ -89,8 +256,9 @@ func TestConsensus(t *testing.T) { }, branch.DefaultNewWriterMap, ) + require.NoError(t, err) - ss := cometmock.NewMockStorage(log.NewNopLogger()) + ss := cometmock.NewMockStorage(log.NewNopLogger(), t.TempDir()) sc := cometmock.NewMockCommiter(log.NewNopLogger(), string(actorName), "stf") mockStore := cometmock.NewMockStore(ss, sc) @@ -108,61 +276,7 @@ func TestConsensus(t *testing.T) { am, err := b.Build() require.NoError(t, err) - c := NewConsensus[mock.Tx](am, mempool.NoOpMempool[mock.Tx]{}, mockStore, Config{}, mock.TxCodec{}, log.NewNopLogger()) - - t.Run("InitChain without update consensus params", func(t *testing.T) { - _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ - Time: time.Now(), - ChainId: "test", - InitialHeight: 1, - }) - require.NoError(t, err) - stateStorageHas(t, mockStore, "init-chain", 1) - stateStorageHas(t, mockStore, "end-block", 1) - }) - - t.Run("InitChain with update consensus params", func(t *testing.T) { - addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *consensustypes.MsgUpdateParams) (*consensustypes.MsgUpdateParams, error) { - kvSet(t, ctx, "exec") - return nil, nil - }) - - _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ - Time: time.Now(), - ChainId: "test", - ConsensusParams: &v1.ConsensusParams{ - Block: &v1.BlockParams{ - MaxGas: 5000000, - }, - }, - InitialHeight: 2, - }) - require.NoError(t, err) - stateStorageHas(t, mockStore, "init-chain", 2) - stateStorageHas(t, mockStore, "exec", 2) - stateStorageHas(t, mockStore, "end-block", 2) - - stateCommitmentNoHas(t, mockStore, "init-chain", 2) - stateStorageHas(t, mockStore, "exec", 2) - stateCommitmentNoHas(t, mockStore, "end-block", 2) - }) - - t.Run("FinalizeBlock genesis block", func(t *testing.T) { - _, err := c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ - Time: time.Now(), - Height: 2, - }) - require.NoError(t, err) - stateStorageNoHas(t, mockStore, "begin-block", 2) - stateStorageHas(t, mockStore, "end-block", 2) - - // commit genesis state - stateCommitmentHas(t, mockStore, "init-chain", 2) - stateCommitmentHas(t, mockStore, "exec", 2) - stateCommitmentHas(t, mockStore, "end-block", 2) - - }) - + return NewConsensus[mock.Tx](am, mempool.NoOpMempool[mock.Tx]{}, mockStore, Config{}, mock.TxCodec{}, log.NewNopLogger()), s } var actorName = []byte("cookies") @@ -206,21 +320,3 @@ func stateCommitmentNoHas(t *testing.T, store types.Store, key string, version u require.Contains(t, err.Error(), "version does not exist") require.Equal(t, len(bz), 0) } - -func stateHas(t *testing.T, accountState corestore.ReaderMap, key string) { - t.Helper() - state, err := accountState.GetReader(actorName) - require.NoError(t, err) - has, err := state.Has([]byte(key)) - require.NoError(t, err) - require.Truef(t, has, "state did not have key: %s", key) -} - -func stateNotHas(t *testing.T, accountState corestore.ReaderMap, key string) { - t.Helper() - state, err := accountState.GetReader(actorName) - require.NoError(t, err) - has, err := state.Has([]byte(key)) - require.NoError(t, err) - require.Falsef(t, has, "state was not supposed to have key: %s", key) -} diff --git a/server/v2/cometbft/mock/mock_store.go b/server/v2/cometbft/mock/mock_store.go index 71a9e6728de0..ad50efb77682 100644 --- a/server/v2/cometbft/mock/mock_store.go +++ b/server/v2/cometbft/mock/mock_store.go @@ -22,8 +22,9 @@ type MockStore struct { Commiter storev2.Committer } -func NewMockStorage(logger log.Logger) storev2.VersionedDatabase { - storageDB, _ := sqlite.New("dir") +func NewMockStorage(logger log.Logger, dir string) storev2.VersionedDatabase { + storageDB, err := sqlite.New(dir) + fmt.Println("storageDB", storageDB, err) ss := storage.NewStorageStore(storageDB, logger) return ss } @@ -72,8 +73,9 @@ func (s *MockStore) Commit(changeset *corestore.Changeset) (corestore.Hash, erro return []byte{}, err } - s.Commiter.Commit(v+1) - return []byte{}, nil + commitInfo, err := s.Commiter.Commit(v+1) + fmt.Println("commitInfo", commitInfo, err) + return []byte{}, err } func (s *MockStore) StateAt(version uint64) (corestore.ReaderMap, error) { diff --git a/server/v2/cometbft/utils.go b/server/v2/cometbft/utils.go index b302e90c78c3..52280e0115ae 100644 --- a/server/v2/cometbft/utils.go +++ b/server/v2/cometbft/utils.go @@ -256,6 +256,7 @@ func (c *Consensus[T]) validateFinalizeBlockHeight(req *abci.FinalizeBlockReques } lastBlockHeight, _, err := c.store.StateLatest() + fmt.Println("lastBlockHeight", lastBlockHeight) if err != nil { return err } @@ -291,6 +292,7 @@ func (c *Consensus[T]) GetConsensusParams(ctx context.Context) (*cmtproto.Consen } res, err := c.app.Query(ctx, latestVersion, &consensus.QueryParamsRequest{}) + fmt.Println("c.app.Query", res, err) if err != nil { return nil, err } diff --git a/server/v2/stf/helper.go b/server/v2/stf/helper.go index 9bd63f5bd3fe..435953f3f587 100644 --- a/server/v2/stf/helper.go +++ b/server/v2/stf/helper.go @@ -25,3 +25,7 @@ func GetStateFromContext(ctx *executionContext) store.WriterMap { func SetMsgRouter(s *STF[mock.Tx], msgRouter Router) { s.msgRouter = msgRouter } + +func SetQueryRouter(s *STF[mock.Tx], queryRouter Router) { + s.queryRouter = queryRouter +} diff --git a/server/v2/stf/stf.go b/server/v2/stf/stf.go index 633a356c36d1..0dc095779edb 100644 --- a/server/v2/stf/stf.go +++ b/server/v2/stf/stf.go @@ -470,7 +470,9 @@ func (s STF[T]) Query( queryCtx := s.makeContext(ctx, nil, queryState, internal.ExecModeSimulate) queryCtx.setHeaderInfo(hi) queryCtx.setGasLimit(gasLimit) - return s.queryRouter.InvokeUntyped(queryCtx, req) + res, err := s.queryRouter.InvokeUntyped(queryCtx, req) + fmt.Println("InvokeUntyped", res, err) + return res, err } // RunWithCtx is made to support genesis, if genesis was just the execution of messages instead diff --git a/server/v2/stf/stf_router.go b/server/v2/stf/stf_router.go index b54c537f850e..09d00cd4fa8e 100644 --- a/server/v2/stf/stf_router.go +++ b/server/v2/stf/stf_router.go @@ -169,7 +169,9 @@ func merge(src, dst gogoproto.Message) { func (r Router) InvokeUntyped(ctx context.Context, req gogoproto.Message) (res gogoproto.Message, err error) { typeName := msgTypeURL(req) + fmt.Println("typeName", typeName) handler, exists := r.handlers[typeName] + fmt.Println("handler", exists) if !exists { return nil, fmt.Errorf("%w: %s", ErrNoHandler, typeName) } From d008afde3c8ccde6cdd23785f44070cb5eb98c19 Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Tue, 6 Aug 2024 13:18:03 +0700 Subject: [PATCH 09/22] test InitChain & FinalizeBlock --- server/v2/cometbft/abci_test.go | 99 ++++++++++++++++++++++++++------- server/v2/cometbft/go.mod | 1 + 2 files changed, 81 insertions(+), 19 deletions(-) diff --git a/server/v2/cometbft/abci_test.go b/server/v2/cometbft/abci_test.go index 9e175d6a06ff..27884fc93c6c 100644 --- a/server/v2/cometbft/abci_test.go +++ b/server/v2/cometbft/abci_test.go @@ -10,7 +10,7 @@ import ( "time" appmodulev2 "cosmossdk.io/core/appmodule/v2" - "cosmossdk.io/core/log" + "cosmossdk.io/log" am "cosmossdk.io/server/v2/appmanager" "cosmossdk.io/server/v2/cometbft/mempool" cometmock "cosmossdk.io/server/v2/cometbft/mock" @@ -26,10 +26,24 @@ import ( "encoding/json" consensustypes "cosmossdk.io/x/consensus/types" + gogotypes "github.com/cosmos/gogoproto/types" "github.com/stretchr/testify/require" ) -var sum = sha256.Sum256([]byte("test-hash")) +var ( + sum = sha256.Sum256([]byte("test-hash")) + DefaulConsensusParams = &v1.ConsensusParams{ + Block: &v1.BlockParams{ + MaxGas: 5000000, + }, + } + anyMsg, _ = gogotypes.MarshalAny(&gogotypes.BoolValue{Value: true}) + mockTx = mock.Tx{ + Sender: []byte("sender"), + Msg: anyMsg, // msg does not matter at all because our handler does nothing. + GasLimit: 100_000, // NO GAS! + } +) func addMsgHandlerToSTF[T any, PT interface { *T @@ -130,14 +144,10 @@ func TestConsensus_InitChain_With_UpdateParam(t *testing.T) { return nil, nil }) _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ - Time: time.Now(), - ChainId: "test", - ConsensusParams: &v1.ConsensusParams{ - Block: &v1.BlockParams{ - MaxGas: 5000000, - }, - }, - InitialHeight: 1, + Time: time.Now(), + ChainId: "test", + ConsensusParams: DefaulConsensusParams, + InitialHeight: 1, }) require.NoError(t, err) stateStorageHas(t, mockStore, "init-chain", 1) @@ -205,10 +215,16 @@ func TestConsensus_FinalizeBlock_Invalid_Height(t *testing.T) { func TestConsensus_FinalizeBlock_NoTxs(t *testing.T) { c, s := setUpConsensus(t) - addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsRequest, error) { + mockStore := c.store + + addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { + cParams := DefaulConsensusParams kvSet(t, ctx, "query") - return nil, nil + return &consensustypes.QueryParamsResponse{ + Params: cParams, + }, nil }) + _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ Time: time.Now(), ChainId: "test", @@ -223,16 +239,64 @@ func TestConsensus_FinalizeBlock_NoTxs(t *testing.T) { require.NoError(t, err) endBlock := 10 - for i := 2; i < endBlock; i++ { + for i := 2; i <= endBlock; i++ { _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ Time: time.Now(), Height: int64(i), Hash: sum[:], }) require.NoError(t, err) + + stateCommitmentHas(t, mockStore, "begin-block", uint64(i)) + stateCommitmentNoHas(t, mockStore, "exec", uint64(i)) + stateCommitmentHas(t, mockStore, "end-block", uint64(i)) } - fmt.Println(c.lastCommittedHeight) + require.Equal(t, int64(endBlock), c.lastCommittedHeight.Load()) +} + +func TestConsensus_FinalizeBlock_MultiTxs(t *testing.T) { + c, s := setUpConsensus(t) + mockStore := c.store + + addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { + cParams := DefaulConsensusParams + kvSet(t, ctx, "query") + return &consensustypes.QueryParamsResponse{ + Params: cParams, + }, nil + }) + addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *gogotypes.Any) (*gogotypes.Any, error) { + kvSet(t, ctx, "exec") + return nil, nil + }) + + _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ + Time: time.Now(), + ChainId: "test", + InitialHeight: 1, + }) + require.NoError(t, err) + + _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ + Time: time.Now(), + Height: 1, + }) + require.NoError(t, err) + endBlock := 10 + for i := 2; i <= endBlock; i++ { + _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ + Time: time.Now(), + Height: int64(i), + Hash: sum[:], + Txs: [][]byte{mockTx.Bytes()}, + }) + require.NoError(t, err) + stateCommitmentHas(t, mockStore, "init-chain", uint64(i)) + stateCommitmentHas(t, mockStore, "exec", uint64(i)) + stateCommitmentHas(t, mockStore, "end-block", uint64(i)) + } + require.Equal(t, int64(endBlock), c.lastCommittedHeight.Load()) } func setUpConsensus(t *testing.T) (*Consensus[mock.Tx], *stf.STF[mock.Tx]) { @@ -276,7 +340,7 @@ func setUpConsensus(t *testing.T) (*Consensus[mock.Tx], *stf.STF[mock.Tx]) { am, err := b.Build() require.NoError(t, err) - return NewConsensus[mock.Tx](am, mempool.NoOpMempool[mock.Tx]{}, mockStore, Config{}, mock.TxCodec{}, log.NewNopLogger()), s + return NewConsensus[mock.Tx](log.NewNopLogger(), "testing-app", "authority", am, mempool.NoOpMempool[mock.Tx]{}, map[string]struct{}{}, nil, mockStore, Config{AppTomlConfig: DefaultAppTomlConfig()}, mock.TxCodec{}, "test"), s } var actorName = []byte("cookies") @@ -314,9 +378,6 @@ func stateCommitmentHas(t *testing.T, store types.Store, key string, version uin func stateCommitmentNoHas(t *testing.T, store types.Store, key string, version uint64) { t.Helper() - bz, err := store.GetStateCommitment().Get(actorName, version, []byte(key)) - // if not committed, should return version does not exist - require.Error(t, err) - require.Contains(t, err.Error(), "version does not exist") + bz, _ := store.GetStateCommitment().Get(actorName, version, []byte(key)) require.Equal(t, len(bz), 0) } diff --git a/server/v2/cometbft/go.mod b/server/v2/cometbft/go.mod index 4a911154f02f..8692576ebe67 100644 --- a/server/v2/cometbft/go.mod +++ b/server/v2/cometbft/go.mod @@ -51,6 +51,7 @@ require ( require ( buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/collections v0.4.0 // indirect + cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/depinject v1.0.0 // indirect cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 // indirect cosmossdk.io/math v1.3.0 // indirect From 9d604c9dc9657757126860776294bd182fb51d52 Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Wed, 7 Aug 2024 16:48:41 +0700 Subject: [PATCH 10/22] extend vote --- server/v2/cometbft/abci_test.go | 63 +++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/server/v2/cometbft/abci_test.go b/server/v2/cometbft/abci_test.go index 27884fc93c6c..48e7df942cf1 100644 --- a/server/v2/cometbft/abci_test.go +++ b/server/v2/cometbft/abci_test.go @@ -299,6 +299,69 @@ func TestConsensus_FinalizeBlock_MultiTxs(t *testing.T) { require.Equal(t, int64(endBlock), c.lastCommittedHeight.Load()) } +func TestConsensus_ExtendVote_Invalid(t *testing.T) { + c, s := setUpConsensus(t) + + addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { + cParams := &v1.ConsensusParams{ + Block: &v1.BlockParams{ + MaxGas: 5000000, + }, + Abci: &v1.ABCIParams{ + VoteExtensionsEnableHeight: 2, + }, + Feature: &v1.FeatureParams{ + VoteExtensionsEnableHeight: &gogotypes.Int64Value{Value: 2}, + }, + } + + kvSet(t, ctx, "query") + return &consensustypes.QueryParamsResponse{ + Params: cParams, + }, nil + }) + addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *consensustypes.MsgUpdateParams) (*consensustypes.MsgUpdateParams, error) { + kvSet(t, ctx, "exec") + return nil, nil + }) + + _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ + Time: time.Now(), + ChainId: "test", + InitialHeight: 1, + ConsensusParams: &v1.ConsensusParams{ + Block: &v1.BlockParams{ + MaxGas: 5000000, + }, + Abci: &v1.ABCIParams{ + VoteExtensionsEnableHeight: 2, + }, + Feature: &v1.FeatureParams{ + VoteExtensionsEnableHeight: &gogotypes.Int64Value{Value: 2}, + }, + }, + }) + require.NoError(t, err) + + // Votes not enabled yet + _, err = c.ExtendVote(context.Background(), &abciproto.ExtendVoteRequest{ + Height: 1, + }) + require.ErrorContains(t, err, "vote extensions are not enabled") + + // Empty extendVote handler + _, err = c.ExtendVote(context.Background(), &abciproto.ExtendVoteRequest{ + Height: 2, + }) + require.ErrorContains(t, err, "verify function was set") + + c.extendVote = DefaultServerOptions[mock.Tx]().ExtendVoteHandler + res, err := c.ExtendVote(context.Background(), &abciproto.ExtendVoteRequest{ + Height: 2, + }) + fmt.Println(res, err) +} + func setUpConsensus(t *testing.T) (*Consensus[mock.Tx], *stf.STF[mock.Tx]) { s, err := stf.NewSTF( log.NewNopLogger().With("module", "stf"), From d4866d90641ab2d62c587a6fe9db35ee8a4c872c Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Thu, 8 Aug 2024 15:59:41 +0700 Subject: [PATCH 11/22] vote --- server/v2/cometbft/abci_test.go | 71 ++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/server/v2/cometbft/abci_test.go b/server/v2/cometbft/abci_test.go index 48e7df942cf1..103bbe237f0b 100644 --- a/server/v2/cometbft/abci_test.go +++ b/server/v2/cometbft/abci_test.go @@ -299,7 +299,7 @@ func TestConsensus_FinalizeBlock_MultiTxs(t *testing.T) { require.Equal(t, int64(endBlock), c.lastCommittedHeight.Load()) } -func TestConsensus_ExtendVote_Invalid(t *testing.T) { +func TestConsensus_ExtendVote(t *testing.T) { c, s := setUpConsensus(t) addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { @@ -355,11 +355,78 @@ func TestConsensus_ExtendVote_Invalid(t *testing.T) { }) require.ErrorContains(t, err, "verify function was set") + // Use NoOp handler c.extendVote = DefaultServerOptions[mock.Tx]().ExtendVoteHandler res, err := c.ExtendVote(context.Background(), &abciproto.ExtendVoteRequest{ Height: 2, }) - fmt.Println(res, err) + require.NoError(t, err) + require.Equal(t, len(res.VoteExtension), 0) +} + +func TestConsensus_VerifyVoteExtension(t *testing.T) { + c, s := setUpConsensus(t) + + addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { + cParams := &v1.ConsensusParams{ + Block: &v1.BlockParams{ + MaxGas: 5000000, + }, + Abci: &v1.ABCIParams{ + VoteExtensionsEnableHeight: 2, + }, + Feature: &v1.FeatureParams{ + VoteExtensionsEnableHeight: &gogotypes.Int64Value{Value: 2}, + }, + } + return &consensustypes.QueryParamsResponse{ + Params: cParams, + }, nil + }) + addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *consensustypes.MsgUpdateParams) (*consensustypes.MsgUpdateParams, error) { + kvSet(t, ctx, "exec") + return nil, nil + }) + + _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ + Time: time.Now(), + ChainId: "test", + InitialHeight: 1, + ConsensusParams: &v1.ConsensusParams{ + Block: &v1.BlockParams{ + MaxGas: 5000000, + }, + Abci: &v1.ABCIParams{ + VoteExtensionsEnableHeight: 2, + }, + Feature: &v1.FeatureParams{ + VoteExtensionsEnableHeight: &gogotypes.Int64Value{Value: 2}, + }, + }, + }) + require.NoError(t, err) + + // Votes not enabled yet + _, err = c.VerifyVoteExtension(context.Background(), &abciproto.VerifyVoteExtensionRequest{ + Height: 1, + }) + require.ErrorContains(t, err, "vote extensions are not enabled") + + // Empty verifyVote handler + _, err = c.VerifyVoteExtension(context.Background(), &abciproto.VerifyVoteExtensionRequest{ + Height: 2, + }) + require.ErrorContains(t, err, "verify function was set") + + // Use NoOp handler + c.verifyVoteExt = DefaultServerOptions[mock.Tx]().VerifyVoteExtensionHandler + res, err := c.VerifyVoteExtension(context.Background(), &abciproto.VerifyVoteExtensionRequest{ + Height: 2, + Hash: []byte("test"), + }) + fmt.Println("res", res, err) + require.NoError(t, err) + require.Equal(t, res.Status, abciproto.VERIFY_VOTE_EXTENSION_STATUS_ACCEPT) } func setUpConsensus(t *testing.T) (*Consensus[mock.Tx], *stf.STF[mock.Tx]) { From 07f4fa3267c1b2344f3d29be683298a245313146 Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Fri, 9 Aug 2024 15:14:38 +0700 Subject: [PATCH 12/22] check tx & prepare proposal --- server/v2/cometbft/abci_test.go | 224 +++++++++++++++++++++++++++++--- 1 file changed, 208 insertions(+), 16 deletions(-) diff --git a/server/v2/cometbft/abci_test.go b/server/v2/cometbft/abci_test.go index 103bbe237f0b..a9de4ed48b94 100644 --- a/server/v2/cometbft/abci_test.go +++ b/server/v2/cometbft/abci_test.go @@ -15,6 +15,7 @@ import ( "cosmossdk.io/server/v2/cometbft/mempool" cometmock "cosmossdk.io/server/v2/cometbft/mock" "cosmossdk.io/server/v2/cometbft/types" + "cosmossdk.io/server/v2/cometbft/handlers" "cosmossdk.io/server/v2/stf" "cosmossdk.io/server/v2/stf/branch" "cosmossdk.io/server/v2/stf/mock" @@ -37,11 +38,16 @@ var ( MaxGas: 5000000, }, } - anyMsg, _ = gogotypes.MarshalAny(&gogotypes.BoolValue{Value: true}) mockTx = mock.Tx{ Sender: []byte("sender"), - Msg: anyMsg, // msg does not matter at all because our handler does nothing. - GasLimit: 100_000, // NO GAS! + Msg: &gogotypes.BoolValue{Value: true}, + GasLimit: 100_000, + } + + invalidMockTx = mock.Tx{ + Sender: []byte("sender"), + Msg: &gogotypes.BoolValue{Value: true}, + GasLimit: 0, } ) @@ -112,7 +118,7 @@ func addQueryHandlerToSTF[T any, PT interface { } func TestConsensus_InitChain_Without_UpdateParam(t *testing.T) { - c, _ := setUpConsensus(t) + c, _ := setUpConsensus(t, 100_000) mockStore := c.store _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ Time: time.Now(), @@ -137,7 +143,7 @@ func TestConsensus_InitChain_Without_UpdateParam(t *testing.T) { } func TestConsensus_InitChain_With_UpdateParam(t *testing.T) { - c, s := setUpConsensus(t) + c, s := setUpConsensus(t, 100_000) mockStore := c.store addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *consensustypes.MsgUpdateParams) (*consensustypes.MsgUpdateParams, error) { kvSet(t, ctx, "exec") @@ -170,7 +176,7 @@ func TestConsensus_InitChain_With_UpdateParam(t *testing.T) { } func TestConsensus_InitChain_Invalid_Height(t *testing.T) { - c, _ := setUpConsensus(t) + c, _ := setUpConsensus(t, 100_000) mockStore := c.store _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ Time: time.Now(), @@ -191,7 +197,7 @@ func TestConsensus_InitChain_Invalid_Height(t *testing.T) { } func TestConsensus_FinalizeBlock_Invalid_Height(t *testing.T) { - c, _ := setUpConsensus(t) + c, _ := setUpConsensus(t, 100_000) _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ Time: time.Now(), ChainId: "test", @@ -214,7 +220,7 @@ func TestConsensus_FinalizeBlock_Invalid_Height(t *testing.T) { } func TestConsensus_FinalizeBlock_NoTxs(t *testing.T) { - c, s := setUpConsensus(t) + c, s := setUpConsensus(t, 100_000) mockStore := c.store addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { @@ -254,8 +260,52 @@ func TestConsensus_FinalizeBlock_NoTxs(t *testing.T) { require.Equal(t, int64(endBlock), c.lastCommittedHeight.Load()) } +func TestConsensus_FinalizeBlock_MultiTxs_OutOfGas(t *testing.T) { + c, s := setUpConsensus(t, 100_000) + + addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { + cParams := DefaulConsensusParams + kvSet(t, ctx, "query") + return &consensustypes.QueryParamsResponse{ + Params: cParams, + }, nil + }) + addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *gogotypes.BoolValue) (*gogotypes.BoolValue, error) { + kvSet(t, ctx, "exec") + return nil, nil + }) + + _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ + Time: time.Now(), + ChainId: "test", + InitialHeight: 1, + }) + require.NoError(t, err) + + _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ + Time: time.Now(), + Height: 1, + }) + require.NoError(t, err) + + endBlock := 10 + for i := 2; i <= endBlock; i++ { + res, err := c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ + Time: time.Now(), + Height: int64(i), + Hash: sum[:], + Txs: [][]byte{invalidMockTx.Bytes()}, + }) + fmt.Println("res", res, err) + require.NoError(t, err) + require.NotEqual(t, res.TxResults[0].Code, 0) + require.Contains(t, res.TxResults[0].Log, "out of gas") + } + require.Equal(t, int64(endBlock), c.lastCommittedHeight.Load()) +} + func TestConsensus_FinalizeBlock_MultiTxs(t *testing.T) { - c, s := setUpConsensus(t) + c, s := setUpConsensus(t, 100_000) mockStore := c.store addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { @@ -265,7 +315,7 @@ func TestConsensus_FinalizeBlock_MultiTxs(t *testing.T) { Params: cParams, }, nil }) - addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *gogotypes.Any) (*gogotypes.Any, error) { + addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *gogotypes.BoolValue) (*gogotypes.BoolValue, error) { kvSet(t, ctx, "exec") return nil, nil }) @@ -299,8 +349,53 @@ func TestConsensus_FinalizeBlock_MultiTxs(t *testing.T) { require.Equal(t, int64(endBlock), c.lastCommittedHeight.Load()) } +func TestConsensus_CheckTx(t *testing.T) { + c, s := setUpConsensus(t, 0) + + addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *gogotypes.BoolValue) (*gogotypes.BoolValue, error) { + kvSet(t, ctx, "exec") + return nil, nil + }) + + _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ + Time: time.Now(), + ChainId: "test", + InitialHeight: 1, + }) + require.NoError(t, err) + + // empty byte + _, err = c.CheckTx(context.Background(), &abciproto.CheckTxRequest{ + Tx: []byte{}, + }) + require.Error(t, err) + + // out of gas + res, err := c.CheckTx(context.Background(), &abciproto.CheckTxRequest{ + Tx: mock.Tx{ + Sender: []byte("sender"), + Msg: &gogotypes.BoolValue{Value: true}, + GasLimit: 100_000, + }.Bytes(), + }) + require.NoError(t, err) + require.Contains(t, res.Log, "out of gas") + require.NotEqual(t, res.Code, 0) + + c, _ = setUpConsensus(t, 100_000) + res, err = c.CheckTx(context.Background(), &abciproto.CheckTxRequest{ + Tx: mock.Tx{ + Sender: []byte("sender"), + Msg: &gogotypes.BoolValue{Value: true}, + GasLimit: 100_000, + }.Bytes(), + }) + require.NoError(t, err) + require.NotEqual(t, res.GasUsed, 0) +} + func TestConsensus_ExtendVote(t *testing.T) { - c, s := setUpConsensus(t) + c, s := setUpConsensus(t, 100_000) addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { cParams := &v1.ConsensusParams{ @@ -365,7 +460,7 @@ func TestConsensus_ExtendVote(t *testing.T) { } func TestConsensus_VerifyVoteExtension(t *testing.T) { - c, s := setUpConsensus(t) + c, s := setUpConsensus(t, 100_000) addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { cParams := &v1.ConsensusParams{ @@ -429,7 +524,104 @@ func TestConsensus_VerifyVoteExtension(t *testing.T) { require.Equal(t, res.Status, abciproto.VERIFY_VOTE_EXTENSION_STATUS_ACCEPT) } -func setUpConsensus(t *testing.T) (*Consensus[mock.Tx], *stf.STF[mock.Tx]) { +func TestConsensus_PrepareProposal(t *testing.T) { + c, _ := setUpConsensus(t, 100_000) + + // Invalid height + _, err := c.PrepareProposal(context.Background(), &abciproto.PrepareProposalRequest{ + Height: 0, + }) + require.Error(t, err) + + // empty handler + _, err = c.PrepareProposal(context.Background(), &abciproto.PrepareProposalRequest{ + Height: 1, + }) + require.Error(t, err) + + // NoOp handler + c.prepareProposalHandler = DefaultServerOptions[mock.Tx]().PrepareProposalHandler + _, err = c.PrepareProposal(context.Background(), &abciproto.PrepareProposalRequest{ + Height: 1, + Txs: [][]byte{mockTx.Bytes()}, + }) + require.NoError(t, err) +} + +func TestConsensus_PrepareProposal_With_Handler_NoOpMempool(t *testing.T) { + c, s := setUpConsensus(t, 100_000) + + addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { + cParams := &v1.ConsensusParams{ + Block: &v1.BlockParams{ + MaxGas: 300_000, + }, + } + return &consensustypes.QueryParamsResponse{ + Params: cParams, + }, nil + }) + + c.prepareProposalHandler = handlers.NewDefaultProposalHandler(c.mempool).PrepareHandler() + + // zero MaxTxBytes + res, err := c.PrepareProposal(context.Background(), &abciproto.PrepareProposalRequest{ + Height: 1, + MaxTxBytes: 0, + Txs: [][]byte{mockTx.Bytes()}, + }) + require.NoError(t, err) + require.Equal(t, len(res.Txs), 0) + + // have tx exeed MaxTxBytes + // each mock tx has 128 bytes, should select 2 txs + res, err = c.PrepareProposal(context.Background(), &abciproto.PrepareProposalRequest{ + Height: 1, + MaxTxBytes: 300, + Txs: [][]byte{mockTx.Bytes(), mockTx.Bytes(), mockTx.Bytes()}, + }) + require.NoError(t, err) + require.Equal(t, len(res.Txs), 2) + + // reach MaxTxBytes + res, err = c.PrepareProposal(context.Background(), &abciproto.PrepareProposalRequest{ + Height: 1, + MaxTxBytes: 256, + Txs: [][]byte{mockTx.Bytes(), mockTx.Bytes()}, + }) + require.NoError(t, err) + require.Equal(t, len(res.Txs), 2) + + // Over gas, under MaxTxBytes + // 300_000 gas limit, should only take 3 txs + res, err = c.PrepareProposal(context.Background(), &abciproto.PrepareProposalRequest{ + Height: 1, + MaxTxBytes: 1000, + Txs: [][]byte{mockTx.Bytes(), mockTx.Bytes(), mockTx.Bytes(), mockTx.Bytes()}, + }) + require.NoError(t, err) + require.Equal(t, len(res.Txs), 3) + + // Reach max gas + res, err = c.PrepareProposal(context.Background(), &abciproto.PrepareProposalRequest{ + Height: 1, + MaxTxBytes: 1000, + Txs: [][]byte{mockTx.Bytes(), mockTx.Bytes(), mockTx.Bytes()}, + }) + require.NoError(t, err) + require.Equal(t, len(res.Txs), 3) + + // have a bad encoding tx + res, err = c.PrepareProposal(context.Background(), &abciproto.PrepareProposalRequest{ + Height: 1, + MaxTxBytes: 1000, + Txs: [][]byte{mockTx.Bytes(), append(mockTx.Bytes(), []byte("bad")...), mockTx.Bytes()}, + }) + require.NoError(t, err) + require.Equal(t, len(res.Txs), 2) +} + +func setUpConsensus(t *testing.T, gasLimit uint64) (*Consensus[mock.Tx], *stf.STF[mock.Tx]) { s, err := stf.NewSTF( log.NewNopLogger().With("module", "stf"), stf.NewMsgRouterBuilder(), @@ -459,9 +651,9 @@ func setUpConsensus(t *testing.T) (*Consensus[mock.Tx], *stf.STF[mock.Tx]) { b := am.Builder[mock.Tx]{ STF: s, DB: mockStore, - ValidateTxGasLimit: 100_000, - QueryGasLimit: 100_000, - SimulationGasLimit: 100_000, + ValidateTxGasLimit: gasLimit, + QueryGasLimit: gasLimit, + SimulationGasLimit: gasLimit, InitGenesis: func(ctx context.Context, src io.Reader, txHandler func(json.RawMessage) error) error { return kvSet(t, ctx, "init-chain") }, From ee055b823aefff8d831b2a37ca5dc7ba2eb9df66 Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Fri, 9 Aug 2024 16:15:12 +0700 Subject: [PATCH 13/22] process proposal --- server/v2/cometbft/abci_test.go | 117 ++++++++++++++++++++++++++++---- 1 file changed, 102 insertions(+), 15 deletions(-) diff --git a/server/v2/cometbft/abci_test.go b/server/v2/cometbft/abci_test.go index a9de4ed48b94..fec55622f540 100644 --- a/server/v2/cometbft/abci_test.go +++ b/server/v2/cometbft/abci_test.go @@ -118,7 +118,7 @@ func addQueryHandlerToSTF[T any, PT interface { } func TestConsensus_InitChain_Without_UpdateParam(t *testing.T) { - c, _ := setUpConsensus(t, 100_000) + c, _ := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) mockStore := c.store _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ Time: time.Now(), @@ -143,7 +143,7 @@ func TestConsensus_InitChain_Without_UpdateParam(t *testing.T) { } func TestConsensus_InitChain_With_UpdateParam(t *testing.T) { - c, s := setUpConsensus(t, 100_000) + c, s := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) mockStore := c.store addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *consensustypes.MsgUpdateParams) (*consensustypes.MsgUpdateParams, error) { kvSet(t, ctx, "exec") @@ -176,7 +176,7 @@ func TestConsensus_InitChain_With_UpdateParam(t *testing.T) { } func TestConsensus_InitChain_Invalid_Height(t *testing.T) { - c, _ := setUpConsensus(t, 100_000) + c, _ := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) mockStore := c.store _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ Time: time.Now(), @@ -197,7 +197,7 @@ func TestConsensus_InitChain_Invalid_Height(t *testing.T) { } func TestConsensus_FinalizeBlock_Invalid_Height(t *testing.T) { - c, _ := setUpConsensus(t, 100_000) + c, _ := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ Time: time.Now(), ChainId: "test", @@ -220,7 +220,7 @@ func TestConsensus_FinalizeBlock_Invalid_Height(t *testing.T) { } func TestConsensus_FinalizeBlock_NoTxs(t *testing.T) { - c, s := setUpConsensus(t, 100_000) + c, s := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) mockStore := c.store addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { @@ -261,7 +261,7 @@ func TestConsensus_FinalizeBlock_NoTxs(t *testing.T) { } func TestConsensus_FinalizeBlock_MultiTxs_OutOfGas(t *testing.T) { - c, s := setUpConsensus(t, 100_000) + c, s := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { cParams := DefaulConsensusParams @@ -305,7 +305,7 @@ func TestConsensus_FinalizeBlock_MultiTxs_OutOfGas(t *testing.T) { } func TestConsensus_FinalizeBlock_MultiTxs(t *testing.T) { - c, s := setUpConsensus(t, 100_000) + c, s := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) mockStore := c.store addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { @@ -350,7 +350,7 @@ func TestConsensus_FinalizeBlock_MultiTxs(t *testing.T) { } func TestConsensus_CheckTx(t *testing.T) { - c, s := setUpConsensus(t, 0) + c, s := setUpConsensus(t, 0, mempool.NoOpMempool[mock.Tx]{}) addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *gogotypes.BoolValue) (*gogotypes.BoolValue, error) { kvSet(t, ctx, "exec") @@ -382,7 +382,7 @@ func TestConsensus_CheckTx(t *testing.T) { require.Contains(t, res.Log, "out of gas") require.NotEqual(t, res.Code, 0) - c, _ = setUpConsensus(t, 100_000) + c, _ = setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) res, err = c.CheckTx(context.Background(), &abciproto.CheckTxRequest{ Tx: mock.Tx{ Sender: []byte("sender"), @@ -395,7 +395,7 @@ func TestConsensus_CheckTx(t *testing.T) { } func TestConsensus_ExtendVote(t *testing.T) { - c, s := setUpConsensus(t, 100_000) + c, s := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { cParams := &v1.ConsensusParams{ @@ -460,7 +460,7 @@ func TestConsensus_ExtendVote(t *testing.T) { } func TestConsensus_VerifyVoteExtension(t *testing.T) { - c, s := setUpConsensus(t, 100_000) + c, s := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { cParams := &v1.ConsensusParams{ @@ -525,7 +525,7 @@ func TestConsensus_VerifyVoteExtension(t *testing.T) { } func TestConsensus_PrepareProposal(t *testing.T) { - c, _ := setUpConsensus(t, 100_000) + c, _ := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) // Invalid height _, err := c.PrepareProposal(context.Background(), &abciproto.PrepareProposalRequest{ @@ -549,7 +549,7 @@ func TestConsensus_PrepareProposal(t *testing.T) { } func TestConsensus_PrepareProposal_With_Handler_NoOpMempool(t *testing.T) { - c, s := setUpConsensus(t, 100_000) + c, s := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { cParams := &v1.ConsensusParams{ @@ -621,7 +621,94 @@ func TestConsensus_PrepareProposal_With_Handler_NoOpMempool(t *testing.T) { require.Equal(t, len(res.Txs), 2) } -func setUpConsensus(t *testing.T, gasLimit uint64) (*Consensus[mock.Tx], *stf.STF[mock.Tx]) { +func TestConsensus_ProcessProposal(t *testing.T) { + c, _ := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) + + // Invalid height + _, err := c.ProcessProposal(context.Background(), &abciproto.ProcessProposalRequest{ + Height: 0, + }) + require.Error(t, err) + + // empty handler + _, err = c.ProcessProposal(context.Background(), &abciproto.ProcessProposalRequest{ + Height: 1, + }) + require.Error(t, err) + + // NoOp handler + c.processProposalHandler = DefaultServerOptions[mock.Tx]().ProcessProposalHandler + _, err = c.ProcessProposal(context.Background(), &abciproto.ProcessProposalRequest{ + Height: 1, + Txs: [][]byte{mockTx.Bytes()}, + }) + require.NoError(t, err) + + // have bad encode tx + _, err = c.ProcessProposal(context.Background(), &abciproto.ProcessProposalRequest{ + Height: 1, + Txs: [][]byte{mockTx.Bytes(), append(mockTx.Bytes(), []byte("bad")...), mockTx.Bytes()}, + }) + fmt.Println("err bad encode", err) + require.Error(t, err) +} + +func TestConsensus_ProcessProposal_With_Handler_OutOfGas(t *testing.T) { + c, s := setUpConsensus(t, 0, cometmock.MockMempool[mock.Tx]{}) + c.processProposalHandler = handlers.NewDefaultProposalHandler(c.mempool).ProcessHandler() + addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { + cParams := &v1.ConsensusParams{ + Block: &v1.BlockParams{ + MaxGas: 300_000, + }, + } + return &consensustypes.QueryParamsResponse{ + Params: cParams, + }, nil + }) + res, err := c.ProcessProposal(context.Background(), &abciproto.ProcessProposalRequest{ + Height: 1, + Txs: [][]byte{invalidMockTx.Bytes(), invalidMockTx.Bytes(), invalidMockTx.Bytes()}, + }) + require.NoError(t, err) + require.Equal(t, res.Status, abciproto.PROCESS_PROPOSAL_STATUS_REJECT) +} + +func TestConsensus_ProcessProposal_With_Handler(t *testing.T) { + c, s := setUpConsensus(t, 100_000, cometmock.MockMempool[mock.Tx]{}) + + addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { + cParams := &v1.ConsensusParams{ + Block: &v1.BlockParams{ + MaxGas: 300_000, + }, + } + return &consensustypes.QueryParamsResponse{ + Params: cParams, + }, nil + }) + + c.processProposalHandler = handlers.NewDefaultProposalHandler(c.mempool).ProcessHandler() + + // exeed max gas + res, err := c.ProcessProposal(context.Background(), &abciproto.ProcessProposalRequest{ + Height: 1, + Txs: [][]byte{mockTx.Bytes(), mockTx.Bytes(), mockTx.Bytes(), mockTx.Bytes()}, + }) + require.NoError(t, err) + require.Equal(t, res.Status, abciproto.PROCESS_PROPOSAL_STATUS_REJECT) + + // have bad encode tx + // should remove that tx and accept + res, err = c.ProcessProposal(context.Background(), &abciproto.ProcessProposalRequest{ + Height: 1, + Txs: [][]byte{mockTx.Bytes(), append(mockTx.Bytes(), []byte("bad")...), mockTx.Bytes(), mockTx.Bytes()}, + }) + fmt.Println(res, err) + require.Equal(t, res.Status, abciproto.PROCESS_PROPOSAL_STATUS_ACCEPT) +} + +func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock.Tx]) (*Consensus[mock.Tx], *stf.STF[mock.Tx]) { s, err := stf.NewSTF( log.NewNopLogger().With("module", "stf"), stf.NewMsgRouterBuilder(), @@ -662,7 +749,7 @@ func setUpConsensus(t *testing.T, gasLimit uint64) (*Consensus[mock.Tx], *stf.ST am, err := b.Build() require.NoError(t, err) - return NewConsensus[mock.Tx](log.NewNopLogger(), "testing-app", "authority", am, mempool.NoOpMempool[mock.Tx]{}, map[string]struct{}{}, nil, mockStore, Config{AppTomlConfig: DefaultAppTomlConfig()}, mock.TxCodec{}, "test"), s + return NewConsensus[mock.Tx](log.NewNopLogger(), "testing-app", "authority", am, mempool, map[string]struct{}{}, nil, mockStore, Config{AppTomlConfig: DefaultAppTomlConfig()}, mock.TxCodec{}, "test"), s } var actorName = []byte("cookies") From 35787e2ce2409280803b4294f92f1d4edcdb0fdf Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Fri, 9 Aug 2024 16:16:54 +0700 Subject: [PATCH 14/22] mock mempool --- server/v2/cometbft/mock/mock_mempool.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 server/v2/cometbft/mock/mock_mempool.go diff --git a/server/v2/cometbft/mock/mock_mempool.go b/server/v2/cometbft/mock/mock_mempool.go new file mode 100644 index 000000000000..67a8116ad480 --- /dev/null +++ b/server/v2/cometbft/mock/mock_mempool.go @@ -0,0 +1,23 @@ +package mock + +import ( + "context" + + "cosmossdk.io/core/transaction" + "cosmossdk.io/server/v2/cometbft/mempool" +) + +var _ mempool.Mempool[transaction.Tx] = (*MockMempool[transaction.Tx])(nil) + +// MockMempool defines a no-op mempool. Transactions are completely discarded and +// ignored when BaseApp interacts with the mempool. +// +// Note: When this mempool is used, it assumed that an application will rely +// on CometBFT's transaction ordering defined in `RequestPrepareProposal`, which +// is FIFO-ordered by default. +type MockMempool[T transaction.Tx] struct{} + +func (MockMempool[T]) Insert(context.Context, T) error { return nil } +func (MockMempool[T]) Select(context.Context, []T) mempool.Iterator[T] { return nil } +func (MockMempool[T]) CountTx() int { return 0 } +func (MockMempool[T]) Remove([]T) error { return nil } From 7bf135cc65c462b1f59d15b9c8be5bb21c674142 Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Wed, 14 Aug 2024 16:38:34 +0700 Subject: [PATCH 15/22] clean up --- server/v2/appmanager/appmanager.go | 3 --- server/v2/cometbft/abci.go | 1 - server/v2/cometbft/utils.go | 2 -- server/v2/stf/mock/tx.go | 3 --- server/v2/stf/stf.go | 4 +--- server/v2/stf/stf_router.go | 2 -- 6 files changed, 1 insertion(+), 14 deletions(-) diff --git a/server/v2/appmanager/appmanager.go b/server/v2/appmanager/appmanager.go index c883a7578885..66e38a762a18 100644 --- a/server/v2/appmanager/appmanager.go +++ b/server/v2/appmanager/appmanager.go @@ -148,9 +148,6 @@ func (a AppManager[T]) Query(ctx context.Context, version uint64, request transa if err != nil { return nil, err } - fmt.Println("queryState", queryState) - fmt.Println("a.config.QueryGasLimit", a.config.QueryGasLimit) - fmt.Println("request", request, request.String()) return a.stf.Query(ctx, queryState, a.config.QueryGasLimit, request) } diff --git a/server/v2/cometbft/abci.go b/server/v2/cometbft/abci.go index 6cd28b30f7f1..b7a300b05f5e 100644 --- a/server/v2/cometbft/abci.go +++ b/server/v2/cometbft/abci.go @@ -496,7 +496,6 @@ func (c *Consensus[T]) FinalizeBlock( c.lastCommittedHeight.Store(req.Height) cp, err := c.GetConsensusParams(ctx) // we get the consensus params from the latest state because we committed state above - fmt.Println("GetConsensusParams", cp, err) if err != nil { return nil, err } diff --git a/server/v2/cometbft/utils.go b/server/v2/cometbft/utils.go index 1f431e8aa837..594e046ad173 100644 --- a/server/v2/cometbft/utils.go +++ b/server/v2/cometbft/utils.go @@ -263,7 +263,6 @@ func (c *Consensus[T]) validateFinalizeBlockHeight(req *abci.FinalizeBlockReques } lastBlockHeight, _, err := c.store.StateLatest() - fmt.Println("lastBlockHeight", lastBlockHeight) if err != nil { return err } @@ -299,7 +298,6 @@ func (c *Consensus[T]) GetConsensusParams(ctx context.Context) (*cmtproto.Consen } res, err := c.app.Query(ctx, latestVersion, &consensus.QueryParamsRequest{}) - fmt.Println("c.app.Query", res, err) if err != nil { return nil, err } diff --git a/server/v2/stf/mock/tx.go b/server/v2/stf/mock/tx.go index a24e4178aa6c..7df7bc0e3208 100644 --- a/server/v2/stf/mock/tx.go +++ b/server/v2/stf/mock/tx.go @@ -4,7 +4,6 @@ import ( "crypto/sha256" "encoding/json" "errors" - "fmt" "reflect" "github.com/cosmos/gogoproto/proto" @@ -68,9 +67,7 @@ func (t Tx) Bytes() []byte { func (t *Tx) Decode(b []byte) error { rawTx := new(encodedTx) - fmt.Println("Decode", rawTx, b) err := json.Unmarshal(b, rawTx) - fmt.Println("after", rawTx, err) if err != nil { return err } diff --git a/server/v2/stf/stf.go b/server/v2/stf/stf.go index 0b35d7340488..d3cd2405b23b 100644 --- a/server/v2/stf/stf.go +++ b/server/v2/stf/stf.go @@ -453,9 +453,7 @@ func (s STF[T]) Query( queryCtx := s.makeContext(ctx, nil, queryState, internal.ExecModeSimulate) queryCtx.setHeaderInfo(hi) queryCtx.setGasLimit(gasLimit) - res, err := s.queryRouter.InvokeUntyped(queryCtx, req) - fmt.Println("InvokeUntyped", res, err) - return res, err + return s.queryRouter.InvokeUntyped(queryCtx, req) } // RunWithCtx is made to support genesis, if genesis was just the execution of messages instead diff --git a/server/v2/stf/stf_router.go b/server/v2/stf/stf_router.go index 1a6b5a755aa6..41d5b805c612 100644 --- a/server/v2/stf/stf_router.go +++ b/server/v2/stf/stf_router.go @@ -170,9 +170,7 @@ func (r coreRouterImpl) InvokeTyped(ctx context.Context, req, resp transaction.M func (r coreRouterImpl) InvokeUntyped(ctx context.Context, req transaction.Msg) (res transaction.Msg, err error) { typeName := msgTypeURL(req) - fmt.Println("typeName", typeName) handler, exists := r.handlers[typeName] - fmt.Println("handler", exists) if !exists { return nil, fmt.Errorf("%w: %s", ErrNoHandler, typeName) } From 76ffcaf00ff1e499751ac44810e9685ca22079a8 Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Thu, 22 Aug 2024 20:25:49 +0700 Subject: [PATCH 16/22] more tests --- server/v2/cometbft/abci_test.go | 149 +++++++++++++++++++++----- server/v2/cometbft/mock/mock_store.go | 3 +- 2 files changed, 122 insertions(+), 30 deletions(-) diff --git a/server/v2/cometbft/abci_test.go b/server/v2/cometbft/abci_test.go index 6ba05e85e7db..7080eaabad29 100644 --- a/server/v2/cometbft/abci_test.go +++ b/server/v2/cometbft/abci_test.go @@ -3,7 +3,6 @@ package cometbft import ( "context" "crypto/sha256" - "fmt" "io" "strings" "testing" @@ -42,13 +41,13 @@ var ( mockTx = mock.Tx{ Sender: []byte("sender"), Msg: &gogotypes.BoolValue{Value: true}, - GasLimit: 100_000, + GasLimit: 100_000, } invalidMockTx = mock.Tx{ Sender: []byte("sender"), Msg: &gogotypes.BoolValue{Value: true}, - GasLimit: 0, + GasLimit: 0, } ) @@ -210,7 +209,6 @@ func TestConsensus_FinalizeBlock_Invalid_Height(t *testing.T) { Height: 3, }) require.Error(t, err) - fmt.Println(err) } func TestConsensus_FinalizeBlock_NoTxs(t *testing.T) { @@ -290,7 +288,6 @@ func TestConsensus_FinalizeBlock_MultiTxs_OutOfGas(t *testing.T) { Hash: sum[:], Txs: [][]byte{invalidMockTx.Bytes()}, }) - fmt.Println("res", res, err) require.NoError(t, err) require.NotEqual(t, res.TxResults[0].Code, 0) require.Contains(t, res.TxResults[0].Log, "out of gas") @@ -511,9 +508,8 @@ func TestConsensus_VerifyVoteExtension(t *testing.T) { c.verifyVoteExt = DefaultServerOptions[mock.Tx]().VerifyVoteExtensionHandler res, err := c.VerifyVoteExtension(context.Background(), &abciproto.VerifyVoteExtensionRequest{ Height: 2, - Hash: []byte("test"), + Hash: []byte("test"), }) - fmt.Println("res", res, err) require.NoError(t, err) require.Equal(t, res.Status, abciproto.VERIFY_VOTE_EXTENSION_STATUS_ACCEPT) } @@ -537,7 +533,7 @@ func TestConsensus_PrepareProposal(t *testing.T) { c.prepareProposalHandler = DefaultServerOptions[mock.Tx]().PrepareProposalHandler _, err = c.PrepareProposal(context.Background(), &abciproto.PrepareProposalRequest{ Height: 1, - Txs: [][]byte{mockTx.Bytes()}, + Txs: [][]byte{mockTx.Bytes()}, }) require.NoError(t, err) } @@ -557,12 +553,12 @@ func TestConsensus_PrepareProposal_With_Handler_NoOpMempool(t *testing.T) { }) c.prepareProposalHandler = handlers.NewDefaultProposalHandler(c.mempool).PrepareHandler() - + // zero MaxTxBytes res, err := c.PrepareProposal(context.Background(), &abciproto.PrepareProposalRequest{ - Height: 1, + Height: 1, MaxTxBytes: 0, - Txs: [][]byte{mockTx.Bytes()}, + Txs: [][]byte{mockTx.Bytes()}, }) require.NoError(t, err) require.Equal(t, len(res.Txs), 0) @@ -570,18 +566,18 @@ func TestConsensus_PrepareProposal_With_Handler_NoOpMempool(t *testing.T) { // have tx exeed MaxTxBytes // each mock tx has 128 bytes, should select 2 txs res, err = c.PrepareProposal(context.Background(), &abciproto.PrepareProposalRequest{ - Height: 1, + Height: 1, MaxTxBytes: 300, - Txs: [][]byte{mockTx.Bytes(), mockTx.Bytes(), mockTx.Bytes()}, + Txs: [][]byte{mockTx.Bytes(), mockTx.Bytes(), mockTx.Bytes()}, }) require.NoError(t, err) require.Equal(t, len(res.Txs), 2) // reach MaxTxBytes res, err = c.PrepareProposal(context.Background(), &abciproto.PrepareProposalRequest{ - Height: 1, + Height: 1, MaxTxBytes: 256, - Txs: [][]byte{mockTx.Bytes(), mockTx.Bytes()}, + Txs: [][]byte{mockTx.Bytes(), mockTx.Bytes()}, }) require.NoError(t, err) require.Equal(t, len(res.Txs), 2) @@ -589,27 +585,27 @@ func TestConsensus_PrepareProposal_With_Handler_NoOpMempool(t *testing.T) { // Over gas, under MaxTxBytes // 300_000 gas limit, should only take 3 txs res, err = c.PrepareProposal(context.Background(), &abciproto.PrepareProposalRequest{ - Height: 1, + Height: 1, MaxTxBytes: 1000, - Txs: [][]byte{mockTx.Bytes(), mockTx.Bytes(), mockTx.Bytes(), mockTx.Bytes()}, + Txs: [][]byte{mockTx.Bytes(), mockTx.Bytes(), mockTx.Bytes(), mockTx.Bytes()}, }) require.NoError(t, err) require.Equal(t, len(res.Txs), 3) // Reach max gas res, err = c.PrepareProposal(context.Background(), &abciproto.PrepareProposalRequest{ - Height: 1, + Height: 1, MaxTxBytes: 1000, - Txs: [][]byte{mockTx.Bytes(), mockTx.Bytes(), mockTx.Bytes()}, + Txs: [][]byte{mockTx.Bytes(), mockTx.Bytes(), mockTx.Bytes()}, }) require.NoError(t, err) require.Equal(t, len(res.Txs), 3) // have a bad encoding tx res, err = c.PrepareProposal(context.Background(), &abciproto.PrepareProposalRequest{ - Height: 1, + Height: 1, MaxTxBytes: 1000, - Txs: [][]byte{mockTx.Bytes(), append(mockTx.Bytes(), []byte("bad")...), mockTx.Bytes()}, + Txs: [][]byte{mockTx.Bytes(), append(mockTx.Bytes(), []byte("bad")...), mockTx.Bytes()}, }) require.NoError(t, err) require.Equal(t, len(res.Txs), 2) @@ -634,16 +630,15 @@ func TestConsensus_ProcessProposal(t *testing.T) { c.processProposalHandler = DefaultServerOptions[mock.Tx]().ProcessProposalHandler _, err = c.ProcessProposal(context.Background(), &abciproto.ProcessProposalRequest{ Height: 1, - Txs: [][]byte{mockTx.Bytes()}, + Txs: [][]byte{mockTx.Bytes()}, }) require.NoError(t, err) // have bad encode tx _, err = c.ProcessProposal(context.Background(), &abciproto.ProcessProposalRequest{ Height: 1, - Txs: [][]byte{mockTx.Bytes(), append(mockTx.Bytes(), []byte("bad")...), mockTx.Bytes()}, + Txs: [][]byte{mockTx.Bytes(), append(mockTx.Bytes(), []byte("bad")...), mockTx.Bytes()}, }) - fmt.Println("err bad encode", err) require.Error(t, err) } @@ -662,7 +657,7 @@ func TestConsensus_ProcessProposal_With_Handler_OutOfGas(t *testing.T) { }) res, err := c.ProcessProposal(context.Background(), &abciproto.ProcessProposalRequest{ Height: 1, - Txs: [][]byte{invalidMockTx.Bytes(), invalidMockTx.Bytes(), invalidMockTx.Bytes()}, + Txs: [][]byte{invalidMockTx.Bytes(), invalidMockTx.Bytes(), invalidMockTx.Bytes()}, }) require.NoError(t, err) require.Equal(t, res.Status, abciproto.PROCESS_PROPOSAL_STATUS_REJECT) @@ -687,7 +682,7 @@ func TestConsensus_ProcessProposal_With_Handler(t *testing.T) { // exeed max gas res, err := c.ProcessProposal(context.Background(), &abciproto.ProcessProposalRequest{ Height: 1, - Txs: [][]byte{mockTx.Bytes(), mockTx.Bytes(), mockTx.Bytes(), mockTx.Bytes()}, + Txs: [][]byte{mockTx.Bytes(), mockTx.Bytes(), mockTx.Bytes(), mockTx.Bytes()}, }) require.NoError(t, err) require.Equal(t, res.Status, abciproto.PROCESS_PROPOSAL_STATUS_REJECT) @@ -696,12 +691,110 @@ func TestConsensus_ProcessProposal_With_Handler(t *testing.T) { // should remove that tx and accept res, err = c.ProcessProposal(context.Background(), &abciproto.ProcessProposalRequest{ Height: 1, - Txs: [][]byte{mockTx.Bytes(), append(mockTx.Bytes(), []byte("bad")...), mockTx.Bytes(), mockTx.Bytes()}, + Txs: [][]byte{mockTx.Bytes(), append(mockTx.Bytes(), []byte("bad")...), mockTx.Bytes(), mockTx.Bytes()}, }) - fmt.Println(res, err) require.Equal(t, res.Status, abciproto.PROCESS_PROPOSAL_STATUS_ACCEPT) } +func TestConsensus_Info(t *testing.T) { + c, s := setUpConsensus(t, 100_000, cometmock.MockMempool[mock.Tx]{}) + + addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { + cParams := &v1.ConsensusParams{ + Block: &v1.BlockParams{ + MaxGas: 300_000, + }, + Version: &v1.VersionParams{ + App: 1, + }, + } + return &consensustypes.QueryParamsResponse{ + Params: cParams, + }, nil + }) + + // Version 0 + res, err := c.Info(context.Background(), &abciproto.InfoRequest{}) + require.NoError(t, err) + require.Equal(t, res.LastBlockHeight, int64(0)) + + // Commit store to version 1 + _, err = c.InitChain(context.Background(), &abciproto.InitChainRequest{ + Time: time.Now(), + ChainId: "test", + InitialHeight: 1, + }) + require.NoError(t, err) + + _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ + Time: time.Now(), + Height: 1, + }) + require.NoError(t, err) + + res, err = c.Info(context.Background(), &abciproto.InfoRequest{}) + require.NoError(t, err) + require.Equal(t, res.LastBlockHeight, int64(1)) +} + +// TODO: +// - GRPC request +// - app request +// - p2p request +func TestConsensus_Query(t *testing.T) { + c, s := setUpConsensus(t, 100_000, cometmock.MockMempool[mock.Tx]{}) + addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { + cParams := DefaulConsensusParams + return &consensustypes.QueryParamsResponse{ + Params: cParams, + }, nil + }) + addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *gogotypes.BoolValue) (*gogotypes.BoolValue, error) { + kvSet(t, ctx, "exec") + return nil, nil + }) + + _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ + Time: time.Now(), + ChainId: "test", + InitialHeight: 1, + }) + require.NoError(t, err) + + _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ + Time: time.Now(), + Height: 1, + Txs: [][]byte{mockTx.Bytes()}, + }) + require.NoError(t, err) + + stateStorageHas(t, c.store, "init-chain", 1) + + // empty request + res, err := c.Query(context.Background(), &abciproto.QueryRequest{}) + require.NoError(t, err) + require.Equal(t, res.Code, uint32(1)) + require.Contains(t, res.Log, "no query path provided") + + // Query store + res, err = c.Query(context.Background(), &abciproto.QueryRequest{ + Path: "store/cookies/", + Data: []byte("init-chain"), + Height: 1, + }) + require.NoError(t, err) + require.Equal(t, string(res.Value), "init-chain") + + // Query store with no value + res, err = c.Query(context.Background(), &abciproto.QueryRequest{ + Path: "store/cookies/", + Data: []byte("exec"), + Height: 1, + }) + require.NoError(t, err) + require.Equal(t, res.Value, []byte(nil)) +} + func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock.Tx]) (*Consensus[mock.Tx], *stf.STF[mock.Tx]) { s, err := stf.NewSTF( log.NewNopLogger().With("module", "stf"), diff --git a/server/v2/cometbft/mock/mock_store.go b/server/v2/cometbft/mock/mock_store.go index 90cee42750a6..4f71a9e09bc8 100644 --- a/server/v2/cometbft/mock/mock_store.go +++ b/server/v2/cometbft/mock/mock_store.go @@ -23,8 +23,7 @@ type MockStore struct { } func NewMockStorage(logger log.Logger, dir string) storev2.VersionedDatabase { - storageDB, err := sqlite.New(dir) - fmt.Println("storageDB", storageDB, err) + storageDB, _ := sqlite.New(dir) ss := storage.NewStorageStore(storageDB, logger) return ss } From c1c4159cefc7e9fe5dc48f4eca1ea508040026fe Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Fri, 30 Aug 2024 01:40:57 +0700 Subject: [PATCH 17/22] remove stf export & update tests --- server/v2/cometbft/abci_test.go | 352 ++++++++++---------------------- server/v2/stf/helper.go | 31 --- 2 files changed, 103 insertions(+), 280 deletions(-) delete mode 100644 server/v2/stf/helper.go diff --git a/server/v2/cometbft/abci_test.go b/server/v2/cometbft/abci_test.go index 7080eaabad29..a2c014f2e3de 100644 --- a/server/v2/cometbft/abci_test.go +++ b/server/v2/cometbft/abci_test.go @@ -9,6 +9,7 @@ import ( "time" appmodulev2 "cosmossdk.io/core/appmodule/v2" + "cosmossdk.io/core/store" "cosmossdk.io/core/transaction" "cosmossdk.io/log" am "cosmossdk.io/server/v2/appmanager" @@ -43,29 +44,28 @@ var ( Msg: &gogotypes.BoolValue{Value: true}, GasLimit: 100_000, } - invalidMockTx = mock.Tx{ Sender: []byte("sender"), Msg: &gogotypes.BoolValue{Value: true}, GasLimit: 0, } + actorName = []byte("cookies") ) -func addMsgHandlerToSTF[T any, PT interface { +func getQueryRouterBuilder[T any, PT interface { *T - transaction.Msg + proto.Message }, U any, UT interface { *U - transaction.Msg + proto.Message }]( t *testing.T, - s *stf.STF[mock.Tx], handler func(ctx context.Context, msg PT) (UT, error), -) { +) *stf.MsgRouterBuilder { t.Helper() - msgRouterBuilder := stf.NewMsgRouterBuilder() - err := msgRouterBuilder.RegisterHandler( + queryRouterBuilder := stf.NewMsgRouterBuilder() + err := queryRouterBuilder.RegisterHandler( proto.MessageName(PT(new(T))), func(ctx context.Context, msg transaction.Msg) (msgResp transaction.Msg, err error) { typedReq := msg.(PT) @@ -79,26 +79,23 @@ func addMsgHandlerToSTF[T any, PT interface { ) require.NoError(t, err) - msgRouter, err := msgRouterBuilder.Build() - require.NoError(t, err) - stf.SetMsgRouter(s, msgRouter) + return queryRouterBuilder } -func addQueryHandlerToSTF[T any, PT interface { +func getMsgRouterBuilder[T any, PT interface { *T - proto.Message + transaction.Msg }, U any, UT interface { *U - proto.Message + transaction.Msg }]( t *testing.T, - s *stf.STF[mock.Tx], handler func(ctx context.Context, msg PT) (UT, error), -) { +) *stf.MsgRouterBuilder { t.Helper() - queryRouterBuilder := stf.NewMsgRouterBuilder() - err := queryRouterBuilder.RegisterHandler( + msgRouterBuilder := stf.NewMsgRouterBuilder() + err := msgRouterBuilder.RegisterHandler( proto.MessageName(PT(new(T))), func(ctx context.Context, msg transaction.Msg) (msgResp transaction.Msg, err error) { typedReq := msg.(PT) @@ -112,13 +109,11 @@ func addQueryHandlerToSTF[T any, PT interface { ) require.NoError(t, err) - queryRouter, err := queryRouterBuilder.Build() - require.NoError(t, err) - stf.SetQueryRouter(s, queryRouter) + return msgRouterBuilder } func TestConsensus_InitChain_Without_UpdateParam(t *testing.T) { - c, _ := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) + c := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) mockStore := c.store _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ Time: time.Now(), @@ -126,24 +121,18 @@ func TestConsensus_InitChain_Without_UpdateParam(t *testing.T) { InitialHeight: 1, }) require.NoError(t, err) - stateStorageHas(t, mockStore, "init-chain", 1) - stateStorageHas(t, mockStore, "end-block", 1) - - stateCommitmentNoHas(t, mockStore, "init-chain", 1) - stateCommitmentNoHas(t, mockStore, "end-block", 1) + assertStoreLatestVersion(t, mockStore, 0) _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ Time: time.Now(), Height: 1, }) require.NoError(t, err) - - stateCommitmentHas(t, mockStore, "init-chain", 1) - stateCommitmentHas(t, mockStore, "end-block", 1) + assertStoreLatestVersion(t, mockStore, 1) } func TestConsensus_InitChain_With_UpdateParam(t *testing.T) { - c, _ := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) + c := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) mockStore := c.store _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ Time: time.Now(), @@ -152,11 +141,7 @@ func TestConsensus_InitChain_With_UpdateParam(t *testing.T) { InitialHeight: 1, }) require.NoError(t, err) - stateStorageHas(t, mockStore, "init-chain", 1) - stateStorageHas(t, mockStore, "end-block", 1) - - stateCommitmentNoHas(t, mockStore, "init-chain", 1) - stateCommitmentNoHas(t, mockStore, "end-block", 1) + assertStoreLatestVersion(t, mockStore, 0) _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ Time: time.Now(), @@ -164,12 +149,11 @@ func TestConsensus_InitChain_With_UpdateParam(t *testing.T) { }) require.NoError(t, err) - stateCommitmentHas(t, mockStore, "init-chain", 1) - stateCommitmentHas(t, mockStore, "end-block", 1) + assertStoreLatestVersion(t, mockStore, 1) } func TestConsensus_InitChain_Invalid_Height(t *testing.T) { - c, _ := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) + c := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) mockStore := c.store _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ Time: time.Now(), @@ -177,8 +161,7 @@ func TestConsensus_InitChain_Invalid_Height(t *testing.T) { InitialHeight: 2, }) require.NoError(t, err) - stateStorageHas(t, mockStore, "init-chain", 2) - stateStorageHas(t, mockStore, "end-block", 2) + assertStoreLatestVersion(t, mockStore, 0) // Shouldn't be able to commit genesis block 2 _, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{ @@ -190,7 +173,7 @@ func TestConsensus_InitChain_Invalid_Height(t *testing.T) { } func TestConsensus_FinalizeBlock_Invalid_Height(t *testing.T) { - c, _ := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) + c := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ Time: time.Now(), ChainId: "test", @@ -212,17 +195,9 @@ func TestConsensus_FinalizeBlock_Invalid_Height(t *testing.T) { } func TestConsensus_FinalizeBlock_NoTxs(t *testing.T) { - c, s := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) + c := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) mockStore := c.store - addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { - cParams := DefaulConsensusParams - kvSet(t, ctx, "query") - return &consensustypes.QueryParamsResponse{ - Params: cParams, - }, nil - }) - _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ Time: time.Now(), ChainId: "test", @@ -245,27 +220,13 @@ func TestConsensus_FinalizeBlock_NoTxs(t *testing.T) { }) require.NoError(t, err) - stateCommitmentHas(t, mockStore, "begin-block", uint64(i)) - stateCommitmentNoHas(t, mockStore, "exec", uint64(i)) - stateCommitmentHas(t, mockStore, "end-block", uint64(i)) + assertStoreLatestVersion(t, mockStore, uint64(i)) } require.Equal(t, int64(endBlock), c.lastCommittedHeight.Load()) } func TestConsensus_FinalizeBlock_MultiTxs_OutOfGas(t *testing.T) { - c, s := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) - - addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { - cParams := DefaulConsensusParams - kvSet(t, ctx, "query") - return &consensustypes.QueryParamsResponse{ - Params: cParams, - }, nil - }) - addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *gogotypes.BoolValue) (*gogotypes.BoolValue, error) { - kvSet(t, ctx, "exec") - return nil, nil - }) + c := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ Time: time.Now(), @@ -286,31 +247,18 @@ func TestConsensus_FinalizeBlock_MultiTxs_OutOfGas(t *testing.T) { Time: time.Now(), Height: int64(i), Hash: sum[:], - Txs: [][]byte{invalidMockTx.Bytes()}, + Txs: [][]byte{invalidMockTx.Bytes(), mockTx.Bytes()}, }) require.NoError(t, err) require.NotEqual(t, res.TxResults[0].Code, 0) - require.Contains(t, res.TxResults[0].Log, "out of gas") } require.Equal(t, int64(endBlock), c.lastCommittedHeight.Load()) } func TestConsensus_FinalizeBlock_MultiTxs(t *testing.T) { - c, s := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) + c := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) mockStore := c.store - addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { - cParams := DefaulConsensusParams - kvSet(t, ctx, "query") - return &consensustypes.QueryParamsResponse{ - Params: cParams, - }, nil - }) - addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *gogotypes.BoolValue) (*gogotypes.BoolValue, error) { - kvSet(t, ctx, "exec") - return nil, nil - }) - _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ Time: time.Now(), ChainId: "test", @@ -330,23 +278,16 @@ func TestConsensus_FinalizeBlock_MultiTxs(t *testing.T) { Time: time.Now(), Height: int64(i), Hash: sum[:], - Txs: [][]byte{mockTx.Bytes()}, + Txs: [][]byte{mockTx.Bytes(), mockTx.Bytes()}, }) require.NoError(t, err) - stateCommitmentHas(t, mockStore, "init-chain", uint64(i)) - stateCommitmentHas(t, mockStore, "exec", uint64(i)) - stateCommitmentHas(t, mockStore, "end-block", uint64(i)) + assertStoreLatestVersion(t, mockStore, uint64(i)) } require.Equal(t, int64(endBlock), c.lastCommittedHeight.Load()) } func TestConsensus_CheckTx(t *testing.T) { - c, s := setUpConsensus(t, 0, mempool.NoOpMempool[mock.Tx]{}) - - addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *gogotypes.BoolValue) (*gogotypes.BoolValue, error) { - kvSet(t, ctx, "exec") - return nil, nil - }) + c := setUpConsensus(t, 0, mempool.NoOpMempool[mock.Tx]{}) _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ Time: time.Now(), @@ -370,10 +311,9 @@ func TestConsensus_CheckTx(t *testing.T) { }.Bytes(), }) require.NoError(t, err) - require.Contains(t, res.Log, "out of gas") require.NotEqual(t, res.Code, 0) - c, _ = setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) + c = setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) res, err = c.CheckTx(context.Background(), &abciproto.CheckTxRequest{ Tx: mock.Tx{ Sender: []byte("sender"), @@ -386,30 +326,7 @@ func TestConsensus_CheckTx(t *testing.T) { } func TestConsensus_ExtendVote(t *testing.T) { - c, s := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) - - addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { - cParams := &v1.ConsensusParams{ - Block: &v1.BlockParams{ - MaxGas: 5000000, - }, - Abci: &v1.ABCIParams{ - VoteExtensionsEnableHeight: 2, - }, - Feature: &v1.FeatureParams{ - VoteExtensionsEnableHeight: &gogotypes.Int64Value{Value: 2}, - }, - } - - kvSet(t, ctx, "query") - return &consensustypes.QueryParamsResponse{ - Params: cParams, - }, nil - }) - addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *consensustypes.MsgUpdateParams) (*consensustypes.MsgUpdateParams, error) { - kvSet(t, ctx, "exec") - return nil, nil - }) + c := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ Time: time.Now(), @@ -451,28 +368,7 @@ func TestConsensus_ExtendVote(t *testing.T) { } func TestConsensus_VerifyVoteExtension(t *testing.T) { - c, s := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) - - addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { - cParams := &v1.ConsensusParams{ - Block: &v1.BlockParams{ - MaxGas: 5000000, - }, - Abci: &v1.ABCIParams{ - VoteExtensionsEnableHeight: 2, - }, - Feature: &v1.FeatureParams{ - VoteExtensionsEnableHeight: &gogotypes.Int64Value{Value: 2}, - }, - } - return &consensustypes.QueryParamsResponse{ - Params: cParams, - }, nil - }) - addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *consensustypes.MsgUpdateParams) (*consensustypes.MsgUpdateParams, error) { - kvSet(t, ctx, "exec") - return nil, nil - }) + c := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ Time: time.Now(), @@ -515,7 +411,7 @@ func TestConsensus_VerifyVoteExtension(t *testing.T) { } func TestConsensus_PrepareProposal(t *testing.T) { - c, _ := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) + c := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) // Invalid height _, err := c.PrepareProposal(context.Background(), &abciproto.PrepareProposalRequest{ @@ -539,18 +435,7 @@ func TestConsensus_PrepareProposal(t *testing.T) { } func TestConsensus_PrepareProposal_With_Handler_NoOpMempool(t *testing.T) { - c, s := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) - - addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { - cParams := &v1.ConsensusParams{ - Block: &v1.BlockParams{ - MaxGas: 300_000, - }, - } - return &consensustypes.QueryParamsResponse{ - Params: cParams, - }, nil - }) + c := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) c.prepareProposalHandler = handlers.NewDefaultProposalHandler(c.mempool).PrepareHandler() @@ -612,7 +497,7 @@ func TestConsensus_PrepareProposal_With_Handler_NoOpMempool(t *testing.T) { } func TestConsensus_ProcessProposal(t *testing.T) { - c, _ := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) + c := setUpConsensus(t, 100_000, mempool.NoOpMempool[mock.Tx]{}) // Invalid height _, err := c.ProcessProposal(context.Background(), &abciproto.ProcessProposalRequest{ @@ -643,18 +528,9 @@ func TestConsensus_ProcessProposal(t *testing.T) { } func TestConsensus_ProcessProposal_With_Handler_OutOfGas(t *testing.T) { - c, s := setUpConsensus(t, 0, cometmock.MockMempool[mock.Tx]{}) + c := setUpConsensus(t, 0, cometmock.MockMempool[mock.Tx]{}) c.processProposalHandler = handlers.NewDefaultProposalHandler(c.mempool).ProcessHandler() - addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { - cParams := &v1.ConsensusParams{ - Block: &v1.BlockParams{ - MaxGas: 300_000, - }, - } - return &consensustypes.QueryParamsResponse{ - Params: cParams, - }, nil - }) + res, err := c.ProcessProposal(context.Background(), &abciproto.ProcessProposalRequest{ Height: 1, Txs: [][]byte{invalidMockTx.Bytes(), invalidMockTx.Bytes(), invalidMockTx.Bytes()}, @@ -664,18 +540,7 @@ func TestConsensus_ProcessProposal_With_Handler_OutOfGas(t *testing.T) { } func TestConsensus_ProcessProposal_With_Handler(t *testing.T) { - c, s := setUpConsensus(t, 100_000, cometmock.MockMempool[mock.Tx]{}) - - addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { - cParams := &v1.ConsensusParams{ - Block: &v1.BlockParams{ - MaxGas: 300_000, - }, - } - return &consensustypes.QueryParamsResponse{ - Params: cParams, - }, nil - }) + c := setUpConsensus(t, 100_000, cometmock.MockMempool[mock.Tx]{}) c.processProposalHandler = handlers.NewDefaultProposalHandler(c.mempool).ProcessHandler() @@ -697,21 +562,7 @@ func TestConsensus_ProcessProposal_With_Handler(t *testing.T) { } func TestConsensus_Info(t *testing.T) { - c, s := setUpConsensus(t, 100_000, cometmock.MockMempool[mock.Tx]{}) - - addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { - cParams := &v1.ConsensusParams{ - Block: &v1.BlockParams{ - MaxGas: 300_000, - }, - Version: &v1.VersionParams{ - App: 1, - }, - } - return &consensustypes.QueryParamsResponse{ - Params: cParams, - }, nil - }) + c := setUpConsensus(t, 100_000, cometmock.MockMempool[mock.Tx]{}) // Version 0 res, err := c.Info(context.Background(), &abciproto.InfoRequest{}) @@ -742,16 +593,22 @@ func TestConsensus_Info(t *testing.T) { // - app request // - p2p request func TestConsensus_Query(t *testing.T) { - c, s := setUpConsensus(t, 100_000, cometmock.MockMempool[mock.Tx]{}) - addQueryHandlerToSTF(t, s, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { - cParams := DefaulConsensusParams - return &consensustypes.QueryParamsResponse{ - Params: cParams, - }, nil - }) - addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *gogotypes.BoolValue) (*gogotypes.BoolValue, error) { - kvSet(t, ctx, "exec") - return nil, nil + c := setUpConsensus(t, 100_000, cometmock.MockMempool[mock.Tx]{}) + + // Write data to state storage + c.store.GetStateStorage().ApplyChangeset(1, &store.Changeset{ + Changes: []store.StateChanges{ + { + Actor: actorName, + StateChanges: []store.KVPair{ + { + Key: []byte("key"), + Value: []byte("value"), + Remove: false, + }, + }, + }, + }, }) _, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{ @@ -768,8 +625,6 @@ func TestConsensus_Query(t *testing.T) { }) require.NoError(t, err) - stateStorageHas(t, c.store, "init-chain", 1) - // empty request res, err := c.Query(context.Background(), &abciproto.QueryRequest{}) require.NoError(t, err) @@ -779,11 +634,11 @@ func TestConsensus_Query(t *testing.T) { // Query store res, err = c.Query(context.Background(), &abciproto.QueryRequest{ Path: "store/cookies/", - Data: []byte("init-chain"), + Data: []byte("key"), Height: 1, }) require.NoError(t, err) - require.Equal(t, string(res.Value), "init-chain") + require.Equal(t, string(res.Value), "value") // Query store with no value res, err = c.Query(context.Background(), &abciproto.QueryRequest{ @@ -795,24 +650,45 @@ func TestConsensus_Query(t *testing.T) { require.Equal(t, res.Value, []byte(nil)) } -func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock.Tx]) (*Consensus[mock.Tx], *stf.STF[mock.Tx]) { +func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock.Tx]) *Consensus[mock.Tx] { + msgRouterBuilder := getMsgRouterBuilder(t, func(ctx context.Context, msg *gogotypes.BoolValue) (*gogotypes.BoolValue, error) { + return nil, nil + }) + + queryRouterBuilder := getQueryRouterBuilder(t, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { + cParams := &v1.ConsensusParams{ + Block: &v1.BlockParams{ + MaxGas: 5000000, + }, + Abci: &v1.ABCIParams{ + VoteExtensionsEnableHeight: 2, + }, + Feature: &v1.FeatureParams{ + VoteExtensionsEnableHeight: &gogotypes.Int64Value{Value: 2}, + }, + } + return &consensustypes.QueryParamsResponse{ + Params: cParams, + }, nil + }) + s, err := stf.NewSTF( log.NewNopLogger().With("module", "stf"), - stf.NewMsgRouterBuilder(), - stf.NewMsgRouterBuilder(), + msgRouterBuilder, + queryRouterBuilder, func(ctx context.Context, txs []mock.Tx) error { return nil }, func(ctx context.Context) error { - return kvSet(t, ctx, "begin-block") + return nil }, func(ctx context.Context) error { - return kvSet(t, ctx, "end-block") + return nil }, func(ctx context.Context, tx mock.Tx) error { - return kvSet(t, ctx, "validate") + return nil }, func(ctx context.Context) ([]appmodulev2.ValidatorUpdate, error) { return nil, nil }, func(ctx context.Context, tx mock.Tx, success bool) error { - return kvSet(t, ctx, "post-tx-exec") + return nil }, branch.DefaultNewWriterMap, ) @@ -829,51 +705,29 @@ func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock. QueryGasLimit: gasLimit, SimulationGasLimit: gasLimit, InitGenesis: func(ctx context.Context, src io.Reader, txHandler func(json.RawMessage) error) error { - return kvSet(t, ctx, "init-chain") + return nil }, } am, err := b.Build() require.NoError(t, err) - return NewConsensus[mock.Tx](log.NewNopLogger(), "testing-app", "authority", am, mempool, map[string]struct{}{}, nil, mockStore, Config{AppTomlConfig: DefaultAppTomlConfig()}, mock.TxCodec{}, "test"), s -} - -var actorName = []byte("cookies") - -func kvSet(t *testing.T, ctx context.Context, v string) error { - t.Helper() - executionCtx := stf.GetExecutionContext(ctx) - require.NotNil(t, executionCtx) - state, err := stf.GetStateFromContext(executionCtx).GetWriter(actorName) - require.NoError(t, err) - return state.Set([]byte(v), []byte(v)) -} - -func stateStorageHas(t *testing.T, store types.Store, key string, version uint64) { - t.Helper() - has, err := store.GetStateStorage().Has(actorName, version, []byte(key)) - require.NoError(t, err) - require.Truef(t, has, "state storage did not have key: %s", key) + return NewConsensus[mock.Tx](log.NewNopLogger(), "testing-app", "authority", am, mempool, map[string]struct{}{}, nil, mockStore, Config{AppTomlConfig: DefaultAppTomlConfig()}, mock.TxCodec{}, "test") } -func stateStorageNoHas(t *testing.T, store types.Store, key string, version uint64) { +// Check target version same with store's latest version +// And should have commit info of target version +// If block 0, commitInfo returned should be nil +func assertStoreLatestVersion(t *testing.T, store types.Store, target uint64) { t.Helper() - has, err := store.GetStateStorage().Has(actorName, version, []byte(key)) + version, err := store.GetLatestVersion() require.NoError(t, err) - require.Falsef(t, has, "state storage had key: %s", key) -} - -func stateCommitmentHas(t *testing.T, store types.Store, key string, version uint64) { - t.Helper() - bz, err := store.GetStateCommitment().Get(actorName, version, []byte(key)) + require.Equal(t, version, target) + commitInfo, err := store.GetStateCommitment().GetCommitInfo(version) require.NoError(t, err) - require.NotEqual(t, len(bz), 0) - require.Equal(t, bz, []byte(key)) -} - -func stateCommitmentNoHas(t *testing.T, store types.Store, key string, version uint64) { - t.Helper() - bz, _ := store.GetStateCommitment().Get(actorName, version, []byte(key)) - require.Equal(t, len(bz), 0) + if target != 0 { + require.Equal(t, commitInfo.Version, target) + } else { + require.Nil(t, commitInfo) + } } diff --git a/server/v2/stf/helper.go b/server/v2/stf/helper.go deleted file mode 100644 index 0e7a54e273b2..000000000000 --- a/server/v2/stf/helper.go +++ /dev/null @@ -1,31 +0,0 @@ -package stf - -import ( - "context" - - "cosmossdk.io/core/store" - "cosmossdk.io/server/v2/stf/mock" -) - -// There some field not be exported -// Helpers for cometbft test - -func GetExecutionContext(ctx context.Context) *executionContext { - executionCtx, ok := ctx.(*executionContext) - if !ok { - return nil - } - return executionCtx -} - -func GetStateFromContext(ctx *executionContext) store.WriterMap { - return ctx.state -} - -func SetMsgRouter(s *STF[mock.Tx], msgRouter coreRouterImpl) { - s.msgRouter = msgRouter -} - -func SetQueryRouter(s *STF[mock.Tx], queryRouter coreRouterImpl) { - s.queryRouter = queryRouter -} From 337515c68406bcdaf3ee0b1ebd8bfda781c9f378 Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Fri, 30 Aug 2024 01:43:39 +0700 Subject: [PATCH 18/22] gofmt --- store/v2/root/store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store/v2/root/store.go b/store/v2/root/store.go index 313f388ab15d..218af42b6f89 100644 --- a/store/v2/root/store.go +++ b/store/v2/root/store.go @@ -182,7 +182,7 @@ func (s *Store) Query(storeKey []byte, version uint64, key []byte, prove bool) ( val, err = s.stateCommitment.Get(storeKey, version, key) if err != nil { return store.QueryResult{}, fmt.Errorf("failed to query SC store: %w", err) - } + } } else { val, err = s.stateStorage.Get(storeKey, version, key) if err != nil { From 48f13ac0db8d53e749ee1716ea284b65a50d1595 Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Fri, 30 Aug 2024 15:59:55 +0700 Subject: [PATCH 19/22] remove --- server/v2/cometbft/mock/mock_reader.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/server/v2/cometbft/mock/mock_reader.go b/server/v2/cometbft/mock/mock_reader.go index 26f03694ce87..7638fc3f115b 100644 --- a/server/v2/cometbft/mock/mock_reader.go +++ b/server/v2/cometbft/mock/mock_reader.go @@ -2,8 +2,6 @@ package mock import ( corestore "cosmossdk.io/core/store" - // ammstore "cosmossdk.io/server/v2/appmanager/store" - // "cosmossdk.io/server/v2/stf/branch" ) // ReaderMap defines an adapter around a RootStore that only exposes read-only @@ -27,9 +25,9 @@ func (roa *ReaderMap) GetReader(actor []byte) (corestore.Reader, error) { // Reader represents a read-only adapter for accessing data from the root store. type MockReader struct { - version uint64 // The version of the data. + version uint64 // The version of the data. store *MockStore // The root store to read data from. - actor []byte // The actor associated with the data. + actor []byte // The actor associated with the data. } func NewMockReader(v uint64, rs *MockStore, actor []byte) *MockReader { From 12e22074a517dea52c9e809470b7fb95cf64b7f9 Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Wed, 4 Sep 2024 13:48:12 +0700 Subject: [PATCH 20/22] move to internal --- server/v2/cometbft/abci_test.go | 2 +- .../v2/cometbft/internal/mock/mock_mempool.go | 19 +++++++++++++++ .../{ => internal}/mock/mock_reader.go | 0 .../{ => internal}/mock/mock_store.go | 7 ++---- server/v2/cometbft/mock/mock_mempool.go | 23 ------------------- 5 files changed, 22 insertions(+), 29 deletions(-) create mode 100644 server/v2/cometbft/internal/mock/mock_mempool.go rename server/v2/cometbft/{ => internal}/mock/mock_reader.go (100%) rename server/v2/cometbft/{ => internal}/mock/mock_store.go (98%) delete mode 100644 server/v2/cometbft/mock/mock_mempool.go diff --git a/server/v2/cometbft/abci_test.go b/server/v2/cometbft/abci_test.go index a2c014f2e3de..00f6267a7bc0 100644 --- a/server/v2/cometbft/abci_test.go +++ b/server/v2/cometbft/abci_test.go @@ -14,8 +14,8 @@ import ( "cosmossdk.io/log" am "cosmossdk.io/server/v2/appmanager" "cosmossdk.io/server/v2/cometbft/handlers" + cometmock "cosmossdk.io/server/v2/cometbft/internal/mock" "cosmossdk.io/server/v2/cometbft/mempool" - cometmock "cosmossdk.io/server/v2/cometbft/mock" "cosmossdk.io/server/v2/cometbft/types" "cosmossdk.io/server/v2/stf" "cosmossdk.io/server/v2/stf/branch" diff --git a/server/v2/cometbft/internal/mock/mock_mempool.go b/server/v2/cometbft/internal/mock/mock_mempool.go new file mode 100644 index 000000000000..89d51e955fae --- /dev/null +++ b/server/v2/cometbft/internal/mock/mock_mempool.go @@ -0,0 +1,19 @@ +package mock + +import ( + "context" + + "cosmossdk.io/core/transaction" + "cosmossdk.io/server/v2/cometbft/mempool" +) + +var _ mempool.Mempool[transaction.Tx] = (*MockMempool[transaction.Tx])(nil) + +// MockMempool implements Mempool +// Used for testing instead of NoOpMempool +type MockMempool[T transaction.Tx] struct{} + +func (MockMempool[T]) Insert(context.Context, T) error { return nil } +func (MockMempool[T]) Select(context.Context, []T) mempool.Iterator[T] { return nil } +func (MockMempool[T]) CountTx() int { return 0 } +func (MockMempool[T]) Remove([]T) error { return nil } diff --git a/server/v2/cometbft/mock/mock_reader.go b/server/v2/cometbft/internal/mock/mock_reader.go similarity index 100% rename from server/v2/cometbft/mock/mock_reader.go rename to server/v2/cometbft/internal/mock/mock_reader.go diff --git a/server/v2/cometbft/mock/mock_store.go b/server/v2/cometbft/internal/mock/mock_store.go similarity index 98% rename from server/v2/cometbft/mock/mock_store.go rename to server/v2/cometbft/internal/mock/mock_store.go index 4f71a9e09bc8..ee9089f8d49f 100644 --- a/server/v2/cometbft/mock/mock_store.go +++ b/server/v2/cometbft/internal/mock/mock_store.go @@ -7,14 +7,13 @@ import ( "cosmossdk.io/core/log" corestore "cosmossdk.io/core/store" - storev2 "cosmossdk.io/store/v2" "cosmossdk.io/store/v2/commitment" + "cosmossdk.io/store/v2/commitment/iavl" dbm "cosmossdk.io/store/v2/db" "cosmossdk.io/store/v2/proof" "cosmossdk.io/store/v2/storage" "cosmossdk.io/store/v2/storage/sqlite" - "cosmossdk.io/store/v2/commitment/iavl" ) type MockStore struct { @@ -72,7 +71,7 @@ func (s *MockStore) Commit(changeset *corestore.Changeset) (corestore.Hash, erro return []byte{}, err } - commitInfo, err := s.Commiter.Commit(v+1) + commitInfo, err := s.Commiter.Commit(v + 1) fmt.Println("commitInfo", commitInfo, err) return []byte{}, err } @@ -138,5 +137,3 @@ func (s *MockStore) WorkingHash(changeset *corestore.Changeset) (corestore.Hash, } return []byte{}, nil } - - diff --git a/server/v2/cometbft/mock/mock_mempool.go b/server/v2/cometbft/mock/mock_mempool.go deleted file mode 100644 index 67a8116ad480..000000000000 --- a/server/v2/cometbft/mock/mock_mempool.go +++ /dev/null @@ -1,23 +0,0 @@ -package mock - -import ( - "context" - - "cosmossdk.io/core/transaction" - "cosmossdk.io/server/v2/cometbft/mempool" -) - -var _ mempool.Mempool[transaction.Tx] = (*MockMempool[transaction.Tx])(nil) - -// MockMempool defines a no-op mempool. Transactions are completely discarded and -// ignored when BaseApp interacts with the mempool. -// -// Note: When this mempool is used, it assumed that an application will rely -// on CometBFT's transaction ordering defined in `RequestPrepareProposal`, which -// is FIFO-ordered by default. -type MockMempool[T transaction.Tx] struct{} - -func (MockMempool[T]) Insert(context.Context, T) error { return nil } -func (MockMempool[T]) Select(context.Context, []T) mempool.Iterator[T] { return nil } -func (MockMempool[T]) CountTx() int { return 0 } -func (MockMempool[T]) Remove([]T) error { return nil } From f4e1fa432da26df2e4647f7eafce1f9232c0888d Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Mon, 9 Sep 2024 16:14:53 +0700 Subject: [PATCH 21/22] update max block gas --- server/v2/cometbft/abci_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/v2/cometbft/abci_test.go b/server/v2/cometbft/abci_test.go index 00f6267a7bc0..8b20d7927083 100644 --- a/server/v2/cometbft/abci_test.go +++ b/server/v2/cometbft/abci_test.go @@ -658,7 +658,7 @@ func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock. queryRouterBuilder := getQueryRouterBuilder(t, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) { cParams := &v1.ConsensusParams{ Block: &v1.BlockParams{ - MaxGas: 5000000, + MaxGas: 300000, }, Abci: &v1.ABCIParams{ VoteExtensionsEnableHeight: 2, From 12be6e417a62712303695a789f2297d6d068f2d2 Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Mon, 9 Sep 2024 16:27:06 +0700 Subject: [PATCH 22/22] update --- server/v2/cometbft/abci_test.go | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/server/v2/cometbft/abci_test.go b/server/v2/cometbft/abci_test.go index 8b20d7927083..2208894e3878 100644 --- a/server/v2/cometbft/abci_test.go +++ b/server/v2/cometbft/abci_test.go @@ -518,25 +518,6 @@ func TestConsensus_ProcessProposal(t *testing.T) { Txs: [][]byte{mockTx.Bytes()}, }) require.NoError(t, err) - - // have bad encode tx - _, err = c.ProcessProposal(context.Background(), &abciproto.ProcessProposalRequest{ - Height: 1, - Txs: [][]byte{mockTx.Bytes(), append(mockTx.Bytes(), []byte("bad")...), mockTx.Bytes()}, - }) - require.Error(t, err) -} - -func TestConsensus_ProcessProposal_With_Handler_OutOfGas(t *testing.T) { - c := setUpConsensus(t, 0, cometmock.MockMempool[mock.Tx]{}) - c.processProposalHandler = handlers.NewDefaultProposalHandler(c.mempool).ProcessHandler() - - res, err := c.ProcessProposal(context.Background(), &abciproto.ProcessProposalRequest{ - Height: 1, - Txs: [][]byte{invalidMockTx.Bytes(), invalidMockTx.Bytes(), invalidMockTx.Bytes()}, - }) - require.NoError(t, err) - require.Equal(t, res.Status, abciproto.PROCESS_PROPOSAL_STATUS_REJECT) } func TestConsensus_ProcessProposal_With_Handler(t *testing.T) { @@ -553,12 +534,12 @@ func TestConsensus_ProcessProposal_With_Handler(t *testing.T) { require.Equal(t, res.Status, abciproto.PROCESS_PROPOSAL_STATUS_REJECT) // have bad encode tx - // should remove that tx and accept + // should reject res, err = c.ProcessProposal(context.Background(), &abciproto.ProcessProposalRequest{ Height: 1, Txs: [][]byte{mockTx.Bytes(), append(mockTx.Bytes(), []byte("bad")...), mockTx.Bytes(), mockTx.Bytes()}, }) - require.Equal(t, res.Status, abciproto.PROCESS_PROPOSAL_STATUS_ACCEPT) + require.Equal(t, res.Status, abciproto.PROCESS_PROPOSAL_STATUS_REJECT) } func TestConsensus_Info(t *testing.T) {