Skip to content

Commit

Permalink
feat: save InitChain tx responses
Browse files Browse the repository at this point in the history
Signed-off-by: Norman Meier <[email protected]>
  • Loading branch information
n0izn0iz committed Jun 10, 2024
1 parent 3f5a6ad commit 97733cb
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 11 deletions.
11 changes: 10 additions & 1 deletion gno.land/pkg/gnoland/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ func PanicOnFailingTxHandler(ctx sdk.Context, tx std.Tx, res sdk.Result) {
// InitChainer returns a function that can initialize the chain with genesis.
func InitChainer(baseApp *sdk.BaseApp, acctKpr auth.AccountKeeperI, bankKpr bank.BankKeeperI, resHandler GenesisTxHandler) func(sdk.Context, abci.RequestInitChain) abci.ResponseInitChain {
return func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
txResponses := []abci.ResponseDeliverTx{}

if req.AppState != nil {
// Get genesis state
genState := req.AppState.(GnoGenesisState)
Expand All @@ -183,13 +185,20 @@ func InitChainer(baseApp *sdk.BaseApp, acctKpr auth.AccountKeeperI, bankKpr bank
)
}

txResponses = append(txResponses, abci.ResponseDeliverTx{
ResponseBase: res.ResponseBase,
GasWanted: res.GasWanted,
GasUsed: res.GasUsed,
})

resHandler(ctx, tx, res)
}
}

// Done!
return abci.ResponseInitChain{
Validators: req.Validators,
Validators: req.Validators,
TxResponses: txResponses,
}
}
}
Expand Down
1 change: 1 addition & 0 deletions tm2/pkg/bft/abci/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ type ResponseInitChain struct {
ResponseBase
ConsensusParams *ConsensusParams
Validators []ValidatorUpdate
TxResponses []ResponseDeliverTx
}

type ResponseQuery struct {
Expand Down
5 changes: 5 additions & 0 deletions tm2/pkg/bft/consensus/replay.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,11 @@ func (h *Handshaker) ReplayBlocks(
return nil, err
}

// save responses
abciResponse := sm.NewABCIResponsesFromNum(len(res.TxResponses))
copy(abciResponse.DeliverTxs, res.TxResponses)
sm.SaveABCIResponses(h.stateDB, 0, abciResponse)

if stateBlockHeight == 0 { // we only update state when we are in initial state
// If the app returned validators or consensus params, update the state.
if len(res.Validators) > 0 {
Expand Down
45 changes: 45 additions & 0 deletions tm2/pkg/bft/consensus/replay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1172,3 +1172,48 @@ func (ica *initChainApp) InitChain(req abci.RequestInitChain) abci.ResponseInitC
Validators: ica.vals,
}
}

func TestHandshakeGenesisResponseDeliverTx(t *testing.T) {
t.Parallel()

app := &initTxsApp{}
clientCreator := proxy.NewLocalClientCreator(app)

config, genesisFile := ResetConfig("handshake_test_")
defer os.RemoveAll(config.RootDir)
stateDB, state, store := makeStateAndStore(config, genesisFile, "v0.0.0-test")

// now start the app using the handshake - it should sync
genDoc, _ := sm.MakeGenesisDocFromFile(genesisFile)
handshaker := NewHandshaker(stateDB, state, store, genDoc)
proxyApp := appconn.NewAppConns(clientCreator)
if err := proxyApp.Start(); err != nil {
t.Fatalf("Error starting proxy app connections: %v", err)
}
defer proxyApp.Stop()
if err := handshaker.Handshake(proxyApp); err != nil {
t.Fatalf("Error on abci handshake: %v", err)
}

// check that the genesis transaction results are saved
res, err := sm.LoadABCIResponses(stateDB, 0)
if err != nil {
t.Fatalf("Failed to load genesis ABCI responses: %v", err)
}

if len(res.DeliverTxs) != numInitResponses {
t.Fatalf("Expected %d genesis tx responses, got %d", numInitResponses, len(res.DeliverTxs))
}
}

const numInitResponses = 42

type initTxsApp struct {
abci.BaseApplication
}

func (ica *initTxsApp) InitChain(req abci.RequestInitChain) abci.ResponseInitChain {
return abci.ResponseInitChain{
TxResponses: make([]abci.ResponseDeliverTx, numInitResponses),
}
}
2 changes: 1 addition & 1 deletion tm2/pkg/bft/state/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func (blockExec *BlockExecutor) ApplyBlock(state State, blockID types.BlockID, b
fail.Fail() // XXX

// Save the results before we commit.
saveABCIResponses(blockExec.db, block.Height, abciResponses)
SaveABCIResponses(blockExec.db, block.Height, abciResponses)

// Save the transaction results
for index, tx := range block.Txs {
Expand Down
6 changes: 0 additions & 6 deletions tm2/pkg/bft/state/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,6 @@ func CalcValidatorsKey(height int64) []byte {
return calcValidatorsKey(height)
}

// SaveABCIResponses is an alias for the private saveABCIResponses method in
// store.go, exported exclusively and explicitly for testing.
func SaveABCIResponses(db dbm.DB, height int64, abciResponses *ABCIResponses) {
saveABCIResponses(db, height, abciResponses)
}

// SaveConsensusParamsInfo is an alias for the private saveConsensusParamsInfo
// method in store.go, exported exclusively and explicitly for testing.
func SaveConsensusParamsInfo(db dbm.DB, nextHeight, changeHeight int64, params abci.ConsensusParams) {
Expand Down
12 changes: 9 additions & 3 deletions tm2/pkg/bft/state/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/gnolang/gno/tm2/pkg/bft/types"
dbm "github.com/gnolang/gno/tm2/pkg/db"
osm "github.com/gnolang/gno/tm2/pkg/os"
"golang.org/x/exp/constraints"
)

const (
Expand Down Expand Up @@ -131,8 +132,13 @@ type ABCIResponses struct {

// NewABCIResponses returns a new ABCIResponses
func NewABCIResponses(block *types.Block) *ABCIResponses {
resDeliverTxs := make([]abci.ResponseDeliverTx, block.NumTxs)
if block.NumTxs == 0 {
return NewABCIResponsesFromNum(block.NumTxs)
}

// NewABCIResponses returns a new ABCIResponses
func NewABCIResponsesFromNum[N constraints.Integer](numTxs N) *ABCIResponses {
resDeliverTxs := make([]abci.ResponseDeliverTx, numTxs)
if numTxs == 0 {
// This makes Amino encoding/decoding consistent.
resDeliverTxs = nil
}
Expand Down Expand Up @@ -175,7 +181,7 @@ func LoadABCIResponses(db dbm.DB, height int64) (*ABCIResponses, error) {
// SaveABCIResponses persists the ABCIResponses to the database.
// This is useful in case we crash after app.Commit and before s.Save().
// Responses are indexed by height so they can also be loaded later to produce Merkle proofs.
func saveABCIResponses(db dbm.DB, height int64, abciResponses *ABCIResponses) {
func SaveABCIResponses(db dbm.DB, height int64, abciResponses *ABCIResponses) {
db.Set(CalcABCIResponsesKey(height), abciResponses.Bytes())
}

Expand Down

0 comments on commit 97733cb

Please sign in to comment.