Skip to content

Commit 3db444a

Browse files
authored
perf: incremental json parsing for AppGenesis (#21249)
1 parent 5028893 commit 3db444a

2 files changed

Lines changed: 44 additions & 28 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ Every module contains its own CHANGELOG.md. Please refer to the module you are i
4949

5050
* (client) [#21436](https://github.com/cosmos/cosmos-sdk/pull/21436) Use `address.Codec` from client.Context in `tx.Sign`.
5151
* (internal) [#21412](https://github.com/cosmos/cosmos-sdk/pull/21412) Using unsafe.String and unsafe.SliceData.
52+
* (x/genutil) [#21249](https://github.com/cosmos/cosmos-sdk/pull/21249) Incremental JSON parsing for AppGenesis where possible.
5253

5354
### Bug Fixes
5455

x/genutil/types/genesis.go

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package types
22

33
import (
4-
"bufio"
54
"bytes"
65
"encoding/json"
76
"errors"
@@ -89,35 +88,50 @@ func (ag *AppGenesis) SaveAs(file string) error {
8988

9089
// AppGenesisFromReader reads the AppGenesis from the reader.
9190
func AppGenesisFromReader(reader io.Reader) (*AppGenesis, error) {
92-
jsonBlob, err := io.ReadAll(reader)
93-
if err != nil {
94-
return nil, err
95-
}
96-
97-
var appGenesis AppGenesis
98-
if err := json.Unmarshal(jsonBlob, &appGenesis); err != nil {
99-
// fallback to CometBFT genesis
100-
var ctmGenesis cmttypes.GenesisDoc
101-
if err2 := cmtjson.Unmarshal(jsonBlob, &ctmGenesis); err2 != nil {
102-
return nil, fmt.Errorf("error unmarshalling AppGenesis: %w\n failed fallback to CometBFT GenDoc: %w", err, err2)
91+
var ag AppGenesis
92+
var err error
93+
// check if io.ReadSeeker is implemented
94+
if rs, ok := reader.(io.ReadSeeker); ok {
95+
err = json.NewDecoder(rs).Decode(&ag)
96+
if err == nil {
97+
return &ag, nil
10398
}
10499

105-
appGenesis = AppGenesis{
106-
AppName: version.AppName,
107-
// AppVersion is not filled as we do not know it from a CometBFT genesis
108-
GenesisTime: ctmGenesis.GenesisTime,
109-
ChainID: ctmGenesis.ChainID,
110-
InitialHeight: ctmGenesis.InitialHeight,
111-
AppHash: ctmGenesis.AppHash,
112-
AppState: ctmGenesis.AppState,
113-
Consensus: &ConsensusGenesis{
114-
Validators: ctmGenesis.Validators,
115-
Params: ctmGenesis.ConsensusParams,
116-
},
100+
err = fmt.Errorf("error unmarshalling AppGenesis: %w", err)
101+
if _, serr := rs.Seek(0, io.SeekStart); serr != nil {
102+
err = errors.Join(err, fmt.Errorf("error seeking back to the front: %w", serr))
103+
return nil, err
117104
}
118105
}
119106

120-
return &appGenesis, nil
107+
// TODO: once cmtjson implements incremental parsing, we can avoid storing the entire file in memory
108+
jsonBlob, ioerr := io.ReadAll(reader)
109+
if ioerr != nil {
110+
err = errors.Join(err, fmt.Errorf("failed to read file completely: %w", ioerr))
111+
return nil, err
112+
}
113+
114+
// fallback to comet genesis parsing
115+
var ctmGenesis cmttypes.GenesisDoc
116+
if uerr := cmtjson.Unmarshal(jsonBlob, &ctmGenesis); uerr != nil {
117+
err = errors.Join(err, fmt.Errorf("failed fallback to CometBFT GenDoc: %w", uerr))
118+
return nil, err
119+
}
120+
121+
ag = AppGenesis{
122+
AppName: version.AppName,
123+
// AppVersion is not filled as we do not know it from a CometBFT genesis
124+
GenesisTime: ctmGenesis.GenesisTime,
125+
ChainID: ctmGenesis.ChainID,
126+
InitialHeight: ctmGenesis.InitialHeight,
127+
AppHash: ctmGenesis.AppHash,
128+
AppState: ctmGenesis.AppState,
129+
Consensus: &ConsensusGenesis{
130+
Validators: ctmGenesis.Validators,
131+
Params: ctmGenesis.ConsensusParams,
132+
},
133+
}
134+
return &ag, nil
121135
}
122136

123137
// AppGenesisFromFile reads the AppGenesis from the provided file.
@@ -127,13 +141,14 @@ func AppGenesisFromFile(genFile string) (*AppGenesis, error) {
127141
return nil, err
128142
}
129143

130-
appGenesis, err := AppGenesisFromReader(bufio.NewReader(file))
144+
appGenesis, err := AppGenesisFromReader(file)
145+
ferr := file.Close()
131146
if err != nil {
132147
return nil, fmt.Errorf("failed to read genesis from file %s: %w", genFile, err)
133148
}
134149

135-
if err := file.Close(); err != nil {
136-
return nil, err
150+
if ferr != nil {
151+
return nil, ferr
137152
}
138153

139154
return appGenesis, nil

0 commit comments

Comments
 (0)