Skip to content

Commit

Permalink
Merge pull request #23 from somatic-labs/faddat/build-and-sign
Browse files Browse the repository at this point in the history
add more code for grpc broadcast
  • Loading branch information
faddat authored Oct 24, 2024
2 parents 28a4e3f + 8302009 commit 43d083a
Show file tree
Hide file tree
Showing 8 changed files with 351 additions and 151 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
on:
push:
branches:
- main
pull_request:
branches:
- main
name: Build
jobs:
build:
strategy:
matrix:
go-version: [1.23.x]
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- run: go build ./...
146 changes: 0 additions & 146 deletions broadcast/broadcast.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,11 @@ import (
cometrpc "github.com/cometbft/cometbft/rpc/client/http"
coretypes "github.com/cometbft/cometbft/rpc/core/types"
tmtypes "github.com/cometbft/cometbft/types"
"github.com/cosmos/ibc-go/modules/apps/callbacks/testing/simapp/params"
"github.com/cosmos/ibc-go/v8/modules/apps/transfer"
transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types"
ibc "github.com/cosmos/ibc-go/v8/modules/core"
meteoritebank "github.com/somatic-labs/meteorite/modules/bank"
meteoriteibc "github.com/somatic-labs/meteorite/modules/ibc"
wasm "github.com/somatic-labs/meteorite/modules/wasm"
types "github.com/somatic-labs/meteorite/types"

sdkmath "cosmossdk.io/math"

"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/std"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
"github.com/cosmos/cosmos-sdk/x/bank"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/gov"

wasmd "github.com/CosmWasm/wasmd/x/wasm"
)

var cdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry())
Expand All @@ -40,134 +22,6 @@ func init() {
banktypes.RegisterInterfaces(cdc.InterfaceRegistry())
}

// SendTransactionViaRPC sends a transaction using the provided TransactionParams and sequence number.
func SendTransactionViaRPC(txParams types.TransactionParams, sequence uint64) (response *coretypes.ResultBroadcastTx, txbody string, err error) {
encodingConfig := params.MakeTestEncodingConfig()
encodingConfig.Codec = cdc

// Register IBC and other necessary types
transferModule := transfer.AppModuleBasic{}
ibcModule := ibc.AppModuleBasic{}
bankModule := bank.AppModuleBasic{}
wasmModule := wasmd.AppModuleBasic{}
govModule := gov.AppModuleBasic{}

ibcModule.RegisterInterfaces(encodingConfig.InterfaceRegistry)
transferModule.RegisterInterfaces(encodingConfig.InterfaceRegistry)
bankModule.RegisterInterfaces(encodingConfig.InterfaceRegistry)
wasmModule.RegisterInterfaces(encodingConfig.InterfaceRegistry)
govModule.RegisterInterfaces(encodingConfig.InterfaceRegistry)
std.RegisterInterfaces(encodingConfig.InterfaceRegistry)

// Create a new TxBuilder.
txBuilder := encodingConfig.TxConfig.NewTxBuilder()

var msg sdk.Msg
var memo string // Declare a variable to hold the memo

switch txParams.MsgType {
case "ibc_transfer":
msg, memo, err = meteoriteibc.CreateIBCTransferMsg(txParams.Config, txParams.AcctAddress, txParams.MsgParams)
if err != nil {
return nil, "", err
}
case "bank_send":
msg, memo, err = meteoritebank.CreateBankSendMsg(txParams.Config, txParams.AcctAddress, txParams.MsgParams)
if err != nil {
return nil, "", err
}
case "store_code":
msg, memo, err = wasm.CreateStoreCodeMsg(txParams.Config, txParams.AcctAddress, txParams.MsgParams)
if err != nil {
return nil, "", err
}
case "instantiate_contract":
msg, memo, err = wasm.CreateInstantiateContractMsg(txParams.Config, txParams.AcctAddress, txParams.MsgParams)
if err != nil {
return nil, "", err
}
default:
return nil, "", fmt.Errorf("unsupported message type: %s", txParams.MsgType)
}

// Set messages
err = txBuilder.SetMsgs(msg)
if err != nil {
return nil, "", err
}

// Estimate gas limit based on transaction size
txSize := len(msg.String())
gasLimit := uint64((int64(txSize) * txParams.Config.Bytes) + txParams.Config.BaseGas)
txBuilder.SetGasLimit(gasLimit)

// Calculate fee based on gas limit and a fixed gas price
gasPrice := sdk.NewDecCoinFromDec(txParams.Config.Denom, sdkmath.LegacyNewDecWithPrec(txParams.Config.Gas.Low, txParams.Config.Gas.Precision))
feeAmount := gasPrice.Amount.MulInt64(int64(gasLimit)).RoundInt()
feecoin := sdk.NewCoin(txParams.Config.Denom, feeAmount)
txBuilder.SetFeeAmount(sdk.NewCoins(feecoin))

// Set the memo (either random for bank_send or as per IBC transfer)
txBuilder.SetMemo(memo)
txBuilder.SetTimeoutHeight(0)

// First round: gather all the signer infos using the "set empty signature" hack
sigV2 := signing.SignatureV2{
PubKey: txParams.PubKey,
Sequence: sequence,
Data: &signing.SingleSignatureData{
SignMode: signing.SignMode(encodingConfig.TxConfig.SignModeHandler().DefaultMode()),
},
}

err = txBuilder.SetSignatures(sigV2)
if err != nil {
fmt.Println("Error setting signatures")
return nil, "", err
}

signerData := authsigning.SignerData{
ChainID: txParams.ChainID,
AccountNumber: txParams.AccNum,
Sequence: sequence,
}

ctx := context.Background()

signed, err := tx.SignWithPrivKey(
ctx,
signing.SignMode(encodingConfig.TxConfig.SignModeHandler().DefaultMode()),
signerData,
txBuilder,
txParams.PrivKey,
encodingConfig.TxConfig,
sequence,
)
if err != nil {
fmt.Println("Couldn't sign")
return nil, "", err
}

err = txBuilder.SetSignatures(signed)
if err != nil {
return nil, "", err
}

// Generate the encoded transaction bytes
txBytes, err := encodingConfig.TxConfig.TxEncoder()(txBuilder.GetTx())
if err != nil {
fmt.Println(err)
return nil, "", err
}

resp, err := Transaction(txBytes, txParams.NodeURL)
if err != nil {
return resp, string(txBytes), fmt.Errorf("failed to broadcast transaction: %w", err)
}

return resp, string(txBytes), nil
}

// Transaction broadcasts the transaction bytes to the given RPC endpoint.
func Transaction(txBytes []byte, rpcEndpoint string) (*coretypes.ResultBroadcastTx, error) {
cmtCli, err := cometrpc.New(rpcEndpoint, "/websocket")
Expand Down
158 changes: 158 additions & 0 deletions broadcast/grpc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package broadcast

import (
"context"
"fmt"

"github.com/cosmos/ibc-go/modules/apps/callbacks/testing/simapp/params"
"github.com/cosmos/ibc-go/v8/modules/apps/transfer"
ibc "github.com/cosmos/ibc-go/v8/modules/core"
client "github.com/somatic-labs/meteorite/client"
meteoritebank "github.com/somatic-labs/meteorite/modules/bank"
meteoriteibc "github.com/somatic-labs/meteorite/modules/ibc"
wasm "github.com/somatic-labs/meteorite/modules/wasm"
types "github.com/somatic-labs/meteorite/types"

sdkmath "cosmossdk.io/math"

"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/std"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/gov"

wasmd "github.com/CosmWasm/wasmd/x/wasm"
)

func SendTransactionViaGRPC(
ctx context.Context,
txParams types.TransactionParams,
sequence uint64,
grpcClient *client.GRPCClient,
) (*sdk.TxResponse, string, error) {
encodingConfig := params.MakeTestEncodingConfig()
encodingConfig.Codec = cdc

// Register necessary interfaces
transferModule := transfer.AppModuleBasic{}
ibcModule := ibc.AppModuleBasic{}
bankModule := bank.AppModuleBasic{}
wasmModule := wasmd.AppModuleBasic{}
govModule := gov.AppModuleBasic{}

ibcModule.RegisterInterfaces(encodingConfig.InterfaceRegistry)
transferModule.RegisterInterfaces(encodingConfig.InterfaceRegistry)
bankModule.RegisterInterfaces(encodingConfig.InterfaceRegistry)
wasmModule.RegisterInterfaces(encodingConfig.InterfaceRegistry)
govModule.RegisterInterfaces(encodingConfig.InterfaceRegistry)
std.RegisterInterfaces(encodingConfig.InterfaceRegistry)

// Create a new TxBuilder.
txBuilder := encodingConfig.TxConfig.NewTxBuilder()

var msg sdk.Msg
var memo string

// Construct the message based on the message type
switch txParams.MsgType {
case "ibc_transfer":
var err error
msg, memo, err = meteoriteibc.CreateIBCTransferMsg(txParams.Config, txParams.AcctAddress, txParams.MsgParams)
if err != nil {
return nil, "", err
}
case "bank_send":
var err error
msg, memo, err = meteoritebank.CreateBankSendMsg(txParams.Config, txParams.AcctAddress, txParams.MsgParams)
if err != nil {
return nil, "", err
}
case "store_code":
var err error
msg, memo, err = wasm.CreateStoreCodeMsg(txParams.Config, txParams.AcctAddress, txParams.MsgParams)
if err != nil {
return nil, "", err
}
case "instantiate_contract":
var err error
msg, memo, err = wasm.CreateInstantiateContractMsg(txParams.Config, txParams.AcctAddress, txParams.MsgParams)
if err != nil {
return nil, "", err
}
default:
return nil, "", fmt.Errorf("unsupported message type: %s", txParams.MsgType)
}

// Set the message and other transaction parameters
if err := txBuilder.SetMsgs(msg); err != nil {
return nil, "", err
}

// Estimate gas limit
txSize := len(msg.String())
gasLimit := uint64((int64(txSize) * txParams.Config.Bytes) + txParams.Config.BaseGas)
txBuilder.SetGasLimit(gasLimit)

// Calculate fee
gasPrice := sdk.NewDecCoinFromDec(txParams.Config.Denom, sdkmath.LegacyNewDecWithPrec(txParams.Config.Gas.Low, txParams.Config.Gas.Precision))
feeAmount := gasPrice.Amount.MulInt64(int64(gasLimit)).RoundInt()
feeCoin := sdk.NewCoin(txParams.Config.Denom, feeAmount)
txBuilder.SetFeeAmount(sdk.NewCoins(feeCoin))

// Set memo and timeout height
txBuilder.SetMemo(memo)
txBuilder.SetTimeoutHeight(0)

// Set up signature
sigV2 := signing.SignatureV2{
PubKey: txParams.PubKey,
Sequence: sequence,
Data: &signing.SingleSignatureData{
SignMode: signing.SignMode_SIGN_MODE_DIRECT,
},
}

if err := txBuilder.SetSignatures(sigV2); err != nil {
return nil, "", err
}

signerData := authsigning.SignerData{
ChainID: txParams.ChainID,
AccountNumber: txParams.AccNum,
Sequence: sequence,
}

// Sign the transaction
if _, err := tx.SignWithPrivKey(
ctx,
signing.SignMode_SIGN_MODE_DIRECT,
signerData,
txBuilder,
txParams.PrivKey,
encodingConfig.TxConfig,
sequence,
); err != nil {
return nil, "", err
}

// Encode the transaction
txBytes, err := encodingConfig.TxConfig.TxEncoder()(txBuilder.GetTx())
if err != nil {
return nil, "", err
}

// Broadcast the transaction via gRPC
grpcRes, err := grpcClient.SendTx(ctx, txBytes)
if err != nil {
return nil, "", fmt.Errorf("failed to broadcast transaction via gRPC: %w", err)
}

// Check for errors in the response
if grpcRes.Code != 0 {
return grpcRes, string(txBytes), fmt.Errorf("broadcast error code %d: %s", grpcRes.Code, grpcRes.RawLog)
}

return grpcRes, string(txBytes), nil
}
Loading

0 comments on commit 43d083a

Please sign in to comment.