From 1aed9a07274d2f7c74b7d49b1d2cb4a25ba7bdee Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Fri, 17 Jan 2025 13:26:04 -0300 Subject: [PATCH 01/31] chore: init of copying relayer msgs --- clientcontroller/babylon.go | 16 + clientcontroller/babylon_msg.go | 749 ++++++++++++++++++++++++++++++++ 2 files changed, 765 insertions(+) create mode 100644 clientcontroller/babylon_msg.go diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 2b7efaa..c3fae18 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -156,6 +156,22 @@ func (bc *BabylonController) reliablySendMsgs(msgs []sdk.Msg) (*provider.Relayer ) } +func (bc *BabylonController) reliablySendMsgsAsMultipleTxs(msgs []sdk.Msg) (*provider.RelayerTxResponse, error) { + // ctx := context.Background() + + // c := bc.bbnClient.GetConfig() + // c.acc + + return nil, nil + // bc.bbnClient.SendMsgToMempool() + // return bc.bbnClient.ReliablySendMsgs( + // context.Background(), + // msgs, + // expectedErrors, + // unrecoverableErrors, + // ) +} + // SubmitCovenantSigs submits the Covenant signature via a MsgAddCovenantSig to Babylon if the daemon runs in Covenant mode // it returns tx hash and error func (bc *BabylonController) SubmitCovenantSigs(covSigs []*types.CovenantSigs) (*types.TxResponse, error) { diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go new file mode 100644 index 0000000..02a20c4 --- /dev/null +++ b/clientcontroller/babylon_msg.go @@ -0,0 +1,749 @@ +package clientcontroller + +import ( + "context" + "fmt" + "math" + "os" + "path" + "strings" + "sync" + "time" + + "errors" + + sdkerrors "cosmossdk.io/errors" + "cosmossdk.io/store/rootmulti" + "github.com/avast/retry-go/v4" + bbn "github.com/babylonlabs-io/babylon/app" + "github.com/babylonlabs-io/babylon/client/config" + abci "github.com/cometbft/cometbft/abci/types" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + legacyerrors "github.com/cosmos/cosmos-sdk/types/errors" + txtypes "github.com/cosmos/cosmos-sdk/types/tx" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + chantypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" + "github.com/cosmos/relayer/v2/relayer/provider" + "github.com/juju/fslock" + abcistrange "github.com/strangelove-ventures/cometbft-client/abci/types" + strangeloveclient "github.com/strangelove-ventures/cometbft-client/client" + rpcclient "github.com/strangelove-ventures/cometbft-client/rpc/client" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +var ( + rtyAttNum = uint(5) + rtyAtt = retry.Attempts(rtyAttNum) + rtyDel = retry.Delay(time.Millisecond * 400) + rtyErr = retry.LastErrorOnly(true) + defaultBroadcastWaitTimeout = 10 * time.Minute + spTag = "send_packet" + waTag = "write_acknowledgement" + srcChanTag = "packet_src_channel" + dstChanTag = "packet_dst_channel" +) + +func reliablySendMsgsAsMultipleTxs( + cfg *config.BabylonConfig, + msgs []sdk.Msg, +) error { + + c, err := strangeloveclient.NewClient(cfg.RPCAddr, cfg.Timeout) + if err != nil { + return err + } + + return nil +} + +// ReliablySendMsgs reliably sends a list of messages to the chain. +// It utilizes a file lock as well as a keyring lock to ensure atomic access. +func ReliablySendMsgs( + ctx context.Context, + logger *zap.Logger, + cfg *config.BabylonConfig, + msgs []sdk.Msg, + expectedErrors, unrecoverableErrors []*errors.Error, +) (*sdk.TxResponse, error) { + var ( + rlyResp *sdk.TxResponse + callbackErr error + wg sync.WaitGroup + ) + + callback := func(rtr *sdk.TxResponse, err error) { + rlyResp = rtr + callbackErr = err + wg.Done() + } + + wg.Add(1) + + if err := retry.Do(func() error { + var sendMsgErr error + krErr := AccessKeyWithLock(cfg.KeyDirectory, func() { + sendMsgErr = c.provider.SendMessagesToMempool(ctx, msgs, "", ctx, []func(*sdk.TxResponse, error){callback}) + }) + if krErr != nil { + logger.Error("unrecoverable err when submitting the tx, skip retrying", zap.Error(krErr)) + return retry.Unrecoverable(krErr) + } + if sendMsgErr != nil { + if ErrorContained(sendMsgErr, unrecoverableErrors) { + logger.Error("unrecoverable err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) + return retry.Unrecoverable(sendMsgErr) + } + if ErrorContained(sendMsgErr, expectedErrors) { + // this is necessary because if err is returned + // the callback function will not be executed so + // that the inside wg.Done will not be executed + wg.Done() + logger.Error("expected err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) + return nil + } + return sendMsgErr + } + return nil + }, retry.Context(ctx), rtyAtt, rtyDel, rtyErr, retry.OnRetry(func(n uint, err error) { + logger.Debug("retrying", zap.Uint("attempt", n+1), zap.Uint("max_attempts", rtyAttNum), zap.Error(err)) + })); err != nil { + return nil, err + } + + wg.Wait() + + if callbackErr != nil { + if ErrorContained(callbackErr, expectedErrors) { + return nil, nil + } + return nil, callbackErr + } + + if rlyResp == nil { + // this case could happen if the error within the retry is an expected error + return nil, nil + } + + if rlyResp.Code != 0 { + return rlyResp, fmt.Errorf("transaction failed with code: %d", rlyResp.Code) + } + + return rlyResp, nil +} + +// SendMessagesToMempool simulates and broadcasts a transaction with the given msgs and memo. +// This method will return once the transaction has entered the mempool. +// In an async goroutine, will wait for the tx to be included in the block unless asyncCtx exits. +// If there is no error broadcasting, the asyncCallback will be called with success/failure of the wait for block inclusion. +func SendMessagesToMempool( + ctx context.Context, + cfg *config.BabylonConfig, + cometClient client.CometRPC, + rpcClient *strangeloveclient.Client, + ar client.AccountRetriever, + + msgs []sdk.Msg, + memo string, + + txSignerKey string, + sequence uint64, + + asyncCtx context.Context, + asyncCallbacks []func(sdk.TxResponse, error), +) error { + + txBytes, fees, err := BuildMessages( + ctx, cfg, cometClient, rpcClient, ar, msgs, memo, 0, txSignerKey, sequence, + ) + if err != nil { + return err + } + + if err := cc.broadcastTx(ctx, txBytes, msgs, fees, asyncCtx, defaultBroadcastWaitTimeout, asyncCallbacks); err != nil { + return err + } + + return nil +} + +func BuildMessages( + ctx context.Context, + cfg *config.BabylonConfig, + cometClient client.CometRPC, + rpcClient *strangeloveclient.Client, + ar client.AccountRetriever, + msgs []sdk.Msg, + memo string, + gas uint64, + txSignerKey string, + sequence uint64, +) ( + txBytes []byte, + fees sdk.Coins, + err error, +) { + encCfg := bbn.GetEncodingConfig() + + keybase, err := keyring.New( + cfg.ChainID, + cfg.KeyringBackend, + cfg.KeyDirectory, + os.Stdin, + encCfg.Codec, + ) + if err != nil { + return nil, sdk.Coins{}, err + } + + cliCtx := client.Context{}.WithClient(cometClient). + WithInterfaceRegistry(encCfg.InterfaceRegistry). + WithChainID(cfg.ChainID). + WithCodec(encCfg.Codec) + + txf := TxFactory(cfg, ar, encCfg.TxConfig, keybase) + txf, err = PrepareFactory(cliCtx, txf, keybase, txSignerKey) + if err != nil { + return nil, sdk.Coins{}, err + } + + if memo != "" { + txf = txf.WithMemo(memo) + } + + txf = txf.WithSequence(sequence) + + adjusted := gas + + if gas == 0 { + _, adjusted, err = CalculateGas(ctx, rpcClient, keybase, txf, txSignerKey, cfg.GasAdjustment, msgs...) + + if err != nil { + return nil, sdk.Coins{}, err + } + } + + // Set the gas amount on the transaction factory + txf = txf.WithGas(adjusted) + + // Build the transaction builder + txb, err := txf.BuildUnsignedTx(msgs...) + if err != nil { + return nil, sdk.Coins{}, err + } + + if err = tx.Sign(ctx, txf, txSignerKey, txb, false); err != nil { + return nil, sdk.Coins{}, err + } + + tx := txb.GetTx() + fees = tx.GetFee() + + // Generate the transaction bytes + txBytes, err = encCfg.TxConfig.TxEncoder()(tx) + if err != nil { + return nil, sdk.Coins{}, err + } + + return txBytes, fees, nil +} + +// BroadcastTx broadcasts a transaction with the given raw bytes and then, in an async goroutine, waits for the tx to be included in the block. +// The wait will end after either the asyncTimeout has run out or the asyncCtx exits. +// If there is no error broadcasting, the asyncCallback will be called with success/failure of the wait for block inclusion. +func BroadcastTx( + ctx context.Context, // context for tx broadcast + logger *zap.Logger, + cfg *config.BabylonConfig, + + rpcClient *strangeloveclient.Client, + tx []byte, // raw tx to be broadcasted + msgs []provider.RelayerMessage, // used for logging only + fees sdk.Coins, // used for metrics + + asyncCtx context.Context, // context for async wait for block inclusion after successful tx broadcast + asyncTimeout time.Duration, // timeout for waiting for block inclusion + asyncCallbacks []func(*provider.RelayerTxResponse, error), // callback for success/fail of the wait for block inclusion +) error { + res, err := rpcClient.BroadcastTxSync(ctx, tx) + isErr := err != nil + isFailed := res != nil && res.Code != 0 + if isErr || isFailed { + if isErr && res == nil { + // There are some cases where BroadcastTxSync will return an error but the associated + // ResultBroadcastTx will be nil. + return err + } + rlyResp := &provider.RelayerTxResponse{ + TxHash: res.Hash.String(), + Codespace: res.Codespace, + Code: res.Code, + Data: res.Data.String(), + } + if isFailed { + err = sdkError(res.Codespace, res.Code) + if err == nil { + err = fmt.Errorf("transaction failed to execute: codespace: %s, code: %d, log: %s", res.Codespace, res.Code, res.Log) + } + } + LogFailedTx(logger, cfg.ChainID, rlyResp, err, msgs) + return err + } + + // TODO: maybe we need to check if the node has tx indexing enabled? + // if not, we need to find a new way to block until inclusion in a block + + go cc.waitForTx(asyncCtx, res.Hash, msgs, asyncTimeout, asyncCallbacks) + + return nil +} + +// CalculateGas simulates a tx to generate the appropriate gas settings before broadcasting a tx. +func CalculateGas( + ctx context.Context, + rpcClient *strangeloveclient.Client, + keybase keyring.Keyring, + txf tx.Factory, + signingKey string, + gasAdjustment float64, + msgs ...sdk.Msg, +) (txtypes.SimulateResponse, uint64, error) { + keyInfo, err := keybase.Key(signingKey) + if err != nil { + return txtypes.SimulateResponse{}, 0, err + } + + var txBytes []byte + if err := retry.Do(func() error { + var err error + txBytes, err = BuildSimTx(keyInfo, txf, msgs...) + if err != nil { + return err + } + return nil + }, retry.Context(ctx), rtyAtt, rtyDel, rtyErr); err != nil { + return txtypes.SimulateResponse{}, 0, err + } + + simQuery := abci.RequestQuery{ + Path: "/cosmos.tx.v1beta1.Service/Simulate", + Data: txBytes, + } + + var res abcistrange.ResponseQuery + if err := retry.Do(func() error { + var err error + res, err = QueryABCI(ctx, rpcClient, simQuery) + if err != nil { + return err + } + return nil + }, retry.Context(ctx), rtyAtt, rtyDel, rtyErr); err != nil { + return txtypes.SimulateResponse{}, 0, err + } + + var simRes txtypes.SimulateResponse + if err := simRes.Unmarshal(res.Value); err != nil { + return txtypes.SimulateResponse{}, 0, err + } + + gas, err := AdjustEstimatedGas(gasAdjustment, simRes.GasInfo.GasUsed) + return simRes, gas, err +} + +// waitForTx waits for a transaction to be included in a block, logs success/fail, then invokes callback. +// This is intended to be called as an async goroutine. +func waitForTx( + ctx context.Context, + log *zap.Logger, + txHash []byte, + msgs []provider.RelayerMessage, // used for logging only + waitTimeout time.Duration, + callbacks []func(*provider.RelayerTxResponse, error), +) { + res, err := cc.waitForBlockInclusion(ctx, txHash, waitTimeout) + if err != nil { + log.Error("Failed to wait for block inclusion", zap.Error(err)) + if len(callbacks) > 0 { + for _, cb := range callbacks { + //Call each callback in order since waitForTx is already invoked asyncronously + cb(nil, err) + } + } + return + } + + rlyResp := &provider.RelayerTxResponse{ + Height: res.Height, + TxHash: res.TxHash, + Codespace: res.Codespace, + Code: res.Code, + Data: res.Data, + Events: parseEventsFromTxResponse(res), + } + + // transaction was executed, log the success or failure using the tx response code + // NOTE: error is nil, logic should use the returned error to determine if the + // transaction was successfully executed. + + if res.Code != 0 { + // Check for any registered SDK errors + err := cc.sdkError(res.Codespace, res.Code) + if err == nil { + err = fmt.Errorf("transaction failed to execute: codespace: %s, code: %d, log: %s", res.Codespace, res.Code, res.RawLog) + } + if len(callbacks) > 0 { + for _, cb := range callbacks { + //Call each callback in order since waitForTx is already invoked asyncronously + cb(nil, err) + } + } + LogFailedTx(log, rlyResp, nil, msgs) + return + } + + if len(callbacks) > 0 { + for _, cb := range callbacks { + //Call each callback in order since waitForTx is already invoked asyncronously + cb(rlyResp, nil) + } + } + cc.LogSuccessTx(res, msgs) +} + +func AccessKeyWithLock(keyDir string, accessFunc func()) error { + // use lock file to guard concurrent access to the keyring + lockFilePath := path.Join(keyDir, "keys.lock") + lock := fslock.New(lockFilePath) + if err := lock.Lock(); err != nil { + return fmt.Errorf("failed to acquire file system lock (%s): %w", lockFilePath, err) + } + + // trigger function that access keyring + accessFunc() + + // unlock and release access + if err := lock.Unlock(); err != nil { + return fmt.Errorf("error unlocking file system lock (%s), please manually delete", lockFilePath) + } + + return nil +} + +// QueryABCI performs an ABCI query and returns the appropriate response and error sdk error code. +func QueryABCI(ctx context.Context, rpcClient *strangeloveclient.Client, req abci.RequestQuery) (abcistrange.ResponseQuery, error) { + opts := rpcclient.ABCIQueryOptions{ + Height: req.Height, + Prove: req.Prove, + } + + result, err := rpcClient.ABCIQueryWithOptions(ctx, req.Path, req.Data, opts) + if err != nil { + return abcistrange.ResponseQuery{}, err + } + + if !result.Response.IsOK() { + return abcistrange.ResponseQuery{}, sdkErrorToGRPCError(result.Response.Code, result.Response.Log) + } + + // data from trusted node or subspace query doesn't need verification + if !opts.Prove || !isQueryStoreWithProof(req.Path) { + return result.Response, nil + } + + return result.Response, nil +} + +// isQueryStoreWithProof expects a format like /<queryType>/<storeName>/<subpath> +// queryType must be "store" and subpath must be "key" to require a proof. +func isQueryStoreWithProof(path string) bool { + if !strings.HasPrefix(path, "/") { + return false + } + + paths := strings.SplitN(path[1:], "/", 3) + + switch { + case len(paths) != 3: + return false + case paths[0] != "store": + return false + case rootmulti.RequireProof("/" + paths[2]): + return true + } + + return false +} + +func ErrorContained(err error, errList []*sdkerrors.Error) bool { + for _, e := range errList { + if strings.Contains(err.Error(), e.Error()) { + return true + } + } + + return false +} + +// PrepareFactory mutates the tx factory with the appropriate account number, sequence number, and min gas settings. +func PrepareFactory( + cliCtx client.Context, + txf tx.Factory, + keybase keyring.Keyring, + signingKey string, +) (tx.Factory, error) { + var ( + err error + from sdk.AccAddress + num, seq uint64 + ) + + // Get key address and retry if fail + if err = retry.Do(func() error { + from, err = GetKeyAddressForKey(keybase, signingKey) + if err != nil { + return err + } + return err + }, rtyAtt, rtyDel, rtyErr); err != nil { + return tx.Factory{}, err + } + + cliCtx = cliCtx.WithFromAddress(from) + + // Set the account number and sequence on the transaction factory and retry if fail + if err = retry.Do(func() error { + if err = txf.AccountRetriever().EnsureExists(cliCtx, from); err != nil { + return err + } + return err + }, rtyAtt, rtyDel, rtyErr); err != nil { + return txf, err + } + + // TODO: why this code? this may potentially require another query when we don't want one + initNum, initSeq := txf.AccountNumber(), txf.Sequence() + if initNum == 0 || initSeq == 0 { + if err = retry.Do(func() error { + num, seq, err = txf.AccountRetriever().GetAccountNumberSequence(cliCtx, from) + if err != nil { + return err + } + return err + }, rtyAtt, rtyDel, rtyErr); err != nil { + return txf, err + } + + if initNum == 0 { + txf = txf.WithAccountNumber(num) + } + + if initSeq == 0 { + txf = txf.WithSequence(seq) + } + } + + return txf, nil +} + +func GetKeyAddressForKey(keybase keyring.Keyring, key string) (sdk.AccAddress, error) { + info, err := keybase.Key(key) + if err != nil { + return nil, err + } + return info.GetAddress() +} + +// TxFactory instantiates a new tx factory with the appropriate configuration settings for this chain. +func TxFactory( + cfg *config.BabylonConfig, + ar client.AccountRetriever, + txConf client.TxConfig, + keybase keyring.Keyring, +) tx.Factory { + return tx.Factory{}. + WithAccountRetriever(ar). + WithChainID(cfg.ChainID). + WithTxConfig(txConf). + WithGasAdjustment(cfg.GasAdjustment). + WithGasPrices(cfg.GasPrices). + WithKeybase(keybase). + WithSignMode(SignMode(cfg.SignModeStr)) +} + +func SignMode(signModeStr string) signing.SignMode { + switch signModeStr { + case "direct": + return signing.SignMode_SIGN_MODE_DIRECT + case "amino-json": + return signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON + default: + return signing.SignMode_SIGN_MODE_UNSPECIFIED + } +} + +// BuildSimTx creates an unsigned tx with an empty single signature and returns +// the encoded transaction or an error if the unsigned transaction cannot be built. +func BuildSimTx(info *keyring.Record, txf tx.Factory, msgs ...sdk.Msg) ([]byte, error) { + txb, err := txf.BuildUnsignedTx(msgs...) + if err != nil { + return nil, err + } + + var pk cryptotypes.PubKey = &secp256k1.PubKey{} // use default public key type + + pk, err = info.GetPubKey() + if err != nil { + return nil, err + } + + // Create an empty signature literal as the ante handler will populate with a + // sentinel pubkey. + sig := signing.SignatureV2{ + PubKey: pk, + Data: &signing.SingleSignatureData{ + SignMode: txf.SignMode(), + }, + Sequence: txf.Sequence(), + } + if err := txb.SetSignatures(sig); err != nil { + return nil, err + } + + protoProvider, ok := txb.(protoTxProvider) + if !ok { + return nil, fmt.Errorf("cannot simulate amino tx") + } + + simReq := txtypes.SimulateRequest{Tx: protoProvider.GetProtoTx()} + return simReq.Marshal() +} + +// protoTxProvider is a type which can provide a proto transaction. It is a +// workaround to get access to the wrapper TxBuilder's method GetProtoTx(). +type protoTxProvider interface { + GetProtoTx() *txtypes.Tx +} + +func sdkErrorToGRPCError(code uint32, log string) error { + switch code { + case legacyerrors.ErrInvalidRequest.ABCICode(): + return status.Error(codes.InvalidArgument, log) + case legacyerrors.ErrUnauthorized.ABCICode(): + return status.Error(codes.Unauthenticated, log) + case legacyerrors.ErrKeyNotFound.ABCICode(): + return status.Error(codes.NotFound, log) + default: + return status.Error(codes.Unknown, log) + } +} + +// AdjustEstimatedGas adjusts the estimated gas usage by multiplying it by the gas adjustment factor +// and return estimated gas is higher than max gas error. If the gas usage is zero, the adjusted gas +// is also zero. +func AdjustEstimatedGas(gasAdjustment float64, gasUsed uint64) (uint64, error) { + if gasUsed == 0 { + return gasUsed, nil + } + + gas := gasAdjustment * float64(gasUsed) + if math.IsInf(gas, 1) { + return 0, fmt.Errorf("infinite gas used") + } + return uint64(gas), nil +} + +// sdkError will return the Cosmos SDK registered error for a given codespace/code combo if registered, otherwise nil. +func sdkError(codespace string, code uint32) error { + // ABCIError will return an error other than "unknown" if syncRes.Code is a registered error in syncRes.Codespace + // This catches all of the sdk errors https://github.com/cosmos/cosmos-sdk/blob/f10f5e5974d2ecbf9efc05bc0bfe1c99fdeed4b6/types/errors/errors.go + err := errors.Unwrap(sdkerrors.ABCIError(codespace, code, "error broadcasting transaction")) + if err.Error() != "unknown" { + return err + } + return nil +} + +// LogFailedTx takes the transaction and the messages to create it and logs the appropriate data +func LogFailedTx(log *zap.Logger, chainId string, res *provider.RelayerTxResponse, err error, msgs []provider.RelayerMessage) { + // Include the chain_id + fields := []zapcore.Field{zap.String("chain_id", chainId)} + + // Extract the channels from the events, if present + if res != nil { + channels := getChannelsIfPresent(res.Events) + fields = append(fields, channels...) + } + fields = append(fields, msgTypesField(msgs)) + + if err != nil { + + if errors.Is(err, chantypes.ErrRedundantTx) { + log.Debug("Redundant message(s)", fields...) + return + } + + // Make a copy since we may continue to the warning + errorFields := append(fields, zap.Error(err)) + log.Error( + "Failed sending cosmos transaction", + errorFields..., + ) + + if res == nil { + return + } + } + + if res.Code != 0 { + if sdkErr := cc.sdkError(res.Codespace, res.Code); err != nil { + fields = append(fields, zap.NamedError("sdk_error", sdkErr)) + } + fields = append(fields, zap.Object("response", res)) + cc.log.Warn( + "Sent transaction but received failure response", + fields..., + ) + } +} + +// getChannelsIfPresent scans the events for channel tags +func getChannelsIfPresent(events []provider.RelayerEvent) []zapcore.Field { + channelTags := []string{srcChanTag, dstChanTag} + fields := []zap.Field{} + + // While a transaction may have multiple messages, we just need to first + // pair of channels + foundTag := map[string]struct{}{} + + for _, event := range events { + for _, tag := range channelTags { + for attributeKey, attributeValue := range event.Attributes { + if attributeKey == tag { + // Only append the tag once + // TODO: what if they are different? + if _, ok := foundTag[tag]; !ok { + fields = append(fields, zap.String(tag, attributeValue)) + foundTag[tag] = struct{}{} + } + } + } + } + } + return fields +} + +func msgTypesField(msgs []provider.RelayerMessage) zap.Field { + msgTypes := make([]string, len(msgs)) + for i, m := range msgs { + msgTypes[i] = m.Type() + } + return zap.Strings("msg_types", msgTypes) +} From c8f253a2a0a6fc6384daa43a8b1e797edbbf38dc Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Fri, 17 Jan 2025 23:20:09 -0300 Subject: [PATCH 02/31] chore: build message complete --- clientcontroller/babylon_msg.go | 245 +++++++++++++++++----------- clientcontroller/babylon_msg_log.go | 224 +++++++++++++++++++++++++ 2 files changed, 371 insertions(+), 98 deletions(-) create mode 100644 clientcontroller/babylon_msg_log.go diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go index 02a20c4..7c538ed 100644 --- a/clientcontroller/babylon_msg.go +++ b/clientcontroller/babylon_msg.go @@ -16,10 +16,17 @@ import ( "cosmossdk.io/store/rootmulti" "github.com/avast/retry-go/v4" bbn "github.com/babylonlabs-io/babylon/app" + appparams "github.com/babylonlabs-io/babylon/app/params" "github.com/babylonlabs-io/babylon/client/config" abci "github.com/cometbft/cometbft/abci/types" + "github.com/cometbft/cometbft/crypto/merkle" + "github.com/cometbft/cometbft/libs/bytes" + coretypes "github.com/cometbft/cometbft/rpc/core/types" + tmtypes "github.com/cometbft/cometbft/types" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" @@ -27,14 +34,13 @@ import ( legacyerrors "github.com/cosmos/cosmos-sdk/types/errors" txtypes "github.com/cosmos/cosmos-sdk/types/tx" "github.com/cosmos/cosmos-sdk/types/tx/signing" - chantypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" + rlycosmos "github.com/cosmos/relayer/v2/chains/cosmos" "github.com/cosmos/relayer/v2/relayer/provider" "github.com/juju/fslock" abcistrange "github.com/strangelove-ventures/cometbft-client/abci/types" strangeloveclient "github.com/strangelove-ventures/cometbft-client/client" rpcclient "github.com/strangelove-ventures/cometbft-client/rpc/client" "go.uber.org/zap" - "go.uber.org/zap/zapcore" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -56,22 +62,31 @@ func reliablySendMsgsAsMultipleTxs( msgs []sdk.Msg, ) error { + encCfg := bbn.GetEncodingConfig() + c, err := strangeloveclient.NewClient(cfg.RPCAddr, cfg.Timeout) if err != nil { return err } - return nil + ctx := context.Background() + return ReliablySendMsgs(ctx, cfg) } // ReliablySendMsgs reliably sends a list of messages to the chain. // It utilizes a file lock as well as a keyring lock to ensure atomic access. func ReliablySendMsgs( ctx context.Context, - logger *zap.Logger, cfg *config.BabylonConfig, + logger *zap.Logger, + cometClient client.CometRPC, + rpcClient *strangeloveclient.Client, + encCfg *appparams.EncodingConfig, + ar client.AccountRetriever, + + accSequence uint64, msgs []sdk.Msg, - expectedErrors, unrecoverableErrors []*errors.Error, + expectedErrors, unrecoverableErrors []*sdkerrors.Error, ) (*sdk.TxResponse, error) { var ( rlyResp *sdk.TxResponse @@ -90,7 +105,7 @@ func ReliablySendMsgs( if err := retry.Do(func() error { var sendMsgErr error krErr := AccessKeyWithLock(cfg.KeyDirectory, func() { - sendMsgErr = c.provider.SendMessagesToMempool(ctx, msgs, "", ctx, []func(*sdk.TxResponse, error){callback}) + sendMsgErr = SendMessagesToMempool(ctx, cfg, logger, cometClient, rpcClient, encCfg, ar, msgs, "", accSequence, []func(*sdk.TxResponse, error){callback}) }) if krErr != nil { logger.Error("unrecoverable err when submitting the tx, skip retrying", zap.Error(krErr)) @@ -146,28 +161,30 @@ func ReliablySendMsgs( func SendMessagesToMempool( ctx context.Context, cfg *config.BabylonConfig, + logger *zap.Logger, cometClient client.CometRPC, rpcClient *strangeloveclient.Client, + encCfg *appparams.EncodingConfig, ar client.AccountRetriever, msgs []sdk.Msg, memo string, - txSignerKey string, sequence uint64, - asyncCtx context.Context, - asyncCallbacks []func(sdk.TxResponse, error), + asyncCallbacks []func(*sdk.TxResponse, error), ) error { + txSignerKey := cfg.Key txBytes, fees, err := BuildMessages( - ctx, cfg, cometClient, rpcClient, ar, msgs, memo, 0, txSignerKey, sequence, + ctx, cfg, cometClient, rpcClient, encCfg, ar, msgs, memo, 0, txSignerKey, sequence, ) if err != nil { return err } - if err := cc.broadcastTx(ctx, txBytes, msgs, fees, asyncCtx, defaultBroadcastWaitTimeout, asyncCallbacks); err != nil { + err = BroadcastTx(ctx, logger, cfg, encCfg, rpcClient, txBytes, msgs, fees, ctx, defaultBroadcastWaitTimeout, asyncCallbacks) + if err != nil { return err } @@ -179,6 +196,7 @@ func BuildMessages( cfg *config.BabylonConfig, cometClient client.CometRPC, rpcClient *strangeloveclient.Client, + encCfg *appparams.EncodingConfig, ar client.AccountRetriever, msgs []sdk.Msg, memo string, @@ -190,7 +208,6 @@ func BuildMessages( fees sdk.Coins, err error, ) { - encCfg := bbn.GetEncodingConfig() keybase, err := keyring.New( cfg.ChainID, @@ -262,15 +279,16 @@ func BroadcastTx( ctx context.Context, // context for tx broadcast logger *zap.Logger, cfg *config.BabylonConfig, + encCfg *appparams.EncodingConfig, rpcClient *strangeloveclient.Client, tx []byte, // raw tx to be broadcasted - msgs []provider.RelayerMessage, // used for logging only + msgs []sdk.Msg, // used for logging only fees sdk.Coins, // used for metrics asyncCtx context.Context, // context for async wait for block inclusion after successful tx broadcast asyncTimeout time.Duration, // timeout for waiting for block inclusion - asyncCallbacks []func(*provider.RelayerTxResponse, error), // callback for success/fail of the wait for block inclusion + asyncCallbacks []func(*sdk.TxResponse, error), // callback for success/fail of the wait for block inclusion ) error { res, err := rpcClient.BroadcastTxSync(ctx, tx) isErr := err != nil @@ -299,8 +317,8 @@ func BroadcastTx( // TODO: maybe we need to check if the node has tx indexing enabled? // if not, we need to find a new way to block until inclusion in a block - - go cc.waitForTx(asyncCtx, res.Hash, msgs, asyncTimeout, asyncCallbacks) + protoCdc := codec.NewProtoCodec(encCfg.InterfaceRegistry) + go waitForTx(asyncCtx, logger, rpcClient, protoCdc, encCfg.TxConfig, cfg.ChainID, res.Hash, msgs, asyncTimeout, asyncCallbacks) return nil } @@ -363,12 +381,16 @@ func CalculateGas( func waitForTx( ctx context.Context, log *zap.Logger, + rpcClient *strangeloveclient.Client, + cdc *codec.ProtoCodec, + txConfig client.TxConfig, + chainId string, txHash []byte, - msgs []provider.RelayerMessage, // used for logging only + msgs []sdk.Msg, // used for logging only waitTimeout time.Duration, - callbacks []func(*provider.RelayerTxResponse, error), + callbacks []func(*sdk.TxResponse, error), ) { - res, err := cc.waitForBlockInclusion(ctx, txHash, waitTimeout) + res, err := waitForBlockInclusion(ctx, rpcClient, txConfig, txHash, waitTimeout) if err != nil { log.Error("Failed to wait for block inclusion", zap.Error(err)) if len(callbacks) > 0 { @@ -395,7 +417,7 @@ func waitForTx( if res.Code != 0 { // Check for any registered SDK errors - err := cc.sdkError(res.Codespace, res.Code) + err := sdkError(res.Codespace, res.Code) if err == nil { err = fmt.Errorf("transaction failed to execute: codespace: %s, code: %d, log: %s", res.Codespace, res.Code, res.RawLog) } @@ -405,17 +427,115 @@ func waitForTx( cb(nil, err) } } - LogFailedTx(log, rlyResp, nil, msgs) + LogFailedTx(log, chainId, rlyResp, nil, msgs) return } if len(callbacks) > 0 { for _, cb := range callbacks { //Call each callback in order since waitForTx is already invoked asyncronously - cb(rlyResp, nil) + cb(res, nil) + } + } + LogSuccessTx(log, chainId, cdc, res, msgs) +} + +// waitForBlockInclusion will wait for a transaction to be included in a block, up to waitTimeout or context cancellation. +func waitForBlockInclusion( + ctx context.Context, + rpcClient *strangeloveclient.Client, + txConfig client.TxConfig, + txHash []byte, + waitTimeout time.Duration, +) (*sdk.TxResponse, error) { + exitAfter := time.After(waitTimeout) + for { + select { + case <-exitAfter: + return nil, fmt.Errorf("timed out after: %d; %w", waitTimeout, rlycosmos.ErrTimeoutAfterWaitingForTxBroadcast) + // This fixed poll is fine because it's only for logging and updating prometheus metrics currently. + case <-time.After(time.Millisecond * 100): + res, err := rpcClient.Tx(ctx, txHash, false) + if err == nil { + return mkTxResult(convertResultTx(res), txConfig) + } + if strings.Contains(err.Error(), "transaction indexing is disabled") { + return nil, fmt.Errorf("cannot determine success/failure of tx because transaction indexing is disabled on rpc url") + } + case <-ctx.Done(): + return nil, ctx.Err() + } + } +} + +func convertResultTx(res *strangeloveclient.TxResponse) *coretypes.ResultTx { + return &coretypes.ResultTx{ + Hash: bytes.HexBytes(res.Hash), + Height: res.Height, + Index: res.Index, + TxResult: abci.ExecTxResult{ + Code: res.ExecTx.Code, + Data: res.ExecTx.Data, + Log: res.ExecTx.Log, + Info: res.ExecTx.Info, + GasWanted: res.ExecTx.GasWanted, + GasUsed: res.ExecTx.GasUsed, + Events: converStringEvents(res.ExecTx.Events), + Codespace: res.ExecTx.Codespace, + }, + Tx: tmtypes.Tx(res.Tx), + Proof: tmtypes.TxProof{ + RootHash: bytes.HexBytes(res.Proof.RootHash), + Data: tmtypes.Tx(res.Proof.Data), + Proof: merkle.Proof{ + Total: res.Proof.Proof.Total, + Index: res.Proof.Proof.Index, + LeafHash: res.Proof.Proof.LeafHash, + Aunts: res.Proof.Proof.Aunts, + }, + }, + } +} + +func converStringEvents(events sdk.StringEvents) []abci.Event { + evts := make([]abci.Event, len(events)) + + for i, evt := range events { + attributes := make([]abci.EventAttribute, len(evt.Attributes)) + + for j, attr := range evt.Attributes { + attributes[j] = abci.EventAttribute{ + Key: attr.Key, + Value: attr.Value, + } + } + + evts[i] = abci.Event{ + Type: evt.Type, + Attributes: attributes, } } - cc.LogSuccessTx(res, msgs) + + return evts +} + +// mkTxResult decodes a comet transaction into an SDK TxResponse. +func mkTxResult( + resTx *coretypes.ResultTx, + txConfig client.TxConfig, +) (*sdk.TxResponse, error) { + txbz, err := txConfig.TxDecoder()(resTx.Tx) + if err != nil { + return nil, err + } + + p, ok := txbz.(intoAny) + if !ok { + return nil, fmt.Errorf("expecting a type implementing intoAny, got: %T", txbz) + } + + any := p.AsAny() + return sdk.NewResponseResultTx(resTx, any, ""), nil } func AccessKeyWithLock(keyDir string, accessFunc func()) error { @@ -671,79 +791,8 @@ func sdkError(codespace string, code uint32) error { return nil } -// LogFailedTx takes the transaction and the messages to create it and logs the appropriate data -func LogFailedTx(log *zap.Logger, chainId string, res *provider.RelayerTxResponse, err error, msgs []provider.RelayerMessage) { - // Include the chain_id - fields := []zapcore.Field{zap.String("chain_id", chainId)} - - // Extract the channels from the events, if present - if res != nil { - channels := getChannelsIfPresent(res.Events) - fields = append(fields, channels...) - } - fields = append(fields, msgTypesField(msgs)) - - if err != nil { - - if errors.Is(err, chantypes.ErrRedundantTx) { - log.Debug("Redundant message(s)", fields...) - return - } - - // Make a copy since we may continue to the warning - errorFields := append(fields, zap.Error(err)) - log.Error( - "Failed sending cosmos transaction", - errorFields..., - ) - - if res == nil { - return - } - } - - if res.Code != 0 { - if sdkErr := cc.sdkError(res.Codespace, res.Code); err != nil { - fields = append(fields, zap.NamedError("sdk_error", sdkErr)) - } - fields = append(fields, zap.Object("response", res)) - cc.log.Warn( - "Sent transaction but received failure response", - fields..., - ) - } -} - -// getChannelsIfPresent scans the events for channel tags -func getChannelsIfPresent(events []provider.RelayerEvent) []zapcore.Field { - channelTags := []string{srcChanTag, dstChanTag} - fields := []zap.Field{} - - // While a transaction may have multiple messages, we just need to first - // pair of channels - foundTag := map[string]struct{}{} - - for _, event := range events { - for _, tag := range channelTags { - for attributeKey, attributeValue := range event.Attributes { - if attributeKey == tag { - // Only append the tag once - // TODO: what if they are different? - if _, ok := foundTag[tag]; !ok { - fields = append(fields, zap.String(tag, attributeValue)) - foundTag[tag] = struct{}{} - } - } - } - } - } - return fields -} - -func msgTypesField(msgs []provider.RelayerMessage) zap.Field { - msgTypes := make([]string, len(msgs)) - for i, m := range msgs { - msgTypes[i] = m.Type() - } - return zap.Strings("msg_types", msgTypes) +// Deprecated: this interface is used only internally for scenario we are +// deprecating (StdTxConfig support) +type intoAny interface { + AsAny() *codectypes.Any } diff --git a/clientcontroller/babylon_msg_log.go b/clientcontroller/babylon_msg_log.go new file mode 100644 index 0000000..aeb0ef0 --- /dev/null +++ b/clientcontroller/babylon_msg_log.go @@ -0,0 +1,224 @@ +package clientcontroller + +import ( + "errors" + "reflect" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + typestx "github.com/cosmos/cosmos-sdk/types/tx" + feetypes "github.com/cosmos/ibc-go/v8/modules/apps/29-fee/types" + transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" + chantypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" + "github.com/cosmos/relayer/v2/relayer/provider" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +// LogFailedTx takes the transaction and the messages to create it and logs the appropriate data +func LogFailedTx(log *zap.Logger, chainId string, res *provider.RelayerTxResponse, err error, msgs []sdk.Msg) { + // Include the chain_id + fields := []zapcore.Field{zap.String("chain_id", chainId)} + + // Extract the channels from the events, if present + if res != nil { + channels := getChannelsIfPresent(res.Events) + fields = append(fields, channels...) + } + fields = append(fields, msgTypesField(msgs)) + + if err != nil { + + if errors.Is(err, chantypes.ErrRedundantTx) { + log.Debug("Redundant message(s)", fields...) + return + } + + // Make a copy since we may continue to the warning + errorFields := append(fields, zap.Error(err)) + log.Error( + "Failed sending cosmos transaction", + errorFields..., + ) + + if res == nil { + return + } + } + + if res.Code != 0 { + if sdkErr := sdkError(res.Codespace, res.Code); err != nil { + fields = append(fields, zap.NamedError("sdk_error", sdkErr)) + } + fields = append(fields, zap.Object("response", res)) + log.Warn( + "Sent transaction but received failure response", + fields..., + ) + } +} + +// LogSuccessTx take the transaction and the messages to create it and logs the appropriate data +func LogSuccessTx(log *zap.Logger, chainId string, cdc *codec.ProtoCodec, res *sdk.TxResponse, msgs []sdk.Msg) { + // Include the chain_id + fields := []zapcore.Field{zap.String("chain_id", chainId)} + + // Extract the channels from the events, if present + if res != nil { + events := parseEventsFromTxResponse(res) + fields = append(fields, getChannelsIfPresent(events)...) + } + + // Include the gas used + fields = append(fields, zap.Int64("gas_used", res.GasUsed)) + + var m sdk.Msg + if err := cdc.InterfaceRegistry().UnpackAny(res.Tx, &m); err == nil { + if tx, ok := m.(*typestx.Tx); ok { + fields = append(fields, zap.Stringer("fees", tx.GetFee())) + if feePayer := getFeePayer(log, cdc, tx); feePayer != "" { + fields = append(fields, zap.String("fee_payer", feePayer)) + } + } else { + log.Debug( + "Failed to convert message to Tx type", + zap.Stringer("type", reflect.TypeOf(m)), + ) + } + } else { + log.Debug("Failed to unpack response Tx into sdk.Msg", zap.Error(err)) + } + + // Include the height, msgType, and tx_hash + fields = append(fields, + zap.Int64("height", res.Height), + msgTypesField(msgs), + zap.String("tx_hash", res.TxHash), + ) + + // Log the successful transaction with fields + log.Info( + "Successful transaction", + fields..., + ) +} + +// getChannelsIfPresent scans the events for channel tags +func getChannelsIfPresent(events []provider.RelayerEvent) []zapcore.Field { + channelTags := []string{srcChanTag, dstChanTag} + fields := []zap.Field{} + + // While a transaction may have multiple messages, we just need to first + // pair of channels + foundTag := map[string]struct{}{} + + for _, event := range events { + for _, tag := range channelTags { + for attributeKey, attributeValue := range event.Attributes { + if attributeKey == tag { + // Only append the tag once + // TODO: what if they are different? + if _, ok := foundTag[tag]; !ok { + fields = append(fields, zap.String(tag, attributeValue)) + foundTag[tag] = struct{}{} + } + } + } + } + } + return fields +} + +func msgTypesField(msgs []sdk.Msg) zap.Field { + msgTypes := make([]string, len(msgs)) + for i, m := range msgs { + msgTypes[i] = sdk.MsgTypeURL(m) + } + return zap.Strings("msg_types", msgTypes) +} + +// getFeePayer returns the bech32 address of the fee payer of a transaction. +// This uses the fee payer field if set, +// otherwise falls back to the address of whoever signed the first message. +func getFeePayer(log *zap.Logger, cdc *codec.ProtoCodec, tx *typestx.Tx) string { + payer := tx.AuthInfo.Fee.Payer + if payer != "" { + return payer + } + + switch firstMsg := tx.GetMsgs()[0].(type) { + case *transfertypes.MsgTransfer: + // There is a possible data race around concurrent map access + // in the cosmos sdk when it converts the address from bech32. + // We don't need the address conversion; just the sender is all that + // GetSigners is doing under the hood anyway. + return firstMsg.Sender + case *clienttypes.MsgCreateClient: + // Without this particular special case, there is a panic in ibc-go + // due to the sdk config singleton expecting one bech32 prefix but seeing another. + return firstMsg.Signer + case *clienttypes.MsgUpdateClient: + // Same failure mode as MsgCreateClient. + return firstMsg.Signer + case *clienttypes.MsgUpgradeClient: + return firstMsg.Signer + case *clienttypes.MsgSubmitMisbehaviour: + // Same failure mode as MsgCreateClient. + return firstMsg.Signer + case *feetypes.MsgRegisterPayee: + return firstMsg.Relayer + case *feetypes.MsgRegisterCounterpartyPayee: + return firstMsg.Relayer + case *feetypes.MsgPayPacketFee: + return firstMsg.Signer + case *feetypes.MsgPayPacketFeeAsync: + return firstMsg.PacketFee.RefundAddress + default: + signers, _, err := cdc.GetMsgV1Signers(firstMsg) + if err != nil { + log.Info("Could not get signers for msg when attempting to get the fee payer", zap.Error(err)) + return "" + } + + return string(signers[0]) + } +} + +func parseEventsFromTxResponse(resp *sdk.TxResponse) []provider.RelayerEvent { + var events []provider.RelayerEvent + + if resp == nil { + return events + } + + for _, logs := range resp.Logs { + for _, event := range logs.Events { + attributes := make(map[string]string) + for _, attribute := range event.Attributes { + attributes[attribute.Key] = attribute.Value + } + events = append(events, provider.RelayerEvent{ + EventType: event.Type, + Attributes: attributes, + }) + } + } + + // After SDK v0.50, indexed events are no longer provided in the logs on + // transaction execution, the response events can be directly used + if len(events) == 0 { + for _, event := range resp.Events { + attributes := make(map[string]string) + for _, attribute := range event.Attributes { + attributes[attribute.Key] = attribute.Value + } + events = append(events, provider.RelayerEvent{ + EventType: event.Type, + Attributes: attributes, + }) + } + } + + return events +} From df5f9ed452fc01bb0592e34f059df7ab64de186a Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Mon, 20 Jan 2025 23:14:46 -0300 Subject: [PATCH 03/31] chore: trytest with acc sequence increment --- clientcontroller/babylon.go | 40 +++++++++- clientcontroller/babylon_msg.go | 125 ++++++++++++++++++++++---------- 2 files changed, 123 insertions(+), 42 deletions(-) diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 6de78f4..4300318 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -8,8 +8,11 @@ import ( sdkmath "cosmossdk.io/math" "github.com/btcsuite/btcd/btcec/v2" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + bbn "github.com/babylonlabs-io/babylon/app" + appparams "github.com/babylonlabs-io/babylon/app/params" bbnclient "github.com/babylonlabs-io/babylon/client/client" bbntypes "github.com/babylonlabs-io/babylon/types" btcctypes "github.com/babylonlabs-io/babylon/x/btccheckpoint/types" @@ -36,6 +39,7 @@ type BabylonController struct { bbnClient *bbnclient.Client cfg *config.BBNConfig btcParams *chaincfg.Params + encCfg *appparams.EncodingConfig logger *zap.Logger } @@ -63,6 +67,7 @@ func NewBabylonController( bc, cfg, btcParams, + bbn.GetEncodingConfig(), logger, }, nil } @@ -165,7 +170,9 @@ func (bc *BabylonController) reliablySendMsgsAsMultipleTxs(msgs []sdk.Msg) (*pro // c := bc.bbnClient.GetConfig() // c.acc - return nil, nil + _, _, err := reliablySendEachMsgAsTx(bc.bbnClient.GetConfig(), msgs, bc.logger, bc.bbnClient.RPCClient, bc.encCfg, bc.QueryAccount, expectedErrors, unrecoverableErrors) + + return nil, err // bc.bbnClient.SendMsgToMempool() // return bc.bbnClient.ReliablySendMsgs( // context.Background(), @@ -190,7 +197,11 @@ func (bc *BabylonController) SubmitCovenantSigs(covSigs []*types.CovenantSigs) ( SlashingUnbondingTxSigs: covSig.SlashingUnbondingSigs, }) } - res, err := bc.reliablySendMsgs(msgs) + // res, err := bc.reliablySendMsgs(msgs) + // if err != nil { + // return nil, err + // } + res, err := bc.reliablySendMsgsAsMultipleTxs(msgs) if err != nil { return nil, err } @@ -525,3 +536,28 @@ func (bc *BabylonController) QueryBtcLightClientTip() (*btclctypes.BTCHeaderInfo return res.Header, nil } + +// QueryAccount returns the account interface based on the address +func (bc *BabylonController) QueryAccount(addr string) (sdk.AccountI, error) { + ctx, cancel := getContextWithCancel(bc.cfg.Timeout) + defer cancel() + + clientCtx := sdkclient.Context{Client: bc.bbnClient.RPCClient} + + queryClient := authtypes.NewQueryClient(clientCtx) + + req := &authtypes.QueryAccountRequest{ + Address: addr, + } + resp, err := queryClient.Account(ctx, req) + if err != nil { + return nil, fmt.Errorf("failed to query account: %v", err) + } + + var account sdk.AccountI + if err := bc.encCfg.InterfaceRegistry.UnpackAny(resp.Account, &account); err != nil { + return nil, err + } + + return account, nil +} diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go index 7c538ed..794372c 100644 --- a/clientcontroller/babylon_msg.go +++ b/clientcontroller/babylon_msg.go @@ -15,7 +15,6 @@ import ( sdkerrors "cosmossdk.io/errors" "cosmossdk.io/store/rootmulti" "github.com/avast/retry-go/v4" - bbn "github.com/babylonlabs-io/babylon/app" appparams "github.com/babylonlabs-io/babylon/app/params" "github.com/babylonlabs-io/babylon/client/config" abci "github.com/cometbft/cometbft/abci/types" @@ -34,7 +33,7 @@ import ( legacyerrors "github.com/cosmos/cosmos-sdk/types/errors" txtypes "github.com/cosmos/cosmos-sdk/types/tx" "github.com/cosmos/cosmos-sdk/types/tx/signing" - rlycosmos "github.com/cosmos/relayer/v2/chains/cosmos" + "github.com/cosmos/relayer/v2/relayer/chains/cosmos" "github.com/cosmos/relayer/v2/relayer/provider" "github.com/juju/fslock" abcistrange "github.com/strangelove-ventures/cometbft-client/abci/types" @@ -57,32 +56,82 @@ var ( dstChanTag = "packet_dst_channel" ) -func reliablySendMsgsAsMultipleTxs( +func reliablySendEachMsgAsTx( cfg *config.BabylonConfig, msgs []sdk.Msg, -) error { - - encCfg := bbn.GetEncodingConfig() - + logger *zap.Logger, + cometClient client.CometRPC, + encCfg *appparams.EncodingConfig, + getAcc func(addr string) (sdk.AccountI, error), + expectedErrors, unrecoverableErrors []*sdkerrors.Error, +) (txResponses []*sdk.TxResponse, failedMsgs []sdk.Msg, err error) { c, err := strangeloveclient.NewClient(cfg.RPCAddr, cfg.Timeout) if err != nil { - return err + return nil, nil, err } ctx := context.Background() - return ReliablySendMsgs(ctx, cfg) + txResponses = make([]*sdk.TxResponse, 0) + failedMsgs = make([]sdk.Msg, 0) + + errAccKey := AccessKeyWithLock(cfg.KeyDirectory, func() error { + keybase, err := KeybaseFromCfg(cfg, encCfg.Codec) + if err != nil { + return err + } + + covAddr, err := GetKeyAddressForKey(keybase, cfg.Key) + if err != nil { + return err + } + + covAcc, err := getAcc(covAddr.String()) + if err != nil { + return err + } + + accSequence := covAcc.GetSequence() + + for _, msg := range msgs { + txResp, err := ReliablySendMsgsWithSequence( + ctx, + cfg, + logger, + cometClient, + c, + encCfg, + accSequence, + []sdk.Msg{msg}, + expectedErrors, unrecoverableErrors, + ) + if err != nil { + // log msg fail + failedMsgs = append(failedMsgs, msg) + } + + accSequence++ + logger.Debug("resp", zap.String("txHash", txResp.TxHash)) + txResponses = append(txResponses, txResp) + } + + return nil + }) + if errAccKey != nil { + return nil, nil, err + } + + return txResponses, failedMsgs, nil } -// ReliablySendMsgs reliably sends a list of messages to the chain. +// ReliablySendMsgsWithSequence reliably sends a list of messages to the chain. // It utilizes a file lock as well as a keyring lock to ensure atomic access. -func ReliablySendMsgs( +func ReliablySendMsgsWithSequence( ctx context.Context, cfg *config.BabylonConfig, logger *zap.Logger, cometClient client.CometRPC, rpcClient *strangeloveclient.Client, encCfg *appparams.EncodingConfig, - ar client.AccountRetriever, accSequence uint64, msgs []sdk.Msg, @@ -103,14 +152,7 @@ func ReliablySendMsgs( wg.Add(1) if err := retry.Do(func() error { - var sendMsgErr error - krErr := AccessKeyWithLock(cfg.KeyDirectory, func() { - sendMsgErr = SendMessagesToMempool(ctx, cfg, logger, cometClient, rpcClient, encCfg, ar, msgs, "", accSequence, []func(*sdk.TxResponse, error){callback}) - }) - if krErr != nil { - logger.Error("unrecoverable err when submitting the tx, skip retrying", zap.Error(krErr)) - return retry.Unrecoverable(krErr) - } + sendMsgErr := SendMessagesToMempool(ctx, cfg, logger, cometClient, rpcClient, encCfg, msgs, "", accSequence, []func(*sdk.TxResponse, error){callback}) if sendMsgErr != nil { if ErrorContained(sendMsgErr, unrecoverableErrors) { logger.Error("unrecoverable err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) @@ -165,7 +207,6 @@ func SendMessagesToMempool( cometClient client.CometRPC, rpcClient *strangeloveclient.Client, encCfg *appparams.EncodingConfig, - ar client.AccountRetriever, msgs []sdk.Msg, memo string, @@ -177,7 +218,7 @@ func SendMessagesToMempool( txSignerKey := cfg.Key txBytes, fees, err := BuildMessages( - ctx, cfg, cometClient, rpcClient, encCfg, ar, msgs, memo, 0, txSignerKey, sequence, + ctx, cfg, cometClient, rpcClient, encCfg, msgs, memo, 0, txSignerKey, sequence, ) if err != nil { return err @@ -197,7 +238,6 @@ func BuildMessages( cometClient client.CometRPC, rpcClient *strangeloveclient.Client, encCfg *appparams.EncodingConfig, - ar client.AccountRetriever, msgs []sdk.Msg, memo string, gas uint64, @@ -208,14 +248,7 @@ func BuildMessages( fees sdk.Coins, err error, ) { - - keybase, err := keyring.New( - cfg.ChainID, - cfg.KeyringBackend, - cfg.KeyDirectory, - os.Stdin, - encCfg.Codec, - ) + keybase, err := KeybaseFromCfg(cfg, encCfg.Codec) if err != nil { return nil, sdk.Coins{}, err } @@ -225,7 +258,7 @@ func BuildMessages( WithChainID(cfg.ChainID). WithCodec(encCfg.Codec) - txf := TxFactory(cfg, ar, encCfg.TxConfig, keybase) + txf := TxFactory(cfg, encCfg.TxConfig, keybase) txf, err = PrepareFactory(cliCtx, txf, keybase, txSignerKey) if err != nil { return nil, sdk.Coins{}, err @@ -452,7 +485,7 @@ func waitForBlockInclusion( for { select { case <-exitAfter: - return nil, fmt.Errorf("timed out after: %d; %w", waitTimeout, rlycosmos.ErrTimeoutAfterWaitingForTxBroadcast) + return nil, fmt.Errorf("timed out after: %d; %w", waitTimeout, cosmos.ErrTimeoutAfterWaitingForTxBroadcast) // This fixed poll is fine because it's only for logging and updating prometheus metrics currently. case <-time.After(time.Millisecond * 100): res, err := rpcClient.Tx(ctx, txHash, false) @@ -538,23 +571,24 @@ func mkTxResult( return sdk.NewResponseResultTx(resTx, any, ""), nil } -func AccessKeyWithLock(keyDir string, accessFunc func()) error { +func AccessKeyWithLock(keyDir string, accessFunc func() error) error { // use lock file to guard concurrent access to the keyring lockFilePath := path.Join(keyDir, "keys.lock") lock := fslock.New(lockFilePath) - if err := lock.Lock(); err != nil { + err := lock.Lock() + if err != nil { return fmt.Errorf("failed to acquire file system lock (%s): %w", lockFilePath, err) } // trigger function that access keyring - accessFunc() + err = accessFunc() // unlock and release access - if err := lock.Unlock(); err != nil { + if errUnlock := lock.Unlock(); errUnlock != nil { return fmt.Errorf("error unlocking file system lock (%s), please manually delete", lockFilePath) } - return nil + return err } // QueryABCI performs an ABCI query and returns the appropriate response and error sdk error code. @@ -612,6 +646,19 @@ func ErrorContained(err error, errList []*sdkerrors.Error) bool { return false } +func KeybaseFromCfg( + cfg *config.BabylonConfig, + cdc codec.Codec, +) (keyring.Keyring, error) { + return keyring.New( + cfg.ChainID, + cfg.KeyringBackend, + cfg.KeyDirectory, + os.Stdin, + cdc, + ) +} + // PrepareFactory mutates the tx factory with the appropriate account number, sequence number, and min gas settings. func PrepareFactory( cliCtx client.Context, @@ -684,12 +731,10 @@ func GetKeyAddressForKey(keybase keyring.Keyring, key string) (sdk.AccAddress, e // TxFactory instantiates a new tx factory with the appropriate configuration settings for this chain. func TxFactory( cfg *config.BabylonConfig, - ar client.AccountRetriever, txConf client.TxConfig, keybase keyring.Keyring, ) tx.Factory { return tx.Factory{}. - WithAccountRetriever(ar). WithChainID(cfg.ChainID). WithTxConfig(txConf). WithGasAdjustment(cfg.GasAdjustment). From fe84b511898fa765b137b73a8e96947f4121262a Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Mon, 20 Jan 2025 23:36:31 -0300 Subject: [PATCH 04/31] chore: passing with account sequence --- clientcontroller/babylon.go | 2 +- clientcontroller/babylon_msg.go | 27 +++++++++------------------ 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 4300318..6d930cf 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -542,7 +542,7 @@ func (bc *BabylonController) QueryAccount(addr string) (sdk.AccountI, error) { ctx, cancel := getContextWithCancel(bc.cfg.Timeout) defer cancel() - clientCtx := sdkclient.Context{Client: bc.bbnClient.RPCClient} + clientCtx := sdkclient.Context{Client: bc.bbnClient.RPCClient}.WithCodec(bc.encCfg.Codec) queryClient := authtypes.NewQueryClient(clientCtx) diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go index 794372c..37e86cd 100644 --- a/clientcontroller/babylon_msg.go +++ b/clientcontroller/babylon_msg.go @@ -253,16 +253,17 @@ func BuildMessages( return nil, sdk.Coins{}, err } - cliCtx := client.Context{}.WithClient(cometClient). - WithInterfaceRegistry(encCfg.InterfaceRegistry). - WithChainID(cfg.ChainID). - WithCodec(encCfg.Codec) + // cliCtx := client.Context{}. + // WithClient(cometClient). + // WithInterfaceRegistry(encCfg.InterfaceRegistry). + // WithChainID(cfg.ChainID). + // WithCodec(encCfg.Codec) txf := TxFactory(cfg, encCfg.TxConfig, keybase) - txf, err = PrepareFactory(cliCtx, txf, keybase, txSignerKey) - if err != nil { - return nil, sdk.Coins{}, err - } + // txf, err = PrepareFactory(cliCtx, txf, keybase, txSignerKey) + // if err != nil { + // return nil, sdk.Coins{}, err + // } if memo != "" { txf = txf.WithMemo(memo) @@ -685,16 +686,6 @@ func PrepareFactory( cliCtx = cliCtx.WithFromAddress(from) - // Set the account number and sequence on the transaction factory and retry if fail - if err = retry.Do(func() error { - if err = txf.AccountRetriever().EnsureExists(cliCtx, from); err != nil { - return err - } - return err - }, rtyAtt, rtyDel, rtyErr); err != nil { - return txf, err - } - // TODO: why this code? this may potentially require another query when we don't want one initNum, initSeq := txf.AccountNumber(), txf.Sequence() if initNum == 0 || initSeq == 0 { From f0296c86e33051fb9db6ac6d4f472583a7581c8d Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Mon, 20 Jan 2025 23:38:21 -0300 Subject: [PATCH 05/31] fix: lint --- clientcontroller/babylon_msg.go | 8 +------- clientcontroller/babylon_msg_log.go | 3 --- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go index 37e86cd..74ac9ae 100644 --- a/clientcontroller/babylon_msg.go +++ b/clientcontroller/babylon_msg.go @@ -27,8 +27,6 @@ import ( "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" legacyerrors "github.com/cosmos/cosmos-sdk/types/errors" txtypes "github.com/cosmos/cosmos-sdk/types/tx" @@ -50,8 +48,6 @@ var ( rtyDel = retry.Delay(time.Millisecond * 400) rtyErr = retry.LastErrorOnly(true) defaultBroadcastWaitTimeout = 10 * time.Minute - spTag = "send_packet" - waTag = "write_acknowledgement" srcChanTag = "packet_src_channel" dstChanTag = "packet_dst_channel" ) @@ -753,9 +749,7 @@ func BuildSimTx(info *keyring.Record, txf tx.Factory, msgs ...sdk.Msg) ([]byte, return nil, err } - var pk cryptotypes.PubKey = &secp256k1.PubKey{} // use default public key type - - pk, err = info.GetPubKey() + pk, err := info.GetPubKey() if err != nil { return nil, err } diff --git a/clientcontroller/babylon_msg_log.go b/clientcontroller/babylon_msg_log.go index aeb0ef0..1d197f9 100644 --- a/clientcontroller/babylon_msg_log.go +++ b/clientcontroller/babylon_msg_log.go @@ -163,9 +163,6 @@ func getFeePayer(log *zap.Logger, cdc *codec.ProtoCodec, tx *typestx.Tx) string return firstMsg.Signer case *clienttypes.MsgUpgradeClient: return firstMsg.Signer - case *clienttypes.MsgSubmitMisbehaviour: - // Same failure mode as MsgCreateClient. - return firstMsg.Signer case *feetypes.MsgRegisterPayee: return firstMsg.Relayer case *feetypes.MsgRegisterCounterpartyPayee: From 530b7e13f085f0a877516ca4176f5f39b41ebcfd Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Mon, 20 Jan 2025 23:40:18 -0300 Subject: [PATCH 06/31] chore: add #98 to changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03153b3..ca7b822 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) * [#95](https://github.com/babylonlabs-io/covenant-emulator/pull/95) removed local signer option as the covenant emulator should only connect to a remote signer * [#96](https://github.com/babylonlabs-io/covenant-emulator/pull/96) add pagination to `queryDelegationsWithStatus` +* [#98](https://github.com/babylonlabs-io/covenant-emulator/pull/98) add submission of covenant +signatures as one msg per transaction if batch of transactions fails ## v0.11.3 From 614717df76a382d7f7db704cc084432b4dfc86a7 Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 21 Jan 2025 06:51:30 -0300 Subject: [PATCH 07/31] fix: sending with acc number --- clientcontroller/babylon_msg.go | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go index 74ac9ae..6179583 100644 --- a/clientcontroller/babylon_msg.go +++ b/clientcontroller/babylon_msg.go @@ -81,12 +81,16 @@ func reliablySendEachMsgAsTx( return err } - covAcc, err := getAcc(covAddr.String()) + covAddrStr := covAddr.String() + logger.Debug("covenant_signing", zap.String("address", covAddrStr)) + + covAcc, err := getAcc(covAddrStr) if err != nil { return err } accSequence := covAcc.GetSequence() + accNumber := covAcc.GetAccountNumber() for _, msg := range msgs { txResp, err := ReliablySendMsgsWithSequence( @@ -96,7 +100,9 @@ func reliablySendEachMsgAsTx( cometClient, c, encCfg, + covAddrStr, accSequence, + accNumber, []sdk.Msg{msg}, expectedErrors, unrecoverableErrors, ) @@ -129,7 +135,8 @@ func ReliablySendMsgsWithSequence( rpcClient *strangeloveclient.Client, encCfg *appparams.EncodingConfig, - accSequence uint64, + accAddress string, + accSequence, accNumber uint64, msgs []sdk.Msg, expectedErrors, unrecoverableErrors []*sdkerrors.Error, ) (*sdk.TxResponse, error) { @@ -148,7 +155,7 @@ func ReliablySendMsgsWithSequence( wg.Add(1) if err := retry.Do(func() error { - sendMsgErr := SendMessagesToMempool(ctx, cfg, logger, cometClient, rpcClient, encCfg, msgs, "", accSequence, []func(*sdk.TxResponse, error){callback}) + sendMsgErr := SendMessagesToMempool(ctx, cfg, logger, cometClient, rpcClient, encCfg, msgs, "", accAddress, accSequence, accNumber, []func(*sdk.TxResponse, error){callback}) if sendMsgErr != nil { if ErrorContained(sendMsgErr, unrecoverableErrors) { logger.Error("unrecoverable err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) @@ -207,14 +214,15 @@ func SendMessagesToMempool( msgs []sdk.Msg, memo string, - sequence uint64, + accAddress string, + accSequence, accNumber uint64, asyncCallbacks []func(*sdk.TxResponse, error), ) error { txSignerKey := cfg.Key txBytes, fees, err := BuildMessages( - ctx, cfg, cometClient, rpcClient, encCfg, msgs, memo, 0, txSignerKey, sequence, + ctx, cfg, cometClient, rpcClient, encCfg, msgs, memo, 0, txSignerKey, accAddress, accSequence, accNumber, ) if err != nil { return err @@ -238,7 +246,8 @@ func BuildMessages( memo string, gas uint64, txSignerKey string, - sequence uint64, + accAddress string, + accSequence, accNumber uint64, ) ( txBytes []byte, fees sdk.Coins, @@ -265,7 +274,8 @@ func BuildMessages( txf = txf.WithMemo(memo) } - txf = txf.WithSequence(sequence) + txf = txf.WithSequence(accSequence). + WithAccountNumber(accNumber) adjusted := gas @@ -720,6 +730,7 @@ func TxFactory( cfg *config.BabylonConfig, txConf client.TxConfig, keybase keyring.Keyring, + ) tx.Factory { return tx.Factory{}. WithChainID(cfg.ChainID). From b36e916437e126954e71297473b702477bb3b836 Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 21 Jan 2025 07:01:19 -0300 Subject: [PATCH 08/31] fix: panic --- clientcontroller/babylon_msg.go | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go index 6179583..12423f2 100644 --- a/clientcontroller/babylon_msg.go +++ b/clientcontroller/babylon_msg.go @@ -55,7 +55,7 @@ var ( func reliablySendEachMsgAsTx( cfg *config.BabylonConfig, msgs []sdk.Msg, - logger *zap.Logger, + log *zap.Logger, cometClient client.CometRPC, encCfg *appparams.EncodingConfig, getAcc func(addr string) (sdk.AccountI, error), @@ -82,7 +82,10 @@ func reliablySendEachMsgAsTx( } covAddrStr := covAddr.String() - logger.Debug("covenant_signing", zap.String("address", covAddrStr)) + log.Debug( + "covenant_signing", + zap.String("address", covAddrStr), + ) covAcc, err := getAcc(covAddrStr) if err != nil { @@ -96,7 +99,7 @@ func reliablySendEachMsgAsTx( txResp, err := ReliablySendMsgsWithSequence( ctx, cfg, - logger, + log, cometClient, c, encCfg, @@ -110,10 +113,15 @@ func reliablySendEachMsgAsTx( // log msg fail failedMsgs = append(failedMsgs, msg) } + if txResp != nil { + log.Debug("resp", zap.String("txHash", txResp.TxHash)) + + txResponses = append(txResponses, txResp) + } else { + failedMsgs = append(failedMsgs, msg) + } accSequence++ - logger.Debug("resp", zap.String("txHash", txResp.TxHash)) - txResponses = append(txResponses, txResp) } return nil @@ -141,13 +149,13 @@ func ReliablySendMsgsWithSequence( expectedErrors, unrecoverableErrors []*sdkerrors.Error, ) (*sdk.TxResponse, error) { var ( - rlyResp *sdk.TxResponse + tx *sdk.TxResponse callbackErr error wg sync.WaitGroup ) - callback := func(rtr *sdk.TxResponse, err error) { - rlyResp = rtr + callback := func(txResp *sdk.TxResponse, err error) { + tx = txResp callbackErr = err wg.Done() } @@ -187,16 +195,16 @@ func ReliablySendMsgsWithSequence( return nil, callbackErr } - if rlyResp == nil { + if tx == nil { // this case could happen if the error within the retry is an expected error return nil, nil } - if rlyResp.Code != 0 { - return rlyResp, fmt.Errorf("transaction failed with code: %d", rlyResp.Code) + if tx.Code != 0 { + return tx, fmt.Errorf("transaction failed with code: %d", tx.Code) } - return rlyResp, nil + return tx, nil } // SendMessagesToMempool simulates and broadcasts a transaction with the given msgs and memo. From 1e149e01a10fdc6566087da96532813d5a74b720 Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 21 Jan 2025 07:43:16 -0300 Subject: [PATCH 09/31] chore: add errgroup --- clientcontroller/babylon_msg.go | 121 +++++++++++++++++++------------- 1 file changed, 72 insertions(+), 49 deletions(-) diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go index 12423f2..5f73403 100644 --- a/clientcontroller/babylon_msg.go +++ b/clientcontroller/babylon_msg.go @@ -38,10 +38,13 @@ import ( strangeloveclient "github.com/strangelove-ventures/cometbft-client/client" rpcclient "github.com/strangelove-ventures/cometbft-client/rpc/client" "go.uber.org/zap" + "golang.org/x/sync/errgroup" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) +const MaxParallelMsgs = 20 + var ( rtyAttNum = uint(5) rtyAtt = retry.Attempts(rtyAttNum) @@ -52,6 +55,8 @@ var ( dstChanTag = "packet_dst_channel" ) +type callbackTx func(*sdk.TxResponse, error) + func reliablySendEachMsgAsTx( cfg *config.BabylonConfig, msgs []sdk.Msg, @@ -67,8 +72,14 @@ func reliablySendEachMsgAsTx( } ctx := context.Background() - txResponses = make([]*sdk.TxResponse, 0) - failedMsgs = make([]sdk.Msg, 0) + + // create outputs at msg len capacity to handle each msg in parallel + // as it is easier than pass 2 channels for each func + txResponses = make([]*sdk.TxResponse, len(msgs)) + failedMsgs = make([]sdk.Msg, len(msgs)) + + eg, egCtx := errgroup.WithContext(ctx) + eg.SetLimit(MaxParallelMsgs) errAccKey := AccessKeyWithLock(cfg.KeyDirectory, func() error { keybase, err := KeybaseFromCfg(cfg, encCfg.Codec) @@ -95,32 +106,49 @@ func reliablySendEachMsgAsTx( accSequence := covAcc.GetSequence() accNumber := covAcc.GetAccountNumber() - for _, msg := range msgs { - txResp, err := ReliablySendMsgsWithSequence( - ctx, - cfg, - log, - cometClient, - c, - encCfg, - covAddrStr, - accSequence, - accNumber, - []sdk.Msg{msg}, - expectedErrors, unrecoverableErrors, - ) - if err != nil { - // log msg fail - failedMsgs = append(failedMsgs, msg) - } - if txResp != nil { - log.Debug("resp", zap.String("txHash", txResp.TxHash)) - - txResponses = append(txResponses, txResp) - } else { - failedMsgs = append(failedMsgs, msg) - } - + for i, msg := range msgs { + eg.Go(func() error { + txResp, err := ReliablySendMsgsWithSequence( + egCtx, + cfg, + log, + cometClient, + c, + encCfg, + covAddrStr, + accSequence, + accNumber, + []sdk.Msg{msg}, + expectedErrors, unrecoverableErrors, + ) + + if err != nil { + failedMsgs[i] = msg + log.Error( + "failed to submit message", + zap.Int("msg_index", i), + zap.String("msg_data", msg.String()), + zap.Error(err), + ) + return err + } + + if txResp != nil { + log.Debug( + "sucessfully submit message", + zap.Int("msg_index", i), + zap.String("tx_hash", txResp.TxHash), + ) + txResponses[i] = txResp + } else { + log.Debug( + "sucessfully submit message, got expected error", + zap.Int("msg_index", i), + ) + failedMsgs[i] = msg + } + return nil + }) accSequence++ } @@ -130,9 +158,19 @@ func reliablySendEachMsgAsTx( return nil, nil, err } + err = eg.Wait() + + // clean the outputs + + if err != nil { + return txResponses, failedMsgs, err + } + return txResponses, failedMsgs, nil } +// func cleanNil() + // ReliablySendMsgsWithSequence reliably sends a list of messages to the chain. // It utilizes a file lock as well as a keyring lock to ensure atomic access. func ReliablySendMsgsWithSequence( @@ -163,7 +201,7 @@ func ReliablySendMsgsWithSequence( wg.Add(1) if err := retry.Do(func() error { - sendMsgErr := SendMessagesToMempool(ctx, cfg, logger, cometClient, rpcClient, encCfg, msgs, "", accAddress, accSequence, accNumber, []func(*sdk.TxResponse, error){callback}) + sendMsgErr := SendMessagesToMempool(ctx, cfg, logger, cometClient, rpcClient, encCfg, msgs, accSequence, accNumber, []callbackTx{callback}) if sendMsgErr != nil { if ErrorContained(sendMsgErr, unrecoverableErrors) { logger.Error("unrecoverable err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) @@ -220,17 +258,16 @@ func SendMessagesToMempool( encCfg *appparams.EncodingConfig, msgs []sdk.Msg, - memo string, - accAddress string, accSequence, accNumber uint64, - asyncCallbacks []func(*sdk.TxResponse, error), + asyncCallbacks []callbackTx, ) error { txSignerKey := cfg.Key + memo, gas := "", uint64(0) txBytes, fees, err := BuildMessages( - ctx, cfg, cometClient, rpcClient, encCfg, msgs, memo, 0, txSignerKey, accAddress, accSequence, accNumber, + ctx, cfg, cometClient, rpcClient, encCfg, msgs, memo, gas, txSignerKey, accSequence, accNumber, ) if err != nil { return err @@ -254,7 +291,6 @@ func BuildMessages( memo string, gas uint64, txSignerKey string, - accAddress string, accSequence, accNumber uint64, ) ( txBytes []byte, @@ -266,18 +302,7 @@ func BuildMessages( return nil, sdk.Coins{}, err } - // cliCtx := client.Context{}. - // WithClient(cometClient). - // WithInterfaceRegistry(encCfg.InterfaceRegistry). - // WithChainID(cfg.ChainID). - // WithCodec(encCfg.Codec) - txf := TxFactory(cfg, encCfg.TxConfig, keybase) - // txf, err = PrepareFactory(cliCtx, txf, keybase, txSignerKey) - // if err != nil { - // return nil, sdk.Coins{}, err - // } - if memo != "" { txf = txf.WithMemo(memo) } @@ -286,7 +311,6 @@ func BuildMessages( WithAccountNumber(accNumber) adjusted := gas - if gas == 0 { _, adjusted, err = CalculateGas(ctx, rpcClient, keybase, txf, txSignerKey, cfg.GasAdjustment, msgs...) @@ -336,7 +360,7 @@ func BroadcastTx( asyncCtx context.Context, // context for async wait for block inclusion after successful tx broadcast asyncTimeout time.Duration, // timeout for waiting for block inclusion - asyncCallbacks []func(*sdk.TxResponse, error), // callback for success/fail of the wait for block inclusion + asyncCallbacks []callbackTx, // callback for success/fail of the wait for block inclusion ) error { res, err := rpcClient.BroadcastTxSync(ctx, tx) isErr := err != nil @@ -436,7 +460,7 @@ func waitForTx( txHash []byte, msgs []sdk.Msg, // used for logging only waitTimeout time.Duration, - callbacks []func(*sdk.TxResponse, error), + callbacks []callbackTx, ) { res, err := waitForBlockInclusion(ctx, rpcClient, txConfig, txHash, waitTimeout) if err != nil { @@ -738,7 +762,6 @@ func TxFactory( cfg *config.BabylonConfig, txConf client.TxConfig, keybase keyring.Keyring, - ) tx.Factory { return tx.Factory{}. WithChainID(cfg.ChainID). From 5bb07890fb5ce5949bd8339a72c36765d845aacb Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 21 Jan 2025 09:57:36 -0300 Subject: [PATCH 10/31] fix: finally signing --- clientcontroller/babylon_msg.go | 125 ++++++++++++++++++++------------ 1 file changed, 79 insertions(+), 46 deletions(-) diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go index 5f73403..0d80fa2 100644 --- a/clientcontroller/babylon_msg.go +++ b/clientcontroller/babylon_msg.go @@ -38,7 +38,6 @@ import ( strangeloveclient "github.com/strangelove-ventures/cometbft-client/client" rpcclient "github.com/strangelove-ventures/cometbft-client/rpc/client" "go.uber.org/zap" - "golang.org/x/sync/errgroup" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -65,8 +64,8 @@ func reliablySendEachMsgAsTx( encCfg *appparams.EncodingConfig, getAcc func(addr string) (sdk.AccountI, error), expectedErrors, unrecoverableErrors []*sdkerrors.Error, -) (txResponses []*sdk.TxResponse, failedMsgs []sdk.Msg, err error) { - c, err := strangeloveclient.NewClient(cfg.RPCAddr, cfg.Timeout) +) (txResponses []*sdk.TxResponse, failedMsgs []*sdk.Msg, err error) { + rpcClient, err := strangeloveclient.NewClient(cfg.RPCAddr, cfg.Timeout) if err != nil { return nil, nil, err } @@ -76,10 +75,12 @@ func reliablySendEachMsgAsTx( // create outputs at msg len capacity to handle each msg in parallel // as it is easier than pass 2 channels for each func txResponses = make([]*sdk.TxResponse, len(msgs)) - failedMsgs = make([]sdk.Msg, len(msgs)) + failedMsgs = make([]*sdk.Msg, len(msgs)) - eg, egCtx := errgroup.WithContext(ctx) - eg.SetLimit(MaxParallelMsgs) + // eg, egCtx := errgroup.WithContext(ctx) + // eg.SetLimit(MaxParallelMsgs) + + var wg sync.WaitGroup errAccKey := AccessKeyWithLock(cfg.KeyDirectory, func() error { keybase, err := KeybaseFromCfg(cfg, encCfg.Codec) @@ -107,66 +108,86 @@ func reliablySendEachMsgAsTx( accNumber := covAcc.GetAccountNumber() for i, msg := range msgs { - eg.Go(func() error { - txResp, err := ReliablySendMsgsWithSequence( - egCtx, - cfg, - log, - cometClient, - c, - encCfg, - covAddrStr, - accSequence, - accNumber, - []sdk.Msg{msg}, - expectedErrors, unrecoverableErrors, - ) + wg.Add(1) + + callback := func(txResp *sdk.TxResponse, err error) { + defer wg.Done() if err != nil { - failedMsgs[i] = msg + failedMsgs[i] = &msg + + if ErrorContained(err, expectedErrors) { + log.Debug( + "sucessfully submit message, got expected error", + zap.Int("msg_index", i), + ) + return + } + log.Error( "failed to submit message", zap.Int("msg_index", i), zap.String("msg_data", msg.String()), zap.Error(err), ) - return err + return } - if txResp != nil { - log.Debug( - "sucessfully submit message", - zap.Int("msg_index", i), - zap.String("tx_hash", txResp.TxHash), - ) - txResponses[i] = txResp - } else { - log.Debug( - "sucessfully submit message, got expected error", - zap.Int("msg_index", i), - ) - failedMsgs[i] = msg + log.Debug( + "sucessfully submit message", + zap.Int("msg_index", i), + zap.String("tx_hash", txResp.TxHash), + ) + txResponses[i] = txResp + } + + errRetry := retry.Do(func() error { + sendMsgErr := SendMessagesToMempool(ctx, cfg, log, cometClient, rpcClient, encCfg, msgs, accSequence, accNumber, []callbackTx{callback}) + if sendMsgErr != nil { + if ErrorContained(sendMsgErr, unrecoverableErrors) { + log.Error("unrecoverable err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) + return retry.Unrecoverable(sendMsgErr) + } + if ErrorContained(sendMsgErr, expectedErrors) { + // this is necessary because if err is returned + // the callback function will not be executed so + // that the inside wg.Done will not be executed + wg.Done() + log.Error("expected err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) + return nil + } + return sendMsgErr } return nil - }) + }, retry.Context(ctx), rtyAtt, rtyDel, rtyErr, retry.OnRetry(func(n uint, err error) { + log.Debug("retrying", zap.Uint("attempt", n+1), zap.Uint("max_attempts", rtyAttNum), zap.Error(err)) + })) + + if errRetry != nil { + return errRetry + } + accSequence++ } return nil }) + + wg.Wait() + if errAccKey != nil { return nil, nil, err } - err = eg.Wait() + // err = eg.Wait() // clean the outputs - if err != nil { - return txResponses, failedMsgs, err - } + // if err != nil { + // return txResponses, failedMsgs, err + // } - return txResponses, failedMsgs, nil + return CleanSlice(txResponses), CleanSlice(failedMsgs), nil } // func cleanNil() @@ -176,7 +197,7 @@ func reliablySendEachMsgAsTx( func ReliablySendMsgsWithSequence( ctx context.Context, cfg *config.BabylonConfig, - logger *zap.Logger, + log *zap.Logger, cometClient client.CometRPC, rpcClient *strangeloveclient.Client, encCfg *appparams.EncodingConfig, @@ -192,6 +213,7 @@ func ReliablySendMsgsWithSequence( wg sync.WaitGroup ) + // todo: callback needs to be in outside func callback := func(txResp *sdk.TxResponse, err error) { tx = txResp callbackErr = err @@ -201,10 +223,10 @@ func ReliablySendMsgsWithSequence( wg.Add(1) if err := retry.Do(func() error { - sendMsgErr := SendMessagesToMempool(ctx, cfg, logger, cometClient, rpcClient, encCfg, msgs, accSequence, accNumber, []callbackTx{callback}) + sendMsgErr := SendMessagesToMempool(ctx, cfg, log, cometClient, rpcClient, encCfg, msgs, accSequence, accNumber, []callbackTx{callback}) if sendMsgErr != nil { if ErrorContained(sendMsgErr, unrecoverableErrors) { - logger.Error("unrecoverable err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) + log.Error("unrecoverable err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) return retry.Unrecoverable(sendMsgErr) } if ErrorContained(sendMsgErr, expectedErrors) { @@ -212,14 +234,14 @@ func ReliablySendMsgsWithSequence( // the callback function will not be executed so // that the inside wg.Done will not be executed wg.Done() - logger.Error("expected err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) + log.Error("expected err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) return nil } return sendMsgErr } return nil }, retry.Context(ctx), rtyAtt, rtyDel, rtyErr, retry.OnRetry(func(n uint, err error) { - logger.Debug("retrying", zap.Uint("attempt", n+1), zap.Uint("max_attempts", rtyAttNum), zap.Error(err)) + log.Debug("retrying", zap.Uint("attempt", n+1), zap.Uint("max_attempts", rtyAttNum), zap.Error(err)) })); err != nil { return nil, err } @@ -868,3 +890,14 @@ func sdkError(codespace string, code uint32) error { type intoAny interface { AsAny() *codectypes.Any } + +// CleanSlice removes nil values from a slice of pointers. +func CleanSlice[T any](slice []*T) []*T { + result := make([]*T, 0, len(slice)) + for _, item := range slice { + if item != nil { + result = append(result, item) + } + } + return result +} From 2ecb65aa8c6d1e575f1ce47dbe0d2c83ba02de08 Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 21 Jan 2025 10:13:38 -0300 Subject: [PATCH 11/31] fix: lint and notes --- clientcontroller/babylon_msg.go | 98 +++++++++++++++++---------------- 1 file changed, 51 insertions(+), 47 deletions(-) diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go index 0d80fa2..180b887 100644 --- a/clientcontroller/babylon_msg.go +++ b/clientcontroller/babylon_msg.go @@ -42,8 +42,8 @@ import ( "google.golang.org/grpc/status" ) -const MaxParallelMsgs = 20 - +// Note: most of the functions were adappt from +// https://github.com/babylonlabs-io/babylon/blob/cd0bbcd98be5e4dda081f7330140cf9dbee4c94d/client/client/tx.go#L76 var ( rtyAttNum = uint(5) rtyAtt = retry.Attempts(rtyAttNum) @@ -54,8 +54,10 @@ var ( dstChanTag = "packet_dst_channel" ) +// callbackTx is the expected type that waits for the inclusion of a transaction on the chain to be called type callbackTx func(*sdk.TxResponse, error) +// reliablySendEachMsgAsTx creates multiple func reliablySendEachMsgAsTx( cfg *config.BabylonConfig, msgs []sdk.Msg, @@ -72,13 +74,11 @@ func reliablySendEachMsgAsTx( ctx := context.Background() + msgLen := len(msgs) // create outputs at msg len capacity to handle each msg in parallel // as it is easier than pass 2 channels for each func - txResponses = make([]*sdk.TxResponse, len(msgs)) - failedMsgs = make([]*sdk.Msg, len(msgs)) - - // eg, egCtx := errgroup.WithContext(ctx) - // eg.SetLimit(MaxParallelMsgs) + txResponses = make([]*sdk.TxResponse, msgLen) + failedMsgs = make([]*sdk.Msg, msgLen) var wg sync.WaitGroup @@ -110,38 +110,9 @@ func reliablySendEachMsgAsTx( for i, msg := range msgs { wg.Add(1) - callback := func(txResp *sdk.TxResponse, err error) { - defer wg.Done() - - if err != nil { - failedMsgs[i] = &msg - - if ErrorContained(err, expectedErrors) { - log.Debug( - "sucessfully submit message, got expected error", - zap.Int("msg_index", i), - ) - return - } - - log.Error( - "failed to submit message", - zap.Int("msg_index", i), - zap.String("msg_data", msg.String()), - zap.Error(err), - ) - return - } - - log.Debug( - "sucessfully submit message", - zap.Int("msg_index", i), - zap.String("tx_hash", txResp.TxHash), - ) - txResponses[i] = txResp - } - + callback := reliablySendEachMsgAsTxCallback(log, &wg, msg, i, txResponses, failedMsgs) errRetry := retry.Do(func() error { + // SendMessagesToMempool launches a go routine to wait for the tx be included and call the callback func sendMsgErr := SendMessagesToMempool(ctx, cfg, log, cometClient, rpcClient, encCfg, msgs, accSequence, accNumber, []callbackTx{callback}) if sendMsgErr != nil { if ErrorContained(sendMsgErr, unrecoverableErrors) { @@ -149,10 +120,10 @@ func reliablySendEachMsgAsTx( return retry.Unrecoverable(sendMsgErr) } if ErrorContained(sendMsgErr, expectedErrors) { + defer wg.Done() // this is necessary because if err is returned // the callback function will not be executed so // that the inside wg.Done will not be executed - wg.Done() log.Error("expected err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) return nil } @@ -179,14 +150,6 @@ func reliablySendEachMsgAsTx( return nil, nil, err } - // err = eg.Wait() - - // clean the outputs - - // if err != nil { - // return txResponses, failedMsgs, err - // } - return CleanSlice(txResponses), CleanSlice(failedMsgs), nil } @@ -901,3 +864,44 @@ func CleanSlice[T any](slice []*T) []*T { } return result } + +func reliablySendEachMsgAsTxCallback( + log *zap.Logger, + wg *sync.WaitGroup, + msg sdk.Msg, + index int, + txResponses []*sdk.TxResponse, + failedMsgs []*sdk.Msg, +) callbackTx { + return func(txResp *sdk.TxResponse, err error) { + defer wg.Done() + + if err != nil { + failedMsgs[index] = &msg + + if ErrorContained(err, expectedErrors) { + log.Debug( + "sucessfully submit message, got expected error", + zap.Int("msg_index", index), + ) + return + } + + log.Error( + "failed to submit message", + zap.Int("msg_index", index), + zap.String("msg_data", msg.String()), + zap.Error(err), + ) + return + } + + log.Debug( + "sucessfully submit message", + zap.Int("msg_index", index), + zap.String("tx_hash", txResp.TxHash), + ) + txResponses[index] = txResp + } + +} From 502cf0e86b92c6912981f0e0c30897ec88c03721 Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 21 Jan 2025 10:15:08 -0300 Subject: [PATCH 12/31] chore: remove split of e2e test runs, failing to start --- itest/e2e_test.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/itest/e2e_test.go b/itest/e2e_test.go index b2ba621..fd44893 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -48,13 +48,8 @@ func TestCovenantEmulatorLifeCycle(t *testing.T) { res, err := tm.CovenantEmulator.AddCovenantSignatures(dels) require.NoError(t, err) require.Empty(t, res) -} - -func TestQueryPendingDelegations(t *testing.T) { - tm, btcPks := StartManagerWithFinalityProvider(t, 1) - defer tm.Stop(t) - // manually sets the pg to a low value + // Check pending dels clientcontroller.MaxPaginationLimit = 2 numDels := 3 @@ -62,7 +57,7 @@ func TestQueryPendingDelegations(t *testing.T) { _ = tm.InsertBTCDelegation(t, btcPks, stakingTime, stakingAmount, false) } - dels, err := tm.CovBBNClient.QueryPendingDelegations(uint64(numDels), nil) + dels, err = tm.CovBBNClient.QueryPendingDelegations(uint64(numDels), nil) require.NoError(t, err) require.Len(t, dels, numDels) } From 81f31d38b69a2554b7b944dd25bfe3f45ba7eaae Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 21 Jan 2025 10:53:17 -0300 Subject: [PATCH 13/31] chore: split e2e run on covenant emulator --- .github/workflows/ci.yml | 60 +++++++++++++++++- Makefile | 10 ++- clientcontroller/babylon.go | 31 ++++++--- clientcontroller/babylon_msg.go | 108 ++------------------------------ itest/e2e_test.go | 9 ++- 5 files changed, 103 insertions(+), 115 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 691d0e5..074fed1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: go-version: '1.23' go-lint-version: 'v1.60.2' run-unit-tests: true - run-integration-tests: true + run-integration-tests: false run-lint: true run-build: true run-gosec: true @@ -55,3 +55,61 @@ jobs: dockerContext: ./ repoName: covenant-signer docker_scan: true + +############################################################################### +### E2E ### +############################################################################### + + e2e-cov-signer: + runs-on: ubuntu-22.04 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Cache Go + uses: actions/setup-go@v5 + with: + go-version: 1.23.1 + - name: Run e2e covenant signer + run: | + cd covenant-signer; make test-e2e + + e2e-cov-emulator-life: + runs-on: ubuntu-22.04 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Cache Go + uses: actions/setup-go@v5 + with: + go-version: 1.23.1 + - name: Run e2e covenant emulator life cycle + run: | + make test-e2e-cov-emu-life + + e2e-cov-pending-dels: + runs-on: ubuntu-22.04 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Cache Go + uses: actions/setup-go@v5 + with: + go-version: 1.23.1 + - name: Run e2e covenant emulator pending dels + run: | + make test-e2e-cov-pending-del \ No newline at end of file diff --git a/Makefile b/Makefile index 13a2569..3e1223b 100644 --- a/Makefile +++ b/Makefile @@ -59,9 +59,17 @@ test: test-e2e: cd $(TOOLS_DIR); go install -trimpath $(BABYLON_PKG) - go test -mod=readonly -timeout=25m -v $(PACKAGES_E2E) -count=1 --tags=e2e + go test -mod=readonly -timeout=5m -v $(PACKAGES_E2E) --tags=e2e cd covenant-signer; make test-e2e +test-e2e-cov-emu-life: + cd $(TOOLS_DIR); go install -trimpath $(BABYLON_PKG) + go test -run TestCovenantEmulatorLifeCycle -mod=readonly -timeout=5m -v $(PACKAGES_E2E) --tags=e2e + +test-e2e-cov-pending-del: + cd $(TOOLS_DIR); go install -trimpath $(BABYLON_PKG) + go test -run TestQueryPendingDelegations -mod=readonly -timeout=5m -v $(PACKAGES_E2E) --tags=e2e + mock-gen: mkdir -p $(MOCKS_DIR) $(MOCKGEN_CMD) -source=clientcontroller/interface.go -package mocks -destination $(MOCKS_DIR)/babylon.go diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 6d930cf..fcf9860 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -166,20 +166,33 @@ func (bc *BabylonController) reliablySendMsgs(msgs []sdk.Msg) (*provider.Relayer func (bc *BabylonController) reliablySendMsgsAsMultipleTxs(msgs []sdk.Msg) (*provider.RelayerTxResponse, error) { // ctx := context.Background() - + cfg := bc.bbnClient.GetConfig() + encCfg := bc.encCfg // c := bc.bbnClient.GetConfig() // c.acc + keybase, err := KeybaseFromCfg(cfg, encCfg.Codec) + if err != nil { + return nil, err + } - _, _, err := reliablySendEachMsgAsTx(bc.bbnClient.GetConfig(), msgs, bc.logger, bc.bbnClient.RPCClient, bc.encCfg, bc.QueryAccount, expectedErrors, unrecoverableErrors) + covAddr, err := GetKeyAddressForKey(keybase, cfg.Key) + if err != nil { + return nil, err + } + + covAddrStr := covAddr.String() + bc.logger.Debug( + "covenant_signing", + zap.String("address", covAddrStr), + ) + + covAcc, err := bc.QueryAccount(covAddrStr) + if err != nil { + return nil, err + } + _, _, err = reliablySendEachMsgAsTx(cfg, msgs, bc.logger, bc.bbnClient.RPCClient, encCfg, covAcc, expectedErrors, unrecoverableErrors) return nil, err - // bc.bbnClient.SendMsgToMempool() - // return bc.bbnClient.ReliablySendMsgs( - // context.Background(), - // msgs, - // expectedErrors, - // unrecoverableErrors, - // ) } // SubmitCovenantSigs submits the Covenant signature via a MsgAddCovenantSig to Babylon if the daemon runs in Covenant mode diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go index 180b887..19ff721 100644 --- a/clientcontroller/babylon_msg.go +++ b/clientcontroller/babylon_msg.go @@ -64,7 +64,7 @@ func reliablySendEachMsgAsTx( log *zap.Logger, cometClient client.CometRPC, encCfg *appparams.EncodingConfig, - getAcc func(addr string) (sdk.AccountI, error), + covAcc sdk.AccountI, expectedErrors, unrecoverableErrors []*sdkerrors.Error, ) (txResponses []*sdk.TxResponse, failedMsgs []*sdk.Msg, err error) { rpcClient, err := strangeloveclient.NewClient(cfg.RPCAddr, cfg.Timeout) @@ -83,27 +83,6 @@ func reliablySendEachMsgAsTx( var wg sync.WaitGroup errAccKey := AccessKeyWithLock(cfg.KeyDirectory, func() error { - keybase, err := KeybaseFromCfg(cfg, encCfg.Codec) - if err != nil { - return err - } - - covAddr, err := GetKeyAddressForKey(keybase, cfg.Key) - if err != nil { - return err - } - - covAddrStr := covAddr.String() - log.Debug( - "covenant_signing", - zap.String("address", covAddrStr), - ) - - covAcc, err := getAcc(covAddrStr) - if err != nil { - return err - } - accSequence := covAcc.GetSequence() accNumber := covAcc.GetAccountNumber() @@ -113,14 +92,15 @@ func reliablySendEachMsgAsTx( callback := reliablySendEachMsgAsTxCallback(log, &wg, msg, i, txResponses, failedMsgs) errRetry := retry.Do(func() error { // SendMessagesToMempool launches a go routine to wait for the tx be included and call the callback func - sendMsgErr := SendMessagesToMempool(ctx, cfg, log, cometClient, rpcClient, encCfg, msgs, accSequence, accNumber, []callbackTx{callback}) + sendMsgErr := SendMessagesToMempool(ctx, cfg, log, cometClient, rpcClient, encCfg, msgs, accSequence, accNumber, callback) if sendMsgErr != nil { + defer wg.Done() + if ErrorContained(sendMsgErr, unrecoverableErrors) { log.Error("unrecoverable err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) return retry.Unrecoverable(sendMsgErr) } if ErrorContained(sendMsgErr, expectedErrors) { - defer wg.Done() // this is necessary because if err is returned // the callback function will not be executed so // that the inside wg.Done will not be executed @@ -131,6 +111,7 @@ func reliablySendEachMsgAsTx( } return nil }, retry.Context(ctx), rtyAtt, rtyDel, rtyErr, retry.OnRetry(func(n uint, err error) { + wg.Add(1) log.Debug("retrying", zap.Uint("attempt", n+1), zap.Uint("max_attempts", rtyAttNum), zap.Error(err)) })) @@ -153,83 +134,6 @@ func reliablySendEachMsgAsTx( return CleanSlice(txResponses), CleanSlice(failedMsgs), nil } -// func cleanNil() - -// ReliablySendMsgsWithSequence reliably sends a list of messages to the chain. -// It utilizes a file lock as well as a keyring lock to ensure atomic access. -func ReliablySendMsgsWithSequence( - ctx context.Context, - cfg *config.BabylonConfig, - log *zap.Logger, - cometClient client.CometRPC, - rpcClient *strangeloveclient.Client, - encCfg *appparams.EncodingConfig, - - accAddress string, - accSequence, accNumber uint64, - msgs []sdk.Msg, - expectedErrors, unrecoverableErrors []*sdkerrors.Error, -) (*sdk.TxResponse, error) { - var ( - tx *sdk.TxResponse - callbackErr error - wg sync.WaitGroup - ) - - // todo: callback needs to be in outside func - callback := func(txResp *sdk.TxResponse, err error) { - tx = txResp - callbackErr = err - wg.Done() - } - - wg.Add(1) - - if err := retry.Do(func() error { - sendMsgErr := SendMessagesToMempool(ctx, cfg, log, cometClient, rpcClient, encCfg, msgs, accSequence, accNumber, []callbackTx{callback}) - if sendMsgErr != nil { - if ErrorContained(sendMsgErr, unrecoverableErrors) { - log.Error("unrecoverable err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) - return retry.Unrecoverable(sendMsgErr) - } - if ErrorContained(sendMsgErr, expectedErrors) { - // this is necessary because if err is returned - // the callback function will not be executed so - // that the inside wg.Done will not be executed - wg.Done() - log.Error("expected err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) - return nil - } - return sendMsgErr - } - return nil - }, retry.Context(ctx), rtyAtt, rtyDel, rtyErr, retry.OnRetry(func(n uint, err error) { - log.Debug("retrying", zap.Uint("attempt", n+1), zap.Uint("max_attempts", rtyAttNum), zap.Error(err)) - })); err != nil { - return nil, err - } - - wg.Wait() - - if callbackErr != nil { - if ErrorContained(callbackErr, expectedErrors) { - return nil, nil - } - return nil, callbackErr - } - - if tx == nil { - // this case could happen if the error within the retry is an expected error - return nil, nil - } - - if tx.Code != 0 { - return tx, fmt.Errorf("transaction failed with code: %d", tx.Code) - } - - return tx, nil -} - // SendMessagesToMempool simulates and broadcasts a transaction with the given msgs and memo. // This method will return once the transaction has entered the mempool. // In an async goroutine, will wait for the tx to be included in the block unless asyncCtx exits. @@ -246,7 +150,7 @@ func SendMessagesToMempool( accSequence, accNumber uint64, - asyncCallbacks []callbackTx, + asyncCallbacks ...callbackTx, ) error { txSignerKey := cfg.Key memo, gas := "", uint64(0) diff --git a/itest/e2e_test.go b/itest/e2e_test.go index fd44893..b2ba621 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -48,8 +48,13 @@ func TestCovenantEmulatorLifeCycle(t *testing.T) { res, err := tm.CovenantEmulator.AddCovenantSignatures(dels) require.NoError(t, err) require.Empty(t, res) +} + +func TestQueryPendingDelegations(t *testing.T) { + tm, btcPks := StartManagerWithFinalityProvider(t, 1) + defer tm.Stop(t) - // Check pending dels + // manually sets the pg to a low value clientcontroller.MaxPaginationLimit = 2 numDels := 3 @@ -57,7 +62,7 @@ func TestCovenantEmulatorLifeCycle(t *testing.T) { _ = tm.InsertBTCDelegation(t, btcPks, stakingTime, stakingAmount, false) } - dels, err = tm.CovBBNClient.QueryPendingDelegations(uint64(numDels), nil) + dels, err := tm.CovBBNClient.QueryPendingDelegations(uint64(numDels), nil) require.NoError(t, err) require.Len(t, dels, numDels) } From 430ed8be6d7028dcd62937d5ff266f7fac470286 Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 21 Jan 2025 10:57:04 -0300 Subject: [PATCH 14/31] chore: remove login docker --- .github/workflows/ci.yml | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 074fed1..e90a3e3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,11 +65,6 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Cache Go uses: actions/setup-go@v5 with: @@ -83,11 +78,6 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Cache Go uses: actions/setup-go@v5 with: @@ -101,11 +91,6 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Cache Go uses: actions/setup-go@v5 with: From 130e6272170480d178a593500848c9664e3cac8d Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 21 Jan 2025 11:18:31 -0300 Subject: [PATCH 15/31] fix: wait group failure --- clientcontroller/babylon.go | 48 ++++++++++++++++++--------------- clientcontroller/babylon_msg.go | 37 +++++++++---------------- 2 files changed, 40 insertions(+), 45 deletions(-) diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index fcf9860..e1fdb6b 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -165,34 +165,40 @@ func (bc *BabylonController) reliablySendMsgs(msgs []sdk.Msg) (*provider.Relayer } func (bc *BabylonController) reliablySendMsgsAsMultipleTxs(msgs []sdk.Msg) (*provider.RelayerTxResponse, error) { - // ctx := context.Background() cfg := bc.bbnClient.GetConfig() encCfg := bc.encCfg - // c := bc.bbnClient.GetConfig() - // c.acc - keybase, err := KeybaseFromCfg(cfg, encCfg.Codec) - if err != nil { - return nil, err - } - covAddr, err := GetKeyAddressForKey(keybase, cfg.Key) - if err != nil { - return nil, err - } + errAccKey := AccessKeyWithLock(cfg.KeyDirectory, func() error { + keybase, err := KeybaseFromCfg(cfg, encCfg.Codec) + if err != nil { + return err + } - covAddrStr := covAddr.String() - bc.logger.Debug( - "covenant_signing", - zap.String("address", covAddrStr), - ) + covAddr, err := GetKeyAddressForKey(keybase, cfg.Key) + if err != nil { + return err + } - covAcc, err := bc.QueryAccount(covAddrStr) - if err != nil { - return nil, err + covAddrStr := covAddr.String() + bc.logger.Debug( + "covenant_signing", + zap.String("address", covAddrStr), + ) + + covAcc, err := bc.QueryAccount(covAddrStr) + if err != nil { + return err + } + + _, _, err = reliablySendEachMsgAsTx(cfg, msgs, bc.logger, bc.bbnClient.RPCClient, encCfg, covAcc) + return err + }) + + if errAccKey != nil { + return nil, errAccKey } - _, _, err = reliablySendEachMsgAsTx(cfg, msgs, bc.logger, bc.bbnClient.RPCClient, encCfg, covAcc, expectedErrors, unrecoverableErrors) - return nil, err + return nil, nil } // SubmitCovenantSigs submits the Covenant signature via a MsgAddCovenantSig to Babylon if the daemon runs in Covenant mode diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go index 19ff721..7104470 100644 --- a/clientcontroller/babylon_msg.go +++ b/clientcontroller/babylon_msg.go @@ -65,7 +65,6 @@ func reliablySendEachMsgAsTx( cometClient client.CometRPC, encCfg *appparams.EncodingConfig, covAcc sdk.AccountI, - expectedErrors, unrecoverableErrors []*sdkerrors.Error, ) (txResponses []*sdk.TxResponse, failedMsgs []*sdk.Msg, err error) { rpcClient, err := strangeloveclient.NewClient(cfg.RPCAddr, cfg.Timeout) if err != nil { @@ -82,28 +81,23 @@ func reliablySendEachMsgAsTx( var wg sync.WaitGroup - errAccKey := AccessKeyWithLock(cfg.KeyDirectory, func() error { - accSequence := covAcc.GetSequence() - accNumber := covAcc.GetAccountNumber() + accSequence := covAcc.GetSequence() + accNumber := covAcc.GetAccountNumber() - for i, msg := range msgs { - wg.Add(1) + for i, msg := range msgs { + wg.Add(1) - callback := reliablySendEachMsgAsTxCallback(log, &wg, msg, i, txResponses, failedMsgs) + callback := reliablySendEachMsgAsTxCallback(log, &wg, msg, i, txResponses, failedMsgs) + + go func(msg sdk.Msg, index int) { errRetry := retry.Do(func() error { - // SendMessagesToMempool launches a go routine to wait for the tx be included and call the callback func sendMsgErr := SendMessagesToMempool(ctx, cfg, log, cometClient, rpcClient, encCfg, msgs, accSequence, accNumber, callback) if sendMsgErr != nil { - defer wg.Done() - if ErrorContained(sendMsgErr, unrecoverableErrors) { log.Error("unrecoverable err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) return retry.Unrecoverable(sendMsgErr) } if ErrorContained(sendMsgErr, expectedErrors) { - // this is necessary because if err is returned - // the callback function will not be executed so - // that the inside wg.Done will not be executed log.Error("expected err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) return nil } @@ -111,26 +105,21 @@ func reliablySendEachMsgAsTx( } return nil }, retry.Context(ctx), rtyAtt, rtyDel, rtyErr, retry.OnRetry(func(n uint, err error) { - wg.Add(1) log.Debug("retrying", zap.Uint("attempt", n+1), zap.Uint("max_attempts", rtyAttNum), zap.Error(err)) })) if errRetry != nil { - return errRetry + log.Error("failed to retry message", zap.Int("msg_index", index), zap.Error(errRetry)) + // If the callback was not invoked, decrement the wait group here + wg.Done() } + }(msg, i) // Pass msg and i as arguments to avoid closure issues - accSequence++ - } - - return nil - }) + accSequence++ + } wg.Wait() - if errAccKey != nil { - return nil, nil, err - } - return CleanSlice(txResponses), CleanSlice(failedMsgs), nil } From 184c4eb43b1cfcda796f78c6ffb4a88a6e19636f Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 21 Jan 2025 11:25:31 -0300 Subject: [PATCH 16/31] chore: set permissions at the job level --- .github/workflows/ci.yml | 72 ++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e90a3e3..7244cc5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,40 +61,46 @@ jobs: ############################################################################### e2e-cov-signer: - runs-on: ubuntu-22.04 - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - name: Cache Go - uses: actions/setup-go@v5 - with: - go-version: 1.23.1 - - name: Run e2e covenant signer - run: | - cd covenant-signer; make test-e2e + permissions: + contents: read + runs-on: ubuntu-22.04 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Cache Go + uses: actions/setup-go@v5 + with: + go-version: 1.23.1 + - name: Run e2e covenant signer + run: | + cd covenant-signer; make test-e2e e2e-cov-emulator-life: - runs-on: ubuntu-22.04 - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - name: Cache Go - uses: actions/setup-go@v5 - with: - go-version: 1.23.1 - - name: Run e2e covenant emulator life cycle - run: | - make test-e2e-cov-emu-life + permissions: + contents: read + runs-on: ubuntu-22.04 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Cache Go + uses: actions/setup-go@v5 + with: + go-version: 1.23.1 + - name: Run e2e covenant emulator life cycle + run: | + make test-e2e-cov-emu-life e2e-cov-pending-dels: - runs-on: ubuntu-22.04 - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - name: Cache Go - uses: actions/setup-go@v5 - with: - go-version: 1.23.1 - - name: Run e2e covenant emulator pending dels - run: | - make test-e2e-cov-pending-del \ No newline at end of file + permissions: + contents: read + runs-on: ubuntu-22.04 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Cache Go + uses: actions/setup-go@v5 + with: + go-version: 1.23.1 + - name: Run e2e covenant emulator pending dels + run: | + make test-e2e-cov-pending-del \ No newline at end of file From 463c313182a500802f875e395bed1e58ccceeb5c Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 21 Jan 2025 11:38:41 -0300 Subject: [PATCH 17/31] chore: solve function closure of vars --- clientcontroller/babylon_msg.go | 95 +++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 33 deletions(-) diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go index 7104470..a9831a5 100644 --- a/clientcontroller/babylon_msg.go +++ b/clientcontroller/babylon_msg.go @@ -84,36 +84,32 @@ func reliablySendEachMsgAsTx( accSequence := covAcc.GetSequence() accNumber := covAcc.GetAccountNumber() - for i, msg := range msgs { - wg.Add(1) - - callback := reliablySendEachMsgAsTxCallback(log, &wg, msg, i, txResponses, failedMsgs) - - go func(msg sdk.Msg, index int) { - errRetry := retry.Do(func() error { - sendMsgErr := SendMessagesToMempool(ctx, cfg, log, cometClient, rpcClient, encCfg, msgs, accSequence, accNumber, callback) - if sendMsgErr != nil { - if ErrorContained(sendMsgErr, unrecoverableErrors) { - log.Error("unrecoverable err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) - return retry.Unrecoverable(sendMsgErr) - } - if ErrorContained(sendMsgErr, expectedErrors) { - log.Error("expected err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) - return nil - } - return sendMsgErr - } - return nil - }, retry.Context(ctx), rtyAtt, rtyDel, rtyErr, retry.OnRetry(func(n uint, err error) { - log.Debug("retrying", zap.Uint("attempt", n+1), zap.Uint("max_attempts", rtyAttNum), zap.Error(err)) - })) - - if errRetry != nil { - log.Error("failed to retry message", zap.Int("msg_index", index), zap.Error(errRetry)) + for msgIndex, msg := range msgs { + + callback := reliablySendEachMsgAsTxCallback(log, &wg, msg, msgIndex, txResponses, failedMsgs) + + go func( + ctx context.Context, + cfg *config.BabylonConfig, + log *zap.Logger, + cometClient client.CometRPC, + rpcClient *strangeloveclient.Client, + encCfg *appparams.EncodingConfig, + msgs []sdk.Msg, + accSequence, accNumber uint64, + callback callbackTx, + + msgIndex int, + ) { + wg.Add(1) + + errSendMsgs := RetrySendMessagesToMempool(ctx, cfg, log, cometClient, rpcClient, encCfg, msgs, accSequence, accNumber, callback) + if errSendMsgs != nil { + log.Error("failed to retry message", zap.Int("msg_index", msgIndex), zap.Error(errSendMsgs)) // If the callback was not invoked, decrement the wait group here wg.Done() } - }(msg, i) // Pass msg and i as arguments to avoid closure issues + }(ctx, cfg, log, cometClient, rpcClient, encCfg, msgs, accSequence, accNumber, callback, msgIndex) accSequence++ } @@ -123,6 +119,39 @@ func reliablySendEachMsgAsTx( return CleanSlice(txResponses), CleanSlice(failedMsgs), nil } +func RetrySendMessagesToMempool( + ctx context.Context, + cfg *config.BabylonConfig, + log *zap.Logger, + cometClient client.CometRPC, + rpcClient *strangeloveclient.Client, + encCfg *appparams.EncodingConfig, + + msgs []sdk.Msg, + + accSequence, accNumber uint64, + + asyncCallbacks ...callbackTx, +) error { + return retry.Do(func() error { + sendMsgErr := SendMessagesToMempool(ctx, cfg, log, cometClient, rpcClient, encCfg, msgs, accSequence, accNumber, asyncCallbacks...) + if sendMsgErr != nil { + if ErrorContained(sendMsgErr, unrecoverableErrors) { + log.Error("unrecoverable err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) + return retry.Unrecoverable(sendMsgErr) + } + if ErrorContained(sendMsgErr, expectedErrors) { + log.Error("expected err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) + return nil + } + return sendMsgErr + } + return nil + }, retry.Context(ctx), rtyAtt, rtyDel, rtyErr, retry.OnRetry(func(n uint, err error) { + log.Debug("retrying", zap.Uint("attempt", n+1), zap.Uint("max_attempts", rtyAttNum), zap.Error(err)) + })) +} + // SendMessagesToMempool simulates and broadcasts a transaction with the given msgs and memo. // This method will return once the transaction has entered the mempool. // In an async goroutine, will wait for the tx to be included in the block unless asyncCtx exits. @@ -762,7 +791,7 @@ func reliablySendEachMsgAsTxCallback( log *zap.Logger, wg *sync.WaitGroup, msg sdk.Msg, - index int, + msgIndex int, txResponses []*sdk.TxResponse, failedMsgs []*sdk.Msg, ) callbackTx { @@ -770,19 +799,19 @@ func reliablySendEachMsgAsTxCallback( defer wg.Done() if err != nil { - failedMsgs[index] = &msg + failedMsgs[msgIndex] = &msg if ErrorContained(err, expectedErrors) { log.Debug( "sucessfully submit message, got expected error", - zap.Int("msg_index", index), + zap.Int("msg_index", msgIndex), ) return } log.Error( "failed to submit message", - zap.Int("msg_index", index), + zap.Int("msg_index", msgIndex), zap.String("msg_data", msg.String()), zap.Error(err), ) @@ -791,10 +820,10 @@ func reliablySendEachMsgAsTxCallback( log.Debug( "sucessfully submit message", - zap.Int("msg_index", index), + zap.Int("msg_index", msgIndex), zap.String("tx_hash", txResp.TxHash), ) - txResponses[index] = txResp + txResponses[msgIndex] = txResp } } From 18ab8ce40b1be40061f71ca5e6cb8e9f7e67c7ac Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 21 Jan 2025 11:42:14 -0300 Subject: [PATCH 18/31] fix: lint call add prior to go routine --- clientcontroller/babylon_msg.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go index a9831a5..a6ba7f7 100644 --- a/clientcontroller/babylon_msg.go +++ b/clientcontroller/babylon_msg.go @@ -85,6 +85,7 @@ func reliablySendEachMsgAsTx( accNumber := covAcc.GetAccountNumber() for msgIndex, msg := range msgs { + wg.Add(1) callback := reliablySendEachMsgAsTxCallback(log, &wg, msg, msgIndex, txResponses, failedMsgs) @@ -101,8 +102,6 @@ func reliablySendEachMsgAsTx( msgIndex int, ) { - wg.Add(1) - errSendMsgs := RetrySendMessagesToMempool(ctx, cfg, log, cometClient, rpcClient, encCfg, msgs, accSequence, accNumber, callback) if errSendMsgs != nil { log.Error("failed to retry message", zap.Int("msg_index", msgIndex), zap.Error(errSendMsgs)) From 64fb0438f014e217b359eb288c561e28557f95e9 Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 21 Jan 2025 12:16:01 -0300 Subject: [PATCH 19/31] chore: set to run a single message at a time --- clientcontroller/babylon_msg.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go index a6ba7f7..ccd229b 100644 --- a/clientcontroller/babylon_msg.go +++ b/clientcontroller/babylon_msg.go @@ -102,13 +102,13 @@ func reliablySendEachMsgAsTx( msgIndex int, ) { - errSendMsgs := RetrySendMessagesToMempool(ctx, cfg, log, cometClient, rpcClient, encCfg, msgs, accSequence, accNumber, callback) - if errSendMsgs != nil { - log.Error("failed to retry message", zap.Int("msg_index", msgIndex), zap.Error(errSendMsgs)) + err := RetrySendMessagesToMempool(ctx, cfg, log, cometClient, rpcClient, encCfg, msgs, accSequence, accNumber, callback) + if err != nil { + log.Error("failed to retry message", zap.Int("msg_index", msgIndex), zap.Error(err)) // If the callback was not invoked, decrement the wait group here wg.Done() } - }(ctx, cfg, log, cometClient, rpcClient, encCfg, msgs, accSequence, accNumber, callback, msgIndex) + }(ctx, cfg, log, cometClient, rpcClient, encCfg, []sdk.Msg{msg}, accSequence, accNumber, callback, msgIndex) accSequence++ } From 3980368ff508efa4ebf2bbf3a63b1eda5ebacfb0 Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 21 Jan 2025 12:28:22 -0300 Subject: [PATCH 20/31] tryfix: e2e test wait group --- clientcontroller/babylon_msg.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go index ccd229b..d16454c 100644 --- a/clientcontroller/babylon_msg.go +++ b/clientcontroller/babylon_msg.go @@ -96,19 +96,23 @@ func reliablySendEachMsgAsTx( cometClient client.CometRPC, rpcClient *strangeloveclient.Client, encCfg *appparams.EncodingConfig, - msgs []sdk.Msg, + msg sdk.Msg, accSequence, accNumber uint64, callback callbackTx, msgIndex int, ) { - err := RetrySendMessagesToMempool(ctx, cfg, log, cometClient, rpcClient, encCfg, msgs, accSequence, accNumber, callback) + err := RetrySendMessagesToMempool(ctx, cfg, log, cometClient, rpcClient, encCfg, []sdk.Msg{msg}, accSequence, accNumber, callback) if err != nil { - log.Error("failed to retry message", zap.Int("msg_index", msgIndex), zap.Error(err)) + if ErrorContained(err, expectedErrors) { + log.Error("expected err when submitting the tx, skip retrying", zap.Error(err)) + } else { + log.Error("failed to retry message", zap.Int("msg_index", msgIndex), zap.Error(err)) + } // If the callback was not invoked, decrement the wait group here wg.Done() } - }(ctx, cfg, log, cometClient, rpcClient, encCfg, []sdk.Msg{msg}, accSequence, accNumber, callback, msgIndex) + }(ctx, cfg, log, cometClient, rpcClient, encCfg, msg, accSequence, accNumber, callback, msgIndex) accSequence++ } @@ -139,10 +143,6 @@ func RetrySendMessagesToMempool( log.Error("unrecoverable err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) return retry.Unrecoverable(sendMsgErr) } - if ErrorContained(sendMsgErr, expectedErrors) { - log.Error("expected err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) - return nil - } return sendMsgErr } return nil From 91a7da1594724ea6dea424be08bb9fbd6a43df58 Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 21 Jan 2025 12:54:46 -0300 Subject: [PATCH 21/31] chore: add option to start covenant emulator --- itest/e2e_test.go | 4 ++-- itest/test_manager.go | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/itest/e2e_test.go b/itest/e2e_test.go index b2ba621..3d10155 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -17,7 +17,7 @@ var ( ) func TestCovenantEmulatorLifeCycle(t *testing.T) { - tm, btcPks := StartManagerWithFinalityProvider(t, 1) + tm, btcPks := StartManagerWithFinalityProvider(t, 1, true) defer tm.Stop(t) // send a BTC delegation that is not following pre-approval flow @@ -51,7 +51,7 @@ func TestCovenantEmulatorLifeCycle(t *testing.T) { } func TestQueryPendingDelegations(t *testing.T) { - tm, btcPks := StartManagerWithFinalityProvider(t, 1) + tm, btcPks := StartManagerWithFinalityProvider(t, 1, false) defer tm.Stop(t) // manually sets the pg to a low value diff --git a/itest/test_manager.go b/itest/test_manager.go index 8a913aa..7ffd28b 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -77,7 +77,7 @@ type testFinalityProviderData struct { PoP *bstypes.ProofOfPossessionBTC } -func StartManager(t *testing.T) *TestManager { +func StartManager(t *testing.T, shouldStartEmulator bool) *TestManager { testDir, err := baseDir("cee2etest") require.NoError(t, err) @@ -158,8 +158,10 @@ func StartManager(t *testing.T) *TestManager { ce, err := covenant.NewCovenantEmulator(covenantConfig, covbc, logger, signer) require.NoError(t, err) - err = ce.Start() - require.NoError(t, err) + if shouldStartEmulator { + err = ce.Start() + require.NoError(t, err) + } tm := &TestManager{ BabylonHandler: bh, @@ -206,8 +208,8 @@ func (tm *TestManager) SendToAddr(t *testing.T, toAddr, amount string) { require.NoError(t, err) } -func StartManagerWithFinalityProvider(t *testing.T, n int) (*TestManager, []*btcec.PublicKey) { - tm := StartManager(t) +func StartManagerWithFinalityProvider(t *testing.T, n int, shouldStartEmulator bool) (*TestManager, []*btcec.PublicKey) { + tm := StartManager(t, shouldStartEmulator) var btcPks []*btcec.PublicKey for i := 0; i < n; i++ { From 960a88ca7833a1da8940bf05e56a862ccf406033 Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 21 Jan 2025 14:31:40 -0300 Subject: [PATCH 22/31] chore: refactory to return an slice of tx response --- Makefile | 2 +- clientcontroller/babylon.go | 84 +++++++++++++++++++++++++-------- clientcontroller/babylon_msg.go | 16 +++++-- clientcontroller/interface.go | 2 +- covenant/covenant.go | 8 ++-- covenant/covenant_test.go | 4 +- testutil/mocks/babylon.go | 4 +- 7 files changed, 87 insertions(+), 33 deletions(-) diff --git a/Makefile b/Makefile index 3e1223b..35ef6ab 100644 --- a/Makefile +++ b/Makefile @@ -64,7 +64,7 @@ test-e2e: test-e2e-cov-emu-life: cd $(TOOLS_DIR); go install -trimpath $(BABYLON_PKG) - go test -run TestCovenantEmulatorLifeCycle -mod=readonly -timeout=5m -v $(PACKAGES_E2E) --tags=e2e + go test -run TestCovenantEmulatorLifeCycle -mod=readonly -timeout=7m -v $(PACKAGES_E2E) --tags=e2e test-e2e-cov-pending-del: cd $(TOOLS_DIR); go install -trimpath $(BABYLON_PKG) diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index e1fdb6b..d62c4c7 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -2,6 +2,7 @@ package clientcontroller import ( "context" + "errors" "fmt" "math" "time" @@ -155,6 +156,37 @@ func (bc *BabylonController) reliablySendMsg(msg sdk.Msg) (*provider.RelayerTxRe return bc.reliablySendMsgs([]sdk.Msg{msg}) } +// SendMsgs first it tries to send all the messages in a single transaction +// if it fails, sends each message in a different transaction. +func (bc *BabylonController) SendMsgs(msgs []sdk.Msg) ([]*types.TxResponse, error) { + resSingleTx, errSingleTx := bc.reliablySendMsgs(msgs) + if errSingleTx != nil { + // failed to send as a batch tx + resMultipleTxs, errMultipleTx := bc.reliablySendMsgsAsMultipleTxs(msgs) + if errMultipleTx != nil { + return nil, errors.Join(errSingleTx, errMultipleTx) + } + + return convertTxResp(resMultipleTxs...), nil + } + + if resSingleTx == nil { // some expected error happened + return []*types.TxResponse{}, nil + } + return convertTxResp(resSingleTx), nil +} + +func convertTxResp(txs ...*provider.RelayerTxResponse) []*types.TxResponse { + resp := make([]*types.TxResponse, len(txs)) + for i, tx := range txs { + resp[i] = &types.TxResponse{ + TxHash: tx.TxHash, + Events: tx.Events, + } + } + return resp +} + func (bc *BabylonController) reliablySendMsgs(msgs []sdk.Msg) (*provider.RelayerTxResponse, error) { return bc.bbnClient.ReliablySendMsgs( context.Background(), @@ -164,9 +196,15 @@ func (bc *BabylonController) reliablySendMsgs(msgs []sdk.Msg) (*provider.Relayer ) } -func (bc *BabylonController) reliablySendMsgsAsMultipleTxs(msgs []sdk.Msg) (*provider.RelayerTxResponse, error) { +func (bc *BabylonController) reliablySendMsgsAsMultipleTxs(msgs []sdk.Msg) ([]*provider.RelayerTxResponse, error) { cfg := bc.bbnClient.GetConfig() encCfg := bc.encCfg + log := bc.logger + + var ( + txResponses []*sdk.TxResponse + failedMsgs []*failedMsg + ) errAccKey := AccessKeyWithLock(cfg.KeyDirectory, func() error { keybase, err := KeybaseFromCfg(cfg, encCfg.Codec) @@ -180,7 +218,7 @@ func (bc *BabylonController) reliablySendMsgsAsMultipleTxs(msgs []sdk.Msg) (*pro } covAddrStr := covAddr.String() - bc.logger.Debug( + log.Debug( "covenant_signing", zap.String("address", covAddrStr), ) @@ -190,20 +228,39 @@ func (bc *BabylonController) reliablySendMsgsAsMultipleTxs(msgs []sdk.Msg) (*pro return err } - _, _, err = reliablySendEachMsgAsTx(cfg, msgs, bc.logger, bc.bbnClient.RPCClient, encCfg, covAcc) + txResponses, failedMsgs, err = reliablySendEachMsgAsTx(cfg, msgs, log, bc.bbnClient.RPCClient, encCfg, covAcc) return err }) - if errAccKey != nil { return nil, errAccKey } - return nil, nil + for _, failedMsg := range failedMsgs { + log.Warn( + "msg failed to submit as tx", + zap.String("msg", failedMsg.msg.String()), + zap.Error(failedMsg.reason), + ) + } + + resp := make([]*provider.RelayerTxResponse, len(txResponses)) + for i, res := range txResponses { + resp[i] = &provider.RelayerTxResponse{ + Height: res.Height, + TxHash: res.TxHash, + Codespace: res.Codespace, + Code: res.Code, + Data: res.Data, + Events: parseEventsFromTxResponse(res), + } + } + + return resp, nil } // SubmitCovenantSigs submits the Covenant signature via a MsgAddCovenantSig to Babylon if the daemon runs in Covenant mode // it returns tx hash and error -func (bc *BabylonController) SubmitCovenantSigs(covSigs []*types.CovenantSigs) (*types.TxResponse, error) { +func (bc *BabylonController) SubmitCovenantSigs(covSigs []*types.CovenantSigs) ([]*types.TxResponse, error) { msgs := make([]sdk.Msg, 0, len(covSigs)) for _, covSig := range covSigs { bip340UnbondingSig := bbntypes.NewBIP340SignatureFromBTCSig(covSig.UnbondingSig) @@ -216,20 +273,7 @@ func (bc *BabylonController) SubmitCovenantSigs(covSigs []*types.CovenantSigs) ( SlashingUnbondingTxSigs: covSig.SlashingUnbondingSigs, }) } - // res, err := bc.reliablySendMsgs(msgs) - // if err != nil { - // return nil, err - // } - res, err := bc.reliablySendMsgsAsMultipleTxs(msgs) - if err != nil { - return nil, err - } - - if res == nil { - return &types.TxResponse{}, nil - } - - return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil + return bc.SendMsgs(msgs) } func (bc *BabylonController) QueryPendingDelegations(limit uint64, filter FilterFn) ([]*types.Delegation, error) { diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go index d16454c..2baafa6 100644 --- a/clientcontroller/babylon_msg.go +++ b/clientcontroller/babylon_msg.go @@ -57,6 +57,11 @@ var ( // callbackTx is the expected type that waits for the inclusion of a transaction on the chain to be called type callbackTx func(*sdk.TxResponse, error) +type failedMsg struct { + msg sdk.Msg + reason error +} + // reliablySendEachMsgAsTx creates multiple func reliablySendEachMsgAsTx( cfg *config.BabylonConfig, @@ -65,7 +70,7 @@ func reliablySendEachMsgAsTx( cometClient client.CometRPC, encCfg *appparams.EncodingConfig, covAcc sdk.AccountI, -) (txResponses []*sdk.TxResponse, failedMsgs []*sdk.Msg, err error) { +) (txResponses []*sdk.TxResponse, failedMsgs []*failedMsg, err error) { rpcClient, err := strangeloveclient.NewClient(cfg.RPCAddr, cfg.Timeout) if err != nil { return nil, nil, err @@ -77,7 +82,7 @@ func reliablySendEachMsgAsTx( // create outputs at msg len capacity to handle each msg in parallel // as it is easier than pass 2 channels for each func txResponses = make([]*sdk.TxResponse, msgLen) - failedMsgs = make([]*sdk.Msg, msgLen) + failedMsgs = make([]*failedMsg, msgLen) var wg sync.WaitGroup @@ -792,13 +797,16 @@ func reliablySendEachMsgAsTxCallback( msg sdk.Msg, msgIndex int, txResponses []*sdk.TxResponse, - failedMsgs []*sdk.Msg, + failedMsgs []*failedMsg, ) callbackTx { return func(txResp *sdk.TxResponse, err error) { defer wg.Done() if err != nil { - failedMsgs[msgIndex] = &msg + failedMsgs[msgIndex] = &failedMsg{ + msg: msg, + reason: err, + } if ErrorContained(err, expectedErrors) { log.Debug( diff --git a/clientcontroller/interface.go b/clientcontroller/interface.go index 53e0e8d..d8b6376 100644 --- a/clientcontroller/interface.go +++ b/clientcontroller/interface.go @@ -20,7 +20,7 @@ type ( // SubmitCovenantSigs submits Covenant signatures to the consumer chain, each corresponding to // a finality provider that the delegation is (re-)staked to // it returns tx hash and error - SubmitCovenantSigs(covSigMsgs []*types.CovenantSigs) (*types.TxResponse, error) + SubmitCovenantSigs(covSigMsgs []*types.CovenantSigs) ([]*types.TxResponse, error) // QueryPendingDelegations queries BTC delegations that are in status of pending QueryPendingDelegations(limit uint64, filter FilterFn) ([]*types.Delegation, error) diff --git a/covenant/covenant.go b/covenant/covenant.go index f97ec09..b5525dd 100644 --- a/covenant/covenant.go +++ b/covenant/covenant.go @@ -83,7 +83,7 @@ func (ce *CovenantEmulator) PublicKeyStr() string { // AddCovenantSignatures adds Covenant signatures on every given Bitcoin delegations and submits them // in a batch to Babylon. Invalid delegations will be skipped with error log error will be returned if // the batch submission fails -func (ce *CovenantEmulator) AddCovenantSignatures(btcDels []*types.Delegation) (*types.TxResponse, error) { +func (ce *CovenantEmulator) AddCovenantSignatures(btcDels []*types.Delegation) ([]*types.TxResponse, error) { if len(btcDels) == 0 { return nil, fmt.Errorf("no delegations") } @@ -511,8 +511,10 @@ func (ce *CovenantEmulator) covenantSigSubmissionLoop() { limit := ce.config.DelegationLimit covenantSigTicker := time.NewTicker(interval) - ce.logger.Info("starting signature submission loop", - zap.Float64("interval seconds", interval.Seconds())) + ce.logger.Info( + "starting signature submission loop", + zap.Float64("interval seconds", interval.Seconds()), + ) for { select { diff --git a/covenant/covenant_test.go b/covenant/covenant_test.go index fbb449c..0577a42 100644 --- a/covenant/covenant_test.go +++ b/covenant/covenant_test.go @@ -254,10 +254,10 @@ func FuzzAddCovenantSig(f *testing.F) { // check the sigs are expected expectedTxHash := testutil.GenRandomHexStr(r, 32) mockClientController.EXPECT().SubmitCovenantSigs(covSigsSet). - Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() + Return([]*types.TxResponse{&types.TxResponse{TxHash: expectedTxHash}}, nil).AnyTimes() res, err := ce.AddCovenantSignatures(btcDels) require.NoError(t, err) - require.Equal(t, expectedTxHash, res.TxHash) + require.Equal(t, expectedTxHash, res[0].TxHash) }) } diff --git a/testutil/mocks/babylon.go b/testutil/mocks/babylon.go index 1644332..e8cb61a 100644 --- a/testutil/mocks/babylon.go +++ b/testutil/mocks/babylon.go @@ -80,10 +80,10 @@ func (mr *MockClientControllerMockRecorder) QueryStakingParamsByVersion(version } // SubmitCovenantSigs mocks base method. -func (m *MockClientController) SubmitCovenantSigs(covSigMsgs []*types.CovenantSigs) (*types.TxResponse, error) { +func (m *MockClientController) SubmitCovenantSigs(covSigMsgs []*types.CovenantSigs) ([]*types.TxResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SubmitCovenantSigs", covSigMsgs) - ret0, _ := ret[0].(*types.TxResponse) + ret0, _ := ret[0].([]*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } From df8759b225237e81c4f1b0e944ac9e479a6cbbfb Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 21 Jan 2025 14:55:48 -0300 Subject: [PATCH 23/31] test: modified to use multiple txs for checking --- clientcontroller/babylon.go | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index d62c4c7..8e01d03 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -2,7 +2,6 @@ package clientcontroller import ( "context" - "errors" "fmt" "math" "time" @@ -159,21 +158,22 @@ func (bc *BabylonController) reliablySendMsg(msg sdk.Msg) (*provider.RelayerTxRe // SendMsgs first it tries to send all the messages in a single transaction // if it fails, sends each message in a different transaction. func (bc *BabylonController) SendMsgs(msgs []sdk.Msg) ([]*types.TxResponse, error) { - resSingleTx, errSingleTx := bc.reliablySendMsgs(msgs) - if errSingleTx != nil { - // failed to send as a batch tx - resMultipleTxs, errMultipleTx := bc.reliablySendMsgsAsMultipleTxs(msgs) - if errMultipleTx != nil { - return nil, errors.Join(errSingleTx, errMultipleTx) - } - - return convertTxResp(resMultipleTxs...), nil - } - - if resSingleTx == nil { // some expected error happened - return []*types.TxResponse{}, nil - } - return convertTxResp(resSingleTx), nil + // resSingleTx, errSingleTx := bc.reliablySendMsgs(msgs) + // if errSingleTx != nil { + // failed to send as a batch tx + resMultipleTxs, errMultipleTx := bc.reliablySendMsgsAsMultipleTxs(msgs) + if errMultipleTx != nil { + // return nil, errors.Join(errSingleTx, errMultipleTx) + return nil, errMultipleTx + } + + return convertTxResp(resMultipleTxs...), nil + // } + + // if resSingleTx == nil { // some expected error happened + // return []*types.TxResponse{}, nil + // } + // return convertTxResp(resSingleTx), nil } func convertTxResp(txs ...*provider.RelayerTxResponse) []*types.TxResponse { From 5994bc1f889d4583f594abbc45c96a2cc179be4f Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 21 Jan 2025 15:11:15 -0300 Subject: [PATCH 24/31] chore: rollback to use batch first --- clientcontroller/babylon.go | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 8e01d03..d62c4c7 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -2,6 +2,7 @@ package clientcontroller import ( "context" + "errors" "fmt" "math" "time" @@ -158,22 +159,21 @@ func (bc *BabylonController) reliablySendMsg(msg sdk.Msg) (*provider.RelayerTxRe // SendMsgs first it tries to send all the messages in a single transaction // if it fails, sends each message in a different transaction. func (bc *BabylonController) SendMsgs(msgs []sdk.Msg) ([]*types.TxResponse, error) { - // resSingleTx, errSingleTx := bc.reliablySendMsgs(msgs) - // if errSingleTx != nil { - // failed to send as a batch tx - resMultipleTxs, errMultipleTx := bc.reliablySendMsgsAsMultipleTxs(msgs) - if errMultipleTx != nil { - // return nil, errors.Join(errSingleTx, errMultipleTx) - return nil, errMultipleTx - } - - return convertTxResp(resMultipleTxs...), nil - // } - - // if resSingleTx == nil { // some expected error happened - // return []*types.TxResponse{}, nil - // } - // return convertTxResp(resSingleTx), nil + resSingleTx, errSingleTx := bc.reliablySendMsgs(msgs) + if errSingleTx != nil { + // failed to send as a batch tx + resMultipleTxs, errMultipleTx := bc.reliablySendMsgsAsMultipleTxs(msgs) + if errMultipleTx != nil { + return nil, errors.Join(errSingleTx, errMultipleTx) + } + + return convertTxResp(resMultipleTxs...), nil + } + + if resSingleTx == nil { // some expected error happened + return []*types.TxResponse{}, nil + } + return convertTxResp(resSingleTx), nil } func convertTxResp(txs ...*provider.RelayerTxResponse) []*types.TxResponse { From 2114a6e62a739571431f8d5ba9a1b2dacf9a2e9b Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 21 Jan 2025 15:16:27 -0300 Subject: [PATCH 25/31] chore: increase exec time --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 35ef6ab..33e11ea 100644 --- a/Makefile +++ b/Makefile @@ -68,7 +68,7 @@ test-e2e-cov-emu-life: test-e2e-cov-pending-del: cd $(TOOLS_DIR); go install -trimpath $(BABYLON_PKG) - go test -run TestQueryPendingDelegations -mod=readonly -timeout=5m -v $(PACKAGES_E2E) --tags=e2e + go test -run TestQueryPendingDelegations -mod=readonly -timeout=7m -v $(PACKAGES_E2E) --tags=e2e mock-gen: mkdir -p $(MOCKS_DIR) From 9a9453b55854b46974431c6ff4ed141805887101 Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Wed, 29 Jan 2025 11:04:24 -0300 Subject: [PATCH 26/31] chore: small refactor, need to have more public funcs in babylonclient --- clientcontroller/babylon.go | 2 +- clientcontroller/babylon_msg.go | 178 ++++++---------------------- clientcontroller/babylon_msg_log.go | 16 +-- 3 files changed, 42 insertions(+), 154 deletions(-) diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 71c81cb..a6f2b68 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -228,7 +228,7 @@ func (bc *BabylonController) reliablySendMsgsAsMultipleTxs(msgs []sdk.Msg) ([]*b return err } - txResponses, failedMsgs, err = reliablySendEachMsgAsTx(cfg, msgs, log, bc.bbnClient.RPCClient, encCfg, covAcc) + txResponses, failedMsgs, err = reliablySendEachMsgAsTx(cfg, bc.bbnClient.Provider(), msgs, log, encCfg, covAcc) return err }) if errAccKey != nil { diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go index 2baafa6..9bb63b3 100644 --- a/clientcontroller/babylon_msg.go +++ b/clientcontroller/babylon_msg.go @@ -16,12 +16,12 @@ import ( "cosmossdk.io/store/rootmulti" "github.com/avast/retry-go/v4" appparams "github.com/babylonlabs-io/babylon/app/params" + "github.com/babylonlabs-io/babylon/client/babylonclient" "github.com/babylonlabs-io/babylon/client/config" abci "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/crypto/merkle" - "github.com/cometbft/cometbft/libs/bytes" + rpcclient "github.com/cometbft/cometbft/rpc/client" + "github.com/cometbft/cometbft/rpc/client/http" coretypes "github.com/cometbft/cometbft/rpc/core/types" - tmtypes "github.com/cometbft/cometbft/types" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/codec" @@ -31,12 +31,8 @@ import ( legacyerrors "github.com/cosmos/cosmos-sdk/types/errors" txtypes "github.com/cosmos/cosmos-sdk/types/tx" "github.com/cosmos/cosmos-sdk/types/tx/signing" - "github.com/cosmos/relayer/v2/relayer/chains/cosmos" - "github.com/cosmos/relayer/v2/relayer/provider" "github.com/juju/fslock" - abcistrange "github.com/strangelove-ventures/cometbft-client/abci/types" - strangeloveclient "github.com/strangelove-ventures/cometbft-client/client" - rpcclient "github.com/strangelove-ventures/cometbft-client/rpc/client" + "go.uber.org/zap" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -65,16 +61,17 @@ type failedMsg struct { // reliablySendEachMsgAsTx creates multiple func reliablySendEachMsgAsTx( cfg *config.BabylonConfig, + cp *babylonclient.CosmosProvider, msgs []sdk.Msg, log *zap.Logger, - cometClient client.CometRPC, encCfg *appparams.EncodingConfig, covAcc sdk.AccountI, ) (txResponses []*sdk.TxResponse, failedMsgs []*failedMsg, err error) { - rpcClient, err := strangeloveclient.NewClient(cfg.RPCAddr, cfg.Timeout) + c, err := http.NewWithTimeout(cfg.RPCAddr, "/websocket", uint(cfg.Timeout.Seconds())) if err != nil { return nil, nil, err } + rpcClient := babylonclient.NewRPCClient(c) ctx := context.Background() @@ -97,9 +94,9 @@ func reliablySendEachMsgAsTx( go func( ctx context.Context, cfg *config.BabylonConfig, + cp *babylonclient.CosmosProvider, log *zap.Logger, - cometClient client.CometRPC, - rpcClient *strangeloveclient.Client, + rpcClient *babylonclient.RPCClient, encCfg *appparams.EncodingConfig, msg sdk.Msg, accSequence, accNumber uint64, @@ -107,7 +104,7 @@ func reliablySendEachMsgAsTx( msgIndex int, ) { - err := RetrySendMessagesToMempool(ctx, cfg, log, cometClient, rpcClient, encCfg, []sdk.Msg{msg}, accSequence, accNumber, callback) + err := RetrySendMessagesToMempool(ctx, cfg, cp, log, rpcClient, encCfg, []sdk.Msg{msg}, accSequence, accNumber, callback) if err != nil { if ErrorContained(err, expectedErrors) { log.Error("expected err when submitting the tx, skip retrying", zap.Error(err)) @@ -117,7 +114,7 @@ func reliablySendEachMsgAsTx( // If the callback was not invoked, decrement the wait group here wg.Done() } - }(ctx, cfg, log, cometClient, rpcClient, encCfg, msg, accSequence, accNumber, callback, msgIndex) + }(ctx, cfg, cp, log, &rpcClient, encCfg, msg, accSequence, accNumber, callback, msgIndex) accSequence++ } @@ -130,9 +127,9 @@ func reliablySendEachMsgAsTx( func RetrySendMessagesToMempool( ctx context.Context, cfg *config.BabylonConfig, + cp *babylonclient.CosmosProvider, log *zap.Logger, - cometClient client.CometRPC, - rpcClient *strangeloveclient.Client, + rpcClient *babylonclient.RPCClient, encCfg *appparams.EncodingConfig, msgs []sdk.Msg, @@ -142,7 +139,7 @@ func RetrySendMessagesToMempool( asyncCallbacks ...callbackTx, ) error { return retry.Do(func() error { - sendMsgErr := SendMessagesToMempool(ctx, cfg, log, cometClient, rpcClient, encCfg, msgs, accSequence, accNumber, asyncCallbacks...) + sendMsgErr := SendMessagesToMempool(ctx, cfg, cp, log, rpcClient, encCfg, msgs, accSequence, accNumber, asyncCallbacks...) if sendMsgErr != nil { if ErrorContained(sendMsgErr, unrecoverableErrors) { log.Error("unrecoverable err when submitting the tx, skip retrying", zap.Error(sendMsgErr)) @@ -163,9 +160,9 @@ func RetrySendMessagesToMempool( func SendMessagesToMempool( ctx context.Context, cfg *config.BabylonConfig, + cp *babylonclient.CosmosProvider, logger *zap.Logger, - cometClient client.CometRPC, - rpcClient *strangeloveclient.Client, + rpcClient *babylonclient.RPCClient, encCfg *appparams.EncodingConfig, msgs []sdk.Msg, @@ -174,17 +171,14 @@ func SendMessagesToMempool( asyncCallbacks ...callbackTx, ) error { - txSignerKey := cfg.Key memo, gas := "", uint64(0) - txBytes, fees, err := BuildMessages( - ctx, cfg, cometClient, rpcClient, encCfg, msgs, memo, gas, txSignerKey, accSequence, accNumber, - ) + txBytes, _, err := BuildMessages(ctx, cfg, cp, encCfg, msgs, accSequence, accNumber, memo, gas) if err != nil { return err } - err = BroadcastTx(ctx, logger, cfg, encCfg, rpcClient, txBytes, msgs, fees, ctx, defaultBroadcastWaitTimeout, asyncCallbacks) + err = BroadcastTx(ctx, logger, cfg, encCfg, rpcClient, txBytes, msgs, ctx, defaultBroadcastWaitTimeout, asyncCallbacks) if err != nil { return err } @@ -195,19 +189,19 @@ func SendMessagesToMempool( func BuildMessages( ctx context.Context, cfg *config.BabylonConfig, - cometClient client.CometRPC, - rpcClient *strangeloveclient.Client, + cp *babylonclient.CosmosProvider, encCfg *appparams.EncodingConfig, msgs []sdk.Msg, + accSequence, accNumber uint64, + // optional memo string, gas uint64, - txSignerKey string, - accSequence, accNumber uint64, ) ( txBytes []byte, fees sdk.Coins, err error, ) { + txSignerKey := cfg.Key keybase, err := KeybaseFromCfg(cfg, encCfg.Codec) if err != nil { return nil, sdk.Coins{}, err @@ -223,8 +217,7 @@ func BuildMessages( adjusted := gas if gas == 0 { - _, adjusted, err = CalculateGas(ctx, rpcClient, keybase, txf, txSignerKey, cfg.GasAdjustment, msgs...) - + _, adjusted, err = cp.CalculateGas(ctx, txf, txSignerKey, msgs...) if err != nil { return nil, sdk.Coins{}, err } @@ -264,10 +257,9 @@ func BroadcastTx( cfg *config.BabylonConfig, encCfg *appparams.EncodingConfig, - rpcClient *strangeloveclient.Client, + rpcClient *babylonclient.RPCClient, tx []byte, // raw tx to be broadcasted msgs []sdk.Msg, // used for logging only - fees sdk.Coins, // used for metrics asyncCtx context.Context, // context for async wait for block inclusion after successful tx broadcast asyncTimeout time.Duration, // timeout for waiting for block inclusion @@ -282,7 +274,7 @@ func BroadcastTx( // ResultBroadcastTx will be nil. return err } - rlyResp := &provider.RelayerTxResponse{ + rlyResp := &babylonclient.RelayerTxResponse{ TxHash: res.Hash.String(), Codespace: res.Codespace, Code: res.Code, @@ -306,65 +298,12 @@ func BroadcastTx( return nil } -// CalculateGas simulates a tx to generate the appropriate gas settings before broadcasting a tx. -func CalculateGas( - ctx context.Context, - rpcClient *strangeloveclient.Client, - keybase keyring.Keyring, - txf tx.Factory, - signingKey string, - gasAdjustment float64, - msgs ...sdk.Msg, -) (txtypes.SimulateResponse, uint64, error) { - keyInfo, err := keybase.Key(signingKey) - if err != nil { - return txtypes.SimulateResponse{}, 0, err - } - - var txBytes []byte - if err := retry.Do(func() error { - var err error - txBytes, err = BuildSimTx(keyInfo, txf, msgs...) - if err != nil { - return err - } - return nil - }, retry.Context(ctx), rtyAtt, rtyDel, rtyErr); err != nil { - return txtypes.SimulateResponse{}, 0, err - } - - simQuery := abci.RequestQuery{ - Path: "/cosmos.tx.v1beta1.Service/Simulate", - Data: txBytes, - } - - var res abcistrange.ResponseQuery - if err := retry.Do(func() error { - var err error - res, err = QueryABCI(ctx, rpcClient, simQuery) - if err != nil { - return err - } - return nil - }, retry.Context(ctx), rtyAtt, rtyDel, rtyErr); err != nil { - return txtypes.SimulateResponse{}, 0, err - } - - var simRes txtypes.SimulateResponse - if err := simRes.Unmarshal(res.Value); err != nil { - return txtypes.SimulateResponse{}, 0, err - } - - gas, err := AdjustEstimatedGas(gasAdjustment, simRes.GasInfo.GasUsed) - return simRes, gas, err -} - // waitForTx waits for a transaction to be included in a block, logs success/fail, then invokes callback. // This is intended to be called as an async goroutine. func waitForTx( ctx context.Context, log *zap.Logger, - rpcClient *strangeloveclient.Client, + rpcClient *babylonclient.RPCClient, cdc *codec.ProtoCodec, txConfig client.TxConfig, chainId string, @@ -385,7 +324,7 @@ func waitForTx( return } - rlyResp := &provider.RelayerTxResponse{ + rlyResp := &babylonclient.RelayerTxResponse{ Height: res.Height, TxHash: res.TxHash, Codespace: res.Codespace, @@ -426,7 +365,7 @@ func waitForTx( // waitForBlockInclusion will wait for a transaction to be included in a block, up to waitTimeout or context cancellation. func waitForBlockInclusion( ctx context.Context, - rpcClient *strangeloveclient.Client, + rpcClient *babylonclient.RPCClient, txConfig client.TxConfig, txHash []byte, waitTimeout time.Duration, @@ -435,12 +374,12 @@ func waitForBlockInclusion( for { select { case <-exitAfter: - return nil, fmt.Errorf("timed out after: %d; %w", waitTimeout, cosmos.ErrTimeoutAfterWaitingForTxBroadcast) + return nil, fmt.Errorf("timed out after: %d; %w", waitTimeout, babylonclient.ErrTimeoutAfterWaitingForTxBroadcast) // This fixed poll is fine because it's only for logging and updating prometheus metrics currently. case <-time.After(time.Millisecond * 100): res, err := rpcClient.Tx(ctx, txHash, false) if err == nil { - return mkTxResult(convertResultTx(res), txConfig) + return mkTxResult(res, txConfig) } if strings.Contains(err.Error(), "transaction indexing is disabled") { return nil, fmt.Errorf("cannot determine success/failure of tx because transaction indexing is disabled on rpc url") @@ -451,57 +390,6 @@ func waitForBlockInclusion( } } -func convertResultTx(res *strangeloveclient.TxResponse) *coretypes.ResultTx { - return &coretypes.ResultTx{ - Hash: bytes.HexBytes(res.Hash), - Height: res.Height, - Index: res.Index, - TxResult: abci.ExecTxResult{ - Code: res.ExecTx.Code, - Data: res.ExecTx.Data, - Log: res.ExecTx.Log, - Info: res.ExecTx.Info, - GasWanted: res.ExecTx.GasWanted, - GasUsed: res.ExecTx.GasUsed, - Events: converStringEvents(res.ExecTx.Events), - Codespace: res.ExecTx.Codespace, - }, - Tx: tmtypes.Tx(res.Tx), - Proof: tmtypes.TxProof{ - RootHash: bytes.HexBytes(res.Proof.RootHash), - Data: tmtypes.Tx(res.Proof.Data), - Proof: merkle.Proof{ - Total: res.Proof.Proof.Total, - Index: res.Proof.Proof.Index, - LeafHash: res.Proof.Proof.LeafHash, - Aunts: res.Proof.Proof.Aunts, - }, - }, - } -} - -func converStringEvents(events sdk.StringEvents) []abci.Event { - evts := make([]abci.Event, len(events)) - - for i, evt := range events { - attributes := make([]abci.EventAttribute, len(evt.Attributes)) - - for j, attr := range evt.Attributes { - attributes[j] = abci.EventAttribute{ - Key: attr.Key, - Value: attr.Value, - } - } - - evts[i] = abci.Event{ - Type: evt.Type, - Attributes: attributes, - } - } - - return evts -} - // mkTxResult decodes a comet transaction into an SDK TxResponse. func mkTxResult( resTx *coretypes.ResultTx, @@ -542,7 +430,7 @@ func AccessKeyWithLock(keyDir string, accessFunc func() error) error { } // QueryABCI performs an ABCI query and returns the appropriate response and error sdk error code. -func QueryABCI(ctx context.Context, rpcClient *strangeloveclient.Client, req abci.RequestQuery) (abcistrange.ResponseQuery, error) { +func QueryABCI(ctx context.Context, rpcClient *babylonclient.RPCClient, req abci.RequestQuery) (abci.ResponseQuery, error) { opts := rpcclient.ABCIQueryOptions{ Height: req.Height, Prove: req.Prove, @@ -550,11 +438,11 @@ func QueryABCI(ctx context.Context, rpcClient *strangeloveclient.Client, req abc result, err := rpcClient.ABCIQueryWithOptions(ctx, req.Path, req.Data, opts) if err != nil { - return abcistrange.ResponseQuery{}, err + return abci.ResponseQuery{}, err } if !result.Response.IsOK() { - return abcistrange.ResponseQuery{}, sdkErrorToGRPCError(result.Response.Code, result.Response.Log) + return abci.ResponseQuery{}, sdkErrorToGRPCError(result.Response.Code, result.Response.Log) } // data from trusted node or subspace query doesn't need verification diff --git a/clientcontroller/babylon_msg_log.go b/clientcontroller/babylon_msg_log.go index 1d197f9..c711050 100644 --- a/clientcontroller/babylon_msg_log.go +++ b/clientcontroller/babylon_msg_log.go @@ -4,6 +4,7 @@ import ( "errors" "reflect" + "github.com/babylonlabs-io/babylon/client/babylonclient" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" typestx "github.com/cosmos/cosmos-sdk/types/tx" @@ -11,13 +12,12 @@ import ( transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" chantypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" - "github.com/cosmos/relayer/v2/relayer/provider" "go.uber.org/zap" "go.uber.org/zap/zapcore" ) // LogFailedTx takes the transaction and the messages to create it and logs the appropriate data -func LogFailedTx(log *zap.Logger, chainId string, res *provider.RelayerTxResponse, err error, msgs []sdk.Msg) { +func LogFailedTx(log *zap.Logger, chainId string, res *babylonclient.RelayerTxResponse, err error, msgs []sdk.Msg) { // Include the chain_id fields := []zapcore.Field{zap.String("chain_id", chainId)} @@ -51,7 +51,7 @@ func LogFailedTx(log *zap.Logger, chainId string, res *provider.RelayerTxRespons if sdkErr := sdkError(res.Codespace, res.Code); err != nil { fields = append(fields, zap.NamedError("sdk_error", sdkErr)) } - fields = append(fields, zap.Object("response", res)) + fields = append(fields, zap.Any("response", res)) log.Warn( "Sent transaction but received failure response", fields..., @@ -105,7 +105,7 @@ func LogSuccessTx(log *zap.Logger, chainId string, cdc *codec.ProtoCodec, res *s } // getChannelsIfPresent scans the events for channel tags -func getChannelsIfPresent(events []provider.RelayerEvent) []zapcore.Field { +func getChannelsIfPresent(events []babylonclient.RelayerEvent) []zapcore.Field { channelTags := []string{srcChanTag, dstChanTag} fields := []zap.Field{} @@ -182,8 +182,8 @@ func getFeePayer(log *zap.Logger, cdc *codec.ProtoCodec, tx *typestx.Tx) string } } -func parseEventsFromTxResponse(resp *sdk.TxResponse) []provider.RelayerEvent { - var events []provider.RelayerEvent +func parseEventsFromTxResponse(resp *sdk.TxResponse) []babylonclient.RelayerEvent { + var events []babylonclient.RelayerEvent if resp == nil { return events @@ -195,7 +195,7 @@ func parseEventsFromTxResponse(resp *sdk.TxResponse) []provider.RelayerEvent { for _, attribute := range event.Attributes { attributes[attribute.Key] = attribute.Value } - events = append(events, provider.RelayerEvent{ + events = append(events, babylonclient.RelayerEvent{ EventType: event.Type, Attributes: attributes, }) @@ -210,7 +210,7 @@ func parseEventsFromTxResponse(resp *sdk.TxResponse) []provider.RelayerEvent { for _, attribute := range event.Attributes { attributes[attribute.Key] = attribute.Value } - events = append(events, provider.RelayerEvent{ + events = append(events, babylonclient.RelayerEvent{ EventType: event.Type, Attributes: attributes, }) From efb3b43e82a87803c05bec4f12b6e2038d8a94d5 Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 18 Feb 2025 16:00:01 -0300 Subject: [PATCH 27/31] chore: bump babylon to v1.0.0-rc.6 --- go.mod | 57 +++++++++---------- go.sum | 124 +++++++++++++++++++++++++----------------- itest/test_manager.go | 4 +- 3 files changed, 104 insertions(+), 81 deletions(-) diff --git a/go.mod b/go.mod index 17151bf..5ec36ac 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( cosmossdk.io/errors v1.0.1 cosmossdk.io/math v1.4.0 github.com/avast/retry-go/v4 v4.5.1 - github.com/babylonlabs-io/babylon v1.0.0-rc.4 + github.com/babylonlabs-io/babylon v1.0.0-rc.6 github.com/btcsuite/btcd v0.24.2 github.com/btcsuite/btcd/btcec/v2 v2.3.4 github.com/btcsuite/btcd/btcutil v1.1.6 @@ -26,23 +26,28 @@ require ( github.com/ory/dockertest/v3 v3.10.0 github.com/prometheus/client_golang v1.20.5 github.com/spf13/viper v1.19.0 - github.com/stretchr/testify v1.9.0 + github.com/stretchr/testify v1.10.0 github.com/urfave/cli v1.22.14 go.uber.org/zap v1.26.0 - golang.org/x/crypto v0.28.0 // indirect - golang.org/x/sync v0.8.0 // indirect + golang.org/x/crypto v0.32.0 // indirect + golang.org/x/sync v0.10.0 // indirect ) require ( + cosmossdk.io/store v1.1.1 + github.com/cometbft/cometbft v0.38.17 + github.com/cosmos/ibc-go/v8 v8.4.0 github.com/go-chi/chi/v5 v5.0.12 github.com/google/uuid v1.6.0 + github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b github.com/rs/zerolog v1.33.0 github.com/spf13/cobra v1.8.1 + google.golang.org/grpc v1.70.0 ) require ( cloud.google.com/go v0.112.1 // indirect - cloud.google.com/go/compute/metadata v0.5.0 // indirect + cloud.google.com/go/compute/metadata v0.5.2 // indirect cloud.google.com/go/iam v1.1.6 // indirect cloud.google.com/go/storage v1.38.0 // indirect cosmossdk.io/api v0.7.6 // indirect @@ -51,7 +56,6 @@ require ( cosmossdk.io/core v0.11.1 // indirect cosmossdk.io/depinject v1.1.0 // indirect cosmossdk.io/log v1.4.1 // indirect - cosmossdk.io/store v1.1.1 // indirect cosmossdk.io/x/circuit v0.1.1 // indirect cosmossdk.io/x/evidence v0.1.1 // indirect cosmossdk.io/x/feegrant v0.1.1 // indirect @@ -63,8 +67,8 @@ require ( github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect - github.com/CosmWasm/wasmd v0.53.0 // indirect - github.com/CosmWasm/wasmvm/v2 v2.1.3 // indirect + github.com/CosmWasm/wasmd v0.53.2 // indirect + github.com/CosmWasm/wasmvm/v2 v2.1.5 // indirect github.com/DataDog/datadog-go v3.2.0+incompatible // indirect github.com/DataDog/zstd v1.5.5 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect @@ -87,7 +91,6 @@ require ( github.com/cockroachdb/pebble v1.1.2 // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/cometbft/cometbft v0.38.15 // indirect github.com/cometbft/cometbft-db v0.15.0 // indirect github.com/containerd/continuity v0.3.0 // indirect github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect @@ -100,7 +103,6 @@ require ( github.com/cosmos/ibc-go/modules/apps/callbacks v0.2.1-0.20231113120333-342c00b0f8bd // indirect github.com/cosmos/ibc-go/modules/capability v1.0.1 // indirect github.com/cosmos/ibc-go/modules/light-clients/08-wasm v0.0.0-20240429153234-e1e6da7e4ead // indirect - github.com/cosmos/ibc-go/v8 v8.4.0 // indirect github.com/cosmos/ics23/go v0.11.0 // indirect github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect @@ -125,7 +127,7 @@ require ( github.com/go-kit/kit v0.13.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect @@ -166,7 +168,6 @@ require ( github.com/jinzhu/copier v0.3.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect - github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b // indirect github.com/kkdai/bstream v1.0.0 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect @@ -193,7 +194,7 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.60.1 // indirect + github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -215,6 +216,7 @@ require ( github.com/tendermint/go-amino v0.16.0 // indirect github.com/tidwall/btree v1.7.0 // indirect github.com/ulikunitz/xz v0.5.11 // indirect + github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.3 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect @@ -224,25 +226,24 @@ require ( go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect - go.opentelemetry.io/otel v1.24.0 // indirect - go.opentelemetry.io/otel/metric v1.24.0 // indirect - go.opentelemetry.io/otel/trace v1.24.0 // indirect + go.opentelemetry.io/otel v1.32.0 // indirect + go.opentelemetry.io/otel/metric v1.32.0 // indirect + go.opentelemetry.io/otel/trace v1.32.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.30.0 // indirect - golang.org/x/oauth2 v0.23.0 // indirect - golang.org/x/sys v0.26.0 // indirect - golang.org/x/term v0.25.0 // indirect - golang.org/x/text v0.19.0 // indirect + golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect + golang.org/x/mod v0.19.0 // indirect + golang.org/x/net v0.34.0 // indirect + golang.org/x/oauth2 v0.24.0 // indirect + golang.org/x/sys v0.29.0 // indirect + golang.org/x/term v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect + golang.org/x/tools v0.23.0 // indirect google.golang.org/api v0.171.0 // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect - google.golang.org/grpc v1.67.1 // indirect - google.golang.org/protobuf v1.35.1 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/protobuf v1.36.4 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 3a4cf02..724cd41 100644 --- a/go.sum +++ b/go.sum @@ -68,8 +68,8 @@ cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= -cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= +cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= +cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= @@ -224,10 +224,10 @@ github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg6 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/CosmWasm/wasmd v0.53.0 h1:kdaoAi20bIb4VCsxw9pRaT2g5PpIp82Wqrr9DRVN9ao= -github.com/CosmWasm/wasmd v0.53.0/go.mod h1:FJl/aWjdpGof3usAMFQpDe07Rkx77PUzp0cygFMOvtw= -github.com/CosmWasm/wasmvm/v2 v2.1.3 h1:CSJTauZqkHyb9yic6JVYCjiGUgxI2MJV2QzfSu8m49c= -github.com/CosmWasm/wasmvm/v2 v2.1.3/go.mod h1:bMhLQL4Yp9CzJi9A83aR7VO9wockOsSlZbT4ztOl6bg= +github.com/CosmWasm/wasmd v0.53.2 h1:c3MQjeQq+r+Zj2rPeW+c9kJmTevuNnZOIkiiCP/3bg4= +github.com/CosmWasm/wasmd v0.53.2/go.mod h1:gP10E56tuToU5rsZR7vZLBL5ssW2mie6KN/WrQLG7/I= +github.com/CosmWasm/wasmvm/v2 v2.1.5 h1:cYI1Ook1IAA5DFA0IVvDQQboorNHZPAZ7emBBHFmXSQ= +github.com/CosmWasm/wasmvm/v2 v2.1.5/go.mod h1:bMhLQL4Yp9CzJi9A83aR7VO9wockOsSlZbT4ztOl6bg= github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= @@ -267,8 +267,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX github.com/aws/aws-sdk-go v1.44.312 h1:llrElfzeqG/YOLFFKjg1xNpZCFJ2xraIi3PqSuP+95k= github.com/aws/aws-sdk-go v1.44.312/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/babylonlabs-io/babylon v1.0.0-rc.4 h1:fZNqUxyfGNwk7bJddglbDkEYsbNAB8jaaxaxRepb2Ow= -github.com/babylonlabs-io/babylon v1.0.0-rc.4/go.mod h1:4nCZ40ZbUFMG7OkbYV91rhwSZUmjBBNc4c3RGLrtrUY= +github.com/babylonlabs-io/babylon v1.0.0-rc.6 h1:qLgyVtLMIWeOR+lnLEXzE9rNTA+lpuuH3FIrObXviBU= +github.com/babylonlabs-io/babylon v1.0.0-rc.6/go.mod h1:lAswl51aYhmOCgPnQOMLA5lbjgSY3l9LfxeawkkEZmY= github.com/babylonlabs-io/btcd/btcec/v2 v2.3.4-babylon.rc.0 h1:BVqjtFpXKYnaPMTfrWgt0sg03jZMywNzz142ZV9ck+g= github.com/babylonlabs-io/btcd/btcec/v2 v2.3.4-babylon.rc.0/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -362,8 +362,8 @@ github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/cometbft/cometbft v0.38.15 h1:5veFd8k1uXM27PBg9sMO3hAfRJ3vbh4OmmLf6cVrqXg= -github.com/cometbft/cometbft v0.38.15/go.mod h1:+wh6ap6xctVG+JOHwbl8pPKZ0GeqdPYqISu7F4b43cQ= +github.com/cometbft/cometbft v0.38.17 h1:FkrQNbAjiFqXydeAO81FUzriL4Bz0abYxN/eOHrQGOk= +github.com/cometbft/cometbft v0.38.17/go.mod h1:5l0SkgeLRXi6bBfQuevXjKqML1jjfJJlvI1Ulp02/o4= github.com/cometbft/cometbft-db v0.15.0 h1:VLtsRt8udD4jHCyjvrsTBpgz83qne5hnL245AcPJVRk= github.com/cometbft/cometbft-db v0.15.0/go.mod h1:EBrFs1GDRiTqrWXYi4v90Awf/gcdD5ExzdPbg4X8+mk= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= @@ -474,6 +474,8 @@ github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/ferranbt/fastssz v0.0.0-20210120143747-11b9eff30ea9 h1:9VDpsWq096+oGMDTT/SgBD/VgZYf4pTF+KTPmZ+OaKM= +github.com/ferranbt/fastssz v0.0.0-20210120143747-11b9eff30ea9/go.mod h1:DyEu2iuLBnb/T51BlsiO3yLYdJC6UbGMrIkqK1KmQxM= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= @@ -513,8 +515,8 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= @@ -648,6 +650,7 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -741,6 +744,8 @@ github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hdevalence/ed25519consensus v0.1.0 h1:jtBwzzcHuTmFrQN6xQZn6CQEO/V9f7HsjsjeEZ6auqU= github.com/hdevalence/ed25519consensus v0.1.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= +github.com/herumi/bls-eth-go-binary v0.0.0-20210130185500-57372fb27371 h1:LEw2KkKciJEr3eKDLzdZ/rjzSR6Y+BS6xKxdA78Bq6s= +github.com/herumi/bls-eth-go-binary v0.0.0-20210130185500-57372fb27371/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= @@ -848,6 +853,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q= github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= +github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU= +github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -859,6 +866,8 @@ 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.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +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/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA= @@ -973,8 +982,8 @@ github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt2 github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc= -github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -1060,8 +1069,9 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= @@ -1070,6 +1080,8 @@ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= +github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= +github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -1088,6 +1100,12 @@ github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= github.com/vulpine-io/io-test v1.0.0 h1:Ot8vMh+ssm1VWDAwJ3U4C5qG9aRnr5YfQFZPNZBAUGI= github.com/vulpine-io/io-test v1.0.0/go.mod h1:X1I+p5GCxVX9m4nFd1HBtr2bVX9v1ZE6x8w+Obt36AU= +github.com/wealdtech/go-eth2-types/v2 v2.5.2 h1:tiA6T88M6XQIbrV5Zz53l1G5HtRERcxQfmET225V4Ls= +github.com/wealdtech/go-eth2-types/v2 v2.5.2/go.mod h1:8lkNUbgklSQ4LZ2oMSuxSdR7WwJW3L9ge1dcoCVyzws= +github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.3 h1:SxrDVSr+oXuT1x8kZt4uWqNCvv5xXEGV9zd7cuSrZS8= +github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.3/go.mod h1:qiIimacW5NhVRy8o+YxWo9YrecXqDAKKbL0+sOa0SJ4= +github.com/wealdtech/go-eth2-wallet-types/v2 v2.8.2 h1:264/meVYWt1wFw6Mtn+xwkZkXjID42gNra4rycoiDXI= +github.com/wealdtech/go-eth2-wallet-types/v2 v2.8.2/go.mod h1:k6kmiKWSWBTd4OxFifTEkPaBLhZspnO2KFD5XJY9nqg= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -1125,14 +1143,16 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.4 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= -go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= -go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= -go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= -go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -1162,9 +1182,10 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= -golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1176,8 +1197,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= -golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1204,8 +1225,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1266,8 +1287,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1293,8 +1314,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= -golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= +golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1309,8 +1330,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1406,13 +1427,14 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= -golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= +golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= +golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1423,8 +1445,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1491,8 +1513,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1671,10 +1693,10 @@ google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= -google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a h1:OAiGFfOiA0v9MRYsSidp3ubZaBnteRUyn3xB2ZQ5G/E= +google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a/go.mod h1:jehYqy3+AhJU9ve55aNOaSml7wUXjF9x6z2LcCfpAhY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -1716,8 +1738,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= -google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1734,8 +1756,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= -google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/itest/test_manager.go b/itest/test_manager.go index 7ffd28b..1232e1b 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -247,7 +247,7 @@ func StartManagerWithFinalityProvider(t *testing.T, n int, shouldStartEmulator b func genTestFinalityProviderData(t *testing.T, babylonAddr sdk.AccAddress) *testFinalityProviderData { finalityProviderEOTSPrivKey, err := btcec.NewPrivateKey() require.NoError(t, err) - pop, err := bstypes.NewPoPBTC(babylonAddr, finalityProviderEOTSPrivKey) + pop, err := datagen.NewPoPBTC(babylonAddr, finalityProviderEOTSPrivKey) require.NoError(t, err) return &testFinalityProviderData{ @@ -360,7 +360,7 @@ func (tm *TestManager) InsertBTCDelegation( ) // proof-of-possession - pop, err := bstypes.NewPoPBTC(tm.CovBBNClient.GetKeyAddress(), delBtcPrivKey) + pop, err := datagen.NewPoPBTC(tm.CovBBNClient.GetKeyAddress(), delBtcPrivKey) require.NoError(t, err) // create and insert BTC headers which include the staking tx to get staking tx info From 4e48e7c82ba768788ed1b62f1d10f3f3886a479f Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 18 Feb 2025 21:53:14 -0300 Subject: [PATCH 28/31] chore: refactory send multiple msgs as tx --- clientcontroller/babylon.go | 32 +++++++++--------- clientcontroller/babylon_msg.go | 57 ++++++++++++++++++++------------- 2 files changed, 51 insertions(+), 38 deletions(-) diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index a6f2b68..069641d 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -2,7 +2,6 @@ package clientcontroller import ( "context" - "errors" "fmt" "math" "time" @@ -159,21 +158,22 @@ func (bc *BabylonController) reliablySendMsg(msg sdk.Msg) (*babylonclient.Relaye // SendMsgs first it tries to send all the messages in a single transaction // if it fails, sends each message in a different transaction. func (bc *BabylonController) SendMsgs(msgs []sdk.Msg) ([]*types.TxResponse, error) { - resSingleTx, errSingleTx := bc.reliablySendMsgs(msgs) - if errSingleTx != nil { - // failed to send as a batch tx - resMultipleTxs, errMultipleTx := bc.reliablySendMsgsAsMultipleTxs(msgs) - if errMultipleTx != nil { - return nil, errors.Join(errSingleTx, errMultipleTx) - } - - return convertTxResp(resMultipleTxs...), nil - } - - if resSingleTx == nil { // some expected error happened - return []*types.TxResponse{}, nil - } - return convertTxResp(resSingleTx), nil + // resSingleTx, errSingleTx := bc.reliablySendMsgs(msgs) + // if errSingleTx != nil { + // failed to send as a batch tx + resMultipleTxs, errMultipleTx := bc.reliablySendMsgsAsMultipleTxs(msgs) + if errMultipleTx != nil { + // return nil, errors.Join(errSingleTx, errMultipleTx) + return nil, errMultipleTx + } + + return convertTxResp(resMultipleTxs...), nil + // } + + // if resSingleTx == nil { // some expected error happened + // return []*types.TxResponse{}, nil + // } + // return convertTxResp(resSingleTx), nil } func convertTxResp(txs ...*babylonclient.RelayerTxResponse) []*types.TxResponse { diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go index 9bb63b3..78e7ad1 100644 --- a/clientcontroller/babylon_msg.go +++ b/clientcontroller/babylon_msg.go @@ -17,6 +17,7 @@ import ( "github.com/avast/retry-go/v4" appparams "github.com/babylonlabs-io/babylon/app/params" "github.com/babylonlabs-io/babylon/client/babylonclient" + bbnclient "github.com/babylonlabs-io/babylon/client/client" "github.com/babylonlabs-io/babylon/client/config" abci "github.com/cometbft/cometbft/abci/types" rpcclient "github.com/cometbft/cometbft/rpc/client" @@ -201,7 +202,6 @@ func BuildMessages( fees sdk.Coins, err error, ) { - txSignerKey := cfg.Key keybase, err := KeybaseFromCfg(cfg, encCfg.Codec) if err != nil { return nil, sdk.Coins{}, err @@ -215,35 +215,48 @@ func BuildMessages( txf = txf.WithSequence(accSequence). WithAccountNumber(accNumber) - adjusted := gas - if gas == 0 { - _, adjusted, err = cp.CalculateGas(ctx, txf, txSignerKey, msgs...) - if err != nil { - return nil, sdk.Coins{}, err - } - } + txSignerKey := cfg.Key - // Set the gas amount on the transaction factory - txf = txf.WithGas(adjusted) + ws := &babylonclient.WalletState{ + NextAccountSequence: accSequence, + Mu: sync.Mutex{}, + } - // Build the transaction builder - txb, err := txf.BuildUnsignedTx(msgs...) + relayerMsgs := bbnclient.ToProviderMsgs(msgs) + txBytes, _, fees, err = cp.BuildMessages(ctx, txf, relayerMsgs, memo, 0, txSignerKey, ws) if err != nil { return nil, sdk.Coins{}, err } - if err = tx.Sign(ctx, txf, txSignerKey, txb, false); err != nil { - return nil, sdk.Coins{}, err - } + // adjusted := gas + // if gas == 0 { + // _, adjusted, err = cp.CalculateGas(ctx, txf, txSignerKey, msgs...) + // if err != nil { + // return nil, sdk.Coins{}, err + // } + // } - tx := txb.GetTx() - fees = tx.GetFee() + // // Set the gas amount on the transaction factory + // txf = txf.WithGas(adjusted) - // Generate the transaction bytes - txBytes, err = encCfg.TxConfig.TxEncoder()(tx) - if err != nil { - return nil, sdk.Coins{}, err - } + // // Build the transaction builder + // txb, err := txf.BuildUnsignedTx(msgs...) + // if err != nil { + // return nil, sdk.Coins{}, err + // } + + // if err = tx.Sign(ctx, txf, txSignerKey, txb, false); err != nil { + // return nil, sdk.Coins{}, err + // } + + // tx := txb.GetTx() + // fees = tx.GetFee() + + // // Generate the transaction bytes + // txBytes, err = encCfg.TxConfig.TxEncoder()(tx) + // if err != nil { + // return nil, sdk.Coins{}, err + // } return txBytes, fees, nil } From f30a3e18547223afc2a74ba1defec53d41cfa70e Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 18 Feb 2025 22:52:08 -0300 Subject: [PATCH 29/31] chore: reduce code duplication --- clientcontroller/babylon.go | 26 +- clientcontroller/babylon_msg.go | 405 +--------------------------- clientcontroller/babylon_msg_log.go | 221 --------------- 3 files changed, 15 insertions(+), 637 deletions(-) delete mode 100644 clientcontroller/babylon_msg_log.go diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 069641d..a48fe34 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -202,17 +202,13 @@ func (bc *BabylonController) reliablySendMsgsAsMultipleTxs(msgs []sdk.Msg) ([]*b log := bc.logger var ( - txResponses []*sdk.TxResponse + txResponses []*babylonclient.RelayerTxResponse failedMsgs []*failedMsg ) errAccKey := AccessKeyWithLock(cfg.KeyDirectory, func() error { - keybase, err := KeybaseFromCfg(cfg, encCfg.Codec) - if err != nil { - return err - } - - covAddr, err := GetKeyAddressForKey(keybase, cfg.Key) + cp := bc.bbnClient.Provider() + covAddr, err := cp.GetKeyAddressForKey(cfg.Key) if err != nil { return err } @@ -228,7 +224,7 @@ func (bc *BabylonController) reliablySendMsgsAsMultipleTxs(msgs []sdk.Msg) ([]*b return err } - txResponses, failedMsgs, err = reliablySendEachMsgAsTx(cfg, bc.bbnClient.Provider(), msgs, log, encCfg, covAcc) + txResponses, failedMsgs, err = reliablySendEachMsgAsTx(cfg, cp, msgs, log, encCfg, covAcc) return err }) if errAccKey != nil { @@ -243,19 +239,7 @@ func (bc *BabylonController) reliablySendMsgsAsMultipleTxs(msgs []sdk.Msg) ([]*b ) } - resp := make([]*babylonclient.RelayerTxResponse, len(txResponses)) - for i, res := range txResponses { - resp[i] = &babylonclient.RelayerTxResponse{ - Height: res.Height, - TxHash: res.TxHash, - Codespace: res.Codespace, - Code: res.Code, - Data: res.Data, - Events: parseEventsFromTxResponse(res), - } - } - - return resp, nil + return txResponses, nil } // SubmitCovenantSigs submits the Covenant signature via a MsgAddCovenantSig to Babylon if the daemon runs in Covenant mode diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go index 78e7ad1..8f433f6 100644 --- a/clientcontroller/babylon_msg.go +++ b/clientcontroller/babylon_msg.go @@ -3,7 +3,6 @@ package clientcontroller import ( "context" "fmt" - "math" "os" "path" "strings" @@ -13,30 +12,22 @@ import ( "errors" sdkerrors "cosmossdk.io/errors" - "cosmossdk.io/store/rootmulti" "github.com/avast/retry-go/v4" appparams "github.com/babylonlabs-io/babylon/app/params" "github.com/babylonlabs-io/babylon/client/babylonclient" bbnclient "github.com/babylonlabs-io/babylon/client/client" "github.com/babylonlabs-io/babylon/client/config" - abci "github.com/cometbft/cometbft/abci/types" - rpcclient "github.com/cometbft/cometbft/rpc/client" "github.com/cometbft/cometbft/rpc/client/http" - coretypes "github.com/cometbft/cometbft/rpc/core/types" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/crypto/keyring" sdk "github.com/cosmos/cosmos-sdk/types" - legacyerrors "github.com/cosmos/cosmos-sdk/types/errors" - txtypes "github.com/cosmos/cosmos-sdk/types/tx" "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/juju/fslock" "go.uber.org/zap" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" ) // Note: most of the functions were adappt from @@ -52,7 +43,7 @@ var ( ) // callbackTx is the expected type that waits for the inclusion of a transaction on the chain to be called -type callbackTx func(*sdk.TxResponse, error) +type callbackTx func(*babylonclient.RelayerTxResponse, error) type failedMsg struct { msg sdk.Msg @@ -67,7 +58,7 @@ func reliablySendEachMsgAsTx( log *zap.Logger, encCfg *appparams.EncodingConfig, covAcc sdk.AccountI, -) (txResponses []*sdk.TxResponse, failedMsgs []*failedMsg, err error) { +) (txResponses []*babylonclient.RelayerTxResponse, failedMsgs []*failedMsg, err error) { c, err := http.NewWithTimeout(cfg.RPCAddr, "/websocket", uint(cfg.Timeout.Seconds())) if err != nil { return nil, nil, err @@ -79,7 +70,7 @@ func reliablySendEachMsgAsTx( msgLen := len(msgs) // create outputs at msg len capacity to handle each msg in parallel // as it is easier than pass 2 channels for each func - txResponses = make([]*sdk.TxResponse, msgLen) + txResponses = make([]*babylonclient.RelayerTxResponse, msgLen) failedMsgs = make([]*failedMsg, msgLen) var wg sync.WaitGroup @@ -137,7 +128,7 @@ func RetrySendMessagesToMempool( accSequence, accNumber uint64, - asyncCallbacks ...callbackTx, + asyncCallbacks ...func(*babylonclient.RelayerTxResponse, error), ) error { return retry.Do(func() error { sendMsgErr := SendMessagesToMempool(ctx, cfg, cp, log, rpcClient, encCfg, msgs, accSequence, accNumber, asyncCallbacks...) @@ -170,7 +161,7 @@ func SendMessagesToMempool( accSequence, accNumber uint64, - asyncCallbacks ...callbackTx, + asyncCallbacks ...func(*babylonclient.RelayerTxResponse, error), ) error { memo, gas := "", uint64(0) @@ -179,7 +170,7 @@ func SendMessagesToMempool( return err } - err = BroadcastTx(ctx, logger, cfg, encCfg, rpcClient, txBytes, msgs, ctx, defaultBroadcastWaitTimeout, asyncCallbacks) + err = cp.BroadcastTx(ctx, txBytes, ctx, defaultBroadcastWaitTimeout, asyncCallbacks) if err != nil { return err } @@ -202,17 +193,8 @@ func BuildMessages( fees sdk.Coins, err error, ) { - keybase, err := KeybaseFromCfg(cfg, encCfg.Codec) - if err != nil { - return nil, sdk.Coins{}, err - } - - txf := TxFactory(cfg, encCfg.TxConfig, keybase) - if memo != "" { - txf = txf.WithMemo(memo) - } - - txf = txf.WithSequence(accSequence). + txf := TxFactory(cfg, encCfg.TxConfig). + WithSequence(accSequence). WithAccountNumber(accNumber) txSignerKey := cfg.Key @@ -228,200 +210,9 @@ func BuildMessages( return nil, sdk.Coins{}, err } - // adjusted := gas - // if gas == 0 { - // _, adjusted, err = cp.CalculateGas(ctx, txf, txSignerKey, msgs...) - // if err != nil { - // return nil, sdk.Coins{}, err - // } - // } - - // // Set the gas amount on the transaction factory - // txf = txf.WithGas(adjusted) - - // // Build the transaction builder - // txb, err := txf.BuildUnsignedTx(msgs...) - // if err != nil { - // return nil, sdk.Coins{}, err - // } - - // if err = tx.Sign(ctx, txf, txSignerKey, txb, false); err != nil { - // return nil, sdk.Coins{}, err - // } - - // tx := txb.GetTx() - // fees = tx.GetFee() - - // // Generate the transaction bytes - // txBytes, err = encCfg.TxConfig.TxEncoder()(tx) - // if err != nil { - // return nil, sdk.Coins{}, err - // } - return txBytes, fees, nil } -// BroadcastTx broadcasts a transaction with the given raw bytes and then, in an async goroutine, waits for the tx to be included in the block. -// The wait will end after either the asyncTimeout has run out or the asyncCtx exits. -// If there is no error broadcasting, the asyncCallback will be called with success/failure of the wait for block inclusion. -func BroadcastTx( - ctx context.Context, // context for tx broadcast - logger *zap.Logger, - cfg *config.BabylonConfig, - encCfg *appparams.EncodingConfig, - - rpcClient *babylonclient.RPCClient, - tx []byte, // raw tx to be broadcasted - msgs []sdk.Msg, // used for logging only - - asyncCtx context.Context, // context for async wait for block inclusion after successful tx broadcast - asyncTimeout time.Duration, // timeout for waiting for block inclusion - asyncCallbacks []callbackTx, // callback for success/fail of the wait for block inclusion -) error { - res, err := rpcClient.BroadcastTxSync(ctx, tx) - isErr := err != nil - isFailed := res != nil && res.Code != 0 - if isErr || isFailed { - if isErr && res == nil { - // There are some cases where BroadcastTxSync will return an error but the associated - // ResultBroadcastTx will be nil. - return err - } - rlyResp := &babylonclient.RelayerTxResponse{ - TxHash: res.Hash.String(), - Codespace: res.Codespace, - Code: res.Code, - Data: res.Data.String(), - } - if isFailed { - err = sdkError(res.Codespace, res.Code) - if err == nil { - err = fmt.Errorf("transaction failed to execute: codespace: %s, code: %d, log: %s", res.Codespace, res.Code, res.Log) - } - } - LogFailedTx(logger, cfg.ChainID, rlyResp, err, msgs) - return err - } - - // TODO: maybe we need to check if the node has tx indexing enabled? - // if not, we need to find a new way to block until inclusion in a block - protoCdc := codec.NewProtoCodec(encCfg.InterfaceRegistry) - go waitForTx(asyncCtx, logger, rpcClient, protoCdc, encCfg.TxConfig, cfg.ChainID, res.Hash, msgs, asyncTimeout, asyncCallbacks) - - return nil -} - -// waitForTx waits for a transaction to be included in a block, logs success/fail, then invokes callback. -// This is intended to be called as an async goroutine. -func waitForTx( - ctx context.Context, - log *zap.Logger, - rpcClient *babylonclient.RPCClient, - cdc *codec.ProtoCodec, - txConfig client.TxConfig, - chainId string, - txHash []byte, - msgs []sdk.Msg, // used for logging only - waitTimeout time.Duration, - callbacks []callbackTx, -) { - res, err := waitForBlockInclusion(ctx, rpcClient, txConfig, txHash, waitTimeout) - if err != nil { - log.Error("Failed to wait for block inclusion", zap.Error(err)) - if len(callbacks) > 0 { - for _, cb := range callbacks { - //Call each callback in order since waitForTx is already invoked asyncronously - cb(nil, err) - } - } - return - } - - rlyResp := &babylonclient.RelayerTxResponse{ - Height: res.Height, - TxHash: res.TxHash, - Codespace: res.Codespace, - Code: res.Code, - Data: res.Data, - Events: parseEventsFromTxResponse(res), - } - - // transaction was executed, log the success or failure using the tx response code - // NOTE: error is nil, logic should use the returned error to determine if the - // transaction was successfully executed. - - if res.Code != 0 { - // Check for any registered SDK errors - err := sdkError(res.Codespace, res.Code) - if err == nil { - err = fmt.Errorf("transaction failed to execute: codespace: %s, code: %d, log: %s", res.Codespace, res.Code, res.RawLog) - } - if len(callbacks) > 0 { - for _, cb := range callbacks { - //Call each callback in order since waitForTx is already invoked asyncronously - cb(nil, err) - } - } - LogFailedTx(log, chainId, rlyResp, nil, msgs) - return - } - - if len(callbacks) > 0 { - for _, cb := range callbacks { - //Call each callback in order since waitForTx is already invoked asyncronously - cb(res, nil) - } - } - LogSuccessTx(log, chainId, cdc, res, msgs) -} - -// waitForBlockInclusion will wait for a transaction to be included in a block, up to waitTimeout or context cancellation. -func waitForBlockInclusion( - ctx context.Context, - rpcClient *babylonclient.RPCClient, - txConfig client.TxConfig, - txHash []byte, - waitTimeout time.Duration, -) (*sdk.TxResponse, error) { - exitAfter := time.After(waitTimeout) - for { - select { - case <-exitAfter: - return nil, fmt.Errorf("timed out after: %d; %w", waitTimeout, babylonclient.ErrTimeoutAfterWaitingForTxBroadcast) - // This fixed poll is fine because it's only for logging and updating prometheus metrics currently. - case <-time.After(time.Millisecond * 100): - res, err := rpcClient.Tx(ctx, txHash, false) - if err == nil { - return mkTxResult(res, txConfig) - } - if strings.Contains(err.Error(), "transaction indexing is disabled") { - return nil, fmt.Errorf("cannot determine success/failure of tx because transaction indexing is disabled on rpc url") - } - case <-ctx.Done(): - return nil, ctx.Err() - } - } -} - -// mkTxResult decodes a comet transaction into an SDK TxResponse. -func mkTxResult( - resTx *coretypes.ResultTx, - txConfig client.TxConfig, -) (*sdk.TxResponse, error) { - txbz, err := txConfig.TxDecoder()(resTx.Tx) - if err != nil { - return nil, err - } - - p, ok := txbz.(intoAny) - if !ok { - return nil, fmt.Errorf("expecting a type implementing intoAny, got: %T", txbz) - } - - any := p.AsAny() - return sdk.NewResponseResultTx(resTx, any, ""), nil -} - func AccessKeyWithLock(keyDir string, accessFunc func() error) error { // use lock file to guard concurrent access to the keyring lockFilePath := path.Join(keyDir, "keys.lock") @@ -442,51 +233,6 @@ func AccessKeyWithLock(keyDir string, accessFunc func() error) error { return err } -// QueryABCI performs an ABCI query and returns the appropriate response and error sdk error code. -func QueryABCI(ctx context.Context, rpcClient *babylonclient.RPCClient, req abci.RequestQuery) (abci.ResponseQuery, error) { - opts := rpcclient.ABCIQueryOptions{ - Height: req.Height, - Prove: req.Prove, - } - - result, err := rpcClient.ABCIQueryWithOptions(ctx, req.Path, req.Data, opts) - if err != nil { - return abci.ResponseQuery{}, err - } - - if !result.Response.IsOK() { - return abci.ResponseQuery{}, sdkErrorToGRPCError(result.Response.Code, result.Response.Log) - } - - // data from trusted node or subspace query doesn't need verification - if !opts.Prove || !isQueryStoreWithProof(req.Path) { - return result.Response, nil - } - - return result.Response, nil -} - -// isQueryStoreWithProof expects a format like /<queryType>/<storeName>/<subpath> -// queryType must be "store" and subpath must be "key" to require a proof. -func isQueryStoreWithProof(path string) bool { - if !strings.HasPrefix(path, "/") { - return false - } - - paths := strings.SplitN(path[1:], "/", 3) - - switch { - case len(paths) != 3: - return false - case paths[0] != "store": - return false - case rootmulti.RequireProof("/" + paths[2]): - return true - } - - return false -} - func ErrorContained(err error, errList []*sdkerrors.Error) bool { for _, e := range errList { if strings.Contains(err.Error(), e.Error()) { @@ -510,77 +256,16 @@ func KeybaseFromCfg( ) } -// PrepareFactory mutates the tx factory with the appropriate account number, sequence number, and min gas settings. -func PrepareFactory( - cliCtx client.Context, - txf tx.Factory, - keybase keyring.Keyring, - signingKey string, -) (tx.Factory, error) { - var ( - err error - from sdk.AccAddress - num, seq uint64 - ) - - // Get key address and retry if fail - if err = retry.Do(func() error { - from, err = GetKeyAddressForKey(keybase, signingKey) - if err != nil { - return err - } - return err - }, rtyAtt, rtyDel, rtyErr); err != nil { - return tx.Factory{}, err - } - - cliCtx = cliCtx.WithFromAddress(from) - - // TODO: why this code? this may potentially require another query when we don't want one - initNum, initSeq := txf.AccountNumber(), txf.Sequence() - if initNum == 0 || initSeq == 0 { - if err = retry.Do(func() error { - num, seq, err = txf.AccountRetriever().GetAccountNumberSequence(cliCtx, from) - if err != nil { - return err - } - return err - }, rtyAtt, rtyDel, rtyErr); err != nil { - return txf, err - } - - if initNum == 0 { - txf = txf.WithAccountNumber(num) - } - - if initSeq == 0 { - txf = txf.WithSequence(seq) - } - } - - return txf, nil -} - -func GetKeyAddressForKey(keybase keyring.Keyring, key string) (sdk.AccAddress, error) { - info, err := keybase.Key(key) - if err != nil { - return nil, err - } - return info.GetAddress() -} - // TxFactory instantiates a new tx factory with the appropriate configuration settings for this chain. func TxFactory( cfg *config.BabylonConfig, txConf client.TxConfig, - keybase keyring.Keyring, ) tx.Factory { return tx.Factory{}. WithChainID(cfg.ChainID). WithTxConfig(txConf). WithGasAdjustment(cfg.GasAdjustment). WithGasPrices(cfg.GasPrices). - WithKeybase(keybase). WithSignMode(SignMode(cfg.SignModeStr)) } @@ -595,75 +280,6 @@ func SignMode(signModeStr string) signing.SignMode { } } -// BuildSimTx creates an unsigned tx with an empty single signature and returns -// the encoded transaction or an error if the unsigned transaction cannot be built. -func BuildSimTx(info *keyring.Record, txf tx.Factory, msgs ...sdk.Msg) ([]byte, error) { - txb, err := txf.BuildUnsignedTx(msgs...) - if err != nil { - return nil, err - } - - pk, err := info.GetPubKey() - if err != nil { - return nil, err - } - - // Create an empty signature literal as the ante handler will populate with a - // sentinel pubkey. - sig := signing.SignatureV2{ - PubKey: pk, - Data: &signing.SingleSignatureData{ - SignMode: txf.SignMode(), - }, - Sequence: txf.Sequence(), - } - if err := txb.SetSignatures(sig); err != nil { - return nil, err - } - - protoProvider, ok := txb.(protoTxProvider) - if !ok { - return nil, fmt.Errorf("cannot simulate amino tx") - } - - simReq := txtypes.SimulateRequest{Tx: protoProvider.GetProtoTx()} - return simReq.Marshal() -} - -// protoTxProvider is a type which can provide a proto transaction. It is a -// workaround to get access to the wrapper TxBuilder's method GetProtoTx(). -type protoTxProvider interface { - GetProtoTx() *txtypes.Tx -} - -func sdkErrorToGRPCError(code uint32, log string) error { - switch code { - case legacyerrors.ErrInvalidRequest.ABCICode(): - return status.Error(codes.InvalidArgument, log) - case legacyerrors.ErrUnauthorized.ABCICode(): - return status.Error(codes.Unauthenticated, log) - case legacyerrors.ErrKeyNotFound.ABCICode(): - return status.Error(codes.NotFound, log) - default: - return status.Error(codes.Unknown, log) - } -} - -// AdjustEstimatedGas adjusts the estimated gas usage by multiplying it by the gas adjustment factor -// and return estimated gas is higher than max gas error. If the gas usage is zero, the adjusted gas -// is also zero. -func AdjustEstimatedGas(gasAdjustment float64, gasUsed uint64) (uint64, error) { - if gasUsed == 0 { - return gasUsed, nil - } - - gas := gasAdjustment * float64(gasUsed) - if math.IsInf(gas, 1) { - return 0, fmt.Errorf("infinite gas used") - } - return uint64(gas), nil -} - // sdkError will return the Cosmos SDK registered error for a given codespace/code combo if registered, otherwise nil. func sdkError(codespace string, code uint32) error { // ABCIError will return an error other than "unknown" if syncRes.Code is a registered error in syncRes.Codespace @@ -697,10 +313,10 @@ func reliablySendEachMsgAsTxCallback( wg *sync.WaitGroup, msg sdk.Msg, msgIndex int, - txResponses []*sdk.TxResponse, + txResponses []*babylonclient.RelayerTxResponse, failedMsgs []*failedMsg, ) callbackTx { - return func(txResp *sdk.TxResponse, err error) { + return func(txResp *babylonclient.RelayerTxResponse, err error) { defer wg.Done() if err != nil { @@ -733,5 +349,4 @@ func reliablySendEachMsgAsTxCallback( ) txResponses[msgIndex] = txResp } - } diff --git a/clientcontroller/babylon_msg_log.go b/clientcontroller/babylon_msg_log.go deleted file mode 100644 index c711050..0000000 --- a/clientcontroller/babylon_msg_log.go +++ /dev/null @@ -1,221 +0,0 @@ -package clientcontroller - -import ( - "errors" - "reflect" - - "github.com/babylonlabs-io/babylon/client/babylonclient" - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - typestx "github.com/cosmos/cosmos-sdk/types/tx" - feetypes "github.com/cosmos/ibc-go/v8/modules/apps/29-fee/types" - transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" - chantypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" - "go.uber.org/zap" - "go.uber.org/zap/zapcore" -) - -// LogFailedTx takes the transaction and the messages to create it and logs the appropriate data -func LogFailedTx(log *zap.Logger, chainId string, res *babylonclient.RelayerTxResponse, err error, msgs []sdk.Msg) { - // Include the chain_id - fields := []zapcore.Field{zap.String("chain_id", chainId)} - - // Extract the channels from the events, if present - if res != nil { - channels := getChannelsIfPresent(res.Events) - fields = append(fields, channels...) - } - fields = append(fields, msgTypesField(msgs)) - - if err != nil { - - if errors.Is(err, chantypes.ErrRedundantTx) { - log.Debug("Redundant message(s)", fields...) - return - } - - // Make a copy since we may continue to the warning - errorFields := append(fields, zap.Error(err)) - log.Error( - "Failed sending cosmos transaction", - errorFields..., - ) - - if res == nil { - return - } - } - - if res.Code != 0 { - if sdkErr := sdkError(res.Codespace, res.Code); err != nil { - fields = append(fields, zap.NamedError("sdk_error", sdkErr)) - } - fields = append(fields, zap.Any("response", res)) - log.Warn( - "Sent transaction but received failure response", - fields..., - ) - } -} - -// LogSuccessTx take the transaction and the messages to create it and logs the appropriate data -func LogSuccessTx(log *zap.Logger, chainId string, cdc *codec.ProtoCodec, res *sdk.TxResponse, msgs []sdk.Msg) { - // Include the chain_id - fields := []zapcore.Field{zap.String("chain_id", chainId)} - - // Extract the channels from the events, if present - if res != nil { - events := parseEventsFromTxResponse(res) - fields = append(fields, getChannelsIfPresent(events)...) - } - - // Include the gas used - fields = append(fields, zap.Int64("gas_used", res.GasUsed)) - - var m sdk.Msg - if err := cdc.InterfaceRegistry().UnpackAny(res.Tx, &m); err == nil { - if tx, ok := m.(*typestx.Tx); ok { - fields = append(fields, zap.Stringer("fees", tx.GetFee())) - if feePayer := getFeePayer(log, cdc, tx); feePayer != "" { - fields = append(fields, zap.String("fee_payer", feePayer)) - } - } else { - log.Debug( - "Failed to convert message to Tx type", - zap.Stringer("type", reflect.TypeOf(m)), - ) - } - } else { - log.Debug("Failed to unpack response Tx into sdk.Msg", zap.Error(err)) - } - - // Include the height, msgType, and tx_hash - fields = append(fields, - zap.Int64("height", res.Height), - msgTypesField(msgs), - zap.String("tx_hash", res.TxHash), - ) - - // Log the successful transaction with fields - log.Info( - "Successful transaction", - fields..., - ) -} - -// getChannelsIfPresent scans the events for channel tags -func getChannelsIfPresent(events []babylonclient.RelayerEvent) []zapcore.Field { - channelTags := []string{srcChanTag, dstChanTag} - fields := []zap.Field{} - - // While a transaction may have multiple messages, we just need to first - // pair of channels - foundTag := map[string]struct{}{} - - for _, event := range events { - for _, tag := range channelTags { - for attributeKey, attributeValue := range event.Attributes { - if attributeKey == tag { - // Only append the tag once - // TODO: what if they are different? - if _, ok := foundTag[tag]; !ok { - fields = append(fields, zap.String(tag, attributeValue)) - foundTag[tag] = struct{}{} - } - } - } - } - } - return fields -} - -func msgTypesField(msgs []sdk.Msg) zap.Field { - msgTypes := make([]string, len(msgs)) - for i, m := range msgs { - msgTypes[i] = sdk.MsgTypeURL(m) - } - return zap.Strings("msg_types", msgTypes) -} - -// getFeePayer returns the bech32 address of the fee payer of a transaction. -// This uses the fee payer field if set, -// otherwise falls back to the address of whoever signed the first message. -func getFeePayer(log *zap.Logger, cdc *codec.ProtoCodec, tx *typestx.Tx) string { - payer := tx.AuthInfo.Fee.Payer - if payer != "" { - return payer - } - - switch firstMsg := tx.GetMsgs()[0].(type) { - case *transfertypes.MsgTransfer: - // There is a possible data race around concurrent map access - // in the cosmos sdk when it converts the address from bech32. - // We don't need the address conversion; just the sender is all that - // GetSigners is doing under the hood anyway. - return firstMsg.Sender - case *clienttypes.MsgCreateClient: - // Without this particular special case, there is a panic in ibc-go - // due to the sdk config singleton expecting one bech32 prefix but seeing another. - return firstMsg.Signer - case *clienttypes.MsgUpdateClient: - // Same failure mode as MsgCreateClient. - return firstMsg.Signer - case *clienttypes.MsgUpgradeClient: - return firstMsg.Signer - case *feetypes.MsgRegisterPayee: - return firstMsg.Relayer - case *feetypes.MsgRegisterCounterpartyPayee: - return firstMsg.Relayer - case *feetypes.MsgPayPacketFee: - return firstMsg.Signer - case *feetypes.MsgPayPacketFeeAsync: - return firstMsg.PacketFee.RefundAddress - default: - signers, _, err := cdc.GetMsgV1Signers(firstMsg) - if err != nil { - log.Info("Could not get signers for msg when attempting to get the fee payer", zap.Error(err)) - return "" - } - - return string(signers[0]) - } -} - -func parseEventsFromTxResponse(resp *sdk.TxResponse) []babylonclient.RelayerEvent { - var events []babylonclient.RelayerEvent - - if resp == nil { - return events - } - - for _, logs := range resp.Logs { - for _, event := range logs.Events { - attributes := make(map[string]string) - for _, attribute := range event.Attributes { - attributes[attribute.Key] = attribute.Value - } - events = append(events, babylonclient.RelayerEvent{ - EventType: event.Type, - Attributes: attributes, - }) - } - } - - // After SDK v0.50, indexed events are no longer provided in the logs on - // transaction execution, the response events can be directly used - if len(events) == 0 { - for _, event := range resp.Events { - attributes := make(map[string]string) - for _, attribute := range event.Attributes { - attributes[attribute.Key] = attribute.Value - } - events = append(events, babylonclient.RelayerEvent{ - EventType: event.Type, - Attributes: attributes, - }) - } - } - - return events -} From b2bc2ad68edcd3c50b284f9ed4d52008b8586395 Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Tue, 18 Feb 2025 22:56:22 -0300 Subject: [PATCH 30/31] fix: lint removed unused --- clientcontroller/babylon_msg.go | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/clientcontroller/babylon_msg.go b/clientcontroller/babylon_msg.go index 8f433f6..020e0b6 100644 --- a/clientcontroller/babylon_msg.go +++ b/clientcontroller/babylon_msg.go @@ -9,8 +9,6 @@ import ( "sync" "time" - "errors" - sdkerrors "cosmossdk.io/errors" "github.com/avast/retry-go/v4" appparams "github.com/babylonlabs-io/babylon/app/params" @@ -21,7 +19,6 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/crypto/keyring" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/tx/signing" @@ -38,8 +35,6 @@ var ( rtyDel = retry.Delay(time.Millisecond * 400) rtyErr = retry.LastErrorOnly(true) defaultBroadcastWaitTimeout = 10 * time.Minute - srcChanTag = "packet_src_channel" - dstChanTag = "packet_dst_channel" ) // callbackTx is the expected type that waits for the inclusion of a transaction on the chain to be called @@ -280,23 +275,6 @@ func SignMode(signModeStr string) signing.SignMode { } } -// sdkError will return the Cosmos SDK registered error for a given codespace/code combo if registered, otherwise nil. -func sdkError(codespace string, code uint32) error { - // ABCIError will return an error other than "unknown" if syncRes.Code is a registered error in syncRes.Codespace - // This catches all of the sdk errors https://github.com/cosmos/cosmos-sdk/blob/f10f5e5974d2ecbf9efc05bc0bfe1c99fdeed4b6/types/errors/errors.go - err := errors.Unwrap(sdkerrors.ABCIError(codespace, code, "error broadcasting transaction")) - if err.Error() != "unknown" { - return err - } - return nil -} - -// Deprecated: this interface is used only internally for scenario we are -// deprecating (StdTxConfig support) -type intoAny interface { - AsAny() *codectypes.Any -} - // CleanSlice removes nil values from a slice of pointers. func CleanSlice[T any](slice []*T) []*T { result := make([]*T, 0, len(slice)) From 082eb53fc1780a16fd4acb28a8724c46533cb92d Mon Sep 17 00:00:00 2001 From: RafilxTenfen <rafaeltenfen.rt@gmail.com> Date: Wed, 19 Feb 2025 09:20:28 -0300 Subject: [PATCH 31/31] chore: set to send one msg per tx if the batch fails --- clientcontroller/babylon.go | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index a48fe34..e373981 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -2,6 +2,7 @@ package clientcontroller import ( "context" + "errors" "fmt" "math" "time" @@ -158,22 +159,21 @@ func (bc *BabylonController) reliablySendMsg(msg sdk.Msg) (*babylonclient.Relaye // SendMsgs first it tries to send all the messages in a single transaction // if it fails, sends each message in a different transaction. func (bc *BabylonController) SendMsgs(msgs []sdk.Msg) ([]*types.TxResponse, error) { - // resSingleTx, errSingleTx := bc.reliablySendMsgs(msgs) - // if errSingleTx != nil { - // failed to send as a batch tx - resMultipleTxs, errMultipleTx := bc.reliablySendMsgsAsMultipleTxs(msgs) - if errMultipleTx != nil { - // return nil, errors.Join(errSingleTx, errMultipleTx) - return nil, errMultipleTx - } - - return convertTxResp(resMultipleTxs...), nil - // } - - // if resSingleTx == nil { // some expected error happened - // return []*types.TxResponse{}, nil - // } - // return convertTxResp(resSingleTx), nil + resSingleTx, errSingleTx := bc.reliablySendMsgs(msgs) + if errSingleTx != nil { + // failed to send as a batch tx + resMultipleTxs, errMultipleTx := bc.reliablySendMsgsAsMultipleTxs(msgs) + if errMultipleTx != nil { + return nil, errors.Join(errSingleTx, errMultipleTx) + } + + return convertTxResp(resMultipleTxs...), nil + } + + if resSingleTx == nil { // some expected error happened + return []*types.TxResponse{}, nil + } + return convertTxResp(resSingleTx), nil } func convertTxResp(txs ...*babylonclient.RelayerTxResponse) []*types.TxResponse {