Skip to content

Commit

Permalink
Merge branch 'dev' into sufay/fix-ci
Browse files Browse the repository at this point in the history
  • Loading branch information
liangping authored Jun 26, 2024
2 parents ec927fd + 44553f8 commit 5e0b525
Show file tree
Hide file tree
Showing 12 changed files with 874 additions and 149 deletions.
16 changes: 16 additions & 0 deletions proto/side/btcbridge/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ service Query {
rpc QuerySigningRequest(QuerySigningRequestRequest) returns (QuerySigningRequestResponse) {
option (google.api.http).get = "/sideprotocol/side/btcbridge/signing/request";
}
// QuerySigningRequestByAddress queries the signing request by the given address.
rpc QuerySigningRequestByAddress(QuerySigningRequestByAddressRequest) returns (QuerySigningRequestByAddressResponse) {
option (google.api.http).get = "/sideprotocol/side/btcbridge/signing/request/{address}";
}
// UTXOs queries all utxos.
rpc QueryUTXOs(QueryUTXOsRequest) returns (QueryUTXOsResponse) {
option (google.api.http).get = "/sideprotocol/side/btcbridge/utxos";
Expand All @@ -53,6 +57,18 @@ message QuerySigningRequestResponse {
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}

// QuerySigningRequestByAddressRequest is request type for the Query/SigningRequestByAddress RPC method.
message QuerySigningRequestByAddressRequest {
string address = 1;
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}

// QuerySigningRequestByAddressResponse is response type for the Query/SigningRequestByAddress RPC method.
message QuerySigningRequestByAddressResponse {
repeated BitcoinSigningRequest requests = 1;
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}

// QueryParamsRequest is request type for the Query/Params RPC method.
message QueryParamsRequest {}

Expand Down
2 changes: 1 addition & 1 deletion proto/side/btcbridge/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ message MsgWithdrawBitcoinRequest {
// withdraw amount in satoshi, etc: 100000000sat = 1btc
string amount = 2;
// fee rate in sats/vB
int64 fee_rate = 3;
string fee_rate = 3;
}

// MsgWithdrawBitcoinResponse defines the Msg/WithdrawBitcoin response type.
Expand Down
16 changes: 13 additions & 3 deletions x/btcbridge/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ func CmdQueryBlock() *cobra.Command {
// CmdQuerySigningRequest returns the command to query signing request
func CmdQuerySigningRequest() *cobra.Command {
cmd := &cobra.Command{
Use: "signing-request [status]",
Short: "Query all signing requests",
Use: "signing-request [status or address]",
Short: "Query signing requests by status or address",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
Expand All @@ -144,7 +144,17 @@ func CmdQuerySigningRequest() *cobra.Command {

status, err := strconv.ParseInt(args[0], 10, 32)
if err != nil {
return err
_, err = sdk.AccAddressFromBech32(args[0])
if err != nil {
return err
}

res, err := queryClient.QuerySigningRequestByAddress(cmd.Context(), &types.QuerySigningRequestByAddressRequest{Address: args[0]})
if err != nil {
return err
}

return clientCtx.PrintProto(res)
}

res, err := queryClient.QuerySigningRequest(cmd.Context(), &types.QuerySigningRequestRequest{Status: types.SigningStatus(status)})
Expand Down
8 changes: 1 addition & 7 deletions x/btcbridge/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"encoding/json"
"fmt"
"os"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -129,15 +128,10 @@ func CmdWithdrawBitcoin() *cobra.Command {
return fmt.Errorf("invalid amount")
}

feeRate, err := strconv.ParseInt(args[1], 10, 64)
if err != nil {
return fmt.Errorf("invalid fee rate")
}

msg := types.NewMsgWithdrawBitcoinRequest(
clientCtx.GetFromAddress().String(),
args[0],
feeRate,
args[1],
)

if err := msg.ValidateBasic(); err != nil {
Expand Down
40 changes: 21 additions & 19 deletions x/btcbridge/keeper/keeper_deposit.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,27 @@ import (
)

// Process Bitcoin Deposit Transaction

func (k Keeper) ProcessBitcoinDepositTransaction(ctx sdk.Context, msg *types.MsgSubmitDepositTransactionRequest) 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

Check failure on line 26 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (01)

too many return values

Check failure on line 26 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (00)

too many return values

Check failure on line 26 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (02)

too many return values

Check failure on line 26 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / Build (amd64, linux)

too many return values
}

header := k.GetBlockHeader(ctx, msg.Blockhash)
// Check if block confirmed
if header == nil || header.Height == 0 {
return types.ErrBlockNotFound
return nil, nil, types.ErrBlockNotFound

Check failure on line 32 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (01)

too many return values

Check failure on line 32 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (00)

too many return values

Check failure on line 32 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (02)

too many return values

Check failure on line 32 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / Build (amd64, linux)

too many return values
}

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 failure on line 38 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (01)

too many return values

Check failure on line 38 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (00)

too many return values

Check failure on line 38 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (02)

too many return values

Check failure on line 38 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / Build (amd64, linux)

too many return values
}
// Check if the block is within the acceptable depth
// if best.Height-header.Height > param.MaxAcceptableBlockDepth {
Expand All @@ -44,62 +46,62 @@ 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

Check failure on line 49 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (01)

too many return values

Check failure on line 49 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (00)

too many return values

Check failure on line 49 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (02)

too many return values

Check failure on line 49 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / Build (amd64, linux)

too many return values
}

// Create a new transaction
var tx wire.MsgTx
err = tx.Deserialize(bytes.NewReader(txBytes))
if err != nil {
fmt.Println("Error deserializing transaction:", err)
return err
return nil, nil, err

Check failure on line 57 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (01)

too many return values

Check failure on line 57 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (00)

too many return values

Check failure on line 57 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (02)

too many return values

Check failure on line 57 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / Build (amd64, linux)

too many return values
}
uTx := btcutil.NewTx(&tx)
if len(uTx.MsgTx().TxIn) < 1 {
return types.ErrInvalidBtcTransaction
return nil, nil, types.ErrInvalidBtcTransaction

Check failure on line 61 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (01)

too many return values

Check failure on line 61 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (00)

too many return values

Check failure on line 61 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (02)

too many return values

Check failure on line 61 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / Build (amd64, linux)

too many return values
}

// Validate the transaction
if err := blockchain.CheckTransactionSanity(uTx); err != nil {
fmt.Println("Transaction is not valid:", err)
return err
return nil, nil, err

Check failure on line 67 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (01)

too many return values

Check failure on line 67 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (00)

too many return values

Check failure on line 67 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (02)

too many return values

Check failure on line 67 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / Build (amd64, linux)

too many return values
}

// 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

Check failure on line 74 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (01)

too many return values

Check failure on line 74 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (00)

too many return values

Check failure on line 74 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (02)

too many return values

Check failure on line 74 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / Build (amd64, linux)

too many return values
}

// Create a new transaction
var prevMsgTx wire.MsgTx
err = prevMsgTx.Deserialize(bytes.NewReader(prevTxBytes))
if err != nil {
fmt.Println("Error deserializing transaction:", err)
return err
return nil, nil, err

Check failure on line 82 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (01)

too many return values

Check failure on line 82 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (00)

too many return values

Check failure on line 82 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (02)

too many return values

Check failure on line 82 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / Build (amd64, linux)

too many return values
}

prevTx := btcutil.NewTx(&prevMsgTx)
if len(prevTx.MsgTx().TxOut) < 1 {
return types.ErrInvalidBtcTransaction
return nil, nil, types.ErrInvalidBtcTransaction

Check failure on line 87 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (01)

too many return values

Check failure on line 87 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (00)

too many return values

Check failure on line 87 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / tests (02)

too many return values

Check failure on line 87 in x/btcbridge/keeper/keeper_deposit.go

View workflow job for this annotation

GitHub Actions / Build (amd64, linux)

too many return values
}
// 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()

// 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 {
Expand All @@ -110,25 +112,25 @@ 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
for i, out := range uTx.MsgTx().TxOut {
// 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())
Expand All @@ -142,14 +144,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 {
Expand Down
50 changes: 36 additions & 14 deletions x/btcbridge/keeper/keeper_withdraw.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -143,56 +144,77 @@ func (k Keeper) FilterSigningRequestsByStatus(ctx sdk.Context, req *types.QueryS
return signingRequests
}

// filter SigningRequest by address with pagination
func (k Keeper) FilterSigningRequestsByAddr(ctx sdk.Context, req *types.QuerySigningRequestByAddressRequest) []*types.BitcoinSigningRequest {
var signingRequests []*types.BitcoinSigningRequest
k.IterateSigningRequests(ctx, func(signingRequest types.BitcoinSigningRequest) (stop bool) {
if signingRequest.Address == req.Address {
signingRequests = append(signingRequests, &signingRequest)
}
// pagination TODO: limit the number of signing requests
if len(signingRequests) >= 100 {
return true
}
return false
})
return signingRequests
}

// Process Bitcoin Withdraw Transaction

func (k Keeper) ProcessBitcoinWithdrawTransaction(ctx sdk.Context, msg *types.MsgSubmitWithdrawTransactionRequest) 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
var tx wire.MsgTx
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
// }
Expand All @@ -202,24 +224,24 @@ 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]

// 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
Expand Down
Loading

0 comments on commit 5e0b525

Please sign in to comment.