From 678986251a4fd9f9f0360c917a10274e04f8c375 Mon Sep 17 00:00:00 2001
From: yys <sw.yunsuk@gmail.com>
Date: Tue, 19 Oct 2021 18:30:51 +0900
Subject: [PATCH] fix: rosetta `getHeight` function to use
 tmRPC.GenesisChunked() instead tmRPC.Genesis() (#10340)

<!--
The default pull request template is for types feat, fix, or refactor.
For other templates, add one of the following parameters to the url:
- template=docs.md
- template=other.md
-->

## Description

When we enable rosetta from the chain with non-zero initial height & huge genesis, it always return
```
Error: rosetta: (502) bad gateway
```

This is due to huge genesis load rejection from Tendermint.

In current implementation, rosetta server requests genesis to get initial height
```
c.tmRPC.Genesis(ctx)
```

but, this will be failed with below message when the genesis is huge
```
{
  "jsonrpc": "2.0",
  "id": -1,
  "error": {
    "code": -32603,
    "message": "Internal error",
    "data": "genesis response is large, please use the genesis_chunked API instead"
  }
}
```

To fix this, we can use following lines
```
status, err := c.tmRPC. GenesisChunked(ctx)

```
---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
---
 CHANGELOG.md                         |  3 ++-
 server/rosetta/client_online.go      | 33 ++++++++++++++++++++++++++--
 server/rosetta/client_online_test.go | 15 +++++++++++++
 3 files changed, 48 insertions(+), 3 deletions(-)
 create mode 100644 server/rosetta/client_online_test.go

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8f059ebd001a..473540dfce4c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -135,7 +135,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
 
 ### Bug Fixes
 
-* (client) [#10226](https://github.com/cosmos/cosmos-sdk/pull/10226) Fix --home flag parsing.
+* (rosetta) [\#10340](https://github.com/cosmos/cosmos-sdk/pull/10340) Use `GenesisChunked(ctx)` instead `Genesis(ctx)` to get genesis block height
+* (client) [#10226](https://github.com/cosmos/cosmos-sdk/pull/10226) Fix --home flag parsing. 
 * [#10180](https://github.com/cosmos/cosmos-sdk/issues/10180) Documentation: make references to Cosmos SDK consistent
 * (x/genutil) [#10104](https://github.com/cosmos/cosmos-sdk/pull/10104) Ensure the `init` command reads the `--home` flag value correctly.
 * [\#9651](https://github.com/cosmos/cosmos-sdk/pull/9651) Change inconsistent limit of `0` to `MaxUint64` on InfiniteGasMeter and add GasRemaining func to GasMeter.
diff --git a/server/rosetta/client_online.go b/server/rosetta/client_online.go
index 0a34b8b1a878..177c01131810 100644
--- a/server/rosetta/client_online.go
+++ b/server/rosetta/client_online.go
@@ -3,8 +3,11 @@ package rosetta
 import (
 	"bytes"
 	"context"
+	"encoding/base64"
 	"encoding/hex"
+	"errors"
 	"fmt"
+	"regexp"
 	"strconv"
 	"time"
 
@@ -481,13 +484,39 @@ func (c *Client) blockTxs(ctx context.Context, height *int64) (crgtypes.BlockTra
 
 func (c *Client) getHeight(ctx context.Context, height *int64) (realHeight *int64, err error) {
 	if height != nil && *height == -1 {
-		genesis, err := c.tmRPC.Genesis(ctx)
+		genesisChunk, err := c.tmRPC.GenesisChunked(ctx, 0)
 		if err != nil {
 			return nil, err
 		}
-		realHeight = &(genesis.Genesis.InitialHeight)
+
+		heightNum, err := extractInitialHeightFromGenesisChunk(genesisChunk.Data)
+		if err != nil {
+			return nil, err
+		}
+
+		realHeight = &heightNum
 	} else {
 		realHeight = height
 	}
 	return
 }
+
+func extractInitialHeightFromGenesisChunk(genesisChunk string) (int64, error) {
+	firstChunk, err := base64.StdEncoding.DecodeString(genesisChunk)
+	if err != nil {
+		return 0, err
+	}
+
+	re, err := regexp.Compile("\"initial_height\":\"(\\d+)\"")
+	if err != nil {
+		return 0, err
+	}
+
+	matches := re.FindStringSubmatch(string(firstChunk))
+	if len(matches) != 2 {
+		return 0, errors.New("failed to fetch initial_height")
+	}
+
+	heightStr := matches[1]
+	return strconv.ParseInt(heightStr, 10, 64)
+}
diff --git a/server/rosetta/client_online_test.go b/server/rosetta/client_online_test.go
new file mode 100644
index 000000000000..9aa8965cf6e9
--- /dev/null
+++ b/server/rosetta/client_online_test.go
@@ -0,0 +1,15 @@
+package rosetta
+
+import (
+	"encoding/base64"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestRegex(t *testing.T) {
+	genesisChuck := base64.StdEncoding.EncodeToString([]byte(`"genesis_time":"2021-09-28T09:00:00Z","chain_id":"bombay-12","initial_height":"5900001","consensus_params":{"block":{"max_bytes":"5000000","max_gas":"1000000000","time_iota_ms":"1000"},"evidence":{"max_age_num_blocks":"100000","max_age_duration":"172800000000000","max_bytes":"50000"},"validator":{"pub_key_types":["ed25519"]},"version":{}},"validators":[{"address":"EEA4891F5F8D523A6B4B3EAC84B5C08655A00409","pub_key":{"type":"tendermint/PubKeyEd25519","value":"UX71gTBNumQq42qRd6j/K8XN/y3/HAcuAJxj97utawI="},"power":"60612","name":"BTC.Secure"},{"address":"973F589DE1CC8A54ABE2ABE0E0A4ABF13A9EBAE4","pub_key":{"type":"tendermint/PubKeyEd25519","value":"AmGQvQSAAXzSIscx/6o4rVdRMT9QvairQHaCXsWhY+c="},"power":"835","name":"MoonletWallet"},{"address":"831F402BDA0C9A3F260D4F221780BC22A4C3FB23","pub_key":{"type":"tendermint/PubKeyEd25519","value":"Tw8yKbPNEo113ZNbJJ8joeXokoMdBoazRTwb1NQ77WA="},"power":"102842","name":"BlockNgine"},{"address":"F2683F267D2B4C8714B44D68612DB37A8DD2EED7","pub_key":{"type":"tendermint/PubKeyEd25519","value":"PVE4IcWDE6QEqJSEkx55IDkg5zxBo8tVRzKFMJXYFSQ="},"power":"23200","name":"Luna Station 88"},{"address":"9D2428CBAC68C654BE11BE405344C560E6A0F626","pub_key":{"type":"tendermint/PubKeyEd25519","value":"93hzGmZjPRqOnQkb8BULjqanW3M2p1qIcLVTGkf1Zhk="},"power":"35420","name":"Terra-India"},{"address":"DC9897F22E74BF1B66E2640FA461F785F9BA7627","pub_key":{"type":"tendermint/PubKeyEd25519","value":"mlYb/Dzqwh0YJjfH59OZ4vtp+Zhdq5Oj5MNaGHq1X0E="},"power":"25163","name":"SolidStake"},{"address":"AA1A027E270A2BD7AF154999E6DE9D39C5711DE7","pub_key":{"type":"tendermint/PubKeyEd25519","value":"28z8FlpbC7sR0f1Q8OWFASDNi0FAmdldzetwQ07JJzg="},"power":"34529","name":"syncnode"},{"address":"E548735750DC5015ADDE3B0E7A1294C3B868680B","pub_key":{"type":"tendermint/PubKeyEd25519","value":"BTDtLSKp4wpQrWBwmGvp9isWC5jXaAtX1nrJtsCEWew="},"power":"36082","name":"OneStar"}`))
+	height, err := extractInitialHeightFromGenesisChunk(genesisChuck)
+	require.NoError(t, err)
+	require.Equal(t, height, int64(5900001))
+}