diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index 27ee7b8be825..8dec182fa0c3 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -42,6 +42,17 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [#18457](https://github.com/cosmos/cosmos-sdk/pull/18457) Add branch.ExecuteWithGasLimit. * [#19041](https://github.com/cosmos/cosmos-sdk/pull/19041) Add `appmodule.Environment` interface to fetch different services * [#19370](https://github.com/cosmos/cosmos-sdk/pull/19370) Add `appmodule.Migrations` interface to handle migrations +* [#19617](https://github.com/cosmos/cosmos-sdk/pull/19617) Add DataBaseService to store non-consensus data in a database + * Create V2 appmodule with v2 api for runtime/v2 + * Introduce `Transaction.Tx` for use in runtime/v2 + * Introduce `HasUpdateValidators` interface and `ValidatorUpdate` struct for validator updates + * Introduce `HasTxValidation` interface for modules to register tx validation handlers + * `HasGenesis` interface for modules to register import, export, validation and default genesis handlers. The new api works with `proto.Message` + * Add `PreMsghandler`and `PostMsgHandler` for pre and post message hooks + * Add `MsgHandler` as an alternative to grpc handlers + * Provide separate `MigrationRegistrar` instead of grouping with `RegisterServices` + +### Improvements ### API Breaking Changes diff --git a/core/appmodule/environment.go b/core/appmodule/environment.go index 17ab778191c0..93778e9e9bbe 100644 --- a/core/appmodule/environment.go +++ b/core/appmodule/environment.go @@ -1,21 +1,8 @@ package appmodule import ( - "cosmossdk.io/core/branch" - "cosmossdk.io/core/event" - "cosmossdk.io/core/gas" - "cosmossdk.io/core/header" - "cosmossdk.io/core/store" - "cosmossdk.io/log" + appmodule "cosmossdk.io/core/appmodule/v2" ) // Environment is used to get all services to their respective module -type Environment struct { - BranchService branch.Service - EventService event.Service - GasService gas.Service - HeaderService header.Service - KVStoreService store.KVStoreService - MemStoreService store.MemoryStoreService - Logger log.Logger -} +type Environment = appmodule.Environment diff --git a/core/appmodule/module.go b/core/appmodule/module.go index ac30c246fde8..7f352a28e7b6 100644 --- a/core/appmodule/module.go +++ b/core/appmodule/module.go @@ -5,20 +5,27 @@ import ( "google.golang.org/grpc" "google.golang.org/protobuf/runtime/protoiface" + + appmodule "cosmossdk.io/core/appmodule/v2" ) // AppModule is a tag interface for app module implementations to use as a basis // for extension interfaces. It provides no functionality itself, but is the // type that all valid app modules should provide so that they can be identified // by other modules (usually via depinject) as app modules. -type AppModule interface { - // IsAppModule is a dummy method to tag a struct as implementing an AppModule. - IsAppModule() +type AppModule = appmodule.AppModule + +// HasMigrations is the extension interface that modules should implement to register migrations. +type HasMigrations interface { + AppModule - // IsOnePerModuleType is a dummy method to help depinject resolve modules. - IsOnePerModuleType() + // RegisterMigrations registers the module's migrations with the app's migrator. + RegisterMigrations(MigrationRegistrar) error } +// HasConsensusVersion is the interface for declaring a module consensus version. +type HasConsensusVersion = appmodule.HasConsensusVersion + // HasServices is the extension interface that modules should implement to register // implementations of services defined in .proto files. type HasServices interface { @@ -39,14 +46,6 @@ type HasServices interface { RegisterServices(grpc.ServiceRegistrar) error } -// HasMigrations is the extension interface that modules should implement to register migrations. -type HasMigrations interface { - AppModule - - // RegisterMigrations registers the module's migrations with the app's migrator. - RegisterMigrations(MigrationRegistrar) error -} - // ResponsePreBlock represents the response from the PreBlock method. // It can modify consensus parameters in storage and signal the caller through the return value. // When it returns ConsensusParamsChanged=true, the caller must refresh the consensus parameter in the finalize context. @@ -65,23 +64,11 @@ type HasPreBlocker interface { // HasBeginBlocker is the extension interface that modules should implement to run // custom logic before transaction processing in a block. -type HasBeginBlocker interface { - AppModule - - // BeginBlock is a method that will be run before transactions are processed in - // a block. - BeginBlock(context.Context) error -} +type HasBeginBlocker = appmodule.HasBeginBlocker // HasEndBlocker is the extension interface that modules should implement to run // custom logic after transaction processing in a block. -type HasEndBlocker interface { - AppModule - - // EndBlock is a method that will be run after transactions are processed in - // a block. - EndBlock(context.Context) error -} +type HasEndBlocker = appmodule.HasEndBlocker // MsgHandlerRouter is implemented by the runtime provider. type MsgHandlerRouter interface { diff --git a/core/appmodule/v2/appmodule.go b/core/appmodule/v2/appmodule.go new file mode 100644 index 000000000000..eb44c9f513b8 --- /dev/null +++ b/core/appmodule/v2/appmodule.go @@ -0,0 +1,92 @@ +package appmodule + +import ( + "context" + + "cosmossdk.io/core/transaction" +) + +// AppModule is a tag interface for app module implementations to use as a basis +// for extension interfaces. It provides no functionality itself, but is the +// type that all valid app modules should provide so that they can be identified +// by other modules (usually via depinject) as app modules. +type AppModule interface { + // IsAppModule is a dummy method to tag a struct as implementing an AppModule. + IsAppModule() + + // IsOnePerModuleType is a dummy method to help depinject resolve modules. + IsOnePerModuleType() +} + +// HasBeginBlocker is the extension interface that modules should implement to run +// custom logic before transaction processing in a block. +type HasBeginBlocker interface { + AppModule + + // BeginBlock is a method that will be run before transactions are processed in + // a block. + BeginBlock(context.Context) error +} + +// HasEndBlocker is the extension interface that modules should implement to run +// custom logic after transaction processing in a block. +type HasEndBlocker interface { + AppModule + + // EndBlock is a method that will be run after transactions are processed in + // a block. + EndBlock(context.Context) error +} + +// HasTxValidation is the extension interface that modules should implement to run +// custom logic for validating transactions. +// It was previously known as AnteHandler/Decorator. +type HasTxValidation[T transaction.Tx] interface { + AppModule + + // TxValidator is a method that will be run on each transaction. + // If an error is returned: + // ,---. + // / | + // / | + // You shall not pass! / | + // / | + // \ ___,' | + // < -' : + // `-.__..--'``-,_\_ + // |o/ ` :,.)_`> + // :/ ` ||/) + // (_.).__,-` |\ + // /( `.`` `| : + // \'`-.) ` ; ; + // | ` /-< + // | ` / `. + // ,-_-..____ /| ` :__..-'\ + // /,'-.__\\ ``-./ :` ; \ + // `\ `\ `\\ \ : ( ` / , `. \ + // \` \ \\ | | ` : : .\ \ + // \ `\_ )) : ; | | ): : + // (`-.-'\ || |\ \ ` ; ; | | + // \-_ `;;._ ( ` / /_ | | + // `-.-.// ,'`-._\__/_,' ; | + // \:: : / ` , / | + // || | ( ,' / / | + // || ,' / | + TxValidator(ctx context.Context, tx T) error +} + +// HasUpdateValidators is an extension interface that contains information about the AppModule and UpdateValidators. +// It can be seen as the alternative of the Cosmos SDK' HasABCIEndBlocker. +// Both are still supported. +type HasUpdateValidators interface { + AppModule + + UpdateValidators(ctx context.Context) ([]ValidatorUpdate, error) +} + +// ValidatorUpdate defines a validator update. +type ValidatorUpdate struct { + PubKey []byte + PubKeyType string + Power int64 // updated power of the validtor +} diff --git a/core/appmodule/v2/environment.go b/core/appmodule/v2/environment.go new file mode 100644 index 000000000000..9badbddc2f73 --- /dev/null +++ b/core/appmodule/v2/environment.go @@ -0,0 +1,22 @@ +package appmodule + +import ( + "cosmossdk.io/core/branch" + "cosmossdk.io/core/event" + "cosmossdk.io/core/gas" + "cosmossdk.io/core/header" + "cosmossdk.io/core/store" + "cosmossdk.io/log" +) + +// Environment is used to get all services to their respective module +type Environment struct { + BranchService branch.Service + EventService event.Service + GasService gas.Service + HeaderService header.Service + KVStoreService store.KVStoreService + MemStoreService store.MemoryStoreService + DataBaseService store.DatabaseService + Logger log.Logger +} diff --git a/core/appmodule/v2/genesis.go b/core/appmodule/v2/genesis.go new file mode 100644 index 000000000000..d457ac89d8c3 --- /dev/null +++ b/core/appmodule/v2/genesis.go @@ -0,0 +1,17 @@ +package appmodule + +import ( + "context" + "encoding/json" +) + +// HasGenesis defines a custom genesis handling API implementation. +// WARNING: this API is meant as a short-term solution to allow for the +// migration of existing modules to the new app module API. It is intended to be replaced by collections +type HasGenesis interface { + AppModule + DefaultGenesis() Message + ValidateGenesis(data json.RawMessage) error + InitGenesis(ctx context.Context, data json.RawMessage) error + ExportGenesis(ctx context.Context) (json.RawMessage, error) +} diff --git a/core/appmodule/v2/handlers.go b/core/appmodule/v2/handlers.go new file mode 100644 index 000000000000..7bfc46bf24cf --- /dev/null +++ b/core/appmodule/v2/handlers.go @@ -0,0 +1,142 @@ +package appmodule + +import ( + "context" + "fmt" +) + +type ( + // PreMsgHandler is a handler that is executed before Handler. If it errors the execution reverts. + PreMsgHandler = func(ctx context.Context, msg Message) error + // Handler handles the state transition of the provided message. + Handler = func(ctx context.Context, msg Message) (msgResp Message, err error) + // PostMsgHandler runs after Handler, only if Handler does not error. If PostMsgHandler errors + // then the execution is reverted. + PostMsgHandler = func(ctx context.Context, msg, msgResp Message) error +) + +// RegisterHandler is a helper function that modules can use to not lose type safety when registering handlers to the +// QueryRouter or MsgRouter. Example usage: +// ```go +// +// func (k Keeper) QueryBalance(ctx context.Context, req *types.QueryBalanceRequest) (*types.QueryBalanceResponse, error) { +// ... query logic ... +// } +// +// func (m Module) RegisterQueryHandlers(router appmodule.QueryRouter) { +// appmodule.RegisterHandler(router, keeper.QueryBalance) +// } +// +// ``` +func RegisterHandler[R interface{ Register(string, Handler) }, Req, Resp Message]( + router R, + handler func(ctx context.Context, msg Req) (msgResp Resp, err error), +) { + untypedHandler := func(ctx context.Context, m Message) (Message, error) { + typed, ok := m.(Req) + if !ok { + return nil, fmt.Errorf("unexpected type %T, wanted: %T", m, *new(Req)) + } + return handler(ctx, typed) + } + router.Register(messageName[Req](), untypedHandler) +} + +// RegisterPreHandler is a helper function that modules can use to not lose type safety when registering PreMsgHandler to the +// PreMsgRouter. Example usage: +// ```go +// +// func (k Keeper) BeforeSend(ctx context.Context, req *types.MsgSend) (*types.QueryBalanceResponse, error) { +// ... before send logic ... +// } +// +// func (m Module) RegisterPreMsgHandlers(router appmodule.PreMsgRouter) { +// appmodule.RegisterPreHandler(router, keeper.BeforeSend) +// } +// +// ``` +func RegisterPreHandler[Req Message]( + router PreMsgRouter, + handler func(ctx context.Context, msg Req) error, +) { + untypedHandler := func(ctx context.Context, m Message) error { + typed, ok := m.(Req) + if !ok { + return fmt.Errorf("unexpected type %T, wanted: %T", m, *new(Req)) + } + return handler(ctx, typed) + } + router.Register(messageName[Req](), untypedHandler) +} + +// RegisterPostHandler is a helper function that modules can use to not lose type safety when registering handlers to the +// PostMsgRouter. Example usage: +// ```go +// +// func (k Keeper) AfterSend(ctx context.Context, req *types.MsgSend, resp *types.MsgSendResponse) error { +// ... query logic ... +// } +// +// func (m Module) RegisterPostMsgHandlers(router appmodule.PostMsgRouter) { +// appmodule.RegisterPostHandler(router, keeper.AfterSend) +// } +// +// ``` +func RegisterPostHandler[Req, Resp Message]( + router PostMsgRouter, + handler func(ctx context.Context, msg Req, msgResp Resp) error, +) { + untypedHandler := func(ctx context.Context, m, mResp Message) error { + typed, ok := m.(Req) + if !ok { + return fmt.Errorf("unexpected type %T, wanted: %T", m, *new(Req)) + } + typedResp, ok := mResp.(Resp) + if !ok { + return fmt.Errorf("unexpected type %T, wanted: %T", m, *new(Resp)) + } + return handler(ctx, typed, typedResp) + } + router.Register(messageName[Req](), untypedHandler) +} + +// msg handler + +type PreMsgRouter interface { + // Register will register a specific message handler hooking into the message with + // the provided name. + Register(msgName string, handler PreMsgHandler) + // RegisterGlobal will register a global message handler hooking into any message + // being executed. + RegisterGlobal(handler PreMsgHandler) +} + +type HasPreMsgHandlers interface { + RegisterPreMsgHandlers(router PreMsgRouter) +} + +type MsgRouter interface { + Register(msgName string, handler Handler) +} + +type HasMsgHandlers interface { + RegisterMsgHandlers(router MsgRouter) +} + +type PostMsgRouter interface { + // Register will register a specific message handler hooking after the execution of message with + // the provided name. + Register(msgName string, handler PostMsgHandler) + // RegisterGlobal will register a global message handler hooking after the execution of any message. + RegisterGlobal(handler PreMsgHandler) +} + +// query handler + +type QueryRouter interface { + Register(queryName string, handler Handler) +} + +type HasQueryHandlers interface { + RegisterQueryHandlers(router QueryRouter) +} diff --git a/core/appmodule/v2/message.go b/core/appmodule/v2/message.go new file mode 100644 index 000000000000..8a8753c9195e --- /dev/null +++ b/core/appmodule/v2/message.go @@ -0,0 +1,21 @@ +package appmodule + +import ( + gogoproto "github.com/cosmos/gogoproto/proto" + protov2 "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/runtime/protoiface" +) + +// Message aliases protoiface.MessageV1 for convenience. +type Message = protoiface.MessageV1 + +func messageName[M Message]() string { + switch m := any(*new(M)).(type) { + case protov2.Message: + return string(m.ProtoReflect().Descriptor().FullName()) + case gogoproto.Message: + return gogoproto.MessageName(m) + default: + panic("unknown message type") + } +} diff --git a/core/appmodule/v2/migrations.go b/core/appmodule/v2/migrations.go new file mode 100644 index 000000000000..794fb4a28cc8 --- /dev/null +++ b/core/appmodule/v2/migrations.go @@ -0,0 +1,41 @@ +package appmodule + +import "context" + +// HasConsensusVersion is the interface for declaring a module consensus version. +type HasConsensusVersion interface { + // ConsensusVersion is a sequence number for state-breaking change of the + // module. It should be incremented on each consensus-breaking change + // introduced by the module. To avoid wrong/empty versions, the initial version + // should be set to 1. + ConsensusVersion() uint64 +} + +// HasMigrations is implemented by a module which upgrades or has upgraded +// to a new consensus version. +type HasMigrations interface { + AppModule + HasConsensusVersion + + // RegisterMigrations registers the module's migrations with the app's migrator. + RegisterMigrations(MigrationRegistrar) error +} + +type MigrationRegistrar interface { + // Register registers an in-place store migration for a module. The + // handler is a migration script to perform in-place migrations from version + // `fromVersion` to version `fromVersion+1`. + // + // EACH TIME a module's ConsensusVersion increments, a new migration MUST + // be registered using this function. If a migration handler is missing for + // a particular function, the upgrade logic (see RunMigrations function) + // will panic. If the ConsensusVersion bump does not introduce any store + // changes, then a no-op function must be registered here. + Register(moduleName string, fromVersion uint64, handler MigrationHandler) error +} + +// MigrationHandler is the migration function that each module registers. +type MigrationHandler func(context.Context) error + +// VersionMap is a map of moduleName -> version +type VersionMap map[string]uint64 diff --git a/core/event/event.go b/core/event/event.go new file mode 100644 index 000000000000..4304e6e2b4af --- /dev/null +++ b/core/event/event.go @@ -0,0 +1,29 @@ +package event + +// Attribute is a kv-pair event attribute. +type Attribute struct { + Key, Value string +} + +func NewAttribute(key, value string) Attribute { + return Attribute{Key: key, Value: value} +} + +// Events represents a list of events. +type Events struct { + Events []Event +} + +func NewEvents(events ...Event) Events { + return Events{Events: events} +} + +// Event defines how an event will emitted +type Event struct { + Type string + Attributes []Attribute +} + +func NewEvent(ty string, attrs ...Attribute) Event { + return Event{Type: ty, Attributes: attrs} +} diff --git a/core/event/service.go b/core/event/service.go index 941f142db5f9..6668c1d5bfa8 100644 --- a/core/event/service.go +++ b/core/event/service.go @@ -36,12 +36,3 @@ type Manager interface { // not a state-machine breaking change. EmitNonConsensus(event protoiface.MessageV1) error } - -// KVEventAttribute is a kv-pair event attribute. -type Attribute struct { - Key, Value string -} - -func NewAttribute(key, value string) Attribute { - return Attribute{Key: key, Value: value} -} diff --git a/core/gas/meter.go b/core/gas/meter.go index 0774fd2a7733..9495201aa4c0 100644 --- a/core/gas/meter.go +++ b/core/gas/meter.go @@ -1,10 +1,25 @@ // Package gas provides a basic API for app modules to track gas usage. package gas -import "context" +import ( + "context" + "errors" + "math" +) +// ErrOutOfGas must be used by GasMeter implementers to signal +// that the state transition consumed all the allowed computational +// gas. +var ErrOutOfGas = errors.New("out of gas") + +// Gas defines type alias of uint64 for gas consumption. Gas is used +// to measure computational overhead when executing state transitions, +// it might be related to storage access and not only. type Gas = uint64 +// NoGasLimit signals that no gas limit must be applied. +const NoGasLimit Gas = math.MaxUint64 + // Service represents a gas service which can retrieve and set a gas meter in a context. // gas.Service is a core API type that should be provided by the runtime module being used to // build an app via depinject. diff --git a/core/go.mod b/core/go.mod index e7bf2f319d5e..e732129de93a 100644 --- a/core/go.mod +++ b/core/go.mod @@ -4,6 +4,7 @@ go 1.20 require ( cosmossdk.io/log v1.3.1 + github.com/cosmos/gogoproto v1.4.11 github.com/stretchr/testify v1.8.4 google.golang.org/grpc v1.62.0 google.golang.org/protobuf v1.32.0 @@ -12,6 +13,7 @@ require ( require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect @@ -19,6 +21,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/rs/zerolog v1.32.0 // indirect + golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb // indirect golang.org/x/net v0.21.0 // indirect golang.org/x/sys v0.17.0 // indirect golang.org/x/text v0.14.0 // indirect diff --git a/core/go.sum b/core/go.sum index 105975b5b061..57133f587985 100644 --- a/core/go.sum +++ b/core/go.sum @@ -1,6 +1,8 @@ cosmossdk.io/log v1.3.1 h1:UZx8nWIkfbbNEWusZqzAx3ZGvu54TZacWib3EzUYmGI= cosmossdk.io/log v1.3.1/go.mod h1:2/dIomt8mKdk6vl3OWJcPk2be3pGOS8OQaLUM/3/tCM= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cosmos/gogoproto v1.4.11 h1:LZcMHrx4FjUgrqQSWeaGC1v/TeuVFqSLa43CC6aWR2g= +github.com/cosmos/gogoproto v1.4.11/go.mod h1:/g39Mh8m17X8Q/GDEs5zYTSNaNnInBSohtaxzQnYq1Y= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -10,6 +12,7 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -36,6 +39,8 @@ github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb h1:mIKbk8weKhSeLH2GmUTrvx8CjkyJmnU1wFmg59CUjFA= +golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/core/store/database.go b/core/store/database.go new file mode 100644 index 000000000000..551727a6342b --- /dev/null +++ b/core/store/database.go @@ -0,0 +1,23 @@ +package store + +// Database provides access to the underlying database for CRUD operations of non-consensus data. +// WARNING: using this api will make your module unprovable for fraud and validity proofs +type DatabaseService interface { + GetDatabase() NonConsensusStore +} + +// NonConsensusStore is a simple key-value store that is used to store non-consensus data. +// Note the non-consensus data is not committed to the blockchain and does not allow iteration +type NonConsensusStore interface { + // Get returns nil iff key doesn't exist. Errors on nil key. + Get(key []byte) ([]byte, error) + + // Has checks if a key exists. Errors on nil key. + Has(key []byte) (bool, error) + + // Set sets the key. Errors on nil key or value. + Set(key, value []byte) error + + // Delete deletes the key. Errors on nil key. + Delete(key []byte) error +} diff --git a/core/transaction/transaction.go b/core/transaction/transaction.go new file mode 100644 index 000000000000..be1e2960ad94 --- /dev/null +++ b/core/transaction/transaction.go @@ -0,0 +1,32 @@ +package transaction + +import ( + "google.golang.org/protobuf/proto" +) + +type ( + Type = proto.Message + Identity = []byte +) + +// Codec defines the TX codec, which converts a TX from bytes to its concrete representation. +type Codec[T Tx] interface { + // Decode decodes the tx bytes into a DecodedTx, containing + // both concrete and bytes representation of the tx. + Decode([]byte) (T, error) +} + +type Tx interface { + // Hash returns the unique identifier for the Tx. + Hash() [32]byte // TODO evaluate if 32 bytes is the right size & benchmark overhead of hashing instead of using identifier + // GetMessages returns the list of state transitions of the Tx. + GetMessages() []Type + // GetSenders returns the tx state transition sender. + GetSenders() []Identity // TODO reduce this to a single identity if accepted + // GetGasLimit returns the gas limit of the tx. Must return math.MaxUint64 for infinite gas + // txs. + GetGasLimit() uint64 + // Bytes returns the encoded version of this tx. Note: this is ideally cached + // from the first instance of the decoding of the tx. + Bytes() []byte +}