Skip to content

Commit

Permalink
refactor!(core): add in environment bundler of service (#19041)
Browse files Browse the repository at this point in the history
Co-authored-by: Facundo <[email protected]>
  • Loading branch information
tac0turtle and facundomedica authored Jan 30, 2024
1 parent 7e4d122 commit ca04e11
Show file tree
Hide file tree
Showing 28 changed files with 212 additions and 135 deletions.
10 changes: 10 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,16 @@ Refer to SimApp `root_v2.go` and `root.go` for an example with an app v2 and a l

<!-- explain app_config.go changes -->

### Core

`appmodule.Environment` interface was introduced to fetch different services from the application. This can be used as an alternative to using `sdk.UnwrapContext(ctx)` to fetch the services. It needs to be passed into a module at instantiation.

Circuit Breaker is used as an example.

```go
app.CircuitKeeper = circuitkeeper.NewKeeper(runtime.NewEnvironment((keys[circuittypes.StoreKey]), nil), appCodec, authtypes.NewModuleAddress(govtypes.ModuleName).String(), app.AuthKeeper.AddressCodec())
```

### Modules

#### `**all**`
Expand Down
2 changes: 2 additions & 0 deletions core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,14 @@ Ref: https://keepachangelog.com/en/1.0.0/

* [#18379](https://github.com/cosmos/cosmos-sdk/pull/18379) Add branch service.
* [#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

### API Breaking

* [#18857](https://github.com/cosmos/cosmos-sdk/pull/18857) Moved `FormatCoins` to `x/tx`.
* [#18861](httpes://github.com/cosmos/cosmos-sdk/pull/18861) Moved `coin.ParseCoin` to `client/v2/internal`.
* [#18866](https://github.com/cosmos/cosmos-sdk/pull/18866) All items related to depinject have been moved to `cosmossdk.io/depinject` (`Provide`, `Invoke`, `Register`)
* [#19041](https://github.com/cosmos/cosmos-sdk/pull/19041) `HasEventListeners` was removed from appmodule due to the fact that it was not used anywhere in the SDK nor implemented

## [v0.12.0](https://github.com/cosmos/cosmos-sdk/releases/tag/core%2Fv0.12.0)

Expand Down
19 changes: 19 additions & 0 deletions core/appmodule/environment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package appmodule

import (
"cosmossdk.io/core/branch"
"cosmossdk.io/core/event"
"cosmossdk.io/core/gas"
"cosmossdk.io/core/header"
"cosmossdk.io/core/store"
)

// 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
}
32 changes: 0 additions & 32 deletions core/appmodule/event.go

This file was deleted.

17 changes: 0 additions & 17 deletions core/appmodule/event_test.go

This file was deleted.

10 changes: 7 additions & 3 deletions core/event/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,27 @@ type Manager interface {
// Callers SHOULD assume that these events may be included in consensus. These events
// MUST be emitted deterministically and adding, removing or changing these events SHOULD
// be considered state-machine breaking.
Emit(ctx context.Context, event protoiface.MessageV1) error
Emit(event protoiface.MessageV1) error

// EmitKV emits an event based on an event and kv-pair attributes.
//
// These events will not be part of consensus and adding, removing or changing these events is
// not a state-machine breaking change.
EmitKV(ctx context.Context, eventType string, attrs ...Attribute) error
EmitKV(eventType string, attrs ...Attribute) error

// EmitNonConsensus emits events represented as a protobuf message (as described in ADR 032), without
// including it in blockchain consensus.
//
// These events will not be part of consensus and adding, removing or changing events is
// not a state-machine breaking change.
EmitNonConsensus(ctx context.Context, event protoiface.MessageV1) error
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}
}
13 changes: 4 additions & 9 deletions core/gas/meter.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,10 @@ type Service interface {
WithBlockGasMeter(ctx context.Context, meter Meter) context.Context
}

// Meter represents a gas meter.
// Meter represents a gas meter for modules consumption
type Meter interface {
GasConsumed() Gas
GasConsumedToLimit() Gas
GasRemaining() Gas
Consume(amount Gas, descriptor string)
Refund(amount Gas, descriptor string)
Remaining() Gas
Limit() Gas
ConsumeGas(amount Gas, descriptor string)
RefundGas(amount Gas, descriptor string)
IsPastLimit() bool
IsOutOfGas() bool
String() string
}
18 changes: 18 additions & 0 deletions runtime/environment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package runtime

import (
"cosmossdk.io/core/appmodule"
"cosmossdk.io/core/store"
)

// NewEnvironment creates a new environment for the application
// if memstoreservice is needed, it can be added to the environment: environment.MemStoreService = memstoreservice
func NewEnvironment(kvService store.KVStoreService) appmodule.Environment {
return appmodule.Environment{
EventService: EventService{},
HeaderService: HeaderService{},
BranchService: BranchService{},
GasService: GasService{},
KVStoreService: kvService,
}
}
6 changes: 3 additions & 3 deletions runtime/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ func NewEventManager(ctx context.Context) event.Manager {

// Emit emits an typed event that is defined in the protobuf file.
// In the future these events will be added to consensus.
func (e Events) Emit(ctx context.Context, event protoiface.MessageV1) error {
func (e Events) Emit(event protoiface.MessageV1) error {
return e.EventManagerI.EmitTypedEvent(event)
}

// EmitKV emits a key value pair event.
func (e Events) EmitKV(ctx context.Context, eventType string, attrs ...event.Attribute) error {
func (e Events) EmitKV(eventType string, attrs ...event.Attribute) error {
attributes := make([]sdk.Attribute, 0, len(attrs))

for _, attr := range attrs {
Expand All @@ -52,6 +52,6 @@ func (e Events) EmitKV(ctx context.Context, eventType string, attrs ...event.Att

// Emit emits an typed event that is defined in the protobuf file.
// In the future these events will be added to consensus.
func (e Events) EmitNonConsensus(ctx context.Context, event protoiface.MessageV1) error {
func (e Events) EmitNonConsensus(event protoiface.MessageV1) error {
return e.EventManagerI.EmitTypedEvent(event)
}
82 changes: 76 additions & 6 deletions runtime/gas.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,99 @@ package runtime

import (
"context"
"fmt"

"cosmossdk.io/core/gas"
storetypes "cosmossdk.io/store/types"

sdk "github.com/cosmos/cosmos-sdk/types"
)

var _ gas.Service = (*GasService)(nil)
var _ gas.Service = GasService{}

type GasService struct{}

func (g GasService) GetGasMeter(ctx context.Context) gas.Meter {
sdkCtx := sdk.UnwrapSDKContext(ctx)
return sdkCtx.GasMeter()
return CoreGasmeter{gm: sdk.UnwrapSDKContext(ctx).GasMeter()}
}

func (g GasService) GetBlockGasMeter(ctx context.Context) gas.Meter {
return sdk.UnwrapSDKContext(ctx).BlockGasMeter()
return CoreGasmeter{gm: sdk.UnwrapSDKContext(ctx).BlockGasMeter()}
}

func (g GasService) WithGasMeter(ctx context.Context, meter gas.Meter) context.Context {
return sdk.UnwrapSDKContext(ctx).WithGasMeter(meter)
return sdk.UnwrapSDKContext(ctx).WithGasMeter(SDKGasMeter{gm: meter})
}

func (g GasService) WithBlockGasMeter(ctx context.Context, meter gas.Meter) context.Context {
return sdk.UnwrapSDKContext(ctx).WithBlockGasMeter(meter)
return sdk.UnwrapSDKContext(ctx).WithGasMeter(SDKGasMeter{gm: meter})
}

// ______________________________________________________________________________________________
// Gas Meter Wrappers
// ______________________________________________________________________________________________

// SDKGasMeter is a wrapper around the SDK's GasMeter that implements the GasMeter interface.
type SDKGasMeter struct {
gm gas.Meter
}

func (gm SDKGasMeter) GasConsumed() storetypes.Gas {
return gm.gm.Remaining()
}

func (gm SDKGasMeter) GasConsumedToLimit() storetypes.Gas {
if gm.IsPastLimit() {
return gm.gm.Limit()
}
return gm.gm.Remaining()
}

func (gm SDKGasMeter) GasRemaining() storetypes.Gas {
return gm.gm.Remaining()
}

func (gm SDKGasMeter) Limit() storetypes.Gas {
return gm.gm.Limit()
}

func (gm SDKGasMeter) ConsumeGas(amount storetypes.Gas, descriptor string) {
gm.gm.Consume(amount, descriptor)
}

func (gm SDKGasMeter) RefundGas(amount storetypes.Gas, descriptor string) {
gm.gm.Refund(amount, descriptor)
}

func (gm SDKGasMeter) IsPastLimit() bool {
return gm.gm.Remaining() <= gm.gm.Limit()
}

func (gm SDKGasMeter) IsOutOfGas() bool {
return gm.gm.Remaining() >= gm.gm.Limit()
}

func (gm SDKGasMeter) String() string {
return fmt.Sprintf("BasicGasMeter:\n limit: %d\n consumed: %d", gm.gm.Limit(), gm.gm.Remaining())
}

// CoreGasmeter is a wrapper around the SDK's GasMeter that implements the GasMeter interface.
type CoreGasmeter struct {
gm storetypes.GasMeter
}

func (cgm CoreGasmeter) Consume(amount gas.Gas, descriptor string) {
cgm.gm.ConsumeGas(amount, descriptor)
}

func (cgm CoreGasmeter) Refund(amount gas.Gas, descriptor string) {
cgm.gm.RefundGas(amount, descriptor)
}

func (cgm CoreGasmeter) Remaining() gas.Gas {
return cgm.gm.GasRemaining()
}

func (cgm CoreGasmeter) Limit() gas.Gas {
return cgm.gm.Limit()
}
5 changes: 5 additions & 0 deletions runtime/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func init() {
ProvideBasicManager,
ProvideAppVersionModifier,
ProvideAddressCodec,
ProvideEnvironment,
),
appconfig.Invoke(SetupAppBuilder),
)
Expand Down Expand Up @@ -251,6 +252,10 @@ func ProvideAppVersionModifier(app *AppBuilder) baseapp.AppVersionModifier {
return app.app
}

func ProvideEnvironment(kvService store.KVStoreService) appmodule.Environment {
return NewEnvironment(kvService)
}

type (
// ValidatorAddressCodec is an alias for address.Codec for validator addresses.
ValidatorAddressCodec address.Codec
Expand Down
4 changes: 4 additions & 0 deletions runtime/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ type memStoreService struct {
key *storetypes.MemoryStoreKey
}

func NewMemStoreService(storeKey *storetypes.MemoryStoreKey) store.MemoryStoreService {
return &memStoreService{key: storeKey}
}

func (m memStoreService) OpenMemoryStore(ctx context.Context) store.KVStore {
return newKVStore(sdk.UnwrapSDKContext(ctx).KVStore(m.key))
}
Expand Down
3 changes: 1 addition & 2 deletions simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,6 @@ func NewSimApp(
addressCodec := authcodec.NewBech32Codec(sdk.Bech32MainPrefix)

// add keepers

accountsKeeper, err := accounts.NewKeeper(
appCodec,
runtime.NewKVStoreService(keys[accounts.StoreKey]),
Expand Down Expand Up @@ -354,7 +353,7 @@ func NewSimApp(
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
)

app.CircuitKeeper = circuitkeeper.NewKeeper(appCodec, runtime.NewKVStoreService(keys[circuittypes.StoreKey]), authtypes.NewModuleAddress(govtypes.ModuleName).String(), app.AuthKeeper.AddressCodec())
app.CircuitKeeper = circuitkeeper.NewKeeper(runtime.NewEnvironment(runtime.NewKVStoreService(keys[circuittypes.StoreKey])), appCodec, authtypes.NewModuleAddress(govtypes.ModuleName).String(), app.AuthKeeper.AddressCodec())
app.BaseApp.SetCircuitBreaker(&app.CircuitKeeper)

app.AuthzKeeper = authzkeeper.NewKeeper(runtime.NewKVStoreService(keys[authzkeeper.StoreKey]), appCodec, app.MsgServiceRouter(), app.AuthKeeper)
Expand Down
5 changes: 2 additions & 3 deletions tests/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,9 @@ replace (
cosmossdk.io/api => ../api
cosmossdk.io/client/v2 => ../client/v2
cosmossdk.io/depinject => ../depinject
cosmossdk.io/core => ../core
cosmossdk.io/x/accounts => ../x/accounts
cosmossdk.io/x/tx => ../x/tx
cosmossdk.io/x/auth => ../x/auth
cosmossdk.io/x/authz => ../x/authz
cosmossdk.io/x/bank => ../x/bank
Expand All @@ -252,7 +254,4 @@ replace (
github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0
// We always want to test against the latest version of the SDK.
github.com/cosmos/cosmos-sdk => ../.
// Fix upstream GHSA-h395-qcrw-5vmq and GHSA-3vp4-m3rf-835h vulnerabilities.
// TODO Remove it: https://github.com/cosmos/cosmos-sdk/issues/10409
github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.9.1
)
1 change: 1 addition & 0 deletions x/accounts/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ replace github.com/cosmos/cosmos-sdk => ../../.
replace (
cosmossdk.io/api => ../../api
cosmossdk.io/depinject => ../../depinject
cosmossdk.io/core => ../../core
cosmossdk.io/x/auth => ../auth
cosmossdk.io/x/bank => ../bank
cosmossdk.io/x/distribution => ../distribution
Expand Down
6 changes: 1 addition & 5 deletions x/accounts/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,8 @@ func (m msgServer) Init(ctx context.Context, request *v1.MsgInit) (*v1.MsgInitRe

eventManager := m.k.eventService.EventManager(ctx)
err = eventManager.EmitKV(
ctx,
"account_creation",
event.Attribute{
Key: "address",
Value: accAddrString,
},
event.NewAttribute("address", accAddrString),
)
if err != nil {
return nil, err
Expand Down
Loading

0 comments on commit ca04e11

Please sign in to comment.