Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enhance rosetta support #11590

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 27 additions & 12 deletions server/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/spf13/viper"

clientflags "github.com/cosmos/cosmos-sdk/client/flags"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -131,6 +132,14 @@ type RosettaConfig struct {

// Offline defines if the server must be run in offline mode
Offline bool `mapstructure:"offline"`

EnableDefaultSuggestedFee bool `mapstructure:"enable-default-suggested-fee"`

// SuggestGas defines gas limit when calculate fee
SuggestedGasLimit int `mapstructure:"suggested-gas-limit"`

// DefaultSuggestDenom defines the defult denom for fee suggestion
DefaultSuggestDenom string `mapstructure:"default-suggest-denom"`
}

// GRPCConfig defines configuration for the gRPC server.
Expand Down Expand Up @@ -236,12 +245,15 @@ func DefaultConfig() *Config {
Address: DefaultGRPCAddress,
},
Rosetta: RosettaConfig{
Enable: false,
Address: ":8080",
Blockchain: "app",
Network: "network",
Retries: 3,
Offline: false,
Enable: false,
Address: ":8080",
Blockchain: "app",
Network: "network",
Retries: 3,
Offline: false,
EnableDefaultFeeSuggest: false,
SuggestGas: clientflags.DefaultGasLimit,
DefaultSuggestDenom: "uatom",
},
GRPCWeb: GRPCWebConfig{
Enable: true,
Expand Down Expand Up @@ -299,12 +311,15 @@ func GetConfig(v *viper.Viper) Config {
EnableUnsafeCORS: v.GetBool("api.enabled-unsafe-cors"),
},
Rosetta: RosettaConfig{
Enable: v.GetBool("rosetta.enable"),
Address: v.GetString("rosetta.address"),
Blockchain: v.GetString("rosetta.blockchain"),
Network: v.GetString("rosetta.network"),
Retries: v.GetInt("rosetta.retries"),
Offline: v.GetBool("rosetta.offline"),
Enable: v.GetBool("rosetta.enable"),
Address: v.GetString("rosetta.address"),
Blockchain: v.GetString("rosetta.blockchain"),
Network: v.GetString("rosetta.network"),
Retries: v.GetInt("rosetta.retries"),
Offline: v.GetBool("rosetta.offline"),
EnableDefaultFeeSuggest: v.GetBool("rosetta.enable-default-fee-suggest"),
SuggestGas: v.GetInt("rosetta.suggest-gas"),
DefaultSuggestDenom: v.GetString("rosetta.default-suggest-denom"),
},
GRPC: GRPCConfig{
Enable: v.GetBool("grpc.enable"),
Expand Down
9 changes: 9 additions & 0 deletions server/config/toml.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,15 @@ retries = {{ .Rosetta.Retries }}
# Offline defines if Rosetta server should run in offline mode.
offline = {{ .Rosetta.Offline }}

# EnableDefaultFeeSuggest indicates to use default fee suggestion
enable-default-fee-suggest = {{ .Rosetta.EnableDefaultFeeSuggest }}

# SuggestGas defines gas limit when calculate fee
suggest-gas = {{ .Rosetta.SuggestGas }}

# DefaultSuggestDenom defines the defult denom for fee suggestion
default-suggest-denom = "{{ .Rosetta.DefaultSuggestDenom }}"

###############################################################################
### gRPC Configuration ###
###############################################################################
Expand Down
32 changes: 31 additions & 1 deletion server/rosetta/client_online.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (
// interface assertion
var _ crgtypes.Client = (*Client)(nil)

const defaultNodeTimeout = 15 * time.Second
const defaultNodeTimeout = time.Minute

// Client implements a single network client to interact with cosmos based chains
type Client struct {
Expand Down Expand Up @@ -121,6 +121,14 @@ func (c *Client) Ready() error {
if err != nil {
return err
}

// to prevent timeout of reading genesis block
var height int64 = -1
_, err = c.BlockByHeight(ctx, &height)
if err != nil {
return err
}

_, err = c.bank.TotalSupply(ctx, &bank.QueryTotalSupplyRequest{})
if err != nil {
return err
Expand Down Expand Up @@ -395,6 +403,28 @@ func (c *Client) ConstructionMetadataFromOptions(ctx context.Context, options ma
return nil, err
}

// if default fees suggestion is enabled and gas limit or price is unset, use default
if c.config.EnableDefaultFeeSuggest {
if constructionOptions.GasLimit <= 0 {
constructionOptions.GasLimit = uint64(c.config.SuggestGas)
}
if constructionOptions.GasPrice == "" {
denom := c.config.DefaultSuggestDenom
constructionOptions.GasPrice = c.config.SuggestPrices.AmountOf(denom).String() + denom
}
}

if constructionOptions.GasLimit > 0 && constructionOptions.GasPrice != "" {
gasPrice, err := sdk.ParseDecCoin(constructionOptions.GasPrice)
if err != nil {
return nil, err
}
// check gasPrice is in the list
if !c.config.SuggestPrices.AmountOf(gasPrice.Denom).IsPositive() {
return nil, crgerrs.ErrBadArgument
}
}

signersData := make([]*SignerData, len(constructionOptions.ExpectedSigners))

for i, signer := range constructionOptions.ExpectedSigners {
Expand Down
77 changes: 61 additions & 16 deletions server/rosetta/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import (
"time"

"github.com/coinbase/rosetta-sdk-go/types"
clientflags "github.com/cosmos/cosmos-sdk/client/flags"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gofmt

"github.com/spf13/pflag"

crg "github.com/cosmos/cosmos-sdk/server/rosetta/lib/server"

"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)

// configuration defaults constants
Expand All @@ -30,17 +32,24 @@ const (
DefaultNetwork = "network"
// DefaultOffline defines the default offline value
DefaultOffline = false
// DefaultEnableDefaultFeeSuggest indicates to use fee suggestion
DefaultEnableDefaultFeeSuggest = false
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

odd to read, we can remove Default prefix and address the changes that @alexanderbez suggested for naming

// DefaultSuggestDenom defines the default denom for fee suggestion
DefaultSuggestDenom = "uatom"
)

// configuration flags
const (
FlagBlockchain = "blockchain"
FlagNetwork = "network"
FlagTendermintEndpoint = "tendermint"
FlagGRPCEndpoint = "grpc"
FlagAddr = "addr"
FlagRetries = "retries"
FlagOffline = "offline"
FlagBlockchain = "blockchain"
FlagNetwork = "network"
FlagTendermintEndpoint = "tendermint"
FlagGRPCEndpoint = "grpc"
FlagAddr = "addr"
FlagRetries = "retries"
FlagOffline = "offline"
FlagEnableDefaultFeeSuggest = "enable-default-fee-suggest"
FlagSuggestGas = "suggest-gas"
FlagSuggestDenom = "suggest-denom"
)

// Config defines the configuration of the rosetta server
Expand All @@ -65,6 +74,14 @@ type Config struct {
Retries int
// Offline defines if the server must be run in offline mode
Offline bool
// EnableDefaultFeeSuggest indicates to use fee suggestion
EnableDefaultFeeSuggest bool
// SuggestGas defines the gas limit for fee suggestion
SuggestGas int
// DefaultSuggestDenom defines the default denom for fee suggestion
DefaultSuggestDenom string
// SuggestPrices defines the gas prices for fee suggestion
SuggestPrices sdk.DecCoins
// Codec overrides the default data and construction api client codecs
Codec *codec.ProtoCodec
// InterfaceRegistry overrides the default data and construction api interface registry
Expand Down Expand Up @@ -99,8 +116,18 @@ func (c *Config) validate() error {
if c.Network == "" {
return fmt.Errorf("network not provided")
}
if c.Offline {
return fmt.Errorf("offline mode is not supported for stargate implementation due to how sigv2 works")
if c.SuggestGas <= 0 {
c.SuggestGas = clientflags.DefaultGasLimit
}
found := false
for i := 0; i < c.SuggestPrices.Len(); i++ {
if c.SuggestPrices.GetDenomByIndex(i) == c.DefaultSuggestDenom {
found = true
break
}
}
if !found {
return fmt.Errorf("default suggest denom is not found in minimum-gas-prices")
}

// these are optional but it must be online
Expand Down Expand Up @@ -153,14 +180,29 @@ func FromFlags(flags *pflag.FlagSet) (*Config, error) {
if err != nil {
return nil, err
}
enableDefaultFeeSuggest, err := flags.GetBool(FlagEnableDefaultFeeSuggest)
if err != nil {
return nil, err
}
suggestGas, err := flags.GetInt(FlagSuggestGas)
if err != nil {
return nil, err
}
suggestDenom, err := flags.GetString(FlagSuggestDenom)
if err != nil {
return nil, err
}
conf := &Config{
Blockchain: blockchain,
Network: network,
TendermintRPC: tendermintRPC,
GRPCEndpoint: gRPCEndpoint,
Addr: addr,
Retries: retries,
Offline: offline,
Blockchain: blockchain,
Network: network,
TendermintRPC: tendermintRPC,
GRPCEndpoint: gRPCEndpoint,
Addr: addr,
Retries: retries,
Offline: offline,
EnableDefaultFeeSuggest: enableDefaultFeeSuggest,
SuggestGas: suggestGas,
DefaultSuggestDenom: suggestDenom,
}
err = conf.validate()
if err != nil {
Expand Down Expand Up @@ -201,4 +243,7 @@ func SetFlags(flags *pflag.FlagSet) {
flags.String(FlagAddr, DefaultAddr, "the address rosetta will bind to")
flags.Int(FlagRetries, DefaultRetries, "the number of retries that will be done before quitting")
flags.Bool(FlagOffline, DefaultOffline, "run rosetta only with construction API")
flags.Bool(FlagEnableDefaultFeeSuggest, DefaultEnableDefaultFeeSuggest, "enable fee suggestion")
flags.Int(FlagSuggestGas, clientflags.DefaultGasLimit, "default gas for fee suggestion")
flags.String(FlagSuggestDenom, DefaultSuggestDenom, "default denom to suggest fee")
}
2 changes: 1 addition & 1 deletion server/rosetta/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ func (c converter) Tx(rawTx tmtypes.Tx, txResult *abci.ResponseDeliverTx) (*rose
var balanceOps []*rosettatypes.Operation
// tx result might be nil, in case we're querying an unconfirmed tx from the mempool
if txResult != nil {
balanceOps = c.BalanceOps(status, txResult.Events)
balanceOps = c.BalanceOps(StatusTxSuccess, txResult.Events) // force set to success because no events for failed tx
}

// now normalize indexes
Expand Down
18 changes: 17 additions & 1 deletion server/rosetta/lib/internal/service/construction.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/coinbase/rosetta-sdk-go/types"

"github.com/cosmos/cosmos-sdk/server/rosetta/lib/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
)

// ConstructionCombine Combine creates a network-specific transaction from an unsigned transaction
Expand Down Expand Up @@ -69,8 +70,23 @@ func (on OnlineNetwork) ConstructionMetadata(ctx context.Context, request *types
return nil, errors.ToRosetta(err)
}

price, err := sdk.ParseDecCoin(metadata["gas_price"].(string))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should be safe and have explicit type assertions on these metadata fields and return an error when the type is invalid. Otherwise, this could could panic of metadata structure changes.

if err != nil {
return nil, errors.ToRosetta(err)
}
gas := sdk.NewIntFromUint64(uint64(metadata["gas_limit"].(float64)))

suggestedFee := types.Amount{
Value: price.Amount.Mul(gas).String(),
Currency: &(types.Currency{
Symbol: price.Denom,
Decimals: 0,
}),
}

return &types.ConstructionMetadataResponse{
Metadata: metadata,
Metadata: metadata,
SuggestedFee: []*types.Amount{&suggestedFee},
}, nil
}

Expand Down
28 changes: 19 additions & 9 deletions server/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
crgserver "github.com/cosmos/cosmos-sdk/server/rosetta/lib/server"
"github.com/cosmos/cosmos-sdk/server/types"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdktypes "github.com/cosmos/cosmos-sdk/types"
)

const (
Expand Down Expand Up @@ -399,16 +400,25 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App
offlineMode = true
}

minGasPrices, err := sdktypes.ParseDecCoins(config.MinGasPrices)
if err != nil {
ctx.Logger.Error("failed to parse minimum-gas-prices: ", err)
return err
}

conf := &rosetta.Config{
Blockchain: config.Rosetta.Blockchain,
Network: config.Rosetta.Network,
TendermintRPC: ctx.Config.RPC.ListenAddress,
GRPCEndpoint: config.GRPC.Address,
Addr: config.Rosetta.Address,
Retries: config.Rosetta.Retries,
Offline: offlineMode,
Codec: clientCtx.Codec.(*codec.ProtoCodec),
InterfaceRegistry: clientCtx.InterfaceRegistry,
Blockchain: config.Rosetta.Blockchain,
Network: config.Rosetta.Network,
TendermintRPC: ctx.Config.RPC.ListenAddress,
GRPCEndpoint: config.GRPC.Address,
Addr: config.Rosetta.Address,
Retries: config.Rosetta.Retries,
Offline: offlineMode,
SuggestGas: config.Rosetta.SuggestGas,
DefaultSuggestDenom: config.Rosetta.DefaultSuggestDenom,
SuggestPrices: minGasPrices.Sort(),
Codec: clientCtx.Codec.(*codec.ProtoCodec),
InterfaceRegistry: clientCtx.InterfaceRegistry,
}

rosettaSrv, err = rosetta.ServerFromConfig(conf)
Expand Down