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

ADR 026: Rosetta API Support #6922

Closed
wants to merge 25 commits into from
Closed
Changes from 12 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
840cdc1
First draft for adr.
jgimeno Aug 3, 2020
ee79d63
Update date.
jgimeno Aug 3, 2020
981950c
Add some implementation details.
jgimeno Aug 3, 2020
13b392f
Update docs/architecture/adr-026-rosetta-api.md
jgimeno Aug 3, 2020
d437a93
Update docs/architecture/adr-026-rosetta-api.md
jgimeno Aug 3, 2020
9797fbe
Merge branch 'master' into jonathan/adr-rosetta
jgimeno Aug 3, 2020
06bcefd
Update docs/architecture/adr-026-rosetta-api.md
jgimeno Aug 3, 2020
77e32d1
Update docs/architecture/adr-026-rosetta-api.md
jgimeno Aug 3, 2020
06cf545
Update docs/architecture/adr-026-rosetta-api.md
jgimeno Aug 3, 2020
1fd90c7
Rosetta more detailed.
jgimeno Aug 4, 2020
1a03d1f
Router maybe does not need to be exposed.
jgimeno Aug 4, 2020
d9b9a9c
Merge branch 'master' into jonathan/adr-rosetta
Aug 4, 2020
163e30c
Update docs/architecture/adr-026-rosetta-api.md
jgimeno Aug 4, 2020
6787e12
Update docs/architecture/adr-026-rosetta-api.md
jgimeno Aug 4, 2020
15c6817
Update docs/architecture/adr-026-rosetta-api.md
jgimeno Aug 4, 2020
1c8e671
Update docs/architecture/adr-026-rosetta-api.md
jgimeno Aug 4, 2020
d7e654f
Update docs/architecture/adr-026-rosetta-api.md
jgimeno Aug 4, 2020
cc26e43
Update docs/architecture/adr-026-rosetta-api.md
jgimeno Aug 4, 2020
217a6ad
Update docs/architecture/adr-026-rosetta-api.md
jgimeno Aug 4, 2020
2cc9964
Update docs/architecture/adr-026-rosetta-api.md
jgimeno Aug 4, 2020
b08fe90
Update docs/architecture/adr-026-rosetta-api.md
jgimeno Aug 6, 2020
bab1c5c
Update docs/architecture/adr-026-rosetta-api.md
jgimeno Aug 6, 2020
fbd0210
Update docs/architecture/adr-026-rosetta-api.md
jgimeno Aug 6, 2020
9cb1b28
Update docs/architecture/adr-026-rosetta-api.md
jgimeno Aug 6, 2020
c28e610
Merge branch 'master' into jonathan/adr-rosetta
Aug 19, 2020
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
139 changes: 139 additions & 0 deletions docs/architecture/adr-026-rosetta-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# ADR 26: Rosetta API Support

## Changelog

- August 3rd, 2020: Initial Draft.

## Status

- Approved, pending fine tuning the details of implementation.

## Context

We think it'd be greatly valuable to application developers to have the Cosmos SDK
tac0turtle marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

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

I would probably add a bit more to the "why?". Rosetta does a pretty good job at this and so you may be able to just take some snippets directly from their page. But essentially anything along the lines of API interop and striving towards a common API standard should suffice.

provide them with out-of-the-box Rosetta API support.
According to [the project's website](https://www.rosetta-api.org/), Rosetta API is an open
standard designed to simplify blockchain deployment and interaction. The latest specifications are
available at [this URL](https://www.rosetta-api.org/docs/Reference.html).

We want to achieve the following objectives:

- Support multiple versions of Cosmos SDK.
- Support Cosmos Hub.
- Implement querying of historical data sets.
Copy link
Contributor

Choose a reason for hiding this comment

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

Historical datasets of what? Previous hub versions? We can probably condense the last two points into one -- support current and previous versions of the Cosmos Hub.


## Decision

We intend to develop a library that could be extended and used by application
Copy link
Member

Choose a reason for hiding this comment

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

I'm a bit lost. if its a seperate repo why is there an ADR in the sdk repo?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah I'm a bit lost here as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The idea was first to be part of the same sdk repo, but @zmanian pointed out that there is one use case where we need to be able to query multiple versions of the hub at the same time, so living in its own repo is more "easy" to maintain than to have the same code in multiple versions of the SDK.

But in the end is very related to the SDK so I opened the ADR here. But if you think is not correct to keep it here we can change it.

Copy link
Member

@tac0turtle tac0turtle Aug 7, 2020

Choose a reason for hiding this comment

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

This ADR should be in the repo for where the code lives, IMO. What do others think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that is correct, meanwhile because the repo is not created yet (no permissions) we can use this as the draft discussion. Even I am not sure if finally everyone agrees on using another repo, this will be clarified in the cosmos-sdk call today I hope! Thanks @marbar3778

developers to integrate an in-process Rosetta API-compliant server with the
application main binaries. We also intend to provide a standalone gateway server
Copy link
Contributor

Choose a reason for hiding this comment

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

What are application main binaries?

program that supports a Cosmos SDK's minimum feature set. Such program could
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the point in a gateway and the main server? You should describe those, specifically the "why".

Copy link
Contributor

Choose a reason for hiding this comment

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

Also note from the Common Mistakes:

Any implementation of the Rosetta APIs must connect exclusively to a running blockchain node in the
same Dockerfile. It is not ok to connect to some external service that preprocesses blockchain data or
to a blockchain node running elsewhere.

It's not clear if this means in-process or just the same host, but you should note this. Also, I don't understand what the gateway is, so unless there is a strong reason for it, we should remove this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for pointing this out.

I understand both ways are compatible as long as they live in the same Dockerfile (localhost or in-process), but if we had the Rosetta as external process in one Dockerfile and the node in another Dockerfile would not be possible.

run alongside the client applications main binaries.

### Implementation
Copy link
Contributor

Choose a reason for hiding this comment

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

There is no mention of how to handle "offline" mode a la multiple modes.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think a lot is missing from this section, particularly:

  1. Mode specification.
  2. How it's bootstrapped and started with a blockchain node (it should be via a sub-command of the app binary).
  3. Types should be defined before their use (e.g. Options and Router)
  4. What are Options and how are they used?
  5. How are multiple networks supported from the same process/server?


```
type Server struct {
options
router
}

type Options struct {}

func NewServer(opt Options, rosettaAdapter RosettaAPIAdapter) {
jgimeno marked this conversation as resolved.
Show resolved Hide resolved
return Server{opt, newRouter(rosettaAdapter)}
}
```

Server is the main struct, it can be configured by an options struct.
jgimeno marked this conversation as resolved.
Show resolved Hide resolved

This server exposes a Start method.
jgimeno marked this conversation as resolved.
Show resolved Hide resolved

```
func (s Server) Start() error {
...
s.ListenAndServe(s.options.endpoint, s.router)
...
}
```

We have another struct which is the Router that will expose the rosetta endpoints.
jgimeno marked this conversation as resolved.
Show resolved Hide resolved

```
type router struct {
muxRouter mux.router
rosettaAdapter RosettaAPIAdapter
jgimeno marked this conversation as resolved.
Show resolved Hide resolved
}

func newRouter(adapter RosettaAPIAdapter) {
jgimeno marked this conversation as resolved.
Show resolved Hide resolved
router := &Router{
mux: mux.NewRouter(),
rosettaAdapter: adapter,
}

router.mux.HandleFunc("/blocks/", router.blocksApi)
...
...

return router
}
```

This router has a handler function by every Rosetta endpoint. The blocks handler looks like this:
jgimeno marked this conversation as resolved.
Show resolved Hide resolved

```
func (r router) blocksApi(w http.ResponseWriter, r *http.Request) {
// We build the RosettaGetBlockRequest
req := ....

res := r.rosettaAdapter.GetBlocks(req)
...

// We write the response.
}
```

The router just translates a rest request into the data struct that the interface of an adapter needs to run.
The RosettaAdapter interface looks like this:

```
type RosettaAdapterInterface interface {
jgimeno marked this conversation as resolved.
Show resolved Hide resolved
GetBlock(req RosettaGetBlockRequest) RosettaGetBlockResponse
...
}
```

And we will provide different implementations of this `adapter` like for 0.38, for 0.39
Copy link
Contributor

@alessio alessio Aug 6, 2020

Choose a reason for hiding this comment

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

Suggested change
And we will provide different implementations of this `adapter` like for 0.38, for 0.39
We will provide implementations of the `Adapter` interface for each of the Cosmos SDK supported release series. Each implementation needs to support historical data queries.

Copy link
Contributor Author

@jgimeno jgimeno Aug 6, 2020

Choose a reason for hiding this comment

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

In this case we can just create an Adapter of adapter that query different adapters and return the merged response.

Query -> AdapterOfAdapters --> Adapter1 (cosmos-sdk 0.37) (Hub1)
-------------------------------> Adapter2 (cosmos-sdk 0.38) (Hub2)
-------------------------------> Adapter3 (cosmos-sdk 0.38) (Hub3)

The implementation maybe we need to offer for that is one for every SDK and a wrapper adapter of adapters to build complex use cases.

and even a `CosmosHub` implementation that will call different versions of the hub.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
and even a `CosmosHub` implementation that will call different versions of the hub.


An example of an adapter implementation looks like this:

```
type CosmosLaunchpad struct {}

func (CosmosLaunchpad) GetBlock(req RosettaGetBlockRequest) {
// Here we would just convert the RosettaGetBlockRequest
// into the data we need to get the block information
// from a node that uses Launchpad.

res := client.Get(...)

// The adapter is responsable to build the response in the type
// specified by the Interface.

return RosettaGetBlockResponse{...}
}
...

```

If our provided adapters don't work for a specific project because they changed their
API they can always create another adapter and inject it into the server.
jgimeno marked this conversation as resolved.
Show resolved Hide resolved

This way we offer the possibility to offer developers the opportunity to instantiate
jgimeno marked this conversation as resolved.
Show resolved Hide resolved
a new server in their applications or just using the binary that can be build from the
jgimeno marked this conversation as resolved.
Show resolved Hide resolved
repository.
jgimeno marked this conversation as resolved.
Show resolved Hide resolved

## References

- https://www.rosetta-api.org/