diff --git a/tm2/pkg/sdk/auth/keeper.go b/tm2/pkg/sdk/auth/keeper.go index e43b5389844..7669b8ace73 100644 --- a/tm2/pkg/sdk/auth/keeper.go +++ b/tm2/pkg/sdk/auth/keeper.go @@ -31,11 +31,6 @@ func NewAccountKeeper( } } -// Logger returns a module-specific logger. -func (ak AccountKeeper) Logger(ctx sdk.Context) *slog.Logger { - return ctx.Logger().With("module", fmt.Sprintf("auth")) -} - // NewAccountWithAddress implements AccountKeeper. func (ak AccountKeeper) NewAccountWithAddress(ctx sdk.Context, addr crypto.Address) std.Account { acc := ak.proto() @@ -53,7 +48,12 @@ func (ak AccountKeeper) NewAccountWithAddress(ctx sdk.Context, addr crypto.Addre return acc } -// GetAccount implements AccountKeeper. +// Logger returns a module-specific logger. +func (ak AccountKeeper) Logger(ctx sdk.Context) *slog.Logger { + return ctx.Logger().With("module", ModuleName) +} + +// GetAccount returns a specific account in the AccountKeeper. func (ak AccountKeeper) GetAccount(ctx sdk.Context, addr crypto.Address) std.Account { stor := ctx.Store(ak.key) bz := stor.Get(AddressStoreKey(addr)) diff --git a/tm2/pkg/sdk/bank/keeper.go b/tm2/pkg/sdk/bank/keeper.go index 5d3699c99ef..f98e6b3e225 100644 --- a/tm2/pkg/sdk/bank/keeper.go +++ b/tm2/pkg/sdk/bank/keeper.go @@ -25,8 +25,8 @@ type BankKeeperI interface { var _ BankKeeperI = BankKeeper{} -// BBankKeeper only allows transfers between accounts without the possibility of -// creating coins. It implements the BankKeeper interface. +// BankKeeper only allows transfers between accounts without the possibility of +// creating coins. It implements the BankKeeperI interface. type BankKeeper struct { ViewKeeper diff --git a/tm2/pkg/sdk/params/consts.go b/tm2/pkg/sdk/params/consts.go new file mode 100644 index 00000000000..eb829a08b73 --- /dev/null +++ b/tm2/pkg/sdk/params/consts.go @@ -0,0 +1,6 @@ +package params + +const ( + ModuleName = "params" + StoreKey = ModuleName +) diff --git a/tm2/pkg/sdk/params/doc.go b/tm2/pkg/sdk/params/doc.go new file mode 100644 index 00000000000..bf7449adb49 --- /dev/null +++ b/tm2/pkg/sdk/params/doc.go @@ -0,0 +1,13 @@ +// Package params provides a lightweight implementation inspired by the x/params +// module of the Cosmos SDK. +// +// It includes a keeper for managing key-value pairs with module identifiers as +// prefixes, along with a global querier for retrieving any key from any module. +// +// Changes: This version removes the concepts of subspaces and proposals, +// allowing the creation of multiple keepers identified by a provided prefix. +// Proposals may be added later when governance modules are introduced. The +// transient store and .Modified helper have also been removed but can be +// implemented later if needed. Keys are represented as strings instead of +// []byte. +package params diff --git a/tm2/pkg/sdk/params/handler.go b/tm2/pkg/sdk/params/handler.go new file mode 100644 index 00000000000..22b6961bd47 --- /dev/null +++ b/tm2/pkg/sdk/params/handler.go @@ -0,0 +1,83 @@ +package params + +import ( + "fmt" + "strings" + + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + "github.com/gnolang/gno/tm2/pkg/sdk" + "github.com/gnolang/gno/tm2/pkg/std" +) + +type paramsHandler struct { + params ParamsKeeper +} + +func NewHandler(params ParamsKeeper) paramsHandler { + return paramsHandler{ + params: params, + } +} + +func (bh paramsHandler) Process(ctx sdk.Context, msg std.Msg) sdk.Result { + errMsg := fmt.Sprintf("unrecognized params message type: %T", msg) + return abciResult(std.ErrUnknownRequest(errMsg)) +} + +//---------------------------------------- +// Query + +const QueryParams = "params" + +func (bh paramsHandler) Query(ctx sdk.Context, req abci.RequestQuery) (res abci.ResponseQuery) { + switch secondPart(req.Path) { + case QueryParams: + return bh.queryParam(ctx, req) + default: + res = sdk.ABCIResponseQueryFromError( + std.ErrUnknownRequest("unknown params query endpoint")) + return + } +} + +// queryParam returns param for a key. +func (bh paramsHandler) queryParam(ctx sdk.Context, req abci.RequestQuery) (res abci.ResponseQuery) { + // parse key from path. + key := thirdPartWithSlashes(req.Path) + if key == "" { + res = sdk.ABCIResponseQueryFromError( + std.ErrUnknownRequest("param key is empty")) + } + + // XXX: validate + + panic("not implemented") + + return +} + +//---------------------------------------- +// misc + +func abciResult(err error) sdk.Result { + return sdk.ABCIResultFromError(err) +} + +// returns the second component of a path. +func secondPart(path string) string { + parts := strings.Split(path, "/") + if len(parts) < 2 { + return "" + } else { + return parts[1] + } +} + +// returns the third component of a path, including other slashes. +func thirdPartWithSlashes(path string) string { + secondSlash := strings.Index(path[strings.Index(path, "/")+1:], "/") + if secondSlash == -1 { + return "" // Return original if less than two slashes + } + return path[strings.Index(path, "/")+secondSlash+1:] +} diff --git a/tm2/pkg/sdk/params/keeper.go b/tm2/pkg/sdk/params/keeper.go new file mode 100644 index 00000000000..da1283bd5cf --- /dev/null +++ b/tm2/pkg/sdk/params/keeper.go @@ -0,0 +1,151 @@ +package params + +import ( + "fmt" + "log/slog" + "maps" + "reflect" + + "github.com/gnolang/gno/tm2/pkg/amino" + "github.com/gnolang/gno/tm2/pkg/sdk" + "github.com/gnolang/gno/tm2/pkg/store" +) + +// global paramstore Keeper. +type ParamsKeeper struct { + key store.StoreKey + table KeyTable + prefix string +} + +// NewParamsKeeper returns a new ParamsKeeper. +func NewParamsKeeper(key store.StoreKey, prefix string) ParamsKeeper { + return ParamsKeeper{ + key: key, + table: NewKeyTable(), + prefix: prefix, + } +} + +// Logger returns a module-specific logger. +// XXX: why do we expose this? +func (pk ParamsKeeper) Logger(ctx sdk.Context) *slog.Logger { + return ctx.Logger().With("module", ModuleName) +} + +func (pk ParamsKeeper) Has(ctx sdk.Context, key string) bool { + stor := ctx.Store(pk.key) + return stor.Has([]byte(key)) +} + +func (pk ParamsKeeper) Get(ctx sdk.Context, key string, ptr interface{}) { + pk.checkType(key, ptr) + stor := ctx.Store(pk.key) + bz := stor.Get([]byte(key)) + err := amino.UnmarshalJSON(bz, ptr) + if err != nil { + panic(err) + } +} + +func (pk ParamsKeeper) GetIfExists(ctx sdk.Context, key string, ptr interface{}) { + stor := ctx.Store(pk.key) + bz := stor.Get([]byte(key)) + if bz == nil { + return + } + pk.checkType(key, ptr) + err := amino.UnmarshalJSON(bz, ptr) + if err != nil { + panic(err) + } +} + +func (pk ParamsKeeper) GetRaw(ctx sdk.Context, key string) []byte { + stor := ctx.Store(pk.key) + return stor.Get([]byte(key)) +} + +func (pk ParamsKeeper) Set(ctx sdk.Context, key string, value interface{}) { + pk.checkType(key, value) + stor := ctx.Store(pk.key) + bz, err := amino.MarshalJSON(value) + if err != nil { + panic(err) + } + stor.Set([]byte(key), bz) +} + +func (pk ParamsKeeper) Update(ctx sdk.Context, key string, value []byte) error { + attr, ok := pk.table.m[key] + if !ok { + panic(fmt.Sprintf("parameter %s not registered", key)) + } + + ty := attr.ty + dest := reflect.New(ty).Interface() + pk.GetIfExists(ctx, key, dest) + + if err := amino.UnmarshalJSON(value, dest); err != nil { + return err + } + + destValue := reflect.Indirect(reflect.ValueOf(dest)).Interface() + if err := pk.Validate(ctx, key, destValue); err != nil { + return err + } + + pk.Set(ctx, key, dest) + return nil +} + +func (pk ParamsKeeper) Validate(ctx sdk.Context, key string, value interface{}) error { + attr, ok := pk.table.m[key] + if !ok { + return fmt.Errorf("parameter %s not registered", key) + } + + if err := attr.vfn(value); err != nil { + return fmt.Errorf("invalid parameter value: %w", err) + } + + return nil +} + +func (pk ParamsKeeper) checkType(key string, value interface{}) { + attr, ok := pk.table.m[key] + if !ok { + panic(fmt.Sprintf("parameter %s is not registered", key)) + } + + ty := attr.ty + pty := reflect.TypeOf(value) + if pty.Kind() == reflect.Ptr { + pty = pty.Elem() + } + + if pty != ty { + panic("type mismatch with registered table") + } +} + +func (pk ParamsKeeper) HasKeyTable() bool { + return len(pk.table.m) > 0 +} + +func (pk ParamsKeeper) WithKeyTable(table KeyTable) ParamsKeeper { + if table.m == nil { + panic("WithKeyTable() called with nil KeyTable") + } + if len(pk.table.m) != 0 { + panic("WithKeyTable() called on already initialized Keeper") + } + + maps.Copy(pk.table.m, table.m) + return pk +} + +// XXX: GetAllKeys +// XXX: GetAllParams +// XXX: ViewKeeper +// XXX: ModuleKeeper diff --git a/tm2/pkg/sdk/params/keeper_test.go b/tm2/pkg/sdk/params/keeper_test.go new file mode 100644 index 00000000000..6fd1e6ae65b --- /dev/null +++ b/tm2/pkg/sdk/params/keeper_test.go @@ -0,0 +1,209 @@ +package params + +import ( + "reflect" + "testing" + + "github.com/gnolang/gno/tm2/pkg/amino" + "github.com/stretchr/testify/require" +) + +// XXX: transient test + +func TestKeeper(t *testing.T) { + kvs := []struct { + key string + param int64 + }{ + {"key1", 10}, + {"key2", 55}, + {"key3", 182}, + {"key4", 17582}, + {"key5", 2768554}, + {"key6", 1157279}, + {"key7", 9058701}, + } + + table := NewKeyTable( + NewParamSetPair("key1", int64(0), validateNoOp), + NewParamSetPair("key2", int64(0), validateNoOp), + NewParamSetPair("key3", int64(0), validateNoOp), + NewParamSetPair("key4", int64(0), validateNoOp), + NewParamSetPair("key5", int64(0), validateNoOp), + NewParamSetPair("key6", int64(0), validateNoOp), + NewParamSetPair("key7", int64(0), validateNoOp), + NewParamSetPair("extra1", bool(false), validateNoOp), + NewParamSetPair("extra2", string(""), validateNoOp), + ) + + env := setupTestEnv() + ctx, store, keeper := env.ctx, env.store, env.keeper + + require.False(t, keeper.HasKeyTable()) + keeper = keeper.WithKeyTable(table) + require.True(t, keeper.HasKeyTable()) + + // Set params + for i, kv := range kvs { + require.NotPanics(t, func() { keeper.Set(ctx, kv.key, kv.param) }, "keeper.Set panics, tc #%d", i) + } + + // Test keeper.Get + for i, kv := range kvs { + var param int64 + require.NotPanics(t, func() { keeper.Get(ctx, kv.key, ¶m) }, "keeper.Get panics, tc #%d", i) + require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i) + } + + // Test keeper.GetRaw + for i, kv := range kvs { + var param int64 + bz := keeper.GetRaw(ctx, kv.key) + err := amino.UnmarshalJSON(bz, ¶m) + require.Nil(t, err, "err is not nil, tc #%d", i) + require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i) + } + + // Test store.Get equals keeper.Get + for i, kv := range kvs { + var param int64 + bz := store.Get([]byte(kv.key)) + require.NotNil(t, bz, "KVStore.Get returns nil, tc #%d", i) + err := amino.UnmarshalJSON(bz, ¶m) + require.NoError(t, err, "UnmarshalJSON returns error, tc #%d", i) + require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i) + } + + // Test invalid keeper.Get + for i, kv := range kvs { + var param bool + require.Panics(t, func() { keeper.Get(ctx, kv.key, ¶m) }, "invalid keeper.Get not panics, tc #%d", i) + } + + // Test invalid keeper.Set + for i, kv := range kvs { + require.Panics(t, func() { keeper.Set(ctx, kv.key, true) }, "invalid keeper.Set not panics, tc #%d", i) + } +} + +// adapted from TestKeeperSubspace from Cosmos SDK, but adapted to a subspace-less Keeper. +func TestKeeper_Subspace(t *testing.T) { + env := setupTestEnv() + ctx, store, keeper := env.ctx, env.store, env.keeper + // XXX: keeper = keeper.WithKeyTable(table) + + // cdc, ctx, key, _, keeper := testComponents() + + kvs := []struct { + key string + param interface{} + zero interface{} + ptr interface{} + }{ + {"string", "test", "", new(string)}, + {"bool", true, false, new(bool)}, + {"int16", int16(1), int16(0), new(int16)}, + {"int32", int32(1), int32(0), new(int32)}, + {"int64", int64(1), int64(0), new(int64)}, + {"uint16", uint16(1), uint16(0), new(uint16)}, + {"uint32", uint32(1), uint32(0), new(uint32)}, + {"uint64", uint64(1), uint64(0), new(uint64)}, + // XXX: {"int", math.NewInt(1), math.Int{}, new(math.Int)}, + // XXX: {"uint", math.NewUint(1), math.Uint{}, new(math.Uint)}, + // XXX: {"dec", math.LegacyNewDec(1), math.LegacyDec{}, new(math.LegacyDec)}, + {"struct", s{1}, s{0}, new(s)}, + } + + table := NewKeyTable( + NewParamSetPair("string", "", validateNoOp), + NewParamSetPair("bool", false, validateNoOp), + NewParamSetPair("int16", int16(0), validateNoOp), + NewParamSetPair("int32", int32(0), validateNoOp), + NewParamSetPair("int64", int64(0), validateNoOp), + NewParamSetPair("uint16", uint16(0), validateNoOp), + NewParamSetPair("uint32", uint32(0), validateNoOp), + NewParamSetPair("uint64", uint64(0), validateNoOp), + // XXX: NewParamSetPair("int", math.Int{}, validateNoOp), + // XXX: NewParamSetPair("uint", math.Uint{}, validateNoOp), + // XXX: NewParamSetPair("dec", math.LegacyDec{}, validateNoOp), + NewParamSetPair("struct", s{}, validateNoOp), + ) + keeper = keeper.WithKeyTable(table) + + // Test keeper.Set, keeper.Modified + for i, kv := range kvs { + // require.False(t, keeper.Modified(ctx, kv.key), "keeper.Modified returns true before setting, tc #%d", i) + require.NotPanics(t, func() { keeper.Set(ctx, kv.key, kv.param) }, "keeper.Set panics, tc #%d", i) + // require.True(t, keeper.Modified(ctx, kv.key), "keeper.Modified returns false after setting, tc #%d", i) + } + + // Test keeper.Get, keeper.GetIfExists + for i, kv := range kvs { + require.NotPanics(t, func() { keeper.GetIfExists(ctx, "invalid", kv.ptr) }, "keeper.GetIfExists panics when no value exists, tc #%d", i) + require.Equal(t, kv.zero, indirect(kv.ptr), "keeper.GetIfExists unmarshalls when no value exists, tc #%d", i) + require.Panics(t, func() { keeper.Get(ctx, "invalid", kv.ptr) }, "invalid keeper.Get not panics when no value exists, tc #%d", i) + require.Equal(t, kv.zero, indirect(kv.ptr), "invalid keeper.Get unmarshalls when no value exists, tc #%d", i) + + require.NotPanics(t, func() { keeper.GetIfExists(ctx, kv.key, kv.ptr) }, "keeper.GetIfExists panics, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i) + require.NotPanics(t, func() { keeper.Get(ctx, kv.key, kv.ptr) }, "keeper.Get panics, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i) + + require.Panics(t, func() { keeper.Get(ctx, "invalid", kv.ptr) }, "invalid keeper.Get not panics when no value exists, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "invalid keeper.Get unmarshalls when no value existt, tc #%d", i) + + require.Panics(t, func() { keeper.Get(ctx, kv.key, nil) }, "invalid keeper.Get not panics when the pointer is nil, tc #%d", i) + require.Panics(t, func() { keeper.Get(ctx, kv.key, new(invalid)) }, "invalid keeper.Get not panics when the pointer is different type, tc #%d", i) + } + + // Test store.Get equals keeper.Get + for i, kv := range kvs { + bz := store.Get([]byte(kv.key)) + require.NotNil(t, bz, "store.Get() returns nil, tc #%d", i) + err := amino.UnmarshalJSON(bz, kv.ptr) + require.NoError(t, err, "cdc.UnmarshalJSON() returns error, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i) + } +} + +func TestJSONUpdate(t *testing.T) { + env := setupTestEnv() + ctx, keeper := env.ctx, env.keeper + key := "key" + + space := keeper.WithKeyTable(NewKeyTable(NewParamSetPair(key, paramJSON{}, validateNoOp))) + + var param paramJSON + + err := space.Update(ctx, key, []byte(`{"param1": "10241024"}`)) + require.NoError(t, err) + space.Get(ctx, key, ¶m) + require.Equal(t, paramJSON{10241024, ""}, param) + + err = space.Update(ctx, key, []byte(`{"param2": "helloworld"}`)) + require.NoError(t, err) + space.Get(ctx, key, ¶m) + require.Equal(t, paramJSON{10241024, "helloworld"}, param) + + err = space.Update(ctx, key, []byte(`{"param1": "20482048"}`)) + require.NoError(t, err) + space.Get(ctx, key, ¶m) + require.Equal(t, paramJSON{20482048, "helloworld"}, param) + + err = space.Update(ctx, key, []byte(`{"param1": "40964096", "param2": "goodbyeworld"}`)) + require.NoError(t, err) + space.Get(ctx, key, ¶m) + require.Equal(t, paramJSON{40964096, "goodbyeworld"}, param) +} + +type ( + invalid struct{} + s struct{ I int } + paramJSON struct { + Param1 int64 `json:"param1,omitempty" yaml:"param1,omitempty"` + Param2 string `json:"param2,omitempty" yaml:"param2,omitempty"` + } +) + +func validateNoOp(_ interface{}) error { return nil } +func indirect(ptr interface{}) interface{} { return reflect.ValueOf(ptr).Elem().Interface() } diff --git a/tm2/pkg/sdk/params/paramset.go b/tm2/pkg/sdk/params/paramset.go new file mode 100644 index 00000000000..b401c56e69e --- /dev/null +++ b/tm2/pkg/sdk/params/paramset.go @@ -0,0 +1,25 @@ +package params + +// This file mirrors the original implementation from the Cosmos SDK. + +type ValueValidatorFn func(value interface{}) error + +// ParamSetPair is used for associating param key and field of param structs. +type ParamSetPair struct { + Key string + Value interface{} + ValidatorFn ValueValidatorFn +} + +// NewParamSetPair creates a new ParamSetPair instance. +func NewParamSetPair(key string, value interface{}, vfn ValueValidatorFn) ParamSetPair { + return ParamSetPair{key, value, vfn} +} + +// ParamSetPairs Slice of KeyFieldPair. +type ParamSetPairs []ParamSetPair + +// ParamSet defines an interface for structs containing parameters for a module. +type ParamSet interface { + ParamSetPairs() ParamSetPairs +} diff --git a/tm2/pkg/sdk/params/table.go b/tm2/pkg/sdk/params/table.go new file mode 100644 index 00000000000..1ce6a3b92db --- /dev/null +++ b/tm2/pkg/sdk/params/table.go @@ -0,0 +1,71 @@ +package params + +// This file closely mirrors the original implementation from the Cosmos SDK, with only minor modifications. + +import ( + "reflect" + "regexp" +) + +type attribute struct { + ty reflect.Type + vfn ValueValidatorFn +} + +// KeyTable subspaces appropriate type for each parameter key +type KeyTable struct { + m map[string]attribute +} + +func NewKeyTable(pairs ...ParamSetPair) KeyTable { + keyTable := KeyTable{ + m: make(map[string]attribute), + } + + for _, psp := range pairs { + keyTable = keyTable.RegisterType(psp) + } + + return keyTable +} + +// RegisterType registers a single ParamSetPair (key-type pair) in a KeyTable. +func (t KeyTable) RegisterType(psp ParamSetPair) KeyTable { + if len(psp.Key) == 0 { + panic("cannot register ParamSetPair with an parameter empty key") + } + if !isAlphaNumeric(psp.Key) { + panic("cannot register ParamSetPair with a non-alphanumeric parameter key") + } + if psp.ValidatorFn == nil { + panic("cannot register ParamSetPair without a value validation function") + } + + if _, ok := t.m[psp.Key]; ok { + panic("duplicate parameter key") + } + + rty := reflect.TypeOf(psp.Value) + + // indirect rty if it is a pointer + for rty.Kind() == reflect.Ptr { + rty = rty.Elem() + } + + t.m[psp.Key] = attribute{ + vfn: psp.ValidatorFn, + ty: rty, + } + + return t +} + +// RegisterParamSet registers multiple ParamSetPairs from a ParamSet in a KeyTable. +func (t KeyTable) RegisterParamSet(ps ParamSet) KeyTable { + for _, psp := range ps.ParamSetPairs() { + t = t.RegisterType(psp) + } + return t +} + +var isAlphaNumeric = regexp.MustCompile(`^[a-zA-Z0-9]+$`).MatchString diff --git a/tm2/pkg/sdk/params/test_common.go b/tm2/pkg/sdk/params/test_common.go new file mode 100644 index 00000000000..8243ee867de --- /dev/null +++ b/tm2/pkg/sdk/params/test_common.go @@ -0,0 +1,46 @@ +package params + +import ( + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + bft "github.com/gnolang/gno/tm2/pkg/bft/types" + "github.com/gnolang/gno/tm2/pkg/db/memdb" + "github.com/gnolang/gno/tm2/pkg/log" + "github.com/gnolang/gno/tm2/pkg/sdk" + "github.com/gnolang/gno/tm2/pkg/store" + "github.com/gnolang/gno/tm2/pkg/store/iavl" +) + +type testEnv struct { + ctx sdk.Context + store store.Store + keeper ParamsKeeper +} + +func setupTestEnv() testEnv { + db := memdb.NewMemDB() + paramsCapKey := store.NewStoreKey("paramsCapKey") + ms := store.NewCommitMultiStore(db) + ms.MountStoreWithDB(paramsCapKey, iavl.StoreConstructor, db) + ms.LoadLatestVersion() + + prefix := "params_test" + keeper := NewParamsKeeper(paramsCapKey, prefix) + + ctx := sdk.NewContext(sdk.RunTxModeDeliver, ms, &bft.Header{Height: 1, ChainID: "test-chain-id"}, log.NewNoopLogger()) + // XXX: context key? + ctx = ctx.WithConsensusParams(&abci.ConsensusParams{ + Block: &abci.BlockParams{ + MaxTxBytes: 1024, + MaxDataBytes: 1024 * 100, + MaxBlockBytes: 1024 * 100, + MaxGas: 10 * 1000 * 1000, + TimeIotaMS: 10, + }, + Validator: &abci.ValidatorParams{ + PubKeyTypeURLs: []string{}, // XXX + }, + }) + + stor := ctx.Store(paramsCapKey) + return testEnv{ctx: ctx, store: stor, keeper: keeper} +} diff --git a/tm2/pkg/store/README.md b/tm2/pkg/store/README.md index abf5c26bc07..24ae0c805ac 100644 --- a/tm2/pkg/store/README.md +++ b/tm2/pkg/store/README.md @@ -116,15 +116,3 @@ type traceOperation struct { ``` `traceOperation.Metadata` is filled with `Store.context` when it is not nil. `TraceContext` is a `map[string]interface{}`. - -## Transient - -`transient.Store` is a base-layer `KVStore` which is automatically discarded at the end of the block. - -```go -type Store struct { - dbadapter.Store -} -``` - -`Store.Store` is a `dbadapter.Store` with a `memdb.NewMemDB()`. All `KVStore` methods are reused. When `Store.Commit()` is called, new `dbadapter.Store` is assigned, discarding previous reference and making it garbage collected.