diff --git a/.changelog/unreleased/features/3008-mempool-async-update.md b/.changelog/unreleased/features/3008-mempool-async-update.md new file mode 100644 index 00000000000..1667aefb637 --- /dev/null +++ b/.changelog/unreleased/features/3008-mempool-async-update.md @@ -0,0 +1,3 @@ +- `[consensus]` Make mempool updates asynchronous from consensus Commit's, + reducing latency for reaching consensus timeouts. + ([#3008](https://github.com/cometbft/cometbft/pull/3008)) diff --git a/.changelog/unreleased/improvements/4-async-fire-events.md b/.changelog/unreleased/improvements/4-async-fire-events.md new file mode 100644 index 00000000000..dc232ddc387 --- /dev/null +++ b/.changelog/unreleased/improvements/4-async-fire-events.md @@ -0,0 +1,3 @@ +- `[consensus]` run fireEvents in goroutine. + ([#4](https://github.com/crypto-org-chain/cometbft/pull/4)) + diff --git a/.changelog/v0.38.1/improvements/1558-experimental-gossip-limiting.md b/.changelog/v0.38.1/improvements/1558-experimental-gossip-limiting.md index 6931cef8274..58fc6c6f863 100644 --- a/.changelog/v0.38.1/improvements/1558-experimental-gossip-limiting.md +++ b/.changelog/v0.38.1/improvements/1558-experimental-gossip-limiting.md @@ -4,6 +4,6 @@ ([\#1584](https://github.com/cometbft/cometbft/pull/1584)) - `[config]` Add mempool parameters `experimental_max_gossip_connections_to_persistent_peers` and `experimental_max_gossip_connections_to_non_persistent_peers` for limiting the number of peers to - which the node gossip transactions. + which the node gossip transactions. ([\#1558](https://github.com/cometbft/cometbft/pull/1558)) ([\#1584](https://github.com/cometbft/cometbft/pull/1584)) diff --git a/.changelog/v0.38.3/bug-fixes/4019-mempool-metric-rejected-txs.md b/.changelog/v0.38.13/bug-fixes/4019-mempool-metric-rejected-txs.md similarity index 100% rename from .changelog/v0.38.3/bug-fixes/4019-mempool-metric-rejected-txs.md rename to .changelog/v0.38.13/bug-fixes/4019-mempool-metric-rejected-txs.md diff --git a/.changelog/v0.38.13/bug-fixes/4295-copy-value-state-indexer.md b/.changelog/v0.38.13/bug-fixes/4295-copy-value-state-indexer.md new file mode 100644 index 00000000000..2ffeb7a04c9 --- /dev/null +++ b/.changelog/v0.38.13/bug-fixes/4295-copy-value-state-indexer.md @@ -0,0 +1,3 @@ +- `[state/indexer]` Fix the tx_search results not returning all results by changing the logic in the indexer to copy the key and values instead of reusing an iterator. This issue only arises when upgrading to cometbft-db v0.13 or later. + ([\#4295](https://github.com/cometbft/cometbft/issues/4295)). Special thanks to @faddat for reporting the issue. + diff --git a/.changelog/unreleased/dependencies/4059-update-cometbft-db.md b/.changelog/v0.38.13/dependencies/4059-update-cometbft-db.md similarity index 50% rename from .changelog/unreleased/dependencies/4059-update-cometbft-db.md rename to .changelog/v0.38.13/dependencies/4059-update-cometbft-db.md index 22900e5e765..8c957a22a38 100644 --- a/.changelog/unreleased/dependencies/4059-update-cometbft-db.md +++ b/.changelog/v0.38.13/dependencies/4059-update-cometbft-db.md @@ -1,4 +1,2 @@ - `[go/runtime]` Bump Go version to 1.22 ([\#4073](https://github.com/cometbft/cometbft/pull/4073)) -- Bump cometbft-db version to v0.12.0 - ([\#4073](https://github.com/cometbft/cometbft/pull/4073)) diff --git a/.changelog/v0.38.13/dependencies/4321-update-cometbft-db.md b/.changelog/v0.38.13/dependencies/4321-update-cometbft-db.md new file mode 100644 index 00000000000..7fdd007fb58 --- /dev/null +++ b/.changelog/v0.38.13/dependencies/4321-update-cometbft-db.md @@ -0,0 +1,2 @@ +- Bump cometbft-db version to v0.14.1 + ([\#4321](https://github.com/cometbft/cometbft/pull/4321)) diff --git a/.changelog/v0.38.13/features/4294-remove-secp256k1-wrapper.md b/.changelog/v0.38.13/features/4294-remove-secp256k1-wrapper.md new file mode 100644 index 00000000000..ca1333d6f8b --- /dev/null +++ b/.changelog/v0.38.13/features/4294-remove-secp256k1-wrapper.md @@ -0,0 +1 @@ +- `[crypto]` use decred secp256k1 directly ([#4294](https://github.com/cometbft/cometbft/pull/4294)) \ No newline at end of file diff --git a/.changelog/v0.38.8/improvements/4019-mempool-metric-evicted-txs.md b/.changelog/v0.38.13/improvements/4019-mempool-metric-evicted-txs.md similarity index 100% rename from .changelog/v0.38.8/improvements/4019-mempool-metric-evicted-txs.md rename to .changelog/v0.38.13/improvements/4019-mempool-metric-evicted-txs.md diff --git a/.changelog/v0.38.13/improvements/4123-mempool-is-full-log.md b/.changelog/v0.38.13/improvements/4123-mempool-is-full-log.md new file mode 100644 index 00000000000..a68573d0c14 --- /dev/null +++ b/.changelog/v0.38.13/improvements/4123-mempool-is-full-log.md @@ -0,0 +1,2 @@ +- `[log]` Change "mempool is full" log to debug level + ([\#4123](https://github.com/cometbft/cometbft/pull/4123)) Special thanks to @yihuang. diff --git a/.changelog/v0.38.13/summary.md b/.changelog/v0.38.13/summary.md new file mode 100644 index 00000000000..8b45341039a --- /dev/null +++ b/.changelog/v0.38.13/summary.md @@ -0,0 +1,7 @@ +*October 24, 2024* + +This patch release addresses the issue where tx_search was not returning all results, which only arises when upgrading +to CometBFT-DB version 0.13 or later. It includes a fix in the state indexer to resolve this problem. We recommend +upgrading to this patch release if you are affected by this issue. + + diff --git a/.changelog/v0.38.8/improvements/4123-mempool-is-full-log.md b/.changelog/v0.38.8/improvements/4123-mempool-is-full-log.md deleted file mode 100644 index 68f187e658d..00000000000 --- a/.changelog/v0.38.8/improvements/4123-mempool-is-full-log.md +++ /dev/null @@ -1,2 +0,0 @@ -- `[log]` Change "mempool is full" log to debug level - ([\#4123](https://github.com/cometbft/cometbft/pull/4123)) diff --git a/.golangci.yml b/.golangci.yml index 24116994dae..7585abcf7b2 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -76,6 +76,7 @@ linters-settings: - github.com/spf13 - github.com/stretchr/testify/require - github.com/syndtr/goleveldb + - github.com/decred/dcrd/dcrec/secp256k1/v4 test: files: - "$test" @@ -96,3 +97,53 @@ linters-settings: - github.com/prometheus/client_golang/prometheus/promhttp - github.com/spf13 - github.com/stretchr/testify + - github.com/decred/dcrd/dcrec/secp256k1/v4 + + revive: + enable-all-rules: true + rules: + - name: comment-spacings # temporarily disabled + disabled: true + - name: max-public-structs + disabled: true + - name: cognitive-complexity + disabled: true + - name: argument-limit + disabled: true + - name: cyclomatic + disabled: true + - name: deep-exit + disabled: true + - name: file-header + disabled: true + - name: function-length + disabled: true + - name: function-result-limit + disabled: true + - name: line-length-limit + disabled: true + - name: flag-parameter + disabled: true + - name: add-constant + disabled: true + - name: empty-lines + disabled: true + - name: import-shadowing + disabled: true + - name: modifies-value-receiver + disabled: true + - name: confusing-naming + disabled: true + - name: defer + disabled: true + - name: unchecked-type-assertion + disabled: true + - name: unhandled-error + disabled: true + arguments: + - "fmt.Printf" + - "fmt.Print" + - "fmt.Println" + gosec: + excludes: + - G115 diff --git a/CHANGELOG.md b/CHANGELOG.md index e620b6586ef..40196034c61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,38 @@ # CHANGELOG +## v0.38.13 + +*October 24, 2024* + +This patch release addresses the issue where tx_search was not returning all results, which only arises when upgrading +to CometBFT-DB version 0.13 or later. It includes a fix in the state indexer to resolve this problem. We recommend +upgrading to this patch release if you are affected by this issue. + +### BUG FIXES + +- `[metrics]` Call unused `rejected_txs` metric in mempool + ([\#4019](https://github.com/cometbft/cometbft/pull/4019)) +- `[state/indexer]` Fix the tx_search results not returning all results by changing the logic in the indexer to copy the key and values instead of reusing an iterator. This issue only arises when upgrading to cometbft-db v0.13 or later. + ([\#4295](https://github.com/cometbft/cometbft/issues/4295)). Special thanks to @faddat for reporting the issue. + +### DEPENDENCIES + +- `[go/runtime]` Bump Go version to 1.22 + ([\#4073](https://github.com/cometbft/cometbft/pull/4073)) +- Bump cometbft-db version to v0.14.1 + ([\#4321](https://github.com/cometbft/cometbft/pull/4321)) + +### FEATURES + +- `[crypto]` use decred secp256k1 directly ([#4294](https://github.com/cometbft/cometbft/pull/4294)) + +### IMPROVEMENTS + +- `[metrics]` Add `evicted_txs` metric to mempool + ([\#4019](https://github.com/cometbft/cometbft/pull/4019)) +- `[log]` Change "mempool is full" log to debug level + ([\#4123](https://github.com/cometbft/cometbft/pull/4123)) Special thanks to @yihuang. + ## v0.38.12 *September 3, 2024* diff --git a/consensus/state.go b/consensus/state.go index d47b43f2413..28372479ae6 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -42,7 +42,10 @@ var ( errPubKeyIsNotSet = errors.New("pubkey is not set. Look for \"Can't get private validator pubkey\" errors") ) -var msgQueueSize = 1000 +var ( + msgQueueSize = 1000 + taskQueueSize = 128 +) // msgs from the reactor which may update the state type msgInfo struct { @@ -160,6 +163,7 @@ func NewState( evpool evidencePool, options ...StateOption, ) *State { + blockExec.SetTaskRunner(spawnTaskRunner(taskQueueSize)) cs := &State{ config: config, blockExec: blockExec, @@ -2585,3 +2589,16 @@ func repairWalFile(src, dst string) error { return nil } + +// spawnTaskRunner spawn a single goroutine to run tasks in FIFO order. +func spawnTaskRunner(buf int) func(func()) { + taskCh := make(chan func(), buf) + go func() { + for f := range taskCh { + f() + } + }() + return func(f func()) { + taskCh <- f + } +} diff --git a/crypto/secp256k1/secp256k1.go b/crypto/secp256k1/secp256k1.go index 51d462c0bed..fdf5727c722 100644 --- a/crypto/secp256k1/secp256k1.go +++ b/crypto/secp256k1/secp256k1.go @@ -8,9 +8,9 @@ import ( "io" "math/big" - secp256k1 "github.com/btcsuite/btcd/btcec/v2" - "github.com/btcsuite/btcd/btcec/v2/ecdsa" - "golang.org/x/crypto/ripemd160" //nolint: staticcheck // necessary for Bitcoin address format + "github.com/decred/dcrd/dcrec/secp256k1/v4" + "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" + "golang.org/x/crypto/ripemd160" //nolint: gosec,staticcheck // necessary for Bitcoin address format "github.com/cometbft/cometbft/crypto" cmtjson "github.com/cometbft/cometbft/libs/json" @@ -43,9 +43,9 @@ func (privKey PrivKey) Bytes() []byte { // PubKey performs the point-scalar multiplication from the privKey on the // generator point to get the pubkey. func (privKey PrivKey) PubKey() crypto.PubKey { - _, pubkeyObject := secp256k1.PrivKeyFromBytes(privKey) + secpPrivKey := secp256k1.PrivKeyFromBytes(privKey) - pk := pubkeyObject.SerializeCompressed() + pk := secpPrivKey.PubKey().SerializeCompressed() return PubKey(pk) } @@ -126,7 +126,7 @@ func GenPrivKeySecp256k1(secret []byte) PrivKey { // Sign creates an ECDSA signature on curve Secp256k1, using SHA256 on the msg. // The returned signature will be of the form R || S (in lower-S form). func (privKey PrivKey) Sign(msg []byte) ([]byte, error) { - priv, _ := secp256k1.PrivKeyFromBytes(privKey) + priv := secp256k1.PrivKeyFromBytes(privKey) sum := sha256.Sum256(msg) sig := ecdsa.SignCompact(priv, sum[:], false) @@ -199,7 +199,7 @@ func (pubKey PubKey) VerifySignature(msg []byte, sigStr []byte) bool { // parse the signature: signature := signatureFromBytes(sigStr) - // Reject malleable signatures. libsecp256k1 does this check but btcec doesn't. + // Reject malleable signatures. libsecp256k1 does this check but decred doesn't. // see: https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/signature_nocgo.go#L90-L93 // Serialize() would negate S value if it is over half order. // Hence, if the signature is different after Serialize() if should be rejected. diff --git a/crypto/secp256k1/secp256k1_internal_test.go b/crypto/secp256k1/secp256k1_internal_test.go index ae1f55e4926..c2f77412d6b 100644 --- a/crypto/secp256k1/secp256k1_internal_test.go +++ b/crypto/secp256k1/secp256k1_internal_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/require" - secp256k1 "github.com/btcsuite/btcd/btcec/v2" + "github.com/decred/dcrd/dcrec/secp256k1/v4" ) func Test_genPrivKey(t *testing.T) { diff --git a/crypto/secp256k1/secp256k1_test.go b/crypto/secp256k1/secp256k1_test.go index 195d9dde709..18de0d29682 100644 --- a/crypto/secp256k1/secp256k1_test.go +++ b/crypto/secp256k1/secp256k1_test.go @@ -6,13 +6,12 @@ import ( "testing" "github.com/btcsuite/btcd/btcutil/base58" + underlyingsecp256k1 "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/secp256k1" - - underlyingSecp256k1 "github.com/btcsuite/btcd/btcec/v2" ) type keyData struct { @@ -75,7 +74,7 @@ func TestSecp256k1LoadPrivkeyAndSerializeIsIdentity(t *testing.T) { // This function creates a private and public key in the underlying libraries format. // The private key is basically calling new(big.Int).SetBytes(pk), which removes leading zero bytes - priv, _ := underlyingSecp256k1.PrivKeyFromBytes(privKeyBytes[:]) + priv := underlyingsecp256k1.PrivKeyFromBytes(privKeyBytes[:]) // this takes the bytes returned by `(big int).Bytes()`, and if the length is less than 32 bytes, // pads the bytes from the left with zero bytes. Therefore these two functions composed // result in the identity function on privKeyBytes, hence the following equality check @@ -87,7 +86,7 @@ func TestSecp256k1LoadPrivkeyAndSerializeIsIdentity(t *testing.T) { func TestGenPrivKeySecp256k1(t *testing.T) { // curve oder N - N := underlyingSecp256k1.S256().N + N := underlyingsecp256k1.S256().N tests := []struct { name string secret []byte diff --git a/go.mod b/go.mod index 2d7710205e6..282e6b6c59f 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,13 @@ module github.com/cometbft/cometbft -go 1.22.2 - -toolchain go1.22.7 +go 1.22.7 require ( github.com/BurntSushi/toml v1.4.0 github.com/adlio/schema v1.3.6 + github.com/btcsuite/btcd/btcutil v1.1.6 github.com/cenkalti/backoff v2.2.1+incompatible // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 github.com/fortytw2/leaktest v1.3.0 github.com/go-kit/kit v0.13.0 github.com/go-kit/log v0.2.1 @@ -20,7 +20,7 @@ require ( github.com/minio/highwayhash v1.0.3 github.com/ory/dockertest v3.3.5+incompatible github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.20.4 + github.com/prometheus/client_golang v1.20.5 github.com/prometheus/client_model v0.6.1 github.com/prometheus/common v0.59.1 github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 @@ -30,18 +30,16 @@ require ( github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.9.0 - golang.org/x/crypto v0.27.0 + golang.org/x/crypto v0.28.0 golang.org/x/net v0.29.0 - google.golang.org/grpc v1.67.0 + google.golang.org/grpc v1.67.1 ) require github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 require ( github.com/Masterminds/semver/v3 v3.3.0 - github.com/btcsuite/btcd/btcec/v2 v2.3.4 - github.com/btcsuite/btcd/btcutil v1.1.6 - github.com/cometbft/cometbft-db v0.12.0 + github.com/cometbft/cometbft-db v0.14.1 github.com/cosmos/gogoproto v1.7.0 github.com/go-git/go-git/v5 v5.12.0 github.com/gofrs/uuid v4.4.0+incompatible @@ -72,11 +70,9 @@ require ( github.com/containerd/continuity v0.3.0 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/dgraph-io/badger/v4 v4.2.0 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect - github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect - github.com/docker/cli v23.0.1+incompatible // indirect + github.com/docker/cli v24.0.7+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect @@ -133,8 +129,8 @@ require ( go.uber.org/multierr v1.10.0 // indirect golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect golang.org/x/mod v0.17.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/text v0.18.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index e3b6a05b273..96b25a7fdf8 100644 --- a/go.sum +++ b/go.sum @@ -33,12 +33,9 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= -github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= -github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= -github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= @@ -46,7 +43,6 @@ github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/ github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= @@ -85,8 +81,8 @@ github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwP github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= -github.com/cometbft/cometbft-db v0.12.0 h1:v77/z0VyfSU7k682IzZeZPFZrQAKiQwkqGN0QzAjMi0= -github.com/cometbft/cometbft-db v0.12.0/go.mod h1:aX2NbCrjNVd2ZajYxt1BsiFf/Z+TQ2MN0VxdicheYuw= +github.com/cometbft/cometbft-db v0.14.1 h1:SxoamPghqICBAIcGpleHbmoPqy+crij/++eZz3DlerQ= +github.com/cometbft/cometbft-db v0.14.1/go.mod h1:KHP1YghilyGV/xjD5DP3+2hyigWx0WTp9X+0Gnx0RxQ= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro= @@ -111,11 +107,10 @@ github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8Bzu github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= -github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/docker/cli v23.0.1+incompatible h1:LRyWITpGzl2C9e9uGxzisptnxAn1zfZKXy13Ul2Q5oM= -github.com/docker/cli v23.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1xfI36MSkFg= +github.com/docker/cli v24.0.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0= github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= @@ -305,8 +300,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= -github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= @@ -394,8 +389,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= @@ -465,15 +460,15 @@ golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -482,8 +477,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -514,8 +509,8 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw= -google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/spec/abci/abci++_app_requirements.md b/spec/abci/abci++_app_requirements.md index 3c5c5e1c775..6d016dc6777 100644 --- a/spec/abci/abci++_app_requirements.md +++ b/spec/abci/abci++_app_requirements.md @@ -297,7 +297,9 @@ will be received on the mempool connection during this processing step, providin update all four connection states to the latest committed state at the same time. -When `Commit` returns, CometBFT unlocks the mempool. +CometBFT unlocks the mempool after it has finished updating for the new block, +which occurs asynchronously from `Commit`. +See [Mempool Update](../mempool/mempool.md) for more information on what the `update` task does. WARNING: if the ABCI app logic processing the `Commit` message sends a `/broadcast_tx_sync` or `/broadcast_tx` and waits for the response diff --git a/state/execution.go b/state/execution.go index 4accf1639d6..5a953eb0101 100644 --- a/state/execution.go +++ b/state/execution.go @@ -43,6 +43,8 @@ type BlockExecutor struct { logger log.Logger metrics *Metrics + + asyncRunner func(func()) } type BlockExecutorOption func(executor *BlockExecutor) @@ -53,6 +55,12 @@ func BlockExecutorWithMetrics(metrics *Metrics) BlockExecutorOption { } } +func BlockExecutorWithAsyncRunner(runner func(func())) BlockExecutorOption { + return func(blockExec *BlockExecutor) { + blockExec.asyncRunner = runner + } +} + // NewBlockExecutor returns a new BlockExecutor with a NopEventBus. // Call SetEventBus to provide one. func NewBlockExecutor( @@ -92,6 +100,10 @@ func (blockExec *BlockExecutor) SetEventBus(eventBus types.BlockEventPublisher) blockExec.eventBus = eventBus } +func (blockExec *BlockExecutor) SetTaskRunner(runner func(func())) { + blockExec.asyncRunner = runner +} + // CreateProposalBlock calls state.MakeBlock with evidence from the evpool // and txs from the mempool. The max bytes must be big enough to fit the commit. // The block space is first allocated to outstanding evidence. @@ -315,9 +327,19 @@ func (blockExec *BlockExecutor) applyBlock(state State, blockID types.BlockID, b } } - // Events are fired after everything else. - // NOTE: if we crash between Commit and Save, events wont be fired during replay - fireEvents(blockExec.logger, blockExec.eventBus, block, blockID, abciResponse, validatorUpdates) + if _, ok := blockExec.eventBus.(types.NopEventBus); !ok { + // Events are fired after everything else. + // NOTE: if we crash between Commit and Save, events wont be fired during replay + task := func() { + fireEvents(blockExec.logger, blockExec.eventBus, block, blockID, abciResponse, validatorUpdates) + } + + if blockExec.asyncRunner != nil { + blockExec.asyncRunner(task) + } else { + task() + } + } return state, nil } @@ -375,34 +397,38 @@ func (blockExec *BlockExecutor) VerifyVoteExtension(ctx context.Context, vote *t return nil } -// Commit locks the mempool, runs the ABCI Commit message, and updates the +// Commit locks the mempool, runs the ABCI Commit message, and asynchronously starts updating the // mempool. -// It returns the result of calling abci.Commit which is the height to retain (if any)). +// Commit returns the result of calling abci.Commit which is the height to retain (if any)). // The application is expected to have persisted its state (if any) before returning // from the ABCI Commit call. This is the only place where the application should // persist its state. // The Mempool must be locked during commit and update because state is // typically reset on Commit and old txs must be replayed against committed // state before new txs are run in the mempool, lest they be invalid. +// The mempool is unlocked when the Update routine completes, which is +// asynchronous from Commit. func (blockExec *BlockExecutor) Commit( state State, block *types.Block, abciResponse *abci.ResponseFinalizeBlock, ) (int64, error) { blockExec.mempool.Lock() - defer blockExec.mempool.Unlock() + unlockMempool := func() { blockExec.mempool.Unlock() } // while mempool is Locked, flush to ensure all async requests have completed // in the ABCI app before Commit. err := blockExec.mempool.FlushAppConn() if err != nil { - blockExec.logger.Error("client error during mempool.FlushAppConn", "err", err) + unlockMempool() + blockExec.logger.Error("client error during mempool.FlushAppConn, flushing mempool", "err", err) return 0, err } // Commit block, get hash back res, err := blockExec.proxyApp.Commit(context.TODO()) if err != nil { + unlockMempool() blockExec.logger.Error("client error during proxyAppConn.CommitSync", "err", err) return 0, err } @@ -415,15 +441,36 @@ func (blockExec *BlockExecutor) Commit( ) // Update mempool. - err = blockExec.mempool.Update( + go blockExec.asyncUpdateMempool(unlockMempool, block, state.Copy(), abciResponse) + + return res.RetainHeight, nil +} + +// updates the mempool with the latest state asynchronously. +func (blockExec *BlockExecutor) asyncUpdateMempool( + unlockMempool func(), + block *types.Block, + state State, + abciResponse *abci.ResponseFinalizeBlock, +) { + defer unlockMempool() + + err := blockExec.mempool.Update( block.Height, block.Txs, abciResponse.TxResults, TxPreCheck(state), TxPostCheck(state), ) - - return res.RetainHeight, err + if err != nil { + // We panic in this case, out of legacy behavior. Before we made the mempool + // update complete asynchronously from Commit, we would panic if the mempool + // update failed. This is because we panic on any error within commit. + // We should consider changing this behavior in the future, as there is no + // need to panic if the mempool update failed. The most severe thing we + // would need to do is dump the mempool and restart it. + panic(fmt.Sprintf("client error during mempool.Update; error %v", err)) + } } //--------------------------------------------------------- diff --git a/state/indexer/block/kv/kv.go b/state/indexer/block/kv/kv.go index 3840e053a33..0533c4b61fe 100644 --- a/state/indexer/block/kv/kv.go +++ b/state/indexer/block/kv/kv.go @@ -385,11 +385,15 @@ FOR_LOOP: } func (idx *BlockerIndexer) setTmpHeights(tmpHeights map[string][]byte, it dbm.Iterator) { - // If we return attributes that occur within the same events, then store the event sequence in the - // result map as well + // If we return attributes that occur within the same events, then store the + // event sequence in the result map as well. eventSeq, _ := parseEventSeqFromEventKey(it.Key()) - retVal := it.Value() - tmpHeights[string(retVal)+strconv.FormatInt(eventSeq, 10)] = it.Value() + + // Copy the value because the iterator will be reused. + value := make([]byte, len(it.Value())) + copy(value, it.Value()) + + tmpHeights[string(value)+strconv.FormatInt(eventSeq, 10)] = value } diff --git a/state/txindex/kv/kv.go b/state/txindex/kv/kv.go index 0e1b25a89d6..f807735feff 100644 --- a/state/txindex/kv/kv.go +++ b/state/txindex/kv/kv.go @@ -342,7 +342,12 @@ func lookForHash(conditions []syntax.Condition) (hash []byte, ok bool, err error func (*TxIndex) setTmpHashes(tmpHeights map[string][]byte, key, value []byte) { eventSeq := extractEventSeqFromKey(key) - tmpHeights[string(value)+eventSeq] = value + + // Copy the value because the iterator will be reused. + valueCopy := make([]byte, len(value)) + copy(valueCopy, value) + + tmpHeights[string(valueCopy)+eventSeq] = valueCopy } // match returns all matching txs by hash that meet a given condition and start diff --git a/test/e2e/docker/Dockerfile b/test/e2e/docker/Dockerfile index 81794cae2c1..9768528c8b7 100644 --- a/test/e2e/docker/Dockerfile +++ b/test/e2e/docker/Dockerfile @@ -1,7 +1,7 @@ # We need to build in a Linux environment to support C libraries, e.g. RocksDB. # We use Debian instead of Alpine, so that we can use binary database packages # instead of spending time compiling them. -FROM cometbft/cometbft-db-testing:v0.12.0 +FROM cometbft/cometbft-db-testing:v0.14.1 RUN apt-get -qq update -y && apt-get -qq upgrade -y >/dev/null diff --git a/version/version.go b/version/version.go index c00b4f8ffe2..458932794f3 100644 --- a/version/version.go +++ b/version/version.go @@ -3,7 +3,7 @@ package version const ( // TMVersionDefault is the used as the fallback version of CometBFT // when not using git describe. It is formatted with semantic versioning. - TMCoreSemVer = "0.38.12" + TMCoreSemVer = "0.38.13" // ABCISemVer is the semantic version of the ABCI protocol ABCISemVer = "2.0.0" ABCIVersion = ABCISemVer