diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d1e49671627..71eeadbededb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [\#9205](https://github.com/cosmos/cosmos-sdk/pull/9205) Improve readability in `abci` handleQueryP2P * [\#9235](https://github.com/cosmos/cosmos-sdk/pull/9235) CreateMembershipProof/CreateNonMembershipProof now returns an error if input key is empty, or input data contains empty key. +* [\#9314](https://github.com/cosmos/cosmos-sdk/pull/9314) Update Rosetta SDK to upstream's latest release. ### Features diff --git a/contrib/rosetta/docker-compose.yaml b/contrib/rosetta/docker-compose.yaml index 0a9e82de8a9e..fabb36b0aa6c 100644 --- a/contrib/rosetta/docker-compose.yaml +++ b/contrib/rosetta/docker-compose.yaml @@ -32,7 +32,7 @@ services: - 8080 test_rosetta: - image: tendermintdev/rosetta-cli:v0.6.6 + image: tendermintdev/rosetta-cli:v0.6.7 volumes: - ./configuration:/rosetta/config:z command: ["./config/run_tests.sh"] diff --git a/contrib/rosetta/rosetta-cli/Dockerfile b/contrib/rosetta/rosetta-cli/Dockerfile index e0bc3c961ff3..f67070f6c42d 100644 --- a/contrib/rosetta/rosetta-cli/Dockerfile +++ b/contrib/rosetta/rosetta-cli/Dockerfile @@ -2,7 +2,7 @@ FROM golang:1.15-alpine as build RUN apk add git gcc libc-dev --no-cache -ARG ROSETTA_VERSION="v0.5.23" +ARG ROSETTA_VERSION="v0.6.7" # build rosetta CLI WORKDIR /rosetta diff --git a/docs/architecture/adr-035-rosetta-api-support.md b/docs/architecture/adr-035-rosetta-api-support.md index b7807ce1d24b..4815a4196d84 100644 --- a/docs/architecture/adr-035-rosetta-api-support.md +++ b/docs/architecture/adr-035-rosetta-api-support.md @@ -7,6 +7,10 @@ - Alessio Treglia (@alessio) - Frojdy Dymylja (@fdymylja) + +## Changelog + +- 2021-05-12: the external library [cosmos-rosetta-gateway](https://github.com/tendermint/cosmos-rosetta-gateway) has been moved within the SDK. ## Context [Rosetta API](https://www.rosetta-api.org/) is an open-source specification and set of tools developed by Coinbase to @@ -34,7 +38,7 @@ The driving principles of the proposed design are: We will achieve these delivering on these principles by the following: -1. There will be an external repo called [cosmos-rosetta-gateway](https://github.com/tendermint/cosmos-rosetta-gateway) +1. There will be a package `rosetta/lib` for the implementation of the core Rosetta API features, particularly: a. The types and interfaces (`Client`, `OfflineClient`...), this separates design from implementation detail. b. The `Server` functionality as this is independent of the Cosmos SDK version. @@ -207,4 +211,3 @@ Proposed ## References - https://www.rosetta-api.org/ -- https://github.com/tendermint/cosmos-rosetta-gateway diff --git a/docs/run-node/rosetta.md b/docs/run-node/rosetta.md index b10bc21e7996..bed8eb9f8998 100644 --- a/docs/run-node/rosetta.md +++ b/docs/run-node/rosetta.md @@ -2,8 +2,6 @@ Package rosetta implements the rosetta API for the current cosmos sdk release series. -The client satisfies [cosmos-rosetta-gateway](https://github.com/tendermint/cosmos-rosetta-gateway) `Client` interface implementation. - ## Extension There are two ways in which you can customize and extend the implementation with your custom settings. @@ -24,7 +22,7 @@ import ( "context" "github.com/coinbase/rosetta-sdk-go/types" -"github.com/cosmos/cosmos-sdk/server/rosetta" +"github.com/cosmos/cosmos-sdk/server/rosetta/lib" ) // CustomClient embeds the standard cosmos client @@ -48,7 +46,7 @@ Example: ```go package custom_errors -import crgerrs "github.com/tendermint/cosmos-rosetta-gateway/errors" +import crgerrs "github.com/cosmos/cosmos-sdk/server/rosetta/lib/errors" var customErrRetriable = true var CustomError = crgerrs.RegisterError(100, "custom message", customErrRetriable, "description") diff --git a/go.mod b/go.mod index 615eabca4bb8..b9594813e6d7 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/bgentry/speakeasy v0.1.0 github.com/btcsuite/btcd v0.21.0-beta github.com/btcsuite/btcutil v1.0.2 - github.com/coinbase/rosetta-sdk-go v0.5.9 + github.com/coinbase/rosetta-sdk-go v0.6.10 github.com/confio/ics23/go v0.6.6 github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/iavl v0.16.0 @@ -19,7 +19,6 @@ require ( github.com/gogo/protobuf v1.3.3 github.com/golang/mock v1.4.4 github.com/golang/protobuf v1.5.2 - github.com/golang/snappy v0.0.2 // indirect github.com/gorilla/handlers v1.5.1 github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 @@ -46,12 +45,12 @@ require ( github.com/spf13/viper v1.7.1 github.com/stretchr/testify v1.7.0 github.com/tendermint/btcd v0.1.1 - github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc2.0.20210304154332-87d6ca4410df github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 github.com/tendermint/go-amino v0.16.0 github.com/tendermint/tendermint v0.34.10 github.com/tendermint/tm-db v0.6.4 golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad + golang.org/x/sys v0.0.0-20210510120138-977fb7262007 // indirect google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f google.golang.org/grpc v1.37.0 google.golang.org/protobuf v1.26.0 diff --git a/go.sum b/go.sum index e3527e4a476e..1f9a41416ea9 100644 --- a/go.sum +++ b/go.sum @@ -46,6 +46,7 @@ github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrd github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/Workiva/go-datastructures v1.0.52 h1:PLSK6pwn8mYdaoaCZEMsXBpBotr4HHn9abU0yMQt0NI= github.com/Workiva/go-datastructures v1.0.52/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= +github.com/Zilliqa/gozilliqa-sdk v1.2.1-0.20201201074141-dd0ecada1be6/go.mod h1:eSYp2T6f0apnuW8TzhV3f6Aff2SE8Dwio++U4ha4yEM= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -78,11 +79,13 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0= +github.com/btcsuite/btcd v0.0.0-20190315201642-aa6e0f35703c/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.21.0-beta h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M= github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= @@ -108,9 +111,8 @@ github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/coinbase/rosetta-sdk-go v0.5.8/go.mod h1:xd4wYUhV3LkY78SPH8BUhc88rXfn2jYgN9BfiSjbcvM= -github.com/coinbase/rosetta-sdk-go v0.5.9 h1:CuGQE3HFmYwdEACJnuOtVI9cofqPsGvq6FdFIzaOPKI= -github.com/coinbase/rosetta-sdk-go v0.5.9/go.mod h1:xd4wYUhV3LkY78SPH8BUhc88rXfn2jYgN9BfiSjbcvM= +github.com/coinbase/rosetta-sdk-go v0.6.10 h1:rgHD/nHjxLh0lMEdfGDqpTtlvtSBwULqrrZ2qPdNaCM= +github.com/coinbase/rosetta-sdk-go v0.6.10/go.mod h1:J/JFMsfcePrjJZkwQFLh+hJErkAmdm9Iyy3D5Y0LfXo= github.com/confio/ics23/go v0.0.0-20200817220745-f173e6211efb/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= github.com/confio/ics23/go v0.6.3/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= github.com/confio/ics23/go v0.6.6 h1:pkOy18YxxJ/r0XFDCnrl4Bjv6h4LkBSpLS6F38mrKL8= @@ -180,7 +182,7 @@ github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 h1:2vLKys4RBU4 github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25/go.mod h1:hTr8+TLQmkUkgcuh3mcr5fjrT9c64ZzsBCdCEC6UppY= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum/go-ethereum v1.9.23/go.mod h1:JIfVb6esrqALTExdz9hRYvrP0xBDf6wCncIu1hNwHpM= +github.com/ethereum/go-ethereum v1.9.25/go.mod h1:vMkFiYLHI4tgPw4k2j4MHKoovchFE8plZ0M9VMk4/oM= github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= @@ -189,7 +191,7 @@ github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQD github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= @@ -266,9 +268,8 @@ github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.2-0.20200707131729-196ae77b8a26/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw= -github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3 h1:ur2rms48b3Ep1dxh7aUV2FZEQ8jEVO2F6ILKx8ofkAg= +github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -292,6 +293,7 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= @@ -376,6 +378,7 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jhump/protoreflect v1.8.2 h1:k2xE7wcUomeqwY0LDCYA16y4WWfyTcMx5mKhk0d4ua0= @@ -430,15 +433,12 @@ github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaW github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= @@ -482,6 +482,7 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/neilotoole/errgroup v0.1.5/go.mod h1:Q2nLGf+594h0CLBs/Mbg6qOr7GtqDK7C2S41udRnToE= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso= @@ -611,6 +612,7 @@ github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZ github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa h1:0U2s5loxrTy6/VgfVoLuVLFJcURKLH49ie0zSch7gh4= github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -663,6 +665,7 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -674,8 +677,6 @@ github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzH github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s= github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U= -github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc2.0.20210304154332-87d6ca4410df h1:hoMLrOS4WyyMM+Y+iWdGu94o0zzp6Q43y7v89Q1/OIw= -github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc2.0.20210304154332-87d6ca4410df/go.mod h1:gBPw8WV2Erm4UGHlBRiM3zaEBst4bsuihmMCNQdgP/s= github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 h1:hqAk8riJvK4RMWx1aInLzndwxKalgi5rTqgfXxOxbEI= github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= @@ -689,14 +690,15 @@ github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8= github.com/tendermint/tm-db v0.6.4 h1:3N2jlnYQkXNQclQwd/eKV/NzlqPlfK21cpRRIx80XXQ= github.com/tendermint/tm-db v0.6.4/go.mod h1:dptYhIpJ2M5kUuenLr+Yyf3zQOv1SgBZcl8/BmWlMBw= -github.com/tidwall/gjson v1.6.1/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0= -github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= +github.com/tidwall/gjson v1.6.7/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI= +github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tidwall/sjson v1.1.2/go.mod h1:SEzaDwxiPzKzNfUEO4HbYF/m4UCSJDsGgNqsS1LvdoY= +github.com/tidwall/sjson v1.1.4/go.mod h1:wXpKXu8CtDjKAZ+3DrKY5ROCorDFahq8l0tey/Lx1fg= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= @@ -705,11 +707,12 @@ github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/vmihailenco/msgpack/v5 v5.0.0-beta.9/go.mod h1:HVxBVPUK/+fZMonk4bi1islLa8V3cfnBug0+4dykPzo= +github.com/vmihailenco/msgpack/v5 v5.1.4/go.mod h1:C5gboKD0TJPqWDTVTtrQNfRbiBwHZGo8UTqP/9/XvLI= github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/ybbus/jsonrpc v2.1.2+incompatible/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -738,10 +741,12 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -833,7 +838,6 @@ golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -864,13 +868,13 @@ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 h1:46ULzRKLh1CwgRq2dC5SlBzEqqNCi8rreOZnNrbqcIY= golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -992,9 +996,8 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/server/rosetta.go b/server/rosetta.go index 088de4a70f69..c29f23a846fa 100644 --- a/server/rosetta.go +++ b/server/rosetta.go @@ -5,10 +5,9 @@ import ( "github.com/spf13/cobra" - "github.com/cosmos/cosmos-sdk/server/rosetta" - "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/server/rosetta" ) // RosettaCommand builds the rosetta root command given diff --git a/server/rosetta/client_offline.go b/server/rosetta/client_offline.go index 75fba0a7115d..1dca56de22d0 100644 --- a/server/rosetta/client_offline.go +++ b/server/rosetta/client_offline.go @@ -5,7 +5,8 @@ import ( "encoding/hex" "github.com/coinbase/rosetta-sdk-go/types" - crgerrs "github.com/tendermint/cosmos-rosetta-gateway/errors" + + crgerrs "github.com/cosmos/cosmos-sdk/server/rosetta/lib/errors" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/server/rosetta/client_online.go b/server/rosetta/client_online.go index ac3db862222e..e78d9a6f045d 100644 --- a/server/rosetta/client_online.go +++ b/server/rosetta/client_online.go @@ -18,8 +18,8 @@ import ( "github.com/tendermint/tendermint/rpc/client/http" "google.golang.org/grpc" - crgerrs "github.com/tendermint/cosmos-rosetta-gateway/errors" - crgtypes "github.com/tendermint/cosmos-rosetta-gateway/types" + crgerrs "github.com/cosmos/cosmos-sdk/server/rosetta/lib/errors" + crgtypes "github.com/cosmos/cosmos-sdk/server/rosetta/lib/types" sdk "github.com/cosmos/cosmos-sdk/types" grpctypes "github.com/cosmos/cosmos-sdk/types/grpc" diff --git a/server/rosetta/config.go b/server/rosetta/config.go index a6a81669398d..dac86e25de93 100644 --- a/server/rosetta/config.go +++ b/server/rosetta/config.go @@ -7,7 +7,8 @@ import ( "github.com/coinbase/rosetta-sdk-go/types" "github.com/spf13/pflag" - crg "github.com/tendermint/cosmos-rosetta-gateway/server" + + crg "github.com/cosmos/cosmos-sdk/server/rosetta/lib/server" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" diff --git a/server/rosetta/converter.go b/server/rosetta/converter.go index 7d2609a67387..4fdd87c75b67 100644 --- a/server/rosetta/converter.go +++ b/server/rosetta/converter.go @@ -11,17 +11,19 @@ import ( "github.com/tendermint/tendermint/crypto" "github.com/btcsuite/btcd/btcec" - crgtypes "github.com/tendermint/cosmos-rosetta-gateway/types" tmcoretypes "github.com/tendermint/tendermint/rpc/core/types" + crgtypes "github.com/cosmos/cosmos-sdk/server/rosetta/lib/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/cosmos-sdk/types/tx/signing" rosettatypes "github.com/coinbase/rosetta-sdk-go/types" - crgerrs "github.com/tendermint/cosmos-rosetta-gateway/errors" abci "github.com/tendermint/tendermint/abci/types" tmtypes "github.com/tendermint/tendermint/types" + crgerrs "github.com/cosmos/cosmos-sdk/server/rosetta/lib/errors" + sdkclient "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" @@ -251,7 +253,7 @@ func (c converter) Ops(status string, msg sdk.Msg) ([]*rosettatypes.Operation, e for i, signer := range msg.GetSigners() { op := &rosettatypes.Operation{ Type: opName, - Status: status, + Status: &status, Account: &rosettatypes.AccountIdentifier{Address: signer.String()}, Metadata: meta, } @@ -395,7 +397,7 @@ func sdkEventToBalanceOperations(status string, event abci.Event) (operations [] op := &rosettatypes.Operation{ Type: event.Type, - Status: status, + Status: &status, Account: &rosettatypes.AccountIdentifier{Address: accountIdentifier}, Amount: &rosettatypes.Amount{ Value: value, @@ -520,7 +522,7 @@ func (c converter) SyncStatus(status *tmcoretypes.ResultStatus) *rosettatypes.Sy } return &rosettatypes.SyncStatus{ - CurrentIndex: status.SyncInfo.LatestBlockHeight, + CurrentIndex: &status.SyncInfo.LatestBlockHeight, TargetIndex: nil, // sync info does not allow us to get target height Stage: &stage, } diff --git a/server/rosetta/converter_test.go b/server/rosetta/converter_test.go index 22d466801686..1177d33405df 100644 --- a/server/rosetta/converter_test.go +++ b/server/rosetta/converter_test.go @@ -5,8 +5,6 @@ import ( "encoding/json" "testing" - "github.com/cosmos/cosmos-sdk/server/rosetta" - abci "github.com/tendermint/tendermint/abci/types" authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" @@ -17,7 +15,9 @@ import ( rosettatypes "github.com/coinbase/rosetta-sdk-go/types" "github.com/stretchr/testify/suite" - crgerrs "github.com/tendermint/cosmos-rosetta-gateway/errors" + + "github.com/cosmos/cosmos-sdk/server/rosetta" + crgerrs "github.com/cosmos/cosmos-sdk/server/rosetta/lib/errors" sdk "github.com/cosmos/cosmos-sdk/types" authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" diff --git a/server/rosetta/lib/errors/errors.go b/server/rosetta/lib/errors/errors.go new file mode 100644 index 000000000000..f2e31b44af27 --- /dev/null +++ b/server/rosetta/lib/errors/errors.go @@ -0,0 +1,146 @@ +package errors + +// errors.go contains all the errors returned by the adapter implementation +// plus some extra utilities to parse those errors + +import ( + "fmt" + + grpccodes "google.golang.org/grpc/codes" + grpcstatus "google.golang.org/grpc/status" + + "github.com/coinbase/rosetta-sdk-go/types" +) + +// ListErrors lists all the registered errors +func ListErrors() []*types.Error { + return registry.list() +} + +// SealAndListErrors seals the registry and lists its errors +func SealAndListErrors() []*types.Error { + registry.seal() + return registry.list() +} + +// Error defines an error that can be converted to a Rosetta API error. +type Error struct { + rosErr *types.Error +} + +func (e *Error) Error() string { + if e.rosErr == nil { + return ErrUnknown.Error() + } + return fmt.Sprintf("rosetta: (%d) %s", e.rosErr.Code, e.rosErr.Message) +} + +// Is implements errors.Is for *Error, two errors are considered equal +// if their error codes are identical +func (e *Error) Is(err error) bool { + // assert it can be casted + rosErr, ok := err.(*Error) + if rosErr == nil || !ok { + return false + } + // check that both *Error's are correctly initialized to avoid dereference panics + if rosErr.rosErr == nil || e.rosErr == nil { + return false + } + // messages are equal if their error codes match + return rosErr.rosErr.Code == e.rosErr.Code +} + +// WrapError wraps the rosetta error with additional context +func WrapError(err *Error, msg string) *Error { + return &Error{rosErr: &types.Error{ + Code: err.rosErr.Code, + Message: err.rosErr.Message, + Description: err.rosErr.Description, + Retriable: err.rosErr.Retriable, + Details: map[string]interface{}{ + "info": msg, + }, + }} +} + +// ToRosetta attempts to converting an error into a rosetta +// error, if the error cannot be converted it will be parsed as unknown +func ToRosetta(err error) *types.Error { + // if it's null or not known + rosErr, ok := err.(*Error) + if rosErr == nil || !ok { + return ToRosetta(WrapError(ErrUnknown, ErrUnknown.Error())) + } + return rosErr.rosErr +} + +// FromGRPCToRosettaError converts a gRPC error to rosetta error +func FromGRPCToRosettaError(err error) *Error { + status, ok := grpcstatus.FromError(err) + if !ok { + return WrapError(ErrUnknown, err.Error()) + } + switch status.Code() { + case grpccodes.NotFound: + return WrapError(ErrNotFound, status.Message()) + case grpccodes.FailedPrecondition: + return WrapError(ErrBadArgument, status.Message()) + case grpccodes.InvalidArgument: + return WrapError(ErrBadArgument, status.Message()) + case grpccodes.Internal: + return WrapError(ErrInternal, status.Message()) + default: + return WrapError(ErrUnknown, status.Message()) + } +} + +func RegisterError(code int32, message string, retryable bool, description string) *Error { + e := &Error{rosErr: &types.Error{ + Code: code, + Message: message, + Description: &description, + Retriable: retryable, + Details: nil, + }} + registry.add(e) + return e +} + +// Default error list +var ( + // ErrUnknown defines an unknown error, if this is returned it means + // the library is ignoring an error + ErrUnknown = RegisterError(0, "unknown", false, "unknown error") + // ErrOffline is returned when there is an attempt to query an endpoint in offline mode + ErrOffline = RegisterError(1, "cannot query endpoint in offline mode", false, "returned when querying an online endpoint in offline mode") + // ErrNetworkNotSupported is returned when there is an attempt to query a network which is not supported + ErrNetworkNotSupported = RegisterError(2, "network is not supported", false, "returned when querying a non supported network") + // ErrCodec is returned when there's an error while marshalling or unmarshalling data + ErrCodec = RegisterError(3, "encode/decode error", true, "returned when there are errors encoding or decoding information to and from the node") + // ErrInvalidOperation is returned when the operation supplied to rosetta is not a valid one + ErrInvalidOperation = RegisterError(4, "invalid operation", false, "returned when the operation is not valid") + // ErrInvalidTransaction is returned when the provided hex bytes of a TX are not valid + ErrInvalidTransaction = RegisterError(5, "invalid transaction", false, "returned when the transaction is invalid") + // ErrInvalidAddress is returned when the byte of the address are bad + ErrInvalidAddress = RegisterError(7, "invalid address", false, "returned when the address is malformed") + // ErrInvalidPubkey is returned when the public key is invalid + ErrInvalidPubkey = RegisterError(8, "invalid pubkey", false, "returned when the public key is invalid") + // ErrInterpreting is returned when there are errors interpreting the data from the node, most likely related to breaking changes, version incompatibilities + ErrInterpreting = RegisterError(9, "error interpreting data from node", false, "returned when there are issues interpreting requests or response from node") + ErrInvalidMemo = RegisterError(11, "invalid memo", false, "returned when the memo is invalid") + // ErrBadArgument is returned when the request is malformed + ErrBadArgument = RegisterError(400, "bad argument", false, "request is malformed") + // ErrNotFound is returned when the required object was not found + // retry is set to true because something that is not found now + // might be found later, example: a TX + ErrNotFound = RegisterError(404, "not found", true, "returned when the node does not find what the client is asking for") + // ErrInternal is returned when the node is experiencing internal errors + ErrInternal = RegisterError(500, "internal error", false, "returned when the node experiences internal errors") + // ErrBadGateway is returned when there are problems interacting with the nodes + ErrBadGateway = RegisterError(502, "bad gateway", true, "return when the node is unreachable") + // ErrNotImplemented is returned when a method is not implemented yet + ErrNotImplemented = RegisterError(14, "not implemented", false, "returned when querying an endpoint which is not implemented") + // ErrUnsupportedCurve is returned when the curve specified is not supported + ErrUnsupportedCurve = RegisterError(15, "unsupported curve, expected secp256k1", false, "returned when using an unsupported crypto curve") +) diff --git a/server/rosetta/lib/errors/errors_test.go b/server/rosetta/lib/errors/errors_test.go new file mode 100644 index 000000000000..f9c5253b62ce --- /dev/null +++ b/server/rosetta/lib/errors/errors_test.go @@ -0,0 +1,68 @@ +package errors + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestRegisterError(t *testing.T) { + var error *Error + // this is the number of errors registered by default in errors.go + registeredErrorsCount := 16 + assert.Equal(t, len(registry.list()), registeredErrorsCount) + assert.ElementsMatch(t, registry.list(), ListErrors()) + // add a new Error + error = RegisterError(69, "nice!", false, "nice!") + assert.NotNil(t, error) + // now we have a new error + registeredErrorsCount++ + assert.Equal(t, len(ListErrors()), registeredErrorsCount) + // re-register an error should not change anything + error = RegisterError(69, "nice!", false, "nice!") + assert.Equal(t, len(ListErrors()), registeredErrorsCount) + + // test sealing + assert.Equal(t, registry.sealed, false) + errors := SealAndListErrors() + assert.Equal(t, registry.sealed, true) + assert.Equal(t, len(errors), registeredErrorsCount) + // add a new error on a sealed registry + error = RegisterError(1024, "bytes", false, "bytes") + assert.NotNil(t, error) + +} + +func TestError_Error(t *testing.T) { + var error *Error + // nil cases + assert.False(t, ErrOffline.Is(error)) + error = &Error{} + assert.False(t, ErrOffline.Is(error)) + // wrong type + assert.False(t, ErrOffline.Is(&MyError{})) + // test with wrapping an error + error = WrapError(ErrOffline, "offline") + assert.True(t, ErrOffline.Is(error)) + + // test equality + assert.False(t, ErrOffline.Is(ErrBadGateway)) + assert.True(t, ErrBadGateway.Is(ErrBadGateway)) +} + +func TestToRosetta(t *testing.T) { + var error *Error + // nil case + assert.NotNil(t, ToRosetta(error)) + // wrong type + assert.NotNil(t, ToRosetta(&MyError{})) +} + +type MyError struct { +} + +func (e *MyError) Error() string { + return "" +} +func (e *MyError) Is(err error) bool { + return true +} \ No newline at end of file diff --git a/server/rosetta/lib/errors/registry.go b/server/rosetta/lib/errors/registry.go new file mode 100644 index 000000000000..9cbafcacf7dc --- /dev/null +++ b/server/rosetta/lib/errors/registry.go @@ -0,0 +1,48 @@ +package errors + +import ( + "fmt" + "os" + "sync" + + "github.com/coinbase/rosetta-sdk-go/types" +) + +type errorRegistry struct { + mu *sync.RWMutex + sealed bool + errors map[int32]*types.Error +} + +func (r *errorRegistry) add(err *Error) { + r.mu.Lock() + defer r.mu.Unlock() + if r.sealed { + _, _ = fmt.Fprintln(os.Stderr, "[ROSETTA] WARNING: attempts to register errors after seal will be ignored") + } + if _, ok := r.errors[err.rosErr.Code]; ok { + _, _ = fmt.Fprintln(os.Stderr, "[ROSETTA] WARNING: attempts to register an already registered error will be ignored, code: ", err.rosErr.Code) + } + r.errors[err.rosErr.Code] = err.rosErr +} + +func (r errorRegistry) list() []*types.Error { + r.mu.RLock() + defer r.mu.RUnlock() + rosErrs := make([]*types.Error, 0, len(registry.errors)) + for _, v := range r.errors { + rosErrs = append(rosErrs, v) + } + return rosErrs +} + +func (r *errorRegistry) seal() { + r.mu.Lock() + defer r.mu.Unlock() + r.sealed = true +} + +var registry = errorRegistry{ + mu: new(sync.RWMutex), + errors: make(map[int32]*types.Error), +} diff --git a/server/rosetta/lib/internal/service/construction.go b/server/rosetta/lib/internal/service/construction.go new file mode 100644 index 000000000000..4be6e9461241 --- /dev/null +++ b/server/rosetta/lib/internal/service/construction.go @@ -0,0 +1,138 @@ +package service + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "strings" + + "github.com/coinbase/rosetta-sdk-go/types" + + "github.com/cosmos/cosmos-sdk/server/rosetta/lib/errors" +) + +// ConstructionCombine Combine creates a network-specific transaction from an unsigned transaction +// and an array of provided signatures. The signed transaction returned from this method will be +// sent to the /construction/submit endpoint by the caller. +func (on OnlineNetwork) ConstructionCombine(ctx context.Context, request *types.ConstructionCombineRequest) (*types.ConstructionCombineResponse, *types.Error) { + txBytes, err := hex.DecodeString(request.UnsignedTransaction) + if err != nil { + return nil, errors.ToRosetta(err) + } + + signedTx, err := on.client.SignedTx(ctx, txBytes, request.Signatures) + if err != nil { + return nil, errors.ToRosetta(err) + } + + return &types.ConstructionCombineResponse{ + SignedTransaction: hex.EncodeToString(signedTx), + }, nil +} + +// ConstructionDerive Derive returns the AccountIdentifier associated with a public key. +func (on OnlineNetwork) ConstructionDerive(_ context.Context, request *types.ConstructionDeriveRequest) (*types.ConstructionDeriveResponse, *types.Error) { + account, err := on.client.AccountIdentifierFromPublicKey(request.PublicKey) + if err != nil { + return nil, errors.ToRosetta(err) + } + return &types.ConstructionDeriveResponse{ + AccountIdentifier: account, + Metadata: nil, + }, nil +} + +// ConstructionHash TransactionHash returns the network-specific transaction hash for a signed +// transaction. +func (on OnlineNetwork) ConstructionHash(ctx context.Context, request *types.ConstructionHashRequest) (*types.TransactionIdentifierResponse, *types.Error) { + bz, err := hex.DecodeString(request.SignedTransaction) + if err != nil { + return nil, errors.ToRosetta(errors.WrapError(errors.ErrInvalidTransaction, "error decoding tx")) + } + + hash := sha256.Sum256(bz) + bzHash := hash[:] + hashString := hex.EncodeToString(bzHash) + + return &types.TransactionIdentifierResponse{ + TransactionIdentifier: &types.TransactionIdentifier{ + Hash: strings.ToUpper(hashString), + }, + }, nil +} + +// ConstructionMetadata Get any information required to construct a transaction for a specific +// network (i.e. ChainID, Gas, Memo, ...). +func (on OnlineNetwork) ConstructionMetadata(ctx context.Context, request *types.ConstructionMetadataRequest) (*types.ConstructionMetadataResponse, *types.Error) { + metadata, err := on.client.ConstructionMetadataFromOptions(ctx, request.Options) + if err != nil { + return nil, errors.ToRosetta(err) + } + + return &types.ConstructionMetadataResponse{ + Metadata: metadata, + }, nil +} + +// ConstructionParse Parse is called on both unsigned and signed transactions to understand the +// intent of the formulated transaction. This is run as a sanity check before signing (after +// /construction/payloads) and before broadcast (after /construction/combine). +func (on OnlineNetwork) ConstructionParse(ctx context.Context, request *types.ConstructionParseRequest) (*types.ConstructionParseResponse, *types.Error) { + txBytes, err := hex.DecodeString(request.Transaction) + if err != nil { + err := errors.WrapError(errors.ErrInvalidTransaction, err.Error()) + return nil, errors.ToRosetta(err) + } + ops, signers, err := on.client.TxOperationsAndSignersAccountIdentifiers(request.Signed, txBytes) + if err != nil { + return nil, errors.ToRosetta(err) + } + return &types.ConstructionParseResponse{ + Operations: ops, + AccountIdentifierSigners: signers, + Metadata: nil, + }, nil + +} + +// ConstructionPayloads Payloads is called with an array of operations and the response from +// /construction/metadata. It returns an unsigned transaction blob and a collection of payloads that +// must be signed by particular AccountIdentifiers using a certain SignatureType. +func (on OnlineNetwork) ConstructionPayloads(ctx context.Context, request *types.ConstructionPayloadsRequest) (*types.ConstructionPayloadsResponse, *types.Error) { + payload, err := on.client.ConstructionPayload(ctx, request) + if err != nil { + return nil, errors.ToRosetta(err) + } + return payload, nil +} + +// ConstructionPreprocess Preprocess is called prior to /construction/payloads to construct a +// request for any metadata that is needed for transaction construction given (i.e. account nonce). +func (on OnlineNetwork) ConstructionPreprocess(ctx context.Context, request *types.ConstructionPreprocessRequest) (*types.ConstructionPreprocessResponse, *types.Error) { + options, err := on.client.PreprocessOperationsToOptions(ctx, request) + if err != nil { + return nil, errors.ToRosetta(err) + } + + return options, nil +} + +// ConstructionSubmit Submit a pre-signed transaction to the node. This call does not block on the +// transaction being included in a block. Rather, it returns immediately with an indication of +// whether or not the transaction was included in the mempool. +func (on OnlineNetwork) ConstructionSubmit(ctx context.Context, request *types.ConstructionSubmitRequest) (*types.TransactionIdentifierResponse, *types.Error) { + txBytes, err := hex.DecodeString(request.SignedTransaction) + if err != nil { + return nil, errors.ToRosetta(err) + } + + res, meta, err := on.client.PostTx(txBytes) + if err != nil { + return nil, errors.ToRosetta(err) + } + + return &types.TransactionIdentifierResponse{ + TransactionIdentifier: res, + Metadata: meta, + }, nil +} diff --git a/server/rosetta/lib/internal/service/data.go b/server/rosetta/lib/internal/service/data.go new file mode 100644 index 000000000000..cda420487202 --- /dev/null +++ b/server/rosetta/lib/internal/service/data.go @@ -0,0 +1,159 @@ +package service + +import ( + "context" + + "github.com/coinbase/rosetta-sdk-go/types" + + "github.com/cosmos/cosmos-sdk/server/rosetta/lib/errors" + crgtypes "github.com/cosmos/cosmos-sdk/server/rosetta/lib/types" +) + +// AccountBalance retrieves the account balance of an address +// rosetta requires us to fetch the block information too +func (on OnlineNetwork) AccountBalance(ctx context.Context, request *types.AccountBalanceRequest) (*types.AccountBalanceResponse, *types.Error) { + var ( + height int64 + block crgtypes.BlockResponse + err error + ) + + switch { + case request.BlockIdentifier == nil: + block, err = on.client.BlockByHeight(ctx, nil) + if err != nil { + return nil, errors.ToRosetta(err) + } + case request.BlockIdentifier.Hash != nil: + block, err = on.client.BlockByHash(ctx, *request.BlockIdentifier.Hash) + if err != nil { + return nil, errors.ToRosetta(err) + } + height = block.Block.Index + case request.BlockIdentifier.Index != nil: + height = *request.BlockIdentifier.Index + block, err = on.client.BlockByHeight(ctx, &height) + if err != nil { + return nil, errors.ToRosetta(err) + } + } + + accountCoins, err := on.client.Balances(ctx, request.AccountIdentifier.Address, &height) + if err != nil { + return nil, errors.ToRosetta(err) + } + + return &types.AccountBalanceResponse{ + BlockIdentifier: block.Block, + Balances: accountCoins, + Metadata: nil, + }, nil +} + +// Block gets the transactions in the given block +func (on OnlineNetwork) Block(ctx context.Context, request *types.BlockRequest) (*types.BlockResponse, *types.Error) { + var ( + blockResponse crgtypes.BlockTransactionsResponse + err error + ) + // block identifier is assumed not to be nil as rosetta will do this check for us + // check if we have to query via hash or block number + switch { + case request.BlockIdentifier.Hash != nil: + blockResponse, err = on.client.BlockTransactionsByHash(ctx, *request.BlockIdentifier.Hash) + if err != nil { + return nil, errors.ToRosetta(err) + } + case request.BlockIdentifier.Index != nil: + blockResponse, err = on.client.BlockTransactionsByHeight(ctx, request.BlockIdentifier.Index) + if err != nil { + return nil, errors.ToRosetta(err) + } + default: + err := errors.WrapError(errors.ErrBadArgument, "at least one of hash or index needs to be specified") + return nil, errors.ToRosetta(err) + } + + return &types.BlockResponse{ + Block: &types.Block{ + BlockIdentifier: blockResponse.Block, + ParentBlockIdentifier: blockResponse.ParentBlock, + Timestamp: blockResponse.MillisecondTimestamp, + Transactions: blockResponse.Transactions, + Metadata: nil, + }, + OtherTransactions: nil, + }, nil +} + +// BlockTransaction gets the given transaction in the specified block, we do not need to check the block itself too +// due to the fact that tendermint achieves instant finality +func (on OnlineNetwork) BlockTransaction(ctx context.Context, request *types.BlockTransactionRequest) (*types.BlockTransactionResponse, *types.Error) { + tx, err := on.client.GetTx(ctx, request.TransactionIdentifier.Hash) + if err != nil { + return nil, errors.ToRosetta(err) + } + + return &types.BlockTransactionResponse{ + Transaction: tx, + }, nil +} + +// Mempool fetches the transactions contained in the mempool +func (on OnlineNetwork) Mempool(ctx context.Context, _ *types.NetworkRequest) (*types.MempoolResponse, *types.Error) { + txs, err := on.client.Mempool(ctx) + if err != nil { + return nil, errors.ToRosetta(err) + } + + return &types.MempoolResponse{ + TransactionIdentifiers: txs, + }, nil +} + +// MempoolTransaction fetches a single transaction in the mempool +// NOTE: it is not implemented yet +func (on OnlineNetwork) MempoolTransaction(ctx context.Context, request *types.MempoolTransactionRequest) (*types.MempoolTransactionResponse, *types.Error) { + tx, err := on.client.GetUnconfirmedTx(ctx, request.TransactionIdentifier.Hash) + if err != nil { + return nil, errors.ToRosetta(err) + } + + return &types.MempoolTransactionResponse{ + Transaction: tx, + }, nil +} + +func (on OnlineNetwork) NetworkList(_ context.Context, _ *types.MetadataRequest) (*types.NetworkListResponse, *types.Error) { + return &types.NetworkListResponse{NetworkIdentifiers: []*types.NetworkIdentifier{on.network}}, nil +} + +func (on OnlineNetwork) NetworkOptions(_ context.Context, _ *types.NetworkRequest) (*types.NetworkOptionsResponse, *types.Error) { + return on.networkOptions, nil +} + +func (on OnlineNetwork) NetworkStatus(ctx context.Context, _ *types.NetworkRequest) (*types.NetworkStatusResponse, *types.Error) { + block, err := on.client.BlockByHeight(ctx, nil) + if err != nil { + return nil, errors.ToRosetta(err) + } + + peers, err := on.client.Peers(ctx) + if err != nil { + return nil, errors.ToRosetta(err) + } + + syncStatus, err := on.client.Status(ctx) + if err != nil { + return nil, errors.ToRosetta(err) + } + + return &types.NetworkStatusResponse{ + CurrentBlockIdentifier: block.Block, + CurrentBlockTimestamp: block.MillisecondTimestamp, + GenesisBlockIdentifier: on.genesisBlockIdentifier, + OldestBlockIdentifier: nil, + SyncStatus: syncStatus, + Peers: peers, + }, nil +} diff --git a/server/rosetta/lib/internal/service/offline.go b/server/rosetta/lib/internal/service/offline.go new file mode 100644 index 000000000000..cc420cc431eb --- /dev/null +++ b/server/rosetta/lib/internal/service/offline.go @@ -0,0 +1,63 @@ +package service + +import ( + "context" + + "github.com/coinbase/rosetta-sdk-go/types" + + crgerrs "github.com/cosmos/cosmos-sdk/server/rosetta/lib/errors" + crgtypes "github.com/cosmos/cosmos-sdk/server/rosetta/lib/types" +) + +// NewOffline instantiates the instance of an offline network +// whilst the offline network does not support the DataAPI, +// it supports a subset of the construction API. +func NewOffline(network *types.NetworkIdentifier, client crgtypes.Client) (crgtypes.API, error) { + return OfflineNetwork{ + OnlineNetwork{ + client: client, + network: network, + networkOptions: networkOptionsFromClient(client), + }, + }, nil +} + +// OfflineNetwork implements an offline data API +// which is basically a data API that constantly +// returns errors, because it cannot be used if offline +type OfflineNetwork struct { + OnlineNetwork +} + +// Implement DataAPI in offline mode, which means no method is available +func (o OfflineNetwork) AccountBalance(_ context.Context, _ *types.AccountBalanceRequest) (*types.AccountBalanceResponse, *types.Error) { + return nil, crgerrs.ToRosetta(crgerrs.ErrOffline) +} + +func (o OfflineNetwork) Block(_ context.Context, _ *types.BlockRequest) (*types.BlockResponse, *types.Error) { + return nil, crgerrs.ToRosetta(crgerrs.ErrOffline) +} + +func (o OfflineNetwork) BlockTransaction(_ context.Context, _ *types.BlockTransactionRequest) (*types.BlockTransactionResponse, *types.Error) { + return nil, crgerrs.ToRosetta(crgerrs.ErrOffline) +} + +func (o OfflineNetwork) Mempool(_ context.Context, _ *types.NetworkRequest) (*types.MempoolResponse, *types.Error) { + return nil, crgerrs.ToRosetta(crgerrs.ErrOffline) +} + +func (o OfflineNetwork) MempoolTransaction(_ context.Context, _ *types.MempoolTransactionRequest) (*types.MempoolTransactionResponse, *types.Error) { + return nil, crgerrs.ToRosetta(crgerrs.ErrOffline) +} + +func (o OfflineNetwork) NetworkStatus(_ context.Context, _ *types.NetworkRequest) (*types.NetworkStatusResponse, *types.Error) { + return nil, crgerrs.ToRosetta(crgerrs.ErrOffline) +} + +func (o OfflineNetwork) ConstructionSubmit(_ context.Context, _ *types.ConstructionSubmitRequest) (*types.TransactionIdentifierResponse, *types.Error) { + return nil, crgerrs.ToRosetta(crgerrs.ErrOffline) +} + +func (o OfflineNetwork) ConstructionMetadata(_ context.Context, _ *types.ConstructionMetadataRequest) (*types.ConstructionMetadataResponse, *types.Error) { + return nil, crgerrs.ToRosetta(crgerrs.ErrOffline) +} diff --git a/server/rosetta/lib/internal/service/online.go b/server/rosetta/lib/internal/service/online.go new file mode 100644 index 000000000000..4853a0fcd29c --- /dev/null +++ b/server/rosetta/lib/internal/service/online.go @@ -0,0 +1,66 @@ +package service + +import ( + "context" + "time" + + "github.com/coinbase/rosetta-sdk-go/types" + + crgerrs "github.com/cosmos/cosmos-sdk/server/rosetta/lib/errors" + crgtypes "github.com/cosmos/cosmos-sdk/server/rosetta/lib/types" +) + +// genesisBlockFetchTimeout defines a timeout to fetch the genesis block +const genesisBlockFetchTimeout = 15 * time.Second + +// NewOnlineNetwork builds a single network adapter. +// It will get the Genesis block on the beginning to avoid calling it everytime. +func NewOnlineNetwork(network *types.NetworkIdentifier, client crgtypes.Client) (crgtypes.API, error) { + ctx, cancel := context.WithTimeout(context.Background(), genesisBlockFetchTimeout) + defer cancel() + + var genesisHeight int64 = 1 + block, err := client.BlockByHeight(ctx, &genesisHeight) + if err != nil { + return OnlineNetwork{}, err + } + + return OnlineNetwork{ + client: client, + network: network, + networkOptions: networkOptionsFromClient(client), + genesisBlockIdentifier: block.Block, + }, nil +} + +// OnlineNetwork groups together all the components required for the full rosetta implementation +type OnlineNetwork struct { + client crgtypes.Client // used to query cosmos app + tendermint + + network *types.NetworkIdentifier // identifies the network, it's static + networkOptions *types.NetworkOptionsResponse // identifies the network options, it's static + + genesisBlockIdentifier *types.BlockIdentifier // identifies genesis block, it's static +} + +// AccountsCoins - relevant only for UTXO based chain +// see https://www.rosetta-api.org/docs/AccountApi.html#accountcoins +func (o OnlineNetwork) AccountCoins(_ context.Context, _ *types.AccountCoinsRequest) (*types.AccountCoinsResponse, *types.Error) { + return nil, crgerrs.ToRosetta(crgerrs.ErrOffline) +} + +// networkOptionsFromClient builds network options given the client +func networkOptionsFromClient(client crgtypes.Client) *types.NetworkOptionsResponse { + return &types.NetworkOptionsResponse{ + Version: &types.Version{ + RosettaVersion: crgtypes.SpecVersion, + NodeVersion: client.Version(), + }, + Allow: &types.Allow{ + OperationStatuses: client.OperationStatuses(), + OperationTypes: client.SupportedOperations(), + Errors: crgerrs.SealAndListErrors(), + HistoricalBalanceLookup: true, + }, + } +} diff --git a/server/rosetta/lib/server/server.go b/server/rosetta/lib/server/server.go new file mode 100644 index 000000000000..81747511a815 --- /dev/null +++ b/server/rosetta/lib/server/server.go @@ -0,0 +1,116 @@ +package server + +import ( + "fmt" + "net/http" + "time" + + assert "github.com/coinbase/rosetta-sdk-go/asserter" + "github.com/coinbase/rosetta-sdk-go/server" + "github.com/coinbase/rosetta-sdk-go/types" + + "github.com/cosmos/cosmos-sdk/server/rosetta/lib/internal/service" + crgtypes "github.com/cosmos/cosmos-sdk/server/rosetta/lib/types" +) + +const DefaultRetries = 5 +const DefaultRetryWait = 5 * time.Second + +// Settings define the rosetta server settings +type Settings struct { + // Network contains the information regarding the network + Network *types.NetworkIdentifier + // Client is the online API handler + Client crgtypes.Client + // Listen is the address the handler will listen at + Listen string + // Offline defines if the rosetta service should be exposed in offline mode + Offline bool + // Retries is the number of readiness checks that will be attempted when instantiating the handler + // valid only for online API + Retries int + // RetryWait is the time that will be waited between retries + RetryWait time.Duration +} + +type Server struct { + h http.Handler + addr string +} + +func (h Server) Start() error { + return http.ListenAndServe(h.addr, h.h) +} + +func NewServer(settings Settings) (Server, error) { + asserter, err := assert.NewServer( + settings.Client.SupportedOperations(), + true, + []*types.NetworkIdentifier{settings.Network}, + nil, + false, + ) + if err != nil { + return Server{}, fmt.Errorf("cannot build asserter: %w", err) + } + + var ( + adapter crgtypes.API + ) + switch settings.Offline { + case true: + adapter, err = newOfflineAdapter(settings) + case false: + adapter, err = newOnlineAdapter(settings) + } + if err != nil { + return Server{}, err + } + h := server.NewRouter( + server.NewAccountAPIController(adapter, asserter), + server.NewBlockAPIController(adapter, asserter), + server.NewNetworkAPIController(adapter, asserter), + server.NewMempoolAPIController(adapter, asserter), + server.NewConstructionAPIController(adapter, asserter), + ) + + return Server{ + h: h, + addr: settings.Listen, + }, nil +} + +func newOfflineAdapter(settings Settings) (crgtypes.API, error) { + if settings.Client == nil { + return nil, fmt.Errorf("client is nil") + } + return service.NewOffline(settings.Network, settings.Client) +} + +func newOnlineAdapter(settings Settings) (crgtypes.API, error) { + if settings.Client == nil { + return nil, fmt.Errorf("client is nil") + } + if settings.Retries <= 0 { + settings.Retries = DefaultRetries + } + if settings.RetryWait == 0 { + settings.RetryWait = DefaultRetryWait + } + + var err error + err = settings.Client.Bootstrap() + if err != nil { + return nil, err + } + + for i := 0; i < settings.Retries; i++ { + err = settings.Client.Ready() + if err != nil { + time.Sleep(settings.RetryWait) + continue + } + return service.NewOnlineNetwork(settings.Network, settings.Client) + } + return nil, fmt.Errorf("maximum number of retries exceeded, last error: %w", err) +} diff --git a/server/rosetta/lib/types/types.go b/server/rosetta/lib/types/types.go new file mode 100644 index 000000000000..4f734c34fbf2 --- /dev/null +++ b/server/rosetta/lib/types/types.go @@ -0,0 +1,164 @@ +package types + +import ( + "context" + + "github.com/coinbase/rosetta-sdk-go/server" + "github.com/coinbase/rosetta-sdk-go/types" +) + +// SpecVersion defines the specification of rosetta +const SpecVersion = "" + +// NetworkInformationProvider defines the interface used to provide information regarding +// the network and the version of the cosmos sdk used +type NetworkInformationProvider interface { + // SupportedOperations lists the operations supported by the implementation + SupportedOperations() []string + // OperationStatuses returns the list of statuses supported by the implementation + OperationStatuses() []*types.OperationStatus + // Version returns the version of the node + Version() string +} + +// Client defines the API the client implementation should provide. +type Client interface { + // Bootstrap Needed if the client needs to perform some action before connecting. + Bootstrap() error + // Ready checks if the servicer constraints for queries are satisfied + // for example the node might still not be ready, it's useful in process + // when the rosetta instance might come up before the node itself + // the servicer must return nil if the node is ready + Ready() error + + // Data API + + // Balances fetches the balance of the given address + // if height is not nil, then the balance will be displayed + // at the provided height, otherwise last block balance will be returned + Balances(ctx context.Context, addr string, height *int64) ([]*types.Amount, error) + // BlockByHash gets a block and its transaction at the provided height + BlockByHash(ctx context.Context, hash string) (BlockResponse, error) + // BlockByHeight gets a block given its height, if height is nil then last block is returned + BlockByHeight(ctx context.Context, height *int64) (BlockResponse, error) + // BlockTransactionsByHash gets the block, parent block and transactions + // given the block hash. + BlockTransactionsByHash(ctx context.Context, hash string) (BlockTransactionsResponse, error) + // BlockTransactionsByHeight gets the block, parent block and transactions + // given the block hash. + BlockTransactionsByHeight(ctx context.Context, height *int64) (BlockTransactionsResponse, error) + // GetTx gets a transaction given its hash + GetTx(ctx context.Context, hash string) (*types.Transaction, error) + // GetUnconfirmedTx gets an unconfirmed Tx given its hash + // NOTE(fdymylja): NOT IMPLEMENTED YET! + GetUnconfirmedTx(ctx context.Context, hash string) (*types.Transaction, error) + // Mempool returns the list of the current non confirmed transactions + Mempool(ctx context.Context) ([]*types.TransactionIdentifier, error) + // Peers gets the peers currently connected to the node + Peers(ctx context.Context) ([]*types.Peer, error) + // Status returns the node status, such as sync data, version etc + Status(ctx context.Context) (*types.SyncStatus, error) + + // Construction API + + // PostTx posts txBytes to the node and returns the transaction identifier plus metadata related + // to the transaction itself. + PostTx(txBytes []byte) (res *types.TransactionIdentifier, meta map[string]interface{}, err error) + // ConstructionMetadataFromOptions builds metadata map from an option map + ConstructionMetadataFromOptions(ctx context.Context, options map[string]interface{}) (meta map[string]interface{}, err error) + OfflineClient +} + +// OfflineClient defines the functionalities supported without having access to the node +type OfflineClient interface { + NetworkInformationProvider + // SignedTx returns the signed transaction given the tx bytes (msgs) plus the signatures + SignedTx(ctx context.Context, txBytes []byte, sigs []*types.Signature) (signedTxBytes []byte, err error) + // TxOperationsAndSignersAccountIdentifiers returns the operations related to a transaction and the account + // identifiers if the transaction is signed + TxOperationsAndSignersAccountIdentifiers(signed bool, hexBytes []byte) (ops []*types.Operation, signers []*types.AccountIdentifier, err error) + // ConstructionPayload returns the construction payload given the request + ConstructionPayload(ctx context.Context, req *types.ConstructionPayloadsRequest) (resp *types.ConstructionPayloadsResponse, err error) + // PreprocessOperationsToOptions returns the options given the preprocess operations + PreprocessOperationsToOptions(ctx context.Context, req *types.ConstructionPreprocessRequest) (resp *types.ConstructionPreprocessResponse, err error) + // AccountIdentifierFromPublicKey returns the account identifier given the public key + AccountIdentifierFromPublicKey(pubKey *types.PublicKey) (*types.AccountIdentifier, error) +} + +type BlockTransactionsResponse struct { + BlockResponse + Transactions []*types.Transaction +} + +type BlockResponse struct { + Block *types.BlockIdentifier + ParentBlock *types.BlockIdentifier + MillisecondTimestamp int64 + TxCount int64 +} + +// API defines the exposed APIs +// if the service is online +type API interface { + DataAPI + ConstructionAPI +} + +// DataAPI defines the full data API implementation +type DataAPI interface { + server.NetworkAPIServicer + server.AccountAPIServicer + server.BlockAPIServicer + server.MempoolAPIServicer +} + +var _ server.ConstructionAPIServicer = ConstructionAPI(nil) + +// ConstructionAPI defines the full construction API with +// the online and offline endpoints +type ConstructionAPI interface { + ConstructionOnlineAPI + ConstructionOfflineAPI +} + +// ConstructionOnlineAPI defines the construction methods +// allowed in an online implementation +type ConstructionOnlineAPI interface { + ConstructionMetadata( + context.Context, + *types.ConstructionMetadataRequest, + ) (*types.ConstructionMetadataResponse, *types.Error) + ConstructionSubmit( + context.Context, + *types.ConstructionSubmitRequest, + ) (*types.TransactionIdentifierResponse, *types.Error) +} + +// ConstructionOfflineAPI defines the construction methods +// allowed +type ConstructionOfflineAPI interface { + ConstructionCombine( + context.Context, + *types.ConstructionCombineRequest, + ) (*types.ConstructionCombineResponse, *types.Error) + ConstructionDerive( + context.Context, + *types.ConstructionDeriveRequest, + ) (*types.ConstructionDeriveResponse, *types.Error) + ConstructionHash( + context.Context, + *types.ConstructionHashRequest, + ) (*types.TransactionIdentifierResponse, *types.Error) + ConstructionParse( + context.Context, + *types.ConstructionParseRequest, + ) (*types.ConstructionParseResponse, *types.Error) + ConstructionPayloads( + context.Context, + *types.ConstructionPayloadsRequest, + ) (*types.ConstructionPayloadsResponse, *types.Error) + ConstructionPreprocess( + context.Context, + *types.ConstructionPreprocessRequest, + ) (*types.ConstructionPreprocessResponse, *types.Error) +} diff --git a/server/rosetta/util.go b/server/rosetta/util.go index 43626b5ed351..6aa3d94a64b1 100644 --- a/server/rosetta/util.go +++ b/server/rosetta/util.go @@ -4,7 +4,7 @@ import ( "encoding/json" "time" - crgerrs "github.com/tendermint/cosmos-rosetta-gateway/errors" + crgerrs "github.com/cosmos/cosmos-sdk/server/rosetta/lib/errors" ) // timeToMilliseconds converts time to milliseconds timestamp diff --git a/server/start.go b/server/start.go index 3d09e2a96da9..1ce8811ba721 100644 --- a/server/start.go +++ b/server/start.go @@ -9,14 +9,11 @@ import ( "runtime/pprof" "time" - "github.com/cosmos/cosmos-sdk/server/rosetta" - "github.com/cosmos/cosmos-sdk/codec" "github.com/spf13/cobra" "google.golang.org/grpc" - crgserver "github.com/tendermint/cosmos-rosetta-gateway/server" "github.com/tendermint/tendermint/abci/server" tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" tmos "github.com/tendermint/tendermint/libs/os" @@ -26,6 +23,9 @@ import ( "github.com/tendermint/tendermint/proxy" "github.com/tendermint/tendermint/rpc/client/local" + "github.com/cosmos/cosmos-sdk/server/rosetta" + crgserver "github.com/cosmos/cosmos-sdk/server/rosetta/lib/server" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/server/api" diff --git a/x/authz/keeper/grpc_query_test.go b/x/authz/keeper/grpc_query_test.go index 80ddf4dc136e..37ddb7cf84c0 100644 --- a/x/authz/keeper/grpc_query_test.go +++ b/x/authz/keeper/grpc_query_test.go @@ -5,10 +5,11 @@ import ( "fmt" "time" + "github.com/stretchr/testify/require" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/authz" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/stretchr/testify/require" ) func (suite *TestSuite) TestGRPCQueryAuthorization() { diff --git a/x/authz/simulation/genesis_test.go b/x/authz/simulation/genesis_test.go index 7a91c8dc8f4b..ef217f92c5ca 100644 --- a/x/authz/simulation/genesis_test.go +++ b/x/authz/simulation/genesis_test.go @@ -34,5 +34,5 @@ func TestRandomizedGenState(t *testing.T) { var authzGenesis authz.GenesisState simState.Cdc.MustUnmarshalJSON(simState.GenState[authz.ModuleName], &authzGenesis) - require.Len(t, authzGenesis.Authorization, len(simState.Accounts) - 1) + require.Len(t, authzGenesis.Authorization, len(simState.Accounts)-1) } diff --git a/x/authz/simulation/operations.go b/x/authz/simulation/operations.go index 2476a8e2fac4..f25bf56ad949 100644 --- a/x/authz/simulation/operations.go +++ b/x/authz/simulation/operations.go @@ -4,6 +4,8 @@ import ( "fmt" "math/rand" + "github.com/gogo/protobuf/proto" + "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" @@ -12,7 +14,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/authz" - "github.com/gogo/protobuf/proto" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/authz/keeper" diff --git a/x/feegrant/filtered_fee.go b/x/feegrant/filtered_fee.go index 01a4afd98101..d842e40852af 100644 --- a/x/feegrant/filtered_fee.go +++ b/x/feegrant/filtered_fee.go @@ -1,10 +1,11 @@ package feegrant import ( + "github.com/gogo/protobuf/proto" + "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/gogo/protobuf/proto" ) // TODO: Revisit this once we have propoer gas fee framework. diff --git a/x/feegrant/msgs_test.go b/x/feegrant/msgs_test.go index 30319da2b442..c5eceb3b6bd3 100644 --- a/x/feegrant/msgs_test.go +++ b/x/feegrant/msgs_test.go @@ -4,11 +4,12 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/feegrant" - "github.com/stretchr/testify/require" ) func TestMsgGrantAllowance(t *testing.T) {