rosetta

package module
v0.50.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 23, 2024 License: Apache-2.0 Imports: 62 Imported by: 2

README

Rosetta

The rosetta project implements Coinbase's Rosetta API. This document provides instructions on how to use the Rosetta API integration. For information about the motivation and design choices, refer to ADR 035.

Installing Rosetta

The Rosetta API server is a stand-alone server that connects to a node of a chain developed with Cosmos SDK.

Rosetta can be added to any cosmos chain node. standalone or natively.

Standalone

Rosetta can be executed as a standalone service, it connects to the node endpoints and expose the required endpoints.

Install Rosetta standalone server with the following command:

go install github.com/cosmos/rosetta

Alternatively, for building from source, simply run make build. The binary will be located in the root folder.

Native - As a node command

To enable Native Rosetta API support, it's required to add the RosettaCommand to your application's root command file (e.g. simd/cmd/root.go).

Import the rosettaCmd package:

import "github.com/cosmos/rosetta/cmd"

Find the following line:

initRootCmd(rootCmd, encodingConfig)

After that line, add the following:

rootCmd.AddCommand(
  rosettaCmd.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Codec)
)

The RosettaCommand function builds the rosetta root command and is defined in the rosettaCmd package (github.com/cosmos/rosetta/cmd).

Since we’ve updated the Cosmos SDK to work with the Rosetta API, updating the application's root command file is all you need to do.

An implementation example can be found in simapp package.

Use Rosetta Command

To run Rosetta in your application CLI, use the following command:

Note: if using the native approach, add your node name before any rosetta comand.

rosetta --help

To test and run Rosetta API endpoints for applications that are running and exposed, use the following command:

rosetta
     --blockchain "your application name (ex: gaia)"
     --network "your chain identifier (ex: testnet-1)"
     --tendermint "tendermint endpoint (ex: localhost:26657)"
     --grpc "gRPC endpoint (ex: localhost:9090)"
     --addr "rosetta binding address (ex: :8080)"
     --grpc-types-server (optional) "gRPC endpoint for message descriptor types"

Plugins - Multi chain connections

Rosetta will try to reflect the node types trough reflection over the node gRPC endpoints, there may be cases were this approach is not enough. It is possible to extend or implement the required types easily trough plugins.

To use Rosetta over any chain, it is required to set up prefixes and registering zone specific interfaces through plugins.

Each plugin is a minimalist implementation of InitZone and RegisterInterfaces which allow Rosetta to parse chain specific data. There is an example for cosmos-hub chain under plugins/cosmos-hun/ folder

  • InitZone: An empty method that is executed first and defines prefixes, parameters and other settings.
  • RegisterInterfaces: This method receives an interface registry which is were the zone specific types and interfaces will be loaded

In order to add a new plugin:

  1. Create a folder over plugins folder with the name of the desired zone
  2. Add a main.go file with the mentioned methods above.
  3. Build the code binary through go build -buildmode=plugin -o main.so main.go

The plugin folder is selected through the cli --plugin flag and loaded into the Rosetta server.

Extensions

There are two ways in which you can customize and extend the implementation with your custom settings.

Message extension

In order to make an sdk.Msg understandable by rosetta the only thing which is required is adding the methods to your messages that satisfy the rosetta.Msg interface. Examples on how to do so can be found in the staking types such as MsgDelegate, or in bank types such as MsgSend.

Client interface override

In case more customization is required, it's possible to embed the Client type and override the methods which require customizations.

Example:

package custom_client
import (

"context"
"github.com/coinbase/rosetta-sdk-go/types"
"github.com/cosmos/rosetta/lib"
)

// CustomClient embeds the standard cosmos client
// which means that it implements the cosmos-rosetta-gateway Client
// interface while at the same time allowing to customize certain methods
type CustomClient struct {
    *rosetta.Client
}

func (c *CustomClient) ConstructionPayload(_ context.Context, request *types.ConstructionPayloadsRequest) (resp *types.ConstructionPayloadsResponse, err error) {
    // provide custom signature bytes
    panic("implement me")
}

NOTE: when using a customized client, the command cannot be used as the constructors required may differ, so it's required to create a new one. We intend to provide a way to init a customized client without writing extra code in the future.

Error extension

Since rosetta requires to provide 'returned' errors to network options. In order to declare a new rosetta error, we use the errors package in cosmos-rosetta-gateway.

Example:

package custom_errors
import crgerrs "github.com/cosmos/rosetta/lib/errors"

var customErrRetriable = true
var CustomError = crgerrs.RegisterError(100, "custom message", customErrRetriable, "description")

Note: errors must be registered before cosmos-rosetta-gateway's Server.Start method is called. Otherwise the registration will be ignored. Errors with same code will be ignored too.

Documentation

Overview

nolint:staticcheck //Since we are usinbg grpc_reflection_v1alpha which is deprecated, we excuse this rule

Index

Constants

View Source
const (
	HTTP  = "http"
	HTTPS = "https"
	TCP   = "tcp"

	HTTPSPORT = "443"
)
View Source
const (
	// DefaultBlockchain defines the default blockchain identifier name
	DefaultBlockchain = "app"
	// DefaultAddr defines the default rosetta binding address
	DefaultAddr = ":8080"
	// DefaultRetries is the default number of retries
	DefaultRetries = 5
	// DefaultCometEndpoint is the default value for the CometBFT endpoint
	DefaultCometEndpoint = "localhost:26657"
	// DefaultGRPCEndpoint is the default value for the gRPC endpoint
	DefaultGRPCEndpoint = "localhost:9090"
	// DefaultGRPCEndpoint is the default value for the gRPC endpoint
	DefaultGRPCTypesServerEndpoint = ""
	// DefaultNetwork defines the default network name
	DefaultNetwork = "network"
	// DefaultOffline defines the default offline value
	DefaultOffline = false
	// DefaultEnableFeeSuggestion indicates to use fee suggestion if `construction/metadata` is called without gas limit and price
	DefaultEnableFeeSuggestion = false
	// DenomToSuggest defines the default denom for fee suggestion
	DenomToSuggest = "uatom"
	// DefaultPrices defines the default list of prices to suggest
	DefaultPrices = "1uatom,1stake"
	// DefaultPlugin define plugin location for interface and type registry
	DefaultPlugin = "cosmos-hub"
)

configuration defaults constants

View Source
const (
	FlagBlockchain              = "blockchain"
	FlagNetwork                 = "network"
	FlagTendermintEndpoint      = "tendermint"
	FlagGRPCEndpoint            = "grpc"
	FlagGRPCTypesServerEndpoint = "grpc-types-server"
	FlagAddr                    = "addr"
	FlagRetries                 = "retries"
	FlagOffline                 = "offline"
	FlagEnableFeeSuggestion     = "enable-fee-suggestion"
	FlagGasToSuggest            = "gas-to-suggest"
	FlagDenomToSuggest          = "denom-to-suggest"
	FlagPricesToSuggest         = "prices-to-suggest"
	FlagPlugin                  = "plugin"
)

configuration flags

View Source
const (
	StatusTxSuccess   = "Success"
	StatusTxReverted  = "Reverted"
	StatusPeerSynced  = "synced"
	StatusPeerSyncing = "syncing"
)

statuses

View Source
const (
	DeliverTxSize       = sha256.Size
	BeginEndBlockTxSize = DeliverTxSize + 1
	EndBlockHashStart   = 0x0
	BeginBlockHashStart = 0x1
)

In rosetta all state transitions must be represented as transactions since in CometBFT begin block and end block are state transitions which are not represented as transactions we mock only the balance changes happening at those levels as transactions. (check BeginBlockTxHash for more info)

View Source
const (
	// BurnerAddressIdentifier mocks the account identifier of a burner address
	// all coins burned in the sdk will be sent to this identifier, which per sdk.AccAddress
	// design we will never be able to query (as of now).
	// Rosetta does not understand supply contraction.
	BurnerAddressIdentifier = "burner"
)
View Source
const (
	Log = "log"
)

misc

Variables

This section is empty.

Functions

func AddOperationIndexes

func AddOperationIndexes(msgOps, balanceOps []*rosettatypes.Operation) (finalOps []*rosettatypes.Operation)

AddOperationIndexes adds the indexes to operations adhering to specific rules: operations related to messages will be always before than the balance ones

func LoadPlugin

func LoadPlugin(ir codectypes.InterfaceRegistry, pluginLocation string) (err error)

func MakeCodec

MakeCodec generates the codec required to interact with the cosmos APIs used by the rosetta gateway

func ReflectInterfaces

func ReflectInterfaces(ir codectypes.InterfaceRegistry, endpoint string) (err error)

func ServerFromConfig

func ServerFromConfig(conf *Config) (crg.Server, error)

func SetFlags

func SetFlags(flags *pflag.FlagSet)

SetFlags sets the configuration flags to the given flagset

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client implements a single network client to interact with cosmos based chains

func NewClient

func NewClient(cfg *Config) (*Client, error)

NewClient instantiates a new online servicer

func (*Client) AccountIdentifierFromPublicKey

func (c *Client) AccountIdentifierFromPublicKey(pubKey *types.PublicKey) (*types.AccountIdentifier, error)

func (*Client) Balances

func (c *Client) Balances(ctx context.Context, addr string, height *int64) ([]*rosettatypes.Amount, error)

func (*Client) BlockByHash

func (c *Client) BlockByHash(ctx context.Context, hash string) (crgtypes.BlockResponse, error)

func (*Client) BlockByHeight

func (c *Client) BlockByHeight(ctx context.Context, height *int64) (crgtypes.BlockResponse, error)

func (*Client) BlockTransactionsByHash

func (c *Client) BlockTransactionsByHash(ctx context.Context, hash string) (crgtypes.BlockTransactionsResponse, error)

func (*Client) BlockTransactionsByHeight

func (c *Client) BlockTransactionsByHeight(ctx context.Context, height *int64) (crgtypes.BlockTransactionsResponse, error)

func (*Client) Bootstrap

func (c *Client) Bootstrap() error

Bootstrap is gonna connect the client to the endpoints

func (*Client) ConstructionMetadataFromOptions

func (c *Client) ConstructionMetadataFromOptions(ctx context.Context, options map[string]interface{}) (meta map[string]interface{}, err error)

ConstructionMetadataFromOptions builds the metadata given the options

func (*Client) ConstructionPayload

func (c *Client) ConstructionPayload(_ context.Context, request *types.ConstructionPayloadsRequest) (resp *types.ConstructionPayloadsResponse, err error)

func (*Client) GenesisBlock

func (c *Client) GenesisBlock(ctx context.Context) (crgtypes.BlockResponse, error)

func (*Client) GetTx

func (c *Client) GetTx(ctx context.Context, hash string) (*rosettatypes.Transaction, error)

GetTx returns a transaction given its hash. For Rosetta we make a synthetic transaction for BeginBlock

and EndBlock to adhere to balance tracking rules.

func (*Client) GetUnconfirmedTx

func (c *Client) GetUnconfirmedTx(ctx context.Context, hash string) (*rosettatypes.Transaction, error)

GetUnconfirmedTx gets an unconfirmed transaction given its hash

func (*Client) InitialHeightBlock

func (c *Client) InitialHeightBlock(ctx context.Context) (crgtypes.BlockResponse, error)

func (*Client) Mempool

Mempool returns the unconfirmed transactions in the mempool

func (*Client) OldestBlock

func (c *Client) OldestBlock(ctx context.Context) (crgtypes.BlockResponse, error)

func (*Client) OperationStatuses

func (c *Client) OperationStatuses() []*types.OperationStatus

func (*Client) Peers

func (c *Client) Peers(ctx context.Context) ([]*rosettatypes.Peer, error)

Peers gets the number of peers

func (*Client) PostTx

func (c *Client) PostTx(txBytes []byte) (*rosettatypes.TransactionIdentifier, map[string]interface{}, error)

func (*Client) PreprocessOperationsToOptions

func (c *Client) PreprocessOperationsToOptions(_ context.Context, req *types.ConstructionPreprocessRequest) (response *types.ConstructionPreprocessResponse, err error)

func (*Client) Ready

func (c *Client) Ready() error

Ready performs a health check and returns an error if the client is not ready.

func (*Client) SignedTx

func (c *Client) SignedTx(_ context.Context, txBytes []byte, signatures []*types.Signature) (signedTxBytes []byte, err error)

func (*Client) Status

func (c *Client) Status(ctx context.Context) (*rosettatypes.SyncStatus, error)

func (*Client) SupportedOperations

func (c *Client) SupportedOperations() []string

func (*Client) TxOperationsAndSignersAccountIdentifiers

func (c *Client) TxOperationsAndSignersAccountIdentifiers(signed bool, txBytes []byte) (ops []*rosettatypes.Operation, signers []*rosettatypes.AccountIdentifier, err error)

func (*Client) Version

func (c *Client) Version() string

type Config

type Config struct {
	// Blockchain defines the blockchain name
	// defaults to DefaultBlockchain
	Blockchain string
	// Network defines the network name
	Network string
	// TendermintRPC defines the endpoint to connect to
	// CometBFT RPC, specifying 'tcp://' before is not
	// required, usually it's at port 26657 of the
	TendermintRPC string
	// GRPCEndpoint defines the cosmos application gRPC endpoint
	// usually it is located at 9090 port
	GRPCEndpoint string
	// Addr defines the default address to bind the rosetta server to
	// defaults to DefaultAddr
	Addr string
	// Retries defines the maximum number of retries
	// rosetta will do before quitting
	Retries int
	// Offline defines if the server must be run in offline mode
	Offline bool
	// EnableFeeSuggestion indicates to use fee suggestion when `construction/metadata` is called without gas limit and price
	EnableFeeSuggestion bool
	// GasToSuggest defines the gas limit for fee suggestion
	GasToSuggest int
	// DenomToSuggest defines the default denom for fee suggestion
	DenomToSuggest string
	// GasPrices defines the gas prices for fee suggestion
	GasPrices 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
	InterfaceRegistry codectypes.InterfaceRegistry
}

Config defines the configuration of the rosetta server

func FromFlags

func FromFlags(flags *pflag.FlagSet) (*Config, error)

FromFlags gets the configuration from flags

func (*Config) NetworkIdentifier

func (c *Config) NetworkIdentifier() *types.NetworkIdentifier

NetworkIdentifier returns the network identifier given the configuration

func (*Config) WithCodec

func (c *Config) WithCodec(ir codectypes.InterfaceRegistry, cdc *codec.ProtoCodec)

WithCodec extends the configuration with a predefined Codec

type ConstructionMetadata

type ConstructionMetadata struct {
	ChainID     string        `json:"chain_id"`
	SignersData []*SignerData `json:"signer_data"`
	GasLimit    uint64        `json:"gas_limit"`
	GasPrice    string        `json:"gas_price"`
	Memo        string        `json:"memo"`
}

ConstructionMetadata are the metadata options used to construct a transaction. It is returned by ConstructionMetadataFromOptions and fed to ConstructionPayload to process the bytes to sign.

func (*ConstructionMetadata) FromMetadata

func (c *ConstructionMetadata) FromMetadata(meta map[string]interface{}) error

func (ConstructionMetadata) ToMetadata

func (c ConstructionMetadata) ToMetadata() (map[string]interface{}, error)

type ConstructionPreprocessMetadata

type ConstructionPreprocessMetadata struct {
	Memo     string `json:"memo"`
	GasLimit uint64 `json:"gas_limit"`
	GasPrice string `json:"gas_price"`
}

ConstructionPreprocessMetadata is used to represent the metadata rosetta can provide during preprocess options

func (*ConstructionPreprocessMetadata) FromMetadata

func (c *ConstructionPreprocessMetadata) FromMetadata(meta map[string]interface{}) error

type Converter

type Converter interface {
	// ToSDK exposes the methods that convert
	// rosetta types to cosmos sdk and CometBFT types
	ToSDK() ToSDKConverter
	// ToRosetta exposes the methods that convert
	// sdk and CometBFT types to rosetta types
	ToRosetta() ToRosettaConverter
}

Converter is a utility that can be used to convert back and forth from rosetta to sdk and CometBFT types IMPORTANT NOTES:

  • IT SHOULD BE USED ONLY TO DEAL WITH THINGS IN A STATELESS WAY! IT SHOULD NEVER INTERACT DIRECTLY WITH COMETBFT RPC AND COSMOS GRPC

- IT SHOULD RETURN cosmos rosetta gateway error types!

type PreprocessOperationsOptionsResponse

type PreprocessOperationsOptionsResponse struct {
	ExpectedSigners []string `json:"expected_signers"`
	Memo            string   `json:"memo"`
	GasLimit        uint64   `json:"gas_limit"`
	GasPrice        string   `json:"gas_price"`
}

PreprocessOperationsOptionsResponse is the structured metadata options returned by the preprocess operations endpoint

func (*PreprocessOperationsOptionsResponse) FromMetadata

func (c *PreprocessOperationsOptionsResponse) FromMetadata(meta map[string]interface{}) error

func (PreprocessOperationsOptionsResponse) ToMetadata

func (c PreprocessOperationsOptionsResponse) ToMetadata() (map[string]interface{}, error)

type SignerData

type SignerData struct {
	AccountNumber uint64 `json:"account_number"`
	Sequence      uint64 `json:"sequence"`
}

SignerData contains information on the signers when the request is being created, used to populate the account information

type ToRosettaConverter

type ToRosettaConverter interface {
	// BlockResponse returns a block response given a result block
	BlockResponse(block *tmcoretypes.ResultBlock) crgtypes.BlockResponse
	// BeginBlockToTx converts the given begin block hash to rosetta transaction hash
	BeginBlockTxHash(blockHash []byte) string
	// EndBlockTxHash converts the given endblock hash to rosetta transaction hash
	EndBlockTxHash(blockHash []byte) string
	// Amounts converts sdk.Coins to rosetta.Amounts
	Amounts(ownedCoins []sdk.Coin, availableCoins sdk.Coins) []*rosettatypes.Amount
	// Ops converts an sdk.Msg to rosetta operations
	Ops(status string, msg sdk.Msg) ([]*rosettatypes.Operation, error)
	// OpsAndSigners takes raw transaction bytes and returns rosetta operations and the expected signers
	OpsAndSigners(txBytes []byte) (ops []*rosettatypes.Operation, signers []*rosettatypes.AccountIdentifier, err error)
	// Meta converts an sdk.Msg to rosetta metadata
	Meta(msg sdk.Msg) (meta map[string]interface{}, err error)
	// SignerData returns account signing data from a queried any account
	SignerData(anyAccount *codectypes.Any) (*SignerData, error)
	// SigningComponents returns rosetta's components required to build a signable transaction
	SigningComponents(tx authsigning.Tx, metadata *ConstructionMetadata, rosPubKeys []*rosettatypes.PublicKey) (txBytes []byte, payloadsToSign []*rosettatypes.SigningPayload, err error)
	// Tx converts a CometBFT transaction and tx result if provided to a rosetta tx
	Tx(rawTx cmttypes.Tx, txResult *abci.ExecTxResult) (*rosettatypes.Transaction, error)
	// TxIdentifiers converts a CometBFT tx to transaction identifiers
	TxIdentifiers(txs []cmttypes.Tx) []*rosettatypes.TransactionIdentifier
	// BalanceOps converts events to balance operations
	BalanceOps(status string, events []abci.Event) []*rosettatypes.Operation
	// SyncStatus converts a CometBFT status to sync status
	SyncStatus(status *tmcoretypes.ResultStatus) *rosettatypes.SyncStatus
	// Peers converts CometBFT peers to rosetta
	Peers(peers []tmcoretypes.Peer) []*rosettatypes.Peer
}

ToRosettaConverter is an interface that exposes all the functions used to convert sdk and CometBFT types to rosetta known types

type ToSDKConverter

type ToSDKConverter interface {
	// UnsignedTx converts rosetta operations to an unsigned cosmos sdk transactions
	UnsignedTx(ops []*rosettatypes.Operation) (tx authsigning.Tx, err error)
	// SignedTx adds the provided signatures after decoding the unsigned transaction raw bytes
	// and returns the signed tx bytes
	SignedTx(txBytes []byte, signatures []*rosettatypes.Signature) (signedTxBytes []byte, err error)
	// Msg converts metadata to an sdk message
	Msg(meta map[string]interface{}, msg sdk.Msg) (err error)
	// HashToTxType returns the transaction type (end block, begin block or deliver tx)
	// and the real hash to query in order to get information
	HashToTxType(hashBytes []byte) (txType TransactionType, realHash []byte)
	// PubKey attempts to convert a rosetta public key to cosmos sdk one
	PubKey(pk *rosettatypes.PublicKey) (cryptotypes.PubKey, error)
}

ToSDKConverter is an interface that exposes all the functions used to convert rosetta types to CometBFT and sdk types

type TransactionType

type TransactionType int

TransactionType is used to distinguish if a rosetta provided hash represents endblock, beginblock or deliver tx

const (
	UnrecognizedTx TransactionType = iota
	BeginBlockTx
	EndBlockTx
	DeliverTxTx
)

Directories

Path Synopsis
cmd
lib
plugins

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL