github.com/cosmos/cosmos-sdk@v0.50.10/docs/architecture/adr-035-rosetta-api-support.md (about)

     1  # ADR 035: Rosetta API Support
     2  
     3  ## Authors
     4  
     5  * Jonathan Gimeno (@jgimeno)
     6  * David Grierson (@senormonito)
     7  * Alessio Treglia (@alessio)
     8  * Frojdy Dymylja (@fdymylja)
     9  
    10  ## Changelog
    11  
    12  * 2021-05-12: the external library  [cosmos-rosetta-gateway](https://github.com/tendermint/cosmos-rosetta-gateway) has been moved within the Cosmos SDK.
    13  
    14  ## Context
    15  
    16  [Rosetta API](https://www.rosetta-api.org/) is an open-source specification and set of tools developed by Coinbase to
    17  standardise blockchain interactions.
    18  
    19  Through the use of a standard API for integrating blockchain applications it will
    20  
    21  * Be easier for a user to interact with a given blockchain
    22  * Allow exchanges to integrate new blockchains quickly and easily
    23  * Enable application developers to build cross-blockchain applications such as block explorers, wallets and dApps at
    24    considerably lower cost and effort.
    25  
    26  ## Decision
    27  
    28  It is clear that adding Rosetta API support to the Cosmos SDK will bring value to all the developers and
    29  Cosmos SDK based chains in the ecosystem. How it is implemented is key.
    30  
    31  The driving principles of the proposed design are:
    32  
    33  1. **Extensibility:** it must be as riskless and painless as possible for application developers to set-up network
    34     configurations to expose Rosetta API-compliant services.
    35  2. **Long term support:** This proposal aims to provide support for all the supported Cosmos SDK release series.
    36  3. **Cost-efficiency:** Backporting changes to Rosetta API specifications from `master` to the various stable
    37     branches of Cosmos SDK is a cost that needs to be reduced.
    38  
    39  We will achieve these delivering on these principles by the following:
    40  
    41  1. There will be a package `rosetta/lib`
    42     for the implementation of the core Rosetta API features, particularly:
    43     a. The types and interfaces (`Client`, `OfflineClient`...), this separates design from implementation detail.
    44     b. The `Server` functionality as this is independent of the Cosmos SDK version.
    45     c. The `Online/OfflineNetwork`, which is not exported, and implements the rosetta API using the `Client` interface to query the node, build tx and so on.
    46     d. The `errors` package to extend rosetta errors.
    47  2. Due to differences between the Cosmos release series, each series will have its own specific implementation of `Client` interface.
    48  3. There will be two options for starting an API service in applications:
    49     a. API shares the application process
    50     b. API-specific process.
    51  
    52  ## Architecture
    53  
    54  ### The External Repo
    55  
    56  As section will describe the proposed external library, including the service implementation, plus the defined types and interfaces.
    57  
    58  #### Server
    59  
    60  `Server` is a simple `struct` that is started and listens to the port specified in the settings. This is meant to be used across all the Cosmos SDK versions that are actively supported.
    61  
    62  The constructor follows:
    63  
    64  `func NewServer(settings Settings) (Server, error)`
    65  
    66  `Settings`, which are used to construct a new server, are the following:
    67  
    68  ```go
    69  // Settings define the rosetta server settings
    70  type Settings struct {
    71  	// Network contains the information regarding the network
    72  	Network *types.NetworkIdentifier
    73  	// Client is the online API handler
    74  	Client crgtypes.Client
    75  	// Listen is the address the handler will listen at
    76  	Listen string
    77  	// Offline defines if the rosetta service should be exposed in offline mode
    78  	Offline bool
    79  	// Retries is the number of readiness checks that will be attempted when instantiating the handler
    80  	// valid only for online API
    81  	Retries int
    82  	// RetryWait is the time that will be waited between retries
    83  	RetryWait time.Duration
    84  }
    85  ```
    86  
    87  #### Types
    88  
    89  Package types uses a mixture of rosetta types and custom defined type wrappers, that the client must parse and return while executing operations.
    90  
    91  ##### Interfaces
    92  
    93  Every SDK version uses a different format to connect (rpc, gRPC, etc), query and build transactions, we have abstracted this in what is the `Client` interface.
    94  The client uses rosetta types, whilst the `Online/OfflineNetwork` takes care of returning correctly parsed rosetta responses and errors.
    95  
    96  Each Cosmos SDK release series will have their own `Client` implementations.
    97  Developers can implement their own custom `Client`s as required.
    98  
    99  ```go
   100  // Client defines the API the client implementation should provide.
   101  type Client interface {
   102  	// Needed if the client needs to perform some action before connecting.
   103  	Bootstrap() error
   104  	// Ready checks if the servicer constraints for queries are satisfied
   105  	// for example the node might still not be ready, it's useful in process
   106  	// when the rosetta instance might come up before the node itself
   107  	// the servicer must return nil if the node is ready
   108  	Ready() error
   109  
   110  	// Data API
   111  
   112  	// Balances fetches the balance of the given address
   113  	// if height is not nil, then the balance will be displayed
   114  	// at the provided height, otherwise last block balance will be returned
   115  	Balances(ctx context.Context, addr string, height *int64) ([]*types.Amount, error)
   116  	// BlockByHashAlt gets a block and its transaction at the provided height
   117  	BlockByHash(ctx context.Context, hash string) (BlockResponse, error)
   118  	// BlockByHeightAlt gets a block given its height, if height is nil then last block is returned
   119  	BlockByHeight(ctx context.Context, height *int64) (BlockResponse, error)
   120  	// BlockTransactionsByHash gets the block, parent block and transactions
   121  	// given the block hash.
   122  	BlockTransactionsByHash(ctx context.Context, hash string) (BlockTransactionsResponse, error)
   123  	// BlockTransactionsByHash gets the block, parent block and transactions
   124  	// given the block hash.
   125  	BlockTransactionsByHeight(ctx context.Context, height *int64) (BlockTransactionsResponse, error)
   126  	// GetTx gets a transaction given its hash
   127  	GetTx(ctx context.Context, hash string) (*types.Transaction, error)
   128  	// GetUnconfirmedTx gets an unconfirmed Tx given its hash
   129  	// NOTE(fdymylja): NOT IMPLEMENTED YET!
   130  	GetUnconfirmedTx(ctx context.Context, hash string) (*types.Transaction, error)
   131  	// Mempool returns the list of the current non confirmed transactions
   132  	Mempool(ctx context.Context) ([]*types.TransactionIdentifier, error)
   133  	// Peers gets the peers currently connected to the node
   134  	Peers(ctx context.Context) ([]*types.Peer, error)
   135  	// Status returns the node status, such as sync data, version etc
   136  	Status(ctx context.Context) (*types.SyncStatus, error)
   137  
   138  	// Construction API
   139  
   140  	// PostTx posts txBytes to the node and returns the transaction identifier plus metadata related
   141  	// to the transaction itself.
   142  	PostTx(txBytes []byte) (res *types.TransactionIdentifier, meta map[string]interface{}, err error)
   143  	// ConstructionMetadataFromOptions
   144  	ConstructionMetadataFromOptions(ctx context.Context, options map[string]interface{}) (meta map[string]interface{}, err error)
   145  	OfflineClient
   146  }
   147  
   148  // OfflineClient defines the functionalities supported without having access to the node
   149  type OfflineClient interface {
   150  	NetworkInformationProvider
   151  	// SignedTx returns the signed transaction given the tx bytes (msgs) plus the signatures
   152  	SignedTx(ctx context.Context, txBytes []byte, sigs []*types.Signature) (signedTxBytes []byte, err error)
   153  	// TxOperationsAndSignersAccountIdentifiers returns the operations related to a transaction and the account
   154  	// identifiers if the transaction is signed
   155  	TxOperationsAndSignersAccountIdentifiers(signed bool, hexBytes []byte) (ops []*types.Operation, signers []*types.AccountIdentifier, err error)
   156  	// ConstructionPayload returns the construction payload given the request
   157  	ConstructionPayload(ctx context.Context, req *types.ConstructionPayloadsRequest) (resp *types.ConstructionPayloadsResponse, err error)
   158  	// PreprocessOperationsToOptions returns the options given the preprocess operations
   159  	PreprocessOperationsToOptions(ctx context.Context, req *types.ConstructionPreprocessRequest) (options map[string]interface{}, err error)
   160  	// AccountIdentifierFromPublicKey returns the account identifier given the public key
   161  	AccountIdentifierFromPublicKey(pubKey *types.PublicKey) (*types.AccountIdentifier, error)
   162  }
   163  ```
   164  
   165  ### 2. Cosmos SDK Implementation
   166  
   167  The Cosmos SDK implementation, based on version, takes care of satisfying the `Client` interface.
   168  In Stargate, Launchpad and 0.37, we have introduced the concept of rosetta.Msg, this message is not in the shared repository as the sdk.Msg type differs between Cosmos SDK versions.
   169  
   170  The rosetta.Msg interface follows:
   171  
   172  ```go
   173  // Msg represents a cosmos-sdk message that can be converted from and to a rosetta operation.
   174  type Msg interface {
   175  	sdk.Msg
   176  	ToOperations(withStatus, hasError bool) []*types.Operation
   177  	FromOperations(ops []*types.Operation) (sdk.Msg, error)
   178  }
   179  ```
   180  
   181  Hence developers who want to extend the rosetta set of supported operations just need to extend their module's sdk.Msgs with the `ToOperations` and `FromOperations` methods.
   182  
   183  ### 3. API service invocation
   184  
   185  As stated at the start, application developers will have two methods for invocation of the Rosetta API service:
   186  
   187  1. Shared process for both application and API
   188  2. Standalone API service
   189  
   190  #### Shared Process (Only Stargate)
   191  
   192  Rosetta API service could run within the same execution process as the application. This would be enabled via app.toml settings, and if gRPC is not enabled the rosetta instance would be spinned in offline mode (tx building capabilities only).
   193  
   194  #### Separate API service
   195  
   196  Client application developers can write a new command to launch a Rosetta API server as a separate process too, using the rosetta command contained in the `/server/rosetta` package. Construction of the command depends on Cosmos SDK version. Examples can be found inside `simd` for stargate, and `contrib/rosetta/simapp` for other release series.
   197  
   198  ## Status
   199  
   200  Proposed
   201  
   202  ## Consequences
   203  
   204  ### Positive
   205  
   206  * Out-of-the-box Rosetta API support within Cosmos SDK.
   207  * Blockchain interface standardisation
   208  
   209  ## References
   210  
   211  * https://www.rosetta-api.org/