-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
v2 genesis #20076
v2 genesis #20076
Changes from 11 commits
50a2333
481d327
f971ee6
f547b91
326345d
db09b12
1f98e32
b4452e1
b7ab61e
46992b5
41cf76b
b468294
aac84e3
12a52c9
ab6d7aa
fe760b7
8a404fd
c725900
8933045
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
package app | ||
|
||
var RuntimeIdentity = []byte("runtime") | ||
var ConsensusIdentity = []byte("consensus") | ||
var ( | ||
RuntimeIdentity = []byte("runtime") | ||
ConsensusIdentity = []byte("consensus") | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,8 @@ | |
"fmt" | ||
"sort" | ||
|
||
"cosmossdk.io/core/genesis" | ||
|
||
"github.com/golang/protobuf/proto" | ||
"golang.org/x/exp/maps" | ||
"google.golang.org/grpc" | ||
|
@@ -26,6 +28,7 @@ | |
|
||
"github.com/cosmos/cosmos-sdk/codec" | ||
sdkmodule "github.com/cosmos/cosmos-sdk/types/module" | ||
"github.com/cosmos/cosmos-sdk/x/genutil/types" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To remove this dependency a genesis themed extension interface in |
||
) | ||
|
||
type MM struct { | ||
|
@@ -140,9 +143,68 @@ | |
return nil | ||
} | ||
|
||
// InitGenesis performs init genesis functionality for modules. | ||
func (m *MM) InitGenesis() { | ||
panic("implement me") | ||
// InitGenesisJSON performs init genesis functionality for modules from genesis data in JSON format | ||
func (m *MM) InitGenesisJSON(ctx context.Context, genesisData map[string]json.RawMessage, txHandler func(json.RawMessage) error) error { | ||
m.logger.Info("initializing blockchain state from genesis.json", "order", m.config.InitGenesis) | ||
var seenValUpdates bool | ||
for _, moduleName := range m.config.InitGenesis { | ||
if genesisData[moduleName] == nil { | ||
continue | ||
} | ||
|
||
mod := m.modules[moduleName] | ||
|
||
// skip genutil as it's a special module that handles gentxs | ||
// TODO: should this be an empty extension interface on genutil for server v2? | ||
if moduleName == "genutil" { | ||
var genesisState types.GenesisState | ||
err := m.cdc.UnmarshalJSON(genesisData[moduleName], &genesisState) | ||
if err != nil { | ||
return fmt.Errorf("failed to unmarshal %s genesis state: %w", moduleName, err) | ||
} | ||
for _, jsonTx := range genesisState.GenTxs { | ||
txHandler(jsonTx) | ||
|
||
} | ||
continue | ||
} | ||
|
||
// we might get an adapted module, a native core API module or a legacy module | ||
if module, ok := mod.(appmodule.HasGenesisAuto); ok { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we shouldn't support |
||
m.logger.Debug("running initialization for module", "module", moduleName) | ||
// core API genesis | ||
source, err := genesis.SourceFromRawJSON(genesisData[moduleName]) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
err = module.InitGenesis(ctx, source) | ||
if err != nil { | ||
return err | ||
} | ||
} else if module, ok := mod.(appmodulev2.HasGenesis); ok { | ||
m.logger.Debug("running initialization for module", "module", moduleName) | ||
if err := module.InitGenesis(ctx, genesisData[moduleName]); err != nil { | ||
return err | ||
} | ||
} else if module, ok := mod.(appmodulev2.HasABCIGenesis); ok { | ||
m.logger.Debug("running initialization for module", "module", moduleName) | ||
moduleValUpdates, err := module.InitGenesis(ctx, genesisData[moduleName]) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// use these validator updates if provided, the module manager assumes | ||
// only one module will update the validator set | ||
if len(moduleValUpdates) > 0 { | ||
if seenValUpdates { | ||
return errors.New("validator InitGenesis updates already set by a previous module") | ||
} else { | ||
seenValUpdates = true | ||
} | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// ExportGenesis performs export genesis functionality for modules | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
package appmanager | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
|
||
|
@@ -22,6 +24,8 @@ type AppManager[T transaction.Tx] struct { | |
exportState func(ctx context.Context, dst map[string]io.Writer) error | ||
importState func(ctx context.Context, src map[string]io.Reader) error | ||
|
||
initGenesis func(ctx context.Context, state io.Reader, txHandler func(tx json.RawMessage) error) error | ||
|
||
stf *stf.STF[T] | ||
} | ||
|
||
|
@@ -30,30 +34,50 @@ func (a AppManager[T]) InitGenesis( | |
headerInfo header.Info, | ||
consensusMessages []transaction.Type, | ||
initGenesisJSON []byte, | ||
) (corestore.WriterMap, error) { | ||
txDecoder transaction.Codec[T], | ||
) (*appmanager.BlockResponse, corestore.WriterMap, error) { | ||
v, zeroState, err := a.db.StateLatest() | ||
if err != nil { | ||
return nil, nil, fmt.Errorf("unable to get latest state: %w", err) | ||
} | ||
if v != 0 { | ||
return nil, nil, fmt.Errorf("cannot init genesis on non-zero state") | ||
} | ||
|
||
var genTxs []T | ||
zeroState, err = a.stf.RunWithCtx(ctx, zeroState, func(ctx context.Context) error { | ||
return a.initGenesis(ctx, bytes.NewBuffer(initGenesisJSON), func(jsonTx json.RawMessage) error { | ||
genTx, err := txDecoder.DecodeJSON(jsonTx) | ||
if err != nil { | ||
return fmt.Errorf("failed to decode genesis transaction: %w", err) | ||
} | ||
genTxs = append(genTxs, genTx) | ||
return nil | ||
}) | ||
}) | ||
if err != nil { | ||
return nil, nil, fmt.Errorf("failed to import genesis state: %w", err) | ||
} | ||
// run block 0 | ||
// TODO: in an ideal world, genesis state is simply an initial state being applied | ||
// unaware of what that state means in relation to every other, so here we can | ||
// chain genesis | ||
block0 := &appmanager.BlockRequest[T]{ | ||
Height: uint64(headerInfo.Height), | ||
Height: uint64(0), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just curious why we hardcode run at block 0 here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. note from call: use height from request, check if storage has any value, if empty then assume genesis |
||
Time: headerInfo.Time, | ||
Hash: headerInfo.Hash, | ||
ChainId: headerInfo.ChainID, | ||
AppHash: headerInfo.AppHash, | ||
Txs: nil, | ||
Txs: genTxs, | ||
ConsensusMessages: consensusMessages, | ||
} | ||
|
||
_, genesisState, err := a.DeliverBlock(ctx, block0) | ||
blockresponse, genesisState, err := a.stf.DeliverBlock(ctx, block0, zeroState) | ||
if err != nil { | ||
return nil, err | ||
return blockresponse, nil, fmt.Errorf("failed to deliver block 0: %w", err) | ||
} | ||
|
||
// TODO: ok so the problem we have now, the genesis is a mix of initial state | ||
// then followed by txs from the genutil module. | ||
|
||
return genesisState, nil | ||
return blockresponse, genesisState, err | ||
} | ||
|
||
func (a AppManager[T]) DeliverBlock( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For usage see: https://github.com/cosmos/cosmos-sdk/blob/kocu/genesis-v2/x/distribution/keeper/abci.go#L27
I think this can be resolved with #19602 which adds a message to retrieve
CometInfo
from the RouterService, or optionally including a keeper.