diff --git a/accounts/abi/bind/bind_test.go b/accounts/abi/bind/bind_test.go index 6e66df8c8b..29ac69ec3f 100644 --- a/accounts/abi/bind/bind_test.go +++ b/accounts/abi/bind/bind_test.go @@ -557,7 +557,7 @@ var bindTests = []struct { bool[] memory d; return (a, c, d); } - + function G() public view returns (A[] memory a) { A[] memory a = new A[](2); a[0].B = bytes32(uint256(1234) << 96); @@ -579,10 +579,10 @@ var bindTests = []struct { // Generate a new random account and a funded simulator key, _ := crypto.GenerateKey() auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - + sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(1000000000000000000)}}, 10000000) defer sim.Close() - + // Deploy a structs method invoker contract and execute its default method _, _, structs, err := DeployStructs(auth, sim) if err != nil { @@ -1730,13 +1730,13 @@ var bindTests = []struct { `NewFallbacks`, ` pragma solidity >=0.6.0 <0.7.0; - + contract NewFallbacks { event Fallback(bytes data); fallback() external { emit Fallback(msg.data); } - + event Received(address addr, uint value); receive() external payable { emit Received(msg.sender, msg.value); @@ -1748,7 +1748,7 @@ var bindTests = []struct { ` "bytes" "math/big" - + "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" "github.com/ava-labs/subnet-evm/core" @@ -1757,23 +1757,23 @@ var bindTests = []struct { ` key, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(key.PublicKey) - - + + sim := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000000000000)}}, 1000000) defer sim.Close() - + opts, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) _, _, c, err := DeployNewFallbacks(opts, sim) if err != nil { t.Fatalf("Failed to deploy contract: %v", err) } sim.Commit(false) - + // Test receive function opts.Value = big.NewInt(100) c.Receive(opts) sim.Commit(false) - + var gotEvent bool iter, _ := c.FilterReceived(nil) defer iter.Close() @@ -1797,7 +1797,7 @@ var bindTests = []struct { calldata := []byte{0x01, 0x02, 0x03} c.Fallback(opts, calldata) sim.Commit(false) - + iter2, _ := c.FilterFallback(nil) defer iter2.Close() for iter2.Next() { @@ -1891,7 +1891,7 @@ var bindTests = []struct { `NewErrors`, ` pragma solidity >0.8.4; - + contract NewErrors { error MyError(uint256); error MyError1(uint256); @@ -1906,7 +1906,7 @@ var bindTests = []struct { []string{`[{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"MyError","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"MyError1","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"MyError2","type":"error"},{"inputs":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"b","type":"uint256"},{"internalType":"uint256","name":"c","type":"uint256"}],"name":"MyError3","type":"error"},{"inputs":[],"name":"Error","outputs":[],"stateMutability":"pure","type":"function"}]`}, ` "math/big" - + "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" "github.com/ava-labs/subnet-evm/core" @@ -1919,7 +1919,7 @@ var bindTests = []struct { sim = backends.NewSimulatedBackend(core.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, 10000000) ) defer sim.Close() - + _, tx, contract, err := DeployNewErrors(user, sim) if err != nil { t.Fatal(err) @@ -1944,12 +1944,12 @@ var bindTests = []struct { name: `ConstructorWithStructParam`, contract: ` pragma solidity >=0.8.0 <0.9.0; - + contract ConstructorWithStructParam { struct StructType { uint256 field; } - + constructor(StructType memory st) {} } `, @@ -1976,7 +1976,7 @@ var bindTests = []struct { t.Fatalf("DeployConstructorWithStructParam() got err %v; want nil err", err) } sim.Commit(true) - + if _, err = bind.WaitDeployed(nil, sim, tx); err != nil { t.Logf("Deployment tx: %+v", tx) t.Errorf("bind.WaitDeployed(nil, %T, ) got err %v; want nil err", sim, err) @@ -2024,7 +2024,7 @@ var bindTests = []struct { t.Fatalf("DeployNameConflict() got err %v; want nil err", err) } sim.Commit(true) - + if _, err = bind.WaitDeployed(nil, sim, tx); err != nil { t.Logf("Deployment tx: %+v", tx) t.Errorf("bind.WaitDeployed(nil, %T, ) got err %v; want nil err", sim, err) diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go index 815e624196..20f11ddc39 100644 --- a/core/txpool/txpool.go +++ b/core/txpool/txpool.go @@ -201,7 +201,9 @@ type Config struct { // DefaultConfig contains the default configurations for the transaction // pool. var DefaultConfig = Config{ - Journal: "transactions.rlp", + // If we re-enable txpool journaling, we should also add the saved local + // transactions to the p2p gossip on startup. + Journal: "", Rejournal: time.Hour, PriceLimit: 1, @@ -212,7 +214,7 @@ var DefaultConfig = Config{ AccountQueue: 64, GlobalQueue: 1024, - Lifetime: 3 * time.Hour, + Lifetime: 10 * time.Minute, } // sanitize checks the provided user configurations and changes anything that's diff --git a/core/txpool/txpool_test.go b/core/txpool/txpool_test.go index 7c586aecea..0e4d438f35 100644 --- a/core/txpool/txpool_test.go +++ b/core/txpool/txpool_test.go @@ -56,7 +56,7 @@ import ( var ( // testTxPoolConfig is a transaction pool configuration without stateful disk // sideeffects used during testing. - testTxPoolConfig Config + testTxPoolConfig = DefaultConfig // eip1559Config is a chain config with EIP-1559 enabled at block 0. eip1559Config *params.ChainConfig @@ -76,9 +76,6 @@ var ( ) func init() { - testTxPoolConfig = DefaultConfig - testTxPoolConfig.Journal = "" - cpy := *params.TestChainConfig eip1559Config = &cpy eip1559Config.SubnetEVMTimestamp = utils.NewUint64(0) diff --git a/eth/api_backend.go b/eth/api_backend.go index 44bc67800c..5e660bebad 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -336,7 +336,14 @@ func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction) if err := ctx.Err(); err != nil { return err } - return b.eth.txPool.AddLocal(signedTx) + if err := b.eth.txPool.AddLocal(signedTx); err != nil { + return err + } + + // We only enqueue transactions for push gossip if they were submitted over the RPC and + // added to the mempool. + b.eth.gossiper.Add(signedTx) + return nil } func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) { diff --git a/eth/backend.go b/eth/backend.go index 213387073f..a8de24fad9 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -70,6 +70,12 @@ type Settings struct { MaxBlocksPerRequest int64 // Maximum number of blocks to serve per getLogs request } +// PushGossiper sends pushes pending transactions to peers until they are +// removed from the mempool. +type PushGossiper interface { + Add(*types.Transaction) +} + // Ethereum implements the Ethereum full node service. type Ethereum struct { config *Config @@ -77,6 +83,7 @@ type Ethereum struct { // Handlers txPool *txpool.TxPool blockchain *core.BlockChain + gossiper PushGossiper // DB interfaces chainDb ethdb.Database // Block chain database @@ -117,6 +124,7 @@ func roundUpCacheSize(input int, allocSize int) int { func New( stack *node.Node, config *Config, + gossiper PushGossiper, chainDb ethdb.Database, settings Settings, lastAcceptedHash common.Hash, @@ -150,6 +158,7 @@ func New( eth := &Ethereum{ config: config, + gossiper: gossiper, chainDb: chainDb, eventMux: new(event.TypeMux), accountManager: stack.AccountManager(), @@ -228,7 +237,6 @@ func New( eth.bloomIndexer.Start(eth.blockchain) - config.TxPool.Journal = "" eth.txPool = txpool.NewTxPool(config.TxPool, eth.blockchain.Config(), eth.blockchain) eth.miner = miner.New(eth, &config.Miner, eth.blockchain.Config(), eth.EventMux(), eth.engine, clock) diff --git a/go.mod b/go.mod index 5d8afb93fd..4e84054be0 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/VictoriaMetrics/fastcache v1.10.0 - github.com/ava-labs/avalanchego v1.11.1 + github.com/ava-labs/avalanchego v1.11.2 github.com/cespare/cp v0.1.0 github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set/v2 v2.1.0 @@ -15,7 +15,7 @@ require ( github.com/fsnotify/fsnotify v1.6.0 github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 github.com/go-cmd/cmd v1.4.1 - github.com/google/uuid v1.3.0 + github.com/google/uuid v1.6.0 github.com/gorilla/rpc v1.2.0 github.com/gorilla/websocket v1.4.2 github.com/hashicorp/go-bexpr v0.1.10 @@ -38,27 +38,26 @@ require ( github.com/stretchr/testify v1.8.4 github.com/tyler-smith/go-bip39 v1.1.0 github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa - go.uber.org/goleak v1.2.1 + go.uber.org/goleak v1.3.0 go.uber.org/mock v0.4.0 - golang.org/x/crypto v0.17.0 - golang.org/x/sync v0.5.0 - golang.org/x/sys v0.15.0 + golang.org/x/crypto v0.18.0 + golang.org/x/sync v0.6.0 + golang.org/x/sys v0.16.0 golang.org/x/text v0.14.0 golang.org/x/time v0.1.0 - google.golang.org/protobuf v1.31.0 + google.golang.org/protobuf v1.32.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0 ) require ( github.com/BurntSushi/toml v1.3.2 // indirect github.com/DataDog/zstd v1.5.2 // indirect - github.com/Microsoft/go-winio v0.5.2 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect - github.com/ava-labs/coreth v0.13.0-rc.0 // indirect + github.com/ava-labs/coreth v0.13.1-rc.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/btcutil v1.1.3 // indirect - github.com/cenkalti/backoff/v4 v4.1.3 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect @@ -68,14 +67,13 @@ require ( github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect github.com/dlclark/regexp2 v1.7.0 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect - github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect github.com/go-stack/stack v1.8.1 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.3.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.2 // indirect @@ -84,7 +82,7 @@ require ( github.com/google/renameio/v2 v2.0.0 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/huin/goupnp v1.0.3 // indirect github.com/jackpal/gateway v1.0.6 // indirect @@ -118,25 +116,24 @@ require ( github.com/tklauser/numcpus v0.2.2 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect - go.opentelemetry.io/otel v1.11.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.0 // indirect - go.opentelemetry.io/otel/sdk v1.11.0 // indirect - go.opentelemetry.io/otel/trace v1.11.0 // indirect - go.opentelemetry.io/proto/otlp v0.19.0 // indirect + go.opentelemetry.io/otel v1.22.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 // indirect + go.opentelemetry.io/otel/metric v1.22.0 // indirect + go.opentelemetry.io/otel/sdk v1.22.0 // indirect + go.opentelemetry.io/otel/trace v1.22.0 // indirect + go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect golang.org/x/exp v0.0.0-20231127185646-65229373498e // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/term v0.15.0 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/term v0.16.0 // indirect golang.org/x/tools v0.16.0 // indirect gonum.org/v1/gonum v0.11.0 // indirect - google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.3 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 1767342461..40cbf87166 100644 --- a/go.sum +++ b/go.sum @@ -46,11 +46,8 @@ github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMd github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= -github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY= github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= @@ -58,12 +55,11 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBA github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/ava-labs/avalanchego v1.11.1 h1:NSelfZ/Di8uGCsRoFK32HOR262eHlpUFmAu8pbfg0Jo= -github.com/ava-labs/avalanchego v1.11.1/go.mod h1:+UpgT8X2fNN93+iE100efkZL7ePfBRfRdmpJ/i3YnyY= -github.com/ava-labs/coreth v0.13.0-rc.0 h1:V2l3qj2ek3geKDJAnF2M94mYJK8kg2kePixujfJ0bmk= -github.com/ava-labs/coreth v0.13.0-rc.0/go.mod h1:eUMbBLDhlZASJjcbf0gIcD2GMn2rRRCUxC8MXLt5QQk= +github.com/ava-labs/avalanchego v1.11.2 h1:8iodZ+RjqpRwHdiXPPtvaNt72qravge7voGzw3yPRzg= +github.com/ava-labs/avalanchego v1.11.2/go.mod h1:oTVnF9idL57J4LM/6RByTmKhI4QvV6OCnF99ysyBljE= +github.com/ava-labs/coreth v0.13.1-rc.5 h1:YcTs9nryZLkf4gPmMyFx1TREFpDTPdg/VCNGGHSF2TY= +github.com/ava-labs/coreth v0.13.1-rc.5/go.mod h1:4y1igTe/sFOIrpAtXoY+AdmfftNHrmrhBBRVfGCAPcw= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= @@ -91,13 +87,11 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= -github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -111,11 +105,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA= github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= @@ -167,8 +156,6 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2zljOa0= @@ -190,7 +177,6 @@ github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= @@ -203,8 +189,8 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= @@ -231,12 +217,9 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= -github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= +github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -283,7 +266,6 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= @@ -308,8 +290,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -323,10 +305,8 @@ github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0U github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 h1:gDLXvp5S9izjldquuoAhDzccbskOL6tDC5jMSyx3zxE= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2/go.mod h1:7pdNwVWBBHGiCxa9lAszqCJMbfTISJ7oMftp8+UGV08= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= @@ -488,7 +468,6 @@ github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= @@ -508,10 +487,8 @@ github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAm github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= @@ -594,25 +571,24 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opentelemetry.io/otel v1.11.0 h1:kfToEGMDq6TrVrJ9Vht84Y8y9enykSZzDDZglV0kIEk= -go.opentelemetry.io/otel v1.11.0/go.mod h1:H2KtuEphyMvlhZ+F7tg9GRhAOe60moNx61Ex+WmiKkk= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.0 h1:0dly5et1i/6Th3WHn0M6kYiJfFNzhhxanrJ0bOfnjEo= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.0/go.mod h1:+Lq4/WkdCkjbGcBMVHHg2apTbv8oMBf29QCnyCCJjNQ= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.0 h1:eyJ6njZmH16h9dOKCi7lMswAnGsSOwgTqWzfxqcuNr8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.0/go.mod h1:FnDp7XemjN3oZ3xGunnfOUTVwd2XcvLbtRAuOSU3oc8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.0 h1:j2RFV0Qdt38XQ2Jvi4WIsQ56w8T7eSirYbMw19VXRDg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.0/go.mod h1:pILgiTEtrqvZpoiuGdblDgS5dbIaTgDrkIuKfEFkt+A= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.0 h1:v29I/NbVp7LXQYMFZhU6q17D0jSEbYOAVONlrO1oH5s= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.0/go.mod h1:/RpLsmbQLDO1XCbWAM4S6TSwj8FKwwgyKKyqtvVfAnw= -go.opentelemetry.io/otel/sdk v1.11.0 h1:ZnKIL9V9Ztaq+ME43IUi/eo22mNsb6a7tGfzaOWB5fo= -go.opentelemetry.io/otel/sdk v1.11.0/go.mod h1:REusa8RsyKaq0OlyangWXaw97t2VogoO4SSEeKkSTAk= -go.opentelemetry.io/otel/trace v1.11.0 h1:20U/Vj42SX+mASlXLmSGBg6jpI1jQtv682lZtTAOVFI= -go.opentelemetry.io/otel/trace v1.11.0/go.mod h1:nyYjis9jy0gytE9LXGU+/m1sHTKbRY0fX0hulNNDP1U= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= -go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= -go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= +go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= +go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 h1:H2JFgRcGiyHg7H7bwcwaQJYrNFqCqrbTQ8K4p1OvDu8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0/go.mod h1:WfCWp1bGoYK8MeULtI15MmQVczfR+bFkk0DF3h06QmQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 h1:FyjCyI9jVEfqhUh2MoSkmolPjfh5fp2hnV0b0irxH4Q= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0/go.mod h1:hYwym2nDEeZfG/motx0p7L7J1N1vyzIThemQsb4g2qY= +go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= +go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= +go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= +go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= +go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= +go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -632,8 +608,8 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -718,8 +694,8 @@ golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -729,7 +705,6 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -742,8 +717,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -762,7 +737,6 @@ golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -789,7 +763,6 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -810,12 +783,12 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.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.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -948,7 +921,6 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= @@ -963,13 +935,12 @@ google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g= -google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98/go.mod h1:S7mY02OqCJTD0E1OiQy1F72PWFB4bZJ87cAtLPYgDR0= -google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw= -google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -984,16 +955,12 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= -google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= 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= @@ -1006,9 +973,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1028,7 +994,6 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go index 6d7fb681bc..45884d2995 100644 --- a/internal/ethapi/api_test.go +++ b/internal/ethapi/api_test.go @@ -54,7 +54,6 @@ import ( "github.com/ava-labs/subnet-evm/core/vm" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/rpc" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" @@ -225,7 +224,6 @@ func newTestBackend(t *testing.T, n int, gspec *core.Genesis, generator func(i i return backend } -func (b testBackend) SyncProgress() ethereum.SyncProgress { return ethereum.SyncProgress{} } func (b testBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { return big.NewInt(0), nil } diff --git a/peer/client.go b/peer/client.go index 41ebc7d6d9..d40e1a268a 100644 --- a/peer/client.go +++ b/peer/client.go @@ -34,9 +34,6 @@ type NetworkClient interface { // Returns response bytes, and ErrRequestFailed if the request failed. SendCrossChainRequest(ctx context.Context, chainID ids.ID, request []byte) ([]byte, error) - // Gossip sends given gossip message to peers - Gossip(gossip []byte) error - // TrackBandwidth should be called for each valid request with the bandwidth // (length of response divided by request time), and with 0 if the response is invalid. TrackBandwidth(nodeID ids.NodeID, bandwidth float64) @@ -90,10 +87,6 @@ func (c *client) SendCrossChainRequest(ctx context.Context, chainID ids.ID, requ return waitingHandler.WaitForResult(ctx) } -func (c *client) Gossip(gossip []byte) error { - return c.network.Gossip(gossip) -} - func (c *client) TrackBandwidth(nodeID ids.NodeID, bandwidth float64) { c.network.TrackBandwidth(nodeID, bandwidth) } diff --git a/peer/network.go b/peer/network.go index 3011356093..3e64df7872 100644 --- a/peer/network.go +++ b/peer/network.go @@ -51,9 +51,6 @@ type Network interface { // SendAppRequest sends message to given nodeID, notifying handler when there's a response or timeout SendAppRequest(ctx context.Context, nodeID ids.NodeID, message []byte, handler message.ResponseHandler) error - // Gossip sends given gossip message to peers - Gossip(gossip []byte) error - // SendCrossChainRequest sends a message to given chainID notifying handler when there's a response or timeout SendCrossChainRequest(ctx context.Context, chainID ids.ID, message []byte, handler message.ResponseHandler) error @@ -437,15 +434,6 @@ func (n *network) markRequestFulfilled(requestID uint32) (message.ResponseHandle return handler, true } -// Gossip sends given gossip message to peers -func (n *network) Gossip(gossip []byte) error { - if n.closed.Get() { - return nil - } - - return n.appSender.SendAppGossip(context.TODO(), gossip) -} - // AppGossip is called by avalanchego -> VM when there is an incoming AppGossip // from a peer. An error returned by this function is treated as fatal by the // engine. diff --git a/peer/network_test.go b/peer/network_test.go index be6a1e27b1..fa1f17053e 100644 --- a/peer/network_test.go +++ b/peer/network_test.go @@ -503,49 +503,6 @@ func TestOnRequestHonoursDeadline(t *testing.T) { assert.EqualValues(t, requestHandler.calls, 1) } -func TestGossip(t *testing.T) { - codecManager := buildCodec(t, HelloGossip{}) - crossChainCodecManager := buildCodec(t, ExampleCrossChainRequest{}, ExampleCrossChainResponse{}) - - nodeID := ids.GenerateTestNodeID() - var clientNetwork Network - wg := &sync.WaitGroup{} - sentGossip := false - wg.Add(1) - sender := testAppSender{ - sendAppGossipFn: func(msg []byte) error { - go func() { - defer wg.Done() - err := clientNetwork.AppGossip(context.Background(), nodeID, msg) - assert.NoError(t, err) - }() - sentGossip = true - return nil - }, - } - - gossipHandler := &testGossipHandler{} - p2pNetwork, err := p2p.NewNetwork(logging.NoLog{}, nil, prometheus.NewRegistry(), "") - require.NoError(t, err) - clientNetwork = NewNetwork(p2pNetwork, sender, codecManager, crossChainCodecManager, ids.EmptyNodeID, 1, 1) - clientNetwork.SetGossipHandler(gossipHandler) - - assert.NoError(t, clientNetwork.Connected(context.Background(), nodeID, defaultPeerVersion)) - - client := NewNetworkClient(clientNetwork) - defer clientNetwork.Shutdown() - - b, err := buildGossip(codecManager, HelloGossip{Msg: "hello there!"}) - assert.NoError(t, err) - - err = client.Gossip(b) - assert.NoError(t, err) - - wg.Wait() - assert.True(t, sentGossip) - assert.True(t, gossipHandler.received) -} - func TestHandleInvalidMessages(t *testing.T) { codecManager := buildCodec(t, HelloGossip{}, TestMessage{}) crossChainCodecManager := buildCodec(t, ExampleCrossChainRequest{}, ExampleCrossChainResponse{}) @@ -914,7 +871,7 @@ type testAppSender struct { sendCrossChainAppResponseFn func(ids.ID, uint32, []byte) error sendAppRequestFn func(context.Context, set.Set[ids.NodeID], uint32, []byte) error sendAppResponseFn func(ids.NodeID, uint32, []byte) error - sendAppGossipFn func([]byte) error + sendAppGossipFn func([]byte, int, int, int) error } func (t testAppSender) SendCrossChainAppRequest(_ context.Context, chainID ids.ID, requestID uint32, appRequestBytes []byte) error { @@ -937,8 +894,16 @@ func (t testAppSender) SendAppResponse(_ context.Context, nodeID ids.NodeID, req return t.sendAppResponseFn(nodeID, requestID, message) } -func (t testAppSender) SendAppGossip(_ context.Context, message []byte) error { - return t.sendAppGossipFn(message) +func (t testAppSender) SendAppGossip(_ context.Context, message []byte, numValidators int, numNonValidators int, numPeers int) error { + return t.sendAppGossipFn(message, numValidators, numNonValidators, numPeers) +} + +func (t testAppSender) SendAppError(ctx context.Context, nodeID ids.NodeID, requestID uint32, errorCode int32, errorMessage string) error { + panic("not implemented") +} + +func (t testAppSender) SendCrossChainAppError(ctx context.Context, chainID ids.ID, requestID uint32, errorCode int32, errorMessage string) error { + panic("not implemented") } func (t testAppSender) SendAppError(ctx context.Context, nodeID ids.NodeID, requestID uint32, errorCode int32, errorMessage string) error { diff --git a/plugin/evm/block_builder.go b/plugin/evm/block_builder.go index 0fefecc777..9cd749bcc1 100644 --- a/plugin/evm/block_builder.go +++ b/plugin/evm/block_builder.go @@ -27,8 +27,7 @@ type blockBuilder struct { ctx *snow.Context chainConfig *params.ChainConfig - txPool *txpool.TxPool - gossiper Gossiper + txPool *txpool.TxPool shutdownChan <-chan struct{} shutdownWg *sync.WaitGroup @@ -56,7 +55,6 @@ func (vm *VM) NewBlockBuilder(notifyBuildBlockChan chan<- commonEng.Message) *bl ctx: vm.ctx, chainConfig: vm.chainConfig, txPool: vm.txPool, - gossiper: vm.gossiper, shutdownChan: vm.shutdownChan, shutdownWg: &vm.shutdownWg, notifyBuildBlockChan: notifyBuildBlockChan, @@ -152,20 +150,9 @@ func (b *blockBuilder) awaitSubmittedTxs() { for { select { - case ethTxsEvent := <-txSubmitChan: + case <-txSubmitChan: log.Trace("New tx detected, trying to generate a block") b.signalTxsReady() - - if b.gossiper != nil && len(ethTxsEvent.Txs) > 0 { - // [GossipEthTxs] will block unless [gossiper.ethTxsToGossipChan] (an - // unbuffered channel) is listened on - if err := b.gossiper.GossipEthTxs(ethTxsEvent.Txs); err != nil { - log.Warn( - "failed to gossip new eth transactions", - "err", err, - ) - } - } case <-b.shutdownChan: b.buildBlockTimer.Stop() return diff --git a/plugin/evm/config.go b/plugin/evm/config.go index 85e164b980..1c5847d4f1 100644 --- a/plugin/evm/config.go +++ b/plugin/evm/config.go @@ -35,12 +35,13 @@ const ( defaultMaxBlocksPerRequest = 0 // Default to no maximum on the number of blocks per getLogs request defaultContinuousProfilerFrequency = 15 * time.Minute defaultContinuousProfilerMaxFiles = 5 - defaultRegossipFrequency = 1 * time.Minute - defaultRegossipMaxTxs = 16 - defaultRegossipTxsPerAddress = 1 - defaultPriorityRegossipFrequency = 1 * time.Second - defaultPriorityRegossipMaxTxs = 32 - defaultPriorityRegossipTxsPerAddress = 16 + defaultPushGossipNumValidators = 100 + defaultPushGossipNumPeers = 0 + defaultPushRegossipNumValidators = 10 + defaultPushRegossipNumPeers = 0 + defaultPushGossipFrequency = 100 * time.Millisecond + defaultPullGossipFrequency = 1 * time.Second + defaultRegossipFrequency = 30 * time.Second defaultOfflinePruningBloomFilterSize uint64 = 512 // Default size (MB) for the offline pruner to use defaultLogLevel = "info" defaultLogJSONFormat = false @@ -133,14 +134,13 @@ type Config struct { // API Settings LocalTxsEnabled bool `json:"local-txs-enabled"` - TxPoolJournal string `json:"tx-pool-journal"` - TxPoolRejournal Duration `json:"tx-pool-rejournal"` TxPoolPriceLimit uint64 `json:"tx-pool-price-limit"` TxPoolPriceBump uint64 `json:"tx-pool-price-bump"` TxPoolAccountSlots uint64 `json:"tx-pool-account-slots"` TxPoolGlobalSlots uint64 `json:"tx-pool-global-slots"` TxPoolAccountQueue uint64 `json:"tx-pool-account-queue"` TxPoolGlobalQueue uint64 `json:"tx-pool-global-queue"` + TxPoolLifetime Duration `json:"tx-pool-lifetime"` APIMaxDuration Duration `json:"api-max-duration"` WSCPURefillRate Duration `json:"ws-cpu-refill-rate"` @@ -156,14 +156,14 @@ type Config struct { KeystoreInsecureUnlockAllowed bool `json:"keystore-insecure-unlock-allowed"` // Gossip Settings - RemoteGossipOnlyEnabled bool `json:"remote-gossip-only-enabled"` - RegossipFrequency Duration `json:"regossip-frequency"` - RegossipMaxTxs int `json:"regossip-max-txs"` - RegossipTxsPerAddress int `json:"regossip-txs-per-address"` - PriorityRegossipFrequency Duration `json:"priority-regossip-frequency"` - PriorityRegossipMaxTxs int `json:"priority-regossip-max-txs"` - PriorityRegossipTxsPerAddress int `json:"priority-regossip-txs-per-address"` - PriorityRegossipAddresses []common.Address `json:"priority-regossip-addresses"` + PushGossipNumValidators int `json:"push-gossip-num-validators"` + PushGossipNumPeers int `json:"push-gossip-num-peers"` + PushRegossipNumValidators int `json:"push-regossip-num-validators"` + PushRegossipNumPeers int `json:"push-regossip-num-peers"` + PushGossipFrequency Duration `json:"push-gossip-frequency"` + PullGossipFrequency Duration `json:"pull-gossip-frequency"` + RegossipFrequency Duration `json:"regossip-frequency"` + PriorityRegossipAddresses []common.Address `json:"priority-regossip-addresses"` // Log LogLevel string `json:"log-level"` @@ -239,14 +239,13 @@ func (c *Config) SetDefaults() { c.RPCTxFeeCap = defaultRpcTxFeeCap c.MetricsExpensiveEnabled = defaultMetricsExpensiveEnabled - c.TxPoolJournal = txpool.DefaultConfig.Journal - c.TxPoolRejournal = Duration{txpool.DefaultConfig.Rejournal} c.TxPoolPriceLimit = txpool.DefaultConfig.PriceLimit c.TxPoolPriceBump = txpool.DefaultConfig.PriceBump c.TxPoolAccountSlots = txpool.DefaultConfig.AccountSlots c.TxPoolGlobalSlots = txpool.DefaultConfig.GlobalSlots c.TxPoolAccountQueue = txpool.DefaultConfig.AccountQueue c.TxPoolGlobalQueue = txpool.DefaultConfig.GlobalQueue + c.TxPoolLifetime.Duration = txpool.DefaultConfig.Lifetime c.APIMaxDuration.Duration = defaultApiMaxDuration c.WSCPURefillRate.Duration = defaultWsCpuRefillRate @@ -264,11 +263,12 @@ func (c *Config) SetDefaults() { c.CommitInterval = defaultCommitInterval c.SnapshotWait = defaultSnapshotWait c.RegossipFrequency.Duration = defaultRegossipFrequency - c.RegossipMaxTxs = defaultRegossipMaxTxs - c.RegossipTxsPerAddress = defaultRegossipTxsPerAddress - c.PriorityRegossipFrequency.Duration = defaultPriorityRegossipFrequency - c.PriorityRegossipMaxTxs = defaultPriorityRegossipMaxTxs - c.PriorityRegossipTxsPerAddress = defaultPriorityRegossipTxsPerAddress + c.PushGossipNumValidators = defaultPushGossipNumValidators + c.PushGossipNumPeers = defaultPushGossipNumPeers + c.PushRegossipNumValidators = defaultPushRegossipNumValidators + c.PushRegossipNumPeers = defaultPushRegossipNumPeers + c.PushGossipFrequency.Duration = defaultPushGossipFrequency + c.PullGossipFrequency.Duration = defaultPullGossipFrequency c.OfflinePruningBloomFilterSize = defaultOfflinePruningBloomFilterSize c.LogLevel = defaultLogLevel c.LogJSONFormat = defaultLogJSONFormat diff --git a/plugin/evm/config_test.go b/plugin/evm/config_test.go index 53a7777423..2a69ea68d0 100644 --- a/plugin/evm/config_test.go +++ b/plugin/evm/config_test.go @@ -22,8 +22,8 @@ func TestUnmarshalConfig(t *testing.T) { }{ { "string durations parsed", - []byte(`{"api-max-duration": "1m", "continuous-profiler-frequency": "2m", "tx-pool-rejournal": "3m30s"}`), - Config{APIMaxDuration: Duration{1 * time.Minute}, ContinuousProfilerFrequency: Duration{2 * time.Minute}, TxPoolRejournal: Duration{3*time.Minute + 30*time.Second}}, + []byte(`{"api-max-duration": "1m", "continuous-profiler-frequency": "2m"}`), + Config{APIMaxDuration: Duration{1 * time.Minute}, ContinuousProfilerFrequency: Duration{2 * time.Minute}}, false, }, { @@ -34,8 +34,8 @@ func TestUnmarshalConfig(t *testing.T) { }, { "nanosecond durations parsed", - []byte(`{"api-max-duration": 5000000000, "continuous-profiler-frequency": 5000000000, "tx-pool-rejournal": 9000000000}`), - Config{APIMaxDuration: Duration{5 * time.Second}, ContinuousProfilerFrequency: Duration{5 * time.Second}, TxPoolRejournal: Duration{9 * time.Second}}, + []byte(`{"api-max-duration": 5000000000, "continuous-profiler-frequency": 5000000000}`), + Config{APIMaxDuration: Duration{5 * time.Second}, ContinuousProfilerFrequency: Duration{5 * time.Second}}, false, }, { @@ -47,9 +47,8 @@ func TestUnmarshalConfig(t *testing.T) { { "tx pool configurations", - []byte(`{"tx-pool-journal": "hello", "tx-pool-price-limit": 1, "tx-pool-price-bump": 2, "tx-pool-account-slots": 3, "tx-pool-global-slots": 4, "tx-pool-account-queue": 5, "tx-pool-global-queue": 6}`), + []byte(`{"tx-pool-price-limit": 1, "tx-pool-price-bump": 2, "tx-pool-account-slots": 3, "tx-pool-global-slots": 4, "tx-pool-account-queue": 5, "tx-pool-global-queue": 6}`), Config{ - TxPoolJournal: "hello", TxPoolPriceLimit: 1, TxPoolPriceBump: 2, TxPoolAccountSlots: 3, diff --git a/plugin/evm/gossip.go b/plugin/evm/gossip.go index 0db574f5fe..e87bb354d3 100644 --- a/plugin/evm/gossip.go +++ b/plugin/evm/gossip.go @@ -11,6 +11,7 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/logging" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/prometheus/client_golang/prometheus" @@ -20,14 +21,19 @@ import ( "github.com/ava-labs/subnet-evm/core" "github.com/ava-labs/subnet-evm/core/txpool" "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/subnet-evm/eth" ) +const pendingTxsBuffer = 10 + var ( _ p2p.Handler = (*txGossipHandler)(nil) _ gossip.Gossipable = (*GossipEthTx)(nil) _ gossip.Marshaller[*GossipEthTx] = (*GossipEthTxMarshaller)(nil) _ gossip.Set[*GossipEthTx] = (*GossipEthTxPool)(nil) + + _ eth.PushGossiper = (*EthPushGossiper)(nil) ) func newTxGossipHandler[T gossip.Gossipable]( @@ -41,11 +47,9 @@ func newTxGossipHandler[T gossip.Gossipable]( validators *p2p.Validators, ) txGossipHandler { // push gossip messages can be handled from any peer - handler := gossip.NewHandler[T]( + handler := gossip.NewHandler( log, marshaller, - // Don't forward gossip to avoid double-forwarding - gossip.NoOpAccumulator[T]{}, mempool, metrics, maxMessageSize, @@ -93,7 +97,7 @@ func NewGossipEthTxPool(mempool *txpool.TxPool, registerer prometheus.Registerer return &GossipEthTxPool{ mempool: mempool, - pendingTxs: make(chan core.NewTxsEvent), + pendingTxs: make(chan core.NewTxsEvent, pendingTxsBuffer), bloom: bloom, }, nil } @@ -146,6 +150,12 @@ func (g *GossipEthTxPool) Add(tx *GossipEthTx) error { return g.mempool.AddRemotes([]*types.Transaction{tx.Tx})[0] } +// Has should just return whether or not the [txID] is still in the mempool, +// not whether it is in the mempool AND pending. +func (g *GossipEthTxPool) Has(txID ids.ID) bool { + return g.mempool.Has(common.Hash(txID)) +} + func (g *GossipEthTxPool) Iterate(f func(tx *GossipEthTx) bool) { g.mempool.IteratePending(func(tx *types.Transaction) bool { return f(&GossipEthTx{Tx: tx}) @@ -180,3 +190,19 @@ type GossipEthTx struct { func (tx *GossipEthTx) GossipID() ids.ID { return ids.ID(tx.Tx.Hash()) } + +// EthPushGossiper is used by the ETH backend to push transactions issued over +// the RPC and added to the mempool to peers. +type EthPushGossiper struct { + vm *VM +} + +func (e *EthPushGossiper) Add(tx *types.Transaction) { + // eth.Backend is initialized before the [ethTxPushGossiper] is created, so + // we just ignore any gossip requests until it is set. + ethTxPushGossiper := e.vm.ethTxPushGossiper.Get() + if ethTxPushGossiper == nil { + return + } + ethTxPushGossiper.Add(&GossipEthTx{tx}) +} diff --git a/plugin/evm/gossip_stats.go b/plugin/evm/gossip_stats.go index aab080fde4..3a6f552fcc 100644 --- a/plugin/evm/gossip_stats.go +++ b/plugin/evm/gossip_stats.go @@ -9,12 +9,6 @@ var _ GossipStats = &gossipStats{} // GossipStats contains methods for updating incoming and outgoing gossip stats. type GossipStats interface { - GossipReceivedStats - GossipSentStats -} - -// GossipReceivedStats groups functions for incoming gossip stats. -type GossipReceivedStats interface { IncEthTxsGossipReceived() // new vs. known txs received @@ -23,27 +17,11 @@ type GossipReceivedStats interface { IncEthTxsGossipReceivedNew() } -// GossipSentStats groups functions for outgoing gossip stats. -type GossipSentStats interface { - IncEthTxsGossipSent() - - // regossip - IncEthTxsRegossipQueued() - IncEthTxsRegossipQueuedLocal(count int) - IncEthTxsRegossipQueuedRemote(count int) -} - // gossipStats implements stats for incoming and outgoing gossip stats. type gossipStats struct { // messages - ethTxsGossipSent metrics.Counter ethTxsGossipReceived metrics.Counter - // regossip - ethTxsRegossipQueued metrics.Counter - ethTxsRegossipQueuedLocal metrics.Counter - ethTxsRegossipQueuedRemote metrics.Counter - // new vs. known txs received ethTxsGossipReceivedError metrics.Counter ethTxsGossipReceivedKnown metrics.Counter @@ -52,13 +30,7 @@ type gossipStats struct { func NewGossipStats() GossipStats { return &gossipStats{ - ethTxsGossipSent: metrics.GetOrRegisterCounter("gossip_eth_txs_sent", nil), - ethTxsGossipReceived: metrics.GetOrRegisterCounter("gossip_eth_txs_received", nil), - - ethTxsRegossipQueued: metrics.GetOrRegisterCounter("regossip_eth_txs_queued_attempts", nil), - ethTxsRegossipQueuedLocal: metrics.GetOrRegisterCounter("regossip_eth_txs_queued_local_tx_count", nil), - ethTxsRegossipQueuedRemote: metrics.GetOrRegisterCounter("regossip_eth_txs_queued_remote_tx_count", nil), - + ethTxsGossipReceived: metrics.GetOrRegisterCounter("gossip_eth_txs_received", nil), ethTxsGossipReceivedError: metrics.GetOrRegisterCounter("gossip_eth_txs_received_error", nil), ethTxsGossipReceivedKnown: metrics.GetOrRegisterCounter("gossip_eth_txs_received_known", nil), ethTxsGossipReceivedNew: metrics.GetOrRegisterCounter("gossip_eth_txs_received_new", nil), @@ -72,15 +44,3 @@ func (g *gossipStats) IncEthTxsGossipReceived() { g.ethTxsGossipReceived.Inc(1) func (g *gossipStats) IncEthTxsGossipReceivedError() { g.ethTxsGossipReceivedError.Inc(1) } func (g *gossipStats) IncEthTxsGossipReceivedKnown() { g.ethTxsGossipReceivedKnown.Inc(1) } func (g *gossipStats) IncEthTxsGossipReceivedNew() { g.ethTxsGossipReceivedNew.Inc(1) } - -// outgoing messages -func (g *gossipStats) IncEthTxsGossipSent() { g.ethTxsGossipSent.Inc(1) } - -// regossip -func (g *gossipStats) IncEthTxsRegossipQueued() { g.ethTxsRegossipQueued.Inc(1) } -func (g *gossipStats) IncEthTxsRegossipQueuedLocal(count int) { - g.ethTxsRegossipQueuedLocal.Inc(int64(count)) -} -func (g *gossipStats) IncEthTxsRegossipQueuedRemote(count int) { - g.ethTxsRegossipQueuedRemote.Inc(int64(count)) -} diff --git a/plugin/evm/gossip_test.go b/plugin/evm/gossip_test.go index a6b8dc0498..e1b47ec972 100644 --- a/plugin/evm/gossip_test.go +++ b/plugin/evm/gossip_test.go @@ -98,7 +98,6 @@ func setupPoolWithConfig(t *testing.T, config *params.ChainConfig, fundedAddress chain, err := core.NewBlockChain(diskdb, core.DefaultCacheConfig, gspec, engine, vm.Config{}, common.Hash{}, false) require.NoError(t, err) testTxPoolConfig := txpool.DefaultConfig - testTxPoolConfig.Journal = "" pool := txpool.NewTxPool(testTxPoolConfig, config, chain) return pool diff --git a/plugin/evm/gossiper.go b/plugin/evm/gossiper.go deleted file mode 100644 index 281262918a..0000000000 --- a/plugin/evm/gossiper.go +++ /dev/null @@ -1,488 +0,0 @@ -// (c) 2019-2021, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package evm - -import ( - "context" - "math/big" - "sync" - "time" - - "github.com/ava-labs/avalanchego/codec" - "github.com/ava-labs/avalanchego/network/p2p/gossip" - - "github.com/ava-labs/subnet-evm/peer" - - "github.com/ava-labs/avalanchego/cache" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/snow" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" - - "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/txpool" - "github.com/ava-labs/subnet-evm/core/types" - "github.com/ava-labs/subnet-evm/plugin/evm/message" -) - -const ( - // We allow [recentCacheSize] to be fairly large because we only store hashes - // in the cache, not entire transactions. - recentCacheSize = 512 - - // [ethTxsGossipInterval] is how often we attempt to gossip newly seen - // transactions to other nodes. - ethTxsGossipInterval = 500 * time.Millisecond - - // [minGossipBatchInterval] is the minimum amount of time that must pass - // before our last gossip to peers. - minGossipBatchInterval = 50 * time.Millisecond -) - -// Gossiper handles outgoing gossip of transactions -type Gossiper interface { - // GossipEthTxs sends AppGossip message containing the given [txs] - GossipEthTxs(txs []*types.Transaction) error -} - -// pushGossiper is used to gossip transactions to the network -type pushGossiper struct { - ctx *snow.Context - config Config - - client peer.NetworkClient - blockchain *core.BlockChain - txPool *txpool.TxPool - ethTxGossiper gossip.Accumulator[*GossipEthTx] - - // We attempt to batch transactions we need to gossip to avoid runaway - // amplification of mempol chatter. - ethTxsToGossipChan chan []*types.Transaction - ethTxsToGossip map[common.Hash]*types.Transaction - lastGossiped time.Time - shutdownChan chan struct{} - shutdownWg *sync.WaitGroup - - // [recentEthTxs] prevent us from over-gossiping the - // same transaction in a short period of time. - recentEthTxs *cache.LRU[common.Hash, interface{}] - - codec codec.Manager - signer types.Signer - stats GossipSentStats -} - -// createGossiper constructs and returns a pushGossiper or noopGossiper -// based on whether vm.chainConfig.SubnetEVMTimestamp is set -func (vm *VM) createGossiper( - stats GossipStats, - ethTxGossiper gossip.Accumulator[*GossipEthTx], -) Gossiper { - net := &pushGossiper{ - ctx: vm.ctx, - config: vm.config, - client: vm.client, - blockchain: vm.blockChain, - txPool: vm.txPool, - ethTxsToGossipChan: make(chan []*types.Transaction), - ethTxsToGossip: make(map[common.Hash]*types.Transaction), - shutdownChan: vm.shutdownChan, - shutdownWg: &vm.shutdownWg, - recentEthTxs: &cache.LRU[common.Hash, interface{}]{Size: recentCacheSize}, - codec: vm.networkCodec, - signer: types.LatestSigner(vm.blockChain.Config()), - stats: stats, - ethTxGossiper: ethTxGossiper, - } - - net.awaitEthTxGossip() - return net -} - -// addrStatus used to track the metadata of addresses being queued for -// regossip. -type addrStatus struct { - nonce uint64 - txsAdded int -} - -// queueExecutableTxs attempts to select up to [maxTxs] from the tx pool for -// regossiping (with at most [maxAcctTxs] per account). -// -// We assume that [txs] contains an array of nonce-ordered transactions for a given -// account. This array of transactions can have gaps and start at a nonce lower -// than the current state of an account. -func (n *pushGossiper) queueExecutableTxs( - state *state.StateDB, - baseFee *big.Int, - txs map[common.Address]types.Transactions, - regossipFrequency Duration, - maxTxs int, - maxAcctTxs int, -) types.Transactions { - var ( - stxs = types.NewTransactionsByPriceAndNonce(n.signer, txs, baseFee) - statuses = make(map[common.Address]*addrStatus) - queued = make([]*types.Transaction, 0, maxTxs) - ) - - // Iterate over possible transactions until there are none left or we have - // hit the regossip target. - for len(queued) < maxTxs { - next := stxs.Peek() - if next == nil { - break - } - - sender, _ := types.Sender(n.signer, next) - status, ok := statuses[sender] - if !ok { - status = &addrStatus{ - nonce: state.GetNonce(sender), - } - statuses[sender] = status - } - - // The tx pool may be out of sync with current state, so we iterate - // through the account transactions until we get to one that is - // executable. - switch { - case next.Nonce() < status.nonce: - stxs.Shift() - continue - case next.Nonce() > status.nonce, time.Since(next.FirstSeen()) < regossipFrequency.Duration, - status.txsAdded >= maxAcctTxs: - stxs.Pop() - continue - } - queued = append(queued, next) - status.nonce++ - status.txsAdded++ - stxs.Shift() - } - - return queued -} - -// queueRegossipTxs finds the best non-priority transactions in the mempool and adds up to -// [RegossipMaxTxs] of them to [txsToGossip]. -func (n *pushGossiper) queueRegossipTxs() types.Transactions { - // Fetch all pending transactions - pending := n.txPool.Pending(true) - - // Split the pending transactions into locals and remotes - localTxs := make(map[common.Address]types.Transactions) - remoteTxs := pending - for _, account := range n.txPool.Locals() { - if txs := remoteTxs[account]; len(txs) > 0 { - delete(remoteTxs, account) - localTxs[account] = txs - } - } - - // Add best transactions to be gossiped (preferring local txs) - tip := n.blockchain.CurrentBlock() - state, err := n.blockchain.StateAt(tip.Root) - if err != nil || state == nil { - log.Debug( - "could not get state at tip", - "tip", tip.Hash(), - "err", err, - ) - return nil - } - rgFrequency := n.config.RegossipFrequency - rgMaxTxs := n.config.RegossipMaxTxs - rgTxsPerAddr := n.config.RegossipTxsPerAddress - localQueued := n.queueExecutableTxs(state, tip.BaseFee, localTxs, rgFrequency, rgMaxTxs, rgTxsPerAddr) - localCount := len(localQueued) - n.stats.IncEthTxsRegossipQueuedLocal(localCount) - if localCount >= rgMaxTxs { - n.stats.IncEthTxsRegossipQueued() - return localQueued - } - remoteQueued := n.queueExecutableTxs(state, tip.BaseFee, remoteTxs, rgFrequency, rgMaxTxs-localCount, rgTxsPerAddr) - n.stats.IncEthTxsRegossipQueuedRemote(len(remoteQueued)) - if localCount+len(remoteQueued) > 0 { - // only increment the regossip stat when there are any txs queued - n.stats.IncEthTxsRegossipQueued() - } - return append(localQueued, remoteQueued...) -} - -// queuePriorityRegossipTxs finds the best priority transactions in the mempool and adds up to -// [PriorityRegossipMaxTxs] of them to [txsToGossip]. -func (n *pushGossiper) queuePriorityRegossipTxs() types.Transactions { - // Fetch all pending transactions from the priority addresses - priorityTxs := n.txPool.PendingFrom(n.config.PriorityRegossipAddresses, true) - - // Add best transactions to be gossiped - tip := n.blockchain.CurrentBlock() - state, err := n.blockchain.StateAt(tip.Root) - if err != nil || state == nil { - log.Debug( - "could not get state at tip", - "tip", tip.Hash(), - "err", err, - ) - return nil - } - return n.queueExecutableTxs( - state, tip.BaseFee, priorityTxs, - n.config.PriorityRegossipFrequency, - n.config.PriorityRegossipMaxTxs, - n.config.PriorityRegossipTxsPerAddress, - ) -} - -// awaitEthTxGossip periodically gossips transactions that have been queued for -// gossip at least once every [ethTxsGossipInterval]. -func (n *pushGossiper) awaitEthTxGossip() { - n.shutdownWg.Add(1) - go n.ctx.Log.RecoverAndPanic(func() { - var ( - gossipTicker = time.NewTicker(ethTxsGossipInterval) - regossipTicker = time.NewTicker(n.config.RegossipFrequency.Duration) - priorityRegossipTicker = time.NewTicker(n.config.PriorityRegossipFrequency.Duration) - ) - defer func() { - gossipTicker.Stop() - regossipTicker.Stop() - priorityRegossipTicker.Stop() - n.shutdownWg.Done() - }() - - for { - select { - case <-gossipTicker.C: - if attempted, err := n.gossipEthTxs(false); err != nil { - log.Warn( - "failed to send eth transactions", - "len(txs)", attempted, - "err", err, - ) - } - if err := n.ethTxGossiper.Gossip(context.TODO()); err != nil { - log.Warn( - "failed to send eth transactions", - "err", err, - ) - } - case <-regossipTicker.C: - for _, tx := range n.queueRegossipTxs() { - n.ethTxsToGossip[tx.Hash()] = tx - } - if attempted, err := n.gossipEthTxs(true); err != nil { - log.Warn( - "failed to regossip eth transactions", - "len(txs)", attempted, - "err", err, - ) - } - case <-priorityRegossipTicker.C: - for _, tx := range n.queuePriorityRegossipTxs() { - n.ethTxsToGossip[tx.Hash()] = tx - } - if attempted, err := n.gossipEthTxs(true); err != nil { - log.Warn( - "failed to regossip priority eth transactions", - "len(txs)", attempted, - "err", err, - ) - } - case txs := <-n.ethTxsToGossipChan: - for _, tx := range txs { - n.ethTxsToGossip[tx.Hash()] = tx - } - if attempted, err := n.gossipEthTxs(false); err != nil { - log.Warn( - "failed to send eth transactions", - "len(txs)", attempted, - "err", err, - ) - } - - gossipTxs := make([]*GossipEthTx, 0, len(txs)) - for _, tx := range txs { - gossipTxs = append(gossipTxs, &GossipEthTx{Tx: tx}) - } - - n.ethTxGossiper.Add(gossipTxs...) - if err := n.ethTxGossiper.Gossip(context.TODO()); err != nil { - log.Warn( - "failed to send eth transactions", - "len(txs)", len(txs), - "err", err, - ) - } - - case <-n.shutdownChan: - return - } - } - }) -} - -func (n *pushGossiper) sendEthTxs(txs []*types.Transaction) error { - if len(txs) == 0 { - return nil - } - - txBytes, err := rlp.EncodeToBytes(txs) - if err != nil { - return err - } - msg := message.EthTxsGossip{ - Txs: txBytes, - } - msgBytes, err := message.BuildGossipMessage(n.codec, msg) - if err != nil { - return err - } - - log.Trace( - "gossiping eth txs", - "len(txs)", len(txs), - "size(txs)", len(msg.Txs), - ) - n.stats.IncEthTxsGossipSent() - return n.client.Gossip(msgBytes) -} - -func (n *pushGossiper) gossipEthTxs(force bool) (int, error) { - if (!force && time.Since(n.lastGossiped) < minGossipBatchInterval) || len(n.ethTxsToGossip) == 0 { - return 0, nil - } - n.lastGossiped = time.Now() - txs := make([]*types.Transaction, 0, len(n.ethTxsToGossip)) - for _, tx := range n.ethTxsToGossip { - txs = append(txs, tx) - delete(n.ethTxsToGossip, tx.Hash()) - } - - selectedTxs := make([]*types.Transaction, 0) - for _, tx := range txs { - txHash := tx.Hash() - txStatus := n.txPool.Status([]common.Hash{txHash})[0] - if txStatus != txpool.TxStatusPending { - continue - } - - if n.config.RemoteGossipOnlyEnabled && n.txPool.HasLocal(txHash) { - continue - } - - // We check [force] outside of the if statement to avoid an unnecessary - // cache lookup. - if !force { - if _, has := n.recentEthTxs.Get(txHash); has { - continue - } - } - n.recentEthTxs.Put(txHash, nil) - - selectedTxs = append(selectedTxs, tx) - } - - if len(selectedTxs) == 0 { - return 0, nil - } - - // Attempt to gossip [selectedTxs] - msgTxs := make([]*types.Transaction, 0) - msgTxsSize := uint64(0) - for _, tx := range selectedTxs { - size := tx.Size() - if msgTxsSize+size > message.EthMsgSoftCapSize { - if err := n.sendEthTxs(msgTxs); err != nil { - return len(selectedTxs), err - } - msgTxs = msgTxs[:0] - msgTxsSize = 0 - } - msgTxs = append(msgTxs, tx) - msgTxsSize += size - } - - // Send any remaining [msgTxs] - return len(selectedTxs), n.sendEthTxs(msgTxs) -} - -// GossipEthTxs enqueues the provided [txs] for gossiping. At some point, the -// [pushGossiper] will attempt to gossip the provided txs to other nodes -// (usually right away if not under load). -// -// NOTE: We never return a non-nil error from this function but retain the -// option to do so in case it becomes useful. -func (n *pushGossiper) GossipEthTxs(txs []*types.Transaction) error { - select { - case n.ethTxsToGossipChan <- txs: - case <-n.shutdownChan: - } - return nil -} - -// GossipHandler handles incoming gossip messages -type GossipHandler struct { - vm *VM - txPool *txpool.TxPool - stats GossipReceivedStats -} - -func NewGossipHandler(vm *VM, stats GossipReceivedStats) *GossipHandler { - return &GossipHandler{ - vm: vm, - txPool: vm.txPool, - stats: stats, - } -} - -func (h *GossipHandler) HandleEthTxs(nodeID ids.NodeID, msg message.EthTxsGossip) error { - log.Trace( - "AppGossip called with EthTxsGossip", - "peerID", nodeID, - "size(txs)", len(msg.Txs), - ) - - if len(msg.Txs) == 0 { - log.Trace( - "AppGossip received empty EthTxsGossip Message", - "peerID", nodeID, - ) - return nil - } - - // The maximum size of this encoded object is enforced by the codec. - txs := make([]*types.Transaction, 0) - if err := rlp.DecodeBytes(msg.Txs, &txs); err != nil { - log.Trace( - "AppGossip provided invalid txs", - "peerID", nodeID, - "err", err, - ) - return nil - } - h.stats.IncEthTxsGossipReceived() - errs := h.txPool.AddRemotes(txs) - for i, err := range errs { - if err != nil { - log.Trace( - "AppGossip failed to add to mempool", - "err", err, - "tx", txs[i].Hash(), - ) - if err == txpool.ErrAlreadyKnown { - h.stats.IncEthTxsGossipReceivedKnown() - } else { - h.stats.IncEthTxsGossipReceivedError() - } - continue - } - h.stats.IncEthTxsGossipReceivedNew() - } - return nil -} diff --git a/plugin/evm/gossiper_eth_gossiping_test.go b/plugin/evm/gossiper_eth_gossiping_test.go index 22982f2d69..96055d01d8 100644 --- a/plugin/evm/gossiper_eth_gossiping_test.go +++ b/plugin/evm/gossiper_eth_gossiping_test.go @@ -7,7 +7,6 @@ import ( "context" "crypto/ecdsa" "encoding/json" - "fmt" "math/big" "os" "strings" @@ -72,158 +71,6 @@ func getValidEthTxs(key *ecdsa.PrivateKey, count int, gasPrice *big.Int) []*type return res } -// show that locally issued eth txs are gossiped -// Note: channel through which subnet-evm mempool push txs to vm is injected here -// to ease up UT, which target only VM behaviors in response to subnet-evm mempool -// signals -func TestMempoolEthTxsAddedTxsGossipedAfterActivation(t *testing.T) { - if os.Getenv("RUN_FLAKY_TESTS") != "true" { - t.Skip("FLAKY") - } - assert := assert.New(t) - - key, err := crypto.GenerateKey() - assert.NoError(err) - - addr := crypto.PubkeyToAddress(key.PublicKey) - - genesisJSON, err := fundAddressByGenesis([]common.Address{addr}) - assert.NoError(err) - - _, vm, _, sender := GenesisVM(t, true, genesisJSON, "", "") - defer func() { - err := vm.Shutdown(context.Background()) - assert.NoError(err) - }() - vm.txPool.SetGasPrice(common.Big1) - vm.txPool.SetMinFee(common.Big0) - - // create eth txes - ethTxs := getValidEthTxs(key, 3, common.Big1) - - var wg sync.WaitGroup - wg.Add(2) - sender.CantSendAppGossip = false - signal1 := make(chan struct{}) - seen := 0 - sender.SendAppGossipF = func(_ context.Context, gossipedBytes []byte) error { - if seen == 0 { - notifyMsgIntf, err := message.ParseGossipMessage(vm.networkCodec, gossipedBytes) - assert.NoError(err) - - requestMsg, ok := notifyMsgIntf.(message.EthTxsGossip) - assert.True(ok) - assert.NotEmpty(requestMsg.Txs) - - txs := make([]*types.Transaction, 0) - assert.NoError(rlp.DecodeBytes(requestMsg.Txs, &txs)) - assert.Len(txs, 2) - assert.ElementsMatch( - []common.Hash{ethTxs[0].Hash(), ethTxs[1].Hash()}, - []common.Hash{txs[0].Hash(), txs[1].Hash()}, - ) - seen++ - close(signal1) - } else if seen == 1 { - notifyMsgIntf, err := message.ParseGossipMessage(vm.networkCodec, gossipedBytes) - assert.NoError(err) - - requestMsg, ok := notifyMsgIntf.(message.EthTxsGossip) - assert.True(ok) - assert.NotEmpty(requestMsg.Txs) - - txs := make([]*types.Transaction, 0) - assert.NoError(rlp.DecodeBytes(requestMsg.Txs, &txs)) - assert.Len(txs, 1) - assert.Equal(ethTxs[2].Hash(), txs[0].Hash()) - - seen++ - } else { - t.Fatal("should not be seen 3 times") - } - wg.Done() - return nil - } - - // Notify VM about eth txs - errs := vm.txPool.AddRemotesSync(ethTxs[:2]) - for _, err := range errs { - assert.NoError(err, "failed adding subnet-evm tx to mempool") - } - - // Gossip txs again (shouldn't gossip hashes) - <-signal1 // wait until reorg processed - assert.NoError(vm.gossiper.GossipEthTxs(ethTxs[:2])) - - errs = vm.txPool.AddRemotesSync(ethTxs) - assert.Contains(errs[0].Error(), "already known") - assert.Contains(errs[1].Error(), "already known") - assert.NoError(errs[2], "failed adding subnet-evm tx to mempool") - - attemptAwait(t, &wg, 5*time.Second) -} - -// show that locally issued eth txs are chunked correctly -func TestMempoolEthTxsAddedTxsGossipedAfterActivationChunking(t *testing.T) { - if os.Getenv("RUN_FLAKY_TESTS") != "true" { - t.Skip("FLAKY") - } - assert := assert.New(t) - - key, err := crypto.GenerateKey() - assert.NoError(err) - - addr := crypto.PubkeyToAddress(key.PublicKey) - - genesisJSON, err := fundAddressByGenesis([]common.Address{addr}) - assert.NoError(err) - - _, vm, _, sender := GenesisVM(t, true, genesisJSON, "", "") - defer func() { - err := vm.Shutdown(context.Background()) - assert.NoError(err) - }() - vm.txPool.SetGasPrice(common.Big1) - vm.txPool.SetMinFee(common.Big0) - - // create eth txes - ethTxs := getValidEthTxs(key, 100, common.Big1) - - var wg sync.WaitGroup - wg.Add(2) - sender.CantSendAppGossip = false - seen := map[common.Hash]struct{}{} - sender.SendAppGossipF = func(_ context.Context, gossipedBytes []byte) error { - notifyMsgIntf, err := message.ParseGossipMessage(vm.networkCodec, gossipedBytes) - assert.NoError(err) - - requestMsg, ok := notifyMsgIntf.(message.EthTxsGossip) - assert.True(ok) - assert.NotEmpty(requestMsg.Txs) - - txs := make([]*types.Transaction, 0) - assert.NoError(rlp.DecodeBytes(requestMsg.Txs, &txs)) - for _, tx := range txs { - seen[tx.Hash()] = struct{}{} - } - wg.Done() - return nil - } - - // Notify VM about eth txs - errs := vm.txPool.AddRemotesSync(ethTxs) - for _, err := range errs { - assert.NoError(err, "failed adding subnet-evm tx to mempool") - } - - attemptAwait(t, &wg, 5*time.Second) - - for _, tx := range ethTxs { - _, ok := seen[tx.Hash()] - assert.True(ok, "missing hash: %v", tx.Hash()) - } -} - // show that a geth tx discovered from gossip is requested to the same node that // gossiped it func TestMempoolEthTxsAppGossipHandling(t *testing.T) { @@ -258,7 +105,7 @@ func TestMempoolEthTxsAppGossipHandling(t *testing.T) { return nil } wg.Add(1) - sender.SendAppGossipF = func(context.Context, []byte) error { + sender.SendAppGossipF = func(context.Context, []byte, int, int, int) error { wg.Done() return nil } @@ -283,162 +130,3 @@ func TestMempoolEthTxsAppGossipHandling(t *testing.T) { // wait for transaction to be re-gossiped attemptAwait(t, &wg, 5*time.Second) } - -func TestMempoolEthTxsRegossipSingleAccount(t *testing.T) { - assert := assert.New(t) - - key, err := crypto.GenerateKey() - assert.NoError(err) - - addr := crypto.PubkeyToAddress(key.PublicKey) - - genesisJSON, err := fundAddressByGenesis([]common.Address{addr}) - assert.NoError(err) - - _, vm, _, _ := GenesisVM(t, true, genesisJSON, `{"local-txs-enabled":true}`, "") - defer func() { - err := vm.Shutdown(context.Background()) - assert.NoError(err) - }() - vm.txPool.SetGasPrice(common.Big1) - vm.txPool.SetMinFee(common.Big0) - - // create eth txes - ethTxs := getValidEthTxs(key, 10, big.NewInt(226*params.GWei)) - - // Notify VM about eth txs - errs := vm.txPool.AddRemotesSync(ethTxs) - for _, err := range errs { - assert.NoError(err, "failed adding subnet-evm tx to remote mempool") - } - - // Only 1 transaction will be regossiped for an address (should be lowest - // nonce) - pushNetwork := vm.gossiper.(*pushGossiper) - queued := pushNetwork.queueRegossipTxs() - assert.Len(queued, 1, "unexpected length of queued txs") - assert.Equal(ethTxs[0].Hash(), queued[0].Hash()) -} - -func TestMempoolEthTxsRegossip(t *testing.T) { - assert := assert.New(t) - - keys := make([]*ecdsa.PrivateKey, 20) - addrs := make([]common.Address, 20) - for i := 0; i < 20; i++ { - key, err := crypto.GenerateKey() - assert.NoError(err) - keys[i] = key - addrs[i] = crypto.PubkeyToAddress(key.PublicKey) - } - - genesisJSON, err := fundAddressByGenesis(addrs) - assert.NoError(err) - - _, vm, _, _ := GenesisVM(t, true, genesisJSON, `{"local-txs-enabled":true}`, "") - defer func() { - err := vm.Shutdown(context.Background()) - assert.NoError(err) - }() - vm.txPool.SetGasPrice(common.Big1) - vm.txPool.SetMinFee(common.Big0) - - // create eth txes - ethTxs := make([]*types.Transaction, 20) - ethTxHashes := make([]common.Hash, 20) - for i := 0; i < 20; i++ { - txs := getValidEthTxs(keys[i], 1, big.NewInt(226*params.GWei)) - tx := txs[0] - ethTxs[i] = tx - ethTxHashes[i] = tx.Hash() - } - - // Notify VM about eth txs - errs := vm.txPool.AddRemotesSync(ethTxs[:10]) - for _, err := range errs { - assert.NoError(err, "failed adding subnet-evm tx to remote mempool") - } - errs = vm.txPool.AddLocals(ethTxs[10:]) - for _, err := range errs { - assert.NoError(err, "failed adding subnet-evm tx to local mempool") - } - - // We expect 16 transactions (the default max number of transactions to - // regossip) comprised of 10 local txs and 5 remote txs (we prioritize local - // txs over remote). - pushNetwork := vm.gossiper.(*pushGossiper) - queued := pushNetwork.queueRegossipTxs() - assert.Len(queued, 16, "unexpected length of queued txs") - - // Confirm queued transactions (should be ordered based on - // timestamp submitted, with local priorized over remote) - queuedTxHashes := make([]common.Hash, 16) - for i, tx := range queued { - queuedTxHashes[i] = tx.Hash() - } - assert.ElementsMatch(queuedTxHashes[:10], ethTxHashes[10:], "missing local transactions") - - // NOTE: We don't care which remote transactions are included in this test - // (due to the non-deterministic way pending transactions are surfaced, this can be difficult - // to assert as well). -} - -func TestMempoolTxsPriorityRegossip(t *testing.T) { - assert := assert.New(t) - - key, err := crypto.GenerateKey() - assert.NoError(err) - addr := crypto.PubkeyToAddress(key.PublicKey) - - key2, err := crypto.GenerateKey() - assert.NoError(err) - addr2 := crypto.PubkeyToAddress(key2.PublicKey) - - cfgJson, err := fundAddressByGenesis([]common.Address{addr, addr2}) - assert.NoError(err) - - cfg := fmt.Sprintf(`{"local-txs-enabled":true,"priority-regossip-addresses":["%s"]}`, addr) - _, vm, _, _ := GenesisVM(t, true, cfgJson, cfg, "") - defer func() { - err := vm.Shutdown(context.Background()) - assert.NoError(err) - }() - vm.txPool.SetGasPrice(common.Big1) - vm.txPool.SetMinFee(common.Big0) - - // create eth txes - txs := getValidEthTxs(key, 10, big.NewInt(226*params.GWei)) - txs2 := getValidEthTxs(key2, 10, big.NewInt(226*params.GWei)) - - // Notify VM about eth txs - for _, err := range vm.txPool.AddRemotesSync(txs) { - assert.NoError(err, "failed adding subnet-evm tx to remote mempool") - } - for _, err := range vm.txPool.AddRemotesSync(txs2) { - assert.NoError(err, "failed adding subnet-evm tx 2 to remote mempool") - } - - // 10 transactions will be regossiped for a priority address (others ignored) - pushNetwork := vm.gossiper.(*pushGossiper) - queued := pushNetwork.queuePriorityRegossipTxs() - assert.Len(queued, 10, "unexpected length of queued txs") - assert.ElementsMatch(txs, queued) -} - -func attemptAwait(t *testing.T, wg *sync.WaitGroup, delay time.Duration) { - ticker := make(chan struct{}) - - // Wait for [wg] and then close [ticket] to indicate that - // the wait group has finished. - go func() { - wg.Wait() - close(ticker) - }() - - select { - case <-time.After(delay): - t.Fatal("Timed out waiting for wait group to complete") - case <-ticker: - // The wait group completed without issue - } -} diff --git a/plugin/evm/handler.go b/plugin/evm/handler.go new file mode 100644 index 0000000000..2915d422a2 --- /dev/null +++ b/plugin/evm/handler.go @@ -0,0 +1,76 @@ +// (c) 2019-2021, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package evm + +import ( + "github.com/ava-labs/avalanchego/ids" + + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rlp" + + "github.com/ava-labs/subnet-evm/core/txpool" + "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/subnet-evm/plugin/evm/message" +) + +// GossipHandler handles incoming gossip messages +type GossipHandler struct { + vm *VM + txPool *txpool.TxPool + stats GossipStats +} + +func NewGossipHandler(vm *VM, stats GossipStats) *GossipHandler { + return &GossipHandler{ + vm: vm, + txPool: vm.txPool, + stats: stats, + } +} + +func (h *GossipHandler) HandleEthTxs(nodeID ids.NodeID, msg message.EthTxsGossip) error { + log.Trace( + "AppGossip called with EthTxsGossip", + "peerID", nodeID, + "size(txs)", len(msg.Txs), + ) + + if len(msg.Txs) == 0 { + log.Trace( + "AppGossip received empty EthTxsGossip Message", + "peerID", nodeID, + ) + return nil + } + + // The maximum size of this encoded object is enforced by the codec. + txs := make([]*types.Transaction, 0) + if err := rlp.DecodeBytes(msg.Txs, &txs); err != nil { + log.Trace( + "AppGossip provided invalid txs", + "peerID", nodeID, + "err", err, + ) + return nil + } + h.stats.IncEthTxsGossipReceived() + errs := h.txPool.AddRemotes(txs) + for i, err := range errs { + if err != nil { + log.Trace( + "AppGossip failed to add to mempool", + "err", err, + "tx", txs[i].Hash(), + ) + if err == txpool.ErrAlreadyKnown { + h.stats.IncEthTxsGossipReceivedKnown() + } else { + h.stats.IncEthTxsGossipReceivedError() + } + continue + } + h.stats.IncEthTxsGossipReceivedNew() + } + return nil +} diff --git a/plugin/evm/syncervm_test.go b/plugin/evm/syncervm_test.go index 69a15ca49d..8b3e0b6fa9 100644 --- a/plugin/evm/syncervm_test.go +++ b/plugin/evm/syncervm_test.go @@ -113,7 +113,7 @@ func TestStateSyncToggleEnabledToDisabled(t *testing.T) { syncDisabledVM := &VM{} appSender := &commonEng.SenderTest{T: t} - appSender.SendAppGossipF = func(context.Context, []byte) error { return nil } + appSender.SendAppGossipF = func(context.Context, []byte, int, int, int) error { return nil } appSender.SendAppRequestF = func(ctx context.Context, nodeSet set.Set[ids.NodeID], requestID uint32, request []byte) error { nodeID, hasItem := nodeSet.Pop() if !hasItem { diff --git a/plugin/evm/tx_gossip_test.go b/plugin/evm/tx_gossip_test.go index 54257b4bb2..fc9355ed84 100644 --- a/plugin/evm/tx_gossip_test.go +++ b/plugin/evm/tx_gossip_test.go @@ -170,6 +170,10 @@ func TestEthTxPushGossipOutbound(t *testing.T) { )) require.NoError(vm.SetState(ctx, snow.NormalOp)) + defer func() { + require.NoError(vm.Shutdown(ctx)) + }() + address := testEthAddrs[0] key := testKeys[0] tx := types.NewTransaction(0, address, big.NewInt(10), 21000, big.NewInt(testMinGasPrice), nil) @@ -178,6 +182,7 @@ func TestEthTxPushGossipOutbound(t *testing.T) { // issue a tx require.NoError(vm.txPool.AddLocal(signedTx)) + vm.ethTxPushGossiper.Get().Add(&GossipEthTx{signedTx}) sent := <-sender.SentAppGossip got := &sdk.PushGossip{} @@ -200,9 +205,7 @@ func TestEthTxPushGossipInbound(t *testing.T) { ctx := context.Background() snowCtx := utils.TestSnowContext() - sender := &common.FakeSender{ - SentAppGossip: make(chan []byte, 1), - } + sender := &common.SenderTest{} vm := &VM{ p2pSender: sender, ethTxPullGossiper: gossip.NoOpGossiper{}, @@ -221,6 +224,10 @@ func TestEthTxPushGossipInbound(t *testing.T) { )) require.NoError(vm.SetState(ctx, snow.NormalOp)) + defer func() { + require.NoError(vm.Shutdown(ctx)) + }() + address := testEthAddrs[0] key := testKeys[0] tx := types.NewTransaction(0, address, big.NewInt(10), 21000, big.NewInt(testMinGasPrice), nil) @@ -244,15 +251,5 @@ func TestEthTxPushGossipInbound(t *testing.T) { inboundGossipMsg := append(binary.AppendUvarint(nil, ethTxGossipProtocol), inboundGossipBytes...) require.NoError(vm.AppGossip(ctx, ids.EmptyNodeID, inboundGossipMsg)) - forwardedMsg := &sdk.PushGossip{} - outboundGossipBytes := <-sender.SentAppGossip - - require.Equal(byte(ethTxGossipProtocol), outboundGossipBytes[0]) - require.NoError(proto.Unmarshal(outboundGossipBytes[1:], forwardedMsg)) - require.Len(forwardedMsg.Gossip, 1) - - forwardedTx, err := marshaller.UnmarshalGossip(forwardedMsg.Gossip[0]) - require.NoError(err) - require.Equal(gossipedTx.GossipID(), forwardedTx.GossipID()) require.True(vm.txPool.Has(signedTx.Hash())) } diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go index 0626cad8ca..37c4aa764e 100644 --- a/plugin/evm/vm.go +++ b/plugin/evm/vm.go @@ -81,6 +81,7 @@ import ( commonEng "github.com/ava-labs/avalanchego/snow/engine/common" + avalancheUtils "github.com/ava-labs/avalanchego/utils" avalancheJSON "github.com/ava-labs/avalanchego/utils/json" ) @@ -109,6 +110,7 @@ const ( ethTxGossipProtocol = 0x0 // gossip constants + pushGossipDiscardedElements = 16_384 txGossipBloomMinTargetElements = 8 * 1024 txGossipBloomTargetFalsePositiveRate = 0.01 txGossipBloomResetFalsePositiveRate = 0.05 @@ -117,8 +119,7 @@ const ( maxValidatorSetStaleness = time.Minute txGossipThrottlingPeriod = 10 * time.Second txGossipThrottlingLimit = 2 - gossipFrequency = 10 * time.Second - txGossipPollSize = 10 + txGossipPollSize = 1 ) // Define the API endpoints for the VM @@ -213,8 +214,6 @@ type VM struct { builder *blockBuilder - gossiper Gossiper - clock mockable.Clock shutdownChan chan struct{} @@ -247,8 +246,8 @@ type VM struct { // Initialize only sets these if nil so they can be overridden in tests p2pSender commonEng.AppSender ethTxGossipHandler p2p.Handler + ethTxPushGossiper avalancheUtils.Atomic[*gossip.PushGossiper[*GossipEthTx]] ethTxPullGossiper gossip.Gossiper - ethTxPushGossiper gossip.Accumulator[*GossipEthTx] } // Initialize implements the snowman.ChainVM interface @@ -390,14 +389,13 @@ func (vm *VM) Initialize( vm.ethConfig.TxPool.Locals = vm.config.PriorityRegossipAddresses vm.ethConfig.TxPool.NoLocals = !vm.config.LocalTxsEnabled - vm.ethConfig.TxPool.Journal = vm.config.TxPoolJournal - vm.ethConfig.TxPool.Rejournal = vm.config.TxPoolRejournal.Duration vm.ethConfig.TxPool.PriceLimit = vm.config.TxPoolPriceLimit vm.ethConfig.TxPool.PriceBump = vm.config.TxPoolPriceBump vm.ethConfig.TxPool.AccountSlots = vm.config.TxPoolAccountSlots vm.ethConfig.TxPool.GlobalSlots = vm.config.TxPoolGlobalSlots vm.ethConfig.TxPool.AccountQueue = vm.config.TxPoolAccountQueue vm.ethConfig.TxPool.GlobalQueue = vm.config.TxPoolGlobalQueue + vm.ethConfig.TxPool.Lifetime = vm.config.TxPoolLifetime.Duration vm.ethConfig.AllowUnfinalizedQueries = vm.config.AllowUnfinalizedQueries vm.ethConfig.AllowUnprotectedTxs = vm.config.AllowUnprotectedTxs @@ -536,6 +534,7 @@ func (vm *VM) initializeChain(lastAcceptedHash common.Hash, ethConfig ethconfig. vm.eth, err = eth.New( node, &vm.ethConfig, + &EthPushGossiper{vm: vm}, vm.chaindb, vm.config.EthBackendSettings(), lastAcceptedHash, @@ -674,40 +673,55 @@ func (vm *VM) initBlockBuilding() error { vm.cancel = cancel ethTxGossipMarshaller := GossipEthTxMarshaller{} - ethTxGossipClient := vm.Network.NewClient(ethTxGossipProtocol, p2p.WithValidatorSampling(vm.validators)) - ethTxGossipMetrics, err := gossip.NewMetrics(vm.sdkMetrics, ethTxGossipNamespace) if err != nil { return fmt.Errorf("failed to initialize eth tx gossip metrics: %w", err) } + ethTxPool, err := NewGossipEthTxPool(vm.txPool, vm.sdkMetrics) + if err != nil { + return err + } + vm.shutdownWg.Add(1) + go func() { + ethTxPool.Subscribe(ctx) + vm.shutdownWg.Done() + }() + + pushGossipParams := gossip.BranchingFactor{ + Validators: vm.config.PushGossipNumValidators, + Peers: vm.config.PushGossipNumPeers, + } + pushRegossipParams := gossip.BranchingFactor{ + Validators: vm.config.PushRegossipNumValidators, + Peers: vm.config.PushRegossipNumPeers, + } - if vm.ethTxPushGossiper == nil { - vm.ethTxPushGossiper = gossip.NewPushGossiper[*GossipEthTx]( + ethTxPushGossiper := vm.ethTxPushGossiper.Get() + if ethTxPushGossiper == nil { + ethTxPushGossiper, err = gossip.NewPushGossiper[*GossipEthTx]( ethTxGossipMarshaller, + ethTxPool, ethTxGossipClient, ethTxGossipMetrics, + pushGossipParams, + pushRegossipParams, + pushGossipDiscardedElements, txGossipTargetMessageSize, + vm.config.RegossipFrequency.Duration, ) + if err != nil { + return fmt.Errorf("failed to initialize eth tx push gossiper: %w", err) + } + vm.ethTxPushGossiper.Set(ethTxPushGossiper) } // NOTE: gossip network must be initialized first otherwise ETH tx gossip will not work. gossipStats := NewGossipStats() - vm.gossiper = vm.createGossiper(gossipStats, vm.ethTxPushGossiper) vm.builder = vm.NewBlockBuilder(vm.toEngine) vm.builder.awaitSubmittedTxs() vm.Network.SetGossipHandler(NewGossipHandler(vm, gossipStats)) - ethTxPool, err := NewGossipEthTxPool(vm.txPool, vm.sdkMetrics) - if err != nil { - return err - } - vm.shutdownWg.Add(1) - go func() { - ethTxPool.Subscribe(ctx) - vm.shutdownWg.Done() - }() - if vm.ethTxGossipHandler == nil { vm.ethTxGossipHandler = newTxGossipHandler[*GossipEthTx]( vm.ctx.Log, @@ -742,9 +756,13 @@ func (vm *VM) initBlockBuilding() error { } } - vm.shutdownWg.Add(1) + vm.shutdownWg.Add(2) + go func() { + gossip.Every(ctx, vm.ctx.Log, ethTxPushGossiper, vm.config.PushGossipFrequency.Duration) + vm.shutdownWg.Done() + }() go func() { - gossip.Every(ctx, vm.ctx.Log, vm.ethTxPullGossiper, gossipFrequency) + gossip.Every(ctx, vm.ctx.Log, vm.ethTxPullGossiper, vm.config.PullGossipFrequency.Duration) vm.shutdownWg.Done() }() diff --git a/plugin/evm/vm_test.go b/plugin/evm/vm_test.go index 09f962a258..ea96cc7689 100644 --- a/plugin/evm/vm_test.go +++ b/plugin/evm/vm_test.go @@ -208,7 +208,7 @@ func GenesisVM(t *testing.T, ctx, dbManager, genesisBytes, issuer, _ := setupGenesis(t, genesisJSON) appSender := &commonEng.SenderTest{T: t} appSender.CantSendAppGossip = true - appSender.SendAppGossipF = func(context.Context, []byte) error { return nil } + appSender.SendAppGossipF = func(context.Context, []byte, int, int, int) error { return nil } err := vm.Initialize( context.Background(), ctx, @@ -1994,7 +1994,7 @@ func TestConfigureLogLevel(t *testing.T) { ctx, dbManager, genesisBytes, issuer, _ := setupGenesis(t, test.genesisJSON) appSender := &commonEng.SenderTest{T: t} appSender.CantSendAppGossip = true - appSender.SendAppGossipF = func(context.Context, []byte) error { return nil } + appSender.SendAppGossipF = func(context.Context, []byte, int, int, int) error { return nil } err := vm.Initialize( context.Background(), ctx, diff --git a/precompile/contracts/warp/README.md b/precompile/contracts/warp/README.md index dd4170690f..10e1daaa38 100644 --- a/precompile/contracts/warp/README.md +++ b/precompile/contracts/warp/README.md @@ -1,18 +1,16 @@ -# Avalanche Warp Messaging +# Integrating Avalanche Warp Messaging into the EVM Avalanche Warp Messaging offers a basic primitive to enable Cross-Subnet communication on the Avalanche Network. It is intended to allow communication between arbitrary Custom Virtual Machines (including, but not limited to Subnet-EVM and Coreth). -## How does Avalanche Warp Messaging Work +## How does Avalanche Warp Messaging Work? Avalanche Warp Messaging uses BLS Multi-Signatures with Public-Key Aggregation where every Avalanche validator registers a public key alongside its NodeID on the Avalanche P-Chain. Every node tracking a Subnet has read access to the Avalanche P-Chain. This provides weighted sets of BLS Public Keys that correspond to the validator sets of each Subnet on the Avalanche Network. Avalanche Warp Messaging provides a basic primitive for signing and verifying messages between Subnets: the receiving network can verify whether an aggregation of signatures from a set of source Subnet validators represents a threshold of stake large enough for the receiving network to process the message. -For more details on Avalanche Warp Messaging, see the AvalancheGo [Warp README](https://github.com/ava-labs/avalanchego/blob/warp-readme/vms/platformvm/warp/README.md). - -## Integrating Avalanche Warp Messaging into the EVM +For more details on Avalanche Warp Messaging, see the AvalancheGo [Warp README](https://docs.avax.network/build/cross-chain/awm/deep-dive). ### Flow of Sending / Receiving a Warp Message within the EVM @@ -46,7 +44,7 @@ Additionally, the `SourceChainID` is excluded because anyone parsing the chain c - `sender` - The `messageID` of the unsigned message (sha256 of the unsigned message) -The actual `message` is the entire [Avalanche Warp Unsigned Message](https://github.com/ava-labs/avalanchego/blob/master/vms/platformvm/warp/unsigned_message.go#L14) including an [AddressedCall](https://github.com/ava-labs/avalanchego/tree/v1.10.15/vms/platformvm/warp/payload). The unsigned message is emitted as the unindexed data in the log. +The actual `message` is the entire [Avalanche Warp Unsigned Message](https://github.com/ava-labs/avalanchego/blob/master/vms/platformvm/warp/unsigned_message.go#L14) including an [AddressedCall](https://github.com/ava-labs/avalanchego/tree/master/vms/platformvm/warp/payload#readme). The unsigned message is emitted as the unindexed data in the log. #### getVerifiedMessage @@ -73,11 +71,11 @@ The `blockchainID` in Avalanche refers to the txID that created the blockchain o ### Predicate Encoding -Avalanche Warp Messages are encoded as a signed Avalanche [Warp Message](https://github.com/ava-labs/avalanchego/blob/v1.10.4/vms/platformvm/warp/message.go#L7) where the [UnsignedMessage](https://github.com/ava-labs/avalanchego/blob/v1.10.4/vms/platformvm/warp/unsigned_message.go#L14)'s payload includes an [AddressedPayload](../../../warp/payload/payload.go). +Avalanche Warp Messages are encoded as a signed Avalanche [Warp Message](https://github.com/ava-labs/avalanchego/blob/master/vms/platformvm/warp/message.go) where the [UnsignedMessage](https://github.com/ava-labs/avalanchego/blob/master/vms/platformvm/warp/unsigned_message.go)'s payload includes an [AddressedPayload](https://github.com/ava-labs/avalanchego/blob/master/vms/platformvm/warp/payload/payload.go). Since the predicate is encoded into the [Transaction Access List](https://eips.ethereum.org/EIPS/eip-2930), it is packed into 32 byte hashes intended to declare storage slots that should be pre-warmed into the cache prior to transaction execution. -Therefore, we use the [Predicate Utils](../../../utils/predicate/README.md) package to encode the actual byte slice of size N into the access list. +Therefore, we use the [Predicate Utils](https://github.com/ava-labs/coreth/blob/master/predicate/Predicate.md) package to encode the actual byte slice of size N into the access list. ### Performance Optimization: C-Chain to Subnet diff --git a/precompile/contracts/warp/config.go b/precompile/contracts/warp/config.go index 5275671e6a..dde04a8695 100644 --- a/precompile/contracts/warp/config.go +++ b/precompile/contracts/warp/config.go @@ -116,7 +116,7 @@ func (c *Config) Accept(acceptCtx *precompileconfig.AcceptContext, blockHash com if err != nil { return fmt.Errorf("failed to parse warp log data into unsigned message (TxHash: %s, LogIndex: %d): %w", txHash, logIndex, err) } - log.Info( + log.Debug( "Accepted warp unsigned message", "blockHash", blockHash, "blockNumber", blockNumber, diff --git a/scripts/versions.sh b/scripts/versions.sh index 573a83dd3a..0754f0451b 100644 --- a/scripts/versions.sh +++ b/scripts/versions.sh @@ -4,8 +4,8 @@ # shellcheck disable=SC2034 # Don't export them as they're used in the context of other calls -AVALANCHE_VERSION=${AVALANCHE_VERSION:-'v1.11.1'} +AVALANCHE_VERSION=${AVALANCHE_VERSION:-'v1.11.2'} GINKGO_VERSION=${GINKGO_VERSION:-'v2.2.0'} # This won't be used, but it's here to make code syncs easier -LATEST_CORETH_VERSION='0.12.11-rc.3' +LATEST_CORETH_VERSION='0.13.1-rc.5'