mirror of
https://github.com/tendermint/tendermint.git
synced 2026-08-22 15:16:24 +00:00
Merge remote-tracking branch 'origin/master' into jasmina/4457_block_sync_verification
This commit is contained in:
@@ -20,7 +20,7 @@ jobs:
|
||||
goos: ["linux"]
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/setup-go@v2
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: "1.17"
|
||||
- uses: actions/checkout@v3
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
needs: build
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/setup-go@v2
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: "1.17"
|
||||
- uses: actions/checkout@v3
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
needs: build
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/setup-go@v2
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: "1.17"
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/setup-go@v2
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.17'
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/setup-go@v2
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.17'
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/setup-go@v2
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.17'
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/setup-go@v2
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.17'
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- uses: actions/setup-go@v2
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.17'
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
fuzz-nightly-test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/setup-go@v2
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.17'
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
|
||||
- name: Install go-fuzz
|
||||
working-directory: test/fuzz
|
||||
run: go get -u github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-build
|
||||
run: go install github.com/dvyukov/go-fuzz/go-fuzz@latest github.com/dvyukov/go-fuzz/go-fuzz-build@latest
|
||||
|
||||
- name: Fuzz mempool
|
||||
working-directory: test/fuzz
|
||||
@@ -39,14 +39,14 @@ jobs:
|
||||
continue-on-error: true
|
||||
|
||||
- name: Archive crashers
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: crashers
|
||||
path: test/fuzz/**/crashers
|
||||
retention-days: 3
|
||||
|
||||
- name: Archive suppressions
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: suppressions
|
||||
path: test/fuzz/**/suppressions
|
||||
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
run: docker exec -i jepsen-control bash -c 'source /root/.bashrc; cd /jepsen/tendermint; lein run test --nemesis ${{ github.event.inputs.nemesis }} --workload ${{ github.event.inputs.workload }} --concurrency ${{ github.event.inputs.concurrency }} --tendermint-url ${{ github.event.inputs.tendermintUrl }} --merkleeyes-url ${{ github.event.inputs.merkleeyesUrl }} --time-limit ${{ github.event.inputs.timeLimit }} ${{ github.event.inputs.dupOrSuperByzValidators }}'
|
||||
|
||||
- name: Archive results
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: results
|
||||
path: tendermint/store/latest
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
timeout-minutes: 8
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v2
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '^1.17'
|
||||
- uses: technote-space/get-diff-action@v6.0.1
|
||||
|
||||
@@ -12,7 +12,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: gaurav-nelson/github-action-markdown-link-check@1.0.14
|
||||
- uses: technote-space/get-diff-action@v6.0.1
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.md
|
||||
- uses: creachadair/github-action-markdown-link-check@master
|
||||
with:
|
||||
check-modified-files-only: 'yes'
|
||||
config-file: '.md-link-check.json'
|
||||
if: env.GIT_DIFF
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-go@v2
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.17'
|
||||
|
||||
@@ -27,11 +27,13 @@ jobs:
|
||||
version: latest
|
||||
args: build --skip-validate # skip validate skips initial sanity checks in order to be able to fully run
|
||||
|
||||
- run: echo https://github.com/tendermint/tendermint/blob/${GITHUB_REF#refs/tags/}/CHANGELOG.md#${GITHUB_REF#refs/tags/} > ../release_notes.md
|
||||
|
||||
- name: Release
|
||||
uses: goreleaser/goreleaser-action@v2
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
version: latest
|
||||
args: release --rm-dist
|
||||
args: release --rm-dist --release-notes=../release_notes.md
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -7,7 +7,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v4
|
||||
- uses: actions/stale@v5
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-pr-message: "This pull request has been automatically marked as stale because it has not had
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
matrix:
|
||||
part: ["00", "01", "02", "03", "04", "05"]
|
||||
steps:
|
||||
- uses: actions/setup-go@v2
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: "1.17"
|
||||
- uses: actions/checkout@v3
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
run: |
|
||||
make test-group-${{ matrix.part }} NUM_SPLIT=6
|
||||
if: env.GIT_DIFF
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "${{ github.sha }}-${{ matrix.part }}-coverage"
|
||||
path: ./build/${{ matrix.part }}.profile.out
|
||||
@@ -50,26 +50,26 @@ jobs:
|
||||
go.mod
|
||||
go.sum
|
||||
Makefile
|
||||
- uses: actions/download-artifact@v2
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: "${{ github.sha }}-00-coverage"
|
||||
if: env.GIT_DIFF
|
||||
- uses: actions/download-artifact@v2
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: "${{ github.sha }}-01-coverage"
|
||||
if: env.GIT_DIFF
|
||||
- uses: actions/download-artifact@v2
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: "${{ github.sha }}-02-coverage"
|
||||
if: env.GIT_DIFF
|
||||
- uses: actions/download-artifact@v2
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: "${{ github.sha }}-03-coverage"
|
||||
if: env.GIT_DIFF
|
||||
- run: |
|
||||
cat ./*profile.out | grep -v "mode: set" >> coverage.txt
|
||||
if: env.GIT_DIFF
|
||||
- uses: codecov/codecov-action@v2.1.0
|
||||
- uses: codecov/codecov-action@v3.0.0
|
||||
with:
|
||||
file: ./coverage.txt
|
||||
if: env.GIT_DIFF
|
||||
|
||||
@@ -2,6 +2,22 @@
|
||||
|
||||
Friendly reminder: We have a [bug bounty program](https://hackerone.com/cosmos).
|
||||
|
||||
## v0.35.3
|
||||
|
||||
April 8, 2022
|
||||
|
||||
### FEATURES
|
||||
|
||||
- [cli] [\#8081](https://github.com/tendermint/tendermint/pull/8081) add a safer-to-use `reset-state` command. (@marbar3778)
|
||||
|
||||
### IMPROVEMENTS
|
||||
|
||||
- [consensus] [\#8138](https://github.com/tendermint/tendermint/pull/8138) change lock handling in reactor and handleMsg for RoundState. (@williambanfield)
|
||||
|
||||
### BUG FIXES
|
||||
|
||||
- [cli] [\#8276](https://github.com/tendermint/tendermint/pull/8276) scmigrate: ensure target key is correctly renamed. (@creachadair)
|
||||
|
||||
## v0.35.2
|
||||
|
||||
February 28, 2022
|
||||
@@ -230,6 +246,12 @@ Special thanks to external contributors on this release: @JayT106,
|
||||
- [cmd/tendermint/commands] [\#6623](https://github.com/tendermint/tendermint/pull/6623) replace `$HOME/.some/test/dir` with `t.TempDir` (@tanyabouman)
|
||||
- [statesync] \6807 Implement P2P state provider as an alternative to RPC (@cmwaters)
|
||||
|
||||
## v0.34.19
|
||||
|
||||
### BUG FIXES
|
||||
|
||||
- [cli] [\#8270](https://github.com/tendermint/tendermint/issues/8270) fix reset commands (@alexanderbez).
|
||||
|
||||
## v0.34.18
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
@@ -19,7 +19,7 @@ Special thanks to external contributors on this release:
|
||||
- [rpc] \#7713 Remove unused options for websocket clients. (@creachadair)
|
||||
- [config] \#7930 Add new event subscription options and defaults. (@creachadair)
|
||||
- [rpc] \#7982 Add new Events interface and deprecate Subscribe. (@creachadair)
|
||||
- [cli] \#8081 make the reset command safe to use. (@marbar3778)
|
||||
- [cli] \#8081 make the reset command safe to use by intoducing `reset-state` command. Fixed by \#8259. (@marbar3778, @cmwaters)
|
||||
- [config] \#8222 default indexer configuration to null. (@creachadair)
|
||||
|
||||
- Apps
|
||||
@@ -62,6 +62,7 @@ Special thanks to external contributors on this release:
|
||||
- [consensus] \#7415 Update proposal validation logic to Prevote nil if a proposal does not meet the conditions for Timelyness per the proposer-based timestamp specification. (@anca)
|
||||
- [consensus] \#7382 Update block validation to no longer require the block timestamp to be the median of the timestamps of the previous commit. (@anca)
|
||||
- [consensus] \#7711 Use the proposer timestamp for the first height instead of the genesis time. Chains will still start consensus at the genesis time. (@anca)
|
||||
- [cli] \#8281 Add a tool to update old config files to the latest version. (@creachadair)
|
||||
|
||||
### IMPROVEMENTS
|
||||
|
||||
@@ -81,3 +82,5 @@ Special thanks to external contributors on this release:
|
||||
- [light] \#7640 Light Client: fix absence proof verification (@ashcherbakov)
|
||||
- [light] \#7641 Light Client: fix querying against the latest height (@ashcherbakov)
|
||||
- [cli] [#7837](https://github.com/tendermint/tendermint/pull/7837) fix app hash in state rollback. (@yihuang)
|
||||
- [cli] \#8276 scmigrate: ensure target key is correctly renamed. (@creachadair)
|
||||
- [cli] \#8294 keymigrate: ensure block hash keys are correctly translated. (@creachadair)
|
||||
|
||||
@@ -178,7 +178,7 @@ go.sum: go.mod
|
||||
|
||||
draw_deps:
|
||||
@# requires brew install graphviz or apt-get install graphviz
|
||||
go get github.com/RobotsAndPencils/goviz
|
||||
go install github.com/RobotsAndPencils/goviz@latest
|
||||
@goviz -i github.com/tendermint/tendermint/cmd/tendermint -d 3 | dot -Tpng -o dependency-graph.png
|
||||
.PHONY: draw_deps
|
||||
|
||||
|
||||
+41
-4
@@ -28,10 +28,28 @@ applications remains correct.
|
||||
|
||||
### Config Changes
|
||||
|
||||
The default configuration for a newly-created node now disables indexing for
|
||||
ABCI event metadata. Existing node configurations that already have indexing
|
||||
turned on are not affected. Operators who wish to enable indexing for a new
|
||||
node, however, must now edit the `config.toml` explicitly.
|
||||
- We have added a new, experimental tool to help operators migrate
|
||||
configuration files created by previous versions of Tendermint.
|
||||
To try this tool, run:
|
||||
|
||||
```shell
|
||||
# Install the tool.
|
||||
go install github.com/tendermint/tendermint/scripts/confix@latest
|
||||
|
||||
# Run the tool with the old configuration file as input.
|
||||
# Replace the -config argument with your path.
|
||||
confix -config ~/.tendermint/config/config.toml -out updated.toml
|
||||
```
|
||||
|
||||
This tool should be able to update configurations from v0.34 and v0.35. We
|
||||
plan to extend it to handle older configuration files in the future. For now,
|
||||
it will report an error (without making any changes) if it does not recognize
|
||||
the version that created the file.
|
||||
|
||||
- The default configuration for a newly-created node now disables indexing for
|
||||
ABCI event metadata. Existing node configurations that already have indexing
|
||||
turned on are not affected. Operators who wish to enable indexing for a new
|
||||
node, however, must now edit the `config.toml` explicitly.
|
||||
|
||||
### RPC Changes
|
||||
|
||||
@@ -108,6 +126,25 @@ lays out the reasoning for the changes as well as [RFC
|
||||
009](https://tinyurl.com/rfc009) for a discussion of the complexities of
|
||||
upgrading consensus parameters.
|
||||
|
||||
### CLI Changes
|
||||
|
||||
The functionality around resetting a node has been extended to make it safer. The
|
||||
`unsafe-reset-all` command has been replaced by a `reset` command with four
|
||||
subcommands: `blockchain`, `peers`, `unsafe-signer` and `unsafe-all`.
|
||||
|
||||
- `tendermint reset blockchain`: Clears a node of all blocks, consensus state, evidence,
|
||||
and indexed transactions. NOTE: This command does not reset application state.
|
||||
If you need to rollback the last application state (to recover from application
|
||||
nondeterminism), see instead the `tendermint rollback` command.
|
||||
- `tendermint reset peers`: Clears the peer store, which persists information on peers used
|
||||
by the networking layer. This can be used to get rid of stale addresses or to switch
|
||||
to a predefined set of static peers.
|
||||
- `tendermint reset unsafe-signer`: Resets the watermark level of the PrivVal File signer
|
||||
allowing it to sign votes from the genesis height. This should only be used in testing as
|
||||
it can lead to the node double signing.
|
||||
- `tendermint reset unsafe-all`: A summation of the other three commands. This will delete
|
||||
the entire `data` directory which may include application data as well.
|
||||
|
||||
## v0.35
|
||||
|
||||
### ABCI Changes
|
||||
|
||||
@@ -175,7 +175,7 @@ func (app *Application) FinalizeBlock(req types.RequestFinalizeBlock) types.Resp
|
||||
|
||||
// Punish validators who committed equivocation.
|
||||
for _, ev := range req.ByzantineValidators {
|
||||
if ev.Type == types.EvidenceType_DUPLICATE_VOTE {
|
||||
if ev.Type == types.MisbehaviorType_DUPLICATE_VOTE {
|
||||
addr := string(ev.Validator.Address)
|
||||
if pubKey, ok := app.valAddrToPubKeyMap[addr]; ok {
|
||||
app.updateValidator(types.ValidatorUpdate{
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
"github.com/tendermint/tendermint/abci/example/code"
|
||||
abciserver "github.com/tendermint/tendermint/abci/server"
|
||||
"github.com/tendermint/tendermint/abci/types"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -104,10 +103,7 @@ func TestPersistentKVStoreInfo(t *testing.T) {
|
||||
// make and apply block
|
||||
height = int64(1)
|
||||
hash := []byte("foo")
|
||||
header := tmproto.Header{
|
||||
Height: height,
|
||||
}
|
||||
kvstore.FinalizeBlock(types.RequestFinalizeBlock{Hash: hash, Header: header})
|
||||
kvstore.FinalizeBlock(types.RequestFinalizeBlock{Hash: hash, Height: height})
|
||||
kvstore.Commit()
|
||||
|
||||
resInfo = kvstore.Info(types.RequestInfo{})
|
||||
@@ -189,13 +185,9 @@ func makeApplyBlock(
|
||||
// make and apply block
|
||||
height := int64(heightInt)
|
||||
hash := []byte("foo")
|
||||
header := tmproto.Header{
|
||||
Height: height,
|
||||
}
|
||||
|
||||
resFinalizeBlock := kvstore.FinalizeBlock(types.RequestFinalizeBlock{
|
||||
Hash: hash,
|
||||
Header: header,
|
||||
Height: height,
|
||||
Txs: txs,
|
||||
})
|
||||
|
||||
|
||||
+968
-595
File diff suppressed because it is too large
Load Diff
@@ -180,7 +180,7 @@ for applications built w/ Cosmos SDK).
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancel := signal.NotifyContext(cmd.Context(), syscall.SIGTERM)
|
||||
ctx, cancel := signal.NotifyContext(cmd.Context(), os.Interrupt, syscall.SIGTERM)
|
||||
defer cancel()
|
||||
|
||||
go func() {
|
||||
|
||||
+78
-64
@@ -13,81 +13,92 @@ import (
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
// MakeResetAllCommand constructs a command that removes the database of
|
||||
// MakeResetCommand constructs a command that removes the database of
|
||||
// the specified Tendermint core instance.
|
||||
func MakeResetAllCommand(conf *config.Config, logger log.Logger) *cobra.Command {
|
||||
func MakeResetCommand(conf *config.Config, logger log.Logger) *cobra.Command {
|
||||
var keyType string
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "unsafe-reset-all",
|
||||
Short: "(unsafe) Remove all the data and WAL, reset this node's validator to genesis state",
|
||||
resetCmd := &cobra.Command{
|
||||
Use: "reset",
|
||||
Short: "Set of commands to conveniently reset tendermint related data",
|
||||
}
|
||||
|
||||
resetBlocksCmd := &cobra.Command{
|
||||
Use: "blockchain",
|
||||
Short: "Removes all blocks, state, transactions and evidence stored by the tendermint node",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return resetAll(conf.DBDir(), conf.PrivValidator.KeyFile(),
|
||||
return ResetState(conf.DBDir(), logger)
|
||||
},
|
||||
}
|
||||
|
||||
resetPeersCmd := &cobra.Command{
|
||||
Use: "peers",
|
||||
Short: "Removes all peer addresses",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return ResetPeerStore(conf.DBDir())
|
||||
},
|
||||
}
|
||||
|
||||
resetSignerCmd := &cobra.Command{
|
||||
Use: "unsafe-signer",
|
||||
Short: "esets private validator signer state",
|
||||
Long: `Resets private validator signer state.
|
||||
Only use in testing. This can cause the node to double sign`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return ResetFilePV(conf.PrivValidator.KeyFile(), conf.PrivValidator.StateFile(), logger, keyType)
|
||||
},
|
||||
}
|
||||
|
||||
resetAllCmd := &cobra.Command{
|
||||
Use: "unsafe-all",
|
||||
Short: "Removes all tendermint data including signing state",
|
||||
Long: `Removes all tendermint data including signing state.
|
||||
Only use in testing. This can cause the node to double sign`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return ResetAll(conf.DBDir(), conf.PrivValidator.KeyFile(),
|
||||
conf.PrivValidator.StateFile(), logger, keyType)
|
||||
},
|
||||
}
|
||||
cmd.Flags().StringVar(&keyType, "key", types.ABCIPubKeyTypeEd25519,
|
||||
"Key type to generate privval file with. Options: ed25519, secp256k1")
|
||||
|
||||
return cmd
|
||||
resetSignerCmd.Flags().StringVar(&keyType, "key", types.ABCIPubKeyTypeEd25519,
|
||||
"Signer key type. Options: ed25519, secp256k1")
|
||||
|
||||
resetAllCmd.Flags().StringVar(&keyType, "key", types.ABCIPubKeyTypeEd25519,
|
||||
"Signer key type. Options: ed25519, secp256k1")
|
||||
|
||||
resetCmd.AddCommand(resetBlocksCmd)
|
||||
resetCmd.AddCommand(resetPeersCmd)
|
||||
resetCmd.AddCommand(resetSignerCmd)
|
||||
resetCmd.AddCommand(resetAllCmd)
|
||||
|
||||
return resetCmd
|
||||
}
|
||||
|
||||
// MakeResetStateCommand constructs a command that removes the database of
|
||||
// the specified Tendermint core instance.
|
||||
func MakeResetStateCommand(conf *config.Config, logger log.Logger) *cobra.Command {
|
||||
var keyType string
|
||||
|
||||
return &cobra.Command{
|
||||
Use: "reset-state",
|
||||
Short: "Remove all the data and WAL",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return resetState(conf.DBDir(), logger, keyType)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func MakeResetPrivateValidatorCommand(conf *config.Config, logger log.Logger) *cobra.Command {
|
||||
var keyType string
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "unsafe-reset-priv-validator",
|
||||
Short: "(unsafe) Reset this node's validator to genesis state",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return resetFilePV(conf.PrivValidator.KeyFile(), conf.PrivValidator.StateFile(), logger, keyType)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVar(&keyType, "key", types.ABCIPubKeyTypeEd25519,
|
||||
"Key type to generate privval file with. Options: ed25519, secp256k1")
|
||||
return cmd
|
||||
|
||||
}
|
||||
|
||||
// XXX: this is totally unsafe.
|
||||
// it's only suitable for testnets.
|
||||
|
||||
// XXX: this is totally unsafe.
|
||||
// it's only suitable for testnets.
|
||||
|
||||
// resetAll removes address book files plus all data, and resets the privValdiator data.
|
||||
func resetAll(dbDir, privValKeyFile, privValStateFile string, logger log.Logger, keyType string) error {
|
||||
// ResetAll removes address book files plus all data, and resets the privValdiator data.
|
||||
// Exported for extenal CLI usage
|
||||
// XXX: this is unsafe and should only suitable for testnets.
|
||||
func ResetAll(dbDir, privValKeyFile, privValStateFile string, logger log.Logger, keyType string) error {
|
||||
if err := os.RemoveAll(dbDir); err == nil {
|
||||
logger.Info("Removed all blockchain history", "dir", dbDir)
|
||||
} else {
|
||||
logger.Error("error removing all blockchain history", "dir", dbDir, "err", err)
|
||||
}
|
||||
|
||||
return resetFilePV(privValKeyFile, privValStateFile, logger, keyType)
|
||||
if err := tmos.EnsureDir(dbDir, 0700); err != nil {
|
||||
logger.Error("unable to recreate dbDir", "err", err)
|
||||
}
|
||||
|
||||
// recreate the dbDir since the privVal state needs to live there
|
||||
return ResetFilePV(privValKeyFile, privValStateFile, logger, keyType)
|
||||
}
|
||||
|
||||
// resetState removes address book files plus all databases.
|
||||
func resetState(dbDir string, logger log.Logger, keyType string) error {
|
||||
// ResetState removes all blocks, tendermint state, indexed transactions and evidence.
|
||||
func ResetState(dbDir string, logger log.Logger) error {
|
||||
blockdb := filepath.Join(dbDir, "blockstore.db")
|
||||
state := filepath.Join(dbDir, "state.db")
|
||||
wal := filepath.Join(dbDir, "cs.wal")
|
||||
evidence := filepath.Join(dbDir, "evidence.db")
|
||||
txIndex := filepath.Join(dbDir, "tx_index.db")
|
||||
peerstore := filepath.Join(dbDir, "peerstore.db")
|
||||
|
||||
if tmos.FileExists(blockdb) {
|
||||
if err := os.RemoveAll(blockdb); err == nil {
|
||||
@@ -129,20 +140,13 @@ func resetState(dbDir string, logger log.Logger, keyType string) error {
|
||||
}
|
||||
}
|
||||
|
||||
if tmos.FileExists(peerstore) {
|
||||
if err := os.RemoveAll(peerstore); err == nil {
|
||||
logger.Info("Removed peerstore.db", "dir", peerstore)
|
||||
} else {
|
||||
logger.Error("error removing peerstore.db", "dir", peerstore, "err", err)
|
||||
}
|
||||
}
|
||||
if err := tmos.EnsureDir(dbDir, 0700); err != nil {
|
||||
logger.Error("unable to recreate dbDir", "err", err)
|
||||
}
|
||||
return nil
|
||||
return tmos.EnsureDir(dbDir, 0700)
|
||||
}
|
||||
|
||||
func resetFilePV(privValKeyFile, privValStateFile string, logger log.Logger, keyType string) error {
|
||||
// ResetFilePV loads the file private validator and resets the watermark to 0. If used on an existing network,
|
||||
// this can cause the node to double sign.
|
||||
// XXX: this is unsafe and should only suitable for testnets.
|
||||
func ResetFilePV(privValKeyFile, privValStateFile string, logger log.Logger, keyType string) error {
|
||||
if _, err := os.Stat(privValKeyFile); err == nil {
|
||||
pv, err := privval.LoadFilePVEmptyState(privValKeyFile, privValStateFile)
|
||||
if err != nil {
|
||||
@@ -166,3 +170,13 @@ func resetFilePV(privValKeyFile, privValStateFile string, logger log.Logger, key
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResetPeerStore removes the peer store containing all information used by the tendermint networking layer
|
||||
// In the case of a reset, new peers will need to be set either via the config or through the discovery mechanism
|
||||
func ResetPeerStore(dbDir string) error {
|
||||
peerstore := filepath.Join(dbDir, "peerstore.db")
|
||||
if tmos.FileExists(peerstore) {
|
||||
return os.RemoveAll(peerstore)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
cfg "github.com/tendermint/tendermint/config"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
"github.com/tendermint/tendermint/privval"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
func Test_ResetAll(t *testing.T) {
|
||||
config := cfg.TestConfig()
|
||||
dir := t.TempDir()
|
||||
config.SetRoot(dir)
|
||||
logger := log.NewNopLogger()
|
||||
cfg.EnsureRoot(dir)
|
||||
require.NoError(t, initFilesWithConfig(context.Background(), config, logger, types.ABCIPubKeyTypeEd25519))
|
||||
pv, err := privval.LoadFilePV(config.PrivValidator.KeyFile(), config.PrivValidator.StateFile())
|
||||
require.NoError(t, err)
|
||||
pv.LastSignState.Height = 10
|
||||
require.NoError(t, pv.Save())
|
||||
require.NoError(t, ResetAll(config.DBDir(), config.PrivValidator.KeyFile(),
|
||||
config.PrivValidator.StateFile(), logger, types.ABCIPubKeyTypeEd25519))
|
||||
require.DirExists(t, config.DBDir())
|
||||
require.NoFileExists(t, filepath.Join(config.DBDir(), "block.db"))
|
||||
require.NoFileExists(t, filepath.Join(config.DBDir(), "state.db"))
|
||||
require.NoFileExists(t, filepath.Join(config.DBDir(), "evidence.db"))
|
||||
require.NoFileExists(t, filepath.Join(config.DBDir(), "tx_index.db"))
|
||||
require.FileExists(t, config.PrivValidator.StateFile())
|
||||
pv, err = privval.LoadFilePV(config.PrivValidator.KeyFile(), config.PrivValidator.StateFile())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(0), pv.LastSignState.Height)
|
||||
}
|
||||
|
||||
func Test_ResetState(t *testing.T) {
|
||||
config := cfg.TestConfig()
|
||||
dir := t.TempDir()
|
||||
config.SetRoot(dir)
|
||||
logger := log.NewNopLogger()
|
||||
cfg.EnsureRoot(dir)
|
||||
require.NoError(t, initFilesWithConfig(context.Background(), config, logger, types.ABCIPubKeyTypeEd25519))
|
||||
pv, err := privval.LoadFilePV(config.PrivValidator.KeyFile(), config.PrivValidator.StateFile())
|
||||
require.NoError(t, err)
|
||||
pv.LastSignState.Height = 10
|
||||
require.NoError(t, pv.Save())
|
||||
require.NoError(t, ResetState(config.DBDir(), logger))
|
||||
require.DirExists(t, config.DBDir())
|
||||
require.NoFileExists(t, filepath.Join(config.DBDir(), "block.db"))
|
||||
require.NoFileExists(t, filepath.Join(config.DBDir(), "state.db"))
|
||||
require.NoFileExists(t, filepath.Join(config.DBDir(), "evidence.db"))
|
||||
require.NoFileExists(t, filepath.Join(config.DBDir(), "tx_index.db"))
|
||||
require.FileExists(t, config.PrivValidator.StateFile())
|
||||
pv, err = privval.LoadFilePV(config.PrivValidator.KeyFile(), config.PrivValidator.StateFile())
|
||||
require.NoError(t, err)
|
||||
// private validator state should still be in tact.
|
||||
require.Equal(t, int64(10), pv.LastSignState.Height)
|
||||
}
|
||||
@@ -105,7 +105,7 @@ func NewRunNodeCmd(nodeProvider cfg.ServiceProvider, conf *cfg.Config, logger lo
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancel := signal.NotifyContext(cmd.Context(), syscall.SIGTERM)
|
||||
ctx, cancel := signal.NotifyContext(cmd.Context(), os.Interrupt, syscall.SIGTERM)
|
||||
defer cancel()
|
||||
|
||||
n, err := nodeProvider(ctx, conf, logger)
|
||||
|
||||
@@ -33,9 +33,7 @@ func main() {
|
||||
commands.MakeLightCommand(conf, logger),
|
||||
commands.MakeReplayCommand(conf, logger),
|
||||
commands.MakeReplayConsoleCommand(conf, logger),
|
||||
commands.MakeResetAllCommand(conf, logger),
|
||||
commands.MakeResetStateCommand(conf, logger),
|
||||
commands.MakeResetPrivateValidatorCommand(conf, logger),
|
||||
commands.MakeResetCommand(conf, logger),
|
||||
commands.MakeShowValidatorCommand(conf, logger),
|
||||
commands.MakeTestnetFilesCommand(conf, logger),
|
||||
commands.MakeShowNodeIDCommand(conf),
|
||||
|
||||
@@ -182,7 +182,7 @@ node example/counter.js
|
||||
In another window, reset and start `tendermint`:
|
||||
|
||||
```sh
|
||||
tendermint unsafe-reset-all
|
||||
tendermint reset unsafe-all
|
||||
tendermint start
|
||||
```
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ There are two ways to generate certificates, [openssl](https://www.openssl.org/)
|
||||
- Install `Certstrap`:
|
||||
|
||||
```sh
|
||||
go get github.com/square/certstrap@v1.2.0
|
||||
go install github.com/square/certstrap@v1.2.0
|
||||
```
|
||||
|
||||
- Create certificate authority for self signing.
|
||||
|
||||
@@ -52,5 +52,6 @@ sections.
|
||||
- [RFC-012: Event Indexing Revisited](./rfc-012-custom-indexing.md)
|
||||
- [RFC-013: ABCI++](./rfc-013-abci++.md)
|
||||
- [RFC-014: Semantic Versioning](./rfc-014-semantic-versioning.md)
|
||||
- [RFC-015: ABCI++ Tx Mutation](./rfc-015-abci++-tx-mutation.md)
|
||||
|
||||
<!-- - [RFC-NNN: Title](./rfc-NNN-title.md) -->
|
||||
|
||||
@@ -164,7 +164,7 @@ page](https://app.logz.io/#/dashboard/data-sources/Filebeat), then:
|
||||
yum install systemd-devel || echo "This will only work on RHEL-based systems."
|
||||
apt-get install libsystemd-dev || echo "This will only work on Debian-based systems."
|
||||
|
||||
go get github.com/mheese/journalbeat
|
||||
go install github.com/mheese/journalbeat@latest
|
||||
ansible-playbook -i inventory/digital_ocean.py -l sentrynet logzio.yml -e LOGZIO_TOKEN=ABCDEFGHIJKLMNOPQRSTUVWXYZ012345
|
||||
```
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ require (
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
|
||||
github.com/lib/pq v1.10.4
|
||||
github.com/lib/pq v1.10.5
|
||||
github.com/libp2p/go-buffer-pool v0.0.2
|
||||
github.com/mroth/weightedrand v0.4.1
|
||||
github.com/oasisprotocol/curve25519-voi v0.0.0-20210609091139-0a56a4bca00b
|
||||
@@ -39,6 +39,7 @@ require (
|
||||
|
||||
require (
|
||||
github.com/creachadair/atomicfile v0.2.4
|
||||
github.com/creachadair/taskgroup v0.3.2
|
||||
github.com/golangci/golangci-lint v1.45.2
|
||||
github.com/google/go-cmp v0.5.7
|
||||
github.com/vektra/mockery/v2 v2.10.4
|
||||
@@ -72,6 +73,7 @@ require (
|
||||
github.com/charithe/durationcheck v0.0.9 // indirect
|
||||
github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af // indirect
|
||||
github.com/containerd/continuity v0.2.1 // indirect
|
||||
github.com/creachadair/tomledit v0.0.16
|
||||
github.com/daixiang0/gci v0.3.3 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/denis-tingaikin/go-header v0.4.3 // indirect
|
||||
|
||||
@@ -223,6 +223,10 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creachadair/atomicfile v0.2.4 h1:GRjpQLmz/78I4+nBQpGMFrRa9yrL157AUTrA6hnF0YU=
|
||||
github.com/creachadair/atomicfile v0.2.4/go.mod h1:BRq8Une6ckFneYXZQ+kO7p1ZZP3I2fzVzf28JxrIkBc=
|
||||
github.com/creachadair/taskgroup v0.3.2 h1:zlfutDS+5XG40AOxcHDSThxKzns8Tnr9jnr6VqkYlkM=
|
||||
github.com/creachadair/taskgroup v0.3.2/go.mod h1:wieWwecHVzsidg2CsUnFinW1faVN4+kq+TDlRJQ0Wbk=
|
||||
github.com/creachadair/tomledit v0.0.16 h1:PDNxgDjeeiNk1cyFfliIVQmagh1jPbDMabOw9yfSKLk=
|
||||
github.com/creachadair/tomledit v0.0.16/go.mod h1:gvtfnSZLa+YNQD28vaPq0Nk12bRxEhmUdBzAWn+EGF4=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
|
||||
@@ -656,8 +660,9 @@ github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJ
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
|
||||
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.5 h1:J+gdV2cUmX7ZqL2B0lFcW0m+egaHC2V3lpO8nWxyYiQ=
|
||||
github.com/lib/pq v1.10.5/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs=
|
||||
github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM=
|
||||
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
|
||||
@@ -407,6 +407,13 @@ func (r *Reactor) SwitchToBlockSync(ctx context.Context, state sm.State) error {
|
||||
go r.requestRoutine(ctx, bsCh)
|
||||
go r.poolRoutine(ctx, true, bsCh)
|
||||
|
||||
if err := r.PublishStatus(ctx, types.EventDataBlockSyncStatus{
|
||||
Complete: false,
|
||||
Height: state.LastBlockHeight,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -211,7 +211,6 @@ func (r *Reactor) OnStart(ctx context.Context) error {
|
||||
go r.peerStatsRoutine(ctx, peerUpdates)
|
||||
|
||||
r.subscribeToBroadcastEvents(chBundle.state)
|
||||
go r.updateRoundStateRoutine()
|
||||
|
||||
if !r.WaitSync() {
|
||||
if err := r.state.Start(ctx); err != nil {
|
||||
@@ -219,6 +218,8 @@ func (r *Reactor) OnStart(ctx context.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
go r.updateRoundStateRoutine(ctx)
|
||||
|
||||
go r.processStateCh(ctx, chBundle)
|
||||
go r.processDataCh(ctx, chBundle)
|
||||
go r.processVoteCh(ctx, chBundle)
|
||||
@@ -260,6 +261,15 @@ func (r *Reactor) SwitchToConsensus(ctx context.Context, state sm.State, skipWAL
|
||||
// NOTE: The line below causes broadcastNewRoundStepRoutine() to broadcast a
|
||||
// NewRoundStepMessage.
|
||||
r.state.updateToState(ctx, state)
|
||||
if err := r.state.Start(ctx); err != nil {
|
||||
panic(fmt.Sprintf(`failed to start consensus state: %v
|
||||
|
||||
conS:
|
||||
%+v
|
||||
|
||||
conR:
|
||||
%+v`, err, r.state, r))
|
||||
}
|
||||
|
||||
r.mtx.Lock()
|
||||
r.waitSync = false
|
||||
@@ -273,16 +283,6 @@ func (r *Reactor) SwitchToConsensus(ctx context.Context, state sm.State, skipWAL
|
||||
r.state.doWALCatchup = false
|
||||
}
|
||||
|
||||
if err := r.state.Start(ctx); err != nil {
|
||||
panic(fmt.Sprintf(`failed to start consensus state: %v
|
||||
|
||||
conS:
|
||||
%+v
|
||||
|
||||
conR:
|
||||
%+v`, err, r.state, r))
|
||||
}
|
||||
|
||||
d := types.EventDataBlockSyncStatus{Complete: true, Height: state.LastBlockHeight}
|
||||
if err := r.eventBus.PublishEventBlockSyncStatus(ctx, d); err != nil {
|
||||
r.logger.Error("failed to emit the blocksync complete event", "err", err)
|
||||
@@ -408,17 +408,20 @@ func (r *Reactor) sendNewRoundStepMessage(ctx context.Context, peerID types.Node
|
||||
})
|
||||
}
|
||||
|
||||
func (r *Reactor) updateRoundStateRoutine() {
|
||||
func (r *Reactor) updateRoundStateRoutine(ctx context.Context) {
|
||||
t := time.NewTicker(100 * time.Microsecond)
|
||||
defer t.Stop()
|
||||
for range t.C {
|
||||
if !r.IsRunning() {
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-t.C:
|
||||
rs := r.state.GetRoundState()
|
||||
r.mtx.Lock()
|
||||
r.rs = rs
|
||||
r.mtx.Unlock()
|
||||
}
|
||||
rs := r.state.GetRoundState()
|
||||
r.mtx.Lock()
|
||||
r.rs = rs
|
||||
r.mtx.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -752,9 +755,6 @@ func (r *Reactor) gossipVotesForHeight(
|
||||
func (r *Reactor) gossipVotesRoutine(ctx context.Context, ps *PeerState, voteCh *p2p.Channel) {
|
||||
logger := r.logger.With("peer", ps.peerID)
|
||||
|
||||
// XXX: simple hack to throttle logs upon sleep
|
||||
logThrottle := 0
|
||||
|
||||
timer := time.NewTimer(0)
|
||||
defer timer.Stop()
|
||||
|
||||
@@ -772,13 +772,6 @@ func (r *Reactor) gossipVotesRoutine(ctx context.Context, ps *PeerState, voteCh
|
||||
rs := r.getRoundState()
|
||||
prs := ps.GetRoundState()
|
||||
|
||||
switch logThrottle {
|
||||
case 1: // first sleep
|
||||
logThrottle = 2
|
||||
case 2: // no more sleep
|
||||
logThrottle = 0
|
||||
}
|
||||
|
||||
// if height matches, then send LastCommit, Prevotes, and Precommits
|
||||
if rs.Height == prs.Height {
|
||||
if ok, err := r.gossipVotesForHeight(ctx, rs, prs, ps, voteCh); err != nil {
|
||||
@@ -813,20 +806,6 @@ func (r *Reactor) gossipVotesRoutine(ctx context.Context, ps *PeerState, voteCh
|
||||
}
|
||||
}
|
||||
|
||||
if logThrottle == 0 {
|
||||
// we sent nothing -- sleep
|
||||
logThrottle = 1
|
||||
logger.Debug(
|
||||
"no votes to send; sleeping",
|
||||
"rs.Height", rs.Height,
|
||||
"prs.Height", prs.Height,
|
||||
"localPV", rs.Votes.Prevotes(rs.Round).BitArray(), "peerPV", prs.Prevotes,
|
||||
"localPC", rs.Votes.Precommits(rs.Round).BitArray(), "peerPC", prs.Precommits,
|
||||
)
|
||||
} else if logThrottle == 2 {
|
||||
logThrottle = 1
|
||||
}
|
||||
|
||||
timer.Reset(r.state.config.PeerGossipSleepDuration)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
@@ -860,10 +839,10 @@ func (r *Reactor) queryMaj23Routine(ctx context.Context, ps *PeerState, stateCh
|
||||
return
|
||||
}
|
||||
|
||||
// TODO create more reliable copies of these
|
||||
// structures so the following go routines don't race
|
||||
rs := r.getRoundState()
|
||||
prs := ps.GetRoundState()
|
||||
// TODO create more reliable coppies of these
|
||||
// structures so the following go routines don't race
|
||||
|
||||
wg := &sync.WaitGroup{}
|
||||
|
||||
|
||||
@@ -220,7 +220,6 @@ func NewHandshaker(
|
||||
eventBus *eventbus.EventBus,
|
||||
genDoc *types.GenesisDoc,
|
||||
) *Handshaker {
|
||||
|
||||
return &Handshaker{
|
||||
stateStore: stateStore,
|
||||
initialState: state,
|
||||
@@ -228,7 +227,6 @@ func NewHandshaker(
|
||||
eventBus: eventBus,
|
||||
genDoc: genDoc,
|
||||
logger: logger,
|
||||
nBlocks: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,7 +357,9 @@ func (h *Handshaker) ReplayBlocks(
|
||||
// First handle edge cases and constraints on the storeBlockHeight and storeBlockBase.
|
||||
switch {
|
||||
case storeBlockHeight == 0:
|
||||
assertAppHashEqualsOneFromState(appHash, state)
|
||||
if err := checkAppHashEqualsOneFromState(appHash, state); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return appHash, nil
|
||||
|
||||
case appBlockHeight == 0 && state.InitialHeight < storeBlockBase:
|
||||
@@ -376,11 +376,11 @@ func (h *Handshaker) ReplayBlocks(
|
||||
|
||||
case storeBlockHeight < stateBlockHeight:
|
||||
// the state should never be ahead of the store (this is under tendermint's control)
|
||||
panic(fmt.Sprintf("StateBlockHeight (%d) > StoreBlockHeight (%d)", stateBlockHeight, storeBlockHeight))
|
||||
return nil, fmt.Errorf("StateBlockHeight (%d) > StoreBlockHeight (%d)", stateBlockHeight, storeBlockHeight)
|
||||
|
||||
case storeBlockHeight > stateBlockHeight+1:
|
||||
// store should be at most one ahead of the state (this is under tendermint's control)
|
||||
panic(fmt.Sprintf("StoreBlockHeight (%d) > StateBlockHeight + 1 (%d)", storeBlockHeight, stateBlockHeight+1))
|
||||
return nil, fmt.Errorf("StoreBlockHeight (%d) > StateBlockHeight + 1 (%d)", storeBlockHeight, stateBlockHeight+1)
|
||||
}
|
||||
|
||||
var err error
|
||||
@@ -395,7 +395,9 @@ func (h *Handshaker) ReplayBlocks(
|
||||
|
||||
} else if appBlockHeight == storeBlockHeight {
|
||||
// We're good!
|
||||
assertAppHashEqualsOneFromState(appHash, state)
|
||||
if err := checkAppHashEqualsOneFromState(appHash, state); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return appHash, nil
|
||||
}
|
||||
|
||||
@@ -415,7 +417,11 @@ func (h *Handshaker) ReplayBlocks(
|
||||
// but we'd have to allow the WAL to replay a block that wrote it's #ENDHEIGHT
|
||||
h.logger.Info("Replay last block using real app")
|
||||
state, err = h.replayBlock(ctx, state, storeBlockHeight, appClient)
|
||||
return state.AppHash, err
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
}
|
||||
return state.AppHash, nil
|
||||
|
||||
case appBlockHeight == storeBlockHeight:
|
||||
// We ran Commit, but didn't save the state, so replayBlock with mock app.
|
||||
@@ -437,13 +443,13 @@ func (h *Handshaker) ReplayBlocks(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return state.AppHash, err
|
||||
return state.AppHash, nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("uncovered case! appHeight: %d, storeHeight: %d, stateHeight: %d",
|
||||
appBlockHeight, storeBlockHeight, stateBlockHeight))
|
||||
return nil, fmt.Errorf("uncovered case! appHeight: %d, storeHeight: %d, stateHeight: %d",
|
||||
appBlockHeight, storeBlockHeight, stateBlockHeight)
|
||||
}
|
||||
|
||||
func (h *Handshaker) replayBlocks(
|
||||
@@ -452,7 +458,8 @@ func (h *Handshaker) replayBlocks(
|
||||
appClient abciclient.Client,
|
||||
appBlockHeight,
|
||||
storeBlockHeight int64,
|
||||
mutateState bool) ([]byte, error) {
|
||||
mutateState bool,
|
||||
) ([]byte, error) {
|
||||
// App is further behind than it should be, so we need to replay blocks.
|
||||
// We replay all blocks from appBlockHeight+1.
|
||||
//
|
||||
@@ -478,7 +485,9 @@ func (h *Handshaker) replayBlocks(
|
||||
block := h.store.LoadBlock(i)
|
||||
// Extra check to ensure the app was not changed in a way it shouldn't have.
|
||||
if len(appHash) > 0 {
|
||||
assertAppHashEqualsOneFromBlock(appHash, block)
|
||||
if err := checkAppHashEqualsOneFromBlock(appHash, block); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if i == finalBlock && !mutateState {
|
||||
@@ -510,7 +519,9 @@ func (h *Handshaker) replayBlocks(
|
||||
appHash = state.AppHash
|
||||
}
|
||||
|
||||
assertAppHashEqualsOneFromState(appHash, state)
|
||||
if err := checkAppHashEqualsOneFromState(appHash, state); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return appHash, nil
|
||||
}
|
||||
|
||||
@@ -539,24 +550,25 @@ func (h *Handshaker) replayBlock(
|
||||
return state, nil
|
||||
}
|
||||
|
||||
func assertAppHashEqualsOneFromBlock(appHash []byte, block *types.Block) {
|
||||
func checkAppHashEqualsOneFromBlock(appHash []byte, block *types.Block) error {
|
||||
if !bytes.Equal(appHash, block.AppHash) {
|
||||
panic(fmt.Sprintf(`block.AppHash does not match AppHash after replay. Got %X, expected %X.
|
||||
return fmt.Errorf(`block.AppHash does not match AppHash after replay. Got '%X', expected '%X'.
|
||||
|
||||
Block: %v
|
||||
`,
|
||||
appHash, block.AppHash, block))
|
||||
Block: %v`,
|
||||
appHash, block.AppHash, block)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func assertAppHashEqualsOneFromState(appHash []byte, state sm.State) {
|
||||
func checkAppHashEqualsOneFromState(appHash []byte, state sm.State) error {
|
||||
if !bytes.Equal(appHash, state.AppHash) {
|
||||
panic(fmt.Sprintf(`state.AppHash does not match AppHash after replay. Got
|
||||
%X, expected %X.
|
||||
return fmt.Errorf(`state.AppHash does not match AppHash after replay. Got '%X', expected '%X'.
|
||||
|
||||
State: %v
|
||||
|
||||
Did you reset Tendermint without resetting your application's data?`,
|
||||
appHash, state.AppHash, state))
|
||||
appHash, state.AppHash, state)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -944,7 +944,7 @@ func buildTMStateFromChain(
|
||||
return state
|
||||
}
|
||||
|
||||
func TestHandshakePanicsIfAppReturnsWrongAppHash(t *testing.T) {
|
||||
func TestHandshakeErrorsIfAppReturnsWrongAppHash(t *testing.T) {
|
||||
// 1. Initialize tendermint and commit 3 blocks with the following app hashes:
|
||||
// - 0x01
|
||||
// - 0x02
|
||||
@@ -988,12 +988,8 @@ func TestHandshakePanicsIfAppReturnsWrongAppHash(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { cancel(); proxyApp.Wait() })
|
||||
|
||||
assert.Panics(t, func() {
|
||||
h := NewHandshaker(logger, stateStore, state, store, eventBus, genDoc)
|
||||
if err = h.Handshake(ctx, proxyApp); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
})
|
||||
h := NewHandshaker(logger, stateStore, state, store, eventBus, genDoc)
|
||||
assert.Error(t, h.Handshake(ctx, proxyApp))
|
||||
}
|
||||
|
||||
// 3. Tendermint must panic if app returns wrong hash for the last block
|
||||
@@ -1008,12 +1004,8 @@ func TestHandshakePanicsIfAppReturnsWrongAppHash(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { cancel(); proxyApp.Wait() })
|
||||
|
||||
assert.Panics(t, func() {
|
||||
h := NewHandshaker(logger, stateStore, state, store, eventBus, genDoc)
|
||||
if err = h.Handshake(ctx, proxyApp); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
})
|
||||
h := NewHandshaker(logger, stateStore, state, store, eventBus, genDoc)
|
||||
require.Error(t, h.Handshake(ctx, proxyApp))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -124,6 +124,7 @@ type State struct {
|
||||
|
||||
stateStore sm.Store
|
||||
initialStatePopulated bool
|
||||
skipBootstrapping bool
|
||||
|
||||
// create and execute blocks
|
||||
blockExec *sm.BlockExecutor
|
||||
@@ -185,6 +186,12 @@ type State struct {
|
||||
// StateOption sets an optional parameter on the State.
|
||||
type StateOption func(*State)
|
||||
|
||||
// SkipStateStoreBootstrap is a state option forces the constructor to
|
||||
// skip state bootstrapping during construction.
|
||||
func SkipStateStoreBootstrap(sm *State) {
|
||||
sm.skipBootstrapping = true
|
||||
}
|
||||
|
||||
// NewState returns a new State.
|
||||
func NewState(
|
||||
ctx context.Context,
|
||||
@@ -213,7 +220,7 @@ func NewState(
|
||||
doWALCatchup: true,
|
||||
wal: nilWAL{},
|
||||
evpool: evpool,
|
||||
evsw: tmevents.NewEventSwitch(logger),
|
||||
evsw: tmevents.NewEventSwitch(),
|
||||
metrics: NopMetrics(),
|
||||
onStopCh: make(chan *cstypes.RoundState),
|
||||
}
|
||||
@@ -223,16 +230,21 @@ func NewState(
|
||||
cs.doPrevote = cs.defaultDoPrevote
|
||||
cs.setProposal = cs.defaultSetProposal
|
||||
|
||||
if err := cs.updateStateFromStore(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// NOTE: we do not call scheduleRound0 yet, we do that upon Start()
|
||||
cs.BaseService = *service.NewBaseService(logger, "State", cs)
|
||||
for _, option := range options {
|
||||
option(cs)
|
||||
}
|
||||
|
||||
// this is not ideal, but it lets the consensus tests start
|
||||
// node-fragments gracefully while letting the nodes
|
||||
// themselves avoid this.
|
||||
if !cs.skipBootstrapping {
|
||||
if err := cs.updateStateFromStore(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return cs, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -309,9 +309,6 @@ func (s *Server) Wait() { <-s.exited; s.BaseService.Wait() }
|
||||
// OnStart implements Service.OnStart by starting the server.
|
||||
func (s *Server) OnStart(ctx context.Context) error { s.run(ctx); return nil }
|
||||
|
||||
// OnReset implements Service.OnReset. It has no effect for this service.
|
||||
func (s *Server) OnReset() error { return nil }
|
||||
|
||||
func (s *Server) publish(ctx context.Context, data types.EventData, events []abci.Event) error {
|
||||
s.pubs.RLock()
|
||||
defer s.pubs.RUnlock()
|
||||
|
||||
@@ -38,23 +38,32 @@ func (env *Environment) BroadcastTxSync(ctx context.Context, tx types.Tx) (*core
|
||||
err := env.Mempool.CheckTx(
|
||||
ctx,
|
||||
tx,
|
||||
func(res *abci.ResponseCheckTx) { resCh <- res },
|
||||
func(res *abci.ResponseCheckTx) {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case resCh <- res:
|
||||
}
|
||||
},
|
||||
mempool.TxInfo{},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r := <-resCh
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, fmt.Errorf("broadcast confirmation not received: %w", ctx.Err())
|
||||
case r := <-resCh:
|
||||
return &coretypes.ResultBroadcastTx{
|
||||
Code: r.Code,
|
||||
Data: r.Data,
|
||||
Log: r.Log,
|
||||
Codespace: r.Codespace,
|
||||
MempoolError: r.MempoolError,
|
||||
Hash: tx.Hash(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &coretypes.ResultBroadcastTx{
|
||||
Code: r.Code,
|
||||
Data: r.Data,
|
||||
Log: r.Log,
|
||||
Codespace: r.Codespace,
|
||||
MempoolError: r.MempoolError,
|
||||
Hash: tx.Hash(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// BroadcastTxCommit returns with the responses from CheckTx and DeliverTx.
|
||||
@@ -64,61 +73,70 @@ func (env *Environment) BroadcastTxCommit(ctx context.Context, tx types.Tx) (*co
|
||||
err := env.Mempool.CheckTx(
|
||||
ctx,
|
||||
tx,
|
||||
func(res *abci.ResponseCheckTx) { resCh <- res },
|
||||
func(res *abci.ResponseCheckTx) {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case resCh <- res:
|
||||
}
|
||||
},
|
||||
mempool.TxInfo{},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r := <-resCh
|
||||
if r.Code != abci.CodeTypeOK {
|
||||
return &coretypes.ResultBroadcastTxCommit{
|
||||
CheckTx: *r,
|
||||
Hash: tx.Hash(),
|
||||
}, fmt.Errorf("transaction encountered error (%s)", r.MempoolError)
|
||||
}
|
||||
|
||||
if !indexer.KVSinkEnabled(env.EventSinks) {
|
||||
return &coretypes.ResultBroadcastTxCommit{
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, fmt.Errorf("broadcast confirmation not received: %w", ctx.Err())
|
||||
case r := <-resCh:
|
||||
if r.Code != abci.CodeTypeOK {
|
||||
return &coretypes.ResultBroadcastTxCommit{
|
||||
CheckTx: *r,
|
||||
Hash: tx.Hash(),
|
||||
},
|
||||
errors.New("cannot confirm transaction because kvEventSink is not enabled")
|
||||
}
|
||||
}, fmt.Errorf("transaction encountered error (%s)", r.MempoolError)
|
||||
}
|
||||
|
||||
startAt := time.Now()
|
||||
timer := time.NewTimer(0)
|
||||
defer timer.Stop()
|
||||
|
||||
count := 0
|
||||
for {
|
||||
count++
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
env.Logger.Error("error on broadcastTxCommit",
|
||||
"duration", time.Since(startAt),
|
||||
"err", err)
|
||||
if !indexer.KVSinkEnabled(env.EventSinks) {
|
||||
return &coretypes.ResultBroadcastTxCommit{
|
||||
CheckTx: *r,
|
||||
Hash: tx.Hash(),
|
||||
}, fmt.Errorf("timeout waiting for commit of tx %s (%s)",
|
||||
tx.Hash(), time.Since(startAt))
|
||||
case <-timer.C:
|
||||
txres, err := env.Tx(ctx, tx.Hash(), false)
|
||||
if err != nil {
|
||||
jitter := 100*time.Millisecond + time.Duration(rand.Int63n(int64(time.Second))) // nolint: gosec
|
||||
backoff := 100 * time.Duration(count) * time.Millisecond
|
||||
timer.Reset(jitter + backoff)
|
||||
continue
|
||||
}
|
||||
},
|
||||
errors.New("cannot confirm transaction because kvEventSink is not enabled")
|
||||
}
|
||||
|
||||
return &coretypes.ResultBroadcastTxCommit{
|
||||
CheckTx: *r,
|
||||
TxResult: txres.TxResult,
|
||||
Hash: tx.Hash(),
|
||||
Height: txres.Height,
|
||||
}, nil
|
||||
startAt := time.Now()
|
||||
timer := time.NewTimer(0)
|
||||
defer timer.Stop()
|
||||
|
||||
count := 0
|
||||
for {
|
||||
count++
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
env.Logger.Error("error on broadcastTxCommit",
|
||||
"duration", time.Since(startAt),
|
||||
"err", err)
|
||||
return &coretypes.ResultBroadcastTxCommit{
|
||||
CheckTx: *r,
|
||||
Hash: tx.Hash(),
|
||||
}, fmt.Errorf("timeout waiting for commit of tx %s (%s)",
|
||||
tx.Hash(), time.Since(startAt))
|
||||
case <-timer.C:
|
||||
txres, err := env.Tx(ctx, tx.Hash(), false)
|
||||
if err != nil {
|
||||
jitter := 100*time.Millisecond + time.Duration(rand.Int63n(int64(time.Second))) // nolint: gosec
|
||||
backoff := 100 * time.Duration(count) * time.Millisecond
|
||||
timer.Reset(jitter + backoff)
|
||||
continue
|
||||
}
|
||||
|
||||
return &coretypes.ResultBroadcastTxCommit{
|
||||
CheckTx: *r,
|
||||
TxResult: txres.TxResult,
|
||||
Hash: tx.Hash(),
|
||||
Height: txres.Height,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,14 +77,25 @@ func (env *Environment) Status(ctx context.Context) (*coretypes.ResultStatus, er
|
||||
EarliestAppHash: earliestAppHash,
|
||||
EarliestBlockHeight: earliestBlockHeight,
|
||||
EarliestBlockTime: time.Unix(0, earliestBlockTimeNano),
|
||||
MaxPeerBlockHeight: env.BlockSyncReactor.GetMaxPeerBlockHeight(),
|
||||
CatchingUp: env.ConsensusReactor.WaitSync(),
|
||||
TotalSyncedTime: env.BlockSyncReactor.GetTotalSyncedTime(),
|
||||
RemainingTime: env.BlockSyncReactor.GetRemainingSyncTime(),
|
||||
// this should start as true, if consensus
|
||||
// hasn't started yet, and then flip to false
|
||||
// (or true,) depending on what's actually
|
||||
// happening.
|
||||
CatchingUp: true,
|
||||
},
|
||||
ValidatorInfo: validatorInfo,
|
||||
}
|
||||
|
||||
if env.ConsensusReactor != nil {
|
||||
result.SyncInfo.CatchingUp = env.ConsensusReactor.WaitSync()
|
||||
}
|
||||
|
||||
if env.BlockSyncReactor != nil {
|
||||
result.SyncInfo.MaxPeerBlockHeight = env.BlockSyncReactor.GetMaxPeerBlockHeight()
|
||||
result.SyncInfo.TotalSyncedTime = env.BlockSyncReactor.GetTotalSyncedTime()
|
||||
result.SyncInfo.RemainingTime = env.BlockSyncReactor.GetRemainingSyncTime()
|
||||
}
|
||||
|
||||
if env.StateSyncMetricer != nil {
|
||||
result.SyncInfo.TotalSnapshots = env.StateSyncMetricer.TotalSnapshots()
|
||||
result.SyncInfo.ChunkProcessAvgTime = env.StateSyncMetricer.ChunkProcessAvgTime()
|
||||
@@ -103,6 +114,9 @@ func (env *Environment) validatorAtHeight(h int64) *types.Validator {
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if env.ConsensusState == nil {
|
||||
return nil
|
||||
}
|
||||
if env.PubKey == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
+16
-10
@@ -48,8 +48,7 @@ type BlockExecutor struct {
|
||||
cache map[string]struct{}
|
||||
}
|
||||
|
||||
// NewBlockExecutor returns a new BlockExecutor with a NopEventBus.
|
||||
// Call SetEventBus to provide one.
|
||||
// NewBlockExecutor returns a new BlockExecutor with the passed-in EventBus.
|
||||
func NewBlockExecutor(
|
||||
stateStore Store,
|
||||
logger log.Logger,
|
||||
@@ -107,12 +106,14 @@ func (blockExec *BlockExecutor) CreateProposalBlock(
|
||||
rpp, err := blockExec.appClient.PrepareProposal(
|
||||
ctx,
|
||||
abci.RequestPrepareProposal{
|
||||
Hash: block.Hash(),
|
||||
Header: *block.Header.ToProto(),
|
||||
MaxTxBytes: maxDataBytes,
|
||||
Txs: block.Txs.ToSliceOfBytes(),
|
||||
LocalLastCommit: extendedCommitInfo(localLastCommit, votes),
|
||||
ByzantineValidators: block.Evidence.ToABCI(),
|
||||
MaxTxBytes: maxDataBytes,
|
||||
Height: block.Height,
|
||||
Time: block.Time,
|
||||
NextValidatorsHash: block.NextValidatorsHash,
|
||||
ProposerAddress: block.ProposerAddress,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
@@ -148,10 +149,13 @@ func (blockExec *BlockExecutor) ProcessProposal(
|
||||
) (bool, error) {
|
||||
req := abci.RequestProcessProposal{
|
||||
Hash: block.Header.Hash(),
|
||||
Header: *block.Header.ToProto(),
|
||||
Height: block.Header.Height,
|
||||
Time: block.Header.Time,
|
||||
Txs: block.Data.Txs.ToSliceOfBytes(),
|
||||
ProposedLastCommit: buildLastCommitInfo(block, blockExec.store, state.InitialHeight),
|
||||
ByzantineValidators: block.Evidence.ToABCI(),
|
||||
ProposerAddress: block.ProposerAddress,
|
||||
NextValidatorsHash: block.NextValidatorsHash,
|
||||
}
|
||||
|
||||
resp, err := blockExec.appClient.ProcessProposal(ctx, req)
|
||||
@@ -204,15 +208,17 @@ func (blockExec *BlockExecutor) ApplyBlock(
|
||||
return state, ErrInvalidBlock(err)
|
||||
}
|
||||
startTime := time.Now().UnixNano()
|
||||
pbh := block.Header.ToProto()
|
||||
finalizeBlockResponse, err := blockExec.appClient.FinalizeBlock(
|
||||
ctx,
|
||||
abci.RequestFinalizeBlock{
|
||||
Hash: block.Hash(),
|
||||
Header: *pbh,
|
||||
Height: block.Header.Height,
|
||||
Time: block.Header.Time,
|
||||
Txs: block.Txs.ToSliceOfBytes(),
|
||||
DecidedLastCommit: buildLastCommitInfo(block, blockExec.store, state.InitialHeight),
|
||||
ByzantineValidators: block.Evidence.ToABCI(),
|
||||
ProposerAddress: block.ProposerAddress,
|
||||
NextValidatorsHash: block.NextValidatorsHash,
|
||||
},
|
||||
)
|
||||
endTime := time.Now().UnixNano()
|
||||
@@ -601,12 +607,12 @@ func ExecCommitBlock(
|
||||
initialHeight int64,
|
||||
s State,
|
||||
) ([]byte, error) {
|
||||
pbh := block.Header.ToProto()
|
||||
finalizeBlockResponse, err := appConn.FinalizeBlock(
|
||||
ctx,
|
||||
abci.RequestFinalizeBlock{
|
||||
Hash: block.Hash(),
|
||||
Header: *pbh,
|
||||
Height: block.Height,
|
||||
Time: block.Time,
|
||||
Txs: block.Txs.ToSliceOfBytes(),
|
||||
DecidedLastCommit: buildLastCommitInfo(block, store, initialHeight),
|
||||
ByzantineValidators: block.Evidence.ToABCI(),
|
||||
|
||||
@@ -216,16 +216,16 @@ func TestFinalizeBlockByzantineValidators(t *testing.T) {
|
||||
|
||||
ev := []types.Evidence{dve, lcae}
|
||||
|
||||
abciEv := []abci.Evidence{
|
||||
abciMb := []abci.Misbehavior{
|
||||
{
|
||||
Type: abci.EvidenceType_DUPLICATE_VOTE,
|
||||
Type: abci.MisbehaviorType_DUPLICATE_VOTE,
|
||||
Height: 3,
|
||||
Time: defaultEvidenceTime,
|
||||
Validator: types.TM2PB.Validator(state.Validators.Validators[0]),
|
||||
TotalVotingPower: 10,
|
||||
},
|
||||
{
|
||||
Type: abci.EvidenceType_LIGHT_CLIENT_ATTACK,
|
||||
Type: abci.MisbehaviorType_LIGHT_CLIENT_ATTACK,
|
||||
Height: 8,
|
||||
Time: defaultEvidenceTime,
|
||||
Validator: types.TM2PB.Validator(state.Validators.Validators[0]),
|
||||
@@ -268,7 +268,7 @@ func TestFinalizeBlockByzantineValidators(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// TODO check state and mempool
|
||||
assert.Equal(t, abciEv, app.ByzantineValidators)
|
||||
assert.Equal(t, abciMb, app.ByzantineValidators)
|
||||
}
|
||||
|
||||
func TestProcessProposal(t *testing.T) {
|
||||
@@ -330,14 +330,17 @@ func TestProcessProposal(t *testing.T) {
|
||||
block1.Txs = txs
|
||||
|
||||
expectedRpp := abci.RequestProcessProposal{
|
||||
Hash: block1.Hash(),
|
||||
Header: *block1.Header.ToProto(),
|
||||
Txs: block1.Txs.ToSliceOfBytes(),
|
||||
Hash: block1.Hash(),
|
||||
Height: block1.Header.Height,
|
||||
Time: block1.Header.Time,
|
||||
ByzantineValidators: block1.Evidence.ToABCI(),
|
||||
ProposedLastCommit: abci.CommitInfo{
|
||||
Round: 0,
|
||||
Votes: voteInfos,
|
||||
},
|
||||
NextValidatorsHash: block1.NextValidatorsHash,
|
||||
ProposerAddress: block1.ProposerAddress,
|
||||
}
|
||||
|
||||
app.On("ProcessProposal", mock.Anything).Return(abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT})
|
||||
|
||||
@@ -270,7 +270,7 @@ type testApp struct {
|
||||
abci.BaseApplication
|
||||
|
||||
CommitVotes []abci.VoteInfo
|
||||
ByzantineValidators []abci.Evidence
|
||||
ByzantineValidators []abci.Misbehavior
|
||||
ValidatorUpdates []abci.ValidatorUpdate
|
||||
}
|
||||
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
// weightedTime for computing a median.
|
||||
type weightedTime struct {
|
||||
Time time.Time
|
||||
Weight int64
|
||||
}
|
||||
|
||||
// newWeightedTime with time and weight.
|
||||
func newWeightedTime(time time.Time, weight int64) *weightedTime {
|
||||
return &weightedTime{
|
||||
Time: time,
|
||||
Weight: weight,
|
||||
}
|
||||
}
|
||||
|
||||
// weightedMedian computes weighted median time for a given array of WeightedTime and the total voting power.
|
||||
func weightedMedian(weightedTimes []*weightedTime, totalVotingPower int64) (res time.Time) {
|
||||
median := totalVotingPower / 2
|
||||
|
||||
sort.Slice(weightedTimes, func(i, j int) bool {
|
||||
if weightedTimes[i] == nil {
|
||||
return false
|
||||
}
|
||||
if weightedTimes[j] == nil {
|
||||
return true
|
||||
}
|
||||
return weightedTimes[i].Time.UnixNano() < weightedTimes[j].Time.UnixNano()
|
||||
})
|
||||
|
||||
for _, weightedTime := range weightedTimes {
|
||||
if weightedTime != nil {
|
||||
if median <= weightedTime.Weight {
|
||||
res = weightedTime.Time
|
||||
break
|
||||
}
|
||||
median -= weightedTime.Weight
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
tmtime "github.com/tendermint/tendermint/libs/time"
|
||||
)
|
||||
|
||||
func TestWeightedMedian(t *testing.T) {
|
||||
m := make([]*weightedTime, 3)
|
||||
|
||||
t1 := tmtime.Now()
|
||||
t2 := t1.Add(5 * time.Second)
|
||||
t3 := t1.Add(10 * time.Second)
|
||||
|
||||
m[2] = newWeightedTime(t1, 33) // faulty processes
|
||||
m[0] = newWeightedTime(t2, 40) // correct processes
|
||||
m[1] = newWeightedTime(t3, 27) // correct processes
|
||||
totalVotingPower := int64(100)
|
||||
|
||||
median := weightedMedian(m, totalVotingPower)
|
||||
assert.Equal(t, t2, median)
|
||||
// median always returns value between values of correct processes
|
||||
assert.Equal(t, true, (median.After(t1) || median.Equal(t1)) &&
|
||||
(median.Before(t3) || median.Equal(t3)))
|
||||
|
||||
m[1] = newWeightedTime(t1, 40) // correct processes
|
||||
m[2] = newWeightedTime(t2, 27) // correct processes
|
||||
m[0] = newWeightedTime(t3, 33) // faulty processes
|
||||
totalVotingPower = int64(100)
|
||||
|
||||
median = weightedMedian(m, totalVotingPower)
|
||||
assert.Equal(t, t2, median)
|
||||
// median always returns value between values of correct processes
|
||||
assert.Equal(t, true, (median.After(t1) || median.Equal(t1)) &&
|
||||
(median.Before(t2) || median.Equal(t2)))
|
||||
|
||||
m = make([]*weightedTime, 8)
|
||||
t4 := t1.Add(15 * time.Second)
|
||||
t5 := t1.Add(60 * time.Second)
|
||||
|
||||
m[3] = newWeightedTime(t1, 10) // correct processes
|
||||
m[1] = newWeightedTime(t2, 10) // correct processes
|
||||
m[5] = newWeightedTime(t2, 10) // correct processes
|
||||
m[4] = newWeightedTime(t3, 23) // faulty processes
|
||||
m[0] = newWeightedTime(t4, 20) // correct processes
|
||||
m[7] = newWeightedTime(t5, 10) // faulty processes
|
||||
totalVotingPower = int64(83)
|
||||
|
||||
median = weightedMedian(m, totalVotingPower)
|
||||
assert.Equal(t, t3, median)
|
||||
// median always returns value between values of correct processes
|
||||
assert.Equal(t, true, (median.After(t1) || median.Equal(t1)) &&
|
||||
(median.Before(t4) || median.Equal(t4)))
|
||||
}
|
||||
@@ -292,7 +292,7 @@ func TestValidateBlockEvidence(t *testing.T) {
|
||||
evpool.On("CheckEvidence", ctx, mock.AnythingOfType("types.EvidenceList")).Return(nil)
|
||||
evpool.On("Update", ctx, mock.AnythingOfType("state.State"), mock.AnythingOfType("types.EvidenceList")).Return()
|
||||
evpool.On("ABCIEvidence", mock.AnythingOfType("int64"), mock.AnythingOfType("[]types.Evidence")).Return(
|
||||
[]abci.Evidence{})
|
||||
[]abci.Misbehavior{})
|
||||
|
||||
eventBus := eventbus.NewDefault(logger)
|
||||
require.NoError(t, eventBus.Start(ctx))
|
||||
|
||||
@@ -143,6 +143,12 @@ type Reactor struct {
|
||||
peerEvents p2p.PeerEventSubscriber
|
||||
chCreator p2p.ChannelCreator
|
||||
sendBlockError func(context.Context, p2p.PeerError) error
|
||||
postSyncHook func(context.Context, sm.State) error
|
||||
|
||||
// when true, the reactor will, during startup perform a
|
||||
// statesync for this node, and otherwise just provide
|
||||
// snapshots to other nodes.
|
||||
needsStateSync bool
|
||||
|
||||
// Dispatcher is used to multiplex light block requests and responses over multiple
|
||||
// peers used by the p2p state provider and in reverse sync.
|
||||
@@ -171,7 +177,6 @@ type Reactor struct {
|
||||
// and querying, references to p2p Channels and a channel to listen for peer
|
||||
// updates on. Note, the reactor will close all p2p Channels when stopping.
|
||||
func NewReactor(
|
||||
ctx context.Context,
|
||||
chainID string,
|
||||
initialHeight int64,
|
||||
cfg config.StateSyncConfig,
|
||||
@@ -184,23 +189,26 @@ func NewReactor(
|
||||
tempDir string,
|
||||
ssMetrics *Metrics,
|
||||
eventBus *eventbus.EventBus,
|
||||
postSyncHook func(context.Context, sm.State) error,
|
||||
needsStateSync bool,
|
||||
) *Reactor {
|
||||
|
||||
r := &Reactor{
|
||||
logger: logger,
|
||||
chainID: chainID,
|
||||
initialHeight: initialHeight,
|
||||
cfg: cfg,
|
||||
conn: conn,
|
||||
chCreator: channelCreator,
|
||||
peerEvents: peerEvents,
|
||||
tempDir: tempDir,
|
||||
stateStore: stateStore,
|
||||
blockStore: blockStore,
|
||||
peers: newPeerList(),
|
||||
providers: make(map[types.NodeID]*BlockProvider),
|
||||
metrics: ssMetrics,
|
||||
eventBus: eventBus,
|
||||
logger: logger,
|
||||
chainID: chainID,
|
||||
initialHeight: initialHeight,
|
||||
cfg: cfg,
|
||||
conn: conn,
|
||||
chCreator: channelCreator,
|
||||
peerEvents: peerEvents,
|
||||
tempDir: tempDir,
|
||||
stateStore: stateStore,
|
||||
blockStore: blockStore,
|
||||
peers: newPeerList(),
|
||||
providers: make(map[types.NodeID]*BlockProvider),
|
||||
metrics: ssMetrics,
|
||||
eventBus: eventBus,
|
||||
postSyncHook: postSyncHook,
|
||||
needsStateSync: needsStateSync,
|
||||
}
|
||||
|
||||
r.BaseService = *service.NewBaseService(logger, "StateSync", r)
|
||||
@@ -300,6 +308,14 @@ func (r *Reactor) OnStart(ctx context.Context) error {
|
||||
go r.processChannels(ctx, snapshotCh, chunkCh, blockCh, paramsCh)
|
||||
go r.processPeerUpdates(ctx, r.peerEvents(ctx))
|
||||
|
||||
if r.needsStateSync {
|
||||
r.logger.Info("starting state sync")
|
||||
if _, err := r.Sync(ctx); err != nil {
|
||||
r.logger.Error("state sync failed; shutting down this node", "err", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -310,20 +326,21 @@ func (r *Reactor) OnStop() {
|
||||
r.dispatcher.Close()
|
||||
}
|
||||
|
||||
func (r *Reactor) PublishStatus(ctx context.Context, event types.EventDataStateSyncStatus) error {
|
||||
if r.eventBus == nil {
|
||||
return errors.New("event system is not configured")
|
||||
}
|
||||
|
||||
return r.eventBus.PublishEventStateSyncStatus(ctx, event)
|
||||
}
|
||||
|
||||
// Sync runs a state sync, fetching snapshots and providing chunks to the
|
||||
// application. At the close of the operation, Sync will bootstrap the state
|
||||
// store and persist the commit at that height so that either consensus or
|
||||
// blocksync can commence. It will then proceed to backfill the necessary amount
|
||||
// of historical blocks before participating in consensus
|
||||
func (r *Reactor) Sync(ctx context.Context) (sm.State, error) {
|
||||
if r.eventBus != nil {
|
||||
if err := r.eventBus.PublishEventStateSyncStatus(ctx, types.EventDataStateSyncStatus{
|
||||
Complete: false,
|
||||
Height: r.initialHeight,
|
||||
}); err != nil {
|
||||
return sm.State{}, err
|
||||
}
|
||||
}
|
||||
|
||||
// We need at least two peers (for cross-referencing of light blocks) before we can
|
||||
// begin state sync
|
||||
if err := r.waitForEnoughPeers(ctx, 2); err != nil {
|
||||
@@ -357,21 +374,33 @@ func (r *Reactor) Sync(ctx context.Context) (sm.State, error) {
|
||||
return sm.State{}, err
|
||||
}
|
||||
|
||||
err = r.stateStore.Bootstrap(state)
|
||||
if err != nil {
|
||||
if err := r.stateStore.Bootstrap(state); err != nil {
|
||||
return sm.State{}, fmt.Errorf("failed to bootstrap node with new state: %w", err)
|
||||
}
|
||||
|
||||
err = r.blockStore.SaveSeenCommit(state.LastBlockHeight, commit)
|
||||
if err != nil {
|
||||
if err := r.blockStore.SaveSeenCommit(state.LastBlockHeight, commit); err != nil {
|
||||
return sm.State{}, fmt.Errorf("failed to store last seen commit: %w", err)
|
||||
}
|
||||
|
||||
err = r.Backfill(ctx, state)
|
||||
if err != nil {
|
||||
if err := r.Backfill(ctx, state); err != nil {
|
||||
r.logger.Error("backfill failed. Proceeding optimistically...", "err", err)
|
||||
}
|
||||
|
||||
if r.eventBus != nil {
|
||||
if err := r.eventBus.PublishEventStateSyncStatus(ctx, types.EventDataStateSyncStatus{
|
||||
Complete: true,
|
||||
Height: state.LastBlockHeight,
|
||||
}); err != nil {
|
||||
return sm.State{}, err
|
||||
}
|
||||
}
|
||||
|
||||
if r.postSyncHook != nil {
|
||||
if err := r.postSyncHook(ctx, state); err != nil {
|
||||
return sm.State{}, err
|
||||
}
|
||||
}
|
||||
|
||||
return state, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -155,7 +155,6 @@ func setup(
|
||||
logger := log.NewNopLogger()
|
||||
|
||||
rts.reactor = NewReactor(
|
||||
ctx,
|
||||
factory.DefaultTestChainID,
|
||||
1,
|
||||
*cfg,
|
||||
@@ -167,7 +166,9 @@ func setup(
|
||||
rts.blockStore,
|
||||
"",
|
||||
m,
|
||||
nil, // eventbus can be nil
|
||||
nil, // eventbus can be nil
|
||||
nil, // post-sync-hook
|
||||
false, // run Sync during Start()
|
||||
)
|
||||
|
||||
rts.syncer = &syncer{
|
||||
|
||||
+8
-87
@@ -3,22 +3,9 @@ package events
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
)
|
||||
|
||||
// ErrListenerWasRemoved is returned by AddEvent if the listener was removed.
|
||||
type ErrListenerWasRemoved struct {
|
||||
listenerID string
|
||||
}
|
||||
|
||||
// Error implements the error interface.
|
||||
func (e ErrListenerWasRemoved) Error() string {
|
||||
return fmt.Sprintf("listener #%s was removed", e.listenerID)
|
||||
}
|
||||
|
||||
// EventData is a generic event data can be typed and registered with
|
||||
// tendermint/go-amino via concrete implementation of this interface.
|
||||
type EventData interface{}
|
||||
@@ -51,13 +38,11 @@ type EventSwitch interface {
|
||||
type eventSwitch struct {
|
||||
mtx sync.RWMutex
|
||||
eventCells map[string]*eventCell
|
||||
listeners map[string]*eventListener
|
||||
}
|
||||
|
||||
func NewEventSwitch(logger log.Logger) EventSwitch {
|
||||
func NewEventSwitch() EventSwitch {
|
||||
evsw := &eventSwitch{
|
||||
eventCells: make(map[string]*eventCell),
|
||||
listeners: make(map[string]*eventListener),
|
||||
}
|
||||
return evsw
|
||||
}
|
||||
@@ -71,20 +56,9 @@ func (evsw *eventSwitch) AddListenerForEvent(listenerID, eventValue string, cb E
|
||||
eventCell = newEventCell()
|
||||
evsw.eventCells[eventValue] = eventCell
|
||||
}
|
||||
|
||||
listener := evsw.listeners[listenerID]
|
||||
if listener == nil {
|
||||
listener = newEventListener(listenerID)
|
||||
evsw.listeners[listenerID] = listener
|
||||
}
|
||||
|
||||
evsw.mtx.Unlock()
|
||||
|
||||
if err := listener.AddEvent(eventValue); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
eventCell.AddListener(listenerID, cb)
|
||||
eventCell.addListener(listenerID, cb)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -99,11 +73,13 @@ func (evsw *eventSwitch) FireEvent(ctx context.Context, event string, data Event
|
||||
}
|
||||
|
||||
// Fire event for all listeners in eventCell
|
||||
eventCell.FireEvent(ctx, data)
|
||||
eventCell.fireEvent(ctx, data)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
type EventCallback func(ctx context.Context, data EventData) error
|
||||
|
||||
// eventCell handles keeping track of listener callbacks for a given event.
|
||||
type eventCell struct {
|
||||
mtx sync.RWMutex
|
||||
@@ -116,21 +92,13 @@ func newEventCell() *eventCell {
|
||||
}
|
||||
}
|
||||
|
||||
func (cell *eventCell) AddListener(listenerID string, cb EventCallback) {
|
||||
func (cell *eventCell) addListener(listenerID string, cb EventCallback) {
|
||||
cell.mtx.Lock()
|
||||
defer cell.mtx.Unlock()
|
||||
cell.listeners[listenerID] = cb
|
||||
cell.mtx.Unlock()
|
||||
}
|
||||
|
||||
func (cell *eventCell) RemoveListener(listenerID string) int {
|
||||
cell.mtx.Lock()
|
||||
delete(cell.listeners, listenerID)
|
||||
numListeners := len(cell.listeners)
|
||||
cell.mtx.Unlock()
|
||||
return numListeners
|
||||
}
|
||||
|
||||
func (cell *eventCell) FireEvent(ctx context.Context, data EventData) {
|
||||
func (cell *eventCell) fireEvent(ctx context.Context, data EventData) {
|
||||
cell.mtx.RLock()
|
||||
eventCallbacks := make([]EventCallback, 0, len(cell.listeners))
|
||||
for _, cb := range cell.listeners {
|
||||
@@ -145,50 +113,3 @@ func (cell *eventCell) FireEvent(ctx context.Context, data EventData) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
type EventCallback func(ctx context.Context, data EventData) error
|
||||
|
||||
type eventListener struct {
|
||||
id string
|
||||
|
||||
mtx sync.RWMutex
|
||||
removed bool
|
||||
events []string
|
||||
}
|
||||
|
||||
func newEventListener(id string) *eventListener {
|
||||
return &eventListener{
|
||||
id: id,
|
||||
removed: false,
|
||||
events: nil,
|
||||
}
|
||||
}
|
||||
|
||||
func (evl *eventListener) AddEvent(event string) error {
|
||||
evl.mtx.Lock()
|
||||
|
||||
if evl.removed {
|
||||
evl.mtx.Unlock()
|
||||
return ErrListenerWasRemoved{listenerID: evl.id}
|
||||
}
|
||||
|
||||
evl.events = append(evl.events, event)
|
||||
evl.mtx.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (evl *eventListener) GetEvents() []string {
|
||||
evl.mtx.RLock()
|
||||
events := make([]string, len(evl.events))
|
||||
copy(events, evl.events)
|
||||
evl.mtx.RUnlock()
|
||||
return events
|
||||
}
|
||||
|
||||
func (evl *eventListener) SetRemoved() {
|
||||
evl.mtx.Lock()
|
||||
evl.removed = true
|
||||
evl.mtx.Unlock()
|
||||
}
|
||||
|
||||
@@ -8,8 +8,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
)
|
||||
|
||||
// TestAddListenerForEventFireOnce sets up an EventSwitch, subscribes a single
|
||||
@@ -18,9 +16,7 @@ func TestAddListenerForEventFireOnce(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
logger := log.NewTestingLogger(t)
|
||||
|
||||
evsw := NewEventSwitch(logger)
|
||||
evsw := NewEventSwitch()
|
||||
|
||||
messages := make(chan EventData)
|
||||
require.NoError(t, evsw.AddListenerForEvent("listener", "event",
|
||||
@@ -45,9 +41,7 @@ func TestAddListenerForEventFireMany(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
logger := log.NewTestingLogger(t)
|
||||
|
||||
evsw := NewEventSwitch(logger)
|
||||
evsw := NewEventSwitch()
|
||||
|
||||
doneSum := make(chan uint64)
|
||||
doneSending := make(chan uint64)
|
||||
@@ -81,9 +75,7 @@ func TestAddListenerForDifferentEvents(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
logger := log.NewTestingLogger(t)
|
||||
|
||||
evsw := NewEventSwitch(logger)
|
||||
evsw := NewEventSwitch()
|
||||
|
||||
doneSum := make(chan uint64)
|
||||
doneSending1 := make(chan uint64)
|
||||
@@ -143,8 +135,7 @@ func TestAddDifferentListenerForDifferentEvents(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
logger := log.NewTestingLogger(t)
|
||||
evsw := NewEventSwitch(logger)
|
||||
evsw := NewEventSwitch()
|
||||
|
||||
doneSum1 := make(chan uint64)
|
||||
doneSum2 := make(chan uint64)
|
||||
@@ -235,9 +226,8 @@ func TestAddDifferentListenerForDifferentEvents(t *testing.T) {
|
||||
func TestManageListenersAsync(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
logger := log.NewTestingLogger(t)
|
||||
|
||||
evsw := NewEventSwitch(logger)
|
||||
evsw := NewEventSwitch()
|
||||
|
||||
doneSum1 := make(chan uint64)
|
||||
doneSum2 := make(chan uint64)
|
||||
|
||||
+2
-12
@@ -12,11 +12,8 @@ var (
|
||||
// errAlreadyStopped is returned when somebody tries to stop an already
|
||||
// stopped service (without resetting it).
|
||||
errAlreadyStopped = errors.New("already stopped")
|
||||
)
|
||||
|
||||
var (
|
||||
_ Service = (*BaseService)(nil)
|
||||
_ Service = (*NopService)(nil)
|
||||
)
|
||||
|
||||
// Service defines a service that can be started, stopped, and reset.
|
||||
@@ -75,8 +72,7 @@ Typical usage:
|
||||
}
|
||||
|
||||
func (fs *FooService) OnStop() {
|
||||
// close/destroy private fields
|
||||
// stop subroutines, etc.
|
||||
// close/destroy private fields and releases resources
|
||||
}
|
||||
*/
|
||||
type BaseService struct {
|
||||
@@ -90,12 +86,6 @@ type BaseService struct {
|
||||
impl Implementation
|
||||
}
|
||||
|
||||
type NopService struct{}
|
||||
|
||||
func (NopService) Start(_ context.Context) error { return nil }
|
||||
func (NopService) IsRunning() bool { return true }
|
||||
func (NopService) Wait() {}
|
||||
|
||||
// NewBaseService creates a new BaseService.
|
||||
func NewBaseService(logger log.Logger, name string, impl Implementation) *BaseService {
|
||||
return &BaseService{
|
||||
@@ -206,5 +196,5 @@ func (bs *BaseService) getWait() <-chan struct{} {
|
||||
// Wait blocks until the service is stopped.
|
||||
func (bs *BaseService) Wait() { <-bs.getWait() }
|
||||
|
||||
// String implements Service by returning a string representation of the service.
|
||||
// String provides a human-friendly representation of the service.
|
||||
func (bs *BaseService) String() string { return bs.name }
|
||||
|
||||
+84
-140
@@ -60,18 +60,17 @@ type nodeImpl struct {
|
||||
nodeKey types.NodeKey // our node privkey
|
||||
|
||||
// services
|
||||
eventSinks []indexer.EventSink
|
||||
stateStore sm.Store
|
||||
blockStore *store.BlockStore // store the blockchain to disk
|
||||
evPool *evidence.Pool
|
||||
stateSync bool // whether the node should state sync on startup
|
||||
stateSyncReactor *statesync.Reactor // for hosting and restoring state sync snapshots
|
||||
|
||||
services []service.Service
|
||||
rpcListeners []net.Listener // rpc servers
|
||||
shutdownOps closer
|
||||
rpcEnv *rpccore.Environment
|
||||
prometheusSrv *http.Server
|
||||
eventSinks []indexer.EventSink
|
||||
initialState sm.State
|
||||
stateStore sm.Store
|
||||
blockStore *store.BlockStore // store the blockchain to disk
|
||||
evPool *evidence.Pool
|
||||
indexerService *indexer.Service
|
||||
services []service.Service
|
||||
rpcListeners []net.Listener // rpc servers
|
||||
shutdownOps closer
|
||||
rpcEnv *rpccore.Environment
|
||||
prometheusSrv *http.Server
|
||||
}
|
||||
|
||||
// newDefaultNode returns a Tendermint node with default settings for the
|
||||
@@ -157,20 +156,8 @@ func makeNode(
|
||||
|
||||
nodeMetrics := defaultMetricsProvider(cfg.Instrumentation)(genDoc.ChainID)
|
||||
|
||||
// Create the proxyApp and establish connections to the ABCI app (consensus, mempool, query).
|
||||
proxyApp := proxy.New(client, logger.With("module", "proxy"), nodeMetrics.proxy)
|
||||
if err := proxyApp.Start(ctx); err != nil {
|
||||
return nil, fmt.Errorf("error starting proxy app connections: %w", err)
|
||||
}
|
||||
|
||||
// EventBus and IndexerService must be started before the handshake because
|
||||
// we might need to index the txs of the replayed block as this might not have happened
|
||||
// when the node stopped last time (i.e. the node stopped or crashed after it saved the block
|
||||
// but before it indexed the txs)
|
||||
eventBus := eventbus.NewDefault(logger.With("module", "events"))
|
||||
if err := eventBus.Start(ctx); err != nil {
|
||||
return nil, combineCloseError(err, makeCloser(closers))
|
||||
}
|
||||
|
||||
var eventLog *eventlog.Log
|
||||
if w := cfg.RPC.EventLogWindowSize; w > 0 {
|
||||
@@ -185,13 +172,11 @@ func makeNode(
|
||||
}
|
||||
}
|
||||
|
||||
indexerService, eventSinks, err := createAndStartIndexerService(
|
||||
ctx, cfg, dbProvider, eventBus,
|
||||
logger, genDoc.ChainID, nodeMetrics.indexer)
|
||||
indexerService, eventSinks, err := createIndexerService(
|
||||
cfg, dbProvider, eventBus, logger, genDoc.ChainID, nodeMetrics.indexer)
|
||||
if err != nil {
|
||||
return nil, combineCloseError(err, makeCloser(closers))
|
||||
}
|
||||
closers = append(closers, func() error { indexerService.Stop(); return nil })
|
||||
|
||||
privValidator, err := createPrivval(ctx, logger, cfg, genDoc, filePrivval)
|
||||
if err != nil {
|
||||
@@ -213,34 +198,6 @@ func makeNode(
|
||||
}
|
||||
}
|
||||
|
||||
// Create the handshaker, which calls RequestInfo, sets the AppVersion on the state,
|
||||
// and replays any blocks as necessary to sync tendermint with the app.
|
||||
if err := consensus.NewHandshaker(
|
||||
logger.With("module", "handshaker"),
|
||||
stateStore, state, blockStore, eventBus, genDoc,
|
||||
).Handshake(ctx, proxyApp); err != nil {
|
||||
return nil, combineCloseError(err, makeCloser(closers))
|
||||
}
|
||||
|
||||
// Reload the state. It will have the Version.Consensus.App set by the
|
||||
// Handshake, and may have other modifications as well (ie. depending on
|
||||
// what happened during block replay).
|
||||
state, err = stateStore.Load()
|
||||
if err != nil {
|
||||
return nil, combineCloseError(
|
||||
fmt.Errorf("cannot load state: %w", err),
|
||||
makeCloser(closers))
|
||||
}
|
||||
|
||||
logNodeStartupInfo(state, pubKey, logger, cfg.Mode)
|
||||
|
||||
// TODO: Fetch and provide real options and do proper p2p bootstrapping.
|
||||
// TODO: Use a persistent peer database.
|
||||
nodeInfo, err := makeNodeInfo(cfg, nodeKey, eventSinks, genDoc, state.Version.Consensus)
|
||||
if err != nil {
|
||||
return nil, combineCloseError(err, makeCloser(closers))
|
||||
}
|
||||
|
||||
peerManager, peerCloser, err := createPeerManager(cfg, dbProvider, nodeKey.ID)
|
||||
closers = append(closers, peerCloser)
|
||||
if err != nil {
|
||||
@@ -257,15 +214,15 @@ func makeNode(
|
||||
privValidator: privValidator,
|
||||
|
||||
peerManager: peerManager,
|
||||
nodeInfo: nodeInfo,
|
||||
nodeKey: nodeKey,
|
||||
|
||||
eventSinks: eventSinks,
|
||||
eventSinks: eventSinks,
|
||||
indexerService: indexerService,
|
||||
services: []service.Service{eventBus},
|
||||
|
||||
services: []service.Service{eventBus},
|
||||
|
||||
stateStore: stateStore,
|
||||
blockStore: blockStore,
|
||||
initialState: state,
|
||||
stateStore: stateStore,
|
||||
blockStore: blockStore,
|
||||
|
||||
shutdownOps: makeCloser(closers),
|
||||
|
||||
@@ -372,13 +329,15 @@ func makeNode(
|
||||
nodeMetrics.consensus.BlockSyncing.Set(1)
|
||||
}
|
||||
|
||||
if cfg.P2P.PexReactor {
|
||||
node.services = append(node.services, pex.NewReactor(logger, peerManager, node.router.OpenChannel, peerManager.Subscribe))
|
||||
}
|
||||
|
||||
// Set up state sync reactor, and schedule a sync if requested.
|
||||
// FIXME The way we do phased startups (e.g. replay -> block sync -> consensus) is very messy,
|
||||
// we should clean this whole thing up. See:
|
||||
// https://github.com/tendermint/tendermint/issues/4644
|
||||
node.stateSync = stateSync
|
||||
node.stateSyncReactor = statesync.NewReactor(
|
||||
ctx,
|
||||
node.services = append(node.services, statesync.NewReactor(
|
||||
genDoc.ChainID,
|
||||
genDoc.InitialHeight,
|
||||
*cfg.StateSync,
|
||||
@@ -391,11 +350,24 @@ func makeNode(
|
||||
cfg.StateSync.TempDir,
|
||||
nodeMetrics.statesync,
|
||||
eventBus,
|
||||
)
|
||||
// the post-sync operation
|
||||
func(ctx context.Context, state sm.State) error {
|
||||
csReactor.SetStateSyncingMetrics(0)
|
||||
|
||||
if cfg.P2P.PexReactor {
|
||||
node.services = append(node.services, pex.NewReactor(logger, peerManager, node.router.OpenChannel, peerManager.Subscribe))
|
||||
}
|
||||
// TODO: Some form of orchestrator is needed here between the state
|
||||
// advancing reactors to be able to control which one of the three
|
||||
// is running
|
||||
// FIXME Very ugly to have these metrics bleed through here.
|
||||
csReactor.SetBlockSyncingMetrics(1)
|
||||
if err := bcReactor.SwitchToBlockSync(ctx, state); err != nil {
|
||||
logger.Error("failed to switch to block sync", "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
stateSync,
|
||||
))
|
||||
|
||||
if cfg.Mode == config.ModeValidator {
|
||||
node.rpcEnv.PubKey = pubKey
|
||||
@@ -408,6 +380,48 @@ func makeNode(
|
||||
|
||||
// OnStart starts the Node. It implements service.Service.
|
||||
func (n *nodeImpl) OnStart(ctx context.Context) error {
|
||||
if err := n.rpcEnv.ProxyApp.Start(ctx); err != nil {
|
||||
return fmt.Errorf("error starting proxy app connections: %w", err)
|
||||
}
|
||||
|
||||
// EventBus and IndexerService must be started before the handshake because
|
||||
// we might need to index the txs of the replayed block as this might not have happened
|
||||
// when the node stopped last time (i.e. the node stopped or crashed after it saved the block
|
||||
// but before it indexed the txs)
|
||||
if err := n.rpcEnv.EventBus.Start(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := n.indexerService.Start(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create the handshaker, which calls RequestInfo, sets the AppVersion on the state,
|
||||
// and replays any blocks as necessary to sync tendermint with the app.
|
||||
if err := consensus.NewHandshaker(n.logger.With("module", "handshaker"),
|
||||
n.stateStore, n.initialState, n.blockStore, n.rpcEnv.EventBus, n.genesisDoc,
|
||||
).Handshake(ctx, n.rpcEnv.ProxyApp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Reload the state. It will have the Version.Consensus.App set by the
|
||||
// Handshake, and may have other modifications as well (ie. depending on
|
||||
// what happened during block replay).
|
||||
state, err := n.stateStore.Load()
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot load state: %w", err)
|
||||
}
|
||||
|
||||
logNodeStartupInfo(state, n.rpcEnv.PubKey, n.logger, n.config.Mode)
|
||||
|
||||
// TODO: Fetch and provide real options and do proper p2p bootstrapping.
|
||||
// TODO: Use a persistent peer database.
|
||||
n.nodeInfo, err = makeNodeInfo(n.config, n.nodeKey, n.eventSinks, n.genesisDoc, state.Version.Consensus)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Start Internal Services
|
||||
|
||||
if n.config.RPC.PprofListenAddress != "" {
|
||||
rpcCtx, rpcCancel := context.WithCancel(ctx)
|
||||
srv := &http.Server{Addr: n.config.RPC.PprofListenAddress, Handler: nil}
|
||||
@@ -445,7 +459,7 @@ func (n *nodeImpl) OnStart(ctx context.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
state, err := n.stateStore.Load()
|
||||
state, err = n.stateStore.Load()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -480,75 +494,6 @@ func (n *nodeImpl) OnStart(ctx context.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
if err := n.stateSyncReactor.Start(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Run state sync
|
||||
// TODO: We shouldn't run state sync if we already have state that has a
|
||||
// LastBlockHeight that is not InitialHeight
|
||||
if n.stateSync {
|
||||
bcR := n.rpcEnv.BlockSyncReactor
|
||||
|
||||
// we need to get the genesis state to get parameters such as
|
||||
state, err := sm.MakeGenesisState(n.genesisDoc)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to derive state: %w", err)
|
||||
}
|
||||
|
||||
// TODO: we may want to move these events within the respective
|
||||
// reactors.
|
||||
// At the beginning of the statesync start, we use the initialHeight as the event height
|
||||
// because of the statesync doesn't have the concreate state height before fetched the snapshot.
|
||||
d := types.EventDataStateSyncStatus{Complete: false, Height: state.InitialHeight}
|
||||
if err := n.stateSyncReactor.PublishStatus(ctx, d); err != nil {
|
||||
n.logger.Error("failed to emit the statesync start event", "err", err)
|
||||
}
|
||||
|
||||
// RUN STATE SYNC NOW:
|
||||
//
|
||||
// TODO: Eventually this should run as part of some
|
||||
// separate orchestrator
|
||||
n.logger.Info("starting state sync")
|
||||
ssState, err := n.stateSyncReactor.Sync(ctx)
|
||||
if err != nil {
|
||||
n.logger.Error("state sync failed; shutting down this node", "err", err)
|
||||
// stop the node
|
||||
n.Stop()
|
||||
return err
|
||||
}
|
||||
|
||||
n.rpcEnv.ConsensusReactor.SetStateSyncingMetrics(0)
|
||||
|
||||
if err := n.stateSyncReactor.PublishStatus(ctx,
|
||||
types.EventDataStateSyncStatus{
|
||||
Complete: true,
|
||||
Height: ssState.LastBlockHeight,
|
||||
}); err != nil {
|
||||
n.logger.Error("failed to emit the statesync start event", "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: Some form of orchestrator is needed here between the state
|
||||
// advancing reactors to be able to control which one of the three
|
||||
// is running
|
||||
// FIXME Very ugly to have these metrics bleed through here.
|
||||
n.rpcEnv.ConsensusReactor.SetBlockSyncingMetrics(1)
|
||||
if err := bcR.SwitchToBlockSync(ctx, ssState); err != nil {
|
||||
n.logger.Error("failed to switch to block sync", "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := bcR.PublishStatus(ctx,
|
||||
types.EventDataBlockSyncStatus{
|
||||
Complete: false,
|
||||
Height: ssState.LastBlockHeight,
|
||||
}); err != nil {
|
||||
n.logger.Error("failed to emit the block sync starting event", "err", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -565,7 +510,6 @@ func (n *nodeImpl) OnStop() {
|
||||
reactor.Wait()
|
||||
}
|
||||
|
||||
n.stateSyncReactor.Wait()
|
||||
n.router.Wait()
|
||||
n.rpcEnv.IsListening = false
|
||||
|
||||
|
||||
+5
-2
@@ -62,12 +62,13 @@ func TestNodeStartStop(t *testing.T) {
|
||||
|
||||
require.NoError(t, n.Start(ctx))
|
||||
// wait for the node to produce a block
|
||||
tctx, cancel := context.WithTimeout(ctx, time.Second)
|
||||
tctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
blocksSub, err := n.EventBus().SubscribeWithArgs(tctx, pubsub.SubscribeArgs{
|
||||
ClientID: "node_test",
|
||||
Query: types.EventQueryNewBlock,
|
||||
Limit: 1000,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = blocksSub.Next(tctx)
|
||||
@@ -138,6 +139,8 @@ func TestNodeSetAppVersion(t *testing.T) {
|
||||
// create node
|
||||
n := getTestNode(ctx, t, cfg, logger)
|
||||
|
||||
require.NoError(t, n.Start(ctx))
|
||||
|
||||
// default config uses the kvstore app
|
||||
appVersion := kvstore.ProtocolVersion
|
||||
|
||||
@@ -624,7 +627,7 @@ func TestNodeSetEventSink(t *testing.T) {
|
||||
genDoc, err := types.GenesisDocFromFile(cfg.GenesisFile())
|
||||
require.NoError(t, err)
|
||||
|
||||
indexService, eventSinks, err := createAndStartIndexerService(ctx, cfg,
|
||||
indexService, eventSinks, err := createIndexerService(cfg,
|
||||
config.DefaultDBProvider, eventBus, logger, genDoc.ChainID,
|
||||
indexer.NopMetrics())
|
||||
require.NoError(t, err)
|
||||
|
||||
+2
-6
@@ -95,8 +95,7 @@ func initDBs(
|
||||
return blockStore, stateDB, makeCloser(closers), nil
|
||||
}
|
||||
|
||||
func createAndStartIndexerService(
|
||||
ctx context.Context,
|
||||
func createIndexerService(
|
||||
cfg *config.Config,
|
||||
dbProvider config.DBProvider,
|
||||
eventBus *eventbus.EventBus,
|
||||
@@ -116,10 +115,6 @@ func createAndStartIndexerService(
|
||||
Metrics: metrics,
|
||||
})
|
||||
|
||||
if err := indexerService.Start(ctx); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return indexerService, eventSinks, nil
|
||||
}
|
||||
|
||||
@@ -264,6 +259,7 @@ func createConsensusReactor(
|
||||
evidencePool,
|
||||
eventBus,
|
||||
consensus.StateMetrics(csMetrics),
|
||||
consensus.SkipStateStoreBootstrap,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
||||
@@ -76,7 +76,7 @@ message RequestBeginBlock {
|
||||
bytes hash = 1;
|
||||
tendermint.types.Header header = 2 [(gogoproto.nullable) = false];
|
||||
CommitInfo last_commit_info = 3 [(gogoproto.nullable) = false];
|
||||
repeated Evidence byzantine_validators = 4 [(gogoproto.nullable) = false];
|
||||
repeated Misbehavior byzantine_validators = 4 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
||||
enum CheckTxType {
|
||||
@@ -123,23 +123,31 @@ message RequestApplySnapshotChunk {
|
||||
}
|
||||
|
||||
message RequestPrepareProposal {
|
||||
bytes hash = 1;
|
||||
tendermint.types.Header header = 2 [(gogoproto.nullable) = false];
|
||||
// the modified transactions cannot exceed this size.
|
||||
int64 max_tx_bytes = 1;
|
||||
// txs is an array of transactions that will be included in a block,
|
||||
// sent to the app for possible modifications.
|
||||
repeated bytes txs = 3;
|
||||
ExtendedCommitInfo local_last_commit = 4 [(gogoproto.nullable) = false];
|
||||
repeated Evidence byzantine_validators = 5 [(gogoproto.nullable) = false];
|
||||
// the modified transactions cannot exceed this size.
|
||||
int64 max_tx_bytes = 6;
|
||||
repeated bytes txs = 2;
|
||||
ExtendedCommitInfo local_last_commit = 3 [(gogoproto.nullable) = false];
|
||||
repeated Misbehavior byzantine_validators = 4 [(gogoproto.nullable) = false];
|
||||
int64 height = 5;
|
||||
google.protobuf.Timestamp time = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
|
||||
bytes next_validators_hash = 7;
|
||||
// address of the public key of the validator proposing the block.
|
||||
bytes proposer_address = 8;
|
||||
}
|
||||
|
||||
message RequestProcessProposal {
|
||||
bytes hash = 1;
|
||||
tendermint.types.Header header = 2 [(gogoproto.nullable) = false];
|
||||
repeated bytes txs = 3;
|
||||
CommitInfo proposed_last_commit = 4 [(gogoproto.nullable) = false];
|
||||
repeated Evidence byzantine_validators = 5 [(gogoproto.nullable) = false];
|
||||
repeated bytes txs = 1;
|
||||
CommitInfo proposed_last_commit = 2 [(gogoproto.nullable) = false];
|
||||
repeated Misbehavior byzantine_validators = 3 [(gogoproto.nullable) = false];
|
||||
// hash is the merkle root hash of the fields of the proposed block.
|
||||
bytes hash = 4;
|
||||
int64 height = 5;
|
||||
google.protobuf.Timestamp time = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
|
||||
bytes next_validators_hash = 7;
|
||||
// address of the public key of the original proposer of the block.
|
||||
bytes proposer_address = 8;
|
||||
}
|
||||
|
||||
// Extends a vote with application-side injection
|
||||
@@ -157,11 +165,16 @@ message RequestVerifyVoteExtension {
|
||||
}
|
||||
|
||||
message RequestFinalizeBlock {
|
||||
bytes hash = 1;
|
||||
tendermint.types.Header header = 2 [(gogoproto.nullable) = false];
|
||||
repeated bytes txs = 3;
|
||||
CommitInfo decided_last_commit = 4 [(gogoproto.nullable) = false];
|
||||
repeated Evidence byzantine_validators = 5 [(gogoproto.nullable) = false];
|
||||
repeated bytes txs = 1;
|
||||
CommitInfo decided_last_commit = 2 [(gogoproto.nullable) = false];
|
||||
repeated Misbehavior byzantine_validators = 3 [(gogoproto.nullable) = false];
|
||||
// hash is the merkle root hash of the fields of the proposed block.
|
||||
bytes hash = 4;
|
||||
int64 height = 5;
|
||||
google.protobuf.Timestamp time = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
|
||||
bytes next_validators_hash = 7;
|
||||
// proposer_address is the address of the public key of the original proposer of the block.
|
||||
bytes proposer_address = 8;
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
@@ -341,6 +354,7 @@ message ResponseExtendVote {
|
||||
bytes vote_extension = 1;
|
||||
}
|
||||
|
||||
|
||||
message ResponseVerifyVoteExtension {
|
||||
VerifyStatus status = 1;
|
||||
|
||||
@@ -355,7 +369,7 @@ message ResponseFinalizeBlock {
|
||||
repeated Event events = 1
|
||||
[(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"];
|
||||
repeated ExecTxResult tx_results = 2;
|
||||
repeated ValidatorUpdate validator_updates = 3;
|
||||
repeated ValidatorUpdate validator_updates = 3 [(gogoproto.nullable) = false];
|
||||
tendermint.types.ConsensusParams consensus_param_updates = 4;
|
||||
bytes app_hash = 5;
|
||||
int64 retain_height = 6;
|
||||
@@ -408,10 +422,10 @@ message ExecTxResult {
|
||||
//
|
||||
// One usage is indexing transaction results.
|
||||
message TxResult {
|
||||
int64 height = 1;
|
||||
uint32 index = 2;
|
||||
bytes tx = 3;
|
||||
ResponseDeliverTx result = 4 [(gogoproto.nullable) = false];
|
||||
int64 height = 1;
|
||||
uint32 index = 2;
|
||||
bytes tx = 3;
|
||||
ExecTxResult result = 4 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
||||
message TxRecord {
|
||||
@@ -466,14 +480,15 @@ message CanonicalVoteExtension {
|
||||
bytes address = 5;
|
||||
}
|
||||
|
||||
enum EvidenceType {
|
||||
|
||||
enum MisbehaviorType {
|
||||
UNKNOWN = 0;
|
||||
DUPLICATE_VOTE = 1;
|
||||
LIGHT_CLIENT_ATTACK = 2;
|
||||
}
|
||||
|
||||
message Evidence {
|
||||
EvidenceType type = 1;
|
||||
message Misbehavior {
|
||||
MisbehaviorType type = 1;
|
||||
// The offending validator
|
||||
Validator validator = 2 [(gogoproto.nullable) = false];
|
||||
// The height when the offense occurred
|
||||
|
||||
@@ -77,7 +77,7 @@ message RequestBeginBlock {
|
||||
bytes hash = 1;
|
||||
tendermint.types.Header header = 2 [(gogoproto.nullable) = false];
|
||||
CommitInfo last_commit_info = 3 [(gogoproto.nullable) = false];
|
||||
repeated Evidence byzantine_validators = 4 [(gogoproto.nullable) = false];
|
||||
repeated Misbehavior byzantine_validators = 4 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
||||
enum CheckTxType {
|
||||
@@ -124,23 +124,31 @@ message RequestApplySnapshotChunk {
|
||||
}
|
||||
|
||||
message RequestPrepareProposal {
|
||||
bytes hash = 1;
|
||||
tendermint.types.Header header = 2 [(gogoproto.nullable) = false];
|
||||
// the modified transactions cannot exceed this size.
|
||||
int64 max_tx_bytes = 1;
|
||||
// txs is an array of transactions that will be included in a block,
|
||||
// sent to the app for possible modifications.
|
||||
repeated bytes txs = 3;
|
||||
ExtendedCommitInfo local_last_commit = 4 [(gogoproto.nullable) = false];
|
||||
repeated Evidence byzantine_validators = 5 [(gogoproto.nullable) = false];
|
||||
// the modified transactions cannot exceed this size.
|
||||
int64 max_tx_bytes = 6;
|
||||
repeated bytes txs = 2;
|
||||
ExtendedCommitInfo local_last_commit = 3 [(gogoproto.nullable) = false];
|
||||
repeated Misbehavior byzantine_validators = 4 [(gogoproto.nullable) = false];
|
||||
int64 height = 5;
|
||||
google.protobuf.Timestamp time = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
|
||||
bytes next_validators_hash = 7;
|
||||
// address of the public key of the validator proposing the block.
|
||||
bytes proposer_address = 8;
|
||||
}
|
||||
|
||||
message RequestProcessProposal {
|
||||
bytes hash = 1;
|
||||
tendermint.types.Header header = 2 [(gogoproto.nullable) = false];
|
||||
repeated bytes txs = 3;
|
||||
CommitInfo proposed_last_commit = 4 [(gogoproto.nullable) = false];
|
||||
repeated Evidence byzantine_validators = 5 [(gogoproto.nullable) = false];
|
||||
repeated bytes txs = 1;
|
||||
CommitInfo proposed_last_commit = 2 [(gogoproto.nullable) = false];
|
||||
repeated Misbehavior byzantine_validators = 3 [(gogoproto.nullable) = false];
|
||||
// hash is the merkle root hash of the fields of the proposed block.
|
||||
bytes hash = 4;
|
||||
int64 height = 5;
|
||||
google.protobuf.Timestamp time = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
|
||||
bytes next_validators_hash = 7;
|
||||
// address of the public key of the original proposer of the block.
|
||||
bytes proposer_address = 8;
|
||||
}
|
||||
|
||||
// Extends a vote with application-side injection
|
||||
@@ -154,11 +162,16 @@ message RequestVerifyVoteExtension {
|
||||
}
|
||||
|
||||
message RequestFinalizeBlock {
|
||||
bytes hash = 1;
|
||||
tendermint.types.Header header = 2 [(gogoproto.nullable) = false];
|
||||
repeated bytes txs = 3;
|
||||
CommitInfo decided_last_commit = 4 [(gogoproto.nullable) = false];
|
||||
repeated Evidence byzantine_validators = 5 [(gogoproto.nullable) = false];
|
||||
repeated bytes txs = 1;
|
||||
CommitInfo decided_last_commit = 2 [(gogoproto.nullable) = false];
|
||||
repeated Misbehavior byzantine_validators = 3 [(gogoproto.nullable) = false];
|
||||
// hash is the merkle root hash of the fields of the proposed block.
|
||||
bytes hash = 4;
|
||||
int64 height = 5;
|
||||
google.protobuf.Timestamp time = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
|
||||
bytes next_validators_hash = 7;
|
||||
// proposer_address is the address of the public key of the original proposer of the block.
|
||||
bytes proposer_address = 8;
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
@@ -454,14 +467,14 @@ message ExtendedVoteInfo {
|
||||
bytes vote_extension = 3;
|
||||
}
|
||||
|
||||
enum EvidenceType {
|
||||
enum MisbehaviorType {
|
||||
UNKNOWN = 0;
|
||||
DUPLICATE_VOTE = 1;
|
||||
LIGHT_CLIENT_ATTACK = 2;
|
||||
}
|
||||
|
||||
message Evidence {
|
||||
EvidenceType type = 1;
|
||||
message Misbehavior {
|
||||
MisbehaviorType type = 1;
|
||||
// The offending validator
|
||||
Validator validator = 2 [(gogoproto.nullable) = false];
|
||||
// The height when the offense occurred
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
syntax = "proto3";
|
||||
package tendermint.privval;
|
||||
option go_package = "github.com/tendermint/tendermint/proto/tendermint/privval";
|
||||
option go_package = "github.com/tendermint/tendermint/proto/tendermint/privval";
|
||||
|
||||
import "tendermint/privval/types.proto";
|
||||
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
// Program condiff performs a keyspace diff on two TOML documents.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/creachadair/tomledit"
|
||||
"github.com/creachadair/tomledit/parser"
|
||||
"github.com/creachadair/tomledit/transform"
|
||||
)
|
||||
|
||||
var (
|
||||
doDesnake = flag.Bool("desnake", false, "Convert snake_case to kebab-case before comparing")
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintf(os.Stderr, `Usage: %[1]s [options] f1 f2
|
||||
|
||||
Diff the keyspaces of the TOML documents in files f1 and f2.
|
||||
The output prints one line per key that differs:
|
||||
|
||||
-S name -- section exists in f1 but not f2
|
||||
+S name -- section exists in f2 but not f1
|
||||
-M name -- mapping exists in f1 but not f2
|
||||
+M name -- mapping exists in f2 but not f1
|
||||
|
||||
Comments, order, and values are ignored for comparison purposes.
|
||||
|
||||
Options:
|
||||
`, filepath.Base(os.Args[0]))
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
if flag.NArg() != 2 {
|
||||
log.Fatalf("Usage: %[1]s <lhs> <rhs>", filepath.Base(os.Args[0]))
|
||||
}
|
||||
lhs := mustParse(flag.Arg(0))
|
||||
rhs := mustParse(flag.Arg(1))
|
||||
if *doDesnake {
|
||||
log.Printf("Converting all names from snake_case to kebab-case")
|
||||
fix := transform.SnakeToKebab()
|
||||
_ = fix(context.Background(), lhs)
|
||||
_ = fix(context.Background(), rhs)
|
||||
}
|
||||
diffDocs(os.Stdout, lhs, rhs)
|
||||
}
|
||||
|
||||
func mustParse(path string) *tomledit.Document {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
log.Fatalf("Opening TOML input: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
doc, err := tomledit.Parse(f)
|
||||
if err != nil {
|
||||
log.Fatalf("Parsing %q: %v", path, err)
|
||||
}
|
||||
return doc
|
||||
}
|
||||
|
||||
func allKeys(s *tomledit.Section) []string {
|
||||
var keys []string
|
||||
s.Scan(func(key parser.Key, _ *tomledit.Entry) bool {
|
||||
keys = append(keys, key.String())
|
||||
return true
|
||||
})
|
||||
return keys
|
||||
}
|
||||
|
||||
const (
|
||||
delSection = "-S"
|
||||
delMapping = "-M"
|
||||
addSection = "+S"
|
||||
addMapping = "+M"
|
||||
|
||||
delMapSep = "\n" + delMapping + " "
|
||||
addMapSep = "\n" + addMapping + " "
|
||||
)
|
||||
|
||||
func diffDocs(w io.Writer, lhs, rhs *tomledit.Document) {
|
||||
diffSections(w, lhs.Global, rhs.Global)
|
||||
lsec, rsec := lhs.Sections, rhs.Sections
|
||||
transform.SortSectionsByName(lsec)
|
||||
transform.SortSectionsByName(rsec)
|
||||
|
||||
i, j := 0, 0
|
||||
for i < len(lsec) && j < len(rsec) {
|
||||
if lsec[i].Name.Before(rsec[j].Name) {
|
||||
fmt.Fprintln(w, delSection, lsec[i].Name)
|
||||
fmt.Fprintln(w, delMapping, strings.Join(allKeys(lsec[i]), delMapSep))
|
||||
i++
|
||||
} else if rsec[j].Name.Before(lsec[i].Name) {
|
||||
fmt.Fprintln(w, addSection, rsec[j].Name)
|
||||
fmt.Fprintln(w, addMapping, strings.Join(allKeys(rsec[j]), addMapSep))
|
||||
j++
|
||||
} else {
|
||||
diffSections(w, lsec[i], rsec[j])
|
||||
i++
|
||||
j++
|
||||
}
|
||||
}
|
||||
for ; i < len(lsec); i++ {
|
||||
fmt.Fprintln(w, delSection, lsec[i].Name)
|
||||
fmt.Fprintln(w, delMapping, strings.Join(allKeys(lsec[i]), delMapSep))
|
||||
}
|
||||
for ; j < len(rsec); j++ {
|
||||
fmt.Fprintln(w, addSection, rsec[j].Name)
|
||||
fmt.Fprintln(w, addMapping, strings.Join(allKeys(rsec[j]), addMapSep))
|
||||
}
|
||||
}
|
||||
|
||||
func diffSections(w io.Writer, lhs, rhs *tomledit.Section) {
|
||||
diffKeys(w, allKeys(lhs), allKeys(rhs))
|
||||
}
|
||||
|
||||
func diffKeys(w io.Writer, lhs, rhs []string) {
|
||||
sort.Strings(lhs)
|
||||
sort.Strings(rhs)
|
||||
|
||||
i, j := 0, 0
|
||||
for i < len(lhs) && j < len(rhs) {
|
||||
if lhs[i] < rhs[j] {
|
||||
fmt.Fprintln(w, delMapping, lhs[i])
|
||||
i++
|
||||
} else if lhs[i] > rhs[j] {
|
||||
fmt.Fprintln(w, addMapping, rhs[j])
|
||||
j++
|
||||
} else {
|
||||
i++
|
||||
j++
|
||||
}
|
||||
}
|
||||
for ; i < len(lhs); i++ {
|
||||
fmt.Fprintln(w, delMapping, lhs[i])
|
||||
}
|
||||
for ; j < len(rhs); j++ {
|
||||
fmt.Fprintln(w, addMapping, rhs[j])
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
// Program confix applies fixes to a Tendermint TOML configuration file to
|
||||
// update a file created with an older version of Tendermint to a compatible
|
||||
// format for a newer version.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/creachadair/atomicfile"
|
||||
"github.com/creachadair/tomledit"
|
||||
"github.com/creachadair/tomledit/parser"
|
||||
"github.com/creachadair/tomledit/transform"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/tendermint/tendermint/config"
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintf(os.Stderr, `Usage: %[1]s -config <src> [-out <dst>]
|
||||
|
||||
Modify the contents of the specified -config TOML file to update the names,
|
||||
locations, and values of configuration settings to the current configuration
|
||||
layout. The output is written to -out, or to stdout.
|
||||
|
||||
It is valid to set -config and -out to the same path. In that case, the file will
|
||||
be modified in-place. In case of any error in updating the file, no output is
|
||||
written.
|
||||
|
||||
Options:
|
||||
`, filepath.Base(os.Args[0]))
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
configPath = flag.String("config", "", "Config file path (required)")
|
||||
outPath = flag.String("out", "", "Output file path (default stdout)")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if *configPath == "" {
|
||||
log.Fatal("You must specify a non-empty -config path")
|
||||
}
|
||||
|
||||
doc, err := LoadConfig(*configPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Loading config: %v", err)
|
||||
}
|
||||
|
||||
ctx := transform.WithLogWriter(context.Background(), os.Stderr)
|
||||
if err := ApplyFixes(ctx, doc); err != nil {
|
||||
log.Fatalf("Updating %q: %v", *configPath, err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := tomledit.Format(&buf, doc); err != nil {
|
||||
log.Fatalf("Formatting config: %v", err)
|
||||
}
|
||||
|
||||
// Verify that Tendermint can parse the results after our edits.
|
||||
if err := CheckValid(buf.Bytes()); err != nil {
|
||||
log.Fatalf("Updated config is invalid: %v", err)
|
||||
}
|
||||
|
||||
if *outPath == "" {
|
||||
os.Stdout.Write(buf.Bytes())
|
||||
} else if err := atomicfile.WriteData(*outPath, buf.Bytes(), 0600); err != nil {
|
||||
log.Fatalf("Writing output: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
var plan = transform.Plan{
|
||||
{
|
||||
// Since https://github.com/tendermint/tendermint/pull/5777.
|
||||
Desc: "Rename everything from snake_case to kebab-case",
|
||||
T: transform.SnakeToKebab(),
|
||||
},
|
||||
{
|
||||
// [fastsync] renamed in https://github.com/tendermint/tendermint/pull/6896.
|
||||
// [blocksync] removed in https://github.com/tendermint/tendermint/pull/7159.
|
||||
Desc: "Remove [fastsync] and [blocksync] sections",
|
||||
T: transform.Func(func(_ context.Context, doc *tomledit.Document) error {
|
||||
doc.First("fast-sync").Remove()
|
||||
transform.FindTable(doc, "fastsync").Remove()
|
||||
transform.FindTable(doc, "blocksync").Remove()
|
||||
return nil
|
||||
}),
|
||||
ErrorOK: true,
|
||||
},
|
||||
{
|
||||
// Since https://github.com/tendermint/tendermint/pull/6241.
|
||||
Desc: `Add top-level mode setting (default "full")`,
|
||||
T: transform.EnsureKey(nil, &parser.KeyValue{
|
||||
Block: parser.Comments{"Mode of Node: full | validator | seed"},
|
||||
Name: parser.Key{"mode"},
|
||||
Value: parser.MustValue(`"full"`),
|
||||
}),
|
||||
ErrorOK: true,
|
||||
},
|
||||
{
|
||||
// Since https://github.com/tendermint/tendermint/pull/7121.
|
||||
Desc: "Remove gRPC settings from the [rpc] section",
|
||||
T: transform.Func(func(_ context.Context, doc *tomledit.Document) error {
|
||||
doc.First("rpc", "grpc-laddr").Remove()
|
||||
doc.First("rpc", "grpc-max-open-connections").Remove()
|
||||
return nil
|
||||
}),
|
||||
},
|
||||
{
|
||||
// Since https://github.com/tendermint/tendermint/pull/8217.
|
||||
Desc: "Remove per-node consensus timeouts (converted to consensus parameters)",
|
||||
T: transform.Remove(
|
||||
parser.Key{"consensus", "skip-timeout-commit"},
|
||||
parser.Key{"consensus", "timeout-commit"},
|
||||
parser.Key{"consensus", "timeout-precommit"},
|
||||
parser.Key{"consensus", "timeout-precommit-delta"},
|
||||
parser.Key{"consensus", "timeout-prevote"},
|
||||
parser.Key{"consensus", "timeout-prevote-delta"},
|
||||
parser.Key{"consensus", "timeout-propose"},
|
||||
parser.Key{"consensus", "timeout-propose-delta"},
|
||||
),
|
||||
ErrorOK: true,
|
||||
},
|
||||
{
|
||||
// Removed wal-dir: https://github.com/tendermint/tendermint/pull/6396.
|
||||
// Removed version: https://github.com/tendermint/tendermint/pull/7171.
|
||||
Desc: "Remove vestigial mempool.wal-dir settings",
|
||||
T: transform.Remove(
|
||||
parser.Key{"mempool", "wal-dir"},
|
||||
parser.Key{"mempool", "version"},
|
||||
),
|
||||
ErrorOK: true,
|
||||
},
|
||||
{
|
||||
// Since https://github.com/tendermint/tendermint/pull/6323.
|
||||
Desc: "Add new [p2p] queue-type setting",
|
||||
T: transform.EnsureKey(parser.Key{"p2p"}, &parser.KeyValue{
|
||||
Block: parser.Comments{"Select the p2p internal queue"},
|
||||
Name: parser.Key{"queue-type"},
|
||||
Value: parser.MustValue(`"priority"`),
|
||||
}),
|
||||
ErrorOK: true,
|
||||
},
|
||||
{
|
||||
// Since https://github.com/tendermint/tendermint/pull/6353.
|
||||
Desc: "Add [p2p] connection count and rate limit settings",
|
||||
T: transform.Func(func(_ context.Context, doc *tomledit.Document) error {
|
||||
tab := transform.FindTable(doc, "p2p")
|
||||
if tab == nil {
|
||||
return errors.New("p2p table not found")
|
||||
}
|
||||
transform.InsertMapping(tab.Section, &parser.KeyValue{
|
||||
Block: parser.Comments{"Maximum number of connections (inbound and outbound)."},
|
||||
Name: parser.Key{"max-connections"},
|
||||
Value: parser.MustValue("64"),
|
||||
}, false)
|
||||
transform.InsertMapping(tab.Section, &parser.KeyValue{
|
||||
Block: parser.Comments{
|
||||
"Rate limits the number of incoming connection attempts per IP address.",
|
||||
},
|
||||
Name: parser.Key{"max-incoming-connection-attempts"},
|
||||
Value: parser.MustValue("100"),
|
||||
}, false)
|
||||
return nil
|
||||
}),
|
||||
},
|
||||
{
|
||||
// Added "chunk-fetchers" https://github.com/tendermint/tendermint/pull/6566.
|
||||
// This value was backported into v0.34.11 (modulo casing).
|
||||
// Renamed to "fetchers" https://github.com/tendermint/tendermint/pull/6587.
|
||||
Desc: "Rename statesync.chunk-fetchers to statesync.fetchers",
|
||||
T: transform.Func(func(ctx context.Context, doc *tomledit.Document) error {
|
||||
// If the key already exists, rename it preserving its value.
|
||||
if found := doc.First("statesync", "chunk-fetchers"); found != nil {
|
||||
found.KeyValue.Name = parser.Key{"fetchers"}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Otherwise, add it.
|
||||
return transform.EnsureKey(parser.Key{"statesync"}, &parser.KeyValue{
|
||||
Block: parser.Comments{
|
||||
"The number of concurrent chunk and block fetchers to run (default: 4).",
|
||||
},
|
||||
Name: parser.Key{"fetchers"},
|
||||
Value: parser.MustValue("4"),
|
||||
})(ctx, doc)
|
||||
}),
|
||||
},
|
||||
{
|
||||
// Since https://github.com/tendermint/tendermint/pull/6807.
|
||||
// Backported into v0.34.13 (modulo casing).
|
||||
Desc: "Add statesync.use-p2p setting",
|
||||
T: transform.EnsureKey(parser.Key{"statesync"}, &parser.KeyValue{
|
||||
Block: parser.Comments{
|
||||
"# State sync uses light client verification to verify state. This can be done either through the",
|
||||
"# P2P layer or RPC layer. Set this to true to use the P2P layer. If false (default), RPC layer",
|
||||
"# will be used.",
|
||||
},
|
||||
Name: parser.Key{"use-p2p"},
|
||||
Value: parser.MustValue("false"),
|
||||
}),
|
||||
},
|
||||
{
|
||||
// Since https://github.com/tendermint/tendermint/pull/6462.
|
||||
Desc: "Move priv-validator settings under [priv-validator]",
|
||||
T: transform.Func(func(_ context.Context, doc *tomledit.Document) error {
|
||||
const pvPrefix = "priv-validator-"
|
||||
|
||||
var found []*tomledit.Entry
|
||||
doc.Scan(func(key parser.Key, e *tomledit.Entry) bool {
|
||||
if e.IsSection() && !e.IsGlobal() {
|
||||
return false // no more candidates
|
||||
} else if len(key) == 1 && strings.HasPrefix(key[0], pvPrefix) {
|
||||
found = append(found, e)
|
||||
}
|
||||
return true
|
||||
})
|
||||
if len(found) == 0 {
|
||||
return nil // nothing to do
|
||||
}
|
||||
|
||||
// Now that we know we have work to do, find the target table.
|
||||
var sec *tomledit.Section
|
||||
if dst := transform.FindTable(doc, "priv-validator"); dst == nil {
|
||||
// If the table doesn't exist, create it. Old config files
|
||||
// probably will not have it, so plug in the comment too.
|
||||
sec = &tomledit.Section{
|
||||
Heading: &parser.Heading{
|
||||
Block: parser.Comments{
|
||||
"#######################################################",
|
||||
"### Priv Validator Configuration ###",
|
||||
"#######################################################",
|
||||
},
|
||||
Name: parser.Key{"priv-validator"},
|
||||
},
|
||||
}
|
||||
doc.Sections = append(doc.Sections, sec)
|
||||
} else {
|
||||
sec = dst.Section
|
||||
}
|
||||
|
||||
for _, e := range found {
|
||||
e.Remove()
|
||||
e.Name = parser.Key{strings.TrimPrefix(e.Name[0], pvPrefix)}
|
||||
sec.Items = append(sec.Items, e.KeyValue)
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
// ApplyFixes transforms doc and reports whether it succeeded.
|
||||
func ApplyFixes(ctx context.Context, doc *tomledit.Document) error {
|
||||
// Check what version of Tendermint might have created this config file, as
|
||||
// a safety check for the updates we are about to make.
|
||||
tmVersion := GuessConfigVersion(doc)
|
||||
if tmVersion == vUnknown {
|
||||
return errors.New("cannot tell what Tendermint version created this config")
|
||||
} else if tmVersion < v34 || tmVersion > v36 {
|
||||
// TODO(creachadair): Add in rewrites for older versions. This will
|
||||
// require some digging to discover what the changes were. The upgrade
|
||||
// instructions do not give specifics.
|
||||
return fmt.Errorf("unable to update version %s config", tmVersion)
|
||||
}
|
||||
return plan.Apply(ctx, doc)
|
||||
}
|
||||
|
||||
// LoadConfig loads and parses the TOML document from path.
|
||||
func LoadConfig(path string) (*tomledit.Document, error) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
return tomledit.Parse(f)
|
||||
}
|
||||
|
||||
const (
|
||||
vUnknown = ""
|
||||
v32 = "v0.32"
|
||||
v33 = "v0.33"
|
||||
v34 = "v0.34"
|
||||
v35 = "v0.35"
|
||||
v36 = "v0.36"
|
||||
)
|
||||
|
||||
// GuessConfigVersion attempts to figure out which version of Tendermint
|
||||
// created the specified config document. It returns "" if the creating version
|
||||
// cannot be determined, otherwise a string of the form "vX.YY".
|
||||
func GuessConfigVersion(doc *tomledit.Document) string {
|
||||
hasDisableWS := doc.First("rpc", "experimental-disable-websocket") != nil
|
||||
hasUseLegacy := doc.First("p2p", "use-legacy") != nil // v0.35 only
|
||||
if hasDisableWS && !hasUseLegacy {
|
||||
return v36
|
||||
}
|
||||
|
||||
hasBlockSync := transform.FindTable(doc, "blocksync") != nil // add: v0.35
|
||||
hasStateSync := transform.FindTable(doc, "statesync") != nil // add: v0.34
|
||||
if hasBlockSync && hasStateSync {
|
||||
return v35
|
||||
} else if hasStateSync {
|
||||
return v34
|
||||
}
|
||||
|
||||
hasIndexKeys := doc.First("tx_index", "index_keys") != nil // add: v0.33
|
||||
hasIndexTags := doc.First("tx_index", "index_tags") != nil // rem: v0.33
|
||||
if hasIndexKeys && !hasIndexTags {
|
||||
return v33
|
||||
}
|
||||
|
||||
hasFastSync := transform.FindTable(doc, "fastsync") != nil // add: v0.32
|
||||
if hasIndexTags && hasFastSync {
|
||||
return v32
|
||||
}
|
||||
|
||||
// Something older, probably.
|
||||
return vUnknown
|
||||
}
|
||||
|
||||
// CheckValid checks whether the specified config appears to be a valid
|
||||
// Tendermint config file. This emulates how the node loads the config.
|
||||
func CheckValid(data []byte) error {
|
||||
v := viper.New()
|
||||
v.SetConfigType("toml")
|
||||
|
||||
if err := v.ReadConfig(bytes.NewReader(data)); err != nil {
|
||||
return fmt.Errorf("reading config: %w", err)
|
||||
}
|
||||
|
||||
var cfg config.Config
|
||||
if err := v.Unmarshal(&cfg); err != nil {
|
||||
return fmt.Errorf("decoding config: %w", err)
|
||||
}
|
||||
|
||||
return cfg.ValidateBasic()
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package main_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/creachadair/tomledit"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
||||
confix "github.com/tendermint/tendermint/scripts/confix"
|
||||
)
|
||||
|
||||
func mustParseConfig(t *testing.T, path string) *tomledit.Document {
|
||||
doc, err := confix.LoadConfig(path)
|
||||
if err != nil {
|
||||
t.Fatalf("Loading config: %v", err)
|
||||
}
|
||||
return doc
|
||||
}
|
||||
|
||||
func TestGuessConfigVersion(t *testing.T) {
|
||||
tests := []struct {
|
||||
path, want string
|
||||
}{
|
||||
{"testdata/non-config.toml", ""},
|
||||
{"testdata/v31-config.toml", ""},
|
||||
{"testdata/v32-config.toml", "v0.32"},
|
||||
{"testdata/v33-config.toml", "v0.33"},
|
||||
{"testdata/v34-config.toml", "v0.34"},
|
||||
{"testdata/v35-config.toml", "v0.35"},
|
||||
{"testdata/v36-config.toml", "v0.36"},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.path, func(t *testing.T) {
|
||||
got := confix.GuessConfigVersion(mustParseConfig(t, test.path))
|
||||
if got != test.want {
|
||||
t.Errorf("Wrong version: got %q, want %q", got, test.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyFixes(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
t.Run("Unknown", func(t *testing.T) {
|
||||
err := confix.ApplyFixes(ctx, mustParseConfig(t, "testdata/v31-config.toml"))
|
||||
if err == nil || !strings.Contains(err.Error(), "cannot tell what Tendermint version") {
|
||||
t.Error("ApplyFixes succeeded, but should have failed for an unknown version")
|
||||
}
|
||||
})
|
||||
t.Run("TooOld", func(t *testing.T) {
|
||||
err := confix.ApplyFixes(ctx, mustParseConfig(t, "testdata/v33-config.toml"))
|
||||
if err == nil || !strings.Contains(err.Error(), "unable to update version v0.33 config") {
|
||||
t.Errorf("ApplyFixes: got %v, want version error", err)
|
||||
}
|
||||
})
|
||||
t.Run("OK", func(t *testing.T) {
|
||||
doc := mustParseConfig(t, "testdata/v34-config.toml")
|
||||
if err := confix.ApplyFixes(ctx, doc); err != nil {
|
||||
t.Fatalf("ApplyFixes: unexpected error: %v", err)
|
||||
}
|
||||
|
||||
t.Run("Fixpoint", func(t *testing.T) {
|
||||
// Verify that reapplying fixes to the same config succeeds, and does not
|
||||
// make any additional changes.
|
||||
var before bytes.Buffer
|
||||
if err := tomledit.Format(&before, doc); err != nil {
|
||||
t.Fatalf("Formatting document: %v", err)
|
||||
}
|
||||
if err := confix.CheckValid(before.Bytes()); err != nil {
|
||||
t.Fatalf("Validating output: %v", err)
|
||||
}
|
||||
want := before.String()
|
||||
|
||||
// Re-parse the output from the first round of transformations.
|
||||
doc2, err := tomledit.Parse(&before)
|
||||
if err != nil {
|
||||
t.Fatalf("Parsing fixed output: %v", err)
|
||||
}
|
||||
if err := confix.ApplyFixes(ctx, doc2); err != nil {
|
||||
t.Fatalf("ApplyFixes: unexpected error: %v", err)
|
||||
}
|
||||
|
||||
var after bytes.Buffer
|
||||
if err := tomledit.Format(&after, doc2); err != nil {
|
||||
t.Fatalf("Formatting document: %v", err)
|
||||
}
|
||||
got := after.String()
|
||||
|
||||
if diff := cmp.Diff(want, got); diff != "" {
|
||||
t.Errorf("Reapplied fixes changed something: (-want, +got)\n%s", diff)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
+S fastsync
|
||||
+M fastsync.version
|
||||
+M mempool.max-tx-bytes
|
||||
+M rpc.max-body-bytes
|
||||
+M rpc.max-header-bytes
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
+M p2p.persistent-peers-max-dial-period
|
||||
+M p2p.unconditional-peer-ids
|
||||
+M tx-index.index-all-keys
|
||||
-M tx-index.index-all-tags
|
||||
+M tx-index.index-keys
|
||||
-M tx-index.index-tags
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
-M prof-laddr
|
||||
+M consensus.double-sign-check-height
|
||||
+M mempool.keep-invalid-txs-in-cache
|
||||
+M mempool.max-batch-bytes
|
||||
+M rpc.experimental-close-on-slow-client
|
||||
+M rpc.experimental-subscription-buffer-size
|
||||
+M rpc.experimental-websocket-write-buffer-size
|
||||
+M rpc.pprof-laddr
|
||||
+S statesync
|
||||
+M statesync.enable
|
||||
+M statesync.rpc-servers
|
||||
+M statesync.trust-height
|
||||
+M statesync.trust-hash
|
||||
+M statesync.trust-period
|
||||
+M statesync.discovery-time
|
||||
+M statesync.temp-dir
|
||||
+M statesync.chunk-request-timeout
|
||||
+M statesync.chunk-fetchers
|
||||
-M tx-index.index-all-keys
|
||||
-M tx-index.index-keys
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
-M fast-sync
|
||||
+M mode
|
||||
-M priv-validator-key-file
|
||||
-M priv-validator-laddr
|
||||
-M priv-validator-state-file
|
||||
+S blocksync
|
||||
+M blocksync.enable
|
||||
+M blocksync.version
|
||||
-S fastsync
|
||||
-M fastsync.version
|
||||
+M mempool.ttl-duration
|
||||
+M mempool.ttl-num-blocks
|
||||
+M mempool.version
|
||||
-M mempool.wal-dir
|
||||
+M p2p.bootstrap-peers
|
||||
+M p2p.max-connections
|
||||
+M p2p.max-incoming-connection-attempts
|
||||
+M p2p.queue-type
|
||||
-M p2p.seed-mode
|
||||
+M p2p.use-legacy
|
||||
+S priv-validator
|
||||
+M priv-validator.key-file
|
||||
+M priv-validator.state-file
|
||||
+M priv-validator.laddr
|
||||
+M priv-validator.client-certificate-file
|
||||
+M priv-validator.client-key-file
|
||||
+M priv-validator.root-ca-file
|
||||
-M statesync.chunk-fetchers
|
||||
+M statesync.fetchers
|
||||
+M statesync.use-p2p
|
||||
+M tx-index.psql-conn
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
-S blocksync
|
||||
-M blocksync.enable
|
||||
-M blocksync.version
|
||||
-M consensus.skip-timeout-commit
|
||||
-M consensus.timeout-commit
|
||||
-M consensus.timeout-precommit
|
||||
-M consensus.timeout-precommit-delta
|
||||
-M consensus.timeout-prevote
|
||||
-M consensus.timeout-prevote-delta
|
||||
-M consensus.timeout-propose
|
||||
-M consensus.timeout-propose-delta
|
||||
-M mempool.version
|
||||
-M p2p.addr-book-file
|
||||
-M p2p.addr-book-strict
|
||||
-M p2p.max-num-inbound-peers
|
||||
-M p2p.max-num-outbound-peers
|
||||
-M p2p.persistent-peers-max-dial-period
|
||||
-M p2p.unconditional-peer-ids
|
||||
-M p2p.use-legacy
|
||||
+M rpc.event-log-max-items
|
||||
+M rpc.event-log-window-size
|
||||
-M rpc.experimental-close-on-slow-client
|
||||
+M rpc.experimental-disable-websocket
|
||||
-M rpc.experimental-subscription-buffer-size
|
||||
-M rpc.experimental-websocket-write-buffer-size
|
||||
-M rpc.grpc-laddr
|
||||
-M rpc.grpc-max-open-connections
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
# This is not a Tendermint config file.
|
||||
|
||||
[ test ]
|
||||
key = 'value'
|
||||
|
||||
# Nothing to see here, move along.
|
||||
+292
@@ -0,0 +1,292 @@
|
||||
# This is a TOML config file.
|
||||
# For more information, see https://github.com/toml-lang/toml
|
||||
|
||||
##### main base config options #####
|
||||
|
||||
# TCP or UNIX socket address of the ABCI application,
|
||||
# or the name of an ABCI application compiled in with the Tendermint binary
|
||||
proxy_app = "tcp://127.0.0.1:26658"
|
||||
|
||||
# A custom human readable name for this node
|
||||
moniker = "localhost"
|
||||
|
||||
# If this node is many blocks behind the tip of the chain, FastSync
|
||||
# allows them to catchup quickly by downloading blocks in parallel
|
||||
# and verifying their commits
|
||||
fast_sync = true
|
||||
|
||||
# Database backend: goleveldb | cleveldb | boltdb
|
||||
# * goleveldb (github.com/syndtr/goleveldb - most popular implementation)
|
||||
# - pure go
|
||||
# - stable
|
||||
# * cleveldb (uses levigo wrapper)
|
||||
# - fast
|
||||
# - requires gcc
|
||||
# - use cleveldb build tag (go build -tags cleveldb)
|
||||
# * boltdb (uses etcd's fork of bolt - github.com/etcd-io/bbolt)
|
||||
# - EXPERIMENTAL
|
||||
# - may be faster is some use-cases (random reads - indexer)
|
||||
# - use boltdb build tag (go build -tags boltdb)
|
||||
db_backend = "goleveldb"
|
||||
|
||||
# Database directory
|
||||
db_dir = "data"
|
||||
|
||||
# Output level for logging, including package level options
|
||||
log_level = "main:info,state:info,*:error"
|
||||
|
||||
# Output format: 'plain' (colored text) or 'json'
|
||||
log_format = "plain"
|
||||
|
||||
##### additional base config options #####
|
||||
|
||||
# Path to the JSON file containing the initial validator set and other meta data
|
||||
genesis_file = "config/genesis.json"
|
||||
|
||||
# Path to the JSON file containing the private key to use as a validator in the consensus protocol
|
||||
priv_validator_key_file = "config/priv_validator_key.json"
|
||||
|
||||
# Path to the JSON file containing the last sign state of a validator
|
||||
priv_validator_state_file = "data/priv_validator_state.json"
|
||||
|
||||
# TCP or UNIX socket address for Tendermint to listen on for
|
||||
# connections from an external PrivValidator process
|
||||
priv_validator_laddr = ""
|
||||
|
||||
# Path to the JSON file containing the private key to use for node authentication in the p2p protocol
|
||||
node_key_file = "config/node_key.json"
|
||||
|
||||
# Mechanism to connect to the ABCI application: socket | grpc
|
||||
abci = "socket"
|
||||
|
||||
# TCP or UNIX socket address for the profiling server to listen on
|
||||
prof_laddr = ""
|
||||
|
||||
# If true, query the ABCI app on connecting to a new peer
|
||||
# so the app can decide if we should keep the connection or not
|
||||
filter_peers = false
|
||||
|
||||
##### advanced configuration options #####
|
||||
|
||||
##### rpc server configuration options #####
|
||||
[rpc]
|
||||
|
||||
# TCP or UNIX socket address for the RPC server to listen on
|
||||
laddr = "tcp://0.0.0.0:26657"
|
||||
|
||||
# A list of origins a cross-domain request can be executed from
|
||||
# Default value '[]' disables cors support
|
||||
# Use '["*"]' to allow any origin
|
||||
cors_allowed_origins = []
|
||||
|
||||
# A list of methods the client is allowed to use with cross-domain requests
|
||||
cors_allowed_methods = ["HEAD", "GET", "POST", ]
|
||||
|
||||
# A list of non simple headers the client is allowed to use with cross-domain requests
|
||||
cors_allowed_headers = ["Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time", ]
|
||||
|
||||
# TCP or UNIX socket address for the gRPC server to listen on
|
||||
# NOTE: This server only supports /broadcast_tx_commit
|
||||
grpc_laddr = ""
|
||||
|
||||
# Maximum number of simultaneous connections.
|
||||
# Does not include RPC (HTTP&WebSocket) connections. See max_open_connections
|
||||
# If you want to accept a larger number than the default, make sure
|
||||
# you increase your OS limits.
|
||||
# 0 - unlimited.
|
||||
# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files}
|
||||
# 1024 - 40 - 10 - 50 = 924 = ~900
|
||||
grpc_max_open_connections = 900
|
||||
|
||||
# Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool
|
||||
unsafe = false
|
||||
|
||||
# Maximum number of simultaneous connections (including WebSocket).
|
||||
# Does not include gRPC connections. See grpc_max_open_connections
|
||||
# If you want to accept a larger number than the default, make sure
|
||||
# you increase your OS limits.
|
||||
# 0 - unlimited.
|
||||
# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files}
|
||||
# 1024 - 40 - 10 - 50 = 924 = ~900
|
||||
max_open_connections = 900
|
||||
|
||||
# Maximum number of unique clientIDs that can /subscribe
|
||||
# If you're using /broadcast_tx_commit, set to the estimated maximum number
|
||||
# of broadcast_tx_commit calls per block.
|
||||
max_subscription_clients = 100
|
||||
|
||||
# Maximum number of unique queries a given client can /subscribe to
|
||||
# If you're using GRPC (or Local RPC client) and /broadcast_tx_commit, set to
|
||||
# the estimated # maximum number of broadcast_tx_commit calls per block.
|
||||
max_subscriptions_per_client = 5
|
||||
|
||||
# How long to wait for a tx to be committed during /broadcast_tx_commit.
|
||||
# WARNING: Using a value larger than 10s will result in increasing the
|
||||
# global HTTP write timeout, which applies to all connections and endpoints.
|
||||
# See https://github.com/tendermint/tendermint/issues/3435
|
||||
timeout_broadcast_tx_commit = "10s"
|
||||
|
||||
# The name of a file containing certificate that is used to create the HTTPS server.
|
||||
# If the certificate is signed by a certificate authority,
|
||||
# the certFile should be the concatenation of the server's certificate, any intermediates,
|
||||
# and the CA's certificate.
|
||||
# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server. Otherwise, HTTP server is run.
|
||||
tls_cert_file = ""
|
||||
|
||||
# The name of a file containing matching private key that is used to create the HTTPS server.
|
||||
# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server. Otherwise, HTTP server is run.
|
||||
tls_key_file = ""
|
||||
|
||||
##### peer to peer configuration options #####
|
||||
[p2p]
|
||||
|
||||
# Address to listen for incoming connections
|
||||
laddr = "tcp://0.0.0.0:26656"
|
||||
|
||||
# Address to advertise to peers for them to dial
|
||||
# If empty, will use the same port as the laddr,
|
||||
# and will introspect on the listener or use UPnP
|
||||
# to figure out the address.
|
||||
external_address = ""
|
||||
|
||||
# Comma separated list of seed nodes to connect to
|
||||
seeds = ""
|
||||
|
||||
# Comma separated list of nodes to keep persistent connections to
|
||||
persistent_peers = ""
|
||||
|
||||
# UPNP port forwarding
|
||||
upnp = false
|
||||
|
||||
# Path to address book
|
||||
addr_book_file = "config/addrbook.json"
|
||||
|
||||
# Set true for strict address routability rules
|
||||
# Set false for private or local networks
|
||||
addr_book_strict = true
|
||||
|
||||
# Maximum number of inbound peers
|
||||
max_num_inbound_peers = 40
|
||||
|
||||
# Maximum number of outbound peers to connect to, excluding persistent peers
|
||||
max_num_outbound_peers = 10
|
||||
|
||||
# Time to wait before flushing messages out on the connection
|
||||
flush_throttle_timeout = "100ms"
|
||||
|
||||
# Maximum size of a message packet payload, in bytes
|
||||
max_packet_msg_payload_size = 1024
|
||||
|
||||
# Rate at which packets can be sent, in bytes/second
|
||||
send_rate = 5120000
|
||||
|
||||
# Rate at which packets can be received, in bytes/second
|
||||
recv_rate = 5120000
|
||||
|
||||
# Set true to enable the peer-exchange reactor
|
||||
pex = true
|
||||
|
||||
# Seed mode, in which node constantly crawls the network and looks for
|
||||
# peers. If another node asks it for addresses, it responds and disconnects.
|
||||
#
|
||||
# Does not work if the peer-exchange reactor is disabled.
|
||||
seed_mode = false
|
||||
|
||||
# Comma separated list of peer IDs to keep private (will not be gossiped to other peers)
|
||||
private_peer_ids = ""
|
||||
|
||||
# Toggle to disable guard against peers connecting from the same ip.
|
||||
allow_duplicate_ip = false
|
||||
|
||||
# Peer connection configuration.
|
||||
handshake_timeout = "20s"
|
||||
dial_timeout = "3s"
|
||||
|
||||
##### mempool configuration options #####
|
||||
[mempool]
|
||||
|
||||
recheck = true
|
||||
broadcast = true
|
||||
wal_dir = ""
|
||||
|
||||
# Maximum number of transactions in the mempool
|
||||
size = 5000
|
||||
|
||||
# Limit the total size of all txs in the mempool.
|
||||
# This only accounts for raw transactions (e.g. given 1MB transactions and
|
||||
# max_txs_bytes=5MB, mempool will only accept 5 transactions).
|
||||
max_txs_bytes = 1073741824
|
||||
|
||||
# Size of the cache (used to filter transactions we saw earlier) in transactions
|
||||
cache_size = 10000
|
||||
|
||||
##### consensus configuration options #####
|
||||
[consensus]
|
||||
|
||||
wal_file = "data/cs.wal/wal"
|
||||
|
||||
timeout_propose = "3s"
|
||||
timeout_propose_delta = "500ms"
|
||||
timeout_prevote = "1s"
|
||||
timeout_prevote_delta = "500ms"
|
||||
timeout_precommit = "1s"
|
||||
timeout_precommit_delta = "500ms"
|
||||
timeout_commit = "1s"
|
||||
|
||||
# Make progress as soon as we have all the precommits (as if TimeoutCommit = 0)
|
||||
skip_timeout_commit = false
|
||||
|
||||
# EmptyBlocks mode and possible interval between empty blocks
|
||||
create_empty_blocks = true
|
||||
create_empty_blocks_interval = "0s"
|
||||
|
||||
# Reactor sleep duration parameters
|
||||
peer_gossip_sleep_duration = "100ms"
|
||||
peer_query_maj23_sleep_duration = "2s"
|
||||
|
||||
##### transactions indexer configuration options #####
|
||||
[tx_index]
|
||||
|
||||
# What indexer to use for transactions
|
||||
#
|
||||
# Options:
|
||||
# 1) "null"
|
||||
# 2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend).
|
||||
indexer = "kv"
|
||||
|
||||
# Comma-separated list of tags to index (by default the only tag is "tx.hash")
|
||||
#
|
||||
# You can also index transactions by height by adding "tx.height" tag here.
|
||||
#
|
||||
# It's recommended to index only a subset of tags due to possible memory
|
||||
# bloat. This is, of course, depends on the indexer's DB and the volume of
|
||||
# transactions.
|
||||
index_tags = ""
|
||||
|
||||
# When set to true, tells indexer to index all tags (predefined tags:
|
||||
# "tx.hash", "tx.height" and all tags from DeliverTx responses).
|
||||
#
|
||||
# Note this may be not desirable (see the comment above). IndexTags has a
|
||||
# precedence over IndexAllTags (i.e. when given both, IndexTags will be
|
||||
# indexed).
|
||||
index_all_tags = false
|
||||
|
||||
##### instrumentation configuration options #####
|
||||
[instrumentation]
|
||||
|
||||
# When true, Prometheus metrics are served under /metrics on
|
||||
# PrometheusListenAddr.
|
||||
# Check out the documentation for the list of available metrics.
|
||||
prometheus = false
|
||||
|
||||
# Address to listen for Prometheus collector(s) connections
|
||||
prometheus_listen_addr = ":26660"
|
||||
|
||||
# Maximum number of simultaneous connections.
|
||||
# If you want to accept a larger number than the default, make sure
|
||||
# you increase your OS limits.
|
||||
# 0 - unlimited.
|
||||
max_open_connections = 3
|
||||
|
||||
# Instrumentation namespace
|
||||
namespace = "tendermint"
|
||||
+319
@@ -0,0 +1,319 @@
|
||||
# This is a TOML config file.
|
||||
# For more information, see https://github.com/toml-lang/toml
|
||||
|
||||
# NOTE: Any path below can be absolute (e.g. "/var/myawesomeapp/data") or
|
||||
# relative to the home directory (e.g. "data"). The home directory is
|
||||
# "$HOME/.tendermint" by default, but could be changed via $TMHOME env variable
|
||||
# or --home cmd flag.
|
||||
|
||||
##### main base config options #####
|
||||
|
||||
# TCP or UNIX socket address of the ABCI application,
|
||||
# or the name of an ABCI application compiled in with the Tendermint binary
|
||||
proxy_app = "tcp://127.0.0.1:26658"
|
||||
|
||||
# A custom human readable name for this node
|
||||
moniker = "localhost"
|
||||
|
||||
# If this node is many blocks behind the tip of the chain, FastSync
|
||||
# allows them to catchup quickly by downloading blocks in parallel
|
||||
# and verifying their commits
|
||||
fast_sync = true
|
||||
|
||||
# Database backend: goleveldb | cleveldb | boltdb
|
||||
# * goleveldb (github.com/syndtr/goleveldb - most popular implementation)
|
||||
# - pure go
|
||||
# - stable
|
||||
# * cleveldb (uses levigo wrapper)
|
||||
# - fast
|
||||
# - requires gcc
|
||||
# - use cleveldb build tag (go build -tags cleveldb)
|
||||
# * boltdb (uses etcd's fork of bolt - github.com/etcd-io/bbolt)
|
||||
# - EXPERIMENTAL
|
||||
# - may be faster is some use-cases (random reads - indexer)
|
||||
# - use boltdb build tag (go build -tags boltdb)
|
||||
db_backend = "goleveldb"
|
||||
|
||||
# Database directory
|
||||
db_dir = "data"
|
||||
|
||||
# Output level for logging, including package level options
|
||||
log_level = "main:info,state:info,*:error"
|
||||
|
||||
# Output format: 'plain' (colored text) or 'json'
|
||||
log_format = "plain"
|
||||
|
||||
##### additional base config options #####
|
||||
|
||||
# Path to the JSON file containing the initial validator set and other meta data
|
||||
genesis_file = "config/genesis.json"
|
||||
|
||||
# Path to the JSON file containing the private key to use as a validator in the consensus protocol
|
||||
priv_validator_key_file = "config/priv_validator_key.json"
|
||||
|
||||
# Path to the JSON file containing the last sign state of a validator
|
||||
priv_validator_state_file = "data/priv_validator_state.json"
|
||||
|
||||
# TCP or UNIX socket address for Tendermint to listen on for
|
||||
# connections from an external PrivValidator process
|
||||
priv_validator_laddr = ""
|
||||
|
||||
# Path to the JSON file containing the private key to use for node authentication in the p2p protocol
|
||||
node_key_file = "config/node_key.json"
|
||||
|
||||
# Mechanism to connect to the ABCI application: socket | grpc
|
||||
abci = "socket"
|
||||
|
||||
# TCP or UNIX socket address for the profiling server to listen on
|
||||
prof_laddr = ""
|
||||
|
||||
# If true, query the ABCI app on connecting to a new peer
|
||||
# so the app can decide if we should keep the connection or not
|
||||
filter_peers = false
|
||||
|
||||
##### advanced configuration options #####
|
||||
|
||||
##### rpc server configuration options #####
|
||||
[rpc]
|
||||
|
||||
# TCP or UNIX socket address for the RPC server to listen on
|
||||
laddr = "tcp://127.0.0.1:26657"
|
||||
|
||||
# A list of origins a cross-domain request can be executed from
|
||||
# Default value '[]' disables cors support
|
||||
# Use '["*"]' to allow any origin
|
||||
cors_allowed_origins = []
|
||||
|
||||
# A list of methods the client is allowed to use with cross-domain requests
|
||||
cors_allowed_methods = ["HEAD", "GET", "POST", ]
|
||||
|
||||
# A list of non simple headers the client is allowed to use with cross-domain requests
|
||||
cors_allowed_headers = ["Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time", ]
|
||||
|
||||
# TCP or UNIX socket address for the gRPC server to listen on
|
||||
# NOTE: This server only supports /broadcast_tx_commit
|
||||
grpc_laddr = ""
|
||||
|
||||
# Maximum number of simultaneous connections.
|
||||
# Does not include RPC (HTTP&WebSocket) connections. See max_open_connections
|
||||
# If you want to accept a larger number than the default, make sure
|
||||
# you increase your OS limits.
|
||||
# 0 - unlimited.
|
||||
# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files}
|
||||
# 1024 - 40 - 10 - 50 = 924 = ~900
|
||||
grpc_max_open_connections = 900
|
||||
|
||||
# Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool
|
||||
unsafe = false
|
||||
|
||||
# Maximum number of simultaneous connections (including WebSocket).
|
||||
# Does not include gRPC connections. See grpc_max_open_connections
|
||||
# If you want to accept a larger number than the default, make sure
|
||||
# you increase your OS limits.
|
||||
# 0 - unlimited.
|
||||
# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files}
|
||||
# 1024 - 40 - 10 - 50 = 924 = ~900
|
||||
max_open_connections = 900
|
||||
|
||||
# Maximum number of unique clientIDs that can /subscribe
|
||||
# If you're using /broadcast_tx_commit, set to the estimated maximum number
|
||||
# of broadcast_tx_commit calls per block.
|
||||
max_subscription_clients = 100
|
||||
|
||||
# Maximum number of unique queries a given client can /subscribe to
|
||||
# If you're using GRPC (or Local RPC client) and /broadcast_tx_commit, set to
|
||||
# the estimated # maximum number of broadcast_tx_commit calls per block.
|
||||
max_subscriptions_per_client = 5
|
||||
|
||||
# How long to wait for a tx to be committed during /broadcast_tx_commit.
|
||||
# WARNING: Using a value larger than 10s will result in increasing the
|
||||
# global HTTP write timeout, which applies to all connections and endpoints.
|
||||
# See https://github.com/tendermint/tendermint/issues/3435
|
||||
timeout_broadcast_tx_commit = "10s"
|
||||
|
||||
# Maximum size of request body, in bytes
|
||||
max_body_bytes = 1000000
|
||||
|
||||
# Maximum size of request header, in bytes
|
||||
max_header_bytes = 1048576
|
||||
|
||||
# The path to a file containing certificate that is used to create the HTTPS server.
|
||||
# Migth be either absolute path or path related to tendermint's config directory.
|
||||
# If the certificate is signed by a certificate authority,
|
||||
# the certFile should be the concatenation of the server's certificate, any intermediates,
|
||||
# and the CA's certificate.
|
||||
# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server.
|
||||
# Otherwise, HTTP server is run.
|
||||
tls_cert_file = ""
|
||||
|
||||
# The path to a file containing matching private key that is used to create the HTTPS server.
|
||||
# Migth be either absolute path or path related to tendermint's config directory.
|
||||
# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server.
|
||||
# Otherwise, HTTP server is run.
|
||||
tls_key_file = ""
|
||||
|
||||
##### peer to peer configuration options #####
|
||||
[p2p]
|
||||
|
||||
# Address to listen for incoming connections
|
||||
laddr = "tcp://0.0.0.0:26656"
|
||||
|
||||
# Address to advertise to peers for them to dial
|
||||
# If empty, will use the same port as the laddr,
|
||||
# and will introspect on the listener or use UPnP
|
||||
# to figure out the address.
|
||||
external_address = ""
|
||||
|
||||
# Comma separated list of seed nodes to connect to
|
||||
seeds = ""
|
||||
|
||||
# Comma separated list of nodes to keep persistent connections to
|
||||
persistent_peers = ""
|
||||
|
||||
# UPNP port forwarding
|
||||
upnp = false
|
||||
|
||||
# Path to address book
|
||||
addr_book_file = "config/addrbook.json"
|
||||
|
||||
# Set true for strict address routability rules
|
||||
# Set false for private or local networks
|
||||
addr_book_strict = true
|
||||
|
||||
# Maximum number of inbound peers
|
||||
max_num_inbound_peers = 40
|
||||
|
||||
# Maximum number of outbound peers to connect to, excluding persistent peers
|
||||
max_num_outbound_peers = 10
|
||||
|
||||
# Time to wait before flushing messages out on the connection
|
||||
flush_throttle_timeout = "100ms"
|
||||
|
||||
# Maximum size of a message packet payload, in bytes
|
||||
max_packet_msg_payload_size = 1024
|
||||
|
||||
# Rate at which packets can be sent, in bytes/second
|
||||
send_rate = 5120000
|
||||
|
||||
# Rate at which packets can be received, in bytes/second
|
||||
recv_rate = 5120000
|
||||
|
||||
# Set true to enable the peer-exchange reactor
|
||||
pex = true
|
||||
|
||||
# Seed mode, in which node constantly crawls the network and looks for
|
||||
# peers. If another node asks it for addresses, it responds and disconnects.
|
||||
#
|
||||
# Does not work if the peer-exchange reactor is disabled.
|
||||
seed_mode = false
|
||||
|
||||
# Comma separated list of peer IDs to keep private (will not be gossiped to other peers)
|
||||
private_peer_ids = ""
|
||||
|
||||
# Toggle to disable guard against peers connecting from the same ip.
|
||||
allow_duplicate_ip = false
|
||||
|
||||
# Peer connection configuration.
|
||||
handshake_timeout = "20s"
|
||||
dial_timeout = "3s"
|
||||
|
||||
##### mempool configuration options #####
|
||||
[mempool]
|
||||
|
||||
recheck = true
|
||||
broadcast = true
|
||||
wal_dir = ""
|
||||
|
||||
# Maximum number of transactions in the mempool
|
||||
size = 5000
|
||||
|
||||
# Limit the total size of all txs in the mempool.
|
||||
# This only accounts for raw transactions (e.g. given 1MB transactions and
|
||||
# max_txs_bytes=5MB, mempool will only accept 5 transactions).
|
||||
max_txs_bytes = 1073741824
|
||||
|
||||
# Size of the cache (used to filter transactions we saw earlier) in transactions
|
||||
cache_size = 10000
|
||||
|
||||
# Maximum size of a single transaction.
|
||||
# NOTE: the max size of a tx transmitted over the network is {max_tx_bytes} + {amino overhead}.
|
||||
max_tx_bytes = 1048576
|
||||
|
||||
##### fast sync configuration options #####
|
||||
[fastsync]
|
||||
|
||||
# Fast Sync version to use:
|
||||
# 1) "v0" (default) - the legacy fast sync implementation
|
||||
# 2) "v1" - refactor of v0 version for better testability
|
||||
version = "v0"
|
||||
|
||||
##### consensus configuration options #####
|
||||
[consensus]
|
||||
|
||||
wal_file = "data/cs.wal/wal"
|
||||
|
||||
timeout_propose = "3s"
|
||||
timeout_propose_delta = "500ms"
|
||||
timeout_prevote = "1s"
|
||||
timeout_prevote_delta = "500ms"
|
||||
timeout_precommit = "1s"
|
||||
timeout_precommit_delta = "500ms"
|
||||
timeout_commit = "1s"
|
||||
|
||||
# Make progress as soon as we have all the precommits (as if TimeoutCommit = 0)
|
||||
skip_timeout_commit = false
|
||||
|
||||
# EmptyBlocks mode and possible interval between empty blocks
|
||||
create_empty_blocks = true
|
||||
create_empty_blocks_interval = "0s"
|
||||
|
||||
# Reactor sleep duration parameters
|
||||
peer_gossip_sleep_duration = "100ms"
|
||||
peer_query_maj23_sleep_duration = "2s"
|
||||
|
||||
##### transactions indexer configuration options #####
|
||||
[tx_index]
|
||||
|
||||
# What indexer to use for transactions
|
||||
#
|
||||
# Options:
|
||||
# 1) "null"
|
||||
# 2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend).
|
||||
indexer = "kv"
|
||||
|
||||
# Comma-separated list of tags to index (by default the only tag is "tx.hash")
|
||||
#
|
||||
# You can also index transactions by height by adding "tx.height" tag here.
|
||||
#
|
||||
# It's recommended to index only a subset of tags due to possible memory
|
||||
# bloat. This is, of course, depends on the indexer's DB and the volume of
|
||||
# transactions.
|
||||
index_tags = ""
|
||||
|
||||
# When set to true, tells indexer to index all tags (predefined tags:
|
||||
# "tx.hash", "tx.height" and all tags from DeliverTx responses).
|
||||
#
|
||||
# Note this may be not desirable (see the comment above). IndexTags has a
|
||||
# precedence over IndexAllTags (i.e. when given both, IndexTags will be
|
||||
# indexed).
|
||||
index_all_tags = false
|
||||
|
||||
##### instrumentation configuration options #####
|
||||
[instrumentation]
|
||||
|
||||
# When true, Prometheus metrics are served under /metrics on
|
||||
# PrometheusListenAddr.
|
||||
# Check out the documentation for the list of available metrics.
|
||||
prometheus = false
|
||||
|
||||
# Address to listen for Prometheus collector(s) connections
|
||||
prometheus_listen_addr = ":26660"
|
||||
|
||||
# Maximum number of simultaneous connections.
|
||||
# If you want to accept a larger number than the default, make sure
|
||||
# you increase your OS limits.
|
||||
# 0 - unlimited.
|
||||
max_open_connections = 3
|
||||
|
||||
# Instrumentation namespace
|
||||
namespace = "tendermint"
|
||||
+335
@@ -0,0 +1,335 @@
|
||||
# This is a TOML config file.
|
||||
# For more information, see https://github.com/toml-lang/toml
|
||||
|
||||
# NOTE: Any path below can be absolute (e.g. "/var/myawesomeapp/data") or
|
||||
# relative to the home directory (e.g. "data"). The home directory is
|
||||
# "$HOME/.tendermint" by default, but could be changed via $TMHOME env variable
|
||||
# or --home cmd flag.
|
||||
|
||||
##### main base config options #####
|
||||
|
||||
# TCP or UNIX socket address of the ABCI application,
|
||||
# or the name of an ABCI application compiled in with the Tendermint binary
|
||||
proxy_app = "tcp://127.0.0.1:26658"
|
||||
|
||||
# A custom human readable name for this node
|
||||
moniker = "localhost"
|
||||
|
||||
# If this node is many blocks behind the tip of the chain, FastSync
|
||||
# allows them to catchup quickly by downloading blocks in parallel
|
||||
# and verifying their commits
|
||||
fast_sync = true
|
||||
|
||||
# Database backend: goleveldb | cleveldb | boltdb | rocksdb
|
||||
# * goleveldb (github.com/syndtr/goleveldb - most popular implementation)
|
||||
# - pure go
|
||||
# - stable
|
||||
# * cleveldb (uses levigo wrapper)
|
||||
# - fast
|
||||
# - requires gcc
|
||||
# - use cleveldb build tag (go build -tags cleveldb)
|
||||
# * boltdb (uses etcd's fork of bolt - github.com/etcd-io/bbolt)
|
||||
# - EXPERIMENTAL
|
||||
# - may be faster is some use-cases (random reads - indexer)
|
||||
# - use boltdb build tag (go build -tags boltdb)
|
||||
# * rocksdb (uses github.com/tecbot/gorocksdb)
|
||||
# - EXPERIMENTAL
|
||||
# - requires gcc
|
||||
# - use rocksdb build tag (go build -tags rocksdb)
|
||||
db_backend = "goleveldb"
|
||||
|
||||
# Database directory
|
||||
db_dir = "data"
|
||||
|
||||
# Output level for logging, including package level options
|
||||
log_level = "main:info,state:info,*:error"
|
||||
|
||||
# Output format: 'plain' (colored text) or 'json'
|
||||
log_format = "plain"
|
||||
|
||||
##### additional base config options #####
|
||||
|
||||
# Path to the JSON file containing the initial validator set and other meta data
|
||||
genesis_file = "config/genesis.json"
|
||||
|
||||
# Path to the JSON file containing the private key to use as a validator in the consensus protocol
|
||||
priv_validator_key_file = "config/priv_validator_key.json"
|
||||
|
||||
# Path to the JSON file containing the last sign state of a validator
|
||||
priv_validator_state_file = "data/priv_validator_state.json"
|
||||
|
||||
# TCP or UNIX socket address for Tendermint to listen on for
|
||||
# connections from an external PrivValidator process
|
||||
priv_validator_laddr = ""
|
||||
|
||||
# Path to the JSON file containing the private key to use for node authentication in the p2p protocol
|
||||
node_key_file = "config/node_key.json"
|
||||
|
||||
# Mechanism to connect to the ABCI application: socket | grpc
|
||||
abci = "socket"
|
||||
|
||||
# TCP or UNIX socket address for the profiling server to listen on
|
||||
prof_laddr = ""
|
||||
|
||||
# If true, query the ABCI app on connecting to a new peer
|
||||
# so the app can decide if we should keep the connection or not
|
||||
filter_peers = false
|
||||
|
||||
##### advanced configuration options #####
|
||||
|
||||
##### rpc server configuration options #####
|
||||
[rpc]
|
||||
|
||||
# TCP or UNIX socket address for the RPC server to listen on
|
||||
laddr = "tcp://127.0.0.1:26657"
|
||||
|
||||
# A list of origins a cross-domain request can be executed from
|
||||
# Default value '[]' disables cors support
|
||||
# Use '["*"]' to allow any origin
|
||||
cors_allowed_origins = []
|
||||
|
||||
# A list of methods the client is allowed to use with cross-domain requests
|
||||
cors_allowed_methods = ["HEAD", "GET", "POST", ]
|
||||
|
||||
# A list of non simple headers the client is allowed to use with cross-domain requests
|
||||
cors_allowed_headers = ["Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time", ]
|
||||
|
||||
# TCP or UNIX socket address for the gRPC server to listen on
|
||||
# NOTE: This server only supports /broadcast_tx_commit
|
||||
grpc_laddr = ""
|
||||
|
||||
# Maximum number of simultaneous connections.
|
||||
# Does not include RPC (HTTP&WebSocket) connections. See max_open_connections
|
||||
# If you want to accept a larger number than the default, make sure
|
||||
# you increase your OS limits.
|
||||
# 0 - unlimited.
|
||||
# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files}
|
||||
# 1024 - 40 - 10 - 50 = 924 = ~900
|
||||
grpc_max_open_connections = 900
|
||||
|
||||
# Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool
|
||||
unsafe = false
|
||||
|
||||
# Maximum number of simultaneous connections (including WebSocket).
|
||||
# Does not include gRPC connections. See grpc_max_open_connections
|
||||
# If you want to accept a larger number than the default, make sure
|
||||
# you increase your OS limits.
|
||||
# 0 - unlimited.
|
||||
# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files}
|
||||
# 1024 - 40 - 10 - 50 = 924 = ~900
|
||||
max_open_connections = 900
|
||||
|
||||
# Maximum number of unique clientIDs that can /subscribe
|
||||
# If you're using /broadcast_tx_commit, set to the estimated maximum number
|
||||
# of broadcast_tx_commit calls per block.
|
||||
max_subscription_clients = 100
|
||||
|
||||
# Maximum number of unique queries a given client can /subscribe to
|
||||
# If you're using GRPC (or Local RPC client) and /broadcast_tx_commit, set to
|
||||
# the estimated # maximum number of broadcast_tx_commit calls per block.
|
||||
max_subscriptions_per_client = 5
|
||||
|
||||
# How long to wait for a tx to be committed during /broadcast_tx_commit.
|
||||
# WARNING: Using a value larger than 10s will result in increasing the
|
||||
# global HTTP write timeout, which applies to all connections and endpoints.
|
||||
# See https://github.com/tendermint/tendermint/issues/3435
|
||||
timeout_broadcast_tx_commit = "10s"
|
||||
|
||||
# Maximum size of request body, in bytes
|
||||
max_body_bytes = 1000000
|
||||
|
||||
# Maximum size of request header, in bytes
|
||||
max_header_bytes = 1048576
|
||||
|
||||
# The path to a file containing certificate that is used to create the HTTPS server.
|
||||
# Migth be either absolute path or path related to tendermint's config directory.
|
||||
# If the certificate is signed by a certificate authority,
|
||||
# the certFile should be the concatenation of the server's certificate, any intermediates,
|
||||
# and the CA's certificate.
|
||||
# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server.
|
||||
# Otherwise, HTTP server is run.
|
||||
tls_cert_file = ""
|
||||
|
||||
# The path to a file containing matching private key that is used to create the HTTPS server.
|
||||
# Migth be either absolute path or path related to tendermint's config directory.
|
||||
# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server.
|
||||
# Otherwise, HTTP server is run.
|
||||
tls_key_file = ""
|
||||
|
||||
##### peer to peer configuration options #####
|
||||
[p2p]
|
||||
|
||||
# Address to listen for incoming connections
|
||||
laddr = "tcp://0.0.0.0:26656"
|
||||
|
||||
# Address to advertise to peers for them to dial
|
||||
# If empty, will use the same port as the laddr,
|
||||
# and will introspect on the listener or use UPnP
|
||||
# to figure out the address.
|
||||
external_address = ""
|
||||
|
||||
# Comma separated list of seed nodes to connect to
|
||||
seeds = ""
|
||||
|
||||
# Comma separated list of nodes to keep persistent connections to
|
||||
persistent_peers = ""
|
||||
|
||||
# UPNP port forwarding
|
||||
upnp = false
|
||||
|
||||
# Path to address book
|
||||
addr_book_file = "config/addrbook.json"
|
||||
|
||||
# Set true for strict address routability rules
|
||||
# Set false for private or local networks
|
||||
addr_book_strict = true
|
||||
|
||||
# Maximum number of inbound peers
|
||||
max_num_inbound_peers = 40
|
||||
|
||||
# Maximum number of outbound peers to connect to, excluding persistent peers
|
||||
max_num_outbound_peers = 10
|
||||
|
||||
# List of node IDs, to which a connection will be (re)established ignoring any existing limits
|
||||
unconditional_peer_ids = ""
|
||||
|
||||
# Maximum pause when redialing a persistent peer (if zero, exponential backoff is used)
|
||||
persistent_peers_max_dial_period = "0s"
|
||||
|
||||
# Time to wait before flushing messages out on the connection
|
||||
flush_throttle_timeout = "100ms"
|
||||
|
||||
# Maximum size of a message packet payload, in bytes
|
||||
max_packet_msg_payload_size = 1024
|
||||
|
||||
# Rate at which packets can be sent, in bytes/second
|
||||
send_rate = 5120000
|
||||
|
||||
# Rate at which packets can be received, in bytes/second
|
||||
recv_rate = 5120000
|
||||
|
||||
# Set true to enable the peer-exchange reactor
|
||||
pex = true
|
||||
|
||||
# Seed mode, in which node constantly crawls the network and looks for
|
||||
# peers. If another node asks it for addresses, it responds and disconnects.
|
||||
#
|
||||
# Does not work if the peer-exchange reactor is disabled.
|
||||
seed_mode = false
|
||||
|
||||
# Comma separated list of peer IDs to keep private (will not be gossiped to other peers)
|
||||
private_peer_ids = ""
|
||||
|
||||
# Toggle to disable guard against peers connecting from the same ip.
|
||||
allow_duplicate_ip = false
|
||||
|
||||
# Peer connection configuration.
|
||||
handshake_timeout = "20s"
|
||||
dial_timeout = "3s"
|
||||
|
||||
##### mempool configuration options #####
|
||||
[mempool]
|
||||
|
||||
recheck = true
|
||||
broadcast = true
|
||||
wal_dir = ""
|
||||
|
||||
# Maximum number of transactions in the mempool
|
||||
size = 5000
|
||||
|
||||
# Limit the total size of all txs in the mempool.
|
||||
# This only accounts for raw transactions (e.g. given 1MB transactions and
|
||||
# max_txs_bytes=5MB, mempool will only accept 5 transactions).
|
||||
max_txs_bytes = 1073741824
|
||||
|
||||
# Size of the cache (used to filter transactions we saw earlier) in transactions
|
||||
cache_size = 10000
|
||||
|
||||
# Maximum size of a single transaction.
|
||||
# NOTE: the max size of a tx transmitted over the network is {max_tx_bytes} + {amino overhead}.
|
||||
max_tx_bytes = 1048576
|
||||
|
||||
##### fast sync configuration options #####
|
||||
[fastsync]
|
||||
|
||||
# Fast Sync version to use:
|
||||
# 1) "v0" (default) - the legacy fast sync implementation
|
||||
# 2) "v1" - refactor of v0 version for better testability
|
||||
# 3) "v2" - refactor of v1 version for better usability
|
||||
version = "v0"
|
||||
|
||||
##### consensus configuration options #####
|
||||
[consensus]
|
||||
|
||||
wal_file = "data/cs.wal/wal"
|
||||
|
||||
timeout_propose = "3s"
|
||||
timeout_propose_delta = "500ms"
|
||||
timeout_prevote = "1s"
|
||||
timeout_prevote_delta = "500ms"
|
||||
timeout_precommit = "1s"
|
||||
timeout_precommit_delta = "500ms"
|
||||
timeout_commit = "1s"
|
||||
|
||||
# Make progress as soon as we have all the precommits (as if TimeoutCommit = 0)
|
||||
skip_timeout_commit = false
|
||||
|
||||
# EmptyBlocks mode and possible interval between empty blocks
|
||||
create_empty_blocks = true
|
||||
create_empty_blocks_interval = "0s"
|
||||
|
||||
# Reactor sleep duration parameters
|
||||
peer_gossip_sleep_duration = "100ms"
|
||||
peer_query_maj23_sleep_duration = "2s"
|
||||
|
||||
##### transactions indexer configuration options #####
|
||||
[tx_index]
|
||||
|
||||
# What indexer to use for transactions
|
||||
#
|
||||
# Options:
|
||||
# 1) "null"
|
||||
# 2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend).
|
||||
indexer = "kv"
|
||||
|
||||
# Comma-separated list of compositeKeys to index (by default the only key is "tx.hash")
|
||||
# Remember that Event has the following structure: type.key
|
||||
# type: [
|
||||
# key: value,
|
||||
# ...
|
||||
# ]
|
||||
#
|
||||
# You can also index transactions by height by adding "tx.height" key here.
|
||||
#
|
||||
# It's recommended to index only a subset of keys due to possible memory
|
||||
# bloat. This is, of course, depends on the indexer's DB and the volume of
|
||||
# transactions.
|
||||
index_keys = ""
|
||||
|
||||
# When set to true, tells indexer to index all compositeKeys (predefined keys:
|
||||
# "tx.hash", "tx.height" and all keys from DeliverTx responses).
|
||||
#
|
||||
# Note this may be not desirable (see the comment above). IndexKeys has a
|
||||
# precedence over IndexAllKeys (i.e. when given both, IndexKeys will be
|
||||
# indexed).
|
||||
index_all_keys = false
|
||||
|
||||
##### instrumentation configuration options #####
|
||||
[instrumentation]
|
||||
|
||||
# When true, Prometheus metrics are served under /metrics on
|
||||
# PrometheusListenAddr.
|
||||
# Check out the documentation for the list of available metrics.
|
||||
prometheus = false
|
||||
|
||||
# Address to listen for Prometheus collector(s) connections
|
||||
prometheus_listen_addr = ":26660"
|
||||
|
||||
# Maximum number of simultaneous connections.
|
||||
# If you want to accept a larger number than the default, make sure
|
||||
# you increase your OS limits.
|
||||
# 0 - unlimited.
|
||||
max_open_connections = 3
|
||||
|
||||
# Instrumentation namespace
|
||||
namespace = "tendermint"
|
||||
+428
@@ -0,0 +1,428 @@
|
||||
# This is a TOML config file.
|
||||
# For more information, see https://github.com/toml-lang/toml
|
||||
|
||||
# NOTE: Any path below can be absolute (e.g. "/var/myawesomeapp/data") or
|
||||
# relative to the home directory (e.g. "data"). The home directory is
|
||||
# "$HOME/.tendermint" by default, but could be changed via $TMHOME env variable
|
||||
# or --home cmd flag.
|
||||
|
||||
#######################################################################
|
||||
### Main Base Config Options ###
|
||||
#######################################################################
|
||||
|
||||
# TCP or UNIX socket address of the ABCI application,
|
||||
# or the name of an ABCI application compiled in with the Tendermint binary
|
||||
proxy_app = "tcp://127.0.0.1:26658"
|
||||
|
||||
# A custom human readable name for this node
|
||||
moniker = "localhost"
|
||||
|
||||
# If this node is many blocks behind the tip of the chain, FastSync
|
||||
# allows them to catchup quickly by downloading blocks in parallel
|
||||
# and verifying their commits
|
||||
fast_sync = true
|
||||
|
||||
# Database backend: goleveldb | cleveldb | boltdb | rocksdb | badgerdb
|
||||
# * goleveldb (github.com/syndtr/goleveldb - most popular implementation)
|
||||
# - pure go
|
||||
# - stable
|
||||
# * cleveldb (uses levigo wrapper)
|
||||
# - fast
|
||||
# - requires gcc
|
||||
# - use cleveldb build tag (go build -tags cleveldb)
|
||||
# * boltdb (uses etcd's fork of bolt - github.com/etcd-io/bbolt)
|
||||
# - EXPERIMENTAL
|
||||
# - may be faster is some use-cases (random reads - indexer)
|
||||
# - use boltdb build tag (go build -tags boltdb)
|
||||
# * rocksdb (uses github.com/tecbot/gorocksdb)
|
||||
# - EXPERIMENTAL
|
||||
# - requires gcc
|
||||
# - use rocksdb build tag (go build -tags rocksdb)
|
||||
# * badgerdb (uses github.com/dgraph-io/badger)
|
||||
# - EXPERIMENTAL
|
||||
# - use badgerdb build tag (go build -tags badgerdb)
|
||||
db_backend = "goleveldb"
|
||||
|
||||
# Database directory
|
||||
db_dir = "data"
|
||||
|
||||
# Output level for logging, including package level options
|
||||
log_level = "info"
|
||||
|
||||
# Output format: 'plain' (colored text) or 'json'
|
||||
log_format = "plain"
|
||||
|
||||
##### additional base config options #####
|
||||
|
||||
# Path to the JSON file containing the initial validator set and other meta data
|
||||
genesis_file = "config/genesis.json"
|
||||
|
||||
# Path to the JSON file containing the private key to use as a validator in the consensus protocol
|
||||
priv_validator_key_file = "config/priv_validator_key.json"
|
||||
|
||||
# Path to the JSON file containing the last sign state of a validator
|
||||
priv_validator_state_file = "data/priv_validator_state.json"
|
||||
|
||||
# TCP or UNIX socket address for Tendermint to listen on for
|
||||
# connections from an external PrivValidator process
|
||||
priv_validator_laddr = ""
|
||||
|
||||
# Path to the JSON file containing the private key to use for node authentication in the p2p protocol
|
||||
node_key_file = "config/node_key.json"
|
||||
|
||||
# Mechanism to connect to the ABCI application: socket | grpc
|
||||
abci = "socket"
|
||||
|
||||
# If true, query the ABCI app on connecting to a new peer
|
||||
# so the app can decide if we should keep the connection or not
|
||||
filter_peers = false
|
||||
|
||||
|
||||
#######################################################################
|
||||
### Advanced Configuration Options ###
|
||||
#######################################################################
|
||||
|
||||
#######################################################
|
||||
### RPC Server Configuration Options ###
|
||||
#######################################################
|
||||
[rpc]
|
||||
|
||||
# TCP or UNIX socket address for the RPC server to listen on
|
||||
laddr = "tcp://127.0.0.1:26657"
|
||||
|
||||
# A list of origins a cross-domain request can be executed from
|
||||
# Default value '[]' disables cors support
|
||||
# Use '["*"]' to allow any origin
|
||||
cors_allowed_origins = []
|
||||
|
||||
# A list of methods the client is allowed to use with cross-domain requests
|
||||
cors_allowed_methods = ["HEAD", "GET", "POST", ]
|
||||
|
||||
# A list of non simple headers the client is allowed to use with cross-domain requests
|
||||
cors_allowed_headers = ["Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time", ]
|
||||
|
||||
# TCP or UNIX socket address for the gRPC server to listen on
|
||||
# NOTE: This server only supports /broadcast_tx_commit
|
||||
grpc_laddr = ""
|
||||
|
||||
# Maximum number of simultaneous connections.
|
||||
# Does not include RPC (HTTP&WebSocket) connections. See max_open_connections
|
||||
# If you want to accept a larger number than the default, make sure
|
||||
# you increase your OS limits.
|
||||
# 0 - unlimited.
|
||||
# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files}
|
||||
# 1024 - 40 - 10 - 50 = 924 = ~900
|
||||
grpc_max_open_connections = 900
|
||||
|
||||
# Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool
|
||||
unsafe = false
|
||||
|
||||
# Maximum number of simultaneous connections (including WebSocket).
|
||||
# Does not include gRPC connections. See grpc_max_open_connections
|
||||
# If you want to accept a larger number than the default, make sure
|
||||
# you increase your OS limits.
|
||||
# 0 - unlimited.
|
||||
# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files}
|
||||
# 1024 - 40 - 10 - 50 = 924 = ~900
|
||||
max_open_connections = 900
|
||||
|
||||
# Maximum number of unique clientIDs that can /subscribe
|
||||
# If you're using /broadcast_tx_commit, set to the estimated maximum number
|
||||
# of broadcast_tx_commit calls per block.
|
||||
max_subscription_clients = 100
|
||||
|
||||
# Maximum number of unique queries a given client can /subscribe to
|
||||
# If you're using GRPC (or Local RPC client) and /broadcast_tx_commit, set to
|
||||
# the estimated # maximum number of broadcast_tx_commit calls per block.
|
||||
max_subscriptions_per_client = 5
|
||||
|
||||
# Experimental parameter to specify the maximum number of events a node will
|
||||
# buffer, per subscription, before returning an error and closing the
|
||||
# subscription. Must be set to at least 100, but higher values will accommodate
|
||||
# higher event throughput rates (and will use more memory).
|
||||
experimental_subscription_buffer_size = 200
|
||||
|
||||
# Experimental parameter to specify the maximum number of RPC responses that
|
||||
# can be buffered per WebSocket client. If clients cannot read from the
|
||||
# WebSocket endpoint fast enough, they will be disconnected, so increasing this
|
||||
# parameter may reduce the chances of them being disconnected (but will cause
|
||||
# the node to use more memory).
|
||||
#
|
||||
# Must be at least the same as "experimental_subscription_buffer_size",
|
||||
# otherwise connections could be dropped unnecessarily. This value should
|
||||
# ideally be somewhat higher than "experimental_subscription_buffer_size" to
|
||||
# accommodate non-subscription-related RPC responses.
|
||||
experimental_websocket_write_buffer_size = 200
|
||||
|
||||
# If a WebSocket client cannot read fast enough, at present we may
|
||||
# silently drop events instead of generating an error or disconnecting the
|
||||
# client.
|
||||
#
|
||||
# Enabling this experimental parameter will cause the WebSocket connection to
|
||||
# be closed instead if it cannot read fast enough, allowing for greater
|
||||
# predictability in subscription behaviour.
|
||||
experimental_close_on_slow_client = false
|
||||
|
||||
# How long to wait for a tx to be committed during /broadcast_tx_commit.
|
||||
# WARNING: Using a value larger than 10s will result in increasing the
|
||||
# global HTTP write timeout, which applies to all connections and endpoints.
|
||||
# See https://github.com/tendermint/tendermint/issues/3435
|
||||
timeout_broadcast_tx_commit = "10s"
|
||||
|
||||
# Maximum size of request body, in bytes
|
||||
max_body_bytes = 1000000
|
||||
|
||||
# Maximum size of request header, in bytes
|
||||
max_header_bytes = 1048576
|
||||
|
||||
# The path to a file containing certificate that is used to create the HTTPS server.
|
||||
# Might be either absolute path or path related to Tendermint's config directory.
|
||||
# If the certificate is signed by a certificate authority,
|
||||
# the certFile should be the concatenation of the server's certificate, any intermediates,
|
||||
# and the CA's certificate.
|
||||
# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server.
|
||||
# Otherwise, HTTP server is run.
|
||||
tls_cert_file = ""
|
||||
|
||||
# The path to a file containing matching private key that is used to create the HTTPS server.
|
||||
# Might be either absolute path or path related to Tendermint's config directory.
|
||||
# NOTE: both tls-cert-file and tls-key-file must be present for Tendermint to create HTTPS server.
|
||||
# Otherwise, HTTP server is run.
|
||||
tls_key_file = ""
|
||||
|
||||
# pprof listen address (https://golang.org/pkg/net/http/pprof)
|
||||
pprof_laddr = ""
|
||||
|
||||
#######################################################
|
||||
### P2P Configuration Options ###
|
||||
#######################################################
|
||||
[p2p]
|
||||
|
||||
# Address to listen for incoming connections
|
||||
laddr = "tcp://0.0.0.0:26656"
|
||||
|
||||
# Address to advertise to peers for them to dial
|
||||
# If empty, will use the same port as the laddr,
|
||||
# and will introspect on the listener or use UPnP
|
||||
# to figure out the address. ip and port are required
|
||||
# example: 159.89.10.97:26656
|
||||
external_address = ""
|
||||
|
||||
# Comma separated list of seed nodes to connect to
|
||||
seeds = ""
|
||||
|
||||
# Comma separated list of nodes to keep persistent connections to
|
||||
persistent_peers = ""
|
||||
|
||||
# UPNP port forwarding
|
||||
upnp = false
|
||||
|
||||
# Path to address book
|
||||
addr_book_file = "config/addrbook.json"
|
||||
|
||||
# Set true for strict address routability rules
|
||||
# Set false for private or local networks
|
||||
addr_book_strict = true
|
||||
|
||||
# Maximum number of inbound peers
|
||||
max_num_inbound_peers = 40
|
||||
|
||||
# Maximum number of outbound peers to connect to, excluding persistent peers
|
||||
max_num_outbound_peers = 10
|
||||
|
||||
# List of node IDs, to which a connection will be (re)established ignoring any existing limits
|
||||
unconditional_peer_ids = ""
|
||||
|
||||
# Maximum pause when redialing a persistent peer (if zero, exponential backoff is used)
|
||||
persistent_peers_max_dial_period = "0s"
|
||||
|
||||
# Time to wait before flushing messages out on the connection
|
||||
flush_throttle_timeout = "100ms"
|
||||
|
||||
# Maximum size of a message packet payload, in bytes
|
||||
max_packet_msg_payload_size = 1024
|
||||
|
||||
# Rate at which packets can be sent, in bytes/second
|
||||
send_rate = 5120000
|
||||
|
||||
# Rate at which packets can be received, in bytes/second
|
||||
recv_rate = 5120000
|
||||
|
||||
# Set true to enable the peer-exchange reactor
|
||||
pex = true
|
||||
|
||||
# Seed mode, in which node constantly crawls the network and looks for
|
||||
# peers. If another node asks it for addresses, it responds and disconnects.
|
||||
#
|
||||
# Does not work if the peer-exchange reactor is disabled.
|
||||
seed_mode = false
|
||||
|
||||
# Comma separated list of peer IDs to keep private (will not be gossiped to other peers)
|
||||
private_peer_ids = ""
|
||||
|
||||
# Toggle to disable guard against peers connecting from the same ip.
|
||||
allow_duplicate_ip = false
|
||||
|
||||
# Peer connection configuration.
|
||||
handshake_timeout = "20s"
|
||||
dial_timeout = "3s"
|
||||
|
||||
#######################################################
|
||||
### Mempool Configuration Option ###
|
||||
#######################################################
|
||||
[mempool]
|
||||
|
||||
recheck = true
|
||||
broadcast = true
|
||||
wal_dir = ""
|
||||
|
||||
# Maximum number of transactions in the mempool
|
||||
size = 5000
|
||||
|
||||
# Limit the total size of all txs in the mempool.
|
||||
# This only accounts for raw transactions (e.g. given 1MB transactions and
|
||||
# max_txs_bytes=5MB, mempool will only accept 5 transactions).
|
||||
max_txs_bytes = 1073741824
|
||||
|
||||
# Size of the cache (used to filter transactions we saw earlier) in transactions
|
||||
cache_size = 10000
|
||||
|
||||
# Do not remove invalid transactions from the cache (default: false)
|
||||
# Set to true if it's not possible for any invalid transaction to become valid
|
||||
# again in the future.
|
||||
keep-invalid-txs-in-cache = false
|
||||
|
||||
# Maximum size of a single transaction.
|
||||
# NOTE: the max size of a tx transmitted over the network is {max_tx_bytes}.
|
||||
max_tx_bytes = 1048576
|
||||
|
||||
# Maximum size of a batch of transactions to send to a peer
|
||||
# Including space needed by encoding (one varint per transaction).
|
||||
# XXX: Unused due to https://github.com/tendermint/tendermint/issues/5796
|
||||
max_batch_bytes = 0
|
||||
|
||||
#######################################################
|
||||
### State Sync Configuration Options ###
|
||||
#######################################################
|
||||
[statesync]
|
||||
# State sync rapidly bootstraps a new node by discovering, fetching, and restoring a state machine
|
||||
# snapshot from peers instead of fetching and replaying historical blocks. Requires some peers in
|
||||
# the network to take and serve state machine snapshots. State sync is not attempted if the node
|
||||
# has any local state (LastBlockHeight > 0). The node will have a truncated block history,
|
||||
# starting from the height of the snapshot.
|
||||
enable = false
|
||||
|
||||
# RPC servers (comma-separated) for light client verification of the synced state machine and
|
||||
# retrieval of state data for node bootstrapping. Also needs a trusted height and corresponding
|
||||
# header hash obtained from a trusted source, and a period during which validators can be trusted.
|
||||
#
|
||||
# For Cosmos SDK-based chains, trust_period should usually be about 2/3 of the unbonding time (~2
|
||||
# weeks) during which they can be financially punished (slashed) for misbehavior.
|
||||
rpc_servers = ""
|
||||
trust_height = 0
|
||||
trust_hash = ""
|
||||
trust_period = "168h0m0s"
|
||||
|
||||
# Time to spend discovering snapshots before initiating a restore.
|
||||
discovery_time = "15s"
|
||||
|
||||
# Temporary directory for state sync snapshot chunks, defaults to the OS tempdir (typically /tmp).
|
||||
# Will create a new, randomly named directory within, and remove it when done.
|
||||
temp_dir = ""
|
||||
|
||||
# The timeout duration before re-requesting a chunk, possibly from a different
|
||||
# peer (default: 1 minute).
|
||||
chunk_request_timeout = "10s"
|
||||
|
||||
# The number of concurrent chunk fetchers to run (default: 1).
|
||||
chunk_fetchers = "4"
|
||||
|
||||
#######################################################
|
||||
### Fast Sync Configuration Connections ###
|
||||
#######################################################
|
||||
[fastsync]
|
||||
|
||||
# Fast Sync version to use:
|
||||
# 1) "v0" (default) - the legacy fast sync implementation
|
||||
# 2) "v1" - refactor of v0 version for better testability
|
||||
# 2) "v2" - complete redesign of v0, optimized for testability & readability
|
||||
version = "v0"
|
||||
|
||||
#######################################################
|
||||
### Consensus Configuration Options ###
|
||||
#######################################################
|
||||
[consensus]
|
||||
|
||||
wal_file = "data/cs.wal/wal"
|
||||
|
||||
# How long we wait for a proposal block before prevoting nil
|
||||
timeout_propose = "3s"
|
||||
# How much timeout_propose increases with each round
|
||||
timeout_propose_delta = "500ms"
|
||||
# How long we wait after receiving +2/3 prevotes for “anything” (ie. not a single block or nil)
|
||||
timeout_prevote = "1s"
|
||||
# How much the timeout_prevote increases with each round
|
||||
timeout_prevote_delta = "500ms"
|
||||
# How long we wait after receiving +2/3 precommits for “anything” (ie. not a single block or nil)
|
||||
timeout_precommit = "1s"
|
||||
# How much the timeout_precommit increases with each round
|
||||
timeout_precommit_delta = "500ms"
|
||||
# How long we wait after committing a block, before starting on the new
|
||||
# height (this gives us a chance to receive some more precommits, even
|
||||
# though we already have +2/3).
|
||||
timeout_commit = "1s"
|
||||
|
||||
# How many blocks to look back to check existence of the node's consensus votes before joining consensus
|
||||
# When non-zero, the node will panic upon restart
|
||||
# if the same consensus key was used to sign {double_sign_check_height} last blocks.
|
||||
# So, validators should stop the state machine, wait for some blocks, and then restart the state machine to avoid panic.
|
||||
double_sign_check_height = 0
|
||||
|
||||
# Make progress as soon as we have all the precommits (as if TimeoutCommit = 0)
|
||||
skip_timeout_commit = false
|
||||
|
||||
# EmptyBlocks mode and possible interval between empty blocks
|
||||
create_empty_blocks = true
|
||||
create_empty_blocks_interval = "0s"
|
||||
|
||||
# Reactor sleep duration parameters
|
||||
peer_gossip_sleep_duration = "100ms"
|
||||
peer_query_maj23_sleep_duration = "2s"
|
||||
|
||||
#######################################################
|
||||
### Transaction Indexer Configuration Options ###
|
||||
#######################################################
|
||||
[tx_index]
|
||||
|
||||
# What indexer to use for transactions
|
||||
#
|
||||
# The application will set which txs to index. In some cases a node operator will be able
|
||||
# to decide which txs to index based on configuration set in the application.
|
||||
#
|
||||
# Options:
|
||||
# 1) "null"
|
||||
# 2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend).
|
||||
# - When "kv" is chosen "tx.height" and "tx.hash" will always be indexed.
|
||||
indexer = "kv"
|
||||
|
||||
#######################################################
|
||||
### Instrumentation Configuration Options ###
|
||||
#######################################################
|
||||
[instrumentation]
|
||||
|
||||
# When true, Prometheus metrics are served under /metrics on
|
||||
# PrometheusListenAddr.
|
||||
# Check out the documentation for the list of available metrics.
|
||||
prometheus = false
|
||||
|
||||
# Address to listen for Prometheus collector(s) connections
|
||||
prometheus_listen_addr = ":26660"
|
||||
|
||||
# Maximum number of simultaneous connections.
|
||||
# If you want to accept a larger number than the default, make sure
|
||||
# you increase your OS limits.
|
||||
# 0 - unlimited.
|
||||
max_open_connections = 3
|
||||
|
||||
# Instrumentation namespace
|
||||
namespace = "tendermint"
|
||||
+527
@@ -0,0 +1,527 @@
|
||||
# This is a TOML config file.
|
||||
# For more information, see https://github.com/toml-lang/toml
|
||||
|
||||
# NOTE: Any path below can be absolute (e.g. "/var/myawesomeapp/data") or
|
||||
# relative to the home directory (e.g. "data"). The home directory is
|
||||
# "$HOME/.tendermint" by default, but could be changed via $TMHOME env variable
|
||||
# or --home cmd flag.
|
||||
|
||||
#######################################################################
|
||||
### Main Base Config Options ###
|
||||
#######################################################################
|
||||
|
||||
# TCP or UNIX socket address of the ABCI application,
|
||||
# or the name of an ABCI application compiled in with the Tendermint binary
|
||||
proxy-app = "tcp://127.0.0.1:26658"
|
||||
|
||||
# A custom human readable name for this node
|
||||
moniker = "localhost"
|
||||
|
||||
# Mode of Node: full | validator | seed
|
||||
# * validator node
|
||||
# - all reactors
|
||||
# - with priv_validator_key.json, priv_validator_state.json
|
||||
# * full node
|
||||
# - all reactors
|
||||
# - No priv_validator_key.json, priv_validator_state.json
|
||||
# * seed node
|
||||
# - only P2P, PEX Reactor
|
||||
# - No priv_validator_key.json, priv_validator_state.json
|
||||
mode = "validator"
|
||||
|
||||
# Database backend: goleveldb | cleveldb | boltdb | rocksdb | badgerdb
|
||||
# * goleveldb (github.com/syndtr/goleveldb - most popular implementation)
|
||||
# - pure go
|
||||
# - stable
|
||||
# * cleveldb (uses levigo wrapper)
|
||||
# - fast
|
||||
# - requires gcc
|
||||
# - use cleveldb build tag (go build -tags cleveldb)
|
||||
# * boltdb (uses etcd's fork of bolt - github.com/etcd-io/bbolt)
|
||||
# - EXPERIMENTAL
|
||||
# - may be faster is some use-cases (random reads - indexer)
|
||||
# - use boltdb build tag (go build -tags boltdb)
|
||||
# * rocksdb (uses github.com/tecbot/gorocksdb)
|
||||
# - EXPERIMENTAL
|
||||
# - requires gcc
|
||||
# - use rocksdb build tag (go build -tags rocksdb)
|
||||
# * badgerdb (uses github.com/dgraph-io/badger)
|
||||
# - EXPERIMENTAL
|
||||
# - use badgerdb build tag (go build -tags badgerdb)
|
||||
db-backend = "goleveldb"
|
||||
|
||||
# Database directory
|
||||
db-dir = "data"
|
||||
|
||||
# Output level for logging, including package level options
|
||||
log-level = "info"
|
||||
|
||||
# Output format: 'plain' (colored text) or 'json'
|
||||
log-format = "plain"
|
||||
|
||||
##### additional base config options #####
|
||||
|
||||
# Path to the JSON file containing the initial validator set and other meta data
|
||||
genesis-file = "config/genesis.json"
|
||||
|
||||
# Path to the JSON file containing the private key to use for node authentication in the p2p protocol
|
||||
node-key-file = "config/node_key.json"
|
||||
|
||||
# Mechanism to connect to the ABCI application: socket | grpc
|
||||
abci = "socket"
|
||||
|
||||
# If true, query the ABCI app on connecting to a new peer
|
||||
# so the app can decide if we should keep the connection or not
|
||||
filter-peers = false
|
||||
|
||||
|
||||
#######################################################
|
||||
### Priv Validator Configuration ###
|
||||
#######################################################
|
||||
[priv-validator]
|
||||
|
||||
# Path to the JSON file containing the private key to use as a validator in the consensus protocol
|
||||
key-file = "config/priv_validator_key.json"
|
||||
|
||||
# Path to the JSON file containing the last sign state of a validator
|
||||
state-file = "data/priv_validator_state.json"
|
||||
|
||||
# TCP or UNIX socket address for Tendermint to listen on for
|
||||
# connections from an external PrivValidator process
|
||||
# when the listenAddr is prefixed with grpc instead of tcp it will use the gRPC Client
|
||||
laddr = ""
|
||||
|
||||
# Path to the client certificate generated while creating needed files for secure connection.
|
||||
# If a remote validator address is provided but no certificate, the connection will be insecure
|
||||
client-certificate-file = ""
|
||||
|
||||
# Client key generated while creating certificates for secure connection
|
||||
client-key-file = ""
|
||||
|
||||
# Path to the Root Certificate Authority used to sign both client and server certificates
|
||||
root-ca-file = ""
|
||||
|
||||
|
||||
#######################################################################
|
||||
### Advanced Configuration Options ###
|
||||
#######################################################################
|
||||
|
||||
#######################################################
|
||||
### RPC Server Configuration Options ###
|
||||
#######################################################
|
||||
[rpc]
|
||||
|
||||
# TCP or UNIX socket address for the RPC server to listen on
|
||||
laddr = "tcp://127.0.0.1:26657"
|
||||
|
||||
# A list of origins a cross-domain request can be executed from
|
||||
# Default value '[]' disables cors support
|
||||
# Use '["*"]' to allow any origin
|
||||
cors-allowed-origins = []
|
||||
|
||||
# A list of methods the client is allowed to use with cross-domain requests
|
||||
cors-allowed-methods = ["HEAD", "GET", "POST", ]
|
||||
|
||||
# A list of non simple headers the client is allowed to use with cross-domain requests
|
||||
cors-allowed-headers = ["Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time", ]
|
||||
|
||||
# TCP or UNIX socket address for the gRPC server to listen on
|
||||
# NOTE: This server only supports /broadcast_tx_commit
|
||||
# Deprecated gRPC in the RPC layer of Tendermint will be deprecated in 0.36.
|
||||
grpc-laddr = ""
|
||||
|
||||
# Maximum number of simultaneous connections.
|
||||
# Does not include RPC (HTTP&WebSocket) connections. See max-open-connections
|
||||
# If you want to accept a larger number than the default, make sure
|
||||
# you increase your OS limits.
|
||||
# 0 - unlimited.
|
||||
# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files}
|
||||
# 1024 - 40 - 10 - 50 = 924 = ~900
|
||||
# Deprecated gRPC in the RPC layer of Tendermint will be deprecated in 0.36.
|
||||
grpc-max-open-connections = 900
|
||||
|
||||
# Activate unsafe RPC commands like /dial-seeds and /unsafe-flush-mempool
|
||||
unsafe = false
|
||||
|
||||
# Maximum number of simultaneous connections (including WebSocket).
|
||||
# Does not include gRPC connections. See grpc-max-open-connections
|
||||
# If you want to accept a larger number than the default, make sure
|
||||
# you increase your OS limits.
|
||||
# 0 - unlimited.
|
||||
# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files}
|
||||
# 1024 - 40 - 10 - 50 = 924 = ~900
|
||||
max-open-connections = 900
|
||||
|
||||
# Maximum number of unique clientIDs that can /subscribe
|
||||
# If you're using /broadcast_tx_commit, set to the estimated maximum number
|
||||
# of broadcast_tx_commit calls per block.
|
||||
max-subscription-clients = 100
|
||||
|
||||
# Maximum number of unique queries a given client can /subscribe to
|
||||
# If you're using GRPC (or Local RPC client) and /broadcast_tx_commit, set to
|
||||
# the estimated # maximum number of broadcast_tx_commit calls per block.
|
||||
max-subscriptions-per-client = 5
|
||||
|
||||
# Experimental parameter to specify the maximum number of events a node will
|
||||
# buffer, per subscription, before returning an error and closing the
|
||||
# subscription. Must be set to at least 100, but higher values will accommodate
|
||||
# higher event throughput rates (and will use more memory).
|
||||
experimental-subscription-buffer-size = 200
|
||||
|
||||
# Experimental parameter to specify the maximum number of RPC responses that
|
||||
# can be buffered per WebSocket client. If clients cannot read from the
|
||||
# WebSocket endpoint fast enough, they will be disconnected, so increasing this
|
||||
# parameter may reduce the chances of them being disconnected (but will cause
|
||||
# the node to use more memory).
|
||||
#
|
||||
# Must be at least the same as "experimental-subscription-buffer-size",
|
||||
# otherwise connections could be dropped unnecessarily. This value should
|
||||
# ideally be somewhat higher than "experimental-subscription-buffer-size" to
|
||||
# accommodate non-subscription-related RPC responses.
|
||||
experimental-websocket-write-buffer-size = 200
|
||||
|
||||
# If a WebSocket client cannot read fast enough, at present we may
|
||||
# silently drop events instead of generating an error or disconnecting the
|
||||
# client.
|
||||
#
|
||||
# Enabling this experimental parameter will cause the WebSocket connection to
|
||||
# be closed instead if it cannot read fast enough, allowing for greater
|
||||
# predictability in subscription behavior.
|
||||
experimental-close-on-slow-client = false
|
||||
|
||||
# How long to wait for a tx to be committed during /broadcast_tx_commit.
|
||||
# WARNING: Using a value larger than 10s will result in increasing the
|
||||
# global HTTP write timeout, which applies to all connections and endpoints.
|
||||
# See https://github.com/tendermint/tendermint/issues/3435
|
||||
timeout-broadcast-tx-commit = "10s"
|
||||
|
||||
# Maximum size of request body, in bytes
|
||||
max-body-bytes = 1000000
|
||||
|
||||
# Maximum size of request header, in bytes
|
||||
max-header-bytes = 1048576
|
||||
|
||||
# The path to a file containing certificate that is used to create the HTTPS server.
|
||||
# Might be either absolute path or path related to Tendermint's config directory.
|
||||
# If the certificate is signed by a certificate authority,
|
||||
# the certFile should be the concatenation of the server's certificate, any intermediates,
|
||||
# and the CA's certificate.
|
||||
# NOTE: both tls-cert-file and tls-key-file must be present for Tendermint to create HTTPS server.
|
||||
# Otherwise, HTTP server is run.
|
||||
tls-cert-file = ""
|
||||
|
||||
# The path to a file containing matching private key that is used to create the HTTPS server.
|
||||
# Might be either absolute path or path related to Tendermint's config directory.
|
||||
# NOTE: both tls-cert-file and tls-key-file must be present for Tendermint to create HTTPS server.
|
||||
# Otherwise, HTTP server is run.
|
||||
tls-key-file = ""
|
||||
|
||||
# pprof listen address (https://golang.org/pkg/net/http/pprof)
|
||||
pprof-laddr = ""
|
||||
|
||||
#######################################################
|
||||
### P2P Configuration Options ###
|
||||
#######################################################
|
||||
[p2p]
|
||||
|
||||
# Enable the legacy p2p layer.
|
||||
use-legacy = false
|
||||
|
||||
# Select the p2p internal queue
|
||||
queue-type = "priority"
|
||||
|
||||
# Address to listen for incoming connections
|
||||
laddr = "tcp://0.0.0.0:26656"
|
||||
|
||||
# Address to advertise to peers for them to dial
|
||||
# If empty, will use the same port as the laddr,
|
||||
# and will introspect on the listener or use UPnP
|
||||
# to figure out the address. ip and port are required
|
||||
# example: 159.89.10.97:26656
|
||||
external-address = ""
|
||||
|
||||
# Comma separated list of seed nodes to connect to
|
||||
# We only use these if we can’t connect to peers in the addrbook
|
||||
# NOTE: not used by the new PEX reactor. Please use BootstrapPeers instead.
|
||||
# TODO: Remove once p2p refactor is complete
|
||||
# ref: https:#github.com/tendermint/tendermint/issues/5670
|
||||
seeds = ""
|
||||
|
||||
# Comma separated list of peers to be added to the peer store
|
||||
# on startup. Either BootstrapPeers or PersistentPeers are
|
||||
# needed for peer discovery
|
||||
bootstrap-peers = ""
|
||||
|
||||
# Comma separated list of nodes to keep persistent connections to
|
||||
persistent-peers = ""
|
||||
|
||||
# UPNP port forwarding
|
||||
upnp = false
|
||||
|
||||
# Path to address book
|
||||
# TODO: Remove once p2p refactor is complete in favor of peer store.
|
||||
addr-book-file = "config/addrbook.json"
|
||||
|
||||
# Set true for strict address routability rules
|
||||
# Set false for private or local networks
|
||||
addr-book-strict = true
|
||||
|
||||
# Maximum number of inbound peers
|
||||
#
|
||||
# TODO: Remove once p2p refactor is complete in favor of MaxConnections.
|
||||
# ref: https://github.com/tendermint/tendermint/issues/5670
|
||||
max-num-inbound-peers = 40
|
||||
|
||||
# Maximum number of outbound peers to connect to, excluding persistent peers
|
||||
#
|
||||
# TODO: Remove once p2p refactor is complete in favor of MaxConnections.
|
||||
# ref: https://github.com/tendermint/tendermint/issues/5670
|
||||
max-num-outbound-peers = 10
|
||||
|
||||
# Maximum number of connections (inbound and outbound).
|
||||
max-connections = 64
|
||||
|
||||
# Rate limits the number of incoming connection attempts per IP address.
|
||||
max-incoming-connection-attempts = 100
|
||||
|
||||
# List of node IDs, to which a connection will be (re)established ignoring any existing limits
|
||||
# TODO: Remove once p2p refactor is complete.
|
||||
# ref: https://github.com/tendermint/tendermint/issues/5670
|
||||
unconditional-peer-ids = ""
|
||||
|
||||
# Maximum pause when redialing a persistent peer (if zero, exponential backoff is used)
|
||||
# TODO: Remove once p2p refactor is complete
|
||||
# ref: https:#github.com/tendermint/tendermint/issues/5670
|
||||
persistent-peers-max-dial-period = "0s"
|
||||
|
||||
# Time to wait before flushing messages out on the connection
|
||||
# TODO: Remove once p2p refactor is complete
|
||||
# ref: https:#github.com/tendermint/tendermint/issues/5670
|
||||
flush-throttle-timeout = "100ms"
|
||||
|
||||
# Maximum size of a message packet payload, in bytes
|
||||
# TODO: Remove once p2p refactor is complete
|
||||
# ref: https:#github.com/tendermint/tendermint/issues/5670
|
||||
max-packet-msg-payload-size = 1400
|
||||
|
||||
# Rate at which packets can be sent, in bytes/second
|
||||
# TODO: Remove once p2p refactor is complete
|
||||
# ref: https:#github.com/tendermint/tendermint/issues/5670
|
||||
send-rate = 5120000
|
||||
|
||||
# Rate at which packets can be received, in bytes/second
|
||||
# TODO: Remove once p2p refactor is complete
|
||||
# ref: https:#github.com/tendermint/tendermint/issues/5670
|
||||
recv-rate = 5120000
|
||||
|
||||
# Set true to enable the peer-exchange reactor
|
||||
pex = true
|
||||
|
||||
# Comma separated list of peer IDs to keep private (will not be gossiped to other peers)
|
||||
# Warning: IPs will be exposed at /net_info, for more information https://github.com/tendermint/tendermint/issues/3055
|
||||
private-peer-ids = ""
|
||||
|
||||
# Toggle to disable guard against peers connecting from the same ip.
|
||||
allow-duplicate-ip = false
|
||||
|
||||
# Peer connection configuration.
|
||||
handshake-timeout = "20s"
|
||||
dial-timeout = "3s"
|
||||
|
||||
#######################################################
|
||||
### Mempool Configuration Option ###
|
||||
#######################################################
|
||||
[mempool]
|
||||
|
||||
# Mempool version to use:
|
||||
# 1) "v0" - The legacy non-prioritized mempool reactor.
|
||||
# 2) "v1" (default) - The prioritized mempool reactor.
|
||||
version = "v1"
|
||||
|
||||
recheck = true
|
||||
broadcast = true
|
||||
|
||||
# Maximum number of transactions in the mempool
|
||||
size = 5000
|
||||
|
||||
# Limit the total size of all txs in the mempool.
|
||||
# This only accounts for raw transactions (e.g. given 1MB transactions and
|
||||
# max-txs-bytes=5MB, mempool will only accept 5 transactions).
|
||||
max-txs-bytes = 1073741824
|
||||
|
||||
# Size of the cache (used to filter transactions we saw earlier) in transactions
|
||||
cache-size = 10000
|
||||
|
||||
# Do not remove invalid transactions from the cache (default: false)
|
||||
# Set to true if it's not possible for any invalid transaction to become valid
|
||||
# again in the future.
|
||||
keep-invalid-txs-in-cache = false
|
||||
|
||||
# Maximum size of a single transaction.
|
||||
# NOTE: the max size of a tx transmitted over the network is {max-tx-bytes}.
|
||||
max-tx-bytes = 1048576
|
||||
|
||||
# Maximum size of a batch of transactions to send to a peer
|
||||
# Including space needed by encoding (one varint per transaction).
|
||||
# XXX: Unused due to https://github.com/tendermint/tendermint/issues/5796
|
||||
max-batch-bytes = 0
|
||||
|
||||
# ttl-duration, if non-zero, defines the maximum amount of time a transaction
|
||||
# can exist for in the mempool.
|
||||
#
|
||||
# Note, if ttl-num-blocks is also defined, a transaction will be removed if it
|
||||
# has existed in the mempool at least ttl-num-blocks number of blocks or if it's
|
||||
# insertion time into the mempool is beyond ttl-duration.
|
||||
ttl-duration = "0s"
|
||||
|
||||
# ttl-num-blocks, if non-zero, defines the maximum number of blocks a transaction
|
||||
# can exist for in the mempool.
|
||||
#
|
||||
# Note, if ttl-duration is also defined, a transaction will be removed if it
|
||||
# has existed in the mempool at least ttl-num-blocks number of blocks or if
|
||||
# it's insertion time into the mempool is beyond ttl-duration.
|
||||
ttl-num-blocks = 0
|
||||
|
||||
#######################################################
|
||||
### State Sync Configuration Options ###
|
||||
#######################################################
|
||||
[statesync]
|
||||
# State sync rapidly bootstraps a new node by discovering, fetching, and restoring a state machine
|
||||
# snapshot from peers instead of fetching and replaying historical blocks. Requires some peers in
|
||||
# the network to take and serve state machine snapshots. State sync is not attempted if the node
|
||||
# has any local state (LastBlockHeight > 0). The node will have a truncated block history,
|
||||
# starting from the height of the snapshot.
|
||||
enable = false
|
||||
|
||||
# State sync uses light client verification to verify state. This can be done either through the
|
||||
# P2P layer or RPC layer. Set this to true to use the P2P layer. If false (default), RPC layer
|
||||
# will be used.
|
||||
use-p2p = false
|
||||
|
||||
# If using RPC, at least two addresses need to be provided. They should be compatible with net.Dial,
|
||||
# for example: "host.example.com:2125"
|
||||
rpc-servers = ""
|
||||
|
||||
# The hash and height of a trusted block. Must be within the trust-period.
|
||||
trust-height = 0
|
||||
trust-hash = ""
|
||||
|
||||
# The trust period should be set so that Tendermint can detect and gossip misbehavior before
|
||||
# it is considered expired. For chains based on the Cosmos SDK, one day less than the unbonding
|
||||
# period should suffice.
|
||||
trust-period = "168h0m0s"
|
||||
|
||||
# Time to spend discovering snapshots before initiating a restore.
|
||||
discovery-time = "15s"
|
||||
|
||||
# Temporary directory for state sync snapshot chunks, defaults to os.TempDir().
|
||||
# The synchronizer will create a new, randomly named directory within this directory
|
||||
# and remove it when the sync is complete.
|
||||
temp-dir = ""
|
||||
|
||||
# The timeout duration before re-requesting a chunk, possibly from a different
|
||||
# peer (default: 15 seconds).
|
||||
chunk-request-timeout = "15s"
|
||||
|
||||
# The number of concurrent chunk and block fetchers to run (default: 4).
|
||||
fetchers = "4"
|
||||
|
||||
#######################################################
|
||||
### Block Sync Configuration Connections ###
|
||||
#######################################################
|
||||
[blocksync]
|
||||
|
||||
# If this node is many blocks behind the tip of the chain, BlockSync
|
||||
# allows them to catchup quickly by downloading blocks in parallel
|
||||
# and verifying their commits
|
||||
enable = true
|
||||
|
||||
# Block Sync version to use:
|
||||
# 1) "v0" (default) - the standard Block Sync implementation
|
||||
# 2) "v2" - DEPRECATED, please use v0
|
||||
version = "v0"
|
||||
|
||||
#######################################################
|
||||
### Consensus Configuration Options ###
|
||||
#######################################################
|
||||
[consensus]
|
||||
|
||||
wal-file = "data/cs.wal/wal"
|
||||
|
||||
# How long we wait for a proposal block before prevoting nil
|
||||
timeout-propose = "3s"
|
||||
# How much timeout-propose increases with each round
|
||||
timeout-propose-delta = "500ms"
|
||||
# How long we wait after receiving +2/3 prevotes for “anything” (ie. not a single block or nil)
|
||||
timeout-prevote = "1s"
|
||||
# How much the timeout-prevote increases with each round
|
||||
timeout-prevote-delta = "500ms"
|
||||
# How long we wait after receiving +2/3 precommits for “anything” (ie. not a single block or nil)
|
||||
timeout-precommit = "1s"
|
||||
# How much the timeout-precommit increases with each round
|
||||
timeout-precommit-delta = "500ms"
|
||||
# How long we wait after committing a block, before starting on the new
|
||||
# height (this gives us a chance to receive some more precommits, even
|
||||
# though we already have +2/3).
|
||||
timeout-commit = "1s"
|
||||
|
||||
# How many blocks to look back to check existence of the node's consensus votes before joining consensus
|
||||
# When non-zero, the node will panic upon restart
|
||||
# if the same consensus key was used to sign {double-sign-check-height} last blocks.
|
||||
# So, validators should stop the state machine, wait for some blocks, and then restart the state machine to avoid panic.
|
||||
double-sign-check-height = 0
|
||||
|
||||
# Make progress as soon as we have all the precommits (as if TimeoutCommit = 0)
|
||||
skip-timeout-commit = false
|
||||
|
||||
# EmptyBlocks mode and possible interval between empty blocks
|
||||
create-empty-blocks = true
|
||||
create-empty-blocks-interval = "0s"
|
||||
|
||||
# Reactor sleep duration parameters
|
||||
peer-gossip-sleep-duration = "100ms"
|
||||
peer-query-maj23-sleep-duration = "2s"
|
||||
|
||||
#######################################################
|
||||
### Transaction Indexer Configuration Options ###
|
||||
#######################################################
|
||||
[tx-index]
|
||||
|
||||
# The backend database list to back the indexer.
|
||||
# If list contains "null" or "", meaning no indexer service will be used.
|
||||
#
|
||||
# The application will set which txs to index. In some cases a node operator will be able
|
||||
# to decide which txs to index based on configuration set in the application.
|
||||
#
|
||||
# Options:
|
||||
# 1) "null"
|
||||
# 2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend).
|
||||
# 3) "psql" - the indexer services backed by PostgreSQL.
|
||||
# When "kv" or "psql" is chosen "tx.height" and "tx.hash" will always be indexed.
|
||||
indexer = ["kv"]
|
||||
|
||||
# The PostgreSQL connection configuration, the connection format:
|
||||
# postgresql://<user>:<password>@<host>:<port>/<db>?<opts>
|
||||
psql-conn = ""
|
||||
|
||||
#######################################################
|
||||
### Instrumentation Configuration Options ###
|
||||
#######################################################
|
||||
[instrumentation]
|
||||
|
||||
# When true, Prometheus metrics are served under /metrics on
|
||||
# PrometheusListenAddr.
|
||||
# Check out the documentation for the list of available metrics.
|
||||
prometheus = false
|
||||
|
||||
# Address to listen for Prometheus collector(s) connections
|
||||
prometheus-listen-addr = ":26660"
|
||||
|
||||
# Maximum number of simultaneous connections.
|
||||
# If you want to accept a larger number than the default, make sure
|
||||
# you increase your OS limits.
|
||||
# 0 - unlimited.
|
||||
max-open-connections = 3
|
||||
|
||||
# Instrumentation namespace
|
||||
namespace = "tendermint"
|
||||
+479
@@ -0,0 +1,479 @@
|
||||
# This is a TOML config file.
|
||||
# For more information, see https://github.com/toml-lang/toml
|
||||
|
||||
# NOTE: Any path below can be absolute (e.g. "/var/myawesomeapp/data") or
|
||||
# relative to the home directory (e.g. "data"). The home directory is
|
||||
# "$HOME/.tendermint" by default, but could be changed via $TMHOME env variable
|
||||
# or --home cmd flag.
|
||||
|
||||
#######################################################################
|
||||
### Main Base Config Options ###
|
||||
#######################################################################
|
||||
|
||||
# TCP or UNIX socket address of the ABCI application,
|
||||
# or the name of an ABCI application compiled in with the Tendermint binary
|
||||
proxy-app = "tcp://127.0.0.1:26658"
|
||||
|
||||
# A custom human readable name for this node
|
||||
moniker = "localhost"
|
||||
|
||||
# Mode of Node: full | validator | seed
|
||||
# * validator node
|
||||
# - all reactors
|
||||
# - with priv_validator_key.json, priv_validator_state.json
|
||||
# * full node
|
||||
# - all reactors
|
||||
# - No priv_validator_key.json, priv_validator_state.json
|
||||
# * seed node
|
||||
# - only P2P, PEX Reactor
|
||||
# - No priv_validator_key.json, priv_validator_state.json
|
||||
mode = "validator"
|
||||
|
||||
# Database backend: goleveldb | cleveldb | boltdb | rocksdb | badgerdb
|
||||
# * goleveldb (github.com/syndtr/goleveldb - most popular implementation)
|
||||
# - pure go
|
||||
# - stable
|
||||
# * cleveldb (uses levigo wrapper)
|
||||
# - fast
|
||||
# - requires gcc
|
||||
# - use cleveldb build tag (go build -tags cleveldb)
|
||||
# * boltdb (uses etcd's fork of bolt - github.com/etcd-io/bbolt)
|
||||
# - EXPERIMENTAL
|
||||
# - may be faster is some use-cases (random reads - indexer)
|
||||
# - use boltdb build tag (go build -tags boltdb)
|
||||
# * rocksdb (uses github.com/tecbot/gorocksdb)
|
||||
# - EXPERIMENTAL
|
||||
# - requires gcc
|
||||
# - use rocksdb build tag (go build -tags rocksdb)
|
||||
# * badgerdb (uses github.com/dgraph-io/badger)
|
||||
# - EXPERIMENTAL
|
||||
# - use badgerdb build tag (go build -tags badgerdb)
|
||||
db-backend = "goleveldb"
|
||||
|
||||
# Database directory
|
||||
db-dir = "data"
|
||||
|
||||
# Output level for logging, including package level options
|
||||
log-level = "info"
|
||||
|
||||
# Output format: 'plain' (colored text) or 'json'
|
||||
log-format = "plain"
|
||||
|
||||
##### additional base config options #####
|
||||
|
||||
# Path to the JSON file containing the initial validator set and other meta data
|
||||
genesis-file = "config/genesis.json"
|
||||
|
||||
# Path to the JSON file containing the private key to use for node authentication in the p2p protocol
|
||||
node-key-file = "config/node_key.json"
|
||||
|
||||
# Mechanism to connect to the ABCI application: socket | grpc
|
||||
abci = "socket"
|
||||
|
||||
# If true, query the ABCI app on connecting to a new peer
|
||||
# so the app can decide if we should keep the connection or not
|
||||
filter-peers = false
|
||||
|
||||
|
||||
#######################################################
|
||||
### Priv Validator Configuration ###
|
||||
#######################################################
|
||||
[priv-validator]
|
||||
|
||||
# Path to the JSON file containing the private key to use as a validator in the consensus protocol
|
||||
key-file = "config/priv_validator_key.json"
|
||||
|
||||
# Path to the JSON file containing the last sign state of a validator
|
||||
state-file = "data/priv_validator_state.json"
|
||||
|
||||
# TCP or UNIX socket address for Tendermint to listen on for
|
||||
# connections from an external PrivValidator process
|
||||
# when the listenAddr is prefixed with grpc instead of tcp it will use the gRPC Client
|
||||
laddr = ""
|
||||
|
||||
# Path to the client certificate generated while creating needed files for secure connection.
|
||||
# If a remote validator address is provided but no certificate, the connection will be insecure
|
||||
client-certificate-file = ""
|
||||
|
||||
# Client key generated while creating certificates for secure connection
|
||||
client-key-file = ""
|
||||
|
||||
# Path to the Root Certificate Authority used to sign both client and server certificates
|
||||
root-ca-file = ""
|
||||
|
||||
|
||||
#######################################################################
|
||||
### Advanced Configuration Options ###
|
||||
#######################################################################
|
||||
|
||||
#######################################################
|
||||
### RPC Server Configuration Options ###
|
||||
#######################################################
|
||||
[rpc]
|
||||
|
||||
# TCP or UNIX socket address for the RPC server to listen on
|
||||
laddr = "tcp://127.0.0.1:26657"
|
||||
|
||||
# A list of origins a cross-domain request can be executed from
|
||||
# Default value '[]' disables cors support
|
||||
# Use '["*"]' to allow any origin
|
||||
cors-allowed-origins = []
|
||||
|
||||
# A list of methods the client is allowed to use with cross-domain requests
|
||||
cors-allowed-methods = ["HEAD", "GET", "POST", ]
|
||||
|
||||
# A list of non simple headers the client is allowed to use with cross-domain requests
|
||||
cors-allowed-headers = ["Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time", ]
|
||||
|
||||
# Activate unsafe RPC commands like /dial-seeds and /unsafe-flush-mempool
|
||||
unsafe = false
|
||||
|
||||
# Maximum number of simultaneous connections (including WebSocket).
|
||||
# If you want to accept a larger number than the default, make sure
|
||||
# you increase your OS limits.
|
||||
# 0 - unlimited.
|
||||
# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files}
|
||||
# 1024 - 40 - 10 - 50 = 924 = ~900
|
||||
max-open-connections = 900
|
||||
|
||||
# Maximum number of unique clientIDs that can /subscribe
|
||||
# If you're using /broadcast_tx_commit, set to the estimated maximum number
|
||||
# of broadcast_tx_commit calls per block.
|
||||
max-subscription-clients = 100
|
||||
|
||||
# Maximum number of unique queries a given client can /subscribe to
|
||||
# If you're using a Local RPC client and /broadcast_tx_commit, set this
|
||||
# to the estimated maximum number of broadcast_tx_commit calls per block.
|
||||
max-subscriptions-per-client = 5
|
||||
|
||||
# If true, disable the websocket interface to the RPC service. This has
|
||||
# the effect of disabling the /subscribe, /unsubscribe, and /unsubscribe_all
|
||||
# methods for event subscription.
|
||||
#
|
||||
# EXPERIMENTAL: This setting will be removed in Tendermint v0.37.
|
||||
experimental-disable-websocket = false
|
||||
|
||||
# The time window size for the event log. All events up to this long before
|
||||
# the latest (up to EventLogMaxItems) will be available for subscribers to
|
||||
# fetch via the /events method. If 0 (the default) the event log and the
|
||||
# /events RPC method are disabled.
|
||||
event-log-window-size = "0s"
|
||||
|
||||
# The maxiumum number of events that may be retained by the event log. If
|
||||
# this value is 0, no upper limit is set. Otherwise, items in excess of
|
||||
# this number will be discarded from the event log.
|
||||
#
|
||||
# Warning: This setting is a safety valve. Setting it too low may cause
|
||||
# subscribers to miss events. Try to choose a value higher than the
|
||||
# maximum worst-case expected event load within the chosen window size in
|
||||
# ordinary operation.
|
||||
#
|
||||
# For example, if the window size is 10 minutes and the node typically
|
||||
# averages 1000 events per ten minutes, but with occasional known spikes of
|
||||
# up to 2000, choose a value > 2000.
|
||||
event-log-max-items = 0
|
||||
|
||||
# How long to wait for a tx to be committed during /broadcast_tx_commit.
|
||||
# WARNING: Using a value larger than 10s will result in increasing the
|
||||
# global HTTP write timeout, which applies to all connections and endpoints.
|
||||
# See https://github.com/tendermint/tendermint/issues/3435
|
||||
timeout-broadcast-tx-commit = "10s"
|
||||
|
||||
# Maximum size of request body, in bytes
|
||||
max-body-bytes = 1000000
|
||||
|
||||
# Maximum size of request header, in bytes
|
||||
max-header-bytes = 1048576
|
||||
|
||||
# The path to a file containing certificate that is used to create the HTTPS server.
|
||||
# Might be either absolute path or path related to Tendermint's config directory.
|
||||
# If the certificate is signed by a certificate authority,
|
||||
# the certFile should be the concatenation of the server's certificate, any intermediates,
|
||||
# and the CA's certificate.
|
||||
# NOTE: both tls-cert-file and tls-key-file must be present for Tendermint to create HTTPS server.
|
||||
# Otherwise, HTTP server is run.
|
||||
tls-cert-file = ""
|
||||
|
||||
# The path to a file containing matching private key that is used to create the HTTPS server.
|
||||
# Might be either absolute path or path related to Tendermint's config directory.
|
||||
# NOTE: both tls-cert-file and tls-key-file must be present for Tendermint to create HTTPS server.
|
||||
# Otherwise, HTTP server is run.
|
||||
tls-key-file = ""
|
||||
|
||||
# pprof listen address (https://golang.org/pkg/net/http/pprof)
|
||||
pprof-laddr = ""
|
||||
|
||||
#######################################################
|
||||
### P2P Configuration Options ###
|
||||
#######################################################
|
||||
[p2p]
|
||||
|
||||
# Select the p2p internal queue
|
||||
queue-type = "priority"
|
||||
|
||||
# Address to listen for incoming connections
|
||||
laddr = "tcp://0.0.0.0:26656"
|
||||
|
||||
# Address to advertise to peers for them to dial
|
||||
# If empty, will use the same port as the laddr,
|
||||
# and will introspect on the listener or use UPnP
|
||||
# to figure out the address. ip and port are required
|
||||
# example: 159.89.10.97:26656
|
||||
external-address = ""
|
||||
|
||||
# Comma separated list of seed nodes to connect to
|
||||
# We only use these if we can’t connect to peers in the addrbook
|
||||
# NOTE: not used by the new PEX reactor. Please use BootstrapPeers instead.
|
||||
# TODO: Remove once p2p refactor is complete
|
||||
# ref: https:#github.com/tendermint/tendermint/issues/5670
|
||||
seeds = ""
|
||||
|
||||
# Comma separated list of peers to be added to the peer store
|
||||
# on startup. Either BootstrapPeers or PersistentPeers are
|
||||
# needed for peer discovery
|
||||
bootstrap-peers = ""
|
||||
|
||||
# Comma separated list of nodes to keep persistent connections to
|
||||
persistent-peers = ""
|
||||
|
||||
# UPNP port forwarding
|
||||
upnp = false
|
||||
|
||||
# Maximum number of connections (inbound and outbound).
|
||||
max-connections = 64
|
||||
|
||||
# Rate limits the number of incoming connection attempts per IP address.
|
||||
max-incoming-connection-attempts = 100
|
||||
|
||||
# Set true to enable the peer-exchange reactor
|
||||
pex = true
|
||||
|
||||
# Comma separated list of peer IDs to keep private (will not be gossiped to other peers)
|
||||
# Warning: IPs will be exposed at /net_info, for more information https://github.com/tendermint/tendermint/issues/3055
|
||||
private-peer-ids = ""
|
||||
|
||||
# Toggle to disable guard against peers connecting from the same ip.
|
||||
allow-duplicate-ip = false
|
||||
|
||||
# Peer connection configuration.
|
||||
handshake-timeout = "20s"
|
||||
dial-timeout = "3s"
|
||||
|
||||
# Time to wait before flushing messages out on the connection
|
||||
# TODO: Remove once MConnConnection is removed.
|
||||
flush-throttle-timeout = "100ms"
|
||||
|
||||
# Maximum size of a message packet payload, in bytes
|
||||
# TODO: Remove once MConnConnection is removed.
|
||||
max-packet-msg-payload-size = 1400
|
||||
|
||||
# Rate at which packets can be sent, in bytes/second
|
||||
# TODO: Remove once MConnConnection is removed.
|
||||
send-rate = 5120000
|
||||
|
||||
# Rate at which packets can be received, in bytes/second
|
||||
# TODO: Remove once MConnConnection is removed.
|
||||
recv-rate = 5120000
|
||||
|
||||
|
||||
#######################################################
|
||||
### Mempool Configuration Option ###
|
||||
#######################################################
|
||||
[mempool]
|
||||
|
||||
recheck = true
|
||||
broadcast = true
|
||||
|
||||
# Maximum number of transactions in the mempool
|
||||
size = 5000
|
||||
|
||||
# Limit the total size of all txs in the mempool.
|
||||
# This only accounts for raw transactions (e.g. given 1MB transactions and
|
||||
# max-txs-bytes=5MB, mempool will only accept 5 transactions).
|
||||
max-txs-bytes = 1073741824
|
||||
|
||||
# Size of the cache (used to filter transactions we saw earlier) in transactions
|
||||
cache-size = 10000
|
||||
|
||||
# Do not remove invalid transactions from the cache (default: false)
|
||||
# Set to true if it's not possible for any invalid transaction to become valid
|
||||
# again in the future.
|
||||
keep-invalid-txs-in-cache = false
|
||||
|
||||
# Maximum size of a single transaction.
|
||||
# NOTE: the max size of a tx transmitted over the network is {max-tx-bytes}.
|
||||
max-tx-bytes = 1048576
|
||||
|
||||
# Maximum size of a batch of transactions to send to a peer
|
||||
# Including space needed by encoding (one varint per transaction).
|
||||
# XXX: Unused due to https://github.com/tendermint/tendermint/issues/5796
|
||||
max-batch-bytes = 0
|
||||
|
||||
# ttl-duration, if non-zero, defines the maximum amount of time a transaction
|
||||
# can exist for in the mempool.
|
||||
#
|
||||
# Note, if ttl-num-blocks is also defined, a transaction will be removed if it
|
||||
# has existed in the mempool at least ttl-num-blocks number of blocks or if it's
|
||||
# insertion time into the mempool is beyond ttl-duration.
|
||||
ttl-duration = "0s"
|
||||
|
||||
# ttl-num-blocks, if non-zero, defines the maximum number of blocks a transaction
|
||||
# can exist for in the mempool.
|
||||
#
|
||||
# Note, if ttl-duration is also defined, a transaction will be removed if it
|
||||
# has existed in the mempool at least ttl-num-blocks number of blocks or if
|
||||
# it's insertion time into the mempool is beyond ttl-duration.
|
||||
ttl-num-blocks = 0
|
||||
|
||||
#######################################################
|
||||
### State Sync Configuration Options ###
|
||||
#######################################################
|
||||
[statesync]
|
||||
# State sync rapidly bootstraps a new node by discovering, fetching, and restoring a state machine
|
||||
# snapshot from peers instead of fetching and replaying historical blocks. Requires some peers in
|
||||
# the network to take and serve state machine snapshots. State sync is not attempted if the node
|
||||
# has any local state (LastBlockHeight > 0). The node will have a truncated block history,
|
||||
# starting from the height of the snapshot.
|
||||
enable = false
|
||||
|
||||
# State sync uses light client verification to verify state. This can be done either through the
|
||||
# P2P layer or RPC layer. Set this to true to use the P2P layer. If false (default), RPC layer
|
||||
# will be used.
|
||||
use-p2p = false
|
||||
|
||||
# If using RPC, at least two addresses need to be provided. They should be compatible with net.Dial,
|
||||
# for example: "host.example.com:2125"
|
||||
rpc-servers = ""
|
||||
|
||||
# The hash and height of a trusted block. Must be within the trust-period.
|
||||
trust-height = 0
|
||||
trust-hash = ""
|
||||
|
||||
# The trust period should be set so that Tendermint can detect and gossip misbehavior before
|
||||
# it is considered expired. For chains based on the Cosmos SDK, one day less than the unbonding
|
||||
# period should suffice.
|
||||
trust-period = "168h0m0s"
|
||||
|
||||
# Time to spend discovering snapshots before initiating a restore.
|
||||
discovery-time = "15s"
|
||||
|
||||
# Temporary directory for state sync snapshot chunks, defaults to os.TempDir().
|
||||
# The synchronizer will create a new, randomly named directory within this directory
|
||||
# and remove it when the sync is complete.
|
||||
temp-dir = ""
|
||||
|
||||
# The timeout duration before re-requesting a chunk, possibly from a different
|
||||
# peer (default: 15 seconds).
|
||||
chunk-request-timeout = "15s"
|
||||
|
||||
# The number of concurrent chunk and block fetchers to run (default: 4).
|
||||
fetchers = "4"
|
||||
|
||||
#######################################################
|
||||
### Consensus Configuration Options ###
|
||||
#######################################################
|
||||
[consensus]
|
||||
|
||||
wal-file = "data/cs.wal/wal"
|
||||
|
||||
# How many blocks to look back to check existence of the node's consensus votes before joining consensus
|
||||
# When non-zero, the node will panic upon restart
|
||||
# if the same consensus key was used to sign {double-sign-check-height} last blocks.
|
||||
# So, validators should stop the state machine, wait for some blocks, and then restart the state machine to avoid panic.
|
||||
double-sign-check-height = 0
|
||||
|
||||
# EmptyBlocks mode and possible interval between empty blocks
|
||||
create-empty-blocks = true
|
||||
create-empty-blocks-interval = "0s"
|
||||
|
||||
# Reactor sleep duration parameters
|
||||
peer-gossip-sleep-duration = "100ms"
|
||||
peer-query-maj23-sleep-duration = "2s"
|
||||
|
||||
### Unsafe Timeout Overrides ###
|
||||
|
||||
# These fields provide temporary overrides for the Timeout consensus parameters.
|
||||
# Use of these parameters is strongly discouraged. Using these parameters may have serious
|
||||
# liveness implications for the validator and for the chain.
|
||||
#
|
||||
# These fields will be removed from the configuration file in the v0.37 release of Tendermint.
|
||||
# For additional information, see ADR-74:
|
||||
# https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-074-timeout-params.md
|
||||
|
||||
# This field provides an unsafe override of the Propose timeout consensus parameter.
|
||||
# This field configures how long the consensus engine will wait for a proposal block before prevoting nil.
|
||||
# If this field is set to a value greater than 0, it will take effect.
|
||||
# unsafe-propose-timeout-override = 0s
|
||||
|
||||
# This field provides an unsafe override of the ProposeDelta timeout consensus parameter.
|
||||
# This field configures how much the propose timeout increases with each round.
|
||||
# If this field is set to a value greater than 0, it will take effect.
|
||||
# unsafe-propose-timeout-delta-override = 0s
|
||||
|
||||
# This field provides an unsafe override of the Vote timeout consensus parameter.
|
||||
# This field configures how long the consensus engine will wait after
|
||||
# receiving +2/3 votes in a round.
|
||||
# If this field is set to a value greater than 0, it will take effect.
|
||||
# unsafe-vote-timeout-override = 0s
|
||||
|
||||
# This field provides an unsafe override of the VoteDelta timeout consensus parameter.
|
||||
# This field configures how much the vote timeout increases with each round.
|
||||
# If this field is set to a value greater than 0, it will take effect.
|
||||
# unsafe-vote-timeout-delta-override = 0s
|
||||
|
||||
# This field provides an unsafe override of the Commit timeout consensus parameter.
|
||||
# This field configures how long the consensus engine will wait after receiving
|
||||
# +2/3 precommits before beginning the next height.
|
||||
# If this field is set to a value greater than 0, it will take effect.
|
||||
# unsafe-commit-timeout-override = 0s
|
||||
|
||||
# This field provides an unsafe override of the BypassCommitTimeout consensus parameter.
|
||||
# This field configures if the consensus engine will wait for the full Commit timeout
|
||||
# before proceeding to the next height.
|
||||
# If this field is set to true, the consensus engine will proceed to the next height
|
||||
# as soon as the node has gathered votes from all of the validators on the network.
|
||||
# unsafe-bypass-commit-timeout-override =
|
||||
|
||||
#######################################################
|
||||
### Transaction Indexer Configuration Options ###
|
||||
#######################################################
|
||||
[tx-index]
|
||||
|
||||
# The backend database list to back the indexer.
|
||||
# If list contains "null" or "", meaning no indexer service will be used.
|
||||
#
|
||||
# The application will set which txs to index. In some cases a node operator will be able
|
||||
# to decide which txs to index based on configuration set in the application.
|
||||
#
|
||||
# Options:
|
||||
# 1) "null" (default) - no indexer services.
|
||||
# 2) "kv" - a simple indexer backed by key-value storage (see DBBackend)
|
||||
# 3) "psql" - the indexer services backed by PostgreSQL.
|
||||
# When "kv" or "psql" is chosen "tx.height" and "tx.hash" will always be indexed.
|
||||
indexer = ["null"]
|
||||
|
||||
# The PostgreSQL connection configuration, the connection format:
|
||||
# postgresql://<user>:<password>@<host>:<port>/<db>?<opts>
|
||||
psql-conn = ""
|
||||
|
||||
#######################################################
|
||||
### Instrumentation Configuration Options ###
|
||||
#######################################################
|
||||
[instrumentation]
|
||||
|
||||
# When true, Prometheus metrics are served under /metrics on
|
||||
# PrometheusListenAddr.
|
||||
# Check out the documentation for the list of available metrics.
|
||||
prometheus = false
|
||||
|
||||
# Address to listen for Prometheus collector(s) connections
|
||||
prometheus-listen-addr = ":26660"
|
||||
|
||||
# Maximum number of simultaneous connections.
|
||||
# If you want to accept a larger number than the default, make sure
|
||||
# you increase your OS limits.
|
||||
# 0 - unlimited.
|
||||
max-open-connections = 3
|
||||
|
||||
# Instrumentation namespace
|
||||
namespace = "tendermint"
|
||||
@@ -15,8 +15,8 @@ import (
|
||||
"math/rand"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/creachadair/taskgroup"
|
||||
"github.com/google/orderedcode"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
)
|
||||
@@ -27,7 +27,7 @@ type (
|
||||
)
|
||||
|
||||
func getAllLegacyKeys(db dbm.DB) ([]keyID, error) {
|
||||
out := []keyID{}
|
||||
var out []keyID
|
||||
|
||||
iter, err := db.Iterator(nil, nil)
|
||||
if err != nil {
|
||||
@@ -43,11 +43,8 @@ func getAllLegacyKeys(db dbm.DB) ([]keyID, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
// there's inconsistency around tm-db's handling of
|
||||
// key copies.
|
||||
nk := make([]byte, len(k))
|
||||
copy(nk, k)
|
||||
out = append(out, nk)
|
||||
// Make an explicit copy, since not all tm-db backends do.
|
||||
out = append(out, []byte(string(k)))
|
||||
}
|
||||
|
||||
if err = iter.Error(); err != nil {
|
||||
@@ -61,17 +58,6 @@ func getAllLegacyKeys(db dbm.DB) ([]keyID, error) {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func makeKeyChan(keys []keyID) <-chan keyID {
|
||||
out := make(chan keyID, len(keys))
|
||||
defer close(out)
|
||||
|
||||
for _, key := range keys {
|
||||
out <- key
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func keyIsLegacy(key keyID) bool {
|
||||
for _, prefix := range []keyID{
|
||||
// core "store"
|
||||
@@ -111,7 +97,7 @@ func keyIsHash(key keyID) bool {
|
||||
return len(key) == 32 && !bytes.Contains(key, []byte("/"))
|
||||
}
|
||||
|
||||
func migarateKey(key keyID) (keyID, error) {
|
||||
func migrateKey(key keyID) (keyID, error) {
|
||||
switch {
|
||||
case bytes.HasPrefix(key, keyID("H:")):
|
||||
val, err := strconv.Atoi(string(key[2:]))
|
||||
@@ -152,12 +138,16 @@ func migarateKey(key keyID) (keyID, error) {
|
||||
|
||||
return orderedcode.Append(nil, int64(3), int64(val))
|
||||
case bytes.HasPrefix(key, keyID("BH:")):
|
||||
val, err := strconv.Atoi(string(key[3:]))
|
||||
hash := string(key[3:])
|
||||
if len(hash)%2 == 1 {
|
||||
hash = "0" + hash
|
||||
}
|
||||
val, err := hex.DecodeString(hash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return orderedcode.Append(nil, int64(4), int64(val))
|
||||
return orderedcode.Append(nil, int64(4), string(val))
|
||||
case bytes.HasPrefix(key, keyID("validatorsKey:")):
|
||||
val, err := strconv.Atoi(string(key[14:]))
|
||||
if err != nil {
|
||||
@@ -349,53 +339,23 @@ func Migrate(ctx context.Context, db dbm.DB) error {
|
||||
return err
|
||||
}
|
||||
|
||||
numWorkers := runtime.NumCPU()
|
||||
wg := &sync.WaitGroup{}
|
||||
var errs []string
|
||||
g, start := taskgroup.New(func(err error) error {
|
||||
errs = append(errs, err.Error())
|
||||
return err
|
||||
}).Limit(runtime.NumCPU())
|
||||
|
||||
errs := make(chan error, numWorkers)
|
||||
|
||||
keyCh := makeKeyChan(keys)
|
||||
|
||||
// run migrations.
|
||||
for i := 0; i < numWorkers; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for key := range keyCh {
|
||||
err := replaceKey(db, key, migarateKey)
|
||||
if err != nil {
|
||||
errs <- err
|
||||
}
|
||||
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
for _, key := range keys {
|
||||
key := key
|
||||
start(func() error {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
}()
|
||||
return replaceKey(db, key, migrateKey)
|
||||
})
|
||||
}
|
||||
|
||||
// collect and process the errors.
|
||||
errStrs := []string{}
|
||||
signal := make(chan struct{})
|
||||
go func() {
|
||||
defer close(signal)
|
||||
for err := range errs {
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
errStrs = append(errStrs, err.Error())
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait for everything to be done.
|
||||
wg.Wait()
|
||||
close(errs)
|
||||
<-signal
|
||||
|
||||
// check the error results
|
||||
if len(errs) != 0 {
|
||||
return fmt.Errorf("encountered errors during migration: %v", errStrs)
|
||||
if g.Wait() != nil {
|
||||
return fmt.Errorf("encountered errors during migration: %q", errs)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func getLegacyPrefixKeys(val int) map[string][]byte {
|
||||
"BlockPartTwo": []byte(fmt.Sprintf("P:%d:%d", val+2, val+val)),
|
||||
"BlockCommit": []byte(fmt.Sprintf("C:%d", val)),
|
||||
"SeenCommit": []byte(fmt.Sprintf("SC:%d", val)),
|
||||
"BlockHeight": []byte(fmt.Sprintf("BH:%d", val)),
|
||||
"BlockHeight": []byte(fmt.Sprintf("BH:%x", val)),
|
||||
"Validators": []byte(fmt.Sprintf("validatorsKey:%d", val)),
|
||||
"ConsensusParams": []byte(fmt.Sprintf("consensusParamsKey:%d", val)),
|
||||
"ABCIResponse": []byte(fmt.Sprintf("abciResponsesKey:%d", val)),
|
||||
@@ -117,7 +117,7 @@ func TestMigration(t *testing.T) {
|
||||
})
|
||||
t.Run("Conversion", func(t *testing.T) {
|
||||
for kind, le := range legacyPrefixes {
|
||||
nk, err := migarateKey(le)
|
||||
nk, err := migrateKey(le)
|
||||
require.NoError(t, err, kind)
|
||||
require.False(t, keyIsLegacy(nk), kind)
|
||||
}
|
||||
@@ -159,7 +159,7 @@ func TestMigration(t *testing.T) {
|
||||
"UserKey3": []byte("foo/bar/baz/1.2/4"),
|
||||
}
|
||||
for kind, key := range table {
|
||||
out, err := migarateKey(key)
|
||||
out, err := migrateKey(key)
|
||||
require.Error(t, err, kind)
|
||||
require.Nil(t, out, kind)
|
||||
}
|
||||
@@ -177,7 +177,7 @@ func TestMigration(t *testing.T) {
|
||||
return nil, errors.New("hi")
|
||||
}))
|
||||
})
|
||||
t.Run("KeyDisapears", func(t *testing.T) {
|
||||
t.Run("KeyDisappears", func(t *testing.T) {
|
||||
db := dbm.NewMemDB()
|
||||
key := keyID("hi")
|
||||
require.NoError(t, db.Set(key, []byte("world")))
|
||||
@@ -215,17 +215,6 @@ func TestMigration(t *testing.T) {
|
||||
require.False(t, keyIsLegacy(key))
|
||||
}
|
||||
})
|
||||
t.Run("ChannelConversion", func(t *testing.T) {
|
||||
ch := makeKeyChan([]keyID{
|
||||
makeKey(t, "abc", int64(2), int64(42)),
|
||||
makeKey(t, int64(42)),
|
||||
})
|
||||
count := 0
|
||||
for range ch {
|
||||
count++
|
||||
}
|
||||
require.Equal(t, 2, count)
|
||||
})
|
||||
t.Run("Migrate", func(t *testing.T) {
|
||||
_, db := getLegacyDatabase(t)
|
||||
|
||||
|
||||
@@ -73,8 +73,6 @@ func sortMigrations(scData []toMigrate) {
|
||||
})
|
||||
}
|
||||
|
||||
func getMigrationsToDelete(in []toMigrate) []toMigrate { return in[1:] }
|
||||
|
||||
func getAllSeenCommits(ctx context.Context, db dbm.DB) ([]toMigrate, error) {
|
||||
scKeyPrefix := makeKeyFromPrefix(prefixSeenCommit)
|
||||
iter, err := db.Iterator(
|
||||
@@ -117,6 +115,34 @@ func getAllSeenCommits(ctx context.Context, db dbm.DB) ([]toMigrate, error) {
|
||||
return scData, nil
|
||||
}
|
||||
|
||||
func renameRecord(ctx context.Context, db dbm.DB, keep toMigrate) error {
|
||||
wantKey := makeKeyFromPrefix(prefixSeenCommit)
|
||||
if bytes.Equal(keep.key, wantKey) {
|
||||
return nil // we already did this conversion
|
||||
}
|
||||
|
||||
// This record's key has already been converted to the "new" format, we just
|
||||
// now need to trim off the tail.
|
||||
val, err := db.Get(keep.key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
batch := db.NewBatch()
|
||||
if err := batch.Delete(keep.key); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := batch.Set(wantKey, val); err != nil {
|
||||
return err
|
||||
}
|
||||
werr := batch.Write()
|
||||
cerr := batch.Close()
|
||||
if werr != nil {
|
||||
return werr
|
||||
}
|
||||
return cerr
|
||||
}
|
||||
|
||||
func deleteRecords(ctx context.Context, db dbm.DB, scData []toMigrate) error {
|
||||
// delete all the remaining stale values in a single batch
|
||||
batch := db.NewBatch()
|
||||
@@ -141,20 +167,29 @@ func Migrate(ctx context.Context, db dbm.DB) error {
|
||||
scData, err := getAllSeenCommits(ctx, db)
|
||||
if err != nil {
|
||||
return fmt.Errorf("sourcing tasks to migrate: %w", err)
|
||||
} else if len(scData) == 0 {
|
||||
return nil // nothing to do
|
||||
}
|
||||
|
||||
// sort earliest->latest commits.
|
||||
// Sort commits in decreasing order of height.
|
||||
sortMigrations(scData)
|
||||
|
||||
// trim the one we want to save:
|
||||
scData = getMigrationsToDelete(scData)
|
||||
// Keep and rename the newest seen commit, delete the rest.
|
||||
// In TM < v0.35 we kept a last-seen commit for each height; in v0.35 we
|
||||
// retain only the latest.
|
||||
keep, remove := scData[0], scData[1:]
|
||||
|
||||
if len(scData) <= 1 {
|
||||
if err := renameRecord(ctx, db, keep); err != nil {
|
||||
return fmt.Errorf("renaming seen commit record: %w", err)
|
||||
}
|
||||
|
||||
if len(remove) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// write the migration (remove )
|
||||
if err := deleteRecords(ctx, db, scData); err != nil {
|
||||
// Remove any older seen commits. Prior to v0.35, we kept these records for
|
||||
// all heights, but v0.35 keeps only the latest.
|
||||
if err := deleteRecords(ctx, db, remove); err != nil {
|
||||
return fmt.Errorf("writing data: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package scmigrate
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"math/rand"
|
||||
"testing"
|
||||
@@ -104,15 +105,6 @@ func TestMigrations(t *testing.T) {
|
||||
assertWellOrderedMigrations(t, testData)
|
||||
})
|
||||
})
|
||||
t.Run("GetMigrationsToDelete", func(t *testing.T) {
|
||||
for i := 1; i < 100; i++ {
|
||||
data := appendRandomMigrations([]toMigrate{}, i)
|
||||
toMigrate := getMigrationsToDelete(data)
|
||||
if len(data) != len(toMigrate)+1 {
|
||||
t.Fatalf("migration prep did not save one document [original=%d migrations=%d]", len(data), len(toMigrate))
|
||||
}
|
||||
}
|
||||
})
|
||||
t.Run("InvalidMigrations", func(t *testing.T) {
|
||||
if _, err := makeToMigrate(nil); err == nil {
|
||||
t.Fatal("should error for nil migrations")
|
||||
@@ -156,18 +148,24 @@ func TestMigrations(t *testing.T) {
|
||||
// safe to rerun
|
||||
t.Run(test, func(t *testing.T) {
|
||||
if err := Migrate(ctx, db); err != nil {
|
||||
t.Fatal(err)
|
||||
t.Fatalf("Migration failed: %v", err)
|
||||
}
|
||||
|
||||
post, err := getAllSeenCommits(ctx, db)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
t.Fatalf("Fetching seen commits: %v", err)
|
||||
}
|
||||
|
||||
if len(post) != 1 {
|
||||
t.Fatal("migration was not successful")
|
||||
t.Fatalf("Wrong number of commits: got %d, wanted 1", len(post))
|
||||
}
|
||||
if post[0].commit.Height != latestHeight {
|
||||
t.Fatal("migration did not save correct document")
|
||||
|
||||
wantKey := makeKeyFromPrefix(prefixSeenCommit)
|
||||
if !bytes.Equal(post[0].key, wantKey) {
|
||||
t.Errorf("Seen commit key: got %x, want %x", post[0].key, wantKey)
|
||||
}
|
||||
if got := post[0].commit.Height; got != latestHeight {
|
||||
t.Fatalf("Wrong commit height after migration: got %d, wanted %d", got, latestHeight)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -287,12 +287,14 @@ title: Methods
|
||||
|
||||
| Name | Type | Description | Field Number |
|
||||
|-------------------------|---------------------------------------------|------------------------------------------------------------------------------------------------------------------|--------------|
|
||||
| hash | bytes | The block header's hash of the block to propose. Present for convenience (can be derived from the block header). | 1 |
|
||||
| header | [Header](../core/data_structures.md#header) | The header of the block to propose. | 2 |
|
||||
| txs | repeated bytes | Preliminary list of transactions that have been picked as part of the block to propose. | 3 |
|
||||
| local_last_commit | [ExtendedCommitInfo](#extendedcommitinfo) | Info about the last commit, obtained locally from Tendermint's data structures. | 4 |
|
||||
| byzantine_validators | repeated [Evidence](#evidence) | List of evidence of validators that acted maliciously. | 5 |
|
||||
| max_tx_bytes | int64 | Currently configured maximum size in bytes taken by the modified transactions. | 6 |
|
||||
| max_tx_bytes | int64 | Currently configured maximum size in bytes taken by the modified transactions. | 1 |
|
||||
| txs | repeated bytes | Preliminary list of transactions that have been picked as part of the block to propose. | 2 |
|
||||
| local_last_commit | [ExtendedCommitInfo](#extendedcommitinfo) | Info about the last commit, obtained locally from Tendermint's data structures. | 3 |
|
||||
| byzantine_validators | repeated [Misbehavior](#misbehavior) | List of information about validators that acted incorrectly. | 4 |
|
||||
| height | int64 | The height of the block that will be proposed. | 5 |
|
||||
| time | [google.protobuf.Timestamp](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Timestamp) | Timestamp of the block that that will be proposed. | 6 |
|
||||
| next_validators_hash | bytes | Merkle root of the next validator set. | 7 |
|
||||
| proposer_address | bytes | [Address](../core/data_structures.md#address) of the validator that is creating the proposal. | 8 |
|
||||
|
||||
* **Response**:
|
||||
|
||||
@@ -305,10 +307,9 @@ title: Methods
|
||||
| consensus_param_updates | [ConsensusParams](#consensusparams) | Changes to consensus-critical gas, size, and other parameters. | 6 |
|
||||
|
||||
* **Usage**:
|
||||
* The first five parameters of `RequestPrepareProposal` are the same as `RequestProcessProposal`
|
||||
* The first six parameters of `RequestPrepareProposal` are the same as `RequestProcessProposal`
|
||||
and `RequestFinalizeBlock`.
|
||||
* The header contains the height, timestamp, and more - it exactly matches the
|
||||
Tendermint block header.
|
||||
* The height and time values match the values from the header of the proposed block.
|
||||
* `RequestPrepareProposal` contains a preliminary set of transactions `txs` that Tendermint considers to be a good block proposal, called _raw proposal_. The Application can modify this set via `ResponsePrepareProposal.tx_records` (see [TxRecord](#txrecord)).
|
||||
* The Application _can_ reorder, remove or add transactions to the raw proposal. Let `tx` be a transaction in `txs`:
|
||||
* If the Application considers that `tx` should not be proposed in this block, e.g., there are other transactions with higher priority, then it should not include it in `tx_records`. In this case, Tendermint won't remove `tx` from the mempool. The Application should be extra-careful, as abusing this feature may cause transactions to stay forever in the mempool.
|
||||
@@ -369,7 +370,7 @@ and _p_'s _validValue_ is `nil`:
|
||||
* _p_'s Tendermint creates a block header.
|
||||
2. _p_'s Tendermint calls `RequestPrepareProposal` with the newly generated block.
|
||||
The call is synchronous: Tendermint's execution will block until the Application returns from the call.
|
||||
3. The Application checks the block (header, transactions, commit info, evidences). Besides,
|
||||
3. The Application checks the block (hashes, transactions, commit info, misbehavior). Besides,
|
||||
* in same-block execution mode, the Application can (and should) provide `ResponsePrepareProposal.app_hash`,
|
||||
`ResponsePrepareProposal.validator_updates`, or
|
||||
`ResponsePrepareProposal.consensus_param_updates`.
|
||||
@@ -398,11 +399,14 @@ Note that, if _p_ has a non-`nil` _validValue_, Tendermint will use it as propos
|
||||
|
||||
| Name | Type | Description | Field Number |
|
||||
|----------------------|---------------------------------------------|----------------------------------------------------------------------------------------------------------------|--------------|
|
||||
| hash | bytes | The block header's hash of the proposed block. Present for convenience (can be derived from the block header). | 1 |
|
||||
| header | [Header](../core/data_structures.md#header) | The proposed block's header. | 2 |
|
||||
| txs | repeated bytes | List of transactions that have been picked as part of the proposed block. | 3 |
|
||||
| proposed_last_commit | [CommitInfo](#commitinfo) | Info about the last commit, obtained from the information in the proposed block. | 4 |
|
||||
| byzantine_validators | repeated [Evidence](#evidence) | List of evidence of validators that acted maliciously. | 5 |
|
||||
| txs | repeated bytes | List of transactions that have been picked as part of the proposed block. | 1 |
|
||||
| proposed_last_commit | [CommitInfo](#commitinfo) | Info about the last commit, obtained from the information in the proposed block. | 2 |
|
||||
| byzantine_validators | repeated [Misbehavior](#misbehavior) | List of information about validators that acted incorrectly. | 3 |
|
||||
| hash | bytes | The block header's hash of the proposed block. | 4 |
|
||||
| height | int64 | The height of the proposed block. | 5 |
|
||||
| time | [google.protobuf.Timestamp](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Timestamp) | Timestamp included in the proposed block. | 6 |
|
||||
| next_validators_hash | bytes | Merkle root of the next validator set. | 7 |
|
||||
| proposer_address | bytes | [Address](../core/data_structures.md#address) of the validator that created the proposal. | 8 |
|
||||
|
||||
* **Response**:
|
||||
|
||||
@@ -415,20 +419,11 @@ Note that, if _p_ has a non-`nil` _validValue_, Tendermint will use it as propos
|
||||
| consensus_param_updates | [ConsensusParams](#consensusparams) | Changes to consensus-critical gas, size, and other parameters. | 5 |
|
||||
|
||||
* **Usage**:
|
||||
* Contains a full proposed block.
|
||||
* The parameters and types of `RequestProcessProposal` are the same as `RequestPrepareProposal`
|
||||
and `RequestFinalizeBlock`.
|
||||
* Contains fields from the proposed block.
|
||||
* The Application may fully execute the block as though it was handling `RequestFinalizeBlock`.
|
||||
However, any resulting state changes must be kept as _candidate state_,
|
||||
and the Application should be ready to backtrack/discard it in case the decided block is different.
|
||||
* The header exactly matches the Tendermint header of the proposed block.
|
||||
* In next-block execution mode, the header hashes _AppHash_, _LastResultHash_, _ValidatorHash_,
|
||||
and _ConsensusHash_ refer to the **last committed block** (data was provided by the last call to
|
||||
`ResponseFinalizeBlock`).
|
||||
* In same-block execution mode, the header hashes _AppHash_, _LastResultHash_, _ValidatorHash_,
|
||||
and _ConsensusHash_ refer to the **same** block being passed in the `Request*` call to this
|
||||
method (data was provided by the call to `ResponsePrepareProposal` at the current height that
|
||||
resulted in the block being passed in the `Request*` call to this method)
|
||||
* The height and timestamp values match the values from the header of the proposed block.
|
||||
* If `ResponseProcessProposal.status` is `REJECT`, Tendermint assumes the proposal received
|
||||
is not valid.
|
||||
* In same-block execution mode, the Application is required to fully execute the block and provide values
|
||||
@@ -573,17 +568,20 @@ from this condition, but not sure), and _p_ receives a Precommit message for rou
|
||||
|
||||
| Name | Type | Description | Field Number |
|
||||
|----------------------|---------------------------------------------|------------------------------------------------------------------------------------------|--------------|
|
||||
| hash | bytes | The block header's hash. Present for convenience (can be derived from the block header). | 1 |
|
||||
| header | [Header](../core/data_structures.md#header) | The block header. | 2 |
|
||||
| txs | repeated bytes | List of transactions committed as part of the block. | 3 |
|
||||
| decided_last_commit | [CommitInfo](#commitinfo) | Info about the last commit, obtained from the block that was just decided. | 4 |
|
||||
| byzantine_validators | repeated [Evidence](#evidence) | List of evidence of validators that acted maliciously. | 5 |
|
||||
| txs | repeated bytes | List of transactions committed as part of the block. | 1 |
|
||||
| decided_last_commit | [CommitInfo](#commitinfo) | Info about the last commit, obtained from the block that was just decided. | 2 |
|
||||
| byzantine_validators | repeated [Misbehavior](#misbehavior) | List of information about validators that acted incorrectly. | 3 |
|
||||
| hash | bytes | The block header's hash. Present for convenience (can be derived from the block header). | 4 |
|
||||
| height | int64 | The height of the finalized block. | 5 |
|
||||
| time | [google.protobuf.Timestamp](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Timestamp) | Timestamp included in the finalized block. | 6 |
|
||||
| next_validators_hash | bytes | Merkle root of the next validator set. | 7 |
|
||||
| proposer_address | bytes | [Address](../core/data_structures.md#address) of the validator that created the proposal.| 8 |
|
||||
|
||||
* **Response**:
|
||||
|
||||
| Name | Type | Description | Field Number |
|
||||
|-------------------------|-------------------------------------------------------------|----------------------------------------------------------------------------------|--------------|
|
||||
| events | repeated [Event](abci++_basic_concepts_002_draft.md#events) | Type & Key-Value events for indexing | 1 |
|
||||
| events | repeated [Event](abci++_basic_concepts_002_draft.md#events) | Type & Key-Value events for indexing | 1 |
|
||||
| tx_results | repeated [ExecTxResult](#txresult) | List of structures containing the data resulting from executing the transactions | 2 |
|
||||
| validator_updates | repeated [ValidatorUpdate](#validatorupdate) | Changes to validator set (set voting power to 0 to remove). | 3 |
|
||||
| consensus_param_updates | [ConsensusParams](#consensusparams) | Changes to consensus-critical gas, size, and other parameters. | 4 |
|
||||
@@ -591,10 +589,10 @@ from this condition, but not sure), and _p_ receives a Precommit message for rou
|
||||
| retain_height | int64 | Blocks below this height may be removed. Defaults to `0` (retain all). | 6 |
|
||||
|
||||
* **Usage**:
|
||||
* Contains a newly decided block.
|
||||
* Contains the fields of the newly decided block.
|
||||
* This method is equivalent to the call sequence `BeginBlock`, [`DeliverTx`],
|
||||
`EndBlock`, `Commit` in the previous version of ABCI.
|
||||
* The header exactly matches the Tendermint header of the proposed block.
|
||||
* The height and timestamp values match the values from the header of the proposed block.
|
||||
* The Application can use `RequestFinalizeBlock.decided_last_commit` and `RequestFinalizeBlock.byzantine_validators`
|
||||
to determine rewards and punishments for the validators.
|
||||
* The application must execute the transactions in full, in the order they appear in `RequestFinalizeBlock.txs`,
|
||||
@@ -696,23 +694,23 @@ Most of the data structures used in ABCI are shared [common data structures](../
|
||||
* Validator identified by PubKey
|
||||
* Used to tell Tendermint to update the validator set
|
||||
|
||||
### Evidence
|
||||
### Misbehavior
|
||||
|
||||
* **Fields**:
|
||||
|
||||
| Name | Type | Description | Field Number |
|
||||
|--------------------|--------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------|--------------|
|
||||
| type | [EvidenceType](#evidencetype) | Type of the evidence. An enum of possible evidence's. | 1 |
|
||||
| type | [MisbehaviorType](#misbehaviortype) | Type of the misbehavior. An enum of possible misbehaviors. | 1 |
|
||||
| validator | [Validator](#validator) | The offending validator | 2 |
|
||||
| height | int64 | Height when the offense occurred | 3 |
|
||||
| time | [google.protobuf.Timestamp](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Timestamp) | Time of the block that was committed at the height that the offense occurred | 4 |
|
||||
| total_voting_power | int64 | Total voting power of the validator set at height `Height` | 5 |
|
||||
|
||||
#### EvidenceType
|
||||
#### MisbehaviorType
|
||||
|
||||
* **Fields**
|
||||
|
||||
EvidenceType is an enum with the listed fields:
|
||||
MisbehaviorType is an enum with the listed fields:
|
||||
|
||||
| Name | Field Number |
|
||||
|---------------------|--------------|
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Evidence
|
||||
|
||||
Evidence is an important component of Tendermint's security model. Whilst the core
|
||||
consensus protocol provides correctness gaurantees for state machine replication
|
||||
consensus protocol provides correctness guarantees for state machine replication
|
||||
that can tolerate less than 1/3 failures, the evidence system looks to detect and
|
||||
gossip byzantine faults whose combined power is greater than or equal to 1/3. It is worth noting that
|
||||
the evidence system is designed purely to detect possible attacks, gossip them,
|
||||
|
||||
+2
-2
@@ -175,7 +175,7 @@ func (app *Application) FinalizeBlock(req abci.RequestFinalizeBlock) abci.Respon
|
||||
txs[i] = &abci.ExecTxResult{Code: code.CodeTypeOK}
|
||||
}
|
||||
|
||||
valUpdates, err := app.validatorUpdates(uint64(req.Header.Height))
|
||||
valUpdates, err := app.validatorUpdates(uint64(req.Height))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -193,7 +193,7 @@ func (app *Application) FinalizeBlock(req abci.RequestFinalizeBlock) abci.Respon
|
||||
},
|
||||
{
|
||||
Key: "height",
|
||||
Value: strconv.Itoa(int(req.Header.Height)),
|
||||
Value: strconv.Itoa(int(req.Height)),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -2,12 +2,8 @@
|
||||
|
||||
export FUZZ_ROOT="github.com/tendermint/tendermint"
|
||||
|
||||
(cd test/fuzz/p2p/addrbook; go run ./init-corpus/main.go)
|
||||
compile_go_fuzzer "$FUZZ_ROOT"/test/fuzz/p2p/addrbook Fuzz fuzz_p2p_addrbook fuzz
|
||||
(cd test/fuzz/p2p/pex; go run ./init-corpus/main.go)
|
||||
compile_go_fuzzer "$FUZZ_ROOT"/test/fuzz/p2p/pex Fuzz fuzz_p2p_pex fuzz
|
||||
(cd test/fuzz/p2p/secret_connection; go run ./init-corpus/main.go)
|
||||
compile_go_fuzzer "$FUZZ_ROOT"/test/fuzz/p2p/secret_connection Fuzz fuzz_p2p_secret_connection fuzz
|
||||
(cd test/fuzz/p2p/secretconnection; go run ./init-corpus/main.go)
|
||||
compile_go_fuzzer "$FUZZ_ROOT"/test/fuzz/p2p/secretconnection Fuzz fuzz_p2p_secretconnection fuzz
|
||||
|
||||
compile_go_fuzzer "$FUZZ_ROOT"/test/fuzz/mempool Fuzz fuzz_mempool fuzz
|
||||
|
||||
|
||||
+17
-17
@@ -23,13 +23,13 @@ import (
|
||||
// Evidence represents any provable malicious activity by a validator.
|
||||
// Verification logic for each evidence is part of the evidence module.
|
||||
type Evidence interface {
|
||||
ABCI() []abci.Evidence // forms individual evidence to be sent to the application
|
||||
Bytes() []byte // bytes which comprise the evidence
|
||||
Hash() []byte // hash of the evidence
|
||||
Height() int64 // height of the infraction
|
||||
String() string // string format of the evidence
|
||||
Time() time.Time // time of the infraction
|
||||
ValidateBasic() error // basic consistency check
|
||||
ABCI() []abci.Misbehavior // forms individual evidence to be sent to the application
|
||||
Bytes() []byte // bytes which comprise the evidence
|
||||
Hash() []byte // hash of the evidence
|
||||
Height() int64 // height of the infraction
|
||||
String() string // string format of the evidence
|
||||
Time() time.Time // time of the infraction
|
||||
ValidateBasic() error // basic consistency check
|
||||
|
||||
// Implementations must support tagged encoding in JSON.
|
||||
jsontypes.Tagged
|
||||
@@ -87,9 +87,9 @@ func NewDuplicateVoteEvidence(vote1, vote2 *Vote, blockTime time.Time, valSet *V
|
||||
}
|
||||
|
||||
// ABCI returns the application relevant representation of the evidence
|
||||
func (dve *DuplicateVoteEvidence) ABCI() []abci.Evidence {
|
||||
return []abci.Evidence{{
|
||||
Type: abci.EvidenceType_DUPLICATE_VOTE,
|
||||
func (dve *DuplicateVoteEvidence) ABCI() []abci.Misbehavior {
|
||||
return []abci.Misbehavior{{
|
||||
Type: abci.MisbehaviorType_DUPLICATE_VOTE,
|
||||
Validator: abci.Validator{
|
||||
Address: dve.VoteA.ValidatorAddress,
|
||||
Power: dve.ValidatorPower,
|
||||
@@ -257,12 +257,12 @@ func (*LightClientAttackEvidence) TypeTag() string { return "tendermint/LightCli
|
||||
|
||||
var _ Evidence = &LightClientAttackEvidence{}
|
||||
|
||||
// ABCI forms an array of abci evidence for each byzantine validator
|
||||
func (l *LightClientAttackEvidence) ABCI() []abci.Evidence {
|
||||
abciEv := make([]abci.Evidence, len(l.ByzantineValidators))
|
||||
// ABCI forms an array of abci.Misbehavior for each byzantine validator
|
||||
func (l *LightClientAttackEvidence) ABCI() []abci.Misbehavior {
|
||||
abciEv := make([]abci.Misbehavior, len(l.ByzantineValidators))
|
||||
for idx, val := range l.ByzantineValidators {
|
||||
abciEv[idx] = abci.Evidence{
|
||||
Type: abci.EvidenceType_LIGHT_CLIENT_ATTACK,
|
||||
abciEv[idx] = abci.Misbehavior{
|
||||
Type: abci.MisbehaviorType_LIGHT_CLIENT_ATTACK,
|
||||
Validator: TM2PB.Validator(val),
|
||||
Height: l.Height(),
|
||||
Time: l.Timestamp,
|
||||
@@ -683,8 +683,8 @@ func (evl EvidenceList) Has(evidence Evidence) bool {
|
||||
|
||||
// ToABCI converts the evidence list to a slice of the ABCI protobuf messages
|
||||
// for use when communicating the evidence to an application.
|
||||
func (evl EvidenceList) ToABCI() []abci.Evidence {
|
||||
var el []abci.Evidence
|
||||
func (evl EvidenceList) ToABCI() []abci.Misbehavior {
|
||||
var el []abci.Misbehavior
|
||||
for _, e := range evl {
|
||||
el = append(el, e.ABCI()...)
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ type ValidatorSet struct {
|
||||
// MaxVotesCount - commits by a validator set larger than this will fail
|
||||
// validation.
|
||||
func NewValidatorSet(valz []*Validator) *ValidatorSet {
|
||||
vals := &ValidatorSet{}
|
||||
vals := &ValidatorSet{Validators: []*Validator{}}
|
||||
err := vals.updateWithChangeSet(valz, false)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot create validator set: %w", err))
|
||||
@@ -235,9 +235,6 @@ func (vals *ValidatorSet) shiftByAvgProposerPriority() {
|
||||
|
||||
// Makes a copy of the validator list.
|
||||
func validatorListCopy(valsList []*Validator) []*Validator {
|
||||
if valsList == nil {
|
||||
return nil
|
||||
}
|
||||
valsCopy := make([]*Validator, len(valsList))
|
||||
for i, val := range valsList {
|
||||
valsCopy[i] = val.Copy()
|
||||
|
||||
Reference in New Issue
Block a user