Skip to content
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

R4R: Split the export command into reset and export #1522

Merged
merged 5 commits into from
Jun 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func MakeLatestCodec() *codec.Codec {
return cdc
}

func (app *IrisApp) ExportOrReplay(replayHeight int64) (replay bool, height int64) {
func (app *IrisApp) ResetOrReplay(replayHeight int64) (replay bool, height int64) {
lastBlockHeight := app.BaseApp.LastBlockHeight()
if replayHeight > lastBlockHeight {
replayHeight = lastBlockHeight
Expand Down
2 changes: 1 addition & 1 deletion app/v1/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
cfg "github.com/tendermint/tendermint/config"
)

const MetricsSubsystem = "v0"
const MetricsSubsystem = "v1"

type Metrics struct {
InvariantFailure metrics.Counter
Expand Down
15 changes: 11 additions & 4 deletions cmd/iris/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ func main() {
server.UnsafeResetAllCmd(ctx),
client.LineBreak,
tendermintCmd,
server.ResetCmd(ctx, cdc, resetAppState),
server.ExportCmd(ctx, cdc, exportAppStateAndTMValidators),
client.LineBreak,
)
Expand All @@ -84,18 +85,24 @@ func newApp(logger log.Logger, db dbm.DB, traceStore io.Writer, config *cfg.Inst
}

func exportAppStateAndTMValidators(ctx *server.Context,
logger log.Logger, db dbm.DB, traceStore io.Writer, height int64, forZeroHeight bool,
logger log.Logger, db dbm.DB, traceStore io.Writer, forZeroHeight bool,
) (json.RawMessage, []tmtypes.GenesisValidator, error) {
gApp := app.NewIrisApp(logger, db, ctx.Config.Instrumentation, traceStore)
return gApp.ExportAppStateAndValidators(forZeroHeight)
}

func resetAppState(ctx *server.Context,
logger log.Logger, db dbm.DB, traceStore io.Writer, height int64) error {
gApp := app.NewIrisApp(logger, db, ctx.Config.Instrumentation, traceStore)
if height > 0 {
if replay, replayHeight := gApp.ExportOrReplay(height); replay {
if replay, replayHeight := gApp.ResetOrReplay(height); replay {
_, err := startNodeAndReplay(ctx, gApp, replayHeight)
if err != nil {
return nil, nil, err
return err
}
}
}
return gApp.ExportAppStateAndValidators(forZeroHeight)
return nil
}

func startNodeAndReplay(ctx *server.Context, app *app.IrisApp, height int64) (n *node.Node, err error) {
Expand Down
4 changes: 3 additions & 1 deletion docs/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ module.exports = {
['How-to-install-irishub.md', 'Install'],
['cli-client.md', 'CLI Client'],
['light-client.md', 'Light Client'],
['export.md', 'Export'],
['reset.md', 'Reset Blockchain State'],
['export.md', 'Export Blockchain State'],
['sentry.md', 'Sentry'],
['tool.md', 'Tool'],
['monitor.md', 'Monitor'],
Expand Down Expand Up @@ -160,6 +161,7 @@ module.exports = {
['How-to-install-irishub.md', '安装'],
['cli-client.md', '命令行客户端'],
['light-client.md', '轻节点客户端(LCD)'],
['reset.md', '重置区块链状态'],
['export.md', '导出区块链状态'],
['sentry.md', '哨兵节点'],
['tool.md', '调试工具'],
Expand Down
21 changes: 9 additions & 12 deletions docs/software/export.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,30 @@

## Description

IRISnet can export blockchain state at any height and output json format string. Save the out json string to a json file and the json file can be used as genesis file of a new blockchain. This can be accomplished by command `iris export`
IRISnet can export blockchain state and output json format string. Save the out json string to a json file and the json file can be used as genesis file of a new blockchain. This can be accomplished by command `iris export`.
If you want to export the state of the historical block height, you need to [reset](reset.md) the blockchain state to the specified height.

## Usage
```
iris export <flags>
```
### Flags
## Flags

| Name,shorthand | type | Required | Default | Description |
| Name,shorthand | type | Required | Default | Description |
| ------------------- | ----- | -------- | -------- | -------------- |
| --for-zero-height | bool | false | false | Do some clean up work before exporting state. If you want use the exported state to start a new blockchain, please add this flag. Otherwise, just leave out it |
| --height | int | false | 0 | Specify the height, default value is 0 which means to export the latest state |
| --home | string | false | $HOME/.iris | Specify the directory which stores node config and blockchain data |
| --output-file | string | false | genesis.json | Target file to save exported state |

1. Export the latest blockchain state:
```
iris export
```
## Examples

2. Export blockchain state at certain height
1. Export the current blockchain state

```
iris export --height=10000
iris export --home=<path_to_your_home>
```

3. If you want to export the blockchain state at certain height and use the exported state as genesis state of another blockchain
2. If you want to export the the current blockchain state and use the exported state as genesis state of another blockchain
```
iris export --height=105000 --for-zero-height --home=<path_to_your_home>
iris export --for-zero-height --home=<path_to_your_home>
```
23 changes: 23 additions & 0 deletions docs/software/reset.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Reset Blockchain State

## Description

IRISnet can reset blockchain state at any height. This can be accomplished by command `iris reset`.

## Usage
```
iris reset <flags>
```
## Flags

| Name,shorthand | type | Required | Default | Description |
| ------------------- | ----- | -------- | -------- | -------------- |
| --height | int | false | 0 | Specify the height, default value is 0 which means to export the latest state |
| --home | string | false | $HOME/.iris | Specify the directory which stores node config and blockchain data |

## Examples

1. Reset the blockchain state to block 100:
```
iris reset --height 100 --home=<path_to_your_home>
```
16 changes: 6 additions & 10 deletions docs/zh/software/export.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

## 介绍

这里介绍一种能导出区块链状态,并以json格式返回给用户。如果把返回的json字符串保存到一个json文件里,那么这个json文件可以作为一个新区块链网络的创世块。导出区块链状态所用的命令为`iris export`
IRISnet支持导出区块链状态,并以json格式返回给用户。如果把返回的json字符串保存到一个json文件里,这个json文件可以作为一个新区块链网络的创世块。导出区块链状态所用的命令为`iris export`。
如果想导出历史高度的状态,需要先[重置](reset.md)app状态到指定的高度。

## 用法

Expand All @@ -15,21 +16,16 @@ iris export <flags>
| 名称,速记 | 类型 | 是否必填 | 默认值 | 介绍 |
| ------------------- | ----- | -------- | -------- | -------------- |
| --for-zero-height | bool | false | false | 导出数据之前做一些清理性的工作,如果不想以导出的数据启动一条新链,可以不加这个标志 |
| --height | int | false | 0 | 指定的高度,默认值为0表示导出当前高度状态 |
| --home | string | false | $HOME/.iris | 指定存储配置和区块链数据的目录 |
| --output-file | string | false | genesis.json | 存储导出状态的文件 |

## 示例

1. 导出最新的区块链状态:
1. 导出当前区块链状态
```
iris export
iris export --home=<path_to_your_home>
```
2. 导出高度10000的区块链状态
2. 如果想导出当前高度的区块链状态,并且以这个状态启动一条新链,可以尝试这个命令
```
iris export --height=10000
```
3. 如果想导出105000高度的区块链状态,并且以这个状态启动一条新链,可以尝试这个命令
```
iris export --height=105000 --for-zero-height --home=<path_to_your_home>
iris export --for-zero-height --home=<path_to_your_home>
```
23 changes: 23 additions & 0 deletions docs/zh/software/reset.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# 重置区块链状态

## 介绍

IRISnet支持重置区块链状态到任意高度,这里介绍重置区块链状态所用的命令为`iris reset`。

## 用法
```
iris reset <flags>
```
## 标志

| Name,shorthand | type | Required | Default | Description |
| ------------------- | ----- | -------- | -------- | -------------- |
| --height | int | false | 0 | Specify the height, default value is 0 which means to export the latest state |
| --home | string | false | $HOME/.iris | Specify the directory which stores node config and blockchain data |

## 示例

1. 重置区块链状态到区块100:
```
iris reset --height 100 --home=<path_to_your_home>
```
5 changes: 4 additions & 1 deletion server/constructors.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ type (

// AppExporter is a function that dumps all app state to
// JSON-serializable structure and returns the current validator set.
AppExporter func(*Context, log.Logger, dbm.DB, io.Writer, int64, bool) (json.RawMessage, []tmtypes.GenesisValidator, error)
AppExporter func(*Context, log.Logger, dbm.DB, io.Writer, bool) (json.RawMessage, []tmtypes.GenesisValidator, error)

// AppReset is a function that reset all app state to particular height
AppReset func(*Context, log.Logger, dbm.DB, io.Writer, int64) error
)

func openDB(rootDir string) (dbm.DB, error) {
Expand Down
9 changes: 2 additions & 7 deletions server/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
)

const (
flagHeight = "height"
flagForZeroHeight = "for-zero-height"
flagOutputFile = "output-file"
)
Expand Down Expand Up @@ -51,12 +50,9 @@ func ExportCmd(ctx *Context, cdc *codec.Codec, appExporter AppExporter) *cobra.C
if err != nil {
return err
}
height := viper.GetInt64(flagHeight)
if height < 0 {
return errors.Errorf("Height must greater than or equal to zero")
}

forZeroHeight := viper.GetBool(flagForZeroHeight)
appState, validators, err := appExporter(ctx, ctx.Logger, db, traceWriter, height, forZeroHeight)
appState, validators, err := appExporter(ctx, ctx.Logger, db, traceWriter, forZeroHeight)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you remove height from export option? It is possible to export state for zero height but not at current height.

Copy link
Contributor Author

@chengwenxi chengwenxi Jun 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you remove height from export option? It is possible to export state for zero height but not at current height.

If you want to export state for zero or snapshoot height, reset it first.

if err != nil {
return errors.Errorf("error exporting state: %v\n", err)
}
Expand Down Expand Up @@ -85,7 +81,6 @@ func ExportCmd(ctx *Context, cdc *codec.Codec, appExporter AppExporter) *cobra.C
return nil
},
}
cmd.Flags().Int64(flagHeight, 0, "Export state from a particular height (0 means latest height)")
cmd.Flags().Bool(flagForZeroHeight, false, "Export state to start at height zero (perform preproccessing)")
cmd.Flags().String(flagOutputFile, "genesis.json", "Target file to save exported state")
return cmd
Expand Down
58 changes: 58 additions & 0 deletions server/reset.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package server

import (
"fmt"

"github.com/irisnet/irishub/codec"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

const (
flagHeight = "height"
)

// ResetCmd reset app state to particular height
func ResetCmd(ctx *Context, cdc *codec.Codec, appReset AppReset) *cobra.Command {
cmd := &cobra.Command{
Use: "reset",
Short: "Reset app state to the specified height",
RunE: func(cmd *cobra.Command, args []string) error {
home := viper.GetString("home")
traceWriterFile := viper.GetString(flagTraceStore)
emptyState, err := isEmptyState(home)
if err != nil {
return err
}

if emptyState {
fmt.Println("WARNING: State is not initialized.")
return nil
}

db, err := openDB(home)
if err != nil {
return err
}
traceWriter, err := openTraceWriter(traceWriterFile)
if err != nil {
return err
}
height := viper.GetInt64(flagHeight)
if height < 0 {
return errors.Errorf("Height must greater than or equal to zero")
}
err = appReset(ctx, ctx.Logger, db, traceWriter, height)
if err != nil {
return errors.Errorf("Error reset state: %v\n", err)
}

fmt.Printf("Reset app state to height %d successfully\n", height)
return nil
},
}
cmd.Flags().Int64(flagHeight, 0, "Reset state from a particular height (0 or greater than latest height means latest height)")
cmd.MarkFlagRequired(flagHeight)
return cmd
}