Skip to content

Commit

Permalink
GetBlockResults, GetABCIQuery, GetValidators, GetTxSearch, DoBroadcas…
Browse files Browse the repository at this point in the history
…tTxSync|Async
  • Loading branch information
Reecepbcups committed Sep 2, 2024
1 parent c536125 commit cdab398
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 44 deletions.
74 changes: 74 additions & 0 deletions client/bytes/bytes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// FROM: COMETBFT
// IBC-Go also uses this package. Maybe the SDK in v2 upstreams this?

package bytes

import (
"encoding/hex"
"fmt"
"strings"

"github.com/cometbft/cometbft/libs/bytes"
)

// HexBytes enables HEX-encoding for json/encoding.
type HexBytes []byte

// Marshal needed for protobuf compatibility
func (bz HexBytes) Marshal() ([]byte, error) {
return bz, nil
}

// Unmarshal needed for protobuf compatibility
func (bz *HexBytes) Unmarshal(data []byte) error {
*bz = data
return nil
}

// This is the point of Bytes.
func (bz HexBytes) MarshalJSON() ([]byte, error) {
s := strings.ToUpper(hex.EncodeToString(bz))
jbz := make([]byte, len(s)+2)
jbz[0] = '"'
copy(jbz[1:], s)
jbz[len(jbz)-1] = '"'
return jbz, nil
}

// This is the point of Bytes.
func (bz *HexBytes) UnmarshalJSON(data []byte) error {
if len(data) < 2 || data[0] != '"' || data[len(data)-1] != '"' {
return fmt.Errorf("invalid hex string: %s", data)
}
bz2, err := hex.DecodeString(string(data[1 : len(data)-1]))
if err != nil {
return err
}
*bz = bz2
return nil
}

// Bytes fulfills various interfaces in light-client, etc...
func (bz HexBytes) Bytes() []byte {
return bz
}

func (bz HexBytes) String() string {
return strings.ToUpper(hex.EncodeToString(bz))
}

// Format writes either address of 0th element in a slice in base 16 notation,
// with leading 0x (%p), or casts HexBytes to bytes and writes as hexadecimal
// string to s.
func (bz HexBytes) Format(s fmt.State, verb rune) {
switch verb {
case 'p':
s.Write([]byte(fmt.Sprintf("%p", bz)))
default:
s.Write([]byte(fmt.Sprintf("%X", []byte(bz))))
}
}

func ConvertCometBFTToHexBytes(cbft bytes.HexBytes) HexBytes {
return HexBytes(cbft)
}
66 changes: 54 additions & 12 deletions client/cometbft_consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
rpcclient "github.com/cometbft/cometbft/rpc/client"
coretypes "github.com/cometbft/cometbft/rpc/core/types"
tmtypes "github.com/cometbft/cometbft/types"
rbytes "github.com/cosmos/relayer/v2/client/bytes"
)

// ConsensusRelayerI is the itnerface we will use across the relayer so we can swap out the underlying consensus engine client.
Expand All @@ -27,22 +28,28 @@ func (r CometRPCClient) GetBlockTime(ctx context.Context, height uint64) (time.T
}

// GetBlockResults implements ConsensusRelayerI.
func (r CometRPCClient) GetBlockResults(ctx context.Context, height uint64) (*coretypes.ResultBlockResults, error) {
func (r CometRPCClient) GetBlockResults(ctx context.Context, height uint64) (*BlockResults, error) {
h := int64(height)
br, err := r.BlockResults(ctx, &h)
if err != nil {
return nil, fmt.Errorf("failed to get block results: %w", err)
}
return br, nil
return &BlockResults{
TxsResults: br.TxsResults,
FinalizeBlockEvents: br.FinalizeBlockEvents,
}, nil
}

// GetABCIQuery implements ConsensusRelayerI.
func (r CometRPCClient) GetABCIQuery(ctx context.Context, queryPath string, data bytes.HexBytes) (*coretypes.ResultABCIQuery, error) {
func (r CometRPCClient) GetABCIQuery(ctx context.Context, queryPath string, data bytes.HexBytes) (*ABCIQueryResponse, error) {
resp, err := r.ABCIQuery(ctx, queryPath, data)
if err != nil {
return nil, fmt.Errorf("failed to get ABCI query: %w", err)
}
return resp, nil
return &ABCIQueryResponse{
Code: resp.Response.Code,
Value: resp.Response.Value,
}, nil
}

// GetTx implements ConsensusRelayerI.
Expand All @@ -51,16 +58,26 @@ func (r CometRPCClient) GetTx(ctx context.Context, hash []byte, prove bool) (*co
if err != nil {
return nil, fmt.Errorf("failed to get tx: %w", err)
}
// return &Transaction{
// Height: uint64(resp.Height),
// TxHash: resp.Hash,
// Code: resp.TxResult.Code,
// Data: string(resp.TxResult.Data),
// Events: resp.TxResult.Events,
// }, nil
return resp, nil
}

// GetTxSearch implements ConsensusRelayerI.
func (r CometRPCClient) GetTxSearch(ctx context.Context, query string, prove bool, page *int, perPage *int, orderBy string) (*coretypes.ResultTxSearch, error) {
func (r CometRPCClient) GetTxSearch(ctx context.Context, query string, prove bool, page *int, perPage *int, orderBy string) (*ResultTxSearch, error) {
resp, err := r.TxSearch(ctx, query, prove, page, perPage, orderBy)
if err != nil {
return nil, fmt.Errorf("failed to get tx search: %w", err)
}
return resp, nil
return &ResultTxSearch{
Txs: resp.Txs,
TotalCount: resp.TotalCount,
}, nil
}

// GetBlockSearch implements ConsensusRelayerI.
Expand All @@ -82,30 +99,55 @@ func (r CometRPCClient) GetCommit(ctx context.Context, height *int64) (*coretype
}

// GetValidators implements ConsensusRelayerI.
func (r CometRPCClient) GetValidators(ctx context.Context, height *int64, page *int, perPage *int) (*coretypes.ResultValidators, error) {
func (r CometRPCClient) GetValidators(ctx context.Context, height *int64, page *int, perPage *int) (*ResultValidators, error) {
v, err := r.Validators(ctx, height, page, perPage)
if err != nil {
return nil, fmt.Errorf("failed to get validators: %w", err)
}
return v, nil

vals := make([]*tmtypes.Validator, len(v.Validators))
for i, val := range v.Validators {
vals[i] = &tmtypes.Validator{
Address: val.Address,
PubKey: val.PubKey,
VotingPower: val.VotingPower,
ProposerPriority: val.ProposerPriority,
}
}

return &ResultValidators{
Validators: vals,
}, nil
}

// DoBroadcastTxAsync implements ConsensusRelayerI.
func (r CometRPCClient) DoBroadcastTxAsync(ctx context.Context, tx tmtypes.Tx) (*coretypes.ResultBroadcastTx, error) {
func (r CometRPCClient) DoBroadcastTxAsync(ctx context.Context, tx tmtypes.Tx) (*ResultBroadcastTx, error) {
b, err := r.BroadcastTxAsync(ctx, tx)
if err != nil {
return nil, fmt.Errorf("failed to broadcast tx async: %w", err)
}
return b, nil
return &ResultBroadcastTx{
Code: b.Code,
Data: rbytes.ConvertCometBFTToHexBytes(b.Data),
Log: b.Log,
Codespace: b.Codespace,
Hash: rbytes.ConvertCometBFTToHexBytes(b.Hash),
}, nil
}

// DoBroadcastTxSync implements ConsensusRelayerI.
func (r CometRPCClient) DoBroadcastTxSync(ctx context.Context, tx tmtypes.Tx) (*coretypes.ResultBroadcastTx, error) {
func (r CometRPCClient) DoBroadcastTxSync(ctx context.Context, tx tmtypes.Tx) (*ResultBroadcastTx, error) {
b, err := r.BroadcastTxSync(ctx, tx)
if err != nil {
return nil, fmt.Errorf("failed to broadcast tx sync: %w", err)
}
return b, nil
return &ResultBroadcastTx{
Code: b.Code,
Data: rbytes.ConvertCometBFTToHexBytes(b.Data),
Log: b.Log,
Codespace: b.Codespace,
Hash: rbytes.ConvertCometBFTToHexBytes(b.Hash),
}, nil
}

// GetABCIQueryWithOptions implements ConsensusRelayerI.
Expand Down
91 changes: 72 additions & 19 deletions client/i.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ package client

import (
"context"
"strings"
"time"

"github.com/cometbft/cometbft/libs/bytes"
abci "github.com/cometbft/cometbft/abci/types"
"github.com/cometbft/cometbft/crypto"
rpcclient "github.com/cometbft/cometbft/rpc/client"
coretypes "github.com/cometbft/cometbft/rpc/core/types"
tmtypes "github.com/cometbft/cometbft/types"

bytes "github.com/cometbft/cometbft/libs/bytes"
rbytes "github.com/cosmos/relayer/v2/client/bytes"
)

// make this so we can use the cometbft & gordian for this.
Expand All @@ -17,21 +22,26 @@ import (
type ConsensusRelayerI interface {
// DONE: (gordian /Block, just returns time.Now() for now. Need to impl proposer setting time)
GetBlockTime(ctx context.Context, height uint64) (time.Time, error) // resultBlock.Block.Time (return the header annotation time.Time)

GetStatus(ctx context.Context) (*Status, error) // TODO:

GetBlockResults(ctx context.Context, height uint64) (*coretypes.ResultBlockResults, error) // in (d *Driver) handleFinalization
GetABCIQuery(ctx context.Context, queryPath string, data bytes.HexBytes) (*coretypes.ResultABCIQuery, error) // err != nil || resp.Response.Code != 0 // TODO: make this through baseapp `(app *BaseApp) Query` now? the store should handle

GetTx(ctx context.Context, hash []byte, prove bool) (*coretypes.ResultTx, error) // resp (Events), err != nil - does this need its own tm store? or does the manager have context to this

GetStatus(ctx context.Context) (*Status, error)
GetBlockResults(ctx context.Context, height uint64) (*BlockResults, error) // in (d *Driver) handleFinalization
GetABCIQuery(ctx context.Context, queryPath string, data bytes.HexBytes) (*ABCIQueryResponse, error) // err != nil || resp.Response.Code != 0 // TODO: make this through baseapp `(app *BaseApp) Query` now? the store should handle
GetValidators(
ctx context.Context,
height *int64,
page, perPage *int,
) (*ResultValidators, error)
GetTxSearch(
ctx context.Context,
query string,
prove bool,
page, perPage *int,
orderBy string,
) (*coretypes.ResultTxSearch, error)
) (*ResultTxSearch, error)
DoBroadcastTxSync(ctx context.Context, tx tmtypes.Tx) (*ResultBroadcastTx, error)
DoBroadcastTxAsync(ctx context.Context, tx tmtypes.Tx) (*ResultBroadcastTx, error)

// TODO: migrate with v2
GetTx(ctx context.Context, hash []byte, prove bool) (*coretypes.ResultTx, error) // resp (Events), err != nil - does this need its own tm store? or does the manager have context to this

GetBlockSearch(
ctx context.Context,
Expand All @@ -41,21 +51,12 @@ type ConsensusRelayerI interface {
) (*coretypes.ResultBlockSearch, error)

GetCommit(ctx context.Context, height *int64) (*coretypes.ResultCommit, error)
GetValidators(
ctx context.Context,
height *int64,
page, perPage *int,
) (*coretypes.ResultValidators, error)

GetABCIQueryWithOptions(
ctx context.Context,
path string,
data bytes.HexBytes,
opts rpcclient.ABCIQueryOptions,
) (*coretypes.ResultABCIQuery, error)

DoBroadcastTxSync(ctx context.Context, tx tmtypes.Tx) (*coretypes.ResultBroadcastTx, error)
DoBroadcastTxAsync(ctx context.Context, tx tmtypes.Tx) (*coretypes.ResultBroadcastTx, error)
}

// Not sure if we can re-use the cometbft type. Just trying to get exactly what we need at minimum
Expand All @@ -68,3 +69,55 @@ type Status struct {
CatchingUp bool
LatestBlockHeight uint64
}

type BlockResults struct {
// TODO: ideally we get off of this into our own internal type. Then the ConsensusRelayerI can have methods to convert
FinalizeBlockEvents []abci.Event `json:"finalize_block_events"`
TxsResults []*abci.ExecTxResult `json:"txs_results"`
}

type ABCIQueryResponse struct {
Code uint32 `json:"code,omitempty"`
Value []byte `json:"value,omitempty"`
}

func (q ABCIQueryResponse) ValueCleaned() string {
// The response value contains the data link escape control character which must be removed before parsing.
return strings.ReplaceAll(strings.TrimSpace(string(q.Value)), "\u0010", "")
}

// TODO: can't do this yet as the cosmos-sdk side in v0.50 is tied to cometbft
// type Transaction struct {
// Height uint64
// TxHash []byte
// Code uint32
// Data string
// Events []abci.Event // TODO: []provider.RelayerEvent
// Tx cmtypes.Tx `json:"tx"`
// }

// coretypes.ResultTxSearch
type ResultTxSearch struct {
Txs []*coretypes.ResultTx `json:"txs"`
TotalCount int `json:"total_count"`
}

type ResultValidators struct {
Validators []*tmtypes.Validator `json:"validators"`
// Validators []Validator // TODO: requires some helper methods on the gordian side for the query to update set stuff
}

type Validator struct {
Address crypto.Address `json:"address"`
PubKey crypto.PubKey `json:"pub_key"`
VotingPower int64 `json:"voting_power"`
ProposerPriority int64 `json:"proposer_priority"`
}

type ResultBroadcastTx struct {
Code uint32 `json:"code"`
Data rbytes.HexBytes `json:"data"`
Log string `json:"log"`
Codespace string `json:"codespace"`
Hash rbytes.HexBytes `json:"hash"`
}
3 changes: 1 addition & 2 deletions relayer/chains/cosmos/cosmos_chain_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"time"

"github.com/avast/retry-go/v4"
coretypes "github.com/cometbft/cometbft/rpc/core/types"
sdk "github.com/cosmos/cosmos-sdk/types"
clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types"
conntypes "github.com/cosmos/ibc-go/v8/modules/core/03-connection/types"
Expand Down Expand Up @@ -394,7 +393,7 @@ func (ccp *CosmosChainProcessor) queryCycle(ctx context.Context, persistence *qu
for i := persistence.latestQueriedBlock + 1; i <= persistence.latestHeight; i++ {
var (
eg errgroup.Group
blockRes *coretypes.ResultBlockResults
blockRes *relayerclient.BlockResults
ibcHeader provider.IBCHeader
)

Expand Down
8 changes: 2 additions & 6 deletions relayer/chains/cosmos/fee_market.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"fmt"
"regexp"
"strings"

sdkmath "cosmossdk.io/math"
"go.uber.org/zap"
Expand Down Expand Up @@ -33,14 +32,11 @@ func (cc *CosmosProvider) DynamicFee(ctx context.Context) string {
// This is currently hardcoded to only work on Osmosis.
func (cc *CosmosProvider) QueryBaseFee(ctx context.Context) (string, error) {
resp, err := cc.ConsensusClient.GetABCIQuery(ctx, queryPath, nil)
if err != nil || resp.Response.Code != 0 {
if err != nil || resp.Code != 0 {
return "", err
}

// The response value contains the data link escape control character which must be removed before parsing.
cleanedString := strings.ReplaceAll(strings.TrimSpace(string(resp.Response.Value)), "\u0010", "")

decFee, err := sdkmath.LegacyNewDecFromStr(cleanedString)
decFee, err := sdkmath.LegacyNewDecFromStr(resp.ValueCleaned())
if err != nil {
return "", err
}
Expand Down
4 changes: 2 additions & 2 deletions relayer/chains/cosmos/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func (cc *CosmosProvider) QueryTx(ctx context.Context, hashHex string) (*provide
return nil, err
}

// TODO: why proove here if we don't actually use it? does it change the events?
// TODO: why prove here if we don't actually use it? does it change the events?
resp, err := cc.ConsensusClient.GetTx(ctx, hash, true)
if err != nil {
return nil, err
Expand All @@ -130,7 +130,7 @@ func (cc *CosmosProvider) QueryTx(ctx context.Context, hashHex string) (*provide
events := parseEventsFromResponseDeliverTx(resp.TxResult.Events)

return &provider.RelayerTxResponse{
Height: resp.Height,
Height: int64(resp.Height),
TxHash: string(hash),
Code: resp.TxResult.Code,
Data: string(resp.TxResult.Data),
Expand Down
Loading

0 comments on commit cdab398

Please sign in to comment.