diff --git a/x/btcbridge/keeper/keeper_deposit.go b/x/btcbridge/keeper/keeper_deposit.go index b2a1578..dd02d04 100644 --- a/x/btcbridge/keeper/keeper_deposit.go +++ b/x/btcbridge/keeper/keeper_deposit.go @@ -15,26 +15,26 @@ import ( ) // Process Bitcoin Deposit Transaction -func (k Keeper) ProcessBitcoinDepositTransaction(ctx sdk.Context, msg *types.MsgSubmitDepositTransactionRequest) error { +func (k Keeper) ProcessBitcoinDepositTransaction(ctx sdk.Context, msg *types.MsgSubmitDepositTransactionRequest) (*chainhash.Hash, btcutil.Address, error) { ctx.Logger().Info("accept bitcoin deposit tx", "blockhash", msg.Blockhash) param := k.GetParams(ctx) if !param.IsAuthorizedSender(msg.Sender) { - return types.ErrSenderAddressNotAuthorized + return nil, nil, types.ErrSenderAddressNotAuthorized } header := k.GetBlockHeader(ctx, msg.Blockhash) // Check if block confirmed if header == nil || header.Height == 0 { - return types.ErrBlockNotFound + return nil, nil, types.ErrBlockNotFound } best := k.GetBestBlockHeader(ctx) // Check if the block is confirmed if best.Height-header.Height < uint64(param.Confirmations) { - return types.ErrNotConfirmed + return nil, nil, types.ErrNotConfirmed } // Check if the block is within the acceptable depth // if best.Height-header.Height > param.MaxAcceptableBlockDepth { @@ -45,7 +45,7 @@ func (k Keeper) ProcessBitcoinDepositTransaction(ctx sdk.Context, msg *types.Msg txBytes, err := base64.StdEncoding.DecodeString(msg.TxBytes) if err != nil { fmt.Println("Error decoding transaction from base64:", err) - return err + return nil, nil, err } // Create a new transaction @@ -53,24 +53,24 @@ func (k Keeper) ProcessBitcoinDepositTransaction(ctx sdk.Context, msg *types.Msg err = tx.Deserialize(bytes.NewReader(txBytes)) if err != nil { fmt.Println("Error deserializing transaction:", err) - return err + return nil, nil, err } uTx := btcutil.NewTx(&tx) if len(uTx.MsgTx().TxIn) < 1 { - return types.ErrInvalidBtcTransaction + return nil, nil, types.ErrInvalidBtcTransaction } // Validate the transaction if err := blockchain.CheckTransactionSanity(uTx); err != nil { fmt.Println("Transaction is not valid:", err) - return err + return nil, nil, err } // Decode the previous transaction prevTxBytes, err := base64.StdEncoding.DecodeString(msg.PrevTxBytes) if err != nil { fmt.Println("Error decoding transaction from base64:", err) - return err + return nil, nil, err } // Create a new transaction @@ -78,21 +78,21 @@ func (k Keeper) ProcessBitcoinDepositTransaction(ctx sdk.Context, msg *types.Msg err = prevMsgTx.Deserialize(bytes.NewReader(prevTxBytes)) if err != nil { fmt.Println("Error deserializing transaction:", err) - return err + return nil, nil, err } prevTx := btcutil.NewTx(&prevMsgTx) if len(prevTx.MsgTx().TxOut) < 1 { - return types.ErrInvalidBtcTransaction + return nil, nil, types.ErrInvalidBtcTransaction } // Validate the transaction if err := blockchain.CheckTransactionSanity(prevTx); err != nil { fmt.Println("Transaction is not valid:", err) - return err + return nil, nil, err } if uTx.MsgTx().TxIn[0].PreviousOutPoint.Hash.String() != prevTx.Hash().String() { - return types.ErrInvalidBtcTransaction + return nil, nil, types.ErrInvalidBtcTransaction } chainCfg := sdk.GetConfig().GetBtcChainCfg() @@ -100,7 +100,7 @@ func (k Keeper) ProcessBitcoinDepositTransaction(ctx sdk.Context, msg *types.Msg // Extract the recipient address recipient, err := types.ExtractRecipientAddr(&tx, &prevMsgTx, param.Vaults, chainCfg) if err != nil { - return err + return nil, nil, err } // if pk.Class() != txscript.WitnessV1TaprootTy || pk.Class() != txscript.WitnessV0PubKeyHashTy || pk.Class() != txscript.WitnessV0ScriptHashTy { @@ -111,13 +111,13 @@ func (k Keeper) ProcessBitcoinDepositTransaction(ctx sdk.Context, msg *types.Msg // check if the proof is valid root, err := chainhash.NewHashFromStr(header.MerkleRoot) if err != nil { - return err + return nil, nil, err } txhash := uTx.MsgTx().TxHash() if !types.VerifyMerkleProof(msg.Proof, &txhash, root) { k.Logger(ctx).Error("Invalid merkle proof", "txhash", tx, "root", root, "proof", msg.Proof) - return types.ErrTransactionNotIncluded + return nil, nil, types.ErrTransactionNotIncluded } // mint voucher token and save utxo if the receiver is a vault address @@ -125,11 +125,11 @@ func (k Keeper) ProcessBitcoinDepositTransaction(ctx sdk.Context, msg *types.Msg // check if the output is a valid address pks, err := txscript.ParsePkScript(out.PkScript) if err != nil { - return err + return nil, nil, err } addr, err := pks.Address(chainCfg) if err != nil { - return err + return nil, nil, err } // check if the receiver is one of the voucher addresses vault := types.SelectVaultByBitcoinAddress(param.Vaults, addr.EncodeAddress()) @@ -143,14 +143,14 @@ func (k Keeper) ProcessBitcoinDepositTransaction(ctx sdk.Context, msg *types.Msg case types.AssetType_ASSET_TYPE_BTC: err := k.mintBTC(ctx, uTx, header.Height, recipient.EncodeAddress(), vault, out, i, param.BtcVoucherDenom) if err != nil { - return err + return nil, nil, err } case types.AssetType_ASSET_TYPE_RUNE: k.mintRUNE(ctx, uTx, header.Height, recipient.EncodeAddress(), vault, out, i, "rune") } } - return nil + return &txhash, recipient, nil } func (k Keeper) mintBTC(ctx sdk.Context, uTx *btcutil.Tx, height uint64, sender string, vault *types.Vault, out *wire.TxOut, vout int, denom string) error { diff --git a/x/btcbridge/keeper/keeper_withdraw.go b/x/btcbridge/keeper/keeper_withdraw.go index 3ec88a2..812c41c 100644 --- a/x/btcbridge/keeper/keeper_withdraw.go +++ b/x/btcbridge/keeper/keeper_withdraw.go @@ -8,6 +8,7 @@ import ( "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" sdk "github.com/cosmos/cosmos-sdk/types" @@ -160,37 +161,37 @@ func (k Keeper) FilterSigningRequestsByAddr(ctx sdk.Context, req *types.QuerySig } // Process Bitcoin Withdraw Transaction -func (k Keeper) ProcessBitcoinWithdrawTransaction(ctx sdk.Context, msg *types.MsgSubmitWithdrawTransactionRequest) error { +func (k Keeper) ProcessBitcoinWithdrawTransaction(ctx sdk.Context, msg *types.MsgSubmitWithdrawTransactionRequest) (*chainhash.Hash, error) { ctx.Logger().Info("accept bitcoin withdraw tx", "blockhash", msg.Blockhash) param := k.GetParams(ctx) if !param.IsAuthorizedSender(msg.Sender) { - return types.ErrSenderAddressNotAuthorized + return nil, types.ErrSenderAddressNotAuthorized } header := k.GetBlockHeader(ctx, msg.Blockhash) // Check if block confirmed if header == nil { - return types.ErrBlockNotFound + return nil, types.ErrBlockNotFound } best := k.GetBestBlockHeader(ctx) // Check if the block is confirmed if best.Height-header.Height < uint64(param.Confirmations) { - return types.ErrNotConfirmed + return nil, types.ErrNotConfirmed } // Check if the block is within the acceptable depth if best.Height-header.Height > param.MaxAcceptableBlockDepth { - return types.ErrExceedMaxAcceptanceDepth + return nil, types.ErrExceedMaxAcceptanceDepth } // Decode the base64 transaction txBytes, err := base64.StdEncoding.DecodeString(msg.TxBytes) if err != nil { fmt.Println("Error decoding transaction from base64:", err) - return err + return nil, err } // Create a new transaction @@ -198,18 +199,21 @@ func (k Keeper) ProcessBitcoinWithdrawTransaction(ctx sdk.Context, msg *types.Ms err = tx.Deserialize(bytes.NewReader(txBytes)) if err != nil { fmt.Println("Error deserializing transaction:", err) - return err + return nil, err } + uTx := btcutil.NewTx(&tx) if len(uTx.MsgTx().TxIn) < 1 { - return types.ErrInvalidBtcTransaction + return nil, types.ErrInvalidBtcTransaction } - if !k.HasSigningRequest(ctx, uTx.MsgTx().TxHash().String()) { - return types.ErrSigningRequestNotExist + txHash := uTx.MsgTx().TxHash() + + if !k.HasSigningRequest(ctx, txHash.String()) { + return nil, types.ErrSigningRequestNotExist } - signingRequest := k.GetSigningRequest(ctx, uTx.MsgTx().TxHash().String()) + signingRequest := k.GetSigningRequest(ctx, txHash.String()) // if signingRequest.Status != types.SigningStatus_SIGNING_STATUS_BROADCASTED || signingRequest.Status != types.SigningStatus_SIGNING_STATUS_SIGNED { // return types.ErrInvalidStatus // } @@ -219,11 +223,11 @@ func (k Keeper) ProcessBitcoinWithdrawTransaction(ctx sdk.Context, msg *types.Ms // Validate the transaction if err := blockchain.CheckTransactionSanity(uTx); err != nil { fmt.Println("Transaction is not valid:", err) - return err + return nil, err } if len(uTx.MsgTx().TxIn[0].Witness) != 2 { - return types.ErrInvalidSenders + return nil, types.ErrInvalidSenders } senderPubKey := uTx.MsgTx().TxIn[0].Witness[1] @@ -231,12 +235,12 @@ func (k Keeper) ProcessBitcoinWithdrawTransaction(ctx sdk.Context, msg *types.Ms // check if the first sender is one of the vault addresses vault := types.SelectVaultByPubKey(param.Vaults, hex.EncodeToString(senderPubKey)) if vault == nil { - return types.ErrInvalidSenders + return nil, types.ErrInvalidSenders } k.spendUTXOs(ctx, uTx) - return nil + return &txHash, nil } // spendUTXOs spends locked utxos diff --git a/x/btcbridge/keeper/msg_server.go b/x/btcbridge/keeper/msg_server.go index 21a4b52..1379ac5 100644 --- a/x/btcbridge/keeper/msg_server.go +++ b/x/btcbridge/keeper/msg_server.go @@ -57,7 +57,8 @@ func (m msgServer) SubmitDepositTransaction(goCtx context.Context, msg *types.Ms return nil, err } - if err := m.ProcessBitcoinDepositTransaction(ctx, msg); err != nil { + txHash, recipient, err := m.ProcessBitcoinDepositTransaction(ctx, msg) + if err != nil { ctx.Logger().Error("Error processing bitcoin deposit transaction", "error", err) return nil, err } @@ -66,7 +67,8 @@ func (m msgServer) SubmitDepositTransaction(goCtx context.Context, msg *types.Ms m.EmitEvent(ctx, msg.Sender, sdk.NewAttribute("blockhash", msg.Blockhash), sdk.NewAttribute("txBytes", msg.TxBytes), - sdk.NewAttribute("txid", MustGetTxId(msg.TxBytes)), + sdk.NewAttribute("txid", txHash.String()), + sdk.NewAttribute("recipient", recipient.EncodeAddress()), ) return &types.MsgSubmitDepositTransactionResponse{}, nil @@ -85,7 +87,8 @@ func (m msgServer) SubmitWithdrawTransaction(goCtx context.Context, msg *types.M return nil, err } - if err := m.ProcessBitcoinWithdrawTransaction(ctx, msg); err != nil { + txHash, err := m.ProcessBitcoinWithdrawTransaction(ctx, msg) + if err != nil { ctx.Logger().Error("Error processing bitcoin withdraw transaction", "error", err) return nil, err } @@ -94,7 +97,7 @@ func (m msgServer) SubmitWithdrawTransaction(goCtx context.Context, msg *types.M m.EmitEvent(ctx, msg.Sender, sdk.NewAttribute("blockhash", msg.Blockhash), sdk.NewAttribute("txBytes", msg.TxBytes), - sdk.NewAttribute("txid", MustGetTxId(msg.TxBytes)), + sdk.NewAttribute("txid", txHash.String()), ) return &types.MsgSubmitWithdrawTransactionResponse{}, nil diff --git a/x/btcbridge/keeper/util.go b/x/btcbridge/keeper/util.go index fdc99d4..56739bd 100644 --- a/x/btcbridge/keeper/util.go +++ b/x/btcbridge/keeper/util.go @@ -1,8 +1,6 @@ package keeper import ( - "bytes" - "encoding/base64" "math/big" "time" @@ -35,20 +33,3 @@ func BitsToTarget(bits string) *big.Int { func BitsToTargetUint32(bits string) uint32 { return uint32(BitsToTarget(bits).Uint64()) } - -// MustGetTxId returns the tx id of the given tx -// Panic if any error occured -func MustGetTxId(rawTxStr string) string { - txBytes, err := base64.StdEncoding.DecodeString(rawTxStr) - if err != nil { - panic(err) - } - - var tx wire.MsgTx - err = tx.Deserialize(bytes.NewReader(txBytes)) - if err != nil { - panic(err) - } - - return tx.TxHash().String() -}