Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(server/v2/cometbft): Add abci unit tests #21020

Merged
merged 38 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
f294fff
coding
hieuvubk Jul 11, 2024
cbd05ce
fixing
hieuvubk Jul 16, 2024
587023f
go mod tidy all
hieuvubk Jul 19, 2024
116e283
remove fmt
hieuvubk Jul 22, 2024
462efb0
helpers
hieuvubk Jul 22, 2024
b17533e
mock store
hieuvubk Jul 22, 2024
2375aa7
add some tests
hieuvubk Jul 22, 2024
44548be
testing
hieuvubk Aug 5, 2024
eede22f
Merge branch 'main' into hieu/comet_mock
hieuvubk Aug 5, 2024
d008afd
test InitChain & FinalizeBlock
hieuvubk Aug 6, 2024
9d604c9
extend vote
hieuvubk Aug 7, 2024
d4866d9
vote
hieuvubk Aug 8, 2024
9bfe6fe
merge main
hieuvubk Aug 8, 2024
07f4fa3
check tx & prepare proposal
hieuvubk Aug 9, 2024
ee055b8
process proposal
hieuvubk Aug 9, 2024
35787e2
mock mempool
hieuvubk Aug 9, 2024
71c4570
merge main
hieuvubk Aug 14, 2024
7bf135c
clean up
hieuvubk Aug 14, 2024
3b6e7ac
merge main
hieuvubk Aug 22, 2024
76ffcaf
more tests
hieuvubk Aug 22, 2024
c1c4159
remove stf export & update tests
hieuvubk Aug 29, 2024
337515c
gofmt
hieuvubk Aug 29, 2024
5afbe85
resolve conflict
hieuvubk Aug 29, 2024
1117fa7
Merge branch 'main' into hieu/comet_mock
hieuvubk Aug 30, 2024
48f13ac
remove
hieuvubk Aug 30, 2024
6a512af
Merge branch 'main' into hieu/comet_mock
hieuvubk Aug 30, 2024
8a01fa2
Merge branch 'main' into hieu/comet_mock
hieuvubk Sep 4, 2024
12e2207
move to internal
hieuvubk Sep 4, 2024
667c1e2
Merge branch 'main' into hieu/comet_mock
hieuvubk Sep 4, 2024
ed8d2bc
Merge branch 'main' into hieu/comet_mock
hieuvubk Sep 4, 2024
7f5c111
Merge branch 'main' into hieu/comet_mock
hieuvubk Sep 5, 2024
5578d48
resolve conflict
hieuvubk Sep 9, 2024
0add40f
Merge branch 'main' into hieu/comet_mock
julienrbrt Sep 9, 2024
f4e1fa4
update max block gas
hieuvubk Sep 9, 2024
f5325d9
Merge branch 'hieu/comet_mock' of https://github.com/cosmos/cosmos-sd…
hieuvubk Sep 9, 2024
12be6e4
update
hieuvubk Sep 9, 2024
96d6f5b
Merge branch 'main' into hieu/comet_mock
hieuvubk Sep 9, 2024
8f7c343
Merge branch 'main' into hieu/comet_mock
hieuvubk Sep 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
226 changes: 226 additions & 0 deletions server/v2/cometbft/abci_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
package cometbft

import (
"context"
"io"
"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"
"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"

"github.com/cosmos/gogoproto/proto"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make lint-fix


"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"),
// Msg: &gogotypes.BoolValue{Value: true},
// GasLimit: 100_000,
// }

// sum := sha256.Sum256([]byte("test-hash"))

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(), string(actorName), "stf")
mockStore := cometmock.NewMockStore(ss, sc)

b := am.Builder[mock.Tx]{
STF: s,
DB: mockStore,
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{}, 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)

})

}

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)
}

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)
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)
}
5 changes: 4 additions & 1 deletion server/v2/cometbft/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this be removed now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no we still need it for tests set up I think

cosmossdk.io/store => ../../../store
cosmossdk.io/store/v2 => ../../../store/v2
cosmossdk.io/x/accounts => ../../../x/accounts
Expand All @@ -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
Expand All @@ -41,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
Expand Down Expand Up @@ -134,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
Expand All @@ -159,7 +163,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
Expand Down
2 changes: 2 additions & 0 deletions server/v2/cometbft/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
67 changes: 67 additions & 0 deletions server/v2/cometbft/mock/mock_reader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package mock

import (
corestore "cosmossdk.io/core/store"
// ammstore "cosmossdk.io/server/v2/appmanager/store"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, remove those commented imports

// "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)
}
Loading
Loading