From 0dfb72e170fd0e52dc3ba6708934592ec1c506f7 Mon Sep 17 00:00:00 2001 From: Masanori Yoshida Date: Fri, 20 Dec 2024 20:21:08 +0900 Subject: [PATCH 1/6] add the txpool package Signed-off-by: Masanori Yoshida --- go.mod | 11 ++ go.sum | 4 +- pkg/client/txpool/txpool.go | 100 +++++++++++++++++ pkg/client/txpool/txpool_test.go | 184 +++++++++++++++++++++++++++++++ 4 files changed, 296 insertions(+), 3 deletions(-) create mode 100644 pkg/client/txpool/txpool.go create mode 100644 pkg/client/txpool/txpool_test.go diff --git a/go.mod b/go.mod index 8350319..b3b46ef 100644 --- a/go.mod +++ b/go.mod @@ -67,6 +67,7 @@ require ( github.com/cosmos/ibc-go/modules/capability v1.0.0 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c // indirect github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect github.com/danieljoos/wincred v1.1.2 // indirect @@ -96,6 +97,7 @@ require ( github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt/v4 v4.5.1 // indirect github.com/golang/glog v1.2.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.6.0 // indirect @@ -114,6 +116,7 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/hashicorp/go-bexpr v0.1.10 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-getter v1.7.1 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect @@ -126,12 +129,15 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.1.0 // indirect + github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/holiman/uint256 v1.3.1 // indirect github.com/huandu/skiplist v1.2.0 // indirect + github.com/huin/goupnp v1.3.0 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/improbable-eng/grpc-web v0.15.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/klauspost/compress v1.17.9 // indirect @@ -149,6 +155,7 @@ require ( github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mitchellh/pointerstructure v1.2.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect @@ -168,6 +175,7 @@ require ( github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/rs/cors v1.8.3 // indirect github.com/rs/zerolog v1.32.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect @@ -184,6 +192,8 @@ require ( github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/ulikunitz/xz v0.5.11 // indirect + github.com/urfave/cli/v2 v2.25.7 // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/zondax/hid v0.9.2 // indirect github.com/zondax/ledger-go v0.14.3 // indirect go.etcd.io/bbolt v1.3.8 // indirect @@ -214,6 +224,7 @@ require ( google.golang.org/grpc v1.62.0 // indirect google.golang.org/protobuf v1.35.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect diff --git a/go.sum b/go.sum index 5c4cccb..4b6eff4 100644 --- a/go.sum +++ b/go.sum @@ -385,7 +385,6 @@ github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZD github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= -github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= @@ -859,6 +858,7 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4 github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= @@ -1007,7 +1007,6 @@ github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= -github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -1105,7 +1104,6 @@ github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0o github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= diff --git a/pkg/client/txpool/txpool.go b/pkg/client/txpool/txpool.go new file mode 100644 index 0000000..d219aa7 --- /dev/null +++ b/pkg/client/txpool/txpool.go @@ -0,0 +1,100 @@ +package txpool + +import ( + "context" + "math/big" + "slices" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" +) + +// RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction +type RPCTransaction struct { + BlockHash *common.Hash `json:"blockHash"` + BlockNumber *hexutil.Big `json:"blockNumber"` + From common.Address `json:"from"` + Gas hexutil.Uint64 `json:"gas"` + GasPrice *hexutil.Big `json:"gasPrice"` + GasFeeCap *hexutil.Big `json:"maxFeePerGas,omitempty"` + GasTipCap *hexutil.Big `json:"maxPriorityFeePerGas,omitempty"` + MaxFeePerBlobGas *hexutil.Big `json:"maxFeePerBlobGas,omitempty"` + Hash common.Hash `json:"hash"` + Input hexutil.Bytes `json:"input"` + Nonce hexutil.Uint64 `json:"nonce"` + To *common.Address `json:"to"` + TransactionIndex *hexutil.Uint64 `json:"transactionIndex"` + Value *hexutil.Big `json:"value"` + Type hexutil.Uint64 `json:"type"` + Accesses *types.AccessList `json:"accessList,omitempty"` + ChainID *hexutil.Big `json:"chainId,omitempty"` + BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"` + V *hexutil.Big `json:"v"` + R *hexutil.Big `json:"r"` + S *hexutil.Big `json:"s"` + YParity *hexutil.Uint64 `json:"yParity,omitempty"` +} + +// ContentFrom calls `txpool_contentFrom` of the Ethereum RPC +func ContentFrom(ctx context.Context, client *ethclient.Client, address common.Address) (map[string]map[string]*RPCTransaction, error) { + var res map[string]map[string]*RPCTransaction + if err := client.Client().CallContext(ctx, &res, "txpool_contentFrom", address); err != nil { + return nil, err + } + return res, nil +} + +// PendingTransactions returns pending txs sent from `address` sorted by nonce. +func PendingTransactions(ctx context.Context, client *ethclient.Client, address common.Address) ([]*RPCTransaction, error) { + txs, err := ContentFrom(ctx, client, address) + if err != nil { + return nil, err + } + + pendingTxMap, found := txs["pending"] + if !found { + return nil, nil + } + + var pendingTxs []*RPCTransaction + for _, pendingTx := range pendingTxMap { + pendingTxs = append(pendingTxs, pendingTx) + } + + slices.SortFunc(pendingTxs, func(a, b *RPCTransaction) int { + if a.Nonce < b.Nonce { + return -1 + } else if a.Nonce > b.Nonce { + return 1 + } else { + return 0 + } + }) + + return pendingTxs, nil +} + +func inclByPercent(n *big.Int, percent uint64) { + n.Mul(n, big.NewInt(int64(100+percent))) + n.Div(n, big.NewInt(100)) +} + +// GetMinimumRequiredFee returns the minimum fee required to successfully send a transaction +func GetMinimumRequiredFee(ctx context.Context, client *ethclient.Client, address common.Address, priceBump uint64) (*big.Int, *big.Int, error) { + pendingTxs, err := PendingTransactions(ctx, client, address) + if err != nil { + return nil, nil, err + } else if len(pendingTxs) == 0 { + return common.Big0, common.Big0, nil + } + + gasFeeCap := pendingTxs[0].GasFeeCap.ToInt() + gasTipCap := pendingTxs[0].GasTipCap.ToInt() + + inclByPercent(gasFeeCap, priceBump) + inclByPercent(gasTipCap, priceBump) + + return gasFeeCap, gasTipCap, nil +} diff --git a/pkg/client/txpool/txpool_test.go b/pkg/client/txpool/txpool_test.go new file mode 100644 index 0000000..b645890 --- /dev/null +++ b/pkg/client/txpool/txpool_test.go @@ -0,0 +1,184 @@ +package txpool + +import ( + "context" + "crypto/ecdsa" + "math/big" + "testing" + "unsafe" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/ethclient/simulated" + "github.com/ethereum/go-ethereum/node" +) + +type account struct { + key *ecdsa.PrivateKey + addr common.Address +} + +func makeGenesisAlloc(t *testing.T, n int) ([]common.Address, types.GenesisAlloc) { + var addrs []common.Address + alloc := make(types.GenesisAlloc) + for i := 0; i < n; i++ { + key, err := crypto.GenerateKey() + if err != nil { + t.Fatalf("failed to generate a private key: err=%v", err) + } + + addr := crypto.PubkeyToAddress(key.PublicKey) + + addrs = append(addrs, addr) + alloc[addr] = types.Account{ + Balance: new(big.Int).Lsh(common.Big1, 250), + PrivateKey: crypto.FromECDSA(key), + } + } + return addrs, alloc +} + +func getPrivateKey(t *testing.T, account types.Account) *ecdsa.PrivateKey { + key, err := crypto.ToECDSA(account.PrivateKey) + if err != nil { + t.Fatalf("failed to unmarshal the private key: err=%v", err) + } + return key +} + +func getEthClient(sim *simulated.Backend) *ethclient.Client { + type simClient struct { + *ethclient.Client + } + ifceCli := sim.Client() + ptrCli := unsafe.Add(unsafe.Pointer(&ifceCli), unsafe.Sizeof(uintptr(0))) + return (*simClient)(ptrCli).Client +} + +func transfer(t *testing.T, ctx context.Context, client *ethclient.Client, signer types.Signer, key *ecdsa.PrivateKey, nonce uint64, gasTipCap, gasFeeCap *big.Int, to common.Address, amount *big.Int) { + tx := types.NewTx(&types.DynamicFeeTx{ + Nonce: nonce, + GasTipCap: gasTipCap, + GasFeeCap: gasFeeCap, + Gas: 21000, + To: &to, + Value: amount, + }) + + tx, err := types.SignTx(tx, signer, key) + if err != nil { + t.Fatalf("failed to sign tx: err=%v", err) + } + + if err := client.SendTransaction(ctx, tx); err != nil { + t.Fatalf("failed to send tx: err=%v", err) + } +} + +func replace(t *testing.T, ctx context.Context, client *ethclient.Client, signer types.Signer, key *ecdsa.PrivateKey, priceBump uint64, nonce uint64, gasTipCap, gasFeeCap *big.Int, to common.Address, amount *big.Int) { + addr := crypto.PubkeyToAddress(key.PublicKey) + + if minFeeCap, minTipCap, err := GetMinimumRequiredFee(ctx, client, addr, priceBump); err != nil { + t.Fatalf("failed to get the minimum fee required to replace tx: err=%v", err) + } else if minFeeCap.Cmp(common.Big0) == 0 { + t.Fatalf("tx to replace not found") + } else { + t.Logf("minimum required fees: feeCap=%v, tipCap=%v", minFeeCap, minTipCap) + if gasFeeCap.Cmp(minFeeCap) < 0 { + t.Logf("gasFeeCap updated: %v => %v", gasFeeCap, minFeeCap) + gasFeeCap = minFeeCap + } + if gasTipCap.Cmp(minTipCap) < 0 { + t.Logf("gasTipCap updated: %v => %v", gasTipCap, minTipCap) + gasTipCap = minTipCap + } + } + + transfer(t, ctx, client, signer, key, nonce, gasTipCap, gasFeeCap, to, amount) +} + +func TestContentFrom(t *testing.T) { + ctx := context.Background() + + addrs, alloc := makeGenesisAlloc(t, 2) + sender, receiver := addrs[0], addrs[1] + senderKey := getPrivateKey(t, alloc[sender]) + + priceBump := uint64(25) + sim := simulated.NewBackend(alloc, func(nodeConf *node.Config, ethConf *ethconfig.Config) { + t.Logf("original price bump is %v", ethConf.TxPool.PriceBump) + ethConf.TxPool.PriceBump = priceBump + }) + defer sim.Close() + + cli := getEthClient(sim) + + // make signer + chainID, err := cli.ChainID(ctx) + if err != nil { + t.Fatalf("failed to get chain ID: err=%v", err) + } + signer := types.LatestSignerForChainID(chainID) + + // we use small fee cap to prepend txs from being included + feeCap := big.NewInt(1_000_000) + tipCap := big.NewInt(1_000_000) + amount := big.NewInt(1_000_000_000) // 1 GWei + + transfer(t, ctx, cli, signer, senderKey, 0, tipCap, feeCap, receiver, amount) + for i := 0; i < 10; i++ { + replace(t, ctx, cli, signer, senderKey, priceBump, 0, tipCap, feeCap, receiver, amount) + } + + // check block info + block, err := cli.BlockByNumber(ctx, nil) + if err != nil { + t.Fatalf("failed to get block by number: err=%v", err) + } else { + t.Logf("bn=%v, basefee=%v", block.Number(), block.BaseFee()) + } + + // commit block + sim.Commit() + + // check block info + block, err = cli.BlockByNumber(ctx, nil) + if err != nil { + t.Fatalf("failed to get block by number: err=%v", err) + } else { + t.Logf("bn=%v, basefee=%v", block.Number(), block.BaseFee()) + } + + // check that len(pendingTxs) == 1 + if pendingTxs, err := PendingTransactions(ctx, cli, sender); err != nil { + t.Fatalf("failed to get pending transactions: err=%v", err) + } else if len(pendingTxs) != 1 { + t.Fatalf("unexpected pending txs: pendingTxs=%v", pendingTxs) + } + + // update fee cap to allow the tx to be included + feeCap = block.BaseFee() + + replace(t, ctx, cli, signer, senderKey, priceBump, 0, tipCap, feeCap, receiver, amount) + + // commit block + sim.Commit() + + // check block info + block, err = cli.BlockByNumber(ctx, nil) + if err != nil { + t.Fatalf("failed to get block by number: err=%v", err) + } else { + t.Logf("bn=%v, basefee=%v", block.Number(), block.BaseFee()) + } + + // check that len(pendingTxs) == 0 + if pendingTxs, err := PendingTransactions(ctx, cli, sender); err != nil { + t.Fatalf("failed to get pending transactions: err=%v", err) + } else if len(pendingTxs) != 0 { + t.Fatalf("unexpected pending txs: pendingTxs=%v", pendingTxs) + } +} From 096c0263bd855a805d5c0b1b65f8a4d65f3c5586 Mon Sep 17 00:00:00 2001 From: Masanori Yoshida Date: Tue, 24 Dec 2024 09:58:49 +0900 Subject: [PATCH 2/6] fix gas calculation to take price bump into consideration Signed-off-by: Masanori Yoshida --- pkg/relay/ethereum/config.pb.go | 145 +++++++++++------- pkg/relay/ethereum/gas.go | 23 ++- .../chains/ethereum/config/config.proto | 2 + 3 files changed, 112 insertions(+), 58 deletions(-) diff --git a/pkg/relay/ethereum/config.pb.go b/pkg/relay/ethereum/config.pb.go index ac4dffe..8fe80b1 100644 --- a/pkg/relay/ethereum/config.pb.go +++ b/pkg/relay/ethereum/config.pb.go @@ -49,6 +49,7 @@ type ChainConfig struct { // Types that are valid to be assigned to XTxMaxSize: // *ChainConfig_TxMaxSize XTxMaxSize isChainConfig_XTxMaxSize `protobuf_oneof:"_tx_max_size"` + PriceBump uint64 `protobuf:"varint,20,opt,name=price_bump,json=priceBump,proto3" json:"price_bump,omitempty"` } func (m *ChainConfig) Reset() { *m = ChainConfig{} } @@ -248,66 +249,67 @@ func init() { } var fileDescriptor_a8a57ab2f9f14837 = []byte{ - // 938 bytes of a gzipped FileDescriptorProto + // 956 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x55, 0xcd, 0x6e, 0x1b, 0x37, 0x10, 0xb6, 0x62, 0xd7, 0x96, 0xa8, 0xd8, 0xb1, 0x19, 0xff, 0xac, 0xdd, 0x46, 0x15, 0xdc, 0x8b, 0x8a, 0xc6, 0x12, 0x10, 0xa3, 0x41, 0xd1, 0x9b, 0xad, 0xc4, 0x49, 0x0a, 0x07, 0x70, 0x37, 0x3e, - 0xf5, 0x42, 0x70, 0xb9, 0xa3, 0x15, 0x61, 0x2e, 0xb9, 0x25, 0x29, 0x47, 0x9b, 0x27, 0xe8, 0xb1, - 0x0f, 0xd0, 0x07, 0xca, 0x31, 0xa7, 0xa2, 0xc7, 0xd6, 0x7e, 0x91, 0x82, 0xb3, 0xfa, 0x33, 0x52, - 0x34, 0xc8, 0xc9, 0xe6, 0x7c, 0x3f, 0x33, 0x23, 0x0e, 0x67, 0xc9, 0x77, 0x16, 0x14, 0x2f, 0xc1, - 0xf6, 0xc4, 0x90, 0x4b, 0xed, 0x7a, 0xe0, 0x87, 0x60, 0x61, 0x94, 0xf7, 0x84, 0xd1, 0x03, 0x99, - 0x4d, 0xfe, 0x74, 0x0b, 0x6b, 0xbc, 0xa1, 0xad, 0x09, 0xb9, 0x5b, 0x91, 0xbb, 0x53, 0x72, 0xb7, - 0x62, 0x1d, 0x6c, 0x67, 0x26, 0x33, 0x48, 0xed, 0x85, 0xff, 0x2a, 0xd5, 0xc1, 0x7e, 0x66, 0x4c, - 0xa6, 0xa0, 0x87, 0xa7, 0x64, 0x34, 0xe8, 0x71, 0x5d, 0x56, 0xd0, 0xe1, 0x9f, 0x6b, 0xa4, 0xd9, - 0x0f, 0x5e, 0x7d, 0x34, 0xa0, 0xfb, 0xa4, 0x8e, 0xd6, 0x4c, 0xa6, 0x51, 0xad, 0x5d, 0xeb, 0x34, - 0xe2, 0x35, 0x3c, 0xbf, 0x4a, 0x69, 0x9b, 0xdc, 0x07, 0x3f, 0x64, 0x33, 0xf8, 0x5e, 0xbb, 0xd6, - 0x59, 0x89, 0x09, 0xf8, 0x61, 0x7f, 0xc2, 0xd8, 0x27, 0x75, 0x5b, 0x08, 0xc6, 0xd3, 0xd4, 0x46, - 0xcb, 0x95, 0xd8, 0x16, 0xe2, 0x24, 0x4d, 0x2d, 0x7d, 0x4c, 0x56, 0x9d, 0xcc, 0x34, 0xd8, 0x68, - 0xa5, 0x5d, 0xeb, 0x34, 0x9f, 0x6c, 0x77, 0xab, 0x9a, 0xba, 0xd3, 0x9a, 0xba, 0x27, 0xba, 0x8c, - 0x27, 0x1c, 0xfa, 0x35, 0x69, 0xca, 0xa4, 0x32, 0x02, 0xe7, 0xa2, 0x2f, 0xd0, 0x8b, 0xc8, 0x04, - 0xbd, 0xc0, 0x39, 0xfa, 0x94, 0xec, 0x49, 0x2d, 0xbd, 0xe4, 0x8a, 0x39, 0xd0, 0x29, 0x13, 0x43, - 0x10, 0x57, 0x85, 0x91, 0xda, 0x47, 0xab, 0x58, 0xd6, 0xce, 0x04, 0x7e, 0x03, 0x3a, 0xed, 0xcf, - 0xc0, 0x45, 0x9d, 0x05, 0x71, 0xbd, 0xa8, 0x5b, 0xbb, 0xa3, 0x8b, 0x41, 0x5c, 0x2f, 0xe8, 0x1e, - 0x13, 0x0a, 0x9a, 0x27, 0x0a, 0x58, 0x0a, 0xc9, 0x28, 0x63, 0xde, 0x72, 0x01, 0x51, 0xbd, 0x5d, - 0xeb, 0xd4, 0xe3, 0xcd, 0x0a, 0x79, 0x16, 0x80, 0xcb, 0x10, 0xa7, 0xdf, 0x93, 0x3d, 0x7e, 0x0d, - 0x96, 0x67, 0xc0, 0x12, 0x65, 0xc4, 0x15, 0xf3, 0x32, 0x07, 0x96, 0x3b, 0x10, 0x51, 0x03, 0xb3, - 0x6c, 0x4f, 0xe0, 0xd3, 0x80, 0x5e, 0xca, 0x1c, 0x5e, 0x3b, 0x10, 0x41, 0x96, 0xf3, 0x31, 0xb3, - 0xe0, 0x6d, 0xc9, 0x06, 0xc6, 0x32, 0xa9, 0x85, 0x1a, 0x39, 0x69, 0x74, 0x44, 0x2a, 0x59, 0xce, - 0xc7, 0x71, 0x40, 0xcf, 0x8c, 0x7d, 0x35, 0xc5, 0x68, 0x4a, 0x28, 0x57, 0xca, 0xbc, 0x65, 0x4a, - 0xb0, 0xc1, 0x48, 0x0b, 0x2f, 0x8d, 0x76, 0x51, 0x13, 0x7f, 0xe6, 0xa7, 0xdd, 0xff, 0x1f, 0x98, - 0xee, 0x49, 0x50, 0x9e, 0xf7, 0xcf, 0xa6, 0xba, 0x6a, 0x0c, 0xe2, 0x4d, 0x74, 0x3c, 0x17, 0xb3, - 0x38, 0xbd, 0x24, 0x5b, 0x19, 0x77, 0x0c, 0x9c, 0x97, 0x39, 0xf7, 0xc0, 0x2c, 0xf7, 0x10, 0xdd, - 0xc7, 0x24, 0x9d, 0x4f, 0x25, 0x39, 0xb3, 0x1c, 0x5d, 0xe2, 0x07, 0x19, 0x77, 0xcf, 0x27, 0x0e, - 0x31, 0xf7, 0x40, 0x0f, 0xc9, 0x7a, 0x68, 0x39, 0x38, 0x2b, 0x99, 0x4b, 0x1f, 0xad, 0x63, 0xa3, - 0xcd, 0x9c, 0x8f, 0x5f, 0x70, 0x77, 0x1e, 0x42, 0x74, 0x8f, 0xac, 0xf9, 0x31, 0xf3, 0x65, 0x01, - 0xd1, 0x06, 0x0e, 0xc2, 0xaa, 0x1f, 0x5f, 0x96, 0x05, 0x50, 0x20, 0x3b, 0x69, 0xa9, 0x79, 0x2e, - 0x05, 0xf3, 0x95, 0x47, 0x95, 0x2f, 0x7a, 0x80, 0x65, 0x3d, 0xf9, 0x54, 0x59, 0xcf, 0x2a, 0xf1, - 0x65, 0x48, 0x35, 0xe9, 0x9b, 0xa6, 0x1f, 0xc5, 0xe8, 0x31, 0xd9, 0xc5, 0x5b, 0x74, 0xac, 0x00, - 0xcb, 0xe0, 0x1a, 0xb4, 0x67, 0xbf, 0x8e, 0xc0, 0x96, 0xd1, 0x26, 0x16, 0xfb, 0xb0, 0x42, 0x2f, - 0xc0, 0x3e, 0x0f, 0xd8, 0xcf, 0x01, 0xa2, 0x5f, 0x92, 0x06, 0x4f, 0x24, 0x2b, 0xb8, 0x1f, 0xba, - 0x68, 0xab, 0xbd, 0xdc, 0x69, 0xc4, 0x75, 0x9e, 0xc8, 0x8b, 0x70, 0xa6, 0x47, 0x84, 0xe6, 0x23, - 0xe5, 0xa5, 0xe0, 0x4a, 0x1d, 0xcf, 0xa6, 0x9c, 0x62, 0x73, 0x5b, 0x73, 0x64, 0x3a, 0xec, 0xdf, - 0x90, 0xa6, 0x1f, 0xb3, 0xf0, 0x3b, 0x39, 0xf9, 0x0e, 0xa2, 0x87, 0x21, 0xeb, 0xcb, 0xa5, 0xb8, - 0xe1, 0xc7, 0xaf, 0xf9, 0xf8, 0x8d, 0x7c, 0x07, 0xbf, 0xd5, 0x6a, 0xa7, 0x1b, 0xe4, 0x3e, 0x5b, - 0x60, 0x1d, 0x5a, 0xb2, 0xfb, 0xdf, 0x77, 0x4b, 0x1f, 0x11, 0xa2, 0xe6, 0x6f, 0xab, 0x7a, 0xe4, - 0x0d, 0x35, 0x7b, 0x5a, 0xa1, 0x72, 0x1c, 0x27, 0xae, 0x14, 0xbe, 0xf1, 0x7a, 0x5c, 0xc7, 0xc0, - 0x89, 0x52, 0xf4, 0x2b, 0xd2, 0x70, 0xa0, 0x40, 0x78, 0x63, 0x5d, 0xb4, 0x8c, 0x6d, 0xcd, 0x03, - 0x87, 0x3f, 0x91, 0xfa, 0xf4, 0xaa, 0x03, 0x53, 0x8f, 0x72, 0xb0, 0xdc, 0x1b, 0x8b, 0x49, 0x56, - 0xe2, 0x79, 0x80, 0xb6, 0x49, 0x33, 0x05, 0x6d, 0x72, 0xa9, 0x11, 0xaf, 0x56, 0xc9, 0x62, 0xe8, - 0xf0, 0x8f, 0x65, 0x42, 0x3f, 0xbe, 0x20, 0xfa, 0x23, 0x39, 0xc0, 0x41, 0x61, 0x85, 0x95, 0xc6, - 0x4a, 0x5f, 0xb2, 0x01, 0x00, 0x5e, 0x4c, 0xc6, 0xa7, 0xcd, 0xec, 0x22, 0xe3, 0x62, 0x42, 0x38, - 0x03, 0xb8, 0x00, 0xfb, 0x82, 0xe3, 0x08, 0xdf, 0x51, 0xe1, 0x08, 0xdf, 0xfb, 0xdc, 0x11, 0x2e, - 0xe6, 0xbe, 0x38, 0xc2, 0xdf, 0x92, 0xad, 0xaa, 0xa2, 0xc5, 0x42, 0xaa, 0xed, 0xb7, 0x81, 0xc0, - 0xbc, 0x80, 0x73, 0xb2, 0x9e, 0x70, 0x07, 0xf3, 0xe4, 0x2b, 0x9f, 0x99, 0xbc, 0x19, 0xe4, 0xd3, - 0xc4, 0x27, 0xe4, 0x51, 0x30, 0x1a, 0x4a, 0xe7, 0x8d, 0x2d, 0x99, 0x85, 0xb7, 0xdc, 0xa6, 0xa1, - 0x02, 0x01, 0xda, 0x4b, 0x05, 0xb8, 0x36, 0xd7, 0xe3, 0x83, 0x01, 0xc0, 0xcb, 0x8a, 0x13, 0x23, - 0xe5, 0x62, 0xc6, 0xa0, 0x3f, 0x90, 0xfd, 0xbb, 0x1b, 0x67, 0xc1, 0x10, 0x17, 0xe9, 0x7a, 0xbc, - 0xb3, 0xb0, 0x73, 0xce, 0x66, 0x4e, 0xa7, 0xfc, 0xfd, 0x3f, 0xad, 0xa5, 0xf7, 0x37, 0xad, 0xda, - 0x87, 0x9b, 0x56, 0xed, 0xef, 0x9b, 0x56, 0xed, 0xf7, 0xdb, 0xd6, 0xd2, 0x87, 0xdb, 0xd6, 0xd2, - 0x5f, 0xb7, 0xad, 0xa5, 0x5f, 0xfa, 0x99, 0xf4, 0xc3, 0x51, 0xd2, 0x15, 0x26, 0xef, 0xa5, 0xdc, - 0x73, 0xec, 0x4b, 0xf1, 0x64, 0xf6, 0x71, 0x3b, 0x92, 0x89, 0x38, 0xc2, 0xae, 0x8f, 0x10, 0xeb, - 0x15, 0x57, 0x59, 0x0f, 0xcf, 0x33, 0x4a, 0xb2, 0x8a, 0x9f, 0x86, 0xe3, 0x7f, 0x03, 0x00, 0x00, - 0xff, 0xff, 0x26, 0xd4, 0x7a, 0xa3, 0x21, 0x07, 0x00, 0x00, + 0xf5, 0x42, 0x70, 0xb9, 0xa3, 0x15, 0x61, 0x2e, 0xb9, 0x25, 0xb9, 0x8e, 0x94, 0x27, 0xe8, 0xb1, + 0x0f, 0xd0, 0x07, 0xca, 0x31, 0xc7, 0x1e, 0x5b, 0xfb, 0x19, 0x7a, 0x2f, 0x38, 0xab, 0x3f, 0x23, + 0x45, 0x83, 0x9c, 0x24, 0xce, 0xf7, 0x33, 0x33, 0xcb, 0xd9, 0x59, 0xf2, 0x9d, 0x05, 0xc5, 0xc7, + 0x60, 0x7b, 0x62, 0xc8, 0xa5, 0x76, 0x3d, 0xf0, 0x43, 0xb0, 0x50, 0xe6, 0x3d, 0x61, 0xf4, 0x40, + 0x66, 0x93, 0x9f, 0x6e, 0x61, 0x8d, 0x37, 0xb4, 0x35, 0x21, 0x77, 0x2b, 0x72, 0x77, 0x4a, 0xee, + 0x56, 0xac, 0x83, 0xed, 0xcc, 0x64, 0x06, 0xa9, 0xbd, 0xf0, 0xaf, 0x52, 0x1d, 0xec, 0x67, 0xc6, + 0x64, 0x0a, 0x7a, 0x78, 0x4a, 0xca, 0x41, 0x8f, 0xeb, 0x71, 0x05, 0x1d, 0xfe, 0xb3, 0x46, 0x9a, + 0xfd, 0xe0, 0xd5, 0x47, 0x03, 0xba, 0x4f, 0xea, 0x68, 0xcd, 0x64, 0x1a, 0xd5, 0xda, 0xb5, 0x4e, + 0x23, 0x5e, 0xc3, 0xf3, 0xab, 0x94, 0xb6, 0xc9, 0x7d, 0xf0, 0x43, 0x36, 0x83, 0xef, 0xb5, 0x6b, + 0x9d, 0x95, 0x98, 0x80, 0x1f, 0xf6, 0x27, 0x8c, 0x7d, 0x52, 0xb7, 0x85, 0x60, 0x3c, 0x4d, 0x6d, + 0xb4, 0x5c, 0x89, 0x6d, 0x21, 0x4e, 0xd2, 0xd4, 0xd2, 0xc7, 0x64, 0xd5, 0xc9, 0x4c, 0x83, 0x8d, + 0x56, 0xda, 0xb5, 0x4e, 0xf3, 0xc9, 0x76, 0xb7, 0xaa, 0xa9, 0x3b, 0xad, 0xa9, 0x7b, 0xa2, 0xc7, + 0xf1, 0x84, 0x43, 0xbf, 0x26, 0x4d, 0x99, 0x54, 0x46, 0xe0, 0x5c, 0xf4, 0x05, 0x7a, 0x11, 0x99, + 0xa0, 0x17, 0x38, 0x47, 0x9f, 0x92, 0x3d, 0xa9, 0xa5, 0x97, 0x5c, 0x31, 0x07, 0x3a, 0x65, 0x62, + 0x08, 0xe2, 0xaa, 0x30, 0x52, 0xfb, 0x68, 0x15, 0xcb, 0xda, 0x99, 0xc0, 0x6f, 0x40, 0xa7, 0xfd, + 0x19, 0xb8, 0xa8, 0xb3, 0x20, 0xae, 0x17, 0x75, 0x6b, 0x77, 0x74, 0x31, 0x88, 0xeb, 0x05, 0xdd, + 0x63, 0x42, 0x41, 0xf3, 0x44, 0x01, 0x4b, 0x21, 0x29, 0x33, 0xe6, 0x2d, 0x17, 0x10, 0xd5, 0xdb, + 0xb5, 0x4e, 0x3d, 0xde, 0xac, 0x90, 0x67, 0x01, 0xb8, 0x0c, 0x71, 0xfa, 0x3d, 0xd9, 0xe3, 0xd7, + 0x60, 0x79, 0x06, 0x2c, 0x51, 0x46, 0x5c, 0x31, 0x2f, 0x73, 0x60, 0xb9, 0x03, 0x11, 0x35, 0x30, + 0xcb, 0xf6, 0x04, 0x3e, 0x0d, 0xe8, 0xa5, 0xcc, 0xe1, 0xb5, 0x03, 0x11, 0x64, 0x39, 0x1f, 0x31, + 0x0b, 0xde, 0x8e, 0xd9, 0xc0, 0x58, 0x26, 0xb5, 0x50, 0xa5, 0x93, 0x46, 0x47, 0xa4, 0x92, 0xe5, + 0x7c, 0x14, 0x07, 0xf4, 0xcc, 0xd8, 0x57, 0x53, 0x8c, 0xa6, 0x84, 0x72, 0xa5, 0xcc, 0x5b, 0xa6, + 0x04, 0x1b, 0x94, 0x5a, 0x78, 0x69, 0xb4, 0x8b, 0x9a, 0xf8, 0x98, 0x9f, 0x76, 0xff, 0x7f, 0x60, + 0xba, 0x27, 0x41, 0x79, 0xde, 0x3f, 0x9b, 0xea, 0xaa, 0x31, 0x88, 0x37, 0xd1, 0xf1, 0x5c, 0xcc, + 0xe2, 0xf4, 0x92, 0x6c, 0x65, 0xdc, 0x31, 0x70, 0x5e, 0xe6, 0xdc, 0x03, 0xb3, 0xdc, 0x43, 0x74, + 0x1f, 0x93, 0x74, 0x3e, 0x95, 0xe4, 0xcc, 0x72, 0x74, 0x89, 0x1f, 0x64, 0xdc, 0x3d, 0x9f, 0x38, + 0xc4, 0xdc, 0x03, 0x3d, 0x24, 0xeb, 0xa1, 0xe5, 0xe0, 0xac, 0x64, 0x2e, 0x7d, 0xb4, 0x8e, 0x8d, + 0x36, 0x73, 0x3e, 0x7a, 0xc1, 0xdd, 0x79, 0x08, 0xd1, 0x3d, 0xb2, 0xe6, 0x47, 0xcc, 0x8f, 0x0b, + 0x88, 0x36, 0x70, 0x10, 0x56, 0xfd, 0xe8, 0x72, 0x5c, 0x00, 0x05, 0xb2, 0x93, 0x8e, 0x35, 0xcf, + 0xa5, 0x60, 0xbe, 0xf2, 0xa8, 0xf2, 0x45, 0x0f, 0xb0, 0xac, 0x27, 0x9f, 0x2a, 0xeb, 0x59, 0x25, + 0xbe, 0x0c, 0xa9, 0x26, 0x7d, 0xd3, 0xf4, 0xa3, 0x18, 0x3d, 0x26, 0xbb, 0x78, 0x8b, 0x8e, 0x15, + 0x60, 0x19, 0x5c, 0x83, 0xf6, 0xec, 0xd7, 0x12, 0xec, 0x38, 0xda, 0xc4, 0x62, 0x1f, 0x56, 0xe8, + 0x05, 0xd8, 0xe7, 0x01, 0xfb, 0x39, 0x40, 0xf4, 0x4b, 0xd2, 0xe0, 0x89, 0x64, 0x05, 0xf7, 0x43, + 0x17, 0x6d, 0xb5, 0x97, 0x3b, 0x8d, 0xb8, 0xce, 0x13, 0x79, 0x11, 0xce, 0xf4, 0x88, 0xd0, 0xbc, + 0x54, 0x5e, 0x0a, 0xae, 0xd4, 0xf1, 0x6c, 0xca, 0x29, 0x36, 0xb7, 0x35, 0x47, 0xa6, 0xc3, 0xfe, + 0x0d, 0x69, 0xfa, 0x11, 0x0b, 0xcf, 0xc9, 0xc9, 0x77, 0x10, 0x3d, 0x0c, 0x59, 0x5f, 0x2e, 0xc5, + 0x0d, 0x3f, 0x7a, 0xcd, 0x47, 0x6f, 0xe4, 0x3b, 0xf8, 0xad, 0x56, 0xa3, 0x8f, 0x08, 0x29, 0xac, + 0x14, 0xc0, 0x92, 0x32, 0x2f, 0xa2, 0x6d, 0xac, 0xac, 0x81, 0x91, 0xd3, 0x32, 0x2f, 0x4e, 0x37, + 0xc8, 0x7d, 0xb6, 0x60, 0x72, 0x68, 0xc9, 0xee, 0x7f, 0x5f, 0x7d, 0x30, 0x52, 0xf3, 0x57, 0xaf, + 0xda, 0x01, 0x0d, 0x35, 0x7b, 0xf3, 0x42, 0x63, 0x38, 0x6d, 0x5c, 0x29, 0x5c, 0x01, 0xf5, 0xb8, + 0x8e, 0x81, 0x13, 0xa5, 0xe8, 0x57, 0xa4, 0xe1, 0x40, 0x81, 0xf0, 0xc6, 0xba, 0x68, 0x19, 0xbb, + 0x9e, 0x07, 0x0e, 0x7f, 0x22, 0xf5, 0xe9, 0x24, 0x04, 0xa6, 0x2e, 0x73, 0xb0, 0xdc, 0x1b, 0x8b, + 0x49, 0x56, 0xe2, 0x79, 0x80, 0xb6, 0x49, 0x33, 0x05, 0x6d, 0x72, 0xa9, 0x11, 0xaf, 0x36, 0xcd, + 0x62, 0xe8, 0xf0, 0x8f, 0x65, 0x42, 0x3f, 0xbe, 0x3f, 0xfa, 0x23, 0x39, 0xc0, 0x39, 0x62, 0x85, + 0x95, 0xc6, 0x4a, 0x3f, 0x66, 0x03, 0x00, 0xbc, 0xb7, 0x8c, 0x4f, 0x9b, 0xd9, 0x45, 0xc6, 0xc5, + 0x84, 0x70, 0x06, 0x70, 0x01, 0xf6, 0x05, 0xc7, 0x09, 0xbf, 0xa3, 0xc2, 0x09, 0xbf, 0xf7, 0xb9, + 0x13, 0x5e, 0xcc, 0x7d, 0x71, 0xc2, 0xbf, 0x25, 0x5b, 0x55, 0x45, 0x8b, 0x85, 0x54, 0xcb, 0x71, + 0x03, 0x81, 0x79, 0x01, 0xe7, 0x64, 0x3d, 0xe1, 0x0e, 0xe6, 0xc9, 0x57, 0x3e, 0x33, 0x79, 0x33, + 0xc8, 0xa7, 0x89, 0x4f, 0xc8, 0xa3, 0x60, 0x34, 0x94, 0xce, 0x1b, 0x3b, 0x66, 0x16, 0xde, 0x72, + 0x9b, 0x86, 0x0a, 0x04, 0x68, 0x2f, 0x15, 0xe0, 0x56, 0x5d, 0x8f, 0x0f, 0x06, 0x00, 0x2f, 0x2b, + 0x4e, 0x8c, 0x94, 0x8b, 0x19, 0x83, 0xfe, 0x40, 0xf6, 0xef, 0x2e, 0xa4, 0x05, 0x43, 0xdc, 0xb3, + 0xeb, 0xf1, 0xce, 0xc2, 0x4a, 0x3a, 0x9b, 0x39, 0x9d, 0xf2, 0xf7, 0x7f, 0xb7, 0x96, 0xde, 0xdf, + 0xb4, 0x6a, 0x1f, 0x6e, 0x5a, 0xb5, 0xbf, 0x6e, 0x5a, 0xb5, 0xdf, 0x6f, 0x5b, 0x4b, 0x1f, 0x6e, + 0x5b, 0x4b, 0x7f, 0xde, 0xb6, 0x96, 0x7e, 0xe9, 0x67, 0xd2, 0x0f, 0xcb, 0xa4, 0x2b, 0x4c, 0xde, + 0x4b, 0xb9, 0xe7, 0xd8, 0x97, 0xe2, 0xc9, 0xec, 0xdb, 0x77, 0x24, 0x13, 0x71, 0x84, 0x5d, 0x1f, + 0x21, 0xd6, 0x2b, 0xae, 0xb2, 0x1e, 0x9e, 0x67, 0x94, 0x64, 0x15, 0xbf, 0x1c, 0xc7, 0xff, 0x06, + 0x00, 0x00, 0xff, 0xff, 0xaa, 0x94, 0x66, 0x70, 0x40, 0x07, 0x00, 0x00, } func (m *ChainConfig) Marshal() (dAtA []byte, err error) { @@ -330,6 +332,13 @@ func (m *ChainConfig) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.PriceBump != 0 { + i = encodeVarintConfig(dAtA, i, uint64(m.PriceBump)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xa0 + } if m.XTxMaxSize != nil { { size := m.XTxMaxSize.Size() @@ -738,6 +747,9 @@ func (m *ChainConfig) Size() (n int) { if m.XTxMaxSize != nil { n += m.XTxMaxSize.Size() } + if m.PriceBump != 0 { + n += 2 + sovConfig(uint64(m.PriceBump)) + } return n } @@ -1362,6 +1374,25 @@ func (m *ChainConfig) Unmarshal(dAtA []byte) error { } } m.XTxMaxSize = &ChainConfig_TxMaxSize{v} + case 20: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PriceBump", wireType) + } + m.PriceBump = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfig + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PriceBump |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipConfig(dAtA[iNdEx:]) diff --git a/pkg/relay/ethereum/gas.go b/pkg/relay/ethereum/gas.go index 96e90da..c0ca523 100644 --- a/pkg/relay/ethereum/gas.go +++ b/pkg/relay/ethereum/gas.go @@ -3,10 +3,13 @@ package ethereum import ( "context" "fmt" + "math/big" + "github.com/datachainlab/ethereum-ibc-relay-chain/pkg/client" + "github.com/datachainlab/ethereum-ibc-relay-chain/pkg/client/txpool" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" - "math/big" + "github.com/ethereum/go-ethereum/common" ) type GasFeeCalculator struct { @@ -22,12 +25,24 @@ func NewGasFeeCalculator(client *client.ETHClient, config *ChainConfig) *GasFeeC } func (m *GasFeeCalculator) Apply(ctx context.Context, txOpts *bind.TransactOpts) error { + minFeeCap := common.Big0 + minTipCap := common.Big0 + if m.config.PriceBump > 0 { + var err error + if minFeeCap, minTipCap, err = txpool.GetMinimumRequiredFee(ctx, m.client.Client, txOpts.From, 10); err != nil { + return err + } + } + switch m.config.TxType { case TxTypeLegacy: gasPrice, err := m.client.SuggestGasPrice(ctx) if err != nil { return fmt.Errorf("failed to suggest gas price: %v", err) } + if gasPrice.Cmp(minFeeCap) < 0 { + gasPrice = minFeeCap + } txOpts.GasPrice = gasPrice return nil case TxTypeDynamic: @@ -37,12 +52,18 @@ func (m *GasFeeCalculator) Apply(ctx context.Context, txOpts *bind.TransactOpts) } // GasTipCap = min(LimitPriorityFeePerGas, simulated_eth_maxPriorityFeePerGas * PriorityFeeRate) m.config.DynamicTxGasConfig.PriorityFeeRate.Mul(gasTipCap) + if gasTipCap.Cmp(minTipCap) < 0 { + gasTipCap = minTipCap + } if l := m.config.DynamicTxGasConfig.GetLimitPriorityFeePerGas(); l.Sign() > 0 && gasTipCap.Cmp(l) > 0 { gasTipCap = l } // GasFeeCap = min(LimitFeePerGas, GasTipCap + BaseFee * BaseFeeRate) m.config.DynamicTxGasConfig.BaseFeeRate.Mul(gasFeeCap) gasFeeCap.Add(gasFeeCap, gasTipCap) + if gasFeeCap.Cmp(minFeeCap) < 0 { + gasFeeCap = minFeeCap + } if l := m.config.DynamicTxGasConfig.GetLimitFeePerGas(); l.Sign() > 0 && gasFeeCap.Cmp(l) > 0 { gasFeeCap = l } diff --git a/proto/relayer/chains/ethereum/config/config.proto b/proto/relayer/chains/ethereum/config/config.proto index 54649a8..3402bd7 100644 --- a/proto/relayer/chains/ethereum/config/config.proto +++ b/proto/relayer/chains/ethereum/config/config.proto @@ -42,6 +42,8 @@ message ChainConfig { string multicall3_address = 18; optional uint64 tx_max_size = 19; + + uint64 price_bump = 20; } message AllowLCFunctionsConfig { From d1c1b16939aad7019cb9d5333e43841db20c892e Mon Sep 17 00:00:00 2001 From: Masanori Yoshida Date: Tue, 24 Dec 2024 10:19:09 +0900 Subject: [PATCH 3/6] use GetMinimumRequiredFee when using the latest nonce Signed-off-by: Masanori Yoshida --- pkg/client/txpool/txpool.go | 16 +++++++++++++--- pkg/client/txpool/txpool_test.go | 2 +- pkg/relay/ethereum/gas.go | 4 ++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/pkg/client/txpool/txpool.go b/pkg/client/txpool/txpool.go index d219aa7..f90ec5f 100644 --- a/pkg/client/txpool/txpool.go +++ b/pkg/client/txpool/txpool.go @@ -82,7 +82,7 @@ func inclByPercent(n *big.Int, percent uint64) { } // GetMinimumRequiredFee returns the minimum fee required to successfully send a transaction -func GetMinimumRequiredFee(ctx context.Context, client *ethclient.Client, address common.Address, priceBump uint64) (*big.Int, *big.Int, error) { +func GetMinimumRequiredFee(ctx context.Context, client *ethclient.Client, address common.Address, nonce uint64, priceBump uint64) (*big.Int, *big.Int, error) { pendingTxs, err := PendingTransactions(ctx, client, address) if err != nil { return nil, nil, err @@ -90,8 +90,18 @@ func GetMinimumRequiredFee(ctx context.Context, client *ethclient.Client, addres return common.Big0, common.Big0, nil } - gasFeeCap := pendingTxs[0].GasFeeCap.ToInt() - gasTipCap := pendingTxs[0].GasTipCap.ToInt() + var targetTx *RPCTransaction + for _, pendingTx := range pendingTxs { + if uint64(pendingTx.Nonce) == nonce { + targetTx = pendingTx + } + } + if targetTx == nil { + return common.Big0, common.Big0, nil + } + + gasFeeCap := targetTx.GasFeeCap.ToInt() + gasTipCap := targetTx.GasTipCap.ToInt() inclByPercent(gasFeeCap, priceBump) inclByPercent(gasTipCap, priceBump) diff --git a/pkg/client/txpool/txpool_test.go b/pkg/client/txpool/txpool_test.go index b645890..e87bd80 100644 --- a/pkg/client/txpool/txpool_test.go +++ b/pkg/client/txpool/txpool_test.go @@ -81,7 +81,7 @@ func transfer(t *testing.T, ctx context.Context, client *ethclient.Client, signe func replace(t *testing.T, ctx context.Context, client *ethclient.Client, signer types.Signer, key *ecdsa.PrivateKey, priceBump uint64, nonce uint64, gasTipCap, gasFeeCap *big.Int, to common.Address, amount *big.Int) { addr := crypto.PubkeyToAddress(key.PublicKey) - if minFeeCap, minTipCap, err := GetMinimumRequiredFee(ctx, client, addr, priceBump); err != nil { + if minFeeCap, minTipCap, err := GetMinimumRequiredFee(ctx, client, addr, nonce, priceBump); err != nil { t.Fatalf("failed to get the minimum fee required to replace tx: err=%v", err) } else if minFeeCap.Cmp(common.Big0) == 0 { t.Fatalf("tx to replace not found") diff --git a/pkg/relay/ethereum/gas.go b/pkg/relay/ethereum/gas.go index c0ca523..a859a30 100644 --- a/pkg/relay/ethereum/gas.go +++ b/pkg/relay/ethereum/gas.go @@ -27,9 +27,9 @@ func NewGasFeeCalculator(client *client.ETHClient, config *ChainConfig) *GasFeeC func (m *GasFeeCalculator) Apply(ctx context.Context, txOpts *bind.TransactOpts) error { minFeeCap := common.Big0 minTipCap := common.Big0 - if m.config.PriceBump > 0 { + if m.config.PriceBump > 0 && txOpts.Nonce != nil { var err error - if minFeeCap, minTipCap, err = txpool.GetMinimumRequiredFee(ctx, m.client.Client, txOpts.From, 10); err != nil { + if minFeeCap, minTipCap, err = txpool.GetMinimumRequiredFee(ctx, m.client.Client, txOpts.From, txOpts.Nonce.Uint64(), 10); err != nil { return err } } From 3c25114bd00dec3eb6a94e98e5b0a683990b878f Mon Sep 17 00:00:00 2001 From: Masanori Yoshida Date: Tue, 24 Dec 2024 10:22:47 +0900 Subject: [PATCH 4/6] break when finding out the only pending tx that matches the nonce Signed-off-by: Masanori Yoshida --- pkg/client/txpool/txpool.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/client/txpool/txpool.go b/pkg/client/txpool/txpool.go index f90ec5f..383a153 100644 --- a/pkg/client/txpool/txpool.go +++ b/pkg/client/txpool/txpool.go @@ -94,6 +94,7 @@ func GetMinimumRequiredFee(ctx context.Context, client *ethclient.Client, addres for _, pendingTx := range pendingTxs { if uint64(pendingTx.Nonce) == nonce { targetTx = pendingTx + break } } if targetTx == nil { From b5db0bcbef3ad163f9557698023157bab5d0950e Mon Sep 17 00:00:00 2001 From: Masanori Yoshida Date: Wed, 25 Dec 2024 01:13:29 +0900 Subject: [PATCH 5/6] delete an unused proto file Signed-off-by: Masanori Yoshida --- .../relayer/chains/ethereum/signers/hd/config.proto | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 proto/relayer/chains/ethereum/signers/hd/config.proto diff --git a/proto/relayer/chains/ethereum/signers/hd/config.proto b/proto/relayer/chains/ethereum/signers/hd/config.proto deleted file mode 100644 index ef41431..0000000 --- a/proto/relayer/chains/ethereum/signers/hd/config.proto +++ /dev/null @@ -1,12 +0,0 @@ -syntax = "proto3"; -package relayer.chains.ethereum.signers.hd; - -import "gogoproto/gogo.proto"; - -option go_package = "github.com/datachainlab/ethereum-ibc-relay-chain/pkg/relay/ethereum/signers/hd"; -option (gogoproto.goproto_getters_all) = false; - -message SignerConfig { - string mnemonic = 1; - string path = 2; -} From ad43f88aa64f11aaa6c555ad21b6d9228f3d95a5 Mon Sep 17 00:00:00 2001 From: Masanori Yoshida Date: Wed, 25 Dec 2024 10:17:53 +0900 Subject: [PATCH 6/6] remove an unused struct definition Signed-off-by: Masanori Yoshida --- pkg/client/txpool/txpool_test.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pkg/client/txpool/txpool_test.go b/pkg/client/txpool/txpool_test.go index e87bd80..94ec8d6 100644 --- a/pkg/client/txpool/txpool_test.go +++ b/pkg/client/txpool/txpool_test.go @@ -16,11 +16,6 @@ import ( "github.com/ethereum/go-ethereum/node" ) -type account struct { - key *ecdsa.PrivateKey - addr common.Address -} - func makeGenesisAlloc(t *testing.T, n int) ([]common.Address, types.GenesisAlloc) { var addrs []common.Address alloc := make(types.GenesisAlloc)