diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go index d1978e76563..7ac25336bac 100644 --- a/gno.land/pkg/gnoland/app.go +++ b/gno.land/pkg/gnoland/app.go @@ -168,6 +168,7 @@ func InitChainer(baseApp *sdk.BaseApp, acctKpr auth.AccountKeeperI, bankKpr bank } // Run genesis txs. + txResponses := make([]abci.ResponseDeliverTx, 0, len(genState.Txs)) for _, tx := range genState.Txs { res := baseApp.Deliver(tx) if res.IsErr() { @@ -180,11 +181,17 @@ func InitChainer(baseApp *sdk.BaseApp, acctKpr auth.AccountKeeperI, bankKpr bank } resHandler(ctx, tx, res) + txResponses = append(txResponses, abci.ResponseDeliverTx{ + ResponseBase: res.ResponseBase, + GasWanted: res.GasWanted, + GasUsed: res.GasUsed, + }) } // Done! return abci.ResponseInitChain{ - Validators: req.Validators, + Validators: req.Validators, + TxResponses: txResponses, } } } diff --git a/tm2/pkg/bft/abci/types/types.go b/tm2/pkg/bft/abci/types/types.go index 637d09b92a3..0fb3eb0dcb0 100644 --- a/tm2/pkg/bft/abci/types/types.go +++ b/tm2/pkg/bft/abci/types/types.go @@ -147,6 +147,7 @@ type ResponseInitChain struct { ResponseBase ConsensusParams *ConsensusParams Validators []ValidatorUpdate + TxResponses []ResponseDeliverTx } type ResponseQuery struct { diff --git a/tm2/pkg/bft/consensus/replay.go b/tm2/pkg/bft/consensus/replay.go index a423d634c2f..2f24d5181b0 100644 --- a/tm2/pkg/bft/consensus/replay.go +++ b/tm2/pkg/bft/consensus/replay.go @@ -9,6 +9,7 @@ import ( "reflect" "time" + "github.com/gnolang/gno/tm2/pkg/amino" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" "github.com/gnolang/gno/tm2/pkg/bft/appconn" cstypes "github.com/gnolang/gno/tm2/pkg/bft/consensus/types" @@ -306,6 +307,7 @@ func (h *Handshaker) ReplayBlocks( if err != nil { return nil, err } + saveGenesisRes(h.stateDB, &res) if stateBlockHeight == 0 { // we only update state when we are in initial state // If the app returned validators or consensus params, update the state. @@ -393,6 +395,15 @@ func (h *Handshaker) ReplayBlocks( appBlockHeight, storeBlockHeight, stateBlockHeight)) } +// panics if failed to marshal the given genesis response +func saveGenesisRes(db dbm.DB, res *abci.ResponseInitChain) { + b, err := amino.MarshalJSON(res) + if err != nil { + panic(fmt.Sprintf("Failed to save genesis response due to marshaling error: %v", err)) + } + db.SetSync([]byte("genesisRes"), b) +} + func (h *Handshaker) replayBlocks(state sm.State, proxyApp appconn.AppConns, appBlockHeight, storeBlockHeight int64, mutateState bool) ([]byte, error) { // App is further behind than it should be, so we need to replay blocks. // We replay all blocks from appBlockHeight+1. diff --git a/tm2/pkg/bft/node/node.go b/tm2/pkg/bft/node/node.go index 5fe47bb8893..4679cfca7a3 100644 --- a/tm2/pkg/bft/node/node.go +++ b/tm2/pkg/bft/node/node.go @@ -427,6 +427,12 @@ func NewNode(config *cfg.Config, if err != nil { return nil, err } + /* + // doesn't work + block0 := types.MakeBlock(0, nil, nil) + block0.AppVersion = state.AppVersion + blockStore.SaveBlock(block0, nil, nil) + */ // Create the proxyApp and establish connections to the ABCI app (consensus, mempool, query). proxyApp, err := createAndStartProxyAppConns(clientCreator, logger) diff --git a/tm2/pkg/bft/rpc/core/blocks.go b/tm2/pkg/bft/rpc/core/blocks.go index 06bb3de1174..673404933dc 100644 --- a/tm2/pkg/bft/rpc/core/blocks.go +++ b/tm2/pkg/bft/rpc/core/blocks.go @@ -420,8 +420,8 @@ func BlockResults(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultBlockR func getHeight(currentHeight int64, heightPtr *int64) (int64, error) { if heightPtr != nil { height := *heightPtr - if height <= 0 { - return 0, fmt.Errorf("height must be greater than 0") + if height < 0 { + return 0, fmt.Errorf("height must be greater than or equal to 0") } if height > currentHeight { return 0, fmt.Errorf("height must be less than or equal to the current blockchain height") diff --git a/tm2/pkg/bft/rpc/core/net.go b/tm2/pkg/bft/rpc/core/net.go index 975d5ed822f..68b448cdb0b 100644 --- a/tm2/pkg/bft/rpc/core/net.go +++ b/tm2/pkg/bft/rpc/core/net.go @@ -1,8 +1,13 @@ package core import ( + "fmt" + + "github.com/gnolang/gno/tm2/pkg/amino" + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" rpctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/lib/types" + dbm "github.com/gnolang/gno/tm2/pkg/db" "github.com/gnolang/gno/tm2/pkg/errors" ) @@ -251,5 +256,22 @@ func UnsafeDialPeers(ctx *rpctypes.Context, peers []string, persistent bool) (*c // // ``` func Genesis(ctx *rpctypes.Context) (*ctypes.ResultGenesis, error) { - return &ctypes.ResultGenesis{Genesis: genDoc}, nil + res, err := loadGenesisRes(stateDB) + if err != nil { + return nil, err + } + return &ctypes.ResultGenesis{Genesis: genDoc, Response: res}, nil +} + +func loadGenesisRes(db dbm.DB) (*abci.ResponseInitChain, error) { + b := db.Get([]byte("genesisRes")) + if len(b) == 0 { + return nil, errors.New("Genesis res not found") + } + var genRes *abci.ResponseInitChain + err := amino.UnmarshalJSON(b, &genRes) + if err != nil { + panic(fmt.Sprintf("Failed to load genesis res due to unmarshaling error: %v (bytes: %X)", err, b)) + } + return genRes, nil } diff --git a/tm2/pkg/bft/rpc/core/types/responses.go b/tm2/pkg/bft/rpc/core/types/responses.go index 2874517147d..54c79b789b3 100644 --- a/tm2/pkg/bft/rpc/core/types/responses.go +++ b/tm2/pkg/bft/rpc/core/types/responses.go @@ -21,7 +21,8 @@ type ResultBlockchainInfo struct { // Genesis file type ResultGenesis struct { - Genesis *types.GenesisDoc `json:"genesis"` + Genesis *types.GenesisDoc `json:"genesis"` + Response *abci.ResponseInitChain `json:"response"` } // Single block (with meta) diff --git a/tm2/pkg/bft/store/store.go b/tm2/pkg/bft/store/store.go index e7671d8033e..d87215034dd 100644 --- a/tm2/pkg/bft/store/store.go +++ b/tm2/pkg/bft/store/store.go @@ -52,6 +52,10 @@ func (bs *BlockStore) Height() int64 { // LoadBlock returns the block with the given height. // If no block is found for that height, it returns nil. func (bs *BlockStore) LoadBlock(height int64) *types.Block { + if height == 0 { + return &types.Block{Header: types.Header{Height: 0, ChainID: "wololo"}} + } + blockMeta := bs.LoadBlockMeta(height) if blockMeta == nil { return nil diff --git a/tm2/pkg/sdk/baseapp.go b/tm2/pkg/sdk/baseapp.go index 1f62f53f81a..8cc4d245227 100644 --- a/tm2/pkg/sdk/baseapp.go +++ b/tm2/pkg/sdk/baseapp.go @@ -318,6 +318,16 @@ func (app *BaseApp) SetOption(req abci.RequestSetOption) (res abci.ResponseSetOp return } +// panics if failed to marshal the given genesis response +func saveGenesisRes(logger *slog.Logger, db dbm.DB, res *abci.ResponseInitChain) { + b, err := amino.MarshalJSON(res) + if err != nil { + panic(fmt.Sprintf("Failed to save genesis response due to marshaling error: %v", err)) + } + db.SetSync([]byte("genesisRes"), b) + logger.Info("saved genesis response", "response", string(b)) +} + // InitChain implements the ABCI interface. It runs the initialization logic // directly on the CommitMultiStore. func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain) {