Skip to content

Commit

Permalink
Merge branch 'main' into marko/storeupgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
tac0turtle authored Aug 13, 2024
2 parents 60703a4 + 75db9d7 commit aca492c
Show file tree
Hide file tree
Showing 52 changed files with 679 additions and 489 deletions.
13 changes: 13 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,19 @@ jobs:
PATTERNS: |
**/*.go
*.go
!store/**
- name: run linting (short)
if: steps.lint_long.outcome == 'skipped' && env.GIT_DIFF
run: |
make lint
env:
GIT_DIFF: ${{ env.GIT_DIFF }}
LINT_DIFF: 1
- uses: technote-space/get-diff-action@v6.1.2
if: steps.lint_long.outcome == 'skipped'
with:
PATTERNS: |
store/**
- name: run linting (short)
if: steps.lint_long.outcome == 'skipped' && env.GIT_DIFF
run: |
Expand Down
26 changes: 12 additions & 14 deletions core/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,24 @@ type QueryResponse struct {
}

type BlockRequest[T transaction.Tx] struct {
Height uint64
Time time.Time
Hash []byte
ChainId string
AppHash []byte
Txs []T
ConsensusMessages []transaction.Msg
Height uint64
Time time.Time
Hash []byte
ChainId string
AppHash []byte
Txs []T

// IsGenesis indicates if this block is the first block of the chain.
IsGenesis bool
}

type BlockResponse struct {
Apphash []byte
ConsensusMessagesResponse []transaction.Msg
ValidatorUpdates []appmodulev2.ValidatorUpdate
PreBlockEvents []event.Event
BeginBlockEvents []event.Event
TxResults []TxResult
EndBlockEvents []event.Event
Apphash []byte
ValidatorUpdates []appmodulev2.ValidatorUpdate
PreBlockEvents []event.Event
BeginBlockEvents []event.Event
TxResults []TxResult
EndBlockEvents []event.Event
}

type RequestInitChain struct {
Expand Down
7 changes: 6 additions & 1 deletion core/context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@ package context
type (
execModeKey struct{}
cometInfoKey struct{}
initInfoKey struct{}
environmentKey struct{}
)

var (
ExecModeKey = execModeKey{}
// ExecModeKey is the context key for setting the execution mode.
ExecModeKey = execModeKey{}
// CometInfoKey is the context key for allowing modules to get CometInfo.
CometInfoKey = cometInfoKey{}
// InitInfoKey is the context key for setting consensus params from genesis in the consensus module.
InitInfoKey = initInfoKey{}

// EnvironmentContextKey is the context key for the environment.
// A caller should not assume the environment is available in each context.
Expand Down
2 changes: 1 addition & 1 deletion core/store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type KVStore interface {
//
// As with KVStore, given keys and values should be considered read-only, and must not be modified after
// passing them to the batch.
type Batch interface {
type Batch = interface {
// Set sets a key/value pair.
// CONTRACT: key, value readonly []byte
Set(key, value []byte) error
Expand Down
21 changes: 12 additions & 9 deletions schema/indexer/indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"cosmossdk.io/schema/appdata"
"cosmossdk.io/schema/logutil"
"cosmossdk.io/schema/view"
)

// Config species the configuration passed to an indexer initialization function.
Expand Down Expand Up @@ -55,10 +56,11 @@ type InitParams struct {
Config Config

// Context is the context that the indexer should use to listen for a shutdown signal via Context.Done(). Other
// parameters may also be passed through context from the app if necessary.
// parameters may also be passed through context from the app if necessary. It is expected to be non-nil.
Context context.Context

// Logger is a logger the indexer can use to write log messages.
// Logger is a logger the indexer can use to write log messages. It may be nil if the indexer does not need
// to write logs.
Logger logutil.Logger
}

Expand All @@ -67,12 +69,13 @@ type InitResult struct {
// Listener is the indexer's app data listener.
Listener appdata.Listener

// LastBlockPersisted indicates the last block that the indexer persisted (if it is persisting data). It
// should be 0 if the indexer has no data stored and wants to start syncing state. It should be -1 if the indexer
// does not care to persist state at all and is just listening for some other streaming purpose. If the indexer
// has persisted state and has missed some blocks, a runtime error will occur to prevent the indexer from continuing
// in an invalid state. If an indexer starts indexing after a chain's genesis (returning 0), the indexer manager
// will attempt to perform a catch-up sync of state. Historical events will not be replayed, but an accurate
// View is a view of indexed data that indexers can provide. It is optional and may be nil.
// If it is provided it can be used for automated testing and other purposes.
// At indexer start-up, the block number returned by the view will be used to determine the
// starting block for the indexer. If the block number is 0, the indexer manager will attempt
// to perform a catch-up sync of state. Historical events will not be replayed, but an accurate
// representation of the current state at the height at which indexing began can be reproduced.
LastBlockPersisted int64
// If the block number is non-zero but does not match the current chain height, a runtime error
// will occur because this is an unsafe condition that indicates lost data.
View view.AppData
}
7 changes: 4 additions & 3 deletions schema/testing/appdatasim/app_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"cosmossdk.io/schema"
"cosmossdk.io/schema/appdata"
"cosmossdk.io/schema/testing/statesim"
"cosmossdk.io/schema/view"
)

// Options are the options for creating an app data simulator.
Expand Down Expand Up @@ -151,11 +152,11 @@ func (a *Simulator) ProcessPacket(packet appdata.Packet) error {
}

// AppState returns the current app state backing the simulator.
func (a *Simulator) AppState() statesim.AppState {
func (a *Simulator) AppState() view.AppState {
return a.state
}

// BlockNum returns the current block number of the simulator.
func (a *Simulator) BlockNum() uint64 {
return a.blockNum
func (a *Simulator) BlockNum() (uint64, error) {
return a.blockNum, nil
}
30 changes: 16 additions & 14 deletions schema/testing/appdatasim/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,36 @@ import (
"fmt"

"cosmossdk.io/schema/testing/statesim"
"cosmossdk.io/schema/view"
)

// HasAppData defines an interface for things that hold app data include app state.
// If an indexer implements this then DiffAppData can be used to compare it with
// the Simulator state which also implements this.
type HasAppData interface {
// AppState returns the app state.
AppState() statesim.AppState

// BlockNum returns the latest block number.
BlockNum() uint64
}

// DiffAppData compares the app data of two objects that implement HasAppData.
// This can be used by indexer to compare their state with the Simulator state
// if the indexer implements HasAppData.
// It returns a human-readable diff if the app data differs and the empty string
// if they are the same.
func DiffAppData(expected, actual HasAppData) string {
func DiffAppData(expected, actual view.AppData) string {
res := ""

if stateDiff := statesim.DiffAppStates(expected.AppState(), actual.AppState()); stateDiff != "" {
res += "App State Diff:\n"
res += stateDiff
}

if expected.BlockNum() != actual.BlockNum() {
res += fmt.Sprintf("BlockNum: expected %d, got %d\n", expected.BlockNum(), actual.BlockNum())
expectedBlock, err := expected.BlockNum()
if err != nil {
res += fmt.Sprintf("ERROR getting expected block num: %s\n", err)
return res
}

actualBlock, err := actual.BlockNum()
if err != nil {
res += fmt.Sprintf("ERROR getting actual block num: %s\n", err)
return res
}

if expectedBlock != actualBlock {
res += fmt.Sprintf("BlockNum: expected %d, got %d\n", expectedBlock, actualBlock)
}

return res
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ StartBlock: {6 <nil> <nil>}
OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["A𞥟",981],"Value":null,"Delete":false},{"TypeName":"ManyValues","Key":"ᵕ؏­􏿽A","Value":{"Value1":-317,"Value2":"AA==","Value3":-37.62890625,"Value4":232},"Delete":false}]}
OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"AACHBAjyAgFHOQAABo+PGAK3Bj7TwwBb/wAB3gE=","Value":{"valNotNull":"HBwBHAY6AAKO+UwDKRICAT0lgRRvCRvHFFoNAigBAUEDHoQUfB2qApRB/z41AAubARsBATQg3gCppQMAAQwHAQ=="},"Delete":false}]}
OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_decimal","Key":"9.5E+8","Value":["-2","88111430.0122412446"],"Delete":false}]}
OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint8","Key":7,"Value":null,"Delete":true},{"TypeName":"test_time","Key":"1970-01-01T00:59:59.999999999+01:00","Value":["1970-01-01T01:00:00.000000001+01:00",null],"Delete":false}]}
OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint8","Key":7,"Value":null,"Delete":true},{"TypeName":"test_time","Key":"1969-12-31T18:59:59.999999999-05:00","Value":["1969-12-31T19:00:00.000000001-05:00",null],"Delete":false}]}
OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":"൴~𝔶ٞ蹯a_ ᛮ!؋aض©-?","Value":{"Value2":""},"Delete":false}]}
OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint8","Key":14,"Value":{"valNotNull":116},"Delete":false},{"TypeName":"test_duration","Key":100403021838,"Value":[1547,null],"Delete":false}]}
OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_int64","Key":-34196421,"Value":[56,224549431],"Delete":false},{"TypeName":"test_bool","Key":true,"Value":{"valNotNull":true,"valNullable":null},"Delete":false}]}
Expand Down
10 changes: 5 additions & 5 deletions schema/testing/appdatasim/testdata/diff_example.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ Module all_kinds
Object key=š℠¼々¢~;-Ⱥ!˃a[ʰᾌ?{ᪧ৵%ᾯ¦〈: NOT FOUND
Object Collection test_time
OBJECT COUNT ERROR: expected 4, got 3
Object key=1970-01-01 01:00:00.000000005 +0100 CET: NOT FOUND
Object key=1970-01-01 01:00:00.001598687 +0100 CET
valNotNull: expected 1970-01-01 01:00:00.007727197 +0100 CET, got 1970-01-01 01:00:00.034531678 +0100 CET
valNullable: expected 1970-01-01 01:00:00.000000484 +0100 CET, got 1970-01-01 01:00:00.000000033 +0100 CET
Object key=1969-12-31 19:00:00.000000005 -0500 EST: NOT FOUND
Object key=1969-12-31 19:00:00.001598687 -0500 EST
valNotNull: expected 1969-12-31 19:00:00.007727197 -0500 EST, got 1969-12-31 19:00:00.034531678 -0500 EST
valNullable: expected 1969-12-31 19:00:00.000000484 -0500 EST, got 1969-12-31 19:00:00.000000033 -0500 EST
Object Collection test_uint16
OBJECT COUNT ERROR: expected 4, got 3
Object key=23712: NOT FOUND
Expand All @@ -75,5 +75,5 @@ Module all_kinds
Object Collection test_uint8
OBJECT COUNT ERROR: expected 3, got 2
Object key=1: NOT FOUND
Module test_cases: NOT FOUND
Module test_cases: actual module NOT FOUND
BlockNum: expected 2, got 1
21 changes: 13 additions & 8 deletions schema/testing/statesim/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"cosmossdk.io/schema"
"cosmossdk.io/schema/appdata"
"cosmossdk.io/schema/view"
)

// App is a collection of simulated module states corresponding to an app's schema for testing purposes.
Expand All @@ -27,7 +28,7 @@ func NewApp(appSchema map[string]schema.ModuleSchema, options Options) *App {
}

for moduleName, moduleSchema := range appSchema {
moduleState := NewModule(moduleSchema, options)
moduleState := NewModule(moduleName, moduleSchema, options)
app.moduleStates.Set(moduleName, moduleState)
}

Expand Down Expand Up @@ -62,7 +63,7 @@ func (a *App) InitializeModule(data appdata.ModuleInitializationData) error {
return fmt.Errorf("module %s already initialized", data.ModuleName)
}

a.moduleStates.Set(data.ModuleName, NewModule(data.Schema, a.options))
a.moduleStates.Set(data.ModuleName, NewModule(data.ModuleName, data.Schema, a.options))
return nil
}

Expand Down Expand Up @@ -91,18 +92,22 @@ func (a *App) UpdateGen() *rapid.Generator[appdata.ObjectUpdateData] {
}

// GetModule returns the module state for the given module name.
func (a *App) GetModule(moduleName string) (ModuleState, bool) {
return a.moduleStates.Get(moduleName)
func (a *App) GetModule(moduleName string) (view.ModuleState, error) {
mod, ok := a.moduleStates.Get(moduleName)
if !ok {
return nil, nil
}
return mod, nil
}

// Modules iterates over all the module state instances in the app.
func (a *App) Modules(f func(moduleName string, modState ModuleState) bool) {
func (a *App) Modules(f func(modState view.ModuleState, err error) bool) {
a.moduleStates.Scan(func(key string, value *Module) bool {
return f(key, value)
return f(value, nil)
})
}

// NumModules returns the number of modules in the app.
func (a *App) NumModules() int {
return a.moduleStates.Len()
func (a *App) NumModules() (int, error) {
return a.moduleStates.Len(), nil
}
52 changes: 33 additions & 19 deletions schema/testing/statesim/app_diff.go
Original file line number Diff line number Diff line change
@@ -1,32 +1,46 @@
package statesim

import "fmt"
import (
"fmt"

// AppState defines an interface for things that represent application state in schema format.
type AppState interface {
// GetModule returns the module state for the given module name.
GetModule(moduleName string) (ModuleState, bool)

// Modules iterates over all the module state instances in the app.
Modules(f func(moduleName string, modState ModuleState) bool)

// NumModules returns the number of modules in the app.
NumModules() int
}
"cosmossdk.io/schema/view"
)

// DiffAppStates compares the app state of two objects that implement AppState and returns a string with a diff if they
// are different or the empty string if they are the same.
func DiffAppStates(expected, actual AppState) string {
func DiffAppStates(expected, actual view.AppState) string {
res := ""

if expected.NumModules() != actual.NumModules() {
res += fmt.Sprintf("MODULE COUNT ERROR: expected %d, got %d\n", expected.NumModules(), actual.NumModules())
expectNumModules, err := expected.NumModules()
if err != nil {
res += fmt.Sprintf("ERROR getting expected num modules: %s\n", err)
return res
}

actualNumModules, err := actual.NumModules()
if err != nil {
res += fmt.Sprintf("ERROR getting actual num modules: %s\n", err)
return res
}

if expectNumModules != actualNumModules {
res += fmt.Sprintf("MODULE COUNT ERROR: expected %d, got %d\n", expectNumModules, actualNumModules)
}

expected.Modules(func(moduleName string, expectedMod ModuleState) bool {
actualMod, found := actual.GetModule(moduleName)
if !found {
res += fmt.Sprintf("Module %s: NOT FOUND\n", moduleName)
expected.Modules(func(expectedMod view.ModuleState, err error) bool {
if err != nil {
res += fmt.Sprintf("ERROR getting expected module: %s\n", err)
return true
}

moduleName := expectedMod.ModuleName()
actualMod, err := actual.GetModule(moduleName)
if err != nil {
res += fmt.Sprintf("ERROR getting actual module: %s\n", err)
return true
}
if actualMod == nil {
res += fmt.Sprintf("Module %s: actual module NOT FOUND\n", moduleName)
return true
}

Expand Down
Loading

0 comments on commit aca492c

Please sign in to comment.