Skip to content

Commit 416795f

Browse files
authored
feat: enable state sync (#265)
* feat: reenable state sync * docs: add state-sync docs * docs: typos * fix: register wasm snapshotter * docs: update state sync docs * fix: add proper seeds
1 parent 1178132 commit 416795f

File tree

4 files changed

+129
-8
lines changed

4 files changed

+129
-8
lines changed

app/app.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/CosmWasm/wasmd/x/wasm"
1616
wasmclient "github.com/CosmWasm/wasmd/x/wasm/client"
1717

18+
wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper"
1819
"github.com/cosmos/cosmos-sdk/baseapp"
1920
"github.com/cosmos/cosmos-sdk/client"
2021
"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
@@ -594,6 +595,17 @@ func New(
594595
app.SetBeginBlocker(app.BeginBlocker)
595596
app.SetEndBlocker(app.EndBlocker)
596597

598+
// must be before Loading version
599+
// requires the snapshot store to be created and registered as a BaseAppOption
600+
if manager := app.SnapshotManager(); manager != nil {
601+
err := manager.RegisterExtensions(
602+
wasmkeeper.NewWasmSnapshotter(app.CommitMultiStore(), &app.WasmKeeper),
603+
)
604+
if err != nil {
605+
panic(fmt.Errorf("failed to register snapshot extension: %s", err))
606+
}
607+
}
608+
597609
if loadLatest {
598610
if err := app.LoadLatestVersion(); err != nil {
599611
tmos.Exit(err.Error())

cmd/fetchd/cmd/root.go

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package cmd
33
import (
44
"bufio"
55
"errors"
6-
"fmt"
76
"io"
87
"math/big"
98
"os"
@@ -237,13 +236,6 @@ func (a appCreator) newApp(logger log.Logger, db dbm.DB, traceStore io.Writer, a
237236
panic(err)
238237
}
239238

240-
// Ensure node don't have snapshot feature enabled until cosmwasm properly support it.
241-
// Snapshots would be taken properly but impossible to restore
242-
// due to missing cosmwasm chunks.
243-
if cast.ToUint64(appOpts.Get(server.FlagStateSyncSnapshotInterval)) > 0 {
244-
panic(fmt.Errorf("state-sync snapshots feature is currently not supported, please set %s = 0 in command flags or ~/.fetchd/config/app.toml", server.FlagStateSyncSnapshotInterval))
245-
}
246-
247239
var wasmOpts []wasm.Option
248240
if cast.ToBool(appOpts.Get("telemetry.enabled")) {
249241
wasmOpts = append(wasmOpts, wasmkeeper.WithVMCacheMetrics(prometheus.DefaultRegisterer))

docs/docs/state-sync.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
2+
# State-sync
3+
4+
State sync is a feature which allows you to quickly bootstrap a new node by allowing it to pull a *state snapshot* taken by other nodes.
5+
6+
The state sync feature is only available from `fetchd v0.10.6` and later. Prior versions needed to either sync from scratch or restore a [chain snapshot](../snapshots), which both could take hours before having the node fully synced.
7+
8+
With state sync, it now takes only a few minutes before having an operational node.
9+
10+
## Configuring the new node
11+
12+
In order to instruct the node to sync itself using a state sync snapshot, it need some configuration in the `~/.fetchd/config/config.toml` file.
13+
Open this file in an editor and lookup for the `statesync` section. By default, it should looks like this:
14+
15+
```yaml
16+
#######################################################
17+
### State Sync Configuration Options ###
18+
#######################################################
19+
[statesync]
20+
# State sync rapidly bootstraps a new node by discovering, fetching, and restoring a state machine
21+
# snapshot from peers instead of fetching and replaying historical blocks. Requires some peers in
22+
# the network to take and serve state machine snapshots. State sync is not attempted if the node
23+
# has any local state (LastBlockHeight > 0). The node will have a truncated block history,
24+
# starting from the height of the snapshot.
25+
enable = false
26+
27+
# RPC servers (comma-separated) for light client verification of the synced state machine and
28+
# retrieval of state data for node bootstrapping. Also needs a trusted height and corresponding
29+
# header hash obtained from a trusted source, and a period during which validators can be trusted.
30+
#
31+
# For Cosmos SDK-based chains, trust_period should usually be about 2/3 of the unbonding time (~2
32+
# weeks) during which they can be financially punished (slashed) for misbehavior.
33+
rpc_servers = ""
34+
trust_height = 0
35+
trust_hash = ""
36+
trust_period = "168h0m0s"
37+
38+
# Time to spend discovering snapshots before initiating a restore.
39+
discovery_time = "15s"
40+
41+
# Temporary directory for state sync snapshot chunks, defaults to the OS tempdir (typically /tmp).
42+
# Will create a new, randomly named directory within, and remove it when done.
43+
temp_dir = ""
44+
45+
# The timeout duration before re-requesting a chunk, possibly from a different
46+
# peer (default: 1 minute).
47+
chunk_request_timeout = "10s"
48+
49+
# The number of concurrent chunk fetchers to run (default: 1).
50+
chunk_fetchers = "4"
51+
```
52+
53+
A few changes are needed:
54+
55+
- First, set `enable = true` to activate the state sync engine.
56+
- Then, **at least 2** rpc servers must be provided. A good place to find some is the [cosmos chain registry](https://github.com/cosmos/chain-registry/blob/master/fetchhub/chain.json#L62). Servers must be comma separated without space (ie: `rpc_servers = "https://rpc-fetchhub.fetch.ai:443,https://fetchapi.terminet.io"`). These servers will be used to verify the snapshots, so make sure you trust them enough for this.
57+
- And last, a *recent* `trust_height` and `trust_hash` are needed. Recent means it must be contained in the `trust_period` (168 hours, or ~1 week old by default). These can be obtained from a RPC server **you trust to provide you correct data** (and the 2nd RPC server from `rpc_servers` will be charged of confirming that the data are correct).
58+
59+
To retrieve the correct value for a fetch.ai RPC server, and the current network height, use:
60+
61+
```bash
62+
curl https://rpc-fetchhub.fetch.ai:443/block | jq -r '{"trusted_hash": .result.block_id.hash, "trusted_height": .result.block.header.height}'
63+
{
64+
"trusted_hash": "46868B76E6C814C35B2D109FCA177EBB70689AE3D46C65E4D75DE5363A86FF97",
65+
"trusted_height": "7041920"
66+
}
67+
```
68+
69+
and set these values in the config file.
70+
71+
Once this is set, make sure you have the correct genesis by downloading it from the RPC node:
72+
73+
```bash
74+
curl https://raw.githubusercontent.com/fetchai/genesis-fetchhub/fetchhub-4/fetchhub-4/data/genesis_migrated_5300200.json --output ~/.fetchd/config/genesis.json
75+
```
76+
77+
and start the node using the seeds from the chain-registry:
78+
79+
```bash
80+
fetchd start --p2p.seeds="17693da418c15c95d629994a320e2c4f51a8069b@connect-fetchhub.fetch.ai:36456,a575c681c2861fe945f77cb3aba0357da294f1f2@connect-fetchhub.fetch.ai:36457,d7cda986c9f59ab9e05058a803c3d0300d15d8da@connect-fetchhub.fetch.ai:36458"
81+
```
82+
83+
After the node initialized, it will start searching for available snapshots, and it should print log messages similar to:
84+
85+
```
86+
8:22AM INF Discovered new snapshot format=1 hash="� ݫ/��\r�F#C(pD�<��\x066��\x1f��\x1f<i�ݝ" height=2000 module=statesync
87+
8:22AM INF Discovered new snapshot format=1 hash="F�=\x05�Gh�{�|�����,�Q'�=]\x1a�$�b�ֿQ" height=1900 module=statesync
88+
```
89+
90+
The node will select the one with the `height` value the closest to the tip of the chain, and it will then start restoring the state, and finish syncing the few blocks remaining.
91+
92+
If it fails to verify any blocks or hash when restoring, it will attempt to restore the next available snapshot, and, if no more are available, will fallback in discovery mode until an usable snapshot is available.
93+
94+
## Configure an existing node to provide snapshots
95+
96+
In order to provide new nodes snapshots they can start from, existing nodes need to be configured to create these snapshots.
97+
This requires changes in the `~/.fetchd/config/app.toml` file, in the `state-sync` section.
98+
99+
```
100+
###############################################################################
101+
### State Sync Configuration ###
102+
###############################################################################
103+
104+
# State sync snapshots allow other nodes to rapidly join the network without replaying historical
105+
# blocks, instead downloading and applying a snapshot of the application state at a given height.
106+
[state-sync]
107+
108+
# snapshot-interval specifies the block interval at which local state sync snapshots are
109+
# taken (0 to disable). Must be a multiple of pruning-keep-every.
110+
snapshot-interval = 0
111+
112+
# snapshot-keep-recent specifies the number of recent snapshots to keep and serve (0 to keep all).
113+
snapshot-keep-recent = 2
114+
```
115+
116+
Here `snapshot-interval` must be set to a number of blocks between each snapshot creation and it must be a multiple of your node prunning settings (default is 100, so valid values are 100, 1000, 700...). The number of snapshots to keep can be set with `snapshot-keep-recent`.

docs/mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ nav:
1919
- Active Networks: 'live-networks.md'
2020
- Mainnet Archive: 'archived-networks.md'
2121
- Snapshots: 'snapshots.md'
22+
- State Sync: 'state-sync.md'
2223
- Commandline Client:
2324
- Introduction: 'cli-introduction.md'
2425
- Keys: 'cli-keys.md'

0 commit comments

Comments
 (0)