From 530cf510712abdbd83ebd442ea4c60d6c898a8ca Mon Sep 17 00:00:00 2001 From: trajan0x <83933037+trajan0x@users.noreply.github.com> Date: Wed, 20 Dec 2023 20:24:31 +0100 Subject: [PATCH] Updates Submitter w/ Oracle fallback (#1671) --------- Co-authored-by: Trajan0x Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- agents/go.mod | 4 +- agents/go.sum | 7 +- agents/types/utils.go | 8 +- contrib/promexporter/config/config.go | 2 +- contrib/terraform-provider-helmproxy/go.mod | 2 +- contrib/terraform-provider-helmproxy/go.sum | 4 +- ethergo/backends/anvil/anvil.go | 89 ++++----- ethergo/backends/base/base.go | 1 + ethergo/backends/simulated/chain.go | 1 + ethergo/chain/chain_impl.go | 1 + ethergo/client/client.go | 30 +++ ethergo/go.mod | 2 +- ethergo/go.sum | 3 +- ethergo/submitter/chain_queue.go | 63 +++++-- ethergo/submitter/export_test.go | 80 +++----- ethergo/submitter/submitter.go | 97 +++++++++- ethergo/submitter/suite_test.go | 14 ++ ethergo/submitter/util.go | 99 +--------- ethergo/submitter/util_test.go | 187 +------------------ ethergo/util/export_test.go | 38 +++- ethergo/util/transactor.go | 97 ++++++++++ ethergo/util/transactor_test.go | 194 ++++++++++++++++++++ services/cctp-relayer/go.mod | 4 +- services/cctp-relayer/go.sum | 7 +- services/omnirpc/go.mod | 4 +- services/omnirpc/go.sum | 7 +- services/scribe/go.mod | 4 +- services/scribe/go.sum | 7 +- services/sinner/go.mod | 4 +- services/sinner/go.sum | 7 +- 30 files changed, 628 insertions(+), 439 deletions(-) create mode 100644 ethergo/util/transactor.go create mode 100644 ethergo/util/transactor_test.go diff --git a/agents/go.mod b/agents/go.mod index b4151a6627..e2d2956519 100644 --- a/agents/go.mod +++ b/agents/go.mod @@ -74,7 +74,7 @@ require ( github.com/acomagu/bufpipe v1.0.4 // indirect github.com/agnivade/levenshtein v1.1.1 // indirect github.com/alecthomas/chroma v0.7.1 // indirect - github.com/andybalholm/brotli v1.0.4 // indirect + github.com/andybalholm/brotli v1.0.5 // indirect github.com/aws/aws-sdk-go-v2 v1.18.0 // indirect github.com/aws/aws-sdk-go-v2/config v1.18.21 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.13.20 // indirect @@ -194,7 +194,7 @@ require ( github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a // indirect github.com/keep-network/keep-common v1.7.1-0.20211012131917-7102d7b9c6a0 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/klauspost/compress v1.15.12 // indirect + github.com/klauspost/compress v1.16.0 // indirect github.com/klauspost/cpuid/v2 v2.2.4 // indirect github.com/kyokomi/emoji/v2 v2.2.8 // indirect github.com/leodido/go-urn v1.2.4 // indirect diff --git a/agents/go.sum b/agents/go.sum index 2f426f6973..0e9b3250a2 100644 --- a/agents/go.sum +++ b/agents/go.sum @@ -148,8 +148,9 @@ github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKS github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -815,8 +816,8 @@ github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6 github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= -github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= diff --git a/agents/types/utils.go b/agents/types/utils.go index 0c789f48b6..1213d68fb0 100644 --- a/agents/types/utils.go +++ b/agents/types/utils.go @@ -3,6 +3,7 @@ package types import ( "context" "fmt" + "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -27,9 +28,12 @@ func signEncoder(ctx context.Context, signer signer.Signer, encoder Encoder, sal } // Sign the message. - signature, err := signer.SignMessage(ctx, core.BytesToSlice(hashedDigest), false) + sig, err := signer.SignMessage(ctx, core.BytesToSlice(hashedDigest), false) if err != nil { return nil, nil, common.Hash{}, fmt.Errorf("could not sign: %w", err) } - return signature, encoded, hashedDigest, nil + + sig = NewSignature(new(big.Int).Add(big.NewInt(27), sig.V()), sig.R(), sig.S()) + + return sig, encoded, hashedDigest, nil } diff --git a/contrib/promexporter/config/config.go b/contrib/promexporter/config/config.go index bfd938e83e..3e32546a33 100644 --- a/contrib/promexporter/config/config.go +++ b/contrib/promexporter/config/config.go @@ -99,7 +99,7 @@ func DecodeConfig(filePath string) (_ Config, err error) { Name: "messenger", }, { - Address: "0x0a1e1d0eb6a1cef79e46f0e2d35b7bf2e958a26a", + Address: "0x49357ba0Ef3a8daC25903472eEe45C41221D4F9a", Name: "cctp", ChainIDs: types.ToInts(types.ETH, types.ARBITRUM, types.AVALANCHE, types.OPTIMISM), }, diff --git a/contrib/terraform-provider-helmproxy/go.mod b/contrib/terraform-provider-helmproxy/go.mod index 1dda73cba5..96caf9d0e4 100644 --- a/contrib/terraform-provider-helmproxy/go.mod +++ b/contrib/terraform-provider-helmproxy/go.mod @@ -127,7 +127,7 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f // indirect - github.com/klauspost/compress v1.15.12 // indirect + github.com/klauspost/compress v1.16.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect diff --git a/contrib/terraform-provider-helmproxy/go.sum b/contrib/terraform-provider-helmproxy/go.sum index 2c53448f70..d646b52ae2 100644 --- a/contrib/terraform-provider-helmproxy/go.sum +++ b/contrib/terraform-provider-helmproxy/go.sum @@ -764,8 +764,8 @@ github.com/kisielk/errcheck v1.6.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= -github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= diff --git a/ethergo/backends/anvil/anvil.go b/ethergo/backends/anvil/anvil.go index f12803f1d5..89f08a3b24 100644 --- a/ethergo/backends/anvil/anvil.go +++ b/ethergo/backends/anvil/anvil.go @@ -135,6 +135,7 @@ func NewAnvilBackend(ctx context.Context, t *testing.T, args *OptionBuilder) *Ba return fmt.Errorf("failed to connect") } + // nolint: staticcheck res, err := rpcClient.ChainID(ctx) if err != nil { return fmt.Errorf("failed to get chain id: %w", err) @@ -263,7 +264,7 @@ func setupOtterscan(ctx context.Context, tb testing.TB, pool *dockertest.Pool, a var logger = log.Logger("anvil-docker") // storeWallets stores preseeded wallets w/ balances. -func (f *Backend) storeWallets(args *OptionBuilder) error { +func (b *Backend) storeWallets(args *OptionBuilder) error { derivationPath := args.GetDerivationPath() derivIter := accounts.DefaultIterator(derivationPath) maxAccounts := args.GetAccounts() @@ -275,7 +276,7 @@ func (f *Backend) storeWallets(args *OptionBuilder) error { return fmt.Errorf("could not get seed phrase: %w", err) } - f.store.Store(walletToKey(f.Backend.T(), wall)) + b.store.Store(walletToKey(b.Backend.T(), wall)) } return nil } @@ -299,31 +300,31 @@ func walletToKey(tb testing.TB, wall wallet.Wallet) *keystore.Key { } // ChainConfig gets the chain config. -func (f *Backend) ChainConfig() *params.ChainConfig { - return f.chainConfig +func (b *Backend) ChainConfig() *params.ChainConfig { + return b.chainConfig } // Signer gets the signer for the chain. -func (f *Backend) Signer() types.Signer { - latestBlock, err := f.BlockNumber(f.Context()) - require.Nil(f.T(), err) +func (b *Backend) Signer() types.Signer { + latestBlock, err := b.BlockNumber(b.Context()) + require.Nil(b.T(), err) - return types.MakeSigner(f.ChainConfig(), new(big.Int).SetUint64(latestBlock)) + return types.MakeSigner(b.ChainConfig(), new(big.Int).SetUint64(latestBlock)) } // FundAccount funds an account with the given amount. -func (f *Backend) FundAccount(ctx context.Context, address common.Address, amount big.Int) { - ctx, cancel := onecontext.Merge(ctx, f.Context()) +func (b *Backend) FundAccount(ctx context.Context, address common.Address, amount big.Int) { + ctx, cancel := onecontext.Merge(ctx, b.Context()) defer cancel() - anvilClient, err := Dial(ctx, f.RPCAddress()) - require.Nilf(f.T(), err, "failed to dial anvil client on chain %d: %v", f.GetChainID(), err) + anvilClient, err := Dial(ctx, b.RPCAddress()) + require.Nilf(b.T(), err, "failed to dial anvil client on chain %d: %v", b.GetChainID(), err) - unlocker := f.fundingMux.Lock(address) + unlocker := b.fundingMux.Lock(address) defer unlocker.Unlock() - prevBalance, err := f.Backend.BalanceAt(ctx, address, nil) - require.Nil(f.T(), err) + prevBalance, err := b.Backend.BalanceAt(ctx, address, nil) + require.Nil(b.T(), err) newBal := new(big.Int).Add(prevBalance, &amount) @@ -338,13 +339,13 @@ func (f *Backend) FundAccount(ctx context.Context, address common.Address, amoun // TODO: this may cause issues when newBal overflows uint64 err = anvilClient.SetBalance(ctx, address, newBal.Uint64()) - require.Nil(f.T(), err) + require.Nil(b.T(), err) } // WaitForConfirmation checks confirmation if the transaction is signed. // nolint: cyclop -func (f *Backend) WaitForConfirmation(ctx context.Context, tx *types.Transaction) { - require.NotNil(f.T(), tx, "tx is nil") +func (b *Backend) WaitForConfirmation(ctx context.Context, tx *types.Transaction) { + require.NotNil(b.T(), tx, "tx is nil") v, r, s := tx.RawSignatureValues() isUnsigned := isZero(v) && isZero(r) && isZero(s) if isUnsigned { @@ -354,7 +355,7 @@ func (f *Backend) WaitForConfirmation(ctx context.Context, tx *types.Transaction return } - f.Backend.WaitForConfirmation(ctx, tx) + b.Backend.WaitForConfirmation(ctx, tx) } func isZero(val *big.Int) bool { @@ -362,40 +363,40 @@ func isZero(val *big.Int) bool { } // GetFundedAccount gets a funded account. -func (f *Backend) GetFundedAccount(ctx context.Context, requestBalance *big.Int) *keystore.Key { - key := f.MockAccount() +func (b *Backend) GetFundedAccount(ctx context.Context, requestBalance *big.Int) *keystore.Key { + key := b.MockAccount() - f.store.Store(key) + b.store.Store(key) - f.FundAccount(ctx, key.Address, *requestBalance) + b.FundAccount(ctx, key.Address, *requestBalance) return key } // GetTxContext gets the tx context for the given address. // TODO: dedupe w/ geth. -func (f *Backend) GetTxContext(ctx context.Context, address *common.Address) (res backends.AuthType) { - ctx, cancel := onecontext.Merge(ctx, f.Context()) +func (b *Backend) GetTxContext(ctx context.Context, address *common.Address) (res backends.AuthType) { + ctx, cancel := onecontext.Merge(ctx, b.Context()) defer cancel() var acct *keystore.Key // TODO handle storing accounts to conform to get tx context if address != nil { - acct = f.store.GetAccount(*address) + acct = b.store.GetAccount(*address) if acct == nil { - f.T().Errorf("could not get account %s", address.String()) + b.T().Errorf("could not get account %s", address.String()) return res } } else { - acct = f.GetFundedAccount(ctx, new(big.Int).SetUint64(math.MaxUint64)) - f.store.Store(acct) + acct = b.GetFundedAccount(ctx, new(big.Int).SetUint64(math.MaxUint64)) + b.store.Store(acct) } - auth, err := f.NewKeyedTransactorFromKey(acct.PrivateKey) - require.Nilf(f.T(), err, "could not get transactor for chain %d: %v", f.GetChainID(), err) + auth, err := b.NewKeyedTransactorFromKey(acct.PrivateKey) + require.Nilf(b.T(), err, "could not get transactor for chain %d: %v", b.GetChainID(), err) - auth.GasPrice, err = f.SuggestGasPrice(ctx) - require.Nilf(f.T(), err, "could not get gas price for chain %d: %v", f.GetChainID(), err) + auth.GasPrice, err = b.SuggestGasPrice(ctx) + require.Nilf(b.T(), err, "could not get gas price for chain %d: %v", b.GetChainID(), err) auth.GasLimit = gasLimit @@ -412,21 +413,21 @@ func (f *Backend) GetTxContext(ctx context.Context, address *common.Address) (re // in the meantime, this may cause race conditions. // // We also print a warning message to the console as an added precaution. -func (f *Backend) ImpersonateAccount(ctx context.Context, address common.Address, transact func(opts *bind.TransactOpts) *types.Transaction) error { - f.impersonationMux.Lock() - defer f.impersonationMux.Unlock() +func (b *Backend) ImpersonateAccount(ctx context.Context, address common.Address, transact func(opts *bind.TransactOpts) *types.Transaction) error { + b.impersonationMux.Lock() + defer b.impersonationMux.Unlock() - f.warnImpersonation() + b.warnImpersonation() - anvilClient, err := Dial(ctx, f.RPCAddress()) - require.Nilf(f.T(), err, "could not dial anvil client rpc at %s for chain %d: %v", f.RPCAddress(), f.GetChainID(), err) + anvilClient, err := Dial(ctx, b.RPCAddress()) + require.Nilf(b.T(), err, "could not dial anvil client rpc at %s for chain %d: %v", b.RPCAddress(), b.GetChainID(), err) err = anvilClient.ImpersonateAccount(ctx, address) - require.Nilf(f.T(), err, "could not impersonate account %s for chain %d: %v", address.String(), f.GetChainID(), err) + require.Nilf(b.T(), err, "could not impersonate account %s for chain %d: %v", address.String(), b.GetChainID(), err) defer func() { err = anvilClient.StopImpersonatingAccount(ctx, address) - require.Nilf(f.T(), err, "could not stop impersonating account %s for chain %d: %v", address.String(), f.GetChainID(), err) + require.Nilf(b.T(), err, "could not stop impersonating account %s for chain %d: %v", address.String(), b.GetChainID(), err) }() tx := transact(&bind.TransactOpts{ @@ -439,14 +440,14 @@ func (f *Backend) ImpersonateAccount(ctx context.Context, address common.Address // TODO: test both legacy and dynamic tx types err = anvilClient.SendUnsignedTransaction(ctx, address, tx) - require.Nilf(f.T(), err, "could not send unsigned transaction for chain %d: %v from %s", f.GetChainID(), err, address.String()) + require.Nilf(b.T(), err, "could not send unsigned transaction for chain %d: %v from %s", b.GetChainID(), err, address.String()) return nil } -func (f *Backend) warnImpersonation() { +func (b *Backend) warnImpersonation() { warnImpersonationOnce.Do(func() { - f.T().Logf(` + b.T().Logf(` Using Account Impersonation. WARNING: This cannot be called concurrently with other impersonation calls. Please make sure your callers are concurrency safe against account impersonation. diff --git a/ethergo/backends/base/base.go b/ethergo/backends/base/base.go index fc3ca85857..e206e152a1 100644 --- a/ethergo/backends/base/base.go +++ b/ethergo/backends/base/base.go @@ -103,6 +103,7 @@ func (b *Backend) EnableTenderly() bool { } // Client fetches an eth client fro the backend. +// nolint: staticcheck func (b *Backend) Client() client.EVMClient { return b.Chain } diff --git a/ethergo/backends/simulated/chain.go b/ethergo/backends/simulated/chain.go index 12ccd7b516..20ff09ba17 100644 --- a/ethergo/backends/simulated/chain.go +++ b/ethergo/backends/simulated/chain.go @@ -134,4 +134,5 @@ func (s Client) SuggestGasPrice(ctx context.Context) (gasPrice *big.Int, err err return big.NewInt(0).Add(estimatedPrice, baseFee), nil } +// nolint: staticcheck var _ client.EVMClient = &Client{} diff --git a/ethergo/chain/chain_impl.go b/ethergo/chain/chain_impl.go index 1f8a5c9229..7d5f62638c 100644 --- a/ethergo/chain/chain_impl.go +++ b/ethergo/chain/chain_impl.go @@ -140,6 +140,7 @@ func NewFromURL(ctx context.Context, url string) (Chain, error) { } // NewFromClient gets a chain from client. +// nolint: staticcheck func NewFromClient(ctx context.Context, config *client.Config, evmClient client.EVMClient) (chain Chain, err error) { rpcURL := "" if len(config.RPCUrl) > 0 { diff --git a/ethergo/client/client.go b/ethergo/client/client.go index 44ff0a9d6b..dce5454319 100644 --- a/ethergo/client/client.go +++ b/ethergo/client/client.go @@ -2,6 +2,8 @@ package client import ( "context" + "encoding/json" + "errors" "fmt" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -96,13 +98,41 @@ func (c *clientImpl) getW3Client() *w3.Client { // BatchWithContext batches multiple w3 calls. func (c *clientImpl) BatchWithContext(ctx context.Context, calls ...w3types.Caller) (err error) { + // Do not create an even if there are no calls + if len(calls) == 0 { + return nil + } + ctx, span := c.tracing.Tracer().Start(ctx, batchAttribute) span.SetAttributes(parseCalls(calls)) span.SetAttributes(attribute.String(endpointAttribute, c.endpoint)) defer func() { + if errors.Is(err, w3.CallErrors{}) { + var batchErr w3.CallErrors + _ = errors.As(err, &batchErr) + for i, callErr := range batchErr { + rawReq, err := calls[i].CreateRequest() + // this already happened, so it can't be failing now. + // just error. + if err != nil { + fmt.Println("could not create request: this should never happen", err) + continue + } + + params, err := json.Marshal(rawReq.Args) + if err != nil { + fmt.Println("could not marshal params: this should never happen", err) + continue + } + span.RecordError(callErr, trace.WithAttributes(attribute.String("method", rawReq.Method), attribute.String("params", string(params)))) + } + metrics.EndSpan(span) + return + } metrics.EndSpanWithErr(span, err) }() + //nolint: wrapcheck return c.getW3Client().CallCtx(ctx, calls...) } diff --git a/ethergo/go.mod b/ethergo/go.mod index 52ccc59ede..7ae67148e3 100644 --- a/ethergo/go.mod +++ b/ethergo/go.mod @@ -117,7 +117,7 @@ require ( github.com/docker/docker v20.10.23+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect - github.com/dustin/go-humanize v1.0.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect github.com/edsrzf/mmap-go v1.0.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/fatih/color v1.13.0 // indirect diff --git a/ethergo/go.sum b/ethergo/go.sum index dec7a90b79..6e02f1d93d 100644 --- a/ethergo/go.sum +++ b/ethergo/go.sum @@ -329,8 +329,9 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dop251/goja v0.0.0-20200219165308-d1232e640a87/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= diff --git a/ethergo/submitter/chain_queue.go b/ethergo/submitter/chain_queue.go index 503d061315..fd2d5a1e16 100644 --- a/ethergo/submitter/chain_queue.go +++ b/ethergo/submitter/chain_queue.go @@ -2,15 +2,18 @@ package submitter import ( "context" + "errors" "fmt" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/lmittmann/w3" "github.com/lmittmann/w3/module/eth" "github.com/lmittmann/w3/w3types" "github.com/synapsecns/sanguine/core" "github.com/synapsecns/sanguine/core/metrics" "github.com/synapsecns/sanguine/ethergo/client" "github.com/synapsecns/sanguine/ethergo/submitter/db" + "github.com/synapsecns/sanguine/ethergo/util" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "golang.org/x/sync/errgroup" @@ -44,6 +47,10 @@ func (c *chainQueue) chainIDInt() int { } func (t *txSubmitterImpl) chainPendingQueue(parentCtx context.Context, chainID *big.Int, txes []db.TX) (err error) { + if len(txes) == 0 { + return nil + } + ctx, span := t.metrics.Tracer().Start(parentCtx, "submitter.ChainQueue") defer func() { metrics.EndSpanWithErr(span, err) @@ -85,30 +92,41 @@ func (t *txSubmitterImpl) chainPendingQueue(parentCtx context.Context, chainID * cq.bumpTX(gCtx, tx) } - cq.updateOldTxStatuses(gCtx) + cq.updateOldTxStatuses(gCtx) err = cq.g.Wait() if err != nil { return fmt.Errorf("error in chainPendingQueue: %w", err) } - sort.Slice(cq.reprocessQueue, func(i, j int) bool { - return cq.reprocessQueue[i].Nonce() < cq.reprocessQueue[j].Nonce() - }) - - calls := make([]w3types.Caller, len(cq.reprocessQueue)) - txHashes := make([]common.Hash, len(cq.reprocessQueue)) - for i, tx := range cq.reprocessQueue { - calls[i] = eth.SendTx(tx.Transaction).Returns(&txHashes[i]) - } - - cq.storeAndSubmit(ctx, calls, span) + cq.storeAndSubmit(ctx, span) return nil } // storeAndSubmit stores the txes in the database and submits them to the chain. -func (c *chainQueue) storeAndSubmit(ctx context.Context, calls []w3types.Caller, span trace.Span) { +func (c *chainQueue) storeAndSubmit(ctx context.Context, parentSpan trace.Span) { + sort.Slice(c.reprocessQueue, func(i, j int) bool { + return c.reprocessQueue[i].Nonce() < c.reprocessQueue[j].Nonce() + }) + + calls := make([]w3types.Caller, len(c.reprocessQueue)) + txHashes := make([]common.Hash, len(c.reprocessQueue)) + spanners := make([]trace.Span, len(c.reprocessQueue)) + + for i, tx := range c.reprocessQueue { + _, span := c.metrics.Tracer().Start(ctx, "chainPendingQueue.submit", trace.WithAttributes(util.TxToAttributes(tx.Transaction)...)) + spanners[i] = span + defer func() { + // in case this span doesn't get ended automatically below, end it here. + if span.IsRecording() { + metrics.EndSpan(span) + } + }() + + calls[i] = eth.SendTx(tx.Transaction).Returns(&txHashes[i]) + } + var wg sync.WaitGroup wg.Add(2) @@ -118,25 +136,38 @@ func (c *chainQueue) storeAndSubmit(ctx context.Context, calls []w3types.Caller, defer wg.Done() err := c.db.PutTXS(storeCtx, c.reprocessQueue...) if err != nil { - span.AddEvent("could not store txes", trace.WithAttributes(attribute.String("error", err.Error()))) + parentSpan.AddEvent("could not store txes", trace.WithAttributes(attribute.String("error", err.Error()))) } }() go func() { defer wg.Done() err := c.client.BatchWithContext(ctx, calls...) + + // Optimistically store all transactions as pending in the first goroutine. + // The call is made concurrently in the second goroutine. + // If the second goroutine finishes first, updating the status, + // there's no need to store them as pending, hence the context is canceled early. cancelStore() for i := range c.reprocessQueue { + span := spanners[i] if err != nil { c.reprocessQueue[i].Status = db.FailedSubmit + //nolint: errorlint, forcetypeassert + if callErrs, ok := err.(w3.CallErrors); ok && len(callErrs) > i { + span.RecordError(errors.New(callErrs[i].Error())) + } else if err != nil { + span.RecordError(err) + } } else { c.reprocessQueue[i].Status = db.Submitted } + span.End() } err = c.db.PutTXS(ctx, c.reprocessQueue...) if err != nil { - span.AddEvent("could not store txes", trace.WithAttributes(attribute.String("error", err.Error()))) + parentSpan.AddEvent("could not store txes", trace.WithAttributes(attribute.String("error", err.Error()))) } }() wg.Wait() @@ -209,7 +240,7 @@ func (c *chainQueue) bumpTX(parentCtx context.Context, ogTx db.TX) { return fmt.Errorf("could not sign tx: %w", err) } - span.AddEvent("add to reprocess queue", trace.WithAttributes(txToAttributes(tx)...)) + span.AddEvent("add to reprocess queue", trace.WithAttributes(util.TxToAttributes(tx)...)) c.addToReprocessQueue(db.TX{ Transaction: tx, diff --git a/ethergo/submitter/export_test.go b/ethergo/submitter/export_test.go index 5cdcf3142d..7b768a32d3 100644 --- a/ethergo/submitter/export_test.go +++ b/ethergo/submitter/export_test.go @@ -12,65 +12,6 @@ import ( "github.com/synapsecns/sanguine/ethergo/signer/signer" "github.com/synapsecns/sanguine/ethergo/submitter/config" "github.com/synapsecns/sanguine/ethergo/submitter/db" - "go.opentelemetry.io/otel/attribute" -) - -// CopyTransactOpts exports copyTransactOpts for testing. -func CopyTransactOpts(opts *bind.TransactOpts) *bind.TransactOpts { - return copyTransactOpts(opts) -} - -// NullFieldAttribute is a constant used to test the null field attribute. -// it exports the underlying constant for testing. -const NullFieldAttribute = nullFieldAttribute - -func AddressPtrToString(address *common.Address) string { - return addressPtrToString(address) -} - -// BigPtrToString converts a big.Int pointer to a string. -func BigPtrToString(num *big.Int) string { - return bigPtrToString(num) -} - -// TxToAttributes exports txToAttributes for testing. -func TxToAttributes(transaction *types.Transaction) []attribute.KeyValue { - return txToAttributes(transaction) -} - -// SortTxes exports sortTxesByChainID for testing. -func SortTxes(txs []db.TX) map[uint64][]db.TX { - return sortTxesByChainID(txs) -} - -// GroupTxesByNonce exports groupTxesByNonce for testing. -func GroupTxesByNonce(txs []db.TX) map[uint64][]db.TX { - return groupTxesByNonce(txs) -} - -const ( - // HashAttr exports hashAttr for testing. - HashAttr = hashAttr - // FromAttr exports fromAttr for testing. - FromAttr = fromAttr - // ToAttr exports toAttr for testing. - ToAttr = toAttr - // DataAttr exports dataAttr for testing. - DataAttr = dataAttr - // ValueAttr exports valueAttr for testing. - ValueAttr = valueAttr - // NonceAttr exports nonceAttr for testing. - NonceAttr = nonceAttr - // GasLimitAttr exports gasLimitAttr for testing. - GasLimitAttr = gasLimitAttr - // ChainIDAttr exports chainIDAttr for testing. - ChainIDAttr = chainIDAttr - // GasPriceAttr exports gasPriceAttr for testing. - GasPriceAttr = gasPriceAttr - // GasFeeCapAttr exports gasFeeCapAttr for testing. - GasFeeCapAttr = gasFeeCapAttr - // GasTipCapAttr exports gasTipCapAttr for testing. - GasTipCapAttr = gasTipCapAttr ) // NewTestTransactionSubmitter wraps TestTransactionSubmitter in a TransactionSubmitter interface. @@ -114,3 +55,24 @@ func (t *txSubmitterImpl) GetNonce(parentCtx context.Context, chainID *big.Int, func (t *txSubmitterImpl) CheckAndSetConfirmation(ctx context.Context, chainClient client.EVM, txes []db.TX) error { return t.checkAndSetConfirmation(ctx, chainClient, txes) } + +// SortTxes exports sortTxesByChainID for testing. +func SortTxes(txs []db.TX) map[uint64][]db.TX { + return sortTxesByChainID(txs) +} + +// GroupTxesByNonce exports groupTxesByNonce for testing. +func GroupTxesByNonce(txs []db.TX) map[uint64][]db.TX { + return groupTxesByNonce(txs) +} + +// SetForceNoFallback exports setForceNoFallback for testing. +func SetForceNoFallback(val bool) { + forceNoFallbackIfZero = val +} + +// export for testing +// Warning! Changing this value will not change the underlying value! +// htis is exported for testing to allow a return to underlying value after the test +// TODO: consider doing a SetForTest +var ForceNoFallbackIfZero = forceNoFallbackIfZero diff --git a/ethergo/submitter/submitter.go b/ethergo/submitter/submitter.go index 03b23291c8..11af4adc5d 100644 --- a/ethergo/submitter/submitter.go +++ b/ethergo/submitter/submitter.go @@ -4,7 +4,10 @@ import ( "context" "errors" "fmt" + "github.com/ethereum/go-ethereum/params" "github.com/puzpuzpuz/xsync/v2" + "github.com/synapsecns/sanguine/ethergo/chain/gas/backend" + "github.com/synapsecns/sanguine/ethergo/chain/gas/london" "math" "math/big" "reflect" @@ -213,7 +216,7 @@ func (t *txSubmitterImpl) getNonce(parentCtx context.Context, chainID *big.Int, func (t *txSubmitterImpl) storeTX(ctx context.Context, tx *types.Transaction, status db.Status) (err error) { ctx, span := t.metrics.Tracer().Start(ctx, "submitter.StoreTX", trace.WithAttributes( - append(txToAttributes(tx), attribute.String("status", status.String()))...)) + append(util.TxToAttributes(tx), attribute.String("status", status.String()))...)) defer func() { metrics.EndSpanWithErr(span, err) @@ -271,7 +274,7 @@ func (t *txSubmitterImpl) SubmitTransaction(parentCtx context.Context, chainID * } // then we copy the transactor, this is the one we'll modify w/ no send. - transactor := copyTransactOpts(parentTransactor) + transactor := util.CopyTransactOpts(parentTransactor) var locker mapmutex.Unlocker @@ -362,7 +365,8 @@ func (t *txSubmitterImpl) setGasPrice(ctx context.Context, client client.EVM, if t.config.SupportsEIP1559(int(bigChainID.Uint64())) { transactor.GasFeeCap = t.config.GetMaxGasPrice(chainID) - transactor.GasTipCap, err = client.SuggestGasTipCap(ctx) + // only use fallback if no previous tx + transactor.GasTipCap, err = t.SuggestGasTipCap(ctx, client, chainID, prevTx != nil) if err != nil { return fmt.Errorf("could not get gas tip cap: %w", err) } @@ -419,7 +423,7 @@ func (t *txSubmitterImpl) getGasBlock(ctx context.Context, chainClient client.EV if ok { span.AddEvent("could not get gas block; using cached value", trace.WithAttributes( attribute.String("error", err.Error()), - attribute.String("blockNumber", bigPtrToString(gasBlock.Number)), + attribute.String("blockNumber", util.BigPtrToString(gasBlock.Number)), )) } else { return nil, fmt.Errorf("could not get gas block: %w", err) @@ -467,4 +471,89 @@ func (t *txSubmitterImpl) getGasEstimate(ctx context.Context, chainClient client return gasEstimate, nil } +// forceNoFallbackIfZero is used to force no fallback if the tip cap is 0. +var forceNoFallbackIfZero = false + +// TODO: test oracle fallback. +func (t *txSubmitterImpl) SuggestGasTipCap(ctx context.Context, client client.EVM, chainID int, fallbackIfZero bool) (tipCap *big.Int, err error) { + tipCap, err = client.SuggestGasTipCap(ctx) + if err != nil { + return nil, fmt.Errorf("could not get gas tip cap: %w", err) + } + + // note: these ifs can be combined, but I've found the largic hard to parse if they are. + // if tip cap is not zero return + if big.NewInt(0).Cmp(tipCap) != 0 { + return tipCap, nil + } + + // past this point tip cap is 0. + + // if we should force no fallback, return + // this is set for testing. + if forceNoFallbackIfZero { + return tipCap, nil + } + + // if we shouldn't fallback, return + if !fallbackIfZero { + return tipCap, nil + } + + blockHeight, err := client.BlockNumber(ctx) + if err != nil { + return nil, fmt.Errorf("could not get block number: %w", err) + } + + // if on the other hand, fee is 0 we should fallback to our pricer + oracleConfig := gas.GetConfig() + oracleConfig.MaxPrice = core.CopyBigInt(t.config.GetMaxGasPrice(chainID)) + + feeOracle := london.NewFeeOracle(wrappedLondonClient{client, chainID}, blockHeight, oracleConfig) + tipCap, err = feeOracle.SuggestTipCap(ctx) + if err != nil { + return nil, fmt.Errorf("could not get tip cap: %w", err) + } + return tipCap, nil +} + +type wrappedLondonClient struct { + client.EVM + chainID int +} + +// ChainConfig is a fake chain config. +// since wrapped client is only used for makeSigner +// and on london, we just enable everything. +func (w wrappedLondonClient) ChainConfig() *params.ChainConfig { + return ¶ms.ChainConfig{ + ChainID: big.NewInt(int64(w.chainID)), + HomesteadBlock: big.NewInt(0), + DAOForkBlock: big.NewInt(0), + DAOForkSupport: false, + EIP150Block: big.NewInt(0), + EIP150Hash: common.Hash{}, + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + ArrowGlacierBlock: big.NewInt(0), + GrayGlacierBlock: big.NewInt(0), + MergeNetsplitBlock: big.NewInt(0), + ShanghaiBlock: big.NewInt(0), + CancunBlock: big.NewInt(0), + TerminalTotalDifficulty: big.NewInt(0), + TerminalTotalDifficultyPassed: false, + Ethash: nil, + Clique: nil, + } +} + +var _ backend.OracleBackendChain = &wrappedLondonClient{} + var _ TransactionSubmitter = &txSubmitterImpl{} diff --git a/ethergo/submitter/suite_test.go b/ethergo/submitter/suite_test.go index d49f25ba8a..01727e1f1e 100644 --- a/ethergo/submitter/suite_test.go +++ b/ethergo/submitter/suite_test.go @@ -119,6 +119,14 @@ func (s *SubmitterSuite) SetupSuite() { }(i, chainID) } wg.Wait() + + // fallback is currently untested. For now we disable it in tests. + // TODO: this should be fixed, or ideally, fallback can be removed. + og := submitter.ForceNoFallbackIfZero + submitter.SetForceNoFallback(true) + s.T().Cleanup(func() { + submitter.SetForceNoFallback(og) + }) } // SetupTest sets up the signer and funds the account with 10 eth on each backend. @@ -201,6 +209,12 @@ func (t *TXSubmitterDBSuite) SetupSuite() { var err error t.metrics, err = metrics.NewByType(t.GetSuiteContext(), buildInfo, metricsHandler) t.Require().NoError(err) + + og := submitter.ForceNoFallbackIfZero + submitter.SetForceNoFallback(true) + t.T().Cleanup(func() { + submitter.SetForceNoFallback(og) + }) } func (t *TXSubmitterDBSuite) SetupTest() { diff --git a/ethergo/submitter/util.go b/ethergo/submitter/util.go index 1df2e13ff8..2ecdf08e5b 100644 --- a/ethergo/submitter/util.go +++ b/ethergo/submitter/util.go @@ -1,108 +1,15 @@ package submitter import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/synapsecns/sanguine/core" "github.com/synapsecns/sanguine/ethergo/chain/gas" "github.com/synapsecns/sanguine/ethergo/submitter/db" - "github.com/synapsecns/sanguine/ethergo/util" - "go.opentelemetry.io/otel/attribute" - "math/big" "sort" ) -// copyTransactOpts creates a deep copy of the given TransactOpts struct -// with big ints wrapped in core.CopyBigInt(). -func copyTransactOpts(opts *bind.TransactOpts) *bind.TransactOpts { - copyOpts := &bind.TransactOpts{ - From: opts.From, - Nonce: core.CopyBigInt(opts.Nonce), - Signer: opts.Signer, - Value: core.CopyBigInt(opts.Value), - GasPrice: core.CopyBigInt(opts.GasPrice), - GasFeeCap: core.CopyBigInt(opts.GasFeeCap), - GasTipCap: core.CopyBigInt(opts.GasTipCap), - GasLimit: opts.GasLimit, - Context: opts.Context, - NoSend: opts.NoSend, - } - return copyOpts -} - -const ( - hashAttr = "tx.Hash" - fromAttr = "tx.From" - toAttr = "tx.To" - dataAttr = "tx.Data" - valueAttr = "tx.Value" - nonceAttr = "tx.Nonce" - gasLimitAttr = "tx.GasLimit" - chainIDAttr = "tx.ChainID" - gasPriceAttr = "tx.GasPrice" - gasFeeCapAttr = "tx.GasFeeCap" - gasTipCapAttr = "tx.GasTipCap" -) - -// txToAttributes converts a transaction to a slice of attribute.KeyValue. -func txToAttributes(transaction *types.Transaction) []attribute.KeyValue { - var from string - call, err := util.TxToCall(transaction) - if err != nil { - from = fmt.Sprintf("could not be detected: %v", err) - } else { - from = call.From.Hex() - } - var attributes = []attribute.KeyValue{ - attribute.String(hashAttr, transaction.Hash().Hex()), - attribute.String(fromAttr, from), - attribute.String(toAttr, addressPtrToString(transaction.To())), - attribute.String(dataAttr, fmt.Sprintf("%x", transaction.Data())), - attribute.String(valueAttr, bigPtrToString(transaction.Value())), - // TODO: this could be downcast to int64, but it's unclear how we should handle overflows. - // since this is only for tracing, we can probably ignore it for now. - attribute.Int64(nonceAttr, int64(transaction.Nonce())), - attribute.Int64(gasLimitAttr, int64(transaction.Gas())), - attribute.String(chainIDAttr, bigPtrToString(transaction.ChainId())), - } - - if transaction.Type() == types.LegacyTxType && transaction.GasPrice() != nil { - attributes = append(attributes, attribute.String(gasPriceAttr, bigPtrToString(transaction.GasPrice()))) - } - - if transaction.Type() == types.DynamicFeeTxType && transaction.GasFeeCap() != nil { - attributes = append(attributes, attribute.String(gasFeeCapAttr, bigPtrToString(transaction.GasFeeCap()))) - } - - if transaction.Type() == types.DynamicFeeTxType && transaction.GasTipCap() != nil { - attributes = append(attributes, attribute.String(gasTipCapAttr, bigPtrToString(transaction.GasTipCap()))) - } - - return attributes -} - -const nullFieldAttribute = "null" - -func addressPtrToString(address *common.Address) string { - if address == nil { - return nullFieldAttribute - } - return address.Hex() -} - -func bigPtrToString(num *big.Int) string { - if num == nil { - return nullFieldAttribute - } - return num.String() -} - -// sortTxesByChainID sorts a slice of transactions by nonce. +// sortTxesByChainID sorts a slice of transactions by chain ID and then by nonce within each chain ID group. func sortTxesByChainID(txs []db.TX) map[uint64][]db.TX { - txesByChainID := make(map[uint64][]db.TX) - // put the transactions in a map by chain id + txesByChainID := make(map[uint64][]db.TX) // put the transactions in a map by chain id + for _, t := range txs { txesByChainID[t.ChainId().Uint64()] = append(txesByChainID[t.ChainId().Uint64()], t) } diff --git a/ethergo/submitter/util_test.go b/ethergo/submitter/util_test.go index dc4b0a4d99..d722b98260 100644 --- a/ethergo/submitter/util_test.go +++ b/ethergo/submitter/util_test.go @@ -1,197 +1,21 @@ package submitter_test import ( - "context" "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/google/go-cmp/cmp" - "github.com/synapsecns/sanguine/core" - "github.com/synapsecns/sanguine/core/testsuite" + "github.com/stretchr/testify/assert" "github.com/synapsecns/sanguine/ethergo/backends/simulated" "github.com/synapsecns/sanguine/ethergo/mocks" "github.com/synapsecns/sanguine/ethergo/submitter" "github.com/synapsecns/sanguine/ethergo/submitter/db" "github.com/synapsecns/sanguine/ethergo/util" - "go.opentelemetry.io/otel/attribute" - "gotest.tools/assert" "math/big" "math/rand" "sync" - "testing" "time" ) -func TestCopyTransactOpts(t *testing.T) { - // Test case 1: All fields populated - opts1 := &bind.TransactOpts{ - From: common.HexToAddress("0x1234567890123456789012345678901234567890"), - Nonce: big.NewInt(1), - Signer: nil, - Value: big.NewInt(100), - GasPrice: big.NewInt(200), - GasFeeCap: big.NewInt(300), - GasTipCap: big.NewInt(400), - GasLimit: 500, - Context: context.Background(), - NoSend: true, - } - - copyOpts1 := submitter.CopyTransactOpts(opts1) - assertTransactOptsEquality(t, opts1, copyOpts1) - - // Test case 2: Some fields populated, others nil - opts2 := &bind.TransactOpts{ - Nonce: nil, - Signer: nil, - Value: nil, - GasPrice: nil, - GasFeeCap: big.NewInt(300), - GasTipCap: big.NewInt(400), - GasLimit: 500, - Context: context.Background(), - NoSend: true, - } - - copyOpts2 := submitter.CopyTransactOpts(opts2) - assertTransactOptsEquality(t, opts2, copyOpts2) - - // Test case 3: All fields nil - opts3 := &bind.TransactOpts{ - Nonce: nil, - Signer: nil, - Value: nil, - GasPrice: nil, - GasFeeCap: nil, - GasTipCap: nil, - GasLimit: 0, - Context: nil, - NoSend: true, - } - - copyOpts3 := submitter.CopyTransactOpts(opts3) - assertTransactOptsEquality(t, opts3, copyOpts3) -} - -func assertTransactOptsEquality(tb testing.TB, toA, toB *bind.TransactOpts) { - tb.Helper() - // Check that the pointer values of the big integer fields are different - assertBigIntsCopiedEqual(tb, toA.Nonce, toB.Nonce, "Nonce") - assertBigIntsCopiedEqual(tb, toA.Value, toB.Value, "Value") - assertBigIntsCopiedEqual(tb, toA.GasPrice, toB.GasPrice, "GasPrice") - assertBigIntsCopiedEqual(tb, toA.GasFeeCap, toB.GasFeeCap, "GasFeeCap") - assertBigIntsCopiedEqual(tb, toA.GasTipCap, toB.GasTipCap, "GasFeeCap") - assert.DeepEqual(tb, toA, toB, testsuite.BigIntComparer(), cmp.AllowUnexported(context.Background())) -} - -// assertBigIntsCopiedEqual checks that the given big.Ints are equal and that -// they have different pointers. -func assertBigIntsCopiedEqual(tb testing.TB, original *big.Int, newVal *big.Int, fieldName string) { - tb.Helper() - if original == nil && newVal == nil { - return - } - - if core.ArePointersEqual(original, newVal) { - tb.Errorf("%s has same pointer as original", fieldName) - } - - if original.Cmp(newVal) != 0 { - tb.Errorf("%s is not equal", fieldName) - } -} - -func TestAddressPtrToString(t *testing.T) { - // Test case 1: Address is nil - var address *common.Address - assert.Equal(t, submitter.AddressPtrToString(address), submitter.NullFieldAttribute) - - // Test case 2: Address is not nil - address = core.PtrTo[common.Address](common.HexToAddress("0x1234567890123456789012345678901234567890")) - assert.Equal(t, submitter.AddressPtrToString(address), "0x1234567890123456789012345678901234567890") -} - -func TestBigPtrToString(t *testing.T) { - // Test case: num is nil - var num *big.Int - expected := submitter.NullFieldAttribute - result := submitter.BigPtrToString(num) - if result != expected { - t.Errorf("bigPtrToString(nil) = %q; want %q", result, expected) - } - - // Test case: num is an integer - num = big.NewInt(123) - expected = "123" - result = submitter.BigPtrToString(num) - if result != expected { - t.Errorf("bigPtrToString(123) = %q; want %q", result, expected) - } -} - -func (s *SubmitterSuite) TestTxToAttributesNullFields() { - s.checkEmptyTx(types.NewTx(&types.DynamicFeeTx{})) - s.checkEmptyTx(types.NewTx(&types.LegacyTx{})) -} - -func (s *SubmitterSuite) checkEmptyTx(rawTx *types.Transaction) { - tx := makeAttrMap(rawTx) - - s.Require().Equal(tx[submitter.HashAttr].AsString(), rawTx.Hash().Hex()) - s.Require().Equal(tx[submitter.NonceAttr].AsInt64(), int64(0)) - s.Require().Equal(tx[submitter.GasLimitAttr].AsInt64(), int64(0)) - s.Require().Equal(tx[submitter.ToAttr].AsString(), submitter.NullFieldAttribute) - s.Require().Equal(tx[submitter.ValueAttr].AsString(), "0") - s.Require().Equal(tx[submitter.DataAttr].AsString(), "") - - if rawTx.Type() == types.DynamicFeeTxType { - s.Require().Equal(tx[submitter.GasTipCapAttr].AsString(), "0") - s.Require().Equal(tx[submitter.GasFeeCapAttr].AsString(), "0") - } - if rawTx.Type() == types.LegacyTxType { - s.Require().Equal(tx[submitter.GasPriceAttr].AsString(), "0") - } -} - -func (s *SubmitterSuite) TestTxToAttributesLegacyTX() { - mockTX := mocks.GetMockTxes(s.GetTestContext(), s.T(), 1, types.LegacyTxType)[0] - mapAttr := makeAttrMap(mockTX) - - s.Require().Equal(mapAttr[submitter.HashAttr].AsString(), mockTX.Hash().String()) - s.Require().Equal(mapAttr[submitter.NonceAttr].AsInt64(), int64(mockTX.Nonce())) - s.Require().Equal(mapAttr[submitter.GasLimitAttr].AsInt64(), int64(mockTX.Gas())) - s.Require().Equal(mapAttr[submitter.ToAttr].AsString(), mockTX.To().String()) - s.Require().Equal(mapAttr[submitter.ValueAttr].AsString(), mockTX.Value().String()) - s.Require().Equal(mapAttr[submitter.DataAttr].AsString(), "") - - s.Require().Equal(mapAttr[submitter.GasPriceAttr].AsString(), mockTX.GasPrice().String()) - _, hasFeeCap := mapAttr[submitter.GasFeeCapAttr] - _, hasTipCap := mapAttr[submitter.GasTipCapAttr] - s.Require().False(hasFeeCap) - s.Require().False(hasTipCap) - s.Require().NotNil(mapAttr[submitter.FromAttr]) -} - -func (s *SubmitterSuite) TestTxToAttributesDynamicTX() { - mockTX := mocks.GetMockTxes(s.GetTestContext(), s.T(), 1, types.DynamicFeeTxType)[0] - mapAttr := makeAttrMap(mockTX) - - s.Require().Equal(mapAttr[submitter.HashAttr].AsString(), mockTX.Hash().String()) - s.Require().Equal(mapAttr[submitter.NonceAttr].AsInt64(), int64(mockTX.Nonce())) - s.Require().Equal(mapAttr[submitter.GasLimitAttr].AsInt64(), int64(mockTX.Gas())) - s.Require().Equal(mapAttr[submitter.ToAttr].AsString(), mockTX.To().String()) - s.Require().Equal(mapAttr[submitter.ValueAttr].AsString(), mockTX.Value().String()) - s.Require().Equal(mapAttr[submitter.DataAttr].AsString(), "") - - s.Require().Equal(mapAttr[submitter.GasFeeCapAttr].AsString(), mockTX.GasFeeCap().String()) - s.Require().Equal(mapAttr[submitter.GasTipCapAttr].AsString(), mockTX.GasTipCap().String()) - _, hasGasPrice := mapAttr[submitter.GasPriceAttr] - s.Require().False(hasGasPrice) - s.Require().NotNil(mapAttr[submitter.FromAttr]) -} - func (s *SubmitterSuite) TestSortTxes() { expected := make(map[uint64][]*types.Transaction) var allTxes []db.TX @@ -274,12 +98,3 @@ func (s *SubmitterSuite) TestGroupTxesByNonce() { } } } - -func makeAttrMap(tx *types.Transaction) map[string]attribute.Value { - mapAttr := make(map[string]attribute.Value) - attr := submitter.TxToAttributes(tx) - for _, a := range attr { - mapAttr[string(a.Key)] = a.Value - } - return mapAttr -} diff --git a/ethergo/util/export_test.go b/ethergo/util/export_test.go index cb7255c762..fc357be3ab 100644 --- a/ethergo/util/export_test.go +++ b/ethergo/util/export_test.go @@ -1,6 +1,9 @@ package util -import "math/big" +import ( + "github.com/ethereum/go-ethereum/common" + "math/big" +) func MakeOptions(options ...CopyOption) TestCopyOptions { return makeOptions(options...) @@ -37,3 +40,36 @@ func (c copyOptions) GasTipCap() *big.Int { func (c copyOptions) TxType() *uint8 { return c.txType } + +// NullFieldAttribute is a constant used to test the null field attribute. +// it exports the underlying constant for testing. +const NullFieldAttribute = nullFieldAttribute + +func AddressPtrToString(address *common.Address) string { + return addressPtrToString(address) +} + +const ( + // HashAttr exports hashAttr for testing. + HashAttr = hashAttr + // FromAttr exports fromAttr for testing. + FromAttr = fromAttr + // ToAttr exports toAttr for testing. + ToAttr = toAttr + // DataAttr exports dataAttr for testing. + DataAttr = dataAttr + // ValueAttr exports valueAttr for testing. + ValueAttr = valueAttr + // NonceAttr exports nonceAttr for testing. + NonceAttr = nonceAttr + // GasLimitAttr exports gasLimitAttr for testing. + GasLimitAttr = gasLimitAttr + // ChainIDAttr exports chainIDAttr for testing. + ChainIDAttr = chainIDAttr + // GasPriceAttr exports gasPriceAttr for testing. + GasPriceAttr = gasPriceAttr + // GasFeeCapAttr exports gasFeeCapAttr for testing. + GasFeeCapAttr = gasFeeCapAttr + // GasTipCapAttr exports gasTipCapAttr for testing. + GasTipCapAttr = gasTipCapAttr +) diff --git a/ethergo/util/transactor.go b/ethergo/util/transactor.go new file mode 100644 index 0000000000..7aaf7902e2 --- /dev/null +++ b/ethergo/util/transactor.go @@ -0,0 +1,97 @@ +package util + +import ( + "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/synapsecns/sanguine/core" + "go.opentelemetry.io/otel/attribute" + "math/big" +) + +// CopyTransactOpts creates a deep copy of the given TransactOpts struct +// with big ints wrapped in core.CopyBigInt(). +func CopyTransactOpts(opts *bind.TransactOpts) *bind.TransactOpts { + copyOpts := &bind.TransactOpts{ + From: opts.From, + Nonce: core.CopyBigInt(opts.Nonce), + Signer: opts.Signer, + Value: core.CopyBigInt(opts.Value), + GasPrice: core.CopyBigInt(opts.GasPrice), + GasFeeCap: core.CopyBigInt(opts.GasFeeCap), + GasTipCap: core.CopyBigInt(opts.GasTipCap), + GasLimit: opts.GasLimit, + Context: opts.Context, + NoSend: opts.NoSend, + } + return copyOpts +} + +const ( + hashAttr = "tx.Hash" + fromAttr = "tx.From" + toAttr = "tx.To" + dataAttr = "tx.Data" + valueAttr = "tx.Value" + nonceAttr = "tx.Nonce" + gasLimitAttr = "tx.GasLimit" + chainIDAttr = "tx.ChainID" + gasPriceAttr = "tx.GasPrice" + gasFeeCapAttr = "tx.GasFeeCap" + gasTipCapAttr = "tx.GasTipCap" +) + +// TxToAttributes converts a transaction to a slice of attribute.KeyValue. +func TxToAttributes(transaction *types.Transaction) []attribute.KeyValue { + var from string + call, err := TxToCall(transaction) + if err != nil { + from = fmt.Sprintf("could not be detected: %v", err) + } else { + from = call.From.Hex() + } + var attributes = []attribute.KeyValue{ + attribute.String(hashAttr, transaction.Hash().Hex()), + attribute.String(fromAttr, from), + attribute.String(toAttr, addressPtrToString(transaction.To())), + attribute.String(dataAttr, fmt.Sprintf("%x", transaction.Data())), + attribute.String(valueAttr, BigPtrToString(transaction.Value())), + // TODO: this could be downcast to int64, but it's unclear how we should handle overflows. + // since this is only for tracing, we can probably ignore it for now. + attribute.Int64(nonceAttr, int64(transaction.Nonce())), + attribute.Int64(gasLimitAttr, int64(transaction.Gas())), + attribute.String(chainIDAttr, BigPtrToString(transaction.ChainId())), + } + + if transaction.Type() == types.LegacyTxType && transaction.GasPrice() != nil { + attributes = append(attributes, attribute.String(gasPriceAttr, BigPtrToString(transaction.GasPrice()))) + } + + if transaction.Type() == types.DynamicFeeTxType && transaction.GasFeeCap() != nil { + attributes = append(attributes, attribute.String(gasFeeCapAttr, BigPtrToString(transaction.GasFeeCap()))) + } + + if transaction.Type() == types.DynamicFeeTxType && transaction.GasTipCap() != nil { + attributes = append(attributes, attribute.String(gasTipCapAttr, BigPtrToString(transaction.GasTipCap()))) + } + + return attributes +} + +const nullFieldAttribute = "null" + +func addressPtrToString(address *common.Address) string { + if address == nil { + return nullFieldAttribute + } + return address.Hex() +} + +// BigPtrToString converts a big.Int pointer to a string. +func BigPtrToString(num *big.Int) string { + if num == nil { + return nullFieldAttribute + } + return num.String() +} diff --git a/ethergo/util/transactor_test.go b/ethergo/util/transactor_test.go new file mode 100644 index 0000000000..9b370cd0be --- /dev/null +++ b/ethergo/util/transactor_test.go @@ -0,0 +1,194 @@ +package util_test + +import ( + "context" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/google/go-cmp/cmp" + "github.com/synapsecns/sanguine/core" + "github.com/synapsecns/sanguine/core/testsuite" + "github.com/synapsecns/sanguine/ethergo/mocks" + "github.com/synapsecns/sanguine/ethergo/util" + "go.opentelemetry.io/otel/attribute" + "gotest.tools/assert" + "math/big" + "testing" +) + +func TestCopyTransactOpts(t *testing.T) { + // Test case 1: All fields populated + opts1 := &bind.TransactOpts{ + From: common.HexToAddress("0x1234567890123456789012345678901234567890"), + Nonce: big.NewInt(1), + Signer: nil, + Value: big.NewInt(100), + GasPrice: big.NewInt(200), + GasFeeCap: big.NewInt(300), + GasTipCap: big.NewInt(400), + GasLimit: 500, + Context: context.Background(), + NoSend: true, + } + + copyOpts1 := util.CopyTransactOpts(opts1) + assertTransactOptsEquality(t, opts1, copyOpts1) + + // Test case 2: Some fields populated, others nil + opts2 := &bind.TransactOpts{ + Nonce: nil, + Signer: nil, + Value: nil, + GasPrice: nil, + GasFeeCap: big.NewInt(300), + GasTipCap: big.NewInt(400), + GasLimit: 500, + Context: context.Background(), + NoSend: true, + } + + copyOpts2 := util.CopyTransactOpts(opts2) + assertTransactOptsEquality(t, opts2, copyOpts2) + + // Test case 3: All fields nil + opts3 := &bind.TransactOpts{ + Nonce: nil, + Signer: nil, + Value: nil, + GasPrice: nil, + GasFeeCap: nil, + GasTipCap: nil, + GasLimit: 0, + Context: nil, + NoSend: true, + } + + copyOpts3 := util.CopyTransactOpts(opts3) + assertTransactOptsEquality(t, opts3, copyOpts3) +} + +func assertTransactOptsEquality(tb testing.TB, toA, toB *bind.TransactOpts) { + tb.Helper() + // Check that the pointer values of the big integer fields are different + assertBigIntsCopiedEqual(tb, toA.Nonce, toB.Nonce, "Nonce") + assertBigIntsCopiedEqual(tb, toA.Value, toB.Value, "Value") + assertBigIntsCopiedEqual(tb, toA.GasPrice, toB.GasPrice, "GasPrice") + assertBigIntsCopiedEqual(tb, toA.GasFeeCap, toB.GasFeeCap, "GasFeeCap") + assertBigIntsCopiedEqual(tb, toA.GasTipCap, toB.GasTipCap, "GasTipCap") + assert.DeepEqual(tb, toA, toB, testsuite.BigIntComparer(), cmp.AllowUnexported(context.Background())) +} + +// assertBigIntsCopiedEqual checks that the given big.Ints are equal and that +// they have different pointers. +func assertBigIntsCopiedEqual(tb testing.TB, original *big.Int, newVal *big.Int, fieldName string) { + tb.Helper() + if original == nil && newVal == nil { + return + } + + if core.ArePointersEqual(original, newVal) { + tb.Errorf("%s has same pointer as original", fieldName) + } + + if original.Cmp(newVal) != 0 { + tb.Errorf("%s is not equal", fieldName) + } +} + +func TestAddressPtrToString(t *testing.T) { + // Test case 1: Address is nil + var address *common.Address + assert.Equal(t, util.AddressPtrToString(address), util.NullFieldAttribute) + + // Test case 2: Address is not nil + address = core.PtrTo[common.Address](common.HexToAddress("0x1234567890123456789012345678901234567890")) + assert.Equal(t, util.AddressPtrToString(address), "0x1234567890123456789012345678901234567890") +} + +func TestBigPtrToString(t *testing.T) { + // Test case: num is nil + var num *big.Int + expected := util.NullFieldAttribute + result := util.BigPtrToString(num) + if result != expected { + t.Errorf("BigPtrToString(nil) = %q; want %q", result, expected) + } + + // Test case: num is an integer + num = big.NewInt(123) + expected = "123" + result = util.BigPtrToString(num) + if result != expected { + t.Errorf("BigPtrToString(123) = %q; want %q", result, expected) + } +} + +func (s *UtilSuite) TestTxToAttributesNullFields() { + s.checkEmptyTx(types.NewTx(&types.DynamicFeeTx{})) + s.checkEmptyTx(types.NewTx(&types.LegacyTx{})) +} + +func (s *UtilSuite) checkEmptyTx(rawTx *types.Transaction) { + tx := makeAttrMap(rawTx) + + s.Require().Equal(tx[util.HashAttr].AsString(), rawTx.Hash().Hex()) + s.Require().Equal(tx[util.NonceAttr].AsInt64(), int64(0)) + s.Require().Equal(tx[util.GasLimitAttr].AsInt64(), int64(0)) + s.Require().Equal(tx[util.ToAttr].AsString(), util.NullFieldAttribute) + s.Require().Equal(tx[util.ValueAttr].AsString(), "0") + s.Require().Equal(tx[util.DataAttr].AsString(), "") + + if rawTx.Type() == types.DynamicFeeTxType { + s.Require().Equal(tx[util.GasTipCapAttr].AsString(), "0") + s.Require().Equal(tx[util.GasFeeCapAttr].AsString(), "0") + } + if rawTx.Type() == types.LegacyTxType { + s.Require().Equal(tx[util.GasPriceAttr].AsString(), "0") + } +} + +func (s *UtilSuite) TestTxToAttributesLegacyTX() { + mockTX := mocks.GetMockTxes(s.GetTestContext(), s.T(), 1, types.LegacyTxType)[0] + mapAttr := makeAttrMap(mockTX) + + s.Require().Equal(mapAttr[util.HashAttr].AsString(), mockTX.Hash().String()) + s.Require().Equal(mapAttr[util.NonceAttr].AsInt64(), int64(mockTX.Nonce())) + s.Require().Equal(mapAttr[util.GasLimitAttr].AsInt64(), int64(mockTX.Gas())) + s.Require().Equal(mapAttr[util.ToAttr].AsString(), mockTX.To().String()) + s.Require().Equal(mapAttr[util.ValueAttr].AsString(), mockTX.Value().String()) + s.Require().Equal(mapAttr[util.DataAttr].AsString(), "") + + s.Require().Equal(mapAttr[util.GasPriceAttr].AsString(), mockTX.GasPrice().String()) + _, hasFeeCap := mapAttr[util.GasFeeCapAttr] + _, hasTipCap := mapAttr[util.GasTipCapAttr] + s.Require().False(hasFeeCap) + s.Require().False(hasTipCap) + s.Require().NotNil(mapAttr[util.FromAttr]) +} + +func (s *UtilSuite) TestTxToAttributesDynamicTX() { + mockTX := mocks.GetMockTxes(s.GetTestContext(), s.T(), 1, types.DynamicFeeTxType)[0] + mapAttr := makeAttrMap(mockTX) + + s.Require().Equal(mapAttr[util.HashAttr].AsString(), mockTX.Hash().String()) + s.Require().Equal(mapAttr[util.NonceAttr].AsInt64(), int64(mockTX.Nonce())) + s.Require().Equal(mapAttr[util.GasLimitAttr].AsInt64(), int64(mockTX.Gas())) + s.Require().Equal(mapAttr[util.ToAttr].AsString(), mockTX.To().String()) + s.Require().Equal(mapAttr[util.ValueAttr].AsString(), mockTX.Value().String()) + s.Require().Equal(mapAttr[util.DataAttr].AsString(), "") + + s.Require().Equal(mapAttr[util.GasFeeCapAttr].AsString(), mockTX.GasFeeCap().String()) + s.Require().Equal(mapAttr[util.GasTipCapAttr].AsString(), mockTX.GasTipCap().String()) + _, hasGasPrice := mapAttr[util.GasPriceAttr] + s.Require().False(hasGasPrice) + s.Require().NotNil(mapAttr[util.FromAttr]) +} + +func makeAttrMap(tx *types.Transaction) map[string]attribute.Value { + mapAttr := make(map[string]attribute.Value) + attr := util.TxToAttributes(tx) + for _, a := range attr { + mapAttr[string(a.Key)] = a.Value + } + return mapAttr +} diff --git a/services/cctp-relayer/go.mod b/services/cctp-relayer/go.mod index acbf3a3e2f..eb96f3af01 100644 --- a/services/cctp-relayer/go.mod +++ b/services/cctp-relayer/go.mod @@ -47,7 +47,7 @@ require ( github.com/VictoriaMetrics/fastcache v1.6.0 // indirect github.com/acomagu/bufpipe v1.0.4 // indirect github.com/agnivade/levenshtein v1.1.1 // indirect - github.com/andybalholm/brotli v1.0.4 // indirect + github.com/andybalholm/brotli v1.0.5 // indirect github.com/aws/aws-sdk-go-v2 v1.18.0 // indirect github.com/aws/aws-sdk-go-v2/config v1.18.21 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.13.20 // indirect @@ -168,7 +168,7 @@ require ( github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a // indirect github.com/keep-network/keep-common v1.7.1-0.20211012131917-7102d7b9c6a0 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/klauspost/compress v1.15.12 // indirect + github.com/klauspost/compress v1.16.0 // indirect github.com/klauspost/cpuid/v2 v2.2.4 // indirect github.com/leodido/go-urn v1.2.4 // indirect github.com/lmittmann/w3 v0.10.0 // indirect diff --git a/services/cctp-relayer/go.sum b/services/cctp-relayer/go.sum index 95cb711ae1..c8bbce7d91 100644 --- a/services/cctp-relayer/go.sum +++ b/services/cctp-relayer/go.sum @@ -134,8 +134,9 @@ github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKS github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -774,8 +775,8 @@ github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6 github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= -github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= diff --git a/services/omnirpc/go.mod b/services/omnirpc/go.mod index 0bc01d8863..fa2aaf3f6c 100644 --- a/services/omnirpc/go.mod +++ b/services/omnirpc/go.mod @@ -59,7 +59,7 @@ require ( github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 // indirect github.com/VictoriaMetrics/fastcache v1.6.0 // indirect github.com/acomagu/bufpipe v1.0.4 // indirect - github.com/andybalholm/brotli v1.0.4 // indirect + github.com/andybalholm/brotli v1.0.5 // indirect github.com/badoux/checkmail v0.0.0-20181210160741-9661bd69e9ad // indirect github.com/benbjohnson/immutable v0.4.3 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -150,7 +150,7 @@ require ( github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a // indirect github.com/keep-network/keep-common v1.7.1-0.20211012131917-7102d7b9c6a0 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/klauspost/compress v1.15.12 // indirect + github.com/klauspost/compress v1.16.0 // indirect github.com/klauspost/cpuid/v2 v2.2.4 // indirect github.com/leodido/go-urn v1.2.4 // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect diff --git a/services/omnirpc/go.sum b/services/omnirpc/go.sum index e9cff36b12..2fa4cdfdca 100644 --- a/services/omnirpc/go.sum +++ b/services/omnirpc/go.sum @@ -116,8 +116,9 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -706,8 +707,8 @@ github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6 github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= -github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= diff --git a/services/scribe/go.mod b/services/scribe/go.mod index ba81b355da..51d7e2b236 100644 --- a/services/scribe/go.mod +++ b/services/scribe/go.mod @@ -83,7 +83,7 @@ require ( github.com/acomagu/bufpipe v1.0.4 // indirect github.com/agnivade/levenshtein v1.1.1 // indirect github.com/alecthomas/chroma v0.7.1 // indirect - github.com/andybalholm/brotli v1.0.4 // indirect + github.com/andybalholm/brotli v1.0.5 // indirect github.com/badoux/checkmail v0.0.0-20181210160741-9661bd69e9ad // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/briandowns/spinner v1.6.1 // indirect @@ -185,7 +185,7 @@ require ( github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a // indirect github.com/keep-network/keep-common v1.7.1-0.20211012131917-7102d7b9c6a0 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/klauspost/compress v1.15.12 // indirect + github.com/klauspost/compress v1.16.0 // indirect github.com/klauspost/cpuid/v2 v2.2.4 // indirect github.com/kyokomi/emoji/v2 v2.2.8 // indirect github.com/leodido/go-urn v1.2.4 // indirect diff --git a/services/scribe/go.sum b/services/scribe/go.sum index cc7aa9b484..faeba00347 100644 --- a/services/scribe/go.sum +++ b/services/scribe/go.sum @@ -139,8 +139,9 @@ github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKS github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -752,8 +753,8 @@ github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6 github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= -github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= diff --git a/services/sinner/go.mod b/services/sinner/go.mod index 2786cbfb24..1d44c975a0 100644 --- a/services/sinner/go.mod +++ b/services/sinner/go.mod @@ -71,7 +71,7 @@ require ( github.com/alecthomas/chroma v0.7.1 // indirect github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 // indirect github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 // indirect - github.com/andybalholm/brotli v1.0.4 // indirect + github.com/andybalholm/brotli v1.0.5 // indirect github.com/aws/aws-sdk-go-v2 v1.18.0 // indirect github.com/aws/aws-sdk-go-v2/config v1.18.21 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.13.20 // indirect @@ -195,7 +195,7 @@ require ( github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a // indirect github.com/keep-network/keep-common v1.7.1-0.20211012131917-7102d7b9c6a0 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/klauspost/compress v1.15.12 // indirect + github.com/klauspost/compress v1.16.0 // indirect github.com/klauspost/cpuid/v2 v2.2.4 // indirect github.com/kyokomi/emoji/v2 v2.2.8 // indirect github.com/leodido/go-urn v1.2.4 // indirect diff --git a/services/sinner/go.sum b/services/sinner/go.sum index e891a409b9..46a5e3e5a2 100644 --- a/services/sinner/go.sum +++ b/services/sinner/go.sum @@ -146,8 +146,9 @@ github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKS github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -809,8 +810,8 @@ github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6 github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= -github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=