Compare commits
3 commits
master
...
patrick/co
Author | SHA1 | Date | |
---|---|---|---|
|
46da44d520 | ||
|
311eb6988c | ||
|
863313103a |
58 changed files with 781 additions and 1082 deletions
.circleci
.dockerignore.gitignoreCONTRIBUTING.mdDockerfileMakefileREADME.mdassets
bitcoin
client.go
client_fixtures
fee_rate.jsonget_block_hash_out_of_range_response.jsonget_block_hash_response.jsonget_block_not_found_response.jsonget_block_response.jsonget_block_response_2.jsonget_blockchain_info_response.jsonget_peer_info_response.jsoninvalid_fee_rate.jsonraw_mempool.jsonrpc_in_warmup_response.json
client_test.gonode.gotypes.goutils.goconfiguration
go.modgo.sumindexer
install.shlbry
main.gomocks
rosetta-cli-conf
services
|
@ -16,9 +16,9 @@ version: 2.1
|
||||||
executors:
|
executors:
|
||||||
default:
|
default:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/golang:1.15
|
- image: circleci/golang:1.13
|
||||||
user: root # go directory is owned by root
|
user: root # go directory is owned by root
|
||||||
working_directory: /go/src/github.com/lbryio/rosetta-lbry
|
working_directory: /go/src/github.com/coinbase/rosetta-bitcoin
|
||||||
environment:
|
environment:
|
||||||
- GO111MODULE: "on"
|
- GO111MODULE: "on"
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ jobs:
|
||||||
name: default
|
name: default
|
||||||
steps:
|
steps:
|
||||||
- *fast-checkout
|
- *fast-checkout
|
||||||
- run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.32.2
|
- run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.30.0
|
||||||
- run: make lint
|
- run: make lint
|
||||||
check-license:
|
check-license:
|
||||||
executor:
|
executor:
|
||||||
|
@ -69,7 +69,7 @@ jobs:
|
||||||
name: default
|
name: default
|
||||||
steps:
|
steps:
|
||||||
- *fast-checkout
|
- *fast-checkout
|
||||||
- run: make coverage
|
- run: make coverage
|
||||||
salus:
|
salus:
|
||||||
machine: true
|
machine: true
|
||||||
steps:
|
steps:
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
rosetta-lbry
|
rosetta-bitcoin
|
||||||
lbry-data
|
bitcoin-data
|
||||||
cli-data
|
cli-data
|
||||||
|
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,3 +1,3 @@
|
||||||
rosetta-lbry
|
rosetta-bitcoin
|
||||||
lbry-data
|
bitcoin-data
|
||||||
cli-data
|
cli-data
|
||||||
|
|
|
@ -10,11 +10,11 @@ from further participation in this project, or potentially all Coinbase projects
|
||||||
|
|
||||||
## Bug Reports
|
## Bug Reports
|
||||||
|
|
||||||
- Ensure your issue [has not already been reported][1]. It may already be fixed!
|
* Ensure your issue [has not already been reported][1]. It may already be fixed!
|
||||||
- Include the steps you carried out to produce the problem.
|
* Include the steps you carried out to produce the problem.
|
||||||
- Include the behavior you observed along with the behavior you expected, and
|
* Include the behavior you observed along with the behavior you expected, and
|
||||||
why you expected it.
|
why you expected it.
|
||||||
- Include any relevant stack traces or debugging output.
|
* Include any relevant stack traces or debugging output.
|
||||||
|
|
||||||
## Feature Requests
|
## Feature Requests
|
||||||
|
|
||||||
|
@ -27,18 +27,18 @@ The best way to see a feature added, however, is to submit a pull request.
|
||||||
|
|
||||||
## Pull Requests
|
## Pull Requests
|
||||||
|
|
||||||
- Before creating your pull request, it's usually worth asking if the code
|
* Before creating your pull request, it's usually worth asking if the code
|
||||||
you're planning on writing will actually be considered for merging. You can
|
you're planning on writing will actually be considered for merging. You can
|
||||||
do this by [opening an issue][1] and asking. It may also help give the
|
do this by [opening an issue][1] and asking. It may also help give the
|
||||||
maintainers context for when the time comes to review your code.
|
maintainers context for when the time comes to review your code.
|
||||||
|
|
||||||
- Ensure your [commit messages are well-written][2]. This can double as your
|
* Ensure your [commit messages are well-written][2]. This can double as your
|
||||||
pull request message, so it pays to take the time to write a clear message.
|
pull request message, so it pays to take the time to write a clear message.
|
||||||
|
|
||||||
- Add tests for your feature. You should be able to look at other tests for
|
* Add tests for your feature. You should be able to look at other tests for
|
||||||
examples. If you're unsure, don't hesitate to [open an issue][1] and ask!
|
examples. If you're unsure, don't hesitate to [open an issue][1] and ask!
|
||||||
|
|
||||||
- Submit your pull request!
|
* Submit your pull request!
|
||||||
|
|
||||||
## Support Requests
|
## Support Requests
|
||||||
|
|
||||||
|
@ -48,6 +48,6 @@ be locked to prevent further discussion.
|
||||||
|
|
||||||
All support requests must be made via [our support team][3].
|
All support requests must be made via [our support team][3].
|
||||||
|
|
||||||
[1]: https://github.com/lbryio/rosetta-bitcoin/issues
|
[1]: https://github.com/coinbase/rosetta-bitcoin/issues
|
||||||
[2]: https://chris.beams.io/posts/git-commit/#seven-rules
|
[2]: https://chris.beams.io/posts/git-commit/#seven-rules
|
||||||
[3]: https://support.coinbase.com/customer/en/portal/articles/2288496-how-can-i-contact-coinbase-support-
|
[3]: https://support.coinbase.com/customer/en/portal/articles/2288496-how-can-i-contact-coinbase-support-
|
||||||
|
|
68
Dockerfile
68
Dockerfile
|
@ -12,47 +12,29 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
# Build LBRYCrdd
|
# Build bitcoind
|
||||||
FROM ubuntu:18.04 as lbrycrdd-builder
|
FROM ubuntu:18.04 as bitcoind-builder
|
||||||
ENV LANG C.UTF-8
|
|
||||||
|
|
||||||
RUN mkdir -p /app \
|
RUN mkdir -p /app \
|
||||||
&& chown -R nobody:nogroup /app
|
&& chown -R nobody:nogroup /app
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Source: https://github.com/lbryio/lbrycrd/blob/v19_master/packaging/docker-for-gcc/Dockerfile
|
# Source: https://github.com/bitcoin/bitcoin/blob/master/doc/build-unix.md#ubuntu--debian
|
||||||
RUN set -xe; \
|
RUN apt-get update && apt-get install -y make gcc g++ autoconf autotools-dev bsdmainutils build-essential git libboost-all-dev \
|
||||||
apt-get update; \
|
libcurl4-openssl-dev libdb++-dev libevent-dev libssl-dev libtool pkg-config python python-pip libzmq3-dev wget
|
||||||
apt-get install --no-install-recommends -y build-essential libtool autotools-dev automake pkg-config git wget apt-utils \
|
|
||||||
librsvg2-bin cmake libcap-dev libz-dev libbz2-dev python-setuptools python3-setuptools xz-utils ccache \
|
|
||||||
bsdmainutils curl ca-certificates; \
|
|
||||||
rm -rf /var/lib/apt/lists/*; \
|
|
||||||
/usr/sbin/update-ccache-symlinks;
|
|
||||||
|
|
||||||
# VERSION: LBRYcrd 0.19.1.3
|
# VERSION: Bitcoin Core 0.20.1
|
||||||
RUN git clone https://github.com/lbryio/lbrycrd \
|
RUN git clone https://github.com/bitcoin/bitcoin \
|
||||||
&& cd lbrycrd \
|
&& cd bitcoin \
|
||||||
&& git checkout v0.19.1.3
|
&& git checkout 7ff64311bee570874c4f0dfa18f518552188df08
|
||||||
|
|
||||||
ENV CXXFLAGS "${CXXFLAGS:--frecord-gcc-switches}"
|
RUN cd bitcoin \
|
||||||
|
|
||||||
RUN cd lbrycrd \
|
|
||||||
&& cd depends \
|
|
||||||
&& make -j$(getconf _NPROCESSORS_ONLN) HOST=x86_64-pc-linux-gnu NO_QT=1 V=1
|
|
||||||
|
|
||||||
ENV DEPS_DIR /app/lbrycrd/depends/x86_64-pc-linux-gnu
|
|
||||||
RUN echo $DEPS_DIR
|
|
||||||
|
|
||||||
ENV CONFIG_SITE ${DEPS_DIR}/share/config.site
|
|
||||||
RUN echo $CONFIG_SITE
|
|
||||||
|
|
||||||
RUN cd lbrycrd \
|
|
||||||
&& ./autogen.sh \
|
&& ./autogen.sh \
|
||||||
&& ./configure --enable-static --with-pic --disable-shared --enable-glibc-back-compat --disable-tests --without-miniupnpc --without-gui --with-incompatible-bdb --disable-hardening --disable-zmq --disable-bench --disable-wallet \
|
&& ./configure --enable-glibc-back-compat --disable-tests --without-miniupnpc --without-gui --with-incompatible-bdb --disable-hardening --disable-zmq --disable-bench --disable-wallet \
|
||||||
&& make -j$(getconf _NPROCESSORS_ONLN)
|
&& make
|
||||||
|
|
||||||
RUN mv lbrycrd/src/lbrycrdd /app/lbrycrdd \
|
RUN mv bitcoin/src/bitcoind /app/bitcoind \
|
||||||
&& rm -rf lbrycrd
|
&& rm -rf bitcoin
|
||||||
|
|
||||||
# Build Rosetta Server Components
|
# Build Rosetta Server Components
|
||||||
FROM ubuntu:18.04 as rosetta-builder
|
FROM ubuntu:18.04 as rosetta-builder
|
||||||
|
@ -62,8 +44,8 @@ RUN mkdir -p /app \
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y curl make gcc g++
|
RUN apt-get update && apt-get install -y curl make gcc g++
|
||||||
ENV GOLANG_VERSION 1.15.5
|
ENV GOLANG_VERSION 1.15.2
|
||||||
ENV GOLANG_DOWNLOAD_SHA256 9a58494e8da722c3aef248c9227b0e9c528c7318309827780f16220998180a0d
|
ENV GOLANG_DOWNLOAD_SHA256 b49fda1ca29a1946d6bb2a5a6982cf07ccd2aba849289508ee0f9918f6bb4552
|
||||||
ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
|
ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
|
||||||
|
|
||||||
RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz \
|
RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz \
|
||||||
|
@ -76,19 +58,13 @@ ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
|
||||||
RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"
|
RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"
|
||||||
|
|
||||||
# Use native remote build context to build in any directory
|
# Use native remote build context to build in any directory
|
||||||
COPY . src
|
COPY . src
|
||||||
## Cleanup
|
|
||||||
RUN cd src \
|
|
||||||
&& rm go.sum \
|
|
||||||
&& go mod edit -replace github.com/golang/lint=golang.org/x/lint@latest \
|
|
||||||
&& go clean -modcache
|
|
||||||
|
|
||||||
RUN cd src \
|
RUN cd src \
|
||||||
&& go build \
|
&& go build \
|
||||||
&& cd .. \
|
&& cd .. \
|
||||||
&& mv src/rosetta-lbry /app/rosetta-lbry \
|
&& mv src/rosetta-bitcoin /app/rosetta-bitcoin \
|
||||||
&& mv src/assets/* /app \
|
&& mv src/assets/* /app \
|
||||||
&& rm -rf src
|
&& rm -rf src
|
||||||
|
|
||||||
## Build Final Image
|
## Build Final Image
|
||||||
FROM ubuntu:18.04
|
FROM ubuntu:18.04
|
||||||
|
@ -104,8 +80,8 @@ RUN mkdir -p /app \
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy binary from lbrycrdd-builder
|
# Copy binary from bitcoind-builder
|
||||||
COPY --from=lbrycrdd-builder /app/lbrycrdd /app/lbrycrdd
|
COPY --from=bitcoind-builder /app/bitcoind /app/bitcoind
|
||||||
|
|
||||||
# Copy binary from rosetta-builder
|
# Copy binary from rosetta-builder
|
||||||
COPY --from=rosetta-builder /app/* /app/
|
COPY --from=rosetta-builder /app/* /app/
|
||||||
|
@ -113,4 +89,4 @@ COPY --from=rosetta-builder /app/* /app/
|
||||||
# Set permissions for everything added to /app
|
# Set permissions for everything added to /app
|
||||||
RUN chmod -R 755 /app/*
|
RUN chmod -R 755 /app/*
|
||||||
|
|
||||||
CMD ["/app/rosetta-lbry"]
|
CMD ["/app/rosetta-bitcoin"]
|
||||||
|
|
20
Makefile
20
Makefile
|
@ -9,7 +9,7 @@ GOLINES_CMD=go run github.com/segmentio/golines
|
||||||
GOLINT_CMD=go run golang.org/x/lint/golint
|
GOLINT_CMD=go run golang.org/x/lint/golint
|
||||||
GOVERALLS_CMD=go run github.com/mattn/goveralls
|
GOVERALLS_CMD=go run github.com/mattn/goveralls
|
||||||
GOIMPORTS_CMD=go run golang.org/x/tools/cmd/goimports
|
GOIMPORTS_CMD=go run golang.org/x/tools/cmd/goimports
|
||||||
GO_PACKAGES=./services/... ./indexer/... ./lbry/... ./configuration/...
|
GO_PACKAGES=./services/... ./indexer/... ./bitcoin/... ./configuration/...
|
||||||
GO_FOLDERS=$(shell echo ${GO_PACKAGES} | sed -e "s/\.\///g" | sed -e "s/\/\.\.\.//g")
|
GO_FOLDERS=$(shell echo ${GO_PACKAGES} | sed -e "s/\.\///g" | sed -e "s/\/\.\.\.//g")
|
||||||
TEST_SCRIPT=go test ${GO_PACKAGES}
|
TEST_SCRIPT=go test ${GO_PACKAGES}
|
||||||
LINT_SETTINGS=golint,misspell,gocyclo,gocritic,whitespace,goconst,gocognit,bodyclose,unconvert,lll,unparam
|
LINT_SETTINGS=golint,misspell,gocyclo,gocritic,whitespace,goconst,gocognit,bodyclose,unconvert,lll,unparam
|
||||||
|
@ -20,27 +20,27 @@ deps:
|
||||||
go get ./...
|
go get ./...
|
||||||
|
|
||||||
build:
|
build:
|
||||||
docker build -t rosetta-lbry:latest https://github.com/lbryio/rosetta-lbry.git
|
docker build -t rosetta-bitcoin:latest https://github.com/coinbase/rosetta-bitcoin.git
|
||||||
|
|
||||||
build-local:
|
build-local:
|
||||||
docker build -t rosetta-lbry:latest .
|
docker build -t rosetta-bitcoin:latest .
|
||||||
|
|
||||||
build-release:
|
build-release:
|
||||||
# make sure to always set version with vX.X.X
|
# make sure to always set version with vX.X.X
|
||||||
docker build -t rosetta-lbry:$(version) .;
|
docker build -t rosetta-bitcoin:$(version) .;
|
||||||
docker save rosetta-lbry:$(version) | gzip > rosetta-lbry-$(version).tar.gz;
|
docker save rosetta-bitcoin:$(version) | gzip > rosetta-bitcoin-$(version).tar.gz;
|
||||||
|
|
||||||
run-mainnet-online:
|
run-mainnet-online:
|
||||||
docker run -d --rm --ulimit "nofile=${NOFILE}:${NOFILE}" -v "${PWD}/lbry-data:/data" -e "MODE=ONLINE" -e "NETWORK=MAINNET" -e "PORT=8080" -p 8080:8080 -p 9246:9246 rosetta-lbry:latest
|
docker run -d --rm --ulimit "nofile=${NOFILE}:${NOFILE}" -v "${PWD}/bitcoin-data:/data" -e "MODE=ONLINE" -e "NETWORK=MAINNET" -e "PORT=8080" -p 8080:8080 -p 8333:8333 rosetta-bitcoin:latest
|
||||||
|
|
||||||
run-mainnet-offline:
|
run-mainnet-offline:
|
||||||
docker run -d --rm -e "MODE=OFFLINE" -e "NETWORK=MAINNET" -e "PORT=8081" -p 8081:8081 rosetta-lbry:latest
|
docker run -d --rm -e "MODE=OFFLINE" -e "NETWORK=MAINNET" -e "PORT=8081" -p 8081:8081 rosetta-bitcoin:latest
|
||||||
|
|
||||||
run-testnet-online:
|
run-testnet-online:
|
||||||
docker run -d --rm --ulimit "nofile=${NOFILE}:${NOFILE}" -v "${PWD}/lbry-data:/data" -e "MODE=ONLINE" -e "NETWORK=TESTNET" -e "PORT=8080" -p 8080:8080 -p 19246:19246 rosetta-lbry:latest
|
docker run -d --rm --ulimit "nofile=${NOFILE}:${NOFILE}" -v "${PWD}/bitcoin-data:/data" -e "MODE=ONLINE" -e "NETWORK=TESTNET" -e "PORT=8080" -p 8080:8080 -p 18333:18333 rosetta-bitcoin:latest
|
||||||
|
|
||||||
run-testnet-offline:
|
run-testnet-offline:
|
||||||
docker run -d --rm -e "MODE=OFFLINE" -e "NETWORK=TESTNET" -e "PORT=8081" -p 8081:8081 rosetta-lbry:latest
|
docker run -d --rm -e "MODE=OFFLINE" -e "NETWORK=TESTNET" -e "PORT=8081" -p 8081:8081 rosetta-bitcoin:latest
|
||||||
|
|
||||||
train:
|
train:
|
||||||
./zstd-train.sh $(network) transaction $(data-directory)
|
./zstd-train.sh $(network) transaction $(data-directory)
|
||||||
|
@ -71,7 +71,7 @@ check-format:
|
||||||
test:
|
test:
|
||||||
${TEST_SCRIPT}
|
${TEST_SCRIPT}
|
||||||
|
|
||||||
coverage:
|
coverage:
|
||||||
if [ "${COVERALLS_TOKEN}" ]; then ${TEST_SCRIPT} -coverprofile=c.out -covermode=count; ${GOVERALLS_CMD} -coverprofile=c.out -repotoken ${COVERALLS_TOKEN}; fi
|
if [ "${COVERALLS_TOKEN}" ]; then ${TEST_SCRIPT} -coverprofile=c.out -covermode=count; ${GOVERALLS_CMD} -coverprofile=c.out -repotoken ${COVERALLS_TOKEN}; fi
|
||||||
|
|
||||||
coverage-local:
|
coverage-local:
|
||||||
|
|
89
README.md
89
README.md
|
@ -7,11 +7,11 @@
|
||||||
Rosetta Bitcoin
|
Rosetta Bitcoin
|
||||||
</h3>
|
</h3>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://circleci.com/gh/lbryio/rosetta-bitcoin/tree/master"><img src="https://circleci.com/gh/lbryio/rosetta-bitcoin/tree/master.svg?style=shield" /></a>
|
<a href="https://circleci.com/gh/coinbase/rosetta-bitcoin/tree/master"><img src="https://circleci.com/gh/coinbase/rosetta-bitcoin/tree/master.svg?style=shield" /></a>
|
||||||
<a href="https://coveralls.io/github/lbryio/rosetta-bitcoin"><img src="https://coveralls.io/repos/github/lbryio/rosetta-bitcoin/badge.svg" /></a>
|
<a href="https://coveralls.io/github/coinbase/rosetta-bitcoin"><img src="https://coveralls.io/repos/github/coinbase/rosetta-bitcoin/badge.svg" /></a>
|
||||||
<a href="https://goreportcard.com/report/github.com/lbryio/rosetta-bitcoin"><img src="https://goreportcard.com/badge/github.com/lbryio/rosetta-bitcoin" /></a>
|
<a href="https://goreportcard.com/report/github.com/coinbase/rosetta-bitcoin"><img src="https://goreportcard.com/badge/github.com/coinbase/rosetta-bitcoin" /></a>
|
||||||
<a href="https://github.com/lbryio/rosetta-bitcoin/blob/master/LICENSE.txt"><img src="https://img.shields.io/github/license/lbryio/rosetta-bitcoin.svg" /></a>
|
<a href="https://github.com/coinbase/rosetta-bitcoin/blob/master/LICENSE.txt"><img src="https://img.shields.io/github/license/coinbase/rosetta-bitcoin.svg" /></a>
|
||||||
<a href="https://pkg.go.dev/github.com/lbryio/rosetta-bitcoin?tab=overview"><img src="https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=shield" /></a>
|
<a href="https://pkg.go.dev/github.com/coinbase/rosetta-bitcoin?tab=overview"><img src="https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=shield" /></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center"><b>
|
<p align="center"><b>
|
||||||
|
@ -20,19 +20,16 @@ USE AT YOUR OWN RISK! COINBASE ASSUMES NO RESPONSIBILITY NOR LIABILITY IF THERE
|
||||||
</b></p>
|
</b></p>
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
`rosetta-bitcoin` provides a reference implementation of the Rosetta API for
|
`rosetta-bitcoin` provides a reference implementation of the Rosetta API for
|
||||||
Bitcoin in Golang. If you haven't heard of the Rosetta API, you can find more
|
Bitcoin in Golang. If you haven't heard of the Rosetta API, you can find more
|
||||||
information [here](https://rosetta-api.org).
|
information [here](https://rosetta-api.org).
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
* Rosetta API implementation (both Data API and Construction API)
|
||||||
- Rosetta API implementation (both Data API and Construction API)
|
* UTXO cache for all accounts (accessible using `/account/balance`)
|
||||||
- UTXO cache for all accounts (accessible using `/account/balance`)
|
* Stateless, offline, curve-based transaction construction from any SegWit-Bech32 Address
|
||||||
- Stateless, offline, curve-based transaction construction from any SegWit-Bech32 Address
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
As specified in the [Rosetta API Principles](https://www.rosetta-api.org/docs/automated_deployment.html),
|
As specified in the [Rosetta API Principles](https://www.rosetta-api.org/docs/automated_deployment.html),
|
||||||
all Rosetta implementations must be deployable via Docker and support running via either an
|
all Rosetta implementations must be deployable via Docker and support running via either an
|
||||||
[`online` or `offline` mode](https://www.rosetta-api.org/docs/node_deployment.html#multiple-modes).
|
[`online` or `offline` mode](https://www.rosetta-api.org/docs/node_deployment.html#multiple-modes).
|
||||||
|
@ -41,77 +38,59 @@ all Rosetta implementations must be deployable via Docker and support running vi
|
||||||
DOCKER [HERE](https://www.docker.com/get-started).**
|
DOCKER [HERE](https://www.docker.com/get-started).**
|
||||||
|
|
||||||
### Install
|
### Install
|
||||||
|
|
||||||
Running the following commands will create a Docker image called `rosetta-bitcoin:latest`.
|
Running the following commands will create a Docker image called `rosetta-bitcoin:latest`.
|
||||||
|
|
||||||
#### From GitHub
|
#### From GitHub
|
||||||
|
|
||||||
To download the pre-built Docker image from the latest release, run:
|
To download the pre-built Docker image from the latest release, run:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
curl -sSfL https://raw.githubusercontent.com/lbryio/rosetta-bitcoin/master/install.sh | sh -s
|
curl -sSfL https://raw.githubusercontent.com/coinbase/rosetta-bitcoin/master/install.sh | sh -s
|
||||||
```
|
```
|
||||||
|
|
||||||
_Do not try to install rosetta-bitcoin using GitHub Packages!_
|
_Do not try to install rosetta-bitcoin using GitHub Packages!_
|
||||||
|
|
||||||
#### From Source
|
#### From Source
|
||||||
|
|
||||||
After cloning this repository, run:
|
After cloning this repository, run:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
make build-local
|
make build-local
|
||||||
```
|
```
|
||||||
|
|
||||||
### Run
|
### Run
|
||||||
|
|
||||||
Running the following commands will start a Docker container in
|
Running the following commands will start a Docker container in
|
||||||
[detached mode](https://docs.docker.com/engine/reference/run/#detached--d) with
|
[detached mode](https://docs.docker.com/engine/reference/run/#detached--d) with
|
||||||
a data directory at `<working directory>/bitcoin-data` and the Rosetta API accessible
|
a data directory at `<working directory>/bitcoin-data` and the Rosetta API accessible
|
||||||
at port `8080`.
|
at port `8080`.
|
||||||
|
|
||||||
#### Mainnet:Online
|
#### Mainnet:Online
|
||||||
|
|
||||||
```text
|
```text
|
||||||
docker run -d --rm --ulimit "nofile=100000:100000" -v "$(pwd)/bitcoin-data:/data" -e "MODE=ONLINE" -e "NETWORK=MAINNET" -e "PORT=8080" -p 8080:8080 -p 8333:8333 rosetta-bitcoin:latest
|
docker run -d --rm --ulimit "nofile=100000:100000" -v "$(pwd)/bitcoin-data:/data" -e "MODE=ONLINE" -e "NETWORK=MAINNET" -e "PORT=8080" -p 8080:8080 -p 8333:8333 rosetta-bitcoin:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
_If you cloned the repository, you can run `make run-mainnet-online`._
|
_If you cloned the repository, you can run `make run-mainnet-online`._
|
||||||
|
|
||||||
#### Mainnet:Offline
|
#### Mainnet:Offline
|
||||||
|
|
||||||
```text
|
```text
|
||||||
docker run -d --rm -e "MODE=OFFLINE" -e "NETWORK=MAINNET" -e "PORT=8081" -p 8081:8081 rosetta-bitcoin:latest
|
docker run -d --rm -e "MODE=OFFLINE" -e "NETWORK=MAINNET" -e "PORT=8081" -p 8081:8081 rosetta-bitcoin:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
_If you cloned the repository, you can run `make run-mainnet-offline`._
|
_If you cloned the repository, you can run `make run-mainnet-offline`._
|
||||||
|
|
||||||
#### Testnet:Online
|
#### Testnet:Online
|
||||||
|
|
||||||
```text
|
```text
|
||||||
docker run -d --rm --ulimit "nofile=100000:100000" -v "$(pwd)/bitcoin-data:/data" -e "MODE=ONLINE" -e "NETWORK=TESTNET" -e "PORT=8080" -p 8080:8080 -p 18333:18333 rosetta-bitcoin:latest
|
docker run -d --rm --ulimit "nofile=100000:100000" -v "$(pwd)/bitcoin-data:/data" -e "MODE=ONLINE" -e "NETWORK=TESTNET" -e "PORT=8080" -p 8080:8080 -p 18333:18333 rosetta-bitcoin:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
_If you cloned the repository, you can run `make run-testnet-online`._
|
_If you cloned the repository, you can run `make run-testnet-online`._
|
||||||
|
|
||||||
#### Testnet:Offline
|
#### Testnet:Offline
|
||||||
|
|
||||||
```text
|
```text
|
||||||
docker run -d --rm -e "MODE=OFFLINE" -e "NETWORK=TESTNET" -e "PORT=8081" -p 8081:8081 rosetta-bitcoin:latest
|
docker run -d --rm -e "MODE=OFFLINE" -e "NETWORK=TESTNET" -e "PORT=8081" -p 8081:8081 rosetta-bitcoin:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
_If you cloned the repository, you can run `make run-testnet-offline`._
|
_If you cloned the repository, you can run `make run-testnet-offline`._
|
||||||
|
|
||||||
## System Requirements
|
## System Requirements
|
||||||
|
|
||||||
`rosetta-bitcoin` has been tested on an [AWS c5.2xlarge instance](https://aws.amazon.com/ec2/instance-types/c5).
|
`rosetta-bitcoin` has been tested on an [AWS c5.2xlarge instance](https://aws.amazon.com/ec2/instance-types/c5).
|
||||||
This instance type has 8 vCPU and 16 GB of RAM.
|
This instance type has 8 vCPU and 16 GB of RAM.
|
||||||
|
|
||||||
### Network Settings
|
### Network Settings
|
||||||
|
|
||||||
To increase the load `rosetta-bitcoin` can handle, it is recommended to tune your OS
|
To increase the load `rosetta-bitcoin` can handle, it is recommended to tune your OS
|
||||||
settings to allow for more connections. On a linux-based OS, you can run the following
|
settings to allow for more connections. On a linux-based OS, you can run the following
|
||||||
commands ([source](http://www.tweaked.io/guide/kernel)):
|
commands ([source](http://www.tweaked.io/guide/kernel)):
|
||||||
|
|
||||||
```text
|
```text
|
||||||
sysctl -w net.ipv4.tcp_tw_reuse=1
|
sysctl -w net.ipv4.tcp_tw_reuse=1
|
||||||
sysctl -w net.core.rmem_max=16777216
|
sysctl -w net.core.rmem_max=16777216
|
||||||
|
@ -120,7 +99,6 @@ sysctl -w net.ipv4.tcp_max_syn_backlog=10000
|
||||||
sysctl -w net.core.somaxconn=10000
|
sysctl -w net.core.somaxconn=10000
|
||||||
sysctl -p (when done)
|
sysctl -p (when done)
|
||||||
```
|
```
|
||||||
|
|
||||||
_We have not tested `rosetta-bitcoin` with `net.ipv4.tcp_tw_recycle` and do not recommend
|
_We have not tested `rosetta-bitcoin` with `net.ipv4.tcp_tw_recycle` and do not recommend
|
||||||
enabling it._
|
enabling it._
|
||||||
|
|
||||||
|
@ -128,7 +106,6 @@ You should also modify your open file settings to `100000`. This can be done on
|
||||||
with the command: `ulimit -n 100000`.
|
with the command: `ulimit -n 100000`.
|
||||||
|
|
||||||
### Memory-Mapped Files
|
### Memory-Mapped Files
|
||||||
|
|
||||||
`rosetta-bitcoin` uses [memory-mapped files](https://en.wikipedia.org/wiki/Memory-mapped_file) to
|
`rosetta-bitcoin` uses [memory-mapped files](https://en.wikipedia.org/wiki/Memory-mapped_file) to
|
||||||
persist data in the `indexer`. As a result, you **must** run `rosetta-bitcoin` on a 64-bit
|
persist data in the `indexer`. As a result, you **must** run `rosetta-bitcoin` on a 64-bit
|
||||||
architecture (the virtual address space easily exceeds 100s of GBs).
|
architecture (the virtual address space easily exceeds 100s of GBs).
|
||||||
|
@ -137,12 +114,10 @@ If you receive a kernel OOM, you may need to increase the allocated size of swap
|
||||||
on your OS. There is a great tutorial for how to do this on Linux [here](https://linuxize.com/post/create-a-linux-swap-file/).
|
on your OS. There is a great tutorial for how to do this on Linux [here](https://linuxize.com/post/create-a-linux-swap-file/).
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
`rosetta-bitcoin` uses the `syncer`, `storage`, `parser`, and `server` package
|
`rosetta-bitcoin` uses the `syncer`, `storage`, `parser`, and `server` package
|
||||||
from [`rosetta-sdk-go`](https://github.com/coinbase/rosetta-sdk-go) instead
|
from [`rosetta-sdk-go`](https://github.com/coinbase/rosetta-sdk-go) instead
|
||||||
of a new Bitcoin-specific implementation of packages of similar functionality. Below
|
of a new Bitcoin-specific implementation of packages of similar functionality. Below
|
||||||
you can find a high-level overview of how everything fits together:
|
you can find a high-level overview of how everything fits together:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
+------------------------------------------------------------------+
|
+------------------------------------------------------------------+
|
||||||
| |
|
| |
|
||||||
|
@ -182,20 +157,17 @@ you can find a high-level overview of how everything fits together:
|
||||||
```
|
```
|
||||||
|
|
||||||
### Optimizations
|
### Optimizations
|
||||||
|
* Automatically prune bitcoind while indexing blocks
|
||||||
- Automatically prune bitcoind while indexing blocks
|
* Reduce sync time with concurrent block indexing
|
||||||
- Reduce sync time with concurrent block indexing
|
* Use [Zstandard compression](https://github.com/facebook/zstd) to reduce the size of data stored on disk
|
||||||
- Use [Zstandard compression](https://github.com/facebook/zstd) to reduce the size of data stored on disk
|
without needing to write a manual byte-level encoding
|
||||||
without needing to write a manual byte-level encoding
|
|
||||||
|
|
||||||
#### Concurrent Block Syncing
|
#### Concurrent Block Syncing
|
||||||
|
|
||||||
To speed up indexing, `rosetta-bitcoin` uses concurrent block processing
|
To speed up indexing, `rosetta-bitcoin` uses concurrent block processing
|
||||||
with a "wait free" design (using channels instead of sleeps to signal
|
with a "wait free" design (using channels instead of sleeps to signal
|
||||||
which threads are unblocked). This allows `rosetta-bitcoin` to fetch
|
which threads are unblocked). This allows `rosetta-bitcoin` to fetch
|
||||||
multiple inputs from disk while it waits for inputs that appeared
|
multiple inputs from disk while it waits for inputs that appeared
|
||||||
in recently processed blocks to save to disk.
|
in recently processed blocks to save to disk.
|
||||||
|
|
||||||
```text
|
```text
|
||||||
+----------+
|
+----------+
|
||||||
| bitcoind |
|
| bitcoind |
|
||||||
|
@ -233,35 +205,30 @@ in recently processed blocks to save to disk.
|
||||||
```
|
```
|
||||||
|
|
||||||
## Testing with rosetta-cli
|
## Testing with rosetta-cli
|
||||||
|
To validate `rosetta-bitcoin`, [install `rosetta-cli`](https://github.com/coinbase/rosetta-cli#install)
|
||||||
To validate `rosetta-bitcoin`, [install `rosetta-cli`](https://github.com/lbryio/rosetta-cli#install)
|
|
||||||
and run one of the following commands:
|
and run one of the following commands:
|
||||||
|
* `rosetta-cli check:data --configuration-file rosetta-cli-conf/testnet/config.json`
|
||||||
- `rosetta-cli check:data --configuration-file rosetta-cli-conf/testnet/config.json`
|
* `rosetta-cli check:construction --configuration-file rosetta-cli-conf/testnet/config.json`
|
||||||
- `rosetta-cli check:construction --configuration-file rosetta-cli-conf/testnet/config.json`
|
* `rosetta-cli check:data --configuration-file rosetta-cli-conf/mainnet/config.json`
|
||||||
- `rosetta-cli check:data --configuration-file rosetta-cli-conf/mainnet/config.json`
|
|
||||||
|
|
||||||
## Future Work
|
## Future Work
|
||||||
|
* Publish benchamrks for sync speed, storage usage, and load testing
|
||||||
- Publish benchamrks for sync speed, storage usage, and load testing
|
* [Rosetta API `/mempool/transaction`](https://www.rosetta-api.org/docs/MempoolApi.html#mempooltransaction) implementation
|
||||||
- [Rosetta API `/mempool/transaction`](https://www.rosetta-api.org/docs/MempoolApi.html#mempooltransaction) implementation
|
* Add CI test using `rosetta-cli` to run on each PR (likely on a regtest network)
|
||||||
- Add CI test using `rosetta-cli` to run on each PR (likely on a regtest network)
|
* Add performance mode to use unlimited RAM (implementation currently optimized to use <= 16 GB of RAM)
|
||||||
- Add performance mode to use unlimited RAM (implementation currently optimized to use <= 16 GB of RAM)
|
* Support Multi-Sig Sends
|
||||||
- Support Multi-Sig Sends
|
|
||||||
|
|
||||||
_Please reach out on our [community](https://community.rosetta-api.org) if you want to tackle anything on this list!_
|
_Please reach out on our [community](https://community.rosetta-api.org) if you want to tackle anything on this list!_
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
* `make deps` to install dependencies
|
||||||
- `make deps` to install dependencies
|
* `make test` to run tests
|
||||||
- `make test` to run tests
|
* `make lint` to lint the source code
|
||||||
- `make lint` to lint the source code
|
* `make salus` to check for security concerns
|
||||||
- `make salus` to check for security concerns
|
* `make build-local` to build a Docker image from the local context
|
||||||
- `make build-local` to build a Docker image from the local context
|
* `make coverage-local` to generate a coverage report
|
||||||
- `make coverage-local` to generate a coverage report
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This project is available open source under the terms of the [Apache 2.0 License](https://opensource.org/licenses/Apache-2.0).
|
This project is available open source under the terms of the [Apache 2.0 License](https://opensource.org/licenses/Apache-2.0).
|
||||||
|
|
||||||
© 2020 Coinbase
|
© 2020 Coinbase
|
||||||
|
|
26
assets/bitcoin-mainnet.conf
Normal file
26
assets/bitcoin-mainnet.conf
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
##
|
||||||
|
## bitcoin.conf configuration file. Lines beginning with # are comments.
|
||||||
|
##
|
||||||
|
|
||||||
|
# DO NOT USE THIS CONFIGURATION FILE IF YOU PLAN TO EXPOSE
|
||||||
|
# BITCOIND'S RPC PORT PUBLICALLY (THESE INSECURE CREDENTIALS
|
||||||
|
# COULD LEAD TO AN ATTACK). ROSETTA-BITCOIN USES THE RPC PORT
|
||||||
|
# FOR INDEXING AND TRANSACTION BROADCAST BUT NEVER PROVIDES THE
|
||||||
|
# CALLER ACCESS TO BITCOIND'S RPC PORT.
|
||||||
|
|
||||||
|
datadir=/data/bitcoind
|
||||||
|
bind=0.0.0.0
|
||||||
|
rpcbind=0.0.0.0
|
||||||
|
bantime=15
|
||||||
|
rpcallowip=0.0.0.0/0
|
||||||
|
rpcthreads=16
|
||||||
|
rpcworkqueue=1000
|
||||||
|
disablewallet=1
|
||||||
|
txindex=0
|
||||||
|
port=8333
|
||||||
|
rpcport=8332
|
||||||
|
rpcuser=rosetta
|
||||||
|
rpcpassword=rosetta
|
||||||
|
|
||||||
|
# allow manual pruning
|
||||||
|
prune=1
|
|
@ -1,14 +1,14 @@
|
||||||
##
|
##
|
||||||
## lbry.conf configuration file. Lines beginning with # are comments.
|
## bitcoin.conf configuration file. Lines beginning with # are comments.
|
||||||
##
|
##
|
||||||
|
|
||||||
# DO NOT USE THIS CONFIGURATION FILE IF YOU PLAN TO EXPOSE
|
# DO NOT USE THIS CONFIGURATION FILE IF YOU PLAN TO EXPOSE
|
||||||
# LBRYCRDD'S RPC PORT PUBLICALLY (THESE INSECURE CREDENTIALS
|
# BITCOIND'S RPC PORT PUBLICALLY (THESE INSECURE CREDENTIALS
|
||||||
# COULD LEAD TO AN ATTACK). ROSETTA-LBRY USES THE RPC PORT
|
# COULD LEAD TO AN ATTACK). ROSETTA-BITCOIN USES THE RPC PORT
|
||||||
# FOR INDEXING AND TRANSACTION BROADCAST BUT NEVER PROVIDES THE
|
# FOR INDEXING AND TRANSACTION BROADCAST BUT NEVER PROVIDES THE
|
||||||
# CALLER ACCESS TO LBRYCRDD'S RPC PORT.
|
# CALLER ACCESS TO BITCOIND'S RPC PORT.
|
||||||
|
|
||||||
datadir=/data/lbrycrdd
|
datadir=/data/bitcoind
|
||||||
bantime=15
|
bantime=15
|
||||||
rpcallowip=0.0.0.0/0
|
rpcallowip=0.0.0.0/0
|
||||||
rpcthreads=16
|
rpcthreads=16
|
||||||
|
@ -23,7 +23,7 @@ prune=1
|
||||||
testnet=1
|
testnet=1
|
||||||
|
|
||||||
[test]
|
[test]
|
||||||
port=19246
|
port=18333
|
||||||
bind=0.0.0.0
|
bind=0.0.0.0
|
||||||
rpcport=19245
|
rpcport=18332
|
||||||
rpcbind=0.0.0.0
|
rpcbind=0.0.0.0
|
17
assets/bitcoin.json
Normal file
17
assets/bitcoin.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"network": {
|
||||||
|
"blockchain": "Bitcoin",
|
||||||
|
"network": "Mainnet"
|
||||||
|
},
|
||||||
|
"online_url": "http://localhost:8080",
|
||||||
|
"data_directory": "",
|
||||||
|
"http_timeout": 10,
|
||||||
|
"sync_concurrency": 8,
|
||||||
|
"transaction_concurrency": 16,
|
||||||
|
"tip_delay": 300,
|
||||||
|
"disable_memory_limit": false,
|
||||||
|
"log_configuration": false,
|
||||||
|
"data": {
|
||||||
|
"historical_balance_disabled": true
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,27 +0,0 @@
|
||||||
##
|
|
||||||
## lbry.conf configuration file. Lines beginning with # are comments.
|
|
||||||
##
|
|
||||||
|
|
||||||
# DO NOT USE THIS CONFIGURATION FILE IF YOU PLAN TO EXPOSE
|
|
||||||
# LBRYCRDD'S RPC PORT PUBLICALLY (THESE INSECURE CREDENTIALS
|
|
||||||
# COULD LEAD TO AN ATTACK). ROSETTA-LBRY USES THE RPC PORT
|
|
||||||
# FOR INDEXING AND TRANSACTION BROADCAST BUT NEVER PROVIDES THE
|
|
||||||
# CALLER ACCESS TO LBRYCRDD'S RPC PORT.
|
|
||||||
|
|
||||||
datadir=/data/lbrycrdd
|
|
||||||
bind=0.0.0.0
|
|
||||||
rpcbind=0.0.0.0
|
|
||||||
bantime=15
|
|
||||||
rpcallowip=0.0.0.0/0
|
|
||||||
rpcthreads=30
|
|
||||||
disablewallet=1
|
|
||||||
txindex=0
|
|
||||||
port=9246
|
|
||||||
rpcport=9245
|
|
||||||
rpcuser=rosetta
|
|
||||||
rpcpassword=rosetta
|
|
||||||
rpcworkqueue=3000
|
|
||||||
dbcache=3000
|
|
||||||
|
|
||||||
# allow manual pruning
|
|
||||||
prune=1
|
|
|
@ -1,17 +0,0 @@
|
||||||
{
|
|
||||||
"network": {
|
|
||||||
"blockchain": "lbry",
|
|
||||||
"network": "Mainnet"
|
|
||||||
},
|
|
||||||
"online_url": "http://localhost:8080",
|
|
||||||
"data_directory": "",
|
|
||||||
"http_timeout": 10,
|
|
||||||
"sync_concurrency": 8,
|
|
||||||
"transaction_concurrency": 16,
|
|
||||||
"tip_delay": 300,
|
|
||||||
"disable_memory_limit": false,
|
|
||||||
"log_configuration": false,
|
|
||||||
"data": {
|
|
||||||
"historical_balance_disabled": true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package lbry
|
package bitcoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -26,16 +26,17 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
lbryUtils "github.com/lbryio/rosetta-lbry/utils"
|
bitcoinUtils "github.com/coinbase/rosetta-bitcoin/utils"
|
||||||
|
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
|
"github.com/coinbase/rosetta-sdk-go/storage"
|
||||||
"github.com/coinbase/rosetta-sdk-go/types"
|
"github.com/coinbase/rosetta-sdk-go/types"
|
||||||
"github.com/coinbase/rosetta-sdk-go/utils"
|
"github.com/coinbase/rosetta-sdk-go/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// genesisBlockIndex is the height of the block we consider to be the
|
// genesisBlockIndex is the height of the block we consider to be the
|
||||||
// genesis block of the lbry blockchain for polling
|
// genesis block of the bitcoin blockchain for polling
|
||||||
genesisBlockIndex = 0
|
genesisBlockIndex = 0
|
||||||
|
|
||||||
// requestID is the JSON-RPC request ID we use for making requests.
|
// requestID is the JSON-RPC request ID we use for making requests.
|
||||||
|
@ -56,28 +57,28 @@ const (
|
||||||
type requestMethod string
|
type requestMethod string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// https://lbry.org/en/developer-reference#getblock
|
// https://bitcoin.org/en/developer-reference#getblock
|
||||||
requestMethodGetBlock requestMethod = "getblock"
|
requestMethodGetBlock requestMethod = "getblock"
|
||||||
|
|
||||||
// https://lbry.org/en/developer-reference#getblockhash
|
// https://bitcoin.org/en/developer-reference#getblockhash
|
||||||
requestMethodGetBlockHash requestMethod = "getblockhash"
|
requestMethodGetBlockHash requestMethod = "getblockhash"
|
||||||
|
|
||||||
// https://lbry.org/en/developer-reference#getblockchaininfo
|
// https://bitcoin.org/en/developer-reference#getblockchaininfo
|
||||||
requestMethodGetBlockchainInfo requestMethod = "getblockchaininfo"
|
requestMethodGetBlockchainInfo requestMethod = "getblockchaininfo"
|
||||||
|
|
||||||
// https://developer.lbry.org/reference/rpc/getpeerinfo.html
|
// https://developer.bitcoin.org/reference/rpc/getpeerinfo.html
|
||||||
requestMethodGetPeerInfo requestMethod = "getpeerinfo"
|
requestMethodGetPeerInfo requestMethod = "getpeerinfo"
|
||||||
|
|
||||||
// https://developer.lbry.org/reference/rpc/pruneblockchain.html
|
// https://developer.bitcoin.org/reference/rpc/pruneblockchain.html
|
||||||
requestMethodPruneBlockchain requestMethod = "pruneblockchain"
|
requestMethodPruneBlockchain requestMethod = "pruneblockchain"
|
||||||
|
|
||||||
// https://developer.lbry.org/reference/rpc/sendrawtransaction.html
|
// https://developer.bitcoin.org/reference/rpc/sendrawtransaction.html
|
||||||
requestMethodSendRawTransaction requestMethod = "sendrawtransaction"
|
requestMethodSendRawTransaction requestMethod = "sendrawtransaction"
|
||||||
|
|
||||||
// https://developer.lbry.org/reference/rpc/estimatesmartfee.html
|
// https://developer.bitcoin.org/reference/rpc/estimatesmartfee.html
|
||||||
requestMethodEstimateSmartFee requestMethod = "estimatesmartfee"
|
requestMethodEstimateSmartFee requestMethod = "estimatesmartfee"
|
||||||
|
|
||||||
// https://developer.lbry.org/reference/rpc/getrawmempool.html
|
// https://developer.bitcoin.org/reference/rpc/getrawmempool.html
|
||||||
requestMethodRawMempool requestMethod = "getrawmempool"
|
requestMethodRawMempool requestMethod = "getrawmempool"
|
||||||
|
|
||||||
// blockNotFoundErrCode is the RPC error code when a block cannot be found
|
// blockNotFoundErrCode is the RPC error code when a block cannot be found
|
||||||
|
@ -89,11 +90,11 @@ const (
|
||||||
dialTimeout = 5 * time.Second
|
dialTimeout = 5 * time.Second
|
||||||
|
|
||||||
// timeMultiplier is used to multiply the time
|
// timeMultiplier is used to multiply the time
|
||||||
// returned in lbry blocks to be milliseconds.
|
// returned in Bitcoin blocks to be milliseconds.
|
||||||
timeMultiplier = 1000
|
timeMultiplier = 1000
|
||||||
|
|
||||||
// rpc credentials are fixed in rosetta-lbry
|
// rpc credentials are fixed in rosetta-bitcoin
|
||||||
// because we never expose access to the raw lbrycrdd
|
// because we never expose access to the raw bitcoind
|
||||||
// endpoints (that could be used perform an attack, like
|
// endpoints (that could be used perform an attack, like
|
||||||
// changing our peers).
|
// changing our peers).
|
||||||
rpcUsername = "rosetta"
|
rpcUsername = "rosetta"
|
||||||
|
@ -109,10 +110,10 @@ var (
|
||||||
ErrJSONRPCError = errors.New("JSON-RPC error")
|
ErrJSONRPCError = errors.New("JSON-RPC error")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client is used to fetch blocks from lbrycrdd and
|
// Client is used to fetch blocks from bitcoind and
|
||||||
// to parse lbry block data into Rosetta types.
|
// to parse Bitcoin block data into Rosetta types.
|
||||||
//
|
//
|
||||||
// We opted not to use existing lbry RPC libraries
|
// We opted not to use existing Bitcoin RPC libraries
|
||||||
// because they don't allow providing context
|
// because they don't allow providing context
|
||||||
// in each request.
|
// in each request.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
|
@ -130,7 +131,7 @@ func LocalhostURL(rpcPort int) string {
|
||||||
return fmt.Sprintf("http://localhost:%d", rpcPort)
|
return fmt.Sprintf("http://localhost:%d", rpcPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient creates a new lbry client.
|
// NewClient creates a new Bitcoin client.
|
||||||
func NewClient(
|
func NewClient(
|
||||||
baseURL string,
|
baseURL string,
|
||||||
genesisBlockIdentifier *types.BlockIdentifier,
|
genesisBlockIdentifier *types.BlockIdentifier,
|
||||||
|
@ -161,7 +162,7 @@ func newHTTPClient(timeout time.Duration) *http.Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetworkStatus returns the *types.NetworkStatusResponse for
|
// NetworkStatus returns the *types.NetworkStatusResponse for
|
||||||
// lbrycrdd.
|
// bitcoind.
|
||||||
func (b *Client) NetworkStatus(ctx context.Context) (*types.NetworkStatusResponse, error) {
|
func (b *Client) NetworkStatus(ctx context.Context) (*types.NetworkStatusResponse, error) {
|
||||||
rawBlock, err := b.getBlock(ctx, nil)
|
rawBlock, err := b.getBlock(ctx, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -240,12 +241,12 @@ func (b *Client) GetRawBlock(
|
||||||
return block, coins, nil
|
return block, coins, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseBlock returns a parsed lbry block given a raw lbry
|
// ParseBlock returns a parsed bitcoin block given a raw bitcoin
|
||||||
// block and a map of transactions containing inputs.
|
// block and a map of transactions containing inputs.
|
||||||
func (b *Client) ParseBlock(
|
func (b *Client) ParseBlock(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
block *Block,
|
block *Block,
|
||||||
coins map[string]*types.AccountCoin,
|
coins map[string]*storage.AccountCoin,
|
||||||
) (*types.Block, error) {
|
) (*types.Block, error) {
|
||||||
rblock, err := b.parseBlockData(block)
|
rblock, err := b.parseBlockData(block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -263,7 +264,7 @@ func (b *Client) ParseBlock(
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendRawTransaction submits a serialized transaction
|
// SendRawTransaction submits a serialized transaction
|
||||||
// to lbrycrdd.
|
// to bitcoind.
|
||||||
func (b *Client) SendRawTransaction(
|
func (b *Client) SendRawTransaction(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
serializedTx string,
|
serializedTx string,
|
||||||
|
@ -300,14 +301,14 @@ func (b *Client) SuggestedFeeRate(
|
||||||
}
|
}
|
||||||
|
|
||||||
// PruneBlockchain prunes up to the provided height.
|
// PruneBlockchain prunes up to the provided height.
|
||||||
// https://lbrycore.org/en/doc/0.20.0/rpc/blockchain/pruneblockchain
|
// https://bitcoincore.org/en/doc/0.20.0/rpc/blockchain/pruneblockchain
|
||||||
func (b *Client) PruneBlockchain(
|
func (b *Client) PruneBlockchain(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
height int64,
|
height int64,
|
||||||
) (int64, error) {
|
) (int64, error) {
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// 1. Height
|
// 1. Height
|
||||||
// https://developer.lbry.org/reference/rpc/pruneblockchain.html#argument-1-height
|
// https://developer.bitcoin.org/reference/rpc/pruneblockchain.html#argument-1-height
|
||||||
params := []interface{}{height}
|
params := []interface{}{height}
|
||||||
|
|
||||||
response := &pruneBlockchainResponse{}
|
response := &pruneBlockchainResponse{}
|
||||||
|
@ -361,7 +362,7 @@ func (b *Client) getBlock(
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// 1. Block hash (string, required)
|
// 1. Block hash (string, required)
|
||||||
// 2. Verbosity (integer, optional, default=1)
|
// 2. Verbosity (integer, optional, default=1)
|
||||||
// https://lbry.org/en/developer-reference#getblock
|
// https://bitcoin.org/en/developer-reference#getblock
|
||||||
params := []interface{}{hash, blockVerbosity}
|
params := []interface{}{hash, blockVerbosity}
|
||||||
|
|
||||||
response := &blockResponse{}
|
response := &blockResponse{}
|
||||||
|
@ -447,14 +448,14 @@ func (b *Client) parseBlockData(block *Block) (*types.Block, error) {
|
||||||
|
|
||||||
// getHashFromIndex performs the `getblockhash` JSON-RPC request for the specified
|
// getHashFromIndex performs the `getblockhash` JSON-RPC request for the specified
|
||||||
// block index, and returns the hash.
|
// block index, and returns the hash.
|
||||||
// https://lbry.org/en/developer-reference#getblockhash
|
// https://bitcoin.org/en/developer-reference#getblockhash
|
||||||
func (b *Client) getHashFromIndex(
|
func (b *Client) getHashFromIndex(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
index int64,
|
index int64,
|
||||||
) (string, error) {
|
) (string, error) {
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// 1. Block height (numeric, required)
|
// 1. Block height (numeric, required)
|
||||||
// https://lbry.org/en/developer-reference#getblockhash
|
// https://bitcoin.org/en/developer-reference#getblockhash
|
||||||
params := []interface{}{index}
|
params := []interface{}{index}
|
||||||
|
|
||||||
response := &blockHashResponse{}
|
response := &blockHashResponse{}
|
||||||
|
@ -471,9 +472,9 @@ func (b *Client) getHashFromIndex(
|
||||||
|
|
||||||
// skipTransactionOperations is used to skip operations on transactions that
|
// skipTransactionOperations is used to skip operations on transactions that
|
||||||
// contain duplicate UTXOs (which are no longer possible after BIP-30). This
|
// contain duplicate UTXOs (which are no longer possible after BIP-30). This
|
||||||
// function mirrors the behavior of a similar commit in lbry-core.
|
// function mirrors the behavior of a similar commit in bitcoin-core.
|
||||||
//
|
//
|
||||||
// Source: https://github.com/lbry/lbry/commit/ab91bf39b7c11e9c86bb2043c24f0f377f1cf514
|
// Source: https://github.com/bitcoin/bitcoin/commit/ab91bf39b7c11e9c86bb2043c24f0f377f1cf514
|
||||||
func skipTransactionOperations(blockNumber int64, blockHash string, transactionHash string) bool {
|
func skipTransactionOperations(blockNumber int64, blockHash string, transactionHash string) bool {
|
||||||
if blockNumber == 91842 && blockHash == "00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec" &&
|
if blockNumber == 91842 && blockHash == "00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec" &&
|
||||||
transactionHash == "d5d27987d2a3dfc724e359870c6644b40e497bdc0589a033220fe15429d88599" {
|
transactionHash == "d5d27987d2a3dfc724e359870c6644b40e497bdc0589a033220fe15429d88599" {
|
||||||
|
@ -492,9 +493,9 @@ func skipTransactionOperations(blockNumber int64, blockHash string, transactionH
|
||||||
func (b *Client) parseTransactions(
|
func (b *Client) parseTransactions(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
block *Block,
|
block *Block,
|
||||||
coins map[string]*types.AccountCoin,
|
coins map[string]*storage.AccountCoin,
|
||||||
) ([]*types.Transaction, error) {
|
) ([]*types.Transaction, error) {
|
||||||
logger := lbryUtils.ExtractLogger(ctx, "client")
|
logger := bitcoinUtils.ExtractLogger(ctx, "client")
|
||||||
|
|
||||||
if block == nil {
|
if block == nil {
|
||||||
return nil, errors.New("error parsing nil block")
|
return nil, errors.New("error parsing nil block")
|
||||||
|
@ -515,8 +516,9 @@ func (b *Client) parseTransactions(
|
||||||
"block hash", block.Hash,
|
"block hash", block.Hash,
|
||||||
"transaction hash", transaction.Hash,
|
"transaction hash", transaction.Hash,
|
||||||
)
|
)
|
||||||
|
|
||||||
for _, op := range txOps {
|
for _, op := range txOps {
|
||||||
op.Status = types.String(SkippedStatus)
|
op.Status = SkippedStatus
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -546,7 +548,7 @@ func (b *Client) parseTransactions(
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
coins[op.CoinChange.CoinIdentifier.Identifier] = &types.AccountCoin{
|
coins[op.CoinChange.CoinIdentifier.Identifier] = &storage.AccountCoin{
|
||||||
Coin: &types.Coin{
|
Coin: &types.Coin{
|
||||||
CoinIdentifier: op.CoinChange.CoinIdentifier,
|
CoinIdentifier: op.CoinChange.CoinIdentifier,
|
||||||
Amount: op.Amount,
|
Amount: op.Amount,
|
||||||
|
@ -564,12 +566,12 @@ func (b *Client) parseTransactions(
|
||||||
func (b *Client) parseTxOperations(
|
func (b *Client) parseTxOperations(
|
||||||
tx *Transaction,
|
tx *Transaction,
|
||||||
txIndex int,
|
txIndex int,
|
||||||
coins map[string]*types.AccountCoin,
|
coins map[string]*storage.AccountCoin,
|
||||||
) ([]*types.Operation, error) {
|
) ([]*types.Operation, error) {
|
||||||
txOps := []*types.Operation{}
|
txOps := []*types.Operation{}
|
||||||
|
|
||||||
for networkIndex, input := range tx.Inputs {
|
for networkIndex, input := range tx.Inputs {
|
||||||
if lbryIsCoinbaseInput(input, txIndex, networkIndex) {
|
if bitcoinIsCoinbaseInput(input, txIndex, networkIndex) {
|
||||||
txOp, err := b.coinbaseTxOperation(input, int64(len(txOps)), int64(networkIndex))
|
txOp, err := b.coinbaseTxOperation(input, int64(len(txOps)), int64(networkIndex))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -579,7 +581,7 @@ func (b *Client) parseTxOperations(
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the *types.AccountCoin the input is associated with
|
// Fetch the *storage.AccountCoin the input is associated with
|
||||||
accountCoin, ok := coins[CoinIdentifier(input.TxHash, input.Vout)]
|
accountCoin, ok := coins[CoinIdentifier(input.TxHash, input.Vout)]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf(
|
return nil, fmt.Errorf(
|
||||||
|
@ -627,7 +629,7 @@ func (b *Client) parseTxOperations(
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseOutputTransactionOperation returns the types.Operation for the specified
|
// parseOutputTransactionOperation returns the types.Operation for the specified
|
||||||
// `lbryOutput` transaction output.
|
// `bitcoinOutput` transaction output.
|
||||||
func (b *Client) parseOutputTransactionOperation(
|
func (b *Client) parseOutputTransactionOperation(
|
||||||
output *Output,
|
output *Output,
|
||||||
txHash string,
|
txHash string,
|
||||||
|
@ -656,7 +658,7 @@ func (b *Client) parseOutputTransactionOperation(
|
||||||
CoinAction: types.CoinCreated,
|
CoinAction: types.CoinCreated,
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are unable to parse the output account (i.e. lbrycrdd
|
// If we are unable to parse the output account (i.e. bitcoind
|
||||||
// returns a blank/nonstandard ScriptPubKey), we create an address as the
|
// returns a blank/nonstandard ScriptPubKey), we create an address as the
|
||||||
// concatenation of the tx hash and index.
|
// concatenation of the tx hash and index.
|
||||||
//
|
//
|
||||||
|
@ -679,7 +681,7 @@ func (b *Client) parseOutputTransactionOperation(
|
||||||
NetworkIndex: &networkIndex,
|
NetworkIndex: &networkIndex,
|
||||||
},
|
},
|
||||||
Type: OutputOpType,
|
Type: OutputOpType,
|
||||||
Status: types.String(SuccessStatus),
|
Status: SuccessStatus,
|
||||||
Account: account,
|
Account: account,
|
||||||
Amount: &types.Amount{
|
Amount: &types.Amount{
|
||||||
Value: strconv.FormatInt(int64(amount), 10),
|
Value: strconv.FormatInt(int64(amount), 10),
|
||||||
|
@ -698,17 +700,17 @@ func (b *Client) getInputTxHash(
|
||||||
txIndex int,
|
txIndex int,
|
||||||
inputIndex int,
|
inputIndex int,
|
||||||
) (string, int64, bool) {
|
) (string, int64, bool) {
|
||||||
if lbryIsCoinbaseInput(input, txIndex, inputIndex) {
|
if bitcoinIsCoinbaseInput(input, txIndex, inputIndex) {
|
||||||
return "", -1, false
|
return "", -1, false
|
||||||
}
|
}
|
||||||
|
|
||||||
return input.TxHash, input.Vout, true
|
return input.TxHash, input.Vout, true
|
||||||
}
|
}
|
||||||
|
|
||||||
// lbryIsCoinbaseInput returns whether the specified input is
|
// bitcoinIsCoinbaseInput returns whether the specified input is
|
||||||
// the coinbase input. The coinbase input is always the first input in the first
|
// the coinbase input. The coinbase input is always the first input in the first
|
||||||
// transaction, and does not contain a previous transaction hash.
|
// transaction, and does not contain a previous transaction hash.
|
||||||
func lbryIsCoinbaseInput(input *Input, txIndex int, inputIndex int) bool {
|
func bitcoinIsCoinbaseInput(input *Input, txIndex int, inputIndex int) bool {
|
||||||
return txIndex == 0 && inputIndex == 0 && input.TxHash == "" && input.Coinbase != ""
|
return txIndex == 0 && inputIndex == 0 && input.TxHash == "" && input.Coinbase != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -718,7 +720,7 @@ func (b *Client) parseInputTransactionOperation(
|
||||||
input *Input,
|
input *Input,
|
||||||
index int64,
|
index int64,
|
||||||
networkIndex int64,
|
networkIndex int64,
|
||||||
accountCoin *types.AccountCoin,
|
accountCoin *storage.AccountCoin,
|
||||||
) (*types.Operation, error) {
|
) (*types.Operation, error) {
|
||||||
metadata, err := input.Metadata()
|
metadata, err := input.Metadata()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -736,7 +738,7 @@ func (b *Client) parseInputTransactionOperation(
|
||||||
NetworkIndex: &networkIndex,
|
NetworkIndex: &networkIndex,
|
||||||
},
|
},
|
||||||
Type: InputOpType,
|
Type: InputOpType,
|
||||||
Status: types.String(SuccessStatus),
|
Status: SuccessStatus,
|
||||||
Account: accountCoin.Account,
|
Account: accountCoin.Account,
|
||||||
Amount: &types.Amount{
|
Amount: &types.Amount{
|
||||||
Value: newValue,
|
Value: newValue,
|
||||||
|
@ -767,7 +769,7 @@ func (b *Client) parseAmount(amount float64) (uint64, error) {
|
||||||
return uint64(atomicAmount), nil
|
return uint64(atomicAmount), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseOutputAccount parses a lbryScriptPubKey and returns an account
|
// parseOutputAccount parses a bitcoinScriptPubKey and returns an account
|
||||||
// identifier. The account identifier's address corresponds to the first
|
// identifier. The account identifier's address corresponds to the first
|
||||||
// address encoded in the script.
|
// address encoded in the script.
|
||||||
func (b *Client) parseOutputAccount(
|
func (b *Client) parseOutputAccount(
|
||||||
|
@ -798,12 +800,12 @@ func (b *Client) coinbaseTxOperation(
|
||||||
NetworkIndex: &networkIndex,
|
NetworkIndex: &networkIndex,
|
||||||
},
|
},
|
||||||
Type: CoinbaseOpType,
|
Type: CoinbaseOpType,
|
||||||
Status: types.String(SuccessStatus),
|
Status: SuccessStatus,
|
||||||
Metadata: metadata,
|
Metadata: metadata,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// post makes a HTTP request to a lbry node
|
// post makes a HTTP request to a Bitcoin node
|
||||||
func (b *Client) post(
|
func (b *Client) post(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
method requestMethod,
|
method requestMethod,
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package lbry
|
package bitcoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
@ -24,6 +24,7 @@ import (
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/coinbase/rosetta-sdk-go/storage"
|
||||||
"github.com/coinbase/rosetta-sdk-go/types"
|
"github.com/coinbase/rosetta-sdk-go/types"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
@ -707,14 +708,14 @@ func mustMarshalMap(v interface{}) map[string]interface{} {
|
||||||
func TestParseBlock(t *testing.T) {
|
func TestParseBlock(t *testing.T) {
|
||||||
tests := map[string]struct {
|
tests := map[string]struct {
|
||||||
block *Block
|
block *Block
|
||||||
coins map[string]*types.AccountCoin
|
coins map[string]*storage.AccountCoin
|
||||||
|
|
||||||
expectedBlock *types.Block
|
expectedBlock *types.Block
|
||||||
expectedError error
|
expectedError error
|
||||||
}{
|
}{
|
||||||
"no fetched transactions": {
|
"no fetched transactions": {
|
||||||
block: block1000,
|
block: block1000,
|
||||||
coins: map[string]*types.AccountCoin{},
|
coins: map[string]*storage.AccountCoin{},
|
||||||
expectedBlock: &types.Block{
|
expectedBlock: &types.Block{
|
||||||
BlockIdentifier: blockIdentifier1000,
|
BlockIdentifier: blockIdentifier1000,
|
||||||
ParentBlockIdentifier: &types.BlockIdentifier{
|
ParentBlockIdentifier: &types.BlockIdentifier{
|
||||||
|
@ -734,7 +735,7 @@ func TestParseBlock(t *testing.T) {
|
||||||
NetworkIndex: int64Pointer(0),
|
NetworkIndex: int64Pointer(0),
|
||||||
},
|
},
|
||||||
Type: CoinbaseOpType,
|
Type: CoinbaseOpType,
|
||||||
Status: types.String(SuccessStatus),
|
Status: SuccessStatus,
|
||||||
Metadata: mustMarshalMap(&OperationMetadata{
|
Metadata: mustMarshalMap(&OperationMetadata{
|
||||||
Coinbase: "04ffff001d02fd04",
|
Coinbase: "04ffff001d02fd04",
|
||||||
Sequence: 4294967295,
|
Sequence: 4294967295,
|
||||||
|
@ -746,7 +747,7 @@ func TestParseBlock(t *testing.T) {
|
||||||
NetworkIndex: int64Pointer(0),
|
NetworkIndex: int64Pointer(0),
|
||||||
},
|
},
|
||||||
Type: OutputOpType,
|
Type: OutputOpType,
|
||||||
Status: types.String(SuccessStatus),
|
Status: SuccessStatus,
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: "4104f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446aac", // nolint
|
Address: "4104f5eeb2b10c944c6b9fbcfff94c35bdeecd93df977882babc7f3a2cf7f5c81d3b09a68db7f0e04f21de5d4230e75e6dbe7ad16eefe0d4325a62067dc6f369446aac", // nolint
|
||||||
},
|
},
|
||||||
|
@ -787,7 +788,7 @@ func TestParseBlock(t *testing.T) {
|
||||||
NetworkIndex: int64Pointer(0),
|
NetworkIndex: int64Pointer(0),
|
||||||
},
|
},
|
||||||
Type: OutputOpType,
|
Type: OutputOpType,
|
||||||
Status: types.String(SuccessStatus),
|
Status: SuccessStatus,
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: "mmtKKnjqTPdkBnBMbNt5Yu2SCwpMaEshEL", // nolint
|
Address: "mmtKKnjqTPdkBnBMbNt5Yu2SCwpMaEshEL", // nolint
|
||||||
},
|
},
|
||||||
|
@ -819,7 +820,7 @@ func TestParseBlock(t *testing.T) {
|
||||||
NetworkIndex: int64Pointer(1),
|
NetworkIndex: int64Pointer(1),
|
||||||
},
|
},
|
||||||
Type: OutputOpType,
|
Type: OutputOpType,
|
||||||
Status: types.String(SuccessStatus),
|
Status: SuccessStatus,
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: "4852fe372ff7534c16713b3146bbc1e86379c70bea4d5c02fb1fa0112980a081:1",
|
Address: "4852fe372ff7534c16713b3146bbc1e86379c70bea4d5c02fb1fa0112980a081:1",
|
||||||
},
|
},
|
||||||
|
@ -864,7 +865,7 @@ func TestParseBlock(t *testing.T) {
|
||||||
},
|
},
|
||||||
"block 100000": {
|
"block 100000": {
|
||||||
block: block100000,
|
block: block100000,
|
||||||
coins: map[string]*types.AccountCoin{
|
coins: map[string]*storage.AccountCoin{
|
||||||
"87a157f3fd88ac7907c05fc55e271dc4acdc5605d187d646604ca8c0e9382e03:0": {
|
"87a157f3fd88ac7907c05fc55e271dc4acdc5605d187d646604ca8c0e9382e03:0": {
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: "1BNwxHGaFbeUBitpjy2AsKpJ29Ybxntqvb",
|
Address: "1BNwxHGaFbeUBitpjy2AsKpJ29Ybxntqvb",
|
||||||
|
@ -927,7 +928,7 @@ func TestParseBlock(t *testing.T) {
|
||||||
NetworkIndex: int64Pointer(0),
|
NetworkIndex: int64Pointer(0),
|
||||||
},
|
},
|
||||||
Type: CoinbaseOpType,
|
Type: CoinbaseOpType,
|
||||||
Status: types.String(SuccessStatus),
|
Status: SuccessStatus,
|
||||||
Metadata: mustMarshalMap(&OperationMetadata{
|
Metadata: mustMarshalMap(&OperationMetadata{
|
||||||
Coinbase: "044c86041b020602",
|
Coinbase: "044c86041b020602",
|
||||||
Sequence: 4294967295,
|
Sequence: 4294967295,
|
||||||
|
@ -939,7 +940,7 @@ func TestParseBlock(t *testing.T) {
|
||||||
NetworkIndex: int64Pointer(0),
|
NetworkIndex: int64Pointer(0),
|
||||||
},
|
},
|
||||||
Type: OutputOpType,
|
Type: OutputOpType,
|
||||||
Status: types.String(SuccessStatus),
|
Status: SuccessStatus,
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: "34qkc2iac6RsyxZVfyE2S5U5WcRsbg2dpK",
|
Address: "34qkc2iac6RsyxZVfyE2S5U5WcRsbg2dpK",
|
||||||
},
|
},
|
||||||
|
@ -971,7 +972,7 @@ func TestParseBlock(t *testing.T) {
|
||||||
NetworkIndex: int64Pointer(1),
|
NetworkIndex: int64Pointer(1),
|
||||||
},
|
},
|
||||||
Type: OutputOpType,
|
Type: OutputOpType,
|
||||||
Status: types.String(SuccessStatus),
|
Status: SuccessStatus,
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: "6a24aa21a9ed10109f4b82aa3ed7ec9d02a2a90246478b3308c8b85daf62fe501d58d05727a4",
|
Address: "6a24aa21a9ed10109f4b82aa3ed7ec9d02a2a90246478b3308c8b85daf62fe501d58d05727a4",
|
||||||
},
|
},
|
||||||
|
@ -1006,7 +1007,7 @@ func TestParseBlock(t *testing.T) {
|
||||||
NetworkIndex: int64Pointer(0),
|
NetworkIndex: int64Pointer(0),
|
||||||
},
|
},
|
||||||
Type: InputOpType,
|
Type: InputOpType,
|
||||||
Status: types.String(SuccessStatus),
|
Status: SuccessStatus,
|
||||||
Amount: &types.Amount{
|
Amount: &types.Amount{
|
||||||
Value: "-5000000000",
|
Value: "-5000000000",
|
||||||
Currency: MainnetCurrency,
|
Currency: MainnetCurrency,
|
||||||
|
@ -1034,7 +1035,7 @@ func TestParseBlock(t *testing.T) {
|
||||||
NetworkIndex: int64Pointer(0),
|
NetworkIndex: int64Pointer(0),
|
||||||
},
|
},
|
||||||
Type: OutputOpType,
|
Type: OutputOpType,
|
||||||
Status: types.String(SuccessStatus),
|
Status: SuccessStatus,
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: "1JqDybm2nWTENrHvMyafbSXXtTk5Uv5QAn",
|
Address: "1JqDybm2nWTENrHvMyafbSXXtTk5Uv5QAn",
|
||||||
},
|
},
|
||||||
|
@ -1066,7 +1067,7 @@ func TestParseBlock(t *testing.T) {
|
||||||
NetworkIndex: int64Pointer(1),
|
NetworkIndex: int64Pointer(1),
|
||||||
},
|
},
|
||||||
Type: OutputOpType,
|
Type: OutputOpType,
|
||||||
Status: types.String(SuccessStatus),
|
Status: SuccessStatus,
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: "1EYTGtG4LnFfiMvjJdsU7GMGCQvsRSjYhx",
|
Address: "1EYTGtG4LnFfiMvjJdsU7GMGCQvsRSjYhx",
|
||||||
},
|
},
|
||||||
|
@ -1111,7 +1112,7 @@ func TestParseBlock(t *testing.T) {
|
||||||
NetworkIndex: int64Pointer(0),
|
NetworkIndex: int64Pointer(0),
|
||||||
},
|
},
|
||||||
Type: InputOpType,
|
Type: InputOpType,
|
||||||
Status: types.String(SuccessStatus),
|
Status: SuccessStatus,
|
||||||
Amount: &types.Amount{
|
Amount: &types.Amount{
|
||||||
Value: "-3467607",
|
Value: "-3467607",
|
||||||
Currency: MainnetCurrency,
|
Currency: MainnetCurrency,
|
||||||
|
@ -1143,7 +1144,7 @@ func TestParseBlock(t *testing.T) {
|
||||||
NetworkIndex: int64Pointer(1),
|
NetworkIndex: int64Pointer(1),
|
||||||
},
|
},
|
||||||
Type: InputOpType,
|
Type: InputOpType,
|
||||||
Status: types.String(SuccessStatus),
|
Status: SuccessStatus,
|
||||||
Amount: &types.Amount{
|
Amount: &types.Amount{
|
||||||
Value: "0",
|
Value: "0",
|
||||||
Currency: MainnetCurrency,
|
Currency: MainnetCurrency,
|
||||||
|
@ -1171,7 +1172,7 @@ func TestParseBlock(t *testing.T) {
|
||||||
NetworkIndex: int64Pointer(2),
|
NetworkIndex: int64Pointer(2),
|
||||||
},
|
},
|
||||||
Type: InputOpType,
|
Type: InputOpType,
|
||||||
Status: types.String(SuccessStatus),
|
Status: SuccessStatus,
|
||||||
Amount: &types.Amount{
|
Amount: &types.Amount{
|
||||||
Value: "-556000000",
|
Value: "-556000000",
|
||||||
Currency: MainnetCurrency,
|
Currency: MainnetCurrency,
|
||||||
|
@ -1199,7 +1200,7 @@ func TestParseBlock(t *testing.T) {
|
||||||
NetworkIndex: int64Pointer(0),
|
NetworkIndex: int64Pointer(0),
|
||||||
},
|
},
|
||||||
Type: OutputOpType,
|
Type: OutputOpType,
|
||||||
Status: types.String(SuccessStatus),
|
Status: SuccessStatus,
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: "76a914c398efa9c392ba6013c5e04ee729755ef7f58b3288ac",
|
Address: "76a914c398efa9c392ba6013c5e04ee729755ef7f58b3288ac",
|
||||||
},
|
},
|
||||||
|
@ -1250,7 +1251,7 @@ func TestParseBlock(t *testing.T) {
|
||||||
},
|
},
|
||||||
"missing transactions": {
|
"missing transactions": {
|
||||||
block: block100000,
|
block: block100000,
|
||||||
coins: map[string]*types.AccountCoin{},
|
coins: map[string]*storage.AccountCoin{},
|
||||||
expectedError: errors.New("error finding previous tx"),
|
expectedError: errors.New("error finding previous tx"),
|
||||||
},
|
},
|
||||||
}
|
}
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package lbry
|
package bitcoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
@ -23,14 +23,14 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/lbryio/rosetta-lbry/utils"
|
"github.com/coinbase/rosetta-bitcoin/utils"
|
||||||
|
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
lbrycrddLogger = "lbrycrdd"
|
bitcoindLogger = "bitcoind"
|
||||||
lbrycrddStdErrLogger = "lbrycrdd stderr"
|
bitcoindStdErrLogger = "bitcoind stderr"
|
||||||
)
|
)
|
||||||
|
|
||||||
func logPipe(ctx context.Context, pipe io.ReadCloser, identifier string) error {
|
func logPipe(ctx context.Context, pipe io.ReadCloser, identifier string) error {
|
||||||
|
@ -43,7 +43,7 @@ func logPipe(ctx context.Context, pipe io.ReadCloser, identifier string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
message := strings.ReplaceAll(str, "\n", "")
|
message := strings.Replace(str, "\n", "", -1)
|
||||||
messages := strings.SplitAfterN(message, " ", 2)
|
messages := strings.SplitAfterN(message, " ", 2)
|
||||||
|
|
||||||
// Trim the timestamp from the log if it exists
|
// Trim the timestamp from the log if it exists
|
||||||
|
@ -51,8 +51,8 @@ func logPipe(ctx context.Context, pipe io.ReadCloser, identifier string) error {
|
||||||
message = messages[1]
|
message = messages[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print debug log if from lbrycrddLogger
|
// Print debug log if from bitcoindLogger
|
||||||
if identifier == lbrycrddLogger {
|
if identifier == bitcoindLogger {
|
||||||
logger.Debugw(message)
|
logger.Debugw(message)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -61,12 +61,12 @@ func logPipe(ctx context.Context, pipe io.ReadCloser, identifier string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Startlbrycrdd starts a lbrycrdd daemon in another goroutine
|
// StartBitcoind starts a bitcoind daemon in another goroutine
|
||||||
// and logs the results to the console.
|
// and logs the results to the console.
|
||||||
func Startlbrycrdd(ctx context.Context, configPath string, g *errgroup.Group) error {
|
func StartBitcoind(ctx context.Context, configPath string, g *errgroup.Group) error {
|
||||||
logger := utils.ExtractLogger(ctx, "lbrycrdd")
|
logger := utils.ExtractLogger(ctx, "bitcoind")
|
||||||
cmd := exec.Command(
|
cmd := exec.Command(
|
||||||
"/app/lbrycrdd",
|
"/app/bitcoind",
|
||||||
fmt.Sprintf("--conf=%s", configPath),
|
fmt.Sprintf("--conf=%s", configPath),
|
||||||
) // #nosec G204
|
) // #nosec G204
|
||||||
|
|
||||||
|
@ -81,21 +81,21 @@ func Startlbrycrdd(ctx context.Context, configPath string, g *errgroup.Group) er
|
||||||
}
|
}
|
||||||
|
|
||||||
g.Go(func() error {
|
g.Go(func() error {
|
||||||
return logPipe(ctx, stdout, lbrycrddLogger)
|
return logPipe(ctx, stdout, bitcoindLogger)
|
||||||
})
|
})
|
||||||
|
|
||||||
g.Go(func() error {
|
g.Go(func() error {
|
||||||
return logPipe(ctx, stderr, lbrycrddStdErrLogger)
|
return logPipe(ctx, stderr, bitcoindStdErrLogger)
|
||||||
})
|
})
|
||||||
|
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
return fmt.Errorf("%w: unable to start lbrycrdd", err)
|
return fmt.Errorf("%w: unable to start bitcoind", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
g.Go(func() error {
|
g.Go(func() error {
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
|
|
||||||
logger.Warnw("sending interrupt to lbrycrdd")
|
logger.Warnw("sending interrupt to bitcoind")
|
||||||
return cmd.Process.Signal(os.Interrupt)
|
return cmd.Process.Signal(os.Interrupt)
|
||||||
})
|
})
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package lbry
|
package bitcoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -23,8 +23,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Blockchain is lbry.
|
// Blockchain is Bitcoin.
|
||||||
Blockchain string = "lbry"
|
Blockchain string = "Bitcoin"
|
||||||
|
|
||||||
// MainnetNetwork is the value of the network
|
// MainnetNetwork is the value of the network
|
||||||
// in MainnetNetworkIdentifier.
|
// in MainnetNetworkIdentifier.
|
||||||
|
@ -38,9 +38,9 @@ const (
|
||||||
// used in Currency.
|
// used in Currency.
|
||||||
Decimals = 8
|
Decimals = 8
|
||||||
|
|
||||||
// SatoshisInlbry is the number of
|
// SatoshisInBitcoin is the number of
|
||||||
// Satoshis in 1 LBC (10^8).
|
// Satoshis in 1 BTC (10^8).
|
||||||
SatoshisInlbry = 100000000
|
SatoshisInBitcoin = 100000000
|
||||||
|
|
||||||
// InputOpType is used to describe
|
// InputOpType is used to describe
|
||||||
// INPUT.
|
// INPUT.
|
||||||
|
@ -55,7 +55,7 @@ const (
|
||||||
CoinbaseOpType = "COINBASE"
|
CoinbaseOpType = "COINBASE"
|
||||||
|
|
||||||
// SuccessStatus is the status of all
|
// SuccessStatus is the status of all
|
||||||
// lbry operations because anything
|
// Bitcoin operations because anything
|
||||||
// on-chain is considered successful.
|
// on-chain is considered successful.
|
||||||
SuccessStatus = "SUCCESS"
|
SuccessStatus = "SUCCESS"
|
||||||
|
|
||||||
|
@ -66,17 +66,17 @@ const (
|
||||||
SkippedStatus = "SKIPPED"
|
SkippedStatus = "SKIPPED"
|
||||||
|
|
||||||
// TransactionHashLength is the length
|
// TransactionHashLength is the length
|
||||||
// of any transaction hash in lbry.
|
// of any transaction hash in Bitcoin.
|
||||||
TransactionHashLength = 64
|
TransactionHashLength = 64
|
||||||
|
|
||||||
// NullData is returned by lbrycrdd
|
// NullData is returned by bitcoind
|
||||||
// as the ScriptPubKey.Type for OP_RETURN
|
// as the ScriptPubKey.Type for OP_RETURN
|
||||||
// locking scripts.
|
// locking scripts.
|
||||||
NullData = "nulldata"
|
NullData = "nulldata"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Fee estimate constants
|
// Fee estimate constants
|
||||||
// Source: https://lbryops.org/en/tools/calc-size/
|
// Source: https://bitcoinops.org/en/tools/calc-size/
|
||||||
const (
|
const (
|
||||||
MinFeeRate = float64(0.00001) // nolint:gomnd
|
MinFeeRate = float64(0.00001) // nolint:gomnd
|
||||||
TransactionOverhead = 12 // 4 version, 2 segwit flag, 1 vin, 1 vout, 4 lock time
|
TransactionOverhead = 12 // 4 version, 2 segwit flag, 1 vin, 1 vout, 4 lock time
|
||||||
|
@ -88,21 +88,21 @@ const (
|
||||||
var (
|
var (
|
||||||
// MainnetGenesisBlockIdentifier is the genesis block for mainnet.
|
// MainnetGenesisBlockIdentifier is the genesis block for mainnet.
|
||||||
MainnetGenesisBlockIdentifier = &types.BlockIdentifier{
|
MainnetGenesisBlockIdentifier = &types.BlockIdentifier{
|
||||||
Hash: "9c89283ba0f3227f6c03b70216b9f665f0118d5e0fa729cedf4fb34d6a34f463",
|
Hash: "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
|
||||||
}
|
}
|
||||||
|
|
||||||
// MainnetParams are the params for mainnet.
|
// MainnetParams are the params for mainnet.
|
||||||
MainnetParams = &LbryMainnetParams
|
MainnetParams = &chaincfg.MainNetParams
|
||||||
|
|
||||||
// MainnetCurrency is the *types.Currency for mainnet.
|
// MainnetCurrency is the *types.Currency for mainnet.
|
||||||
MainnetCurrency = &types.Currency{
|
MainnetCurrency = &types.Currency{
|
||||||
Symbol: "LBC",
|
Symbol: "BTC",
|
||||||
Decimals: Decimals,
|
Decimals: Decimals,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestnetGenesisBlockIdentifier is the genesis block for testnet.
|
// TestnetGenesisBlockIdentifier is the genesis block for testnet.
|
||||||
TestnetGenesisBlockIdentifier = &types.BlockIdentifier{
|
TestnetGenesisBlockIdentifier = &types.BlockIdentifier{
|
||||||
Hash: "9c89283ba0f3227f6c03b70216b9f665f0118d5e0fa729cedf4fb34d6a34f463",
|
Hash: "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943",
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestnetParams are the params for testnet.
|
// TestnetParams are the params for testnet.
|
||||||
|
@ -110,7 +110,7 @@ var (
|
||||||
|
|
||||||
// TestnetCurrency is the *types.Currency for testnet.
|
// TestnetCurrency is the *types.Currency for testnet.
|
||||||
TestnetCurrency = &types.Currency{
|
TestnetCurrency = &types.Currency{
|
||||||
Symbol: "tLBC",
|
Symbol: "tBTC",
|
||||||
Decimals: Decimals,
|
Decimals: Decimals,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ScriptPubKey is a script placed on the output operations
|
// ScriptPubKey is a script placed on the output operations
|
||||||
// of a lbry transaction that must be satisfied to spend
|
// of a Bitcoin transaction that must be satisfied to spend
|
||||||
// the output.
|
// the output.
|
||||||
type ScriptPubKey struct {
|
type ScriptPubKey struct {
|
||||||
ASM string `json:"asm"`
|
ASM string `json:"asm"`
|
||||||
|
@ -146,14 +146,14 @@ type ScriptPubKey struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScriptSig is a script on the input operations of a
|
// ScriptSig is a script on the input operations of a
|
||||||
// lbry transaction that satisfies the ScriptPubKey
|
// Bitcoin transaction that satisfies the ScriptPubKey
|
||||||
// on an output being spent.
|
// on an output being spent.
|
||||||
type ScriptSig struct {
|
type ScriptSig struct {
|
||||||
ASM string `json:"asm"`
|
ASM string `json:"asm"`
|
||||||
Hex string `json:"hex"`
|
Hex string `json:"hex"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockchainInfo is information about the lbry network.
|
// BlockchainInfo is information about the Bitcoin network.
|
||||||
// This struct only contains the information necessary for
|
// This struct only contains the information necessary for
|
||||||
// this implementation.
|
// this implementation.
|
||||||
type BlockchainInfo struct {
|
type BlockchainInfo struct {
|
||||||
|
@ -176,7 +176,7 @@ type PeerInfo struct {
|
||||||
SyncedHeaders int64 `json:"synced_headers"`
|
SyncedHeaders int64 `json:"synced_headers"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block is a raw lbry block (with verbosity == 2).
|
// Block is a raw Bitcoin block (with verbosity == 2).
|
||||||
type Block struct {
|
type Block struct {
|
||||||
Hash string `json:"hash"`
|
Hash string `json:"hash"`
|
||||||
Height int64 `json:"height"`
|
Height int64 `json:"height"`
|
||||||
|
@ -223,7 +223,7 @@ type BlockMetadata struct {
|
||||||
Difficulty float64 `json:"difficulty,omitempty"`
|
Difficulty float64 `json:"difficulty,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transaction is a raw lbry transaction.
|
// Transaction is a raw Bitcoin transaction.
|
||||||
type Transaction struct {
|
type Transaction struct {
|
||||||
Hex string `json:"hex"`
|
Hex string `json:"hex"`
|
||||||
Hash string `json:"txid"`
|
Hash string `json:"txid"`
|
||||||
|
@ -260,7 +260,7 @@ type TransactionMetadata struct {
|
||||||
Weight int64 `json:"weight,omitempty"`
|
Weight int64 `json:"weight,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Input is a raw input in a lbry transaction.
|
// Input is a raw input in a Bitcoin transaction.
|
||||||
type Input struct {
|
type Input struct {
|
||||||
TxHash string `json:"txid"`
|
TxHash string `json:"txid"`
|
||||||
Vout int64 `json:"vout"`
|
Vout int64 `json:"vout"`
|
||||||
|
@ -284,7 +284,7 @@ func (i Input) Metadata() (map[string]interface{}, error) {
|
||||||
return types.MarshalMap(m)
|
return types.MarshalMap(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output is a raw output in a lbry transaction.
|
// Output is a raw output in a Bitcoin transaction.
|
||||||
type Output struct {
|
type Output struct {
|
||||||
Value float64 `json:"value"`
|
Value float64 `json:"value"`
|
||||||
Index int64 `json:"n"`
|
Index int64 `json:"n"`
|
||||||
|
@ -301,7 +301,7 @@ func (o Output) Metadata() (map[string]interface{}, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OperationMetadata is a collection of useful
|
// OperationMetadata is a collection of useful
|
||||||
// metadata from lbry inputs and outputs.
|
// metadata from Bitcoin inputs and outputs.
|
||||||
type OperationMetadata struct {
|
type OperationMetadata struct {
|
||||||
// Coinbase Metadata
|
// Coinbase Metadata
|
||||||
Coinbase string `json:"coinbase,omitempty"`
|
Coinbase string `json:"coinbase,omitempty"`
|
||||||
|
@ -499,7 +499,7 @@ func (r rawMempoolResponse) Err() error {
|
||||||
|
|
||||||
// CoinIdentifier converts a tx hash and vout into
|
// CoinIdentifier converts a tx hash and vout into
|
||||||
// the canonical CoinIdentifier.Identifier used in
|
// the canonical CoinIdentifier.Identifier used in
|
||||||
// rosetta-lbry.
|
// rosetta-bitcoin.
|
||||||
func CoinIdentifier(hash string, vout int64) string {
|
func CoinIdentifier(hash string, vout int64) string {
|
||||||
return fmt.Sprintf("%s:%d", hash, vout)
|
return fmt.Sprintf("%s:%d", hash, vout)
|
||||||
}
|
}
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package lbry
|
package bitcoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
|
@ -22,10 +22,10 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/lbryio/rosetta-lbry/lbry"
|
"github.com/coinbase/rosetta-bitcoin/bitcoin"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/chaincfg"
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
"github.com/coinbase/rosetta-sdk-go/storage/encoder"
|
"github.com/coinbase/rosetta-sdk-go/storage"
|
||||||
"github.com/coinbase/rosetta-sdk-go/types"
|
"github.com/coinbase/rosetta-sdk-go/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -42,34 +42,34 @@ const (
|
||||||
// to make outbound connections.
|
// to make outbound connections.
|
||||||
Offline Mode = "OFFLINE"
|
Offline Mode = "OFFLINE"
|
||||||
|
|
||||||
// Mainnet is the lbry Mainnet.
|
// Mainnet is the Bitcoin Mainnet.
|
||||||
Mainnet string = "MAINNET"
|
Mainnet string = "MAINNET"
|
||||||
|
|
||||||
// Testnet is lbry Testnet3.
|
// Testnet is Bitcoin Testnet3.
|
||||||
Testnet string = "TESTNET"
|
Testnet string = "TESTNET"
|
||||||
|
|
||||||
// mainnetConfigPath is the path of the lbry
|
// mainnetConfigPath is the path of the Bitcoin
|
||||||
// configuration file for mainnet.
|
// configuration file for mainnet.
|
||||||
mainnetConfigPath = "/app/lbry-mainnet.conf"
|
mainnetConfigPath = "/app/bitcoin-mainnet.conf"
|
||||||
|
|
||||||
// testnetConfigPath is the path of the lbry
|
// testnetConfigPath is the path of the Bitcoin
|
||||||
// configuration file for testnet.
|
// configuration file for testnet.
|
||||||
testnetConfigPath = "/app/lbry-testnet.conf"
|
testnetConfigPath = "/app/bitcoin-testnet.conf"
|
||||||
|
|
||||||
// Zstandard compression dictionaries
|
// Zstandard compression dictionaries
|
||||||
transactionNamespace = "transaction"
|
transactionNamespace = "transaction"
|
||||||
testnetTransactionDictionary = "/app/testnet-transaction.zstd"
|
testnetTransactionDictionary = "/app/testnet-transaction.zstd"
|
||||||
mainnetTransactionDictionary = "/app/mainnet-transaction.zstd"
|
mainnetTransactionDictionary = "/app/mainnet-transaction.zstd"
|
||||||
|
|
||||||
mainnetRPCPort = 9245
|
mainnetRPCPort = 8332
|
||||||
testnetRPCPort = 19245
|
testnetRPCPort = 18332
|
||||||
|
|
||||||
// min prune depth is 288:
|
// min prune depth is 288:
|
||||||
// https://github.com/lbry/lbry/blob/ad2952d17a2af419a04256b10b53c7377f826a27/src/validation.h#L84
|
// https://github.com/bitcoin/bitcoin/blob/ad2952d17a2af419a04256b10b53c7377f826a27/src/validation.h#L84
|
||||||
pruneDepth = int64(10000) //nolint
|
pruneDepth = int64(10000) //nolint
|
||||||
|
|
||||||
// min prune height (on mainnet):
|
// min prune height (on mainnet):
|
||||||
// https://github.com/lbry/lbry/blob/62d137ac3b701aae36c1aa3aa93a83fd6357fde6/src/chainparams.cpp#L102
|
// https://github.com/bitcoin/bitcoin/blob/62d137ac3b701aae36c1aa3aa93a83fd6357fde6/src/chainparams.cpp#L102
|
||||||
minPruneHeight = int64(100000) //nolint
|
minPruneHeight = int64(100000) //nolint
|
||||||
|
|
||||||
// attempt to prune once an hour
|
// attempt to prune once an hour
|
||||||
|
@ -79,8 +79,8 @@ const (
|
||||||
// persistent data.
|
// persistent data.
|
||||||
DataDirectory = "/data"
|
DataDirectory = "/data"
|
||||||
|
|
||||||
LBRYcrdPath = "LBRYcrd"
|
bitcoindPath = "bitcoind"
|
||||||
indexerPath = "indexer"
|
indexerPath = "indexer"
|
||||||
|
|
||||||
// allFilePermissions specifies anyone can do anything
|
// allFilePermissions specifies anyone can do anything
|
||||||
// to the file.
|
// to the file.
|
||||||
|
@ -120,8 +120,8 @@ type Configuration struct {
|
||||||
ConfigPath string
|
ConfigPath string
|
||||||
Pruning *PruningConfiguration
|
Pruning *PruningConfiguration
|
||||||
IndexerPath string
|
IndexerPath string
|
||||||
LBRYcrdPath string
|
BitcoindPath string
|
||||||
Compressors []*encoder.CompressorEntry
|
Compressors []*storage.CompressorEntry
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadConfiguration attempts to create a new Configuration
|
// LoadConfiguration attempts to create a new Configuration
|
||||||
|
@ -143,9 +143,9 @@ func LoadConfiguration(baseDirectory string) (*Configuration, error) {
|
||||||
return nil, fmt.Errorf("%w: unable to create indexer path", err)
|
return nil, fmt.Errorf("%w: unable to create indexer path", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
config.LBRYcrdPath = path.Join(baseDirectory, LBRYcrdPath)
|
config.BitcoindPath = path.Join(baseDirectory, bitcoindPath)
|
||||||
if err := ensurePathExists(config.LBRYcrdPath); err != nil {
|
if err := ensurePathExists(config.BitcoindPath); err != nil {
|
||||||
return nil, fmt.Errorf("%w: unable to create LBRYcrd path", err)
|
return nil, fmt.Errorf("%w: unable to create bitcoind path", err)
|
||||||
}
|
}
|
||||||
case Offline:
|
case Offline:
|
||||||
config.Mode = Offline
|
config.Mode = Offline
|
||||||
|
@ -159,15 +159,15 @@ func LoadConfiguration(baseDirectory string) (*Configuration, error) {
|
||||||
switch networkValue {
|
switch networkValue {
|
||||||
case Mainnet:
|
case Mainnet:
|
||||||
config.Network = &types.NetworkIdentifier{
|
config.Network = &types.NetworkIdentifier{
|
||||||
Blockchain: lbry.Blockchain,
|
Blockchain: bitcoin.Blockchain,
|
||||||
Network: lbry.MainnetNetwork,
|
Network: bitcoin.MainnetNetwork,
|
||||||
}
|
}
|
||||||
config.GenesisBlockIdentifier = lbry.MainnetGenesisBlockIdentifier
|
config.GenesisBlockIdentifier = bitcoin.MainnetGenesisBlockIdentifier
|
||||||
config.Params = lbry.MainnetParams
|
config.Params = bitcoin.MainnetParams
|
||||||
config.Currency = lbry.MainnetCurrency
|
config.Currency = bitcoin.MainnetCurrency
|
||||||
config.ConfigPath = mainnetConfigPath
|
config.ConfigPath = mainnetConfigPath
|
||||||
config.RPCPort = mainnetRPCPort
|
config.RPCPort = mainnetRPCPort
|
||||||
config.Compressors = []*encoder.CompressorEntry{
|
config.Compressors = []*storage.CompressorEntry{
|
||||||
{
|
{
|
||||||
Namespace: transactionNamespace,
|
Namespace: transactionNamespace,
|
||||||
DictionaryPath: mainnetTransactionDictionary,
|
DictionaryPath: mainnetTransactionDictionary,
|
||||||
|
@ -175,15 +175,15 @@ func LoadConfiguration(baseDirectory string) (*Configuration, error) {
|
||||||
}
|
}
|
||||||
case Testnet:
|
case Testnet:
|
||||||
config.Network = &types.NetworkIdentifier{
|
config.Network = &types.NetworkIdentifier{
|
||||||
Blockchain: lbry.Blockchain,
|
Blockchain: bitcoin.Blockchain,
|
||||||
Network: lbry.TestnetNetwork,
|
Network: bitcoin.TestnetNetwork,
|
||||||
}
|
}
|
||||||
config.GenesisBlockIdentifier = lbry.TestnetGenesisBlockIdentifier
|
config.GenesisBlockIdentifier = bitcoin.TestnetGenesisBlockIdentifier
|
||||||
config.Params = lbry.TestnetParams
|
config.Params = bitcoin.TestnetParams
|
||||||
config.Currency = lbry.TestnetCurrency
|
config.Currency = bitcoin.TestnetCurrency
|
||||||
config.ConfigPath = testnetConfigPath
|
config.ConfigPath = testnetConfigPath
|
||||||
config.RPCPort = testnetRPCPort
|
config.RPCPort = testnetRPCPort
|
||||||
config.Compressors = []*encoder.CompressorEntry{
|
config.Compressors = []*storage.CompressorEntry{
|
||||||
{
|
{
|
||||||
Namespace: transactionNamespace,
|
Namespace: transactionNamespace,
|
||||||
DictionaryPath: testnetTransactionDictionary,
|
DictionaryPath: testnetTransactionDictionary,
|
||||||
|
|
|
@ -20,9 +20,9 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/lbryio/rosetta-lbry/lbry"
|
"github.com/coinbase/rosetta-bitcoin/bitcoin"
|
||||||
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/storage/encoder"
|
"github.com/coinbase/rosetta-sdk-go/storage"
|
||||||
"github.com/coinbase/rosetta-sdk-go/types"
|
"github.com/coinbase/rosetta-sdk-go/types"
|
||||||
"github.com/coinbase/rosetta-sdk-go/utils"
|
"github.com/coinbase/rosetta-sdk-go/utils"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -56,12 +56,12 @@ func TestLoadConfiguration(t *testing.T) {
|
||||||
cfg: &Configuration{
|
cfg: &Configuration{
|
||||||
Mode: Online,
|
Mode: Online,
|
||||||
Network: &types.NetworkIdentifier{
|
Network: &types.NetworkIdentifier{
|
||||||
Network: lbry.MainnetNetwork,
|
Network: bitcoin.MainnetNetwork,
|
||||||
Blockchain: lbry.Blockchain,
|
Blockchain: bitcoin.Blockchain,
|
||||||
},
|
},
|
||||||
Params: lbry.MainnetParams,
|
Params: bitcoin.MainnetParams,
|
||||||
Currency: lbry.MainnetCurrency,
|
Currency: bitcoin.MainnetCurrency,
|
||||||
GenesisBlockIdentifier: lbry.MainnetGenesisBlockIdentifier,
|
GenesisBlockIdentifier: bitcoin.MainnetGenesisBlockIdentifier,
|
||||||
Port: 1000,
|
Port: 1000,
|
||||||
RPCPort: mainnetRPCPort,
|
RPCPort: mainnetRPCPort,
|
||||||
ConfigPath: mainnetConfigPath,
|
ConfigPath: mainnetConfigPath,
|
||||||
|
@ -70,7 +70,7 @@ func TestLoadConfiguration(t *testing.T) {
|
||||||
Depth: pruneDepth,
|
Depth: pruneDepth,
|
||||||
MinHeight: minPruneHeight,
|
MinHeight: minPruneHeight,
|
||||||
},
|
},
|
||||||
Compressors: []*encoder.CompressorEntry{
|
Compressors: []*storage.CompressorEntry{
|
||||||
{
|
{
|
||||||
Namespace: transactionNamespace,
|
Namespace: transactionNamespace,
|
||||||
DictionaryPath: mainnetTransactionDictionary,
|
DictionaryPath: mainnetTransactionDictionary,
|
||||||
|
@ -85,12 +85,12 @@ func TestLoadConfiguration(t *testing.T) {
|
||||||
cfg: &Configuration{
|
cfg: &Configuration{
|
||||||
Mode: Online,
|
Mode: Online,
|
||||||
Network: &types.NetworkIdentifier{
|
Network: &types.NetworkIdentifier{
|
||||||
Network: lbry.TestnetNetwork,
|
Network: bitcoin.TestnetNetwork,
|
||||||
Blockchain: lbry.Blockchain,
|
Blockchain: bitcoin.Blockchain,
|
||||||
},
|
},
|
||||||
Params: lbry.TestnetParams,
|
Params: bitcoin.TestnetParams,
|
||||||
Currency: lbry.TestnetCurrency,
|
Currency: bitcoin.TestnetCurrency,
|
||||||
GenesisBlockIdentifier: lbry.TestnetGenesisBlockIdentifier,
|
GenesisBlockIdentifier: bitcoin.TestnetGenesisBlockIdentifier,
|
||||||
Port: 1000,
|
Port: 1000,
|
||||||
RPCPort: testnetRPCPort,
|
RPCPort: testnetRPCPort,
|
||||||
ConfigPath: testnetConfigPath,
|
ConfigPath: testnetConfigPath,
|
||||||
|
@ -99,7 +99,7 @@ func TestLoadConfiguration(t *testing.T) {
|
||||||
Depth: pruneDepth,
|
Depth: pruneDepth,
|
||||||
MinHeight: minPruneHeight,
|
MinHeight: minPruneHeight,
|
||||||
},
|
},
|
||||||
Compressors: []*encoder.CompressorEntry{
|
Compressors: []*storage.CompressorEntry{
|
||||||
{
|
{
|
||||||
Namespace: transactionNamespace,
|
Namespace: transactionNamespace,
|
||||||
DictionaryPath: testnetTransactionDictionary,
|
DictionaryPath: testnetTransactionDictionary,
|
||||||
|
@ -143,7 +143,7 @@ func TestLoadConfiguration(t *testing.T) {
|
||||||
assert.Contains(t, err.Error(), test.err.Error())
|
assert.Contains(t, err.Error(), test.err.Error())
|
||||||
} else {
|
} else {
|
||||||
test.cfg.IndexerPath = path.Join(newDir, "indexer")
|
test.cfg.IndexerPath = path.Join(newDir, "indexer")
|
||||||
test.cfg.lbrycrddPath = path.Join(newDir, "lbrycrdd")
|
test.cfg.BitcoindPath = path.Join(newDir, "bitcoind")
|
||||||
assert.Equal(t, test.cfg, cfg)
|
assert.Equal(t, test.cfg, cfg)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
24
go.mod
24
go.mod
|
@ -1,32 +1,16 @@
|
||||||
module github.com/lbryio/rosetta-lbry
|
module github.com/coinbase/rosetta-bitcoin
|
||||||
|
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a // indirect
|
|
||||||
4d63.com/gochecknoinits v0.0.0-20200108094044-eb73b47b9fc4 // indirect
|
|
||||||
dmitri.shuralyov.com/go/generated v0.0.0-20170818220700-b1254a446363 // indirect
|
|
||||||
github.com/alecthomas/gocyclo v0.0.0-20150208221726-aa8f8b160214 // indirect
|
|
||||||
github.com/alexkohler/nakedret v1.0.0 // indirect
|
|
||||||
github.com/btcsuite/btcd v0.21.0-beta
|
github.com/btcsuite/btcd v0.21.0-beta
|
||||||
github.com/btcsuite/btcutil v1.0.2
|
github.com/btcsuite/btcutil v1.0.2
|
||||||
github.com/coinbase/rosetta-sdk-go v0.6.3
|
github.com/coinbase/rosetta-sdk-go v0.5.8-0.20201027222031-dd9e29377d5f
|
||||||
github.com/dgraph-io/badger/v2 v2.2007.2
|
github.com/dgraph-io/badger/v2 v2.2007.2
|
||||||
github.com/golang/lint v0.0.0-20200302205851-738671d3881b // indirect
|
|
||||||
github.com/gordonklaus/ineffassign v0.0.0-20201107091007-3b93a8888063 // indirect
|
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2
|
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2
|
||||||
github.com/jgautheron/goconst v0.0.0-20201117150253-ccae5bf973f3 // indirect
|
|
||||||
github.com/mdempsky/maligned v0.0.0-20201101000000-d73c43cb16d0 // indirect
|
|
||||||
github.com/mdempsky/unconvert v0.0.0-20200228143138-95ecdbfc0b5f // indirect
|
|
||||||
github.com/mibk/dupl v1.0.0 // indirect
|
|
||||||
github.com/opennota/check v0.0.0-20180911053232-0c771f5545ff // indirect
|
|
||||||
github.com/stretchr/testify v1.6.1
|
github.com/stretchr/testify v1.6.1
|
||||||
github.com/stripe/safesql v0.2.0 // indirect
|
|
||||||
github.com/tsenart/deadcode v0.0.0-20160724212837-210d2dc333e9 // indirect
|
|
||||||
github.com/walle/lll v1.0.1 // indirect
|
|
||||||
go.uber.org/zap v1.16.0
|
go.uber.org/zap v1.16.0
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
|
||||||
|
golang.org/x/tools v0.0.0-20200904185747-39188db58858 // indirect
|
||||||
honnef.co/go/tools v0.0.1-2020.1.5 // indirect
|
honnef.co/go/tools v0.0.1-2020.1.5 // indirect
|
||||||
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect
|
|
||||||
mvdan.cc/unparam v0.0.0-20200501210554-b37ab49443f7 // indirect
|
|
||||||
)
|
)
|
||||||
|
|
95
go.sum
95
go.sum
|
@ -1,10 +1,4 @@
|
||||||
4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a h1:wFEQiK85fRsEVF0CRrPAos5LoAryUsIX1kPW/WrIqFw=
|
|
||||||
4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a/go.mod h1:Sk40JNJmh0koZukOjJfaBNLZazbZthFfHnLHIcZNS6A=
|
|
||||||
4d63.com/gochecknoinits v0.0.0-20200108094044-eb73b47b9fc4 h1:bf5qocEKjrY58JO2GwywfLsb1199lIVs7qHkiplwHy0=
|
|
||||||
4d63.com/gochecknoinits v0.0.0-20200108094044-eb73b47b9fc4/go.mod h1:4o1i5aXtIF5tJFt3UD1knCVmWOXg7fLYdHVu6jeNcnM=
|
|
||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
dmitri.shuralyov.com/go/generated v0.0.0-20170818220700-b1254a446363 h1:o4lAkfETerCnr1kF9/qwkwjICnU+YLHNDCM8h2xj7as=
|
|
||||||
dmitri.shuralyov.com/go/generated v0.0.0-20170818220700-b1254a446363/go.mod h1:WG7q7swWsS2f9PYpt5DoEP/EBYWx8We5UoRltn9vJl8=
|
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4=
|
github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4=
|
||||||
github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc=
|
github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc=
|
||||||
|
@ -19,7 +13,6 @@ github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxB
|
||||||
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
|
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
|
||||||
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
|
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
|
||||||
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
|
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
|
||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM=
|
github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM=
|
||||||
|
@ -30,30 +23,21 @@ github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||||
github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8=
|
github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8=
|
||||||
github.com/Zilliqa/gozilliqa-sdk v1.2.1-0.20201201074141-dd0ecada1be6 h1:1d9pzdbkth4D9AX6ndKSl7of3UTV0RYl3z64U2dXMGo=
|
|
||||||
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/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
||||||
github.com/alecthomas/gocyclo v0.0.0-20150208221726-aa8f8b160214 h1:YI/8G3uLbYyowJeOPVL6BMKe2wbL54h0FdEKmncU6lU=
|
|
||||||
github.com/alecthomas/gocyclo v0.0.0-20150208221726-aa8f8b160214/go.mod h1:Ef5UOtJdJ5rVFObdOVsrNgKV/Wf4I+daTCSk8GTrHIk=
|
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/alexflint/go-arg v0.0.0-20160306200701-e71d6514f40a/go.mod h1:PHxo6ZWOLVMZZgWSAqBynb/KhIqoGO6WKwOVX7rM9dg=
|
|
||||||
github.com/alexkohler/nakedret v1.0.0 h1:S/bzOFhZHYUJp6qPmdXdFHS5nlWGFmLmoc8QOydvotE=
|
|
||||||
github.com/alexkohler/nakedret v1.0.0/go.mod h1:tfDQbtPt67HhBK/6P0yNktIX7peCxfOp0jO9007DrLE=
|
|
||||||
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
||||||
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
|
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
|
||||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ=
|
github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ=
|
||||||
github.com/btcsuite/btcd v0.0.0-20190315201642-aa6e0f35703c/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
|
|
||||||
github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw=
|
github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw=
|
||||||
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
|
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 h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M=
|
||||||
github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94=
|
github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94=
|
||||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo=
|
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo=
|
||||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
|
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
|
||||||
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 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 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts=
|
||||||
github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts=
|
github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts=
|
||||||
|
@ -77,8 +61,8 @@ github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJ
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U=
|
github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U=
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/coinbase/rosetta-sdk-go v0.6.3 h1:PPj14tPJ7SFc8sY/hlwK8zddT7PKwWU2wicxyerDxlg=
|
github.com/coinbase/rosetta-sdk-go v0.5.8-0.20201027222031-dd9e29377d5f h1:aWkN9dKMkMMpZKX5QycpePxH176Fj2fNNC7jESfLZw0=
|
||||||
github.com/coinbase/rosetta-sdk-go v0.6.3/go.mod h1:MvQfsL2KlJ5786OdDviRIJE3agui2YcvS1CaQPDl1Yo=
|
github.com/coinbase/rosetta-sdk-go v0.5.8-0.20201027222031-dd9e29377d5f/go.mod h1:l5aNeyeZKBkmWbVdkdLpWdToQ6hTwI7cZ1OU9cMbljY=
|
||||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
|
@ -112,11 +96,11 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
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/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/ethereum/go-ethereum v1.9.24 h1:6AK+ORt3EMDO+FTjzXy/AQwHMbu52J2nYHIjyQX9azQ=
|
github.com/ethereum/go-ethereum v1.9.23 h1:SIKhg/z4Q7AbvqcxuPYvMxf36che/Rq/Pp0IdYEkbtw=
|
||||||
github.com/ethereum/go-ethereum v1.9.24/go.mod h1:JIfVb6esrqALTExdz9hRYvrP0xBDf6wCncIu1hNwHpM=
|
github.com/ethereum/go-ethereum v1.9.23/go.mod h1:JIfVb6esrqALTExdz9hRYvrP0xBDf6wCncIu1hNwHpM=
|
||||||
github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
|
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
|
||||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||||
github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
|
github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
|
@ -130,11 +114,8 @@ github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dT
|
||||||
github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
|
github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
|
||||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/lint v0.0.0-20200302205851-738671d3881b h1:BOvdkG2qv61G8DSvnEEgkjT/+tkEyHPPUfz0uGXXELY=
|
|
||||||
github.com/golang/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
@ -162,11 +143,9 @@ github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
|
||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
|
||||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
|
||||||
github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
|
github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 h1:FlFbCRLd5Jr4iYXZufAvgWN6Ao0JrI5chLINnUXDDr0=
|
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 h1:FlFbCRLd5Jr4iYXZufAvgWN6Ao0JrI5chLINnUXDDr0=
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI=
|
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI=
|
||||||
|
@ -182,16 +161,12 @@ github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH
|
||||||
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89 h1:12K8AlpT0/6QUXSfV0yi4Q0jkbq8NDtIKFtF61AoqV0=
|
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89 h1:12K8AlpT0/6QUXSfV0yi4Q0jkbq8NDtIKFtF61AoqV0=
|
||||||
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
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/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
github.com/jgautheron/goconst v0.0.0-20201117150253-ccae5bf973f3 h1:7nkB9fLPMwtn/R6qfPcHileL/x9ydlhw8XyDrLI1ZXg=
|
|
||||||
github.com/jgautheron/goconst v0.0.0-20201117150253-ccae5bf973f3/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4=
|
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI=
|
github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI=
|
||||||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||||
github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
|
github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
|
||||||
github.com/kisielk/errcheck v1.1.0 h1:ZqfnKyx9KGpRcW04j5nnPDgRgoXUeLh2YFBeFzphcA0=
|
|
||||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
|
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE=
|
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE=
|
||||||
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
|
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
|
||||||
|
@ -201,37 +176,33 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
||||||
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
||||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||||
github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77 h1:6xiz3+ZczT3M4+I+JLpcPGG1bQKm8067HktB17EDWEE=
|
github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77 h1:6xiz3+ZczT3M4+I+JLpcPGG1bQKm8067HktB17EDWEE=
|
||||||
github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4=
|
github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4=
|
||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/mattn/go-colorable v0.1.0/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.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
||||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
|
github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw=
|
||||||
|
github.com/mattn/go-colorable v0.1.7/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-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-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
|
||||||
github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/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 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
|
||||||
|
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 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/mdempsky/maligned v0.0.0-20201101000000-d73c43cb16d0 h1:+6XJvFZBYbNv/nSekNWFZyaGNMXcPnZ4n/HHoCXn+Ms=
|
|
||||||
github.com/mdempsky/maligned v0.0.0-20201101000000-d73c43cb16d0/go.mod h1:3UB4iTzhLciyWcrrvXSkrtCIU+IJ5GCfEmnleHRsxL4=
|
|
||||||
github.com/mdempsky/unconvert v0.0.0-20200228143138-95ecdbfc0b5f h1:Kc3s6QFyh9DLgInXpWKuG+8I7R7lXbnP7mcoOVIt6KY=
|
|
||||||
github.com/mdempsky/unconvert v0.0.0-20200228143138-95ecdbfc0b5f/go.mod h1:AmCV4WB3cDMZqgPk+OUQKumliiQS4ZYsBt3AXekyuAU=
|
|
||||||
github.com/mibk/dupl v1.0.0 h1:aZc3jqrF9n0tUHwHt/+jsRxA8cRgA0Gdl56M7W7PoqE=
|
|
||||||
github.com/mibk/dupl v1.0.0/go.mod h1:pCr4pNxxIbFGvtyCOi0c7LVjmV6duhKWV+ex5vh38ME=
|
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8=
|
github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8=
|
||||||
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
|
github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
|
||||||
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
|
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
|
||||||
github.com/neilotoole/errgroup v0.1.5 h1:DxEGoIfFm5ooGicidR+okiHjoOaGRKFaSxDPVZuuu2I=
|
|
||||||
github.com/neilotoole/errgroup v0.1.5/go.mod h1:Q2nLGf+594h0CLBs/Mbg6qOr7GtqDK7C2S41udRnToE=
|
|
||||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||||
|
@ -245,8 +216,6 @@ github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5
|
||||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
github.com/opennota/check v0.0.0-20180911053232-0c771f5545ff h1:lRHufowVGvUvxGsPveAZOpSa/9T5Gpxg6d7UbHCA9MQ=
|
|
||||||
github.com/opennota/check v0.0.0-20180911053232-0c771f5545ff/go.mod h1:tydB+MZxWpY8M/NRu7jQhND/mXuLAPsKcSV6JkzofsA=
|
|
||||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||||
github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34=
|
github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34=
|
||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
|
@ -265,19 +234,15 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R
|
||||||
github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=
|
github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
|
||||||
github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||||
github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ=
|
github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ=
|
||||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM=
|
|
||||||
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/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/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
|
||||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
|
@ -294,37 +259,26 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
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.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
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 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stripe/safesql v0.2.0 h1:xiefmCDd8c35PVSGrL2FhBiaKxviXnGziBDOpOejeBE=
|
|
||||||
github.com/stripe/safesql v0.2.0/go.mod h1:q7b2n0JmzM1mVGfcYpanfVb2j23cXZeWFxcILPn3JV4=
|
|
||||||
github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM=
|
github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM=
|
||||||
github.com/tidwall/gjson v1.6.1 h1:LRbvNuNuvAiISWg6gxLEFuCe72UKy5hDqhxW/8183ws=
|
github.com/tidwall/gjson v1.6.1 h1:LRbvNuNuvAiISWg6gxLEFuCe72UKy5hDqhxW/8183ws=
|
||||||
github.com/tidwall/gjson v1.6.1/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0=
|
github.com/tidwall/gjson v1.6.1/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0=
|
||||||
github.com/tidwall/gjson v1.6.3 h1:aHoiiem0dr7GHkW001T1SMTJ7X5PvyekH5WX0whWGnI=
|
|
||||||
github.com/tidwall/gjson v1.6.3/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0=
|
|
||||||
github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc=
|
github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc=
|
||||||
github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
|
github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
|
||||||
github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU=
|
github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU=
|
||||||
github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||||
github.com/tidwall/sjson v1.1.2 h1:NC5okI+tQ8OG/oyzchvwXXxRxCV/FVdhODbPKkQ25jQ=
|
github.com/tidwall/sjson v1.1.2 h1:NC5okI+tQ8OG/oyzchvwXXxRxCV/FVdhODbPKkQ25jQ=
|
||||||
github.com/tidwall/sjson v1.1.2/go.mod h1:SEzaDwxiPzKzNfUEO4HbYF/m4UCSJDsGgNqsS1LvdoY=
|
github.com/tidwall/sjson v1.1.2/go.mod h1:SEzaDwxiPzKzNfUEO4HbYF/m4UCSJDsGgNqsS1LvdoY=
|
||||||
github.com/tsenart/deadcode v0.0.0-20160724212837-210d2dc333e9 h1:vY5WqiEon0ZSTGM3ayVVi+twaHKHDFUVloaQ/wug9/c=
|
|
||||||
github.com/tsenart/deadcode v0.0.0-20160724212837-210d2dc333e9/go.mod h1:q+QjxYvZ+fpjMXqs+XEriussHjSYqeXVnAdSV1tkMYk=
|
|
||||||
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
|
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/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/vmihailenco/msgpack/v5 v5.1.0 h1:+od5YbEXxW95SPlW6beocmt8nOtlh83zqat5Ip9Hwdc=
|
github.com/vmihailenco/msgpack/v5 v5.0.0-beta.8 h1:R2L6zPq1pWFumpeIxAJoeiov5GxyEZUq9NyS8eus/6s=
|
||||||
github.com/vmihailenco/msgpack/v5 v5.1.0/go.mod h1:C5gboKD0TJPqWDTVTtrQNfRbiBwHZGo8UTqP/9/XvLI=
|
github.com/vmihailenco/msgpack/v5 v5.0.0-beta.8/go.mod h1:HVxBVPUK/+fZMonk4bi1islLa8V3cfnBug0+4dykPzo=
|
||||||
github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc=
|
github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc=
|
||||||
github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
|
github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
|
||||||
github.com/walle/lll v1.0.1 h1:lbK8008fOXbQNYt8daBGUrjvElvlwlE7D7N/9dLP5IQ=
|
|
||||||
github.com/walle/lll v1.0.1/go.mod h1:lYxcXzoPhiAHR9eaq+Yv7RYg1nIipLloBCIfPUzfaWQ=
|
|
||||||
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees=
|
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees=
|
||||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
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.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
|
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
|
||||||
|
@ -332,7 +286,6 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
|
go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
|
||||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
|
|
||||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM=
|
go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM=
|
||||||
|
@ -340,7 +293,6 @@ go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
|
||||||
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/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-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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
@ -359,7 +311,6 @@ golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTk
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3 h1:XQyxROzUlZH+WIQwySDgnISgOivlhjIEwaQaJEJrrN0=
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3 h1:XQyxROzUlZH+WIQwySDgnISgOivlhjIEwaQaJEJrrN0=
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
|
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||||
|
@ -370,7 +321,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
|
||||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b h1:GgiSbuUyC0BlbUmHQBgFqu32eiRR/CEYdjOjOd4zE6Y=
|
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b h1:GgiSbuUyC0BlbUmHQBgFqu32eiRR/CEYdjOjOd4zE6Y=
|
||||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|
||||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
@ -382,7 +332,6 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc h1:zK/HqS5bZxDptfPJNq8v7vJfXtkU7r9TLIoSr1bXaP4=
|
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc h1:zK/HqS5bZxDptfPJNq8v7vJfXtkU7r9TLIoSr1bXaP4=
|
||||||
|
@ -391,20 +340,18 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA=
|
golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA=
|
||||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
|
||||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/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-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-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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
@ -412,6 +359,7 @@ golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
@ -422,7 +370,6 @@ golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/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 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM=
|
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM=
|
||||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
@ -444,12 +391,8 @@ golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtn
|
||||||
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa h1:5E4dL8+NgFOgjwbTKz+OOEGGhP+ectTmF842l6KjupQ=
|
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa h1:5E4dL8+NgFOgjwbTKz+OOEGGhP+ectTmF842l6KjupQ=
|
||||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200225230052-807dcd883420/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
|
||||||
golang.org/x/tools v0.0.0-20200904185747-39188db58858 h1:xLt+iB5ksWcZVxqc+g9K41ZHy+6MKWfXCDsjSThnsPA=
|
golang.org/x/tools v0.0.0-20200904185747-39188db58858 h1:xLt+iB5ksWcZVxqc+g9K41ZHy+6MKWfXCDsjSThnsPA=
|
||||||
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||||
golang.org/x/tools v0.0.0-20201030204249-4fc0492b8eca h1:KWfVIHfTHZf4IQhrLjrbG+kLyoSym7yYp0WgqtOVH9s=
|
|
||||||
golang.org/x/tools v0.0.0-20201030204249-4fc0492b8eca/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
|
@ -505,7 +448,3 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
honnef.co/go/tools v0.0.1-2020.1.5 h1:nI5egYTGJakVyOryqLs1cQO5dO0ksin5XXs2pspk75k=
|
honnef.co/go/tools v0.0.1-2020.1.5 h1:nI5egYTGJakVyOryqLs1cQO5dO0ksin5XXs2pspk75k=
|
||||||
honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I=
|
|
||||||
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
|
|
||||||
mvdan.cc/unparam v0.0.0-20200501210554-b37ab49443f7 h1:kAREL6MPwpsk1/PQPFD3Eg7WAQR5mPTWZJaBiG5LDbY=
|
|
||||||
mvdan.cc/unparam v0.0.0-20200501210554-b37ab49443f7/go.mod h1:HGC5lll35J70Y5v7vCGb9oLhHoScFwkHDJm/05RdSTc=
|
|
||||||
|
|
|
@ -18,12 +18,11 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/parser"
|
"github.com/coinbase/rosetta-sdk-go/parser"
|
||||||
"github.com/coinbase/rosetta-sdk-go/storage/database"
|
"github.com/coinbase/rosetta-sdk-go/storage"
|
||||||
"github.com/coinbase/rosetta-sdk-go/storage/modules"
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/types"
|
"github.com/coinbase/rosetta-sdk-go/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ modules.BalanceStorageHandler = (*BalanceStorageHandler)(nil)
|
var _ storage.BalanceStorageHandler = (*BalanceStorageHandler)(nil)
|
||||||
|
|
||||||
// BalanceStorageHandler implements storage.BalanceStorageHandler.
|
// BalanceStorageHandler implements storage.BalanceStorageHandler.
|
||||||
type BalanceStorageHandler struct{}
|
type BalanceStorageHandler struct{}
|
||||||
|
@ -45,21 +44,3 @@ func (h *BalanceStorageHandler) BlockRemoved(
|
||||||
) error {
|
) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AccountsReconciled updates the total accounts reconciled by count.
|
|
||||||
func (h *BalanceStorageHandler) AccountsReconciled(
|
|
||||||
ctx context.Context,
|
|
||||||
dbTx database.Transaction,
|
|
||||||
count int,
|
|
||||||
) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AccountsSeen updates the total accounts seen by count.
|
|
||||||
func (h *BalanceStorageHandler) AccountsSeen(
|
|
||||||
ctx context.Context,
|
|
||||||
dbTx database.Transaction,
|
|
||||||
count int,
|
|
||||||
) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -16,21 +16,14 @@ package indexer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"math/big"
|
|
||||||
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/asserter"
|
"github.com/coinbase/rosetta-sdk-go/asserter"
|
||||||
"github.com/coinbase/rosetta-sdk-go/parser"
|
"github.com/coinbase/rosetta-sdk-go/parser"
|
||||||
"github.com/coinbase/rosetta-sdk-go/storage/database"
|
"github.com/coinbase/rosetta-sdk-go/storage"
|
||||||
"github.com/coinbase/rosetta-sdk-go/storage/modules"
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/types"
|
"github.com/coinbase/rosetta-sdk-go/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ modules.BalanceStorageHelper = (*BalanceStorageHelper)(nil)
|
var _ storage.BalanceStorageHelper = (*BalanceStorageHelper)(nil)
|
||||||
|
|
||||||
var (
|
|
||||||
errNotImplemented = errors.New("not implemented")
|
|
||||||
)
|
|
||||||
|
|
||||||
// BalanceStorageHelper implements storage.BalanceStorageHelper.
|
// BalanceStorageHelper implements storage.BalanceStorageHelper.
|
||||||
type BalanceStorageHelper struct {
|
type BalanceStorageHelper struct {
|
||||||
|
@ -67,19 +60,3 @@ func (h *BalanceStorageHelper) ExemptFunc() parser.ExemptOperation {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AccountsReconciled returns the total accounts reconciled by count.
|
|
||||||
func (h *BalanceStorageHelper) AccountsReconciled(
|
|
||||||
ctx context.Context,
|
|
||||||
dbTx database.Transaction,
|
|
||||||
) (*big.Int, error) {
|
|
||||||
return nil, errNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
// AccountsSeen returns the total accounts seen by count.
|
|
||||||
func (h *BalanceStorageHelper) AccountsSeen(
|
|
||||||
ctx context.Context,
|
|
||||||
dbTx database.Transaction,
|
|
||||||
) (*big.Int, error) {
|
|
||||||
return nil, errNotImplemented
|
|
||||||
}
|
|
||||||
|
|
|
@ -17,23 +17,22 @@ package indexer
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/storage/database"
|
"github.com/coinbase/rosetta-sdk-go/storage"
|
||||||
"github.com/coinbase/rosetta-sdk-go/storage/modules"
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/types"
|
"github.com/coinbase/rosetta-sdk-go/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ modules.CoinStorageHelper = (*CoinStorageHelper)(nil)
|
var _ storage.CoinStorageHelper = (*CoinStorageHelper)(nil)
|
||||||
|
|
||||||
// CoinStorageHelper implements storage.CoinStorageHelper.
|
// CoinStorageHelper implements storage.CoinStorageHelper.
|
||||||
type CoinStorageHelper struct {
|
type CoinStorageHelper struct {
|
||||||
b *modules.BlockStorage
|
b *storage.BlockStorage
|
||||||
}
|
}
|
||||||
|
|
||||||
// CurrentBlockIdentifier returns the current head block identifier
|
// CurrentBlockIdentifier returns the current head block identifier
|
||||||
// and is used to comply with the CoinStorageHelper interface.
|
// and is used to comply with the CoinStorageHelper interface.
|
||||||
func (h *CoinStorageHelper) CurrentBlockIdentifier(
|
func (h *CoinStorageHelper) CurrentBlockIdentifier(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
transaction database.Transaction,
|
transaction storage.DatabaseTransaction,
|
||||||
) (*types.BlockIdentifier, error) {
|
) (*types.BlockIdentifier, error) {
|
||||||
return h.b.GetHeadBlockIdentifierTransactional(ctx, transaction)
|
return h.b.GetHeadBlockIdentifierTransactional(ctx, transaction)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,17 +18,16 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/lbryio/rosetta-lbry/configuration"
|
"github.com/coinbase/rosetta-bitcoin/bitcoin"
|
||||||
"github.com/lbryio/rosetta-lbry/lbry"
|
"github.com/coinbase/rosetta-bitcoin/configuration"
|
||||||
"github.com/lbryio/rosetta-lbry/services"
|
"github.com/coinbase/rosetta-bitcoin/services"
|
||||||
"github.com/lbryio/rosetta-lbry/utils"
|
"github.com/coinbase/rosetta-bitcoin/utils"
|
||||||
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/asserter"
|
"github.com/coinbase/rosetta-sdk-go/asserter"
|
||||||
"github.com/coinbase/rosetta-sdk-go/storage/database"
|
"github.com/coinbase/rosetta-sdk-go/storage"
|
||||||
storageErrs "github.com/coinbase/rosetta-sdk-go/storage/errors"
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/storage/modules"
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/syncer"
|
"github.com/coinbase/rosetta-sdk-go/syncer"
|
||||||
"github.com/coinbase/rosetta-sdk-go/types"
|
"github.com/coinbase/rosetta-sdk-go/types"
|
||||||
sdkUtils "github.com/coinbase/rosetta-sdk-go/utils"
|
sdkUtils "github.com/coinbase/rosetta-sdk-go/utils"
|
||||||
|
@ -54,7 +53,7 @@ const (
|
||||||
// estimate for pre-fetching blocks. In other words,
|
// estimate for pre-fetching blocks. In other words,
|
||||||
// this is the estimated memory overhead for each
|
// this is the estimated memory overhead for each
|
||||||
// block fetched by the indexer.
|
// block fetched by the indexer.
|
||||||
sizeMultiplier = 5
|
sizeMultiplier = 15
|
||||||
|
|
||||||
// zeroValue is 0 as a string
|
// zeroValue is 0 as a string
|
||||||
zeroValue = "0"
|
zeroValue = "0"
|
||||||
|
@ -68,11 +67,11 @@ var (
|
||||||
type Client interface {
|
type Client interface {
|
||||||
NetworkStatus(context.Context) (*types.NetworkStatusResponse, error)
|
NetworkStatus(context.Context) (*types.NetworkStatusResponse, error)
|
||||||
PruneBlockchain(context.Context, int64) (int64, error)
|
PruneBlockchain(context.Context, int64) (int64, error)
|
||||||
GetRawBlock(context.Context, *types.PartialBlockIdentifier) (*lbry.Block, []string, error)
|
GetRawBlock(context.Context, *types.PartialBlockIdentifier) (*bitcoin.Block, []string, error)
|
||||||
ParseBlock(
|
ParseBlock(
|
||||||
context.Context,
|
context.Context,
|
||||||
*lbry.Block,
|
*bitcoin.Block,
|
||||||
map[string]*types.AccountCoin,
|
map[string]*storage.AccountCoin,
|
||||||
) (*types.Block, error)
|
) (*types.Block, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,13 +89,15 @@ type Indexer struct {
|
||||||
client Client
|
client Client
|
||||||
|
|
||||||
asserter *asserter.Asserter
|
asserter *asserter.Asserter
|
||||||
database database.Database
|
database storage.Database
|
||||||
blockStorage *modules.BlockStorage
|
blockStorage *storage.BlockStorage
|
||||||
balanceStorage *modules.BalanceStorage
|
balanceStorage *storage.BalanceStorage
|
||||||
coinStorage *modules.CoinStorage
|
coinStorage *storage.CoinStorage
|
||||||
workers []modules.BlockWorker
|
workers []storage.BlockWorker
|
||||||
|
|
||||||
waiter *waitTable
|
waiter *waitTable
|
||||||
|
coinMapMutex sync.RWMutex
|
||||||
|
coinMap map[string]*storage.AccountCoin
|
||||||
}
|
}
|
||||||
|
|
||||||
// CloseDatabase closes a storage.Database. This should be called
|
// CloseDatabase closes a storage.Database. This should be called
|
||||||
|
@ -127,11 +128,11 @@ func defaultBadgerOptions(
|
||||||
opts.ValueLogLoadingMode = options.MemoryMap
|
opts.ValueLogLoadingMode = options.MemoryMap
|
||||||
|
|
||||||
// Use an extended table size for larger commits.
|
// Use an extended table size for larger commits.
|
||||||
opts.MaxTableSize = database.DefaultMaxTableSize
|
opts.MaxTableSize = storage.DefaultMaxTableSize
|
||||||
|
|
||||||
// Smaller value log sizes means smaller contiguous memory allocations
|
// Smaller value log sizes means smaller contiguous memory allocations
|
||||||
// and less RAM usage on cleanup.
|
// and less RAM usage on cleanup.
|
||||||
opts.ValueLogFileSize = database.DefaultLogValueSize
|
opts.ValueLogFileSize = storage.DefaultLogValueSize
|
||||||
|
|
||||||
// To allow writes at a faster speed, we create a new memtable as soon as
|
// To allow writes at a faster speed, we create a new memtable as soon as
|
||||||
// an existing memtable is filled up. This option determines how many
|
// an existing memtable is filled up. This option determines how many
|
||||||
|
@ -166,11 +167,11 @@ func Initialize(
|
||||||
config *configuration.Configuration,
|
config *configuration.Configuration,
|
||||||
client Client,
|
client Client,
|
||||||
) (*Indexer, error) {
|
) (*Indexer, error) {
|
||||||
localStore, err := database.NewBadgerDatabase(
|
localStore, err := storage.NewBadgerStorage(
|
||||||
ctx,
|
ctx,
|
||||||
config.IndexerPath,
|
config.IndexerPath,
|
||||||
database.WithCompressorEntries(config.Compressors),
|
storage.WithCompressorEntries(config.Compressors),
|
||||||
database.WithCustomSettings(defaultBadgerOptions(
|
storage.WithCustomSettings(defaultBadgerOptions(
|
||||||
config.IndexerPath,
|
config.IndexerPath,
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
|
@ -178,12 +179,12 @@ func Initialize(
|
||||||
return nil, fmt.Errorf("%w: unable to initialize storage", err)
|
return nil, fmt.Errorf("%w: unable to initialize storage", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
blockStorage := modules.NewBlockStorage(localStore)
|
blockStorage := storage.NewBlockStorage(localStore)
|
||||||
asserter, err := asserter.NewClientWithOptions(
|
asserter, err := asserter.NewClientWithOptions(
|
||||||
config.Network,
|
config.Network,
|
||||||
config.GenesisBlockIdentifier,
|
config.GenesisBlockIdentifier,
|
||||||
lbry.OperationTypes,
|
bitcoin.OperationTypes,
|
||||||
lbry.OperationStatuses,
|
bitcoin.OperationStatuses,
|
||||||
services.Errors,
|
services.Errors,
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
|
@ -200,28 +201,31 @@ func Initialize(
|
||||||
blockStorage: blockStorage,
|
blockStorage: blockStorage,
|
||||||
waiter: newWaitTable(),
|
waiter: newWaitTable(),
|
||||||
asserter: asserter,
|
asserter: asserter,
|
||||||
|
// TODO: only enable during fast catchup (i.e. far behind chain)
|
||||||
|
// Delete oldest entries whenever some size: https://stackoverflow.com/questions/60829460/is-there-a-way-to-delete-first-element-from-map
|
||||||
|
coinMap: map[string]*storage.AccountCoin{},
|
||||||
}
|
}
|
||||||
|
|
||||||
coinStorage := modules.NewCoinStorage(
|
coinStorage := storage.NewCoinStorage(
|
||||||
localStore,
|
localStore,
|
||||||
&CoinStorageHelper{blockStorage},
|
&CoinStorageHelper{blockStorage},
|
||||||
asserter,
|
asserter,
|
||||||
)
|
)
|
||||||
i.coinStorage = coinStorage
|
i.coinStorage = coinStorage
|
||||||
|
|
||||||
balanceStorage := modules.NewBalanceStorage(localStore)
|
balanceStorage := storage.NewBalanceStorage(localStore)
|
||||||
balanceStorage.Initialize(
|
balanceStorage.Initialize(
|
||||||
&BalanceStorageHelper{asserter},
|
&BalanceStorageHelper{asserter},
|
||||||
&BalanceStorageHandler{},
|
&BalanceStorageHandler{},
|
||||||
)
|
)
|
||||||
i.balanceStorage = balanceStorage
|
i.balanceStorage = balanceStorage
|
||||||
|
|
||||||
i.workers = []modules.BlockWorker{coinStorage, balanceStorage}
|
i.workers = []storage.BlockWorker{coinStorage, balanceStorage}
|
||||||
|
|
||||||
return i, nil
|
return i, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// waitForNode returns once lbrycrdd is ready to serve
|
// waitForNode returns once bitcoind is ready to serve
|
||||||
// block queries.
|
// block queries.
|
||||||
func (i *Indexer) waitForNode(ctx context.Context) error {
|
func (i *Indexer) waitForNode(ctx context.Context) error {
|
||||||
logger := utils.ExtractLogger(ctx, "indexer")
|
logger := utils.ExtractLogger(ctx, "indexer")
|
||||||
|
@ -231,15 +235,15 @@ func (i *Indexer) waitForNode(ctx context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Infow("waiting for lbrycrdd...")
|
logger.Infow("waiting for bitcoind...")
|
||||||
if err := sdkUtils.ContextSleep(ctx, nodeWaitSleep); err != nil {
|
if err := sdkUtils.ContextSleep(ctx, nodeWaitSleep); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync attempts to index lbry blocks using
|
// Sync attempts to index Bitcoin blocks using
|
||||||
// the lbry.Client until stopped.
|
// the bitcoin.Client until stopped.
|
||||||
func (i *Indexer) Sync(ctx context.Context) error {
|
func (i *Indexer) Sync(ctx context.Context) error {
|
||||||
if err := i.waitForNode(ctx); err != nil {
|
if err := i.waitForNode(ctx); err != nil {
|
||||||
return fmt.Errorf("%w: failed to wait for node", err)
|
return fmt.Errorf("%w: failed to wait for node", err)
|
||||||
|
@ -257,7 +261,7 @@ func (i *Indexer) Sync(ctx context.Context) error {
|
||||||
// If previously processed blocks exist in storage, they are fetched.
|
// If previously processed blocks exist in storage, they are fetched.
|
||||||
// Otherwise, none are provided to the cache (the syncer will not attempt
|
// Otherwise, none are provided to the cache (the syncer will not attempt
|
||||||
// a reorg if the cache is empty).
|
// a reorg if the cache is empty).
|
||||||
pastBlocks := i.blockStorage.CreateBlockCache(ctx, syncer.DefaultPastBlockLimit)
|
pastBlocks := i.blockStorage.CreateBlockCache(ctx)
|
||||||
|
|
||||||
syncer := syncer.New(
|
syncer := syncer.New(
|
||||||
i.network,
|
i.network,
|
||||||
|
@ -272,7 +276,7 @@ func (i *Indexer) Sync(ctx context.Context) error {
|
||||||
return syncer.Sync(ctx, startIndex, indexPlaceholder)
|
return syncer.Sync(ctx, startIndex, indexPlaceholder)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prune attempts to prune blocks in lbrycrdd every
|
// Prune attempts to prune blocks in bitcoind every
|
||||||
// pruneFrequency.
|
// pruneFrequency.
|
||||||
func (i *Indexer) Prune(ctx context.Context) error {
|
func (i *Indexer) Prune(ctx context.Context) error {
|
||||||
logger := utils.ExtractLogger(ctx, "pruner")
|
logger := utils.ExtractLogger(ctx, "pruner")
|
||||||
|
@ -291,25 +295,25 @@ func (i *Indexer) Prune(ctx context.Context) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must meet pruning conditions in lbry core
|
// Must meet pruning conditions in bitcoin core
|
||||||
// Source:
|
// Source:
|
||||||
// https://github.com/lbry/lbry/blob/a63a26f042134fa80356860c109edb25ac567552/src/rpc/blockchain.cpp#L953-L960
|
// https://github.com/bitcoin/bitcoin/blob/a63a26f042134fa80356860c109edb25ac567552/src/rpc/blockchain.cpp#L953-L960
|
||||||
pruneHeight := head.Index - i.pruningConfig.Depth
|
pruneHeight := head.Index - i.pruningConfig.Depth
|
||||||
if pruneHeight <= i.pruningConfig.MinHeight {
|
if pruneHeight <= i.pruningConfig.MinHeight {
|
||||||
logger.Infow("waiting to prune", "min prune height", i.pruningConfig.MinHeight)
|
logger.Infow("waiting to prune", "min prune height", i.pruningConfig.MinHeight)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Infow("attempting to prune lbrycrdd", "prune height", pruneHeight)
|
logger.Infow("attempting to prune bitcoind", "prune height", pruneHeight)
|
||||||
prunedHeight, err := i.client.PruneBlockchain(ctx, pruneHeight)
|
prunedHeight, err := i.client.PruneBlockchain(ctx, pruneHeight)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warnw(
|
logger.Warnw(
|
||||||
"unable to prune lbrycrdd",
|
"unable to prune bitcoind",
|
||||||
"prune height", pruneHeight,
|
"prune height", pruneHeight,
|
||||||
"error", err,
|
"error", err,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
logger.Infow("pruned lbrycrdd", "prune height", prunedHeight)
|
logger.Infow("pruned bitcoind", "prune height", prunedHeight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -319,6 +323,30 @@ func (i *Indexer) Prune(ctx context.Context) error {
|
||||||
func (i *Indexer) BlockAdded(ctx context.Context, block *types.Block) error {
|
func (i *Indexer) BlockAdded(ctx context.Context, block *types.Block) error {
|
||||||
logger := utils.ExtractLogger(ctx, "indexer")
|
logger := utils.ExtractLogger(ctx, "indexer")
|
||||||
|
|
||||||
|
// Update cache
|
||||||
|
i.coinMapMutex.Lock()
|
||||||
|
for _, transaction := range block.Transactions {
|
||||||
|
for _, op := range transaction.Operations {
|
||||||
|
if op.CoinChange == nil || op.Amount == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if op.CoinChange.CoinAction == types.CoinSpent {
|
||||||
|
delete(i.coinMap, op.CoinChange.CoinIdentifier.Identifier)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
i.coinMap[op.CoinChange.CoinIdentifier.Identifier] = &storage.AccountCoin{
|
||||||
|
Account: op.Account,
|
||||||
|
Coin: &types.Coin{
|
||||||
|
CoinIdentifier: op.CoinChange.CoinIdentifier,
|
||||||
|
Amount: op.Amount,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i.coinMapMutex.Unlock()
|
||||||
|
|
||||||
err := i.blockStorage.AddBlock(ctx, block)
|
err := i.blockStorage.AddBlock(ctx, block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
|
@ -418,20 +446,36 @@ func (i *Indexer) NetworkStatus(
|
||||||
return i.client.NetworkStatus(ctx)
|
return i.client.NetworkStatus(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *Indexer) getCoin(
|
||||||
|
ctx context.Context,
|
||||||
|
dbTx storage.DatabaseTransaction,
|
||||||
|
coinIdentifier *types.CoinIdentifier,
|
||||||
|
) (*types.Coin, *types.AccountIdentifier, error) {
|
||||||
|
i.coinMapMutex.RLock()
|
||||||
|
m, ok := i.coinMap[coinIdentifier.Identifier]
|
||||||
|
i.coinMapMutex.RUnlock()
|
||||||
|
if ok {
|
||||||
|
return m.Coin, m.Account, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// THis is SUPER dangerous (won't survive restart)
|
||||||
|
return nil, nil, storage.ErrCoinNotFound
|
||||||
|
}
|
||||||
|
|
||||||
func (i *Indexer) findCoin(
|
func (i *Indexer) findCoin(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
btcBlock *lbry.Block,
|
btcBlock *bitcoin.Block,
|
||||||
coinIdentifier string,
|
coinIdentifier string,
|
||||||
) (*types.Coin, *types.AccountIdentifier, error) {
|
) (*types.Coin, *types.AccountIdentifier, error) {
|
||||||
for ctx.Err() == nil {
|
for ctx.Err() == nil {
|
||||||
databaseTransaction := i.database.ReadTransaction(ctx)
|
databaseTransaction := i.database.NewDatabaseTransaction(ctx, false)
|
||||||
defer databaseTransaction.Discard(ctx)
|
defer databaseTransaction.Discard(ctx)
|
||||||
|
|
||||||
coinHeadBlock, err := i.blockStorage.GetHeadBlockIdentifierTransactional(
|
coinHeadBlock, err := i.blockStorage.GetHeadBlockIdentifierTransactional(
|
||||||
ctx,
|
ctx,
|
||||||
databaseTransaction,
|
databaseTransaction,
|
||||||
)
|
)
|
||||||
if errors.Is(err, storageErrs.ErrHeadBlockNotFound) {
|
if errors.Is(err, storage.ErrHeadBlockNotFound) {
|
||||||
if err := sdkUtils.ContextSleep(ctx, missingTransactionDelay); err != nil {
|
if err := sdkUtils.ContextSleep(ctx, missingTransactionDelay); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -446,7 +490,7 @@ func (i *Indexer) findCoin(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to find coin
|
// Attempt to find coin
|
||||||
coin, owner, err := i.coinStorage.GetCoinTransactional(
|
coin, owner, err := i.getCoin(
|
||||||
ctx,
|
ctx,
|
||||||
databaseTransaction,
|
databaseTransaction,
|
||||||
&types.CoinIdentifier{
|
&types.CoinIdentifier{
|
||||||
|
@ -457,7 +501,7 @@ func (i *Indexer) findCoin(
|
||||||
return coin, owner, nil
|
return coin, owner, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !errors.Is(err, storageErrs.ErrCoinNotFound) {
|
if !errors.Is(err, storage.ErrCoinNotFound) {
|
||||||
return nil, nil, fmt.Errorf("%w: unable to lookup coin %s", err, coinIdentifier)
|
return nil, nil, fmt.Errorf("%w: unable to lookup coin %s", err, coinIdentifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,7 +526,7 @@ func (i *Indexer) findCoin(
|
||||||
|
|
||||||
// Put Transaction in WaitTable if doesn't already exist (could be
|
// Put Transaction in WaitTable if doesn't already exist (could be
|
||||||
// multiple listeners)
|
// multiple listeners)
|
||||||
transactionHash := lbry.TransactionHash(coinIdentifier)
|
transactionHash := bitcoin.TransactionHash(coinIdentifier)
|
||||||
val, ok := i.waiter.Get(transactionHash, false)
|
val, ok := i.waiter.Get(transactionHash, false)
|
||||||
if !ok {
|
if !ok {
|
||||||
val = &waitTableEntry{
|
val = &waitTableEntry{
|
||||||
|
@ -505,10 +549,10 @@ func (i *Indexer) findCoin(
|
||||||
|
|
||||||
func (i *Indexer) checkHeaderMatch(
|
func (i *Indexer) checkHeaderMatch(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
btcBlock *lbry.Block,
|
btcBlock *bitcoin.Block,
|
||||||
) error {
|
) error {
|
||||||
headBlock, err := i.blockStorage.GetHeadBlockIdentifier(ctx)
|
headBlock, err := i.blockStorage.GetHeadBlockIdentifier(ctx)
|
||||||
if err != nil && !errors.Is(err, storageErrs.ErrHeadBlockNotFound) {
|
if err != nil && !errors.Is(err, storage.ErrHeadBlockNotFound) {
|
||||||
return fmt.Errorf("%w: unable to lookup head block", err)
|
return fmt.Errorf("%w: unable to lookup head block", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,14 +569,14 @@ func (i *Indexer) checkHeaderMatch(
|
||||||
|
|
||||||
func (i *Indexer) findCoins(
|
func (i *Indexer) findCoins(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
btcBlock *lbry.Block,
|
btcBlock *bitcoin.Block,
|
||||||
coins []string,
|
coins []string,
|
||||||
) (map[string]*types.AccountCoin, error) {
|
) (map[string]*storage.AccountCoin, error) {
|
||||||
if err := i.checkHeaderMatch(ctx, btcBlock); err != nil {
|
if err := i.checkHeaderMatch(ctx, btcBlock); err != nil {
|
||||||
return nil, fmt.Errorf("%w: check header match failed", err)
|
return nil, fmt.Errorf("%w: check header match failed", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
coinMap := map[string]*types.AccountCoin{}
|
coinMap := map[string]*storage.AccountCoin{}
|
||||||
remainingCoins := []string{}
|
remainingCoins := []string{}
|
||||||
for _, coinIdentifier := range coins {
|
for _, coinIdentifier := range coins {
|
||||||
coin, owner, err := i.findCoin(
|
coin, owner, err := i.findCoin(
|
||||||
|
@ -541,7 +585,7 @@ func (i *Indexer) findCoins(
|
||||||
coinIdentifier,
|
coinIdentifier,
|
||||||
)
|
)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
coinMap[coinIdentifier] = &types.AccountCoin{
|
coinMap[coinIdentifier] = &storage.AccountCoin{
|
||||||
Account: owner,
|
Account: owner,
|
||||||
Coin: coin,
|
Coin: coin,
|
||||||
}
|
}
|
||||||
|
@ -564,7 +608,7 @@ func (i *Indexer) findCoins(
|
||||||
shouldAbort := false
|
shouldAbort := false
|
||||||
for _, coinIdentifier := range remainingCoins {
|
for _, coinIdentifier := range remainingCoins {
|
||||||
// Wait on Channel
|
// Wait on Channel
|
||||||
txHash := lbry.TransactionHash(coinIdentifier)
|
txHash := bitcoin.TransactionHash(coinIdentifier)
|
||||||
entry, ok := i.waiter.Get(txHash, true)
|
entry, ok := i.waiter.Get(txHash, true)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("transaction %s not in waiter", txHash)
|
return nil, fmt.Errorf("transaction %s not in waiter", txHash)
|
||||||
|
@ -626,7 +670,7 @@ func (i *Indexer) Block(
|
||||||
blockIdentifier *types.PartialBlockIdentifier,
|
blockIdentifier *types.PartialBlockIdentifier,
|
||||||
) (*types.Block, error) {
|
) (*types.Block, error) {
|
||||||
// get raw block
|
// get raw block
|
||||||
var btcBlock *lbry.Block
|
var btcBlock *bitcoin.Block
|
||||||
var coins []string
|
var coins []string
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
@ -674,14 +718,14 @@ func (i *Indexer) Block(
|
||||||
func (i *Indexer) GetScriptPubKeys(
|
func (i *Indexer) GetScriptPubKeys(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
coins []*types.Coin,
|
coins []*types.Coin,
|
||||||
) ([]*lbry.ScriptPubKey, error) {
|
) ([]*bitcoin.ScriptPubKey, error) {
|
||||||
databaseTransaction := i.database.ReadTransaction(ctx)
|
databaseTransaction := i.database.NewDatabaseTransaction(ctx, false)
|
||||||
defer databaseTransaction.Discard(ctx)
|
defer databaseTransaction.Discard(ctx)
|
||||||
|
|
||||||
scripts := make([]*lbry.ScriptPubKey, len(coins))
|
scripts := make([]*bitcoin.ScriptPubKey, len(coins))
|
||||||
for j, coin := range coins {
|
for j, coin := range coins {
|
||||||
coinIdentifier := coin.CoinIdentifier
|
coinIdentifier := coin.CoinIdentifier
|
||||||
transactionHash, networkIndex, err := lbry.ParseCoinIdentifier(coinIdentifier)
|
transactionHash, networkIndex, err := bitcoin.ParseCoinIdentifier(coinIdentifier)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%w: unable to parse coin identifier", err)
|
return nil, fmt.Errorf("%w: unable to parse coin identifier", err)
|
||||||
}
|
}
|
||||||
|
@ -700,7 +744,7 @@ func (i *Indexer) GetScriptPubKeys(
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, op := range transaction.Operations {
|
for _, op := range transaction.Operations {
|
||||||
if op.Type != lbry.OutputOpType {
|
if op.Type != bitcoin.OutputOpType {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,7 +752,7 @@ func (i *Indexer) GetScriptPubKeys(
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var opMetadata lbry.OperationMetadata
|
var opMetadata bitcoin.OperationMetadata
|
||||||
if err := types.UnmarshalMap(op.Metadata, &opMetadata); err != nil {
|
if err := types.UnmarshalMap(op.Metadata, &opMetadata); err != nil {
|
||||||
return nil, fmt.Errorf(
|
return nil, fmt.Errorf(
|
||||||
"%w: unable to unmarshal operation metadata %+v",
|
"%w: unable to unmarshal operation metadata %+v",
|
||||||
|
@ -788,7 +832,7 @@ func (i *Indexer) GetBalance(
|
||||||
currency *types.Currency,
|
currency *types.Currency,
|
||||||
blockIdentifier *types.PartialBlockIdentifier,
|
blockIdentifier *types.PartialBlockIdentifier,
|
||||||
) (*types.Amount, *types.BlockIdentifier, error) {
|
) (*types.Amount, *types.BlockIdentifier, error) {
|
||||||
dbTx := i.database.ReadTransaction(ctx)
|
dbTx := i.database.NewDatabaseTransaction(ctx, false)
|
||||||
defer dbTx.Discard(ctx)
|
defer dbTx.Discard(ctx)
|
||||||
|
|
||||||
blockResponse, err := i.blockStorage.GetBlockLazyTransactional(
|
blockResponse, err := i.blockStorage.GetBlockLazyTransactional(
|
||||||
|
@ -807,7 +851,7 @@ func (i *Indexer) GetBalance(
|
||||||
currency,
|
currency,
|
||||||
blockResponse.Block.BlockIdentifier.Index,
|
blockResponse.Block.BlockIdentifier.Index,
|
||||||
)
|
)
|
||||||
if errors.Is(err, storageErrs.ErrAccountMissing) {
|
if errors.Is(err, storage.ErrAccountMissing) {
|
||||||
return &types.Amount{
|
return &types.Amount{
|
||||||
Value: zeroValue,
|
Value: zeroValue,
|
||||||
Currency: currency,
|
Currency: currency,
|
||||||
|
|
|
@ -23,10 +23,11 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/lbryio/rosetta-lbry/configuration"
|
"github.com/coinbase/rosetta-bitcoin/bitcoin"
|
||||||
"github.com/lbryio/rosetta-lbry/lbry"
|
"github.com/coinbase/rosetta-bitcoin/configuration"
|
||||||
mocks "github.com/lbryio/rosetta-lbry/mocks/indexer"
|
mocks "github.com/coinbase/rosetta-bitcoin/mocks/indexer"
|
||||||
|
|
||||||
|
"github.com/coinbase/rosetta-sdk-go/storage"
|
||||||
"github.com/coinbase/rosetta-sdk-go/types"
|
"github.com/coinbase/rosetta-sdk-go/types"
|
||||||
"github.com/coinbase/rosetta-sdk-go/utils"
|
"github.com/coinbase/rosetta-sdk-go/utils"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -59,10 +60,10 @@ func TestIndexer_Pruning(t *testing.T) {
|
||||||
minHeight := int64(200)
|
minHeight := int64(200)
|
||||||
cfg := &configuration.Configuration{
|
cfg := &configuration.Configuration{
|
||||||
Network: &types.NetworkIdentifier{
|
Network: &types.NetworkIdentifier{
|
||||||
Network: lbry.MainnetNetwork,
|
Network: bitcoin.MainnetNetwork,
|
||||||
Blockchain: lbry.Blockchain,
|
Blockchain: bitcoin.Blockchain,
|
||||||
},
|
},
|
||||||
GenesisBlockIdentifier: lbry.MainnetGenesisBlockIdentifier,
|
GenesisBlockIdentifier: bitcoin.MainnetGenesisBlockIdentifier,
|
||||||
Pruning: &configuration.PruningConfiguration{
|
Pruning: &configuration.PruningConfiguration{
|
||||||
Frequency: 50 * time.Millisecond,
|
Frequency: 50 * time.Millisecond,
|
||||||
Depth: pruneDepth,
|
Depth: pruneDepth,
|
||||||
|
@ -74,7 +75,7 @@ func TestIndexer_Pruning(t *testing.T) {
|
||||||
i, err := Initialize(ctx, cancel, cfg, mockClient)
|
i, err := Initialize(ctx, cancel, cfg, mockClient)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// Waiting for lbrycrdd...
|
// Waiting for bitcoind...
|
||||||
mockClient.On("NetworkStatus", ctx).Return(nil, errors.New("not ready")).Once()
|
mockClient.On("NetworkStatus", ctx).Return(nil, errors.New("not ready")).Once()
|
||||||
mockClient.On("NetworkStatus", ctx).Return(&types.NetworkStatusResponse{}, nil).Once()
|
mockClient.On("NetworkStatus", ctx).Return(&types.NetworkStatusResponse{}, nil).Once()
|
||||||
|
|
||||||
|
@ -83,7 +84,7 @@ func TestIndexer_Pruning(t *testing.T) {
|
||||||
CurrentBlockIdentifier: &types.BlockIdentifier{
|
CurrentBlockIdentifier: &types.BlockIdentifier{
|
||||||
Index: 1000,
|
Index: 1000,
|
||||||
},
|
},
|
||||||
GenesisBlockIdentifier: lbry.MainnetGenesisBlockIdentifier,
|
GenesisBlockIdentifier: bitcoin.MainnetGenesisBlockIdentifier,
|
||||||
}, nil)
|
}, nil)
|
||||||
|
|
||||||
// Timeout on first request
|
// Timeout on first request
|
||||||
|
@ -131,7 +132,7 @@ func TestIndexer_Pruning(t *testing.T) {
|
||||||
parentIdentifier.Hash = getBlockHash(0)
|
parentIdentifier.Hash = getBlockHash(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
block := &lbry.Block{
|
block := &bitcoin.Block{
|
||||||
Hash: identifier.Hash,
|
Hash: identifier.Hash,
|
||||||
Height: identifier.Index,
|
Height: identifier.Index,
|
||||||
PreviousBlockHash: parentIdentifier.Hash,
|
PreviousBlockHash: parentIdentifier.Hash,
|
||||||
|
@ -156,7 +157,7 @@ func TestIndexer_Pruning(t *testing.T) {
|
||||||
"ParseBlock",
|
"ParseBlock",
|
||||||
mock.Anything,
|
mock.Anything,
|
||||||
block,
|
block,
|
||||||
map[string]*types.AccountCoin{},
|
map[string]*storage.AccountCoin{},
|
||||||
).Return(
|
).Return(
|
||||||
blockReturn,
|
blockReturn,
|
||||||
nil,
|
nil,
|
||||||
|
@ -166,7 +167,7 @@ func TestIndexer_Pruning(t *testing.T) {
|
||||||
"ParseBlock",
|
"ParseBlock",
|
||||||
mock.Anything,
|
mock.Anything,
|
||||||
block,
|
block,
|
||||||
map[string]*types.AccountCoin{},
|
map[string]*storage.AccountCoin{},
|
||||||
).Return(
|
).Return(
|
||||||
blockReturn,
|
blockReturn,
|
||||||
nil,
|
nil,
|
||||||
|
@ -224,10 +225,10 @@ func TestIndexer_Transactions(t *testing.T) {
|
||||||
mockClient := &mocks.Client{}
|
mockClient := &mocks.Client{}
|
||||||
cfg := &configuration.Configuration{
|
cfg := &configuration.Configuration{
|
||||||
Network: &types.NetworkIdentifier{
|
Network: &types.NetworkIdentifier{
|
||||||
Network: lbry.MainnetNetwork,
|
Network: bitcoin.MainnetNetwork,
|
||||||
Blockchain: lbry.Blockchain,
|
Blockchain: bitcoin.Blockchain,
|
||||||
},
|
},
|
||||||
GenesisBlockIdentifier: lbry.MainnetGenesisBlockIdentifier,
|
GenesisBlockIdentifier: bitcoin.MainnetGenesisBlockIdentifier,
|
||||||
IndexerPath: newDir,
|
IndexerPath: newDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,13 +240,13 @@ func TestIndexer_Transactions(t *testing.T) {
|
||||||
CurrentBlockIdentifier: &types.BlockIdentifier{
|
CurrentBlockIdentifier: &types.BlockIdentifier{
|
||||||
Index: 1000,
|
Index: 1000,
|
||||||
},
|
},
|
||||||
GenesisBlockIdentifier: lbry.MainnetGenesisBlockIdentifier,
|
GenesisBlockIdentifier: bitcoin.MainnetGenesisBlockIdentifier,
|
||||||
}, nil)
|
}, nil)
|
||||||
|
|
||||||
// Add blocks
|
// Add blocks
|
||||||
waitForCheck := make(chan struct{})
|
waitForCheck := make(chan struct{})
|
||||||
type coinBankEntry struct {
|
type coinBankEntry struct {
|
||||||
Script *lbry.ScriptPubKey
|
Script *bitcoin.ScriptPubKey
|
||||||
Coin *types.Coin
|
Coin *types.Coin
|
||||||
Account *types.AccountIdentifier
|
Account *types.AccountIdentifier
|
||||||
}
|
}
|
||||||
|
@ -270,7 +271,7 @@ func TestIndexer_Transactions(t *testing.T) {
|
||||||
rawHash := fmt.Sprintf("block %d transaction %d", i, j)
|
rawHash := fmt.Sprintf("block %d transaction %d", i, j)
|
||||||
hash := fmt.Sprintf("%x", sha256.Sum256([]byte(rawHash)))
|
hash := fmt.Sprintf("%x", sha256.Sum256([]byte(rawHash)))
|
||||||
coinIdentifier := fmt.Sprintf("%s:%d", hash, index0)
|
coinIdentifier := fmt.Sprintf("%s:%d", hash, index0)
|
||||||
scriptPubKey := &lbry.ScriptPubKey{
|
scriptPubKey := &bitcoin.ScriptPubKey{
|
||||||
ASM: coinIdentifier,
|
ASM: coinIdentifier,
|
||||||
}
|
}
|
||||||
marshal, err := types.MarshalMap(scriptPubKey)
|
marshal, err := types.MarshalMap(scriptPubKey)
|
||||||
|
@ -285,14 +286,14 @@ func TestIndexer_Transactions(t *testing.T) {
|
||||||
Index: 0,
|
Index: 0,
|
||||||
NetworkIndex: &index0,
|
NetworkIndex: &index0,
|
||||||
},
|
},
|
||||||
Status: types.String(bitcoin.SuccessStatus),
|
Status: bitcoin.SuccessStatus,
|
||||||
Type: bitcoin.OutputOpType,
|
Type: bitcoin.OutputOpType,
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: rawHash,
|
Address: rawHash,
|
||||||
},
|
},
|
||||||
Amount: &types.Amount{
|
Amount: &types.Amount{
|
||||||
Value: fmt.Sprintf("%d", rand.Intn(1000)),
|
Value: fmt.Sprintf("%d", rand.Intn(1000)),
|
||||||
Currency: lbry.TestnetCurrency,
|
Currency: bitcoin.TestnetCurrency,
|
||||||
},
|
},
|
||||||
CoinChange: &types.CoinChange{
|
CoinChange: &types.CoinChange{
|
||||||
CoinAction: types.CoinCreated,
|
CoinAction: types.CoinCreated,
|
||||||
|
@ -322,7 +323,7 @@ func TestIndexer_Transactions(t *testing.T) {
|
||||||
transactions = append(transactions, tx)
|
transactions = append(transactions, tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
block := &lbry.Block{
|
block := &bitcoin.Block{
|
||||||
Hash: identifier.Hash,
|
Hash: identifier.Hash,
|
||||||
Height: identifier.Index,
|
Height: identifier.Index,
|
||||||
PreviousBlockHash: parentIdentifier.Hash,
|
PreviousBlockHash: parentIdentifier.Hash,
|
||||||
|
@ -355,9 +356,9 @@ func TestIndexer_Transactions(t *testing.T) {
|
||||||
Transactions: transactions,
|
Transactions: transactions,
|
||||||
}
|
}
|
||||||
|
|
||||||
coinMap := map[string]*types.AccountCoin{}
|
coinMap := map[string]*storage.AccountCoin{}
|
||||||
for _, coinIdentifier := range requiredCoins {
|
for _, coinIdentifier := range requiredCoins {
|
||||||
coinMap[coinIdentifier] = &types.AccountCoin{
|
coinMap[coinIdentifier] = &storage.AccountCoin{
|
||||||
Account: coinBank[coinIdentifier].Account,
|
Account: coinBank[coinIdentifier].Account,
|
||||||
Coin: coinBank[coinIdentifier].Coin,
|
Coin: coinBank[coinIdentifier].Coin,
|
||||||
}
|
}
|
||||||
|
@ -401,13 +402,13 @@ func TestIndexer_Transactions(t *testing.T) {
|
||||||
if currBlock.BlockIdentifier.Index == 1000 {
|
if currBlock.BlockIdentifier.Index == 1000 {
|
||||||
// Ensure ScriptPubKeys are accessible.
|
// Ensure ScriptPubKeys are accessible.
|
||||||
allCoins := []*types.Coin{}
|
allCoins := []*types.Coin{}
|
||||||
expectedPubKeys := []*lbry.ScriptPubKey{}
|
expectedPubKeys := []*bitcoin.ScriptPubKey{}
|
||||||
for k, v := range coinBank {
|
for k, v := range coinBank {
|
||||||
allCoins = append(allCoins, &types.Coin{
|
allCoins = append(allCoins, &types.Coin{
|
||||||
CoinIdentifier: &types.CoinIdentifier{Identifier: k},
|
CoinIdentifier: &types.CoinIdentifier{Identifier: k},
|
||||||
Amount: &types.Amount{
|
Amount: &types.Amount{
|
||||||
Value: fmt.Sprintf("-%s", v.Coin.Amount.Value),
|
Value: fmt.Sprintf("-%s", v.Coin.Amount.Value),
|
||||||
Currency: lbry.TestnetCurrency,
|
Currency: bitcoin.TestnetCurrency,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expectedPubKeys = append(expectedPubKeys, v.Script)
|
expectedPubKeys = append(expectedPubKeys, v.Script)
|
||||||
|
@ -442,10 +443,10 @@ func TestIndexer_Reorg(t *testing.T) {
|
||||||
mockClient := &mocks.Client{}
|
mockClient := &mocks.Client{}
|
||||||
cfg := &configuration.Configuration{
|
cfg := &configuration.Configuration{
|
||||||
Network: &types.NetworkIdentifier{
|
Network: &types.NetworkIdentifier{
|
||||||
Network: lbry.MainnetNetwork,
|
Network: bitcoin.MainnetNetwork,
|
||||||
Blockchain: lbry.Blockchain,
|
Blockchain: bitcoin.Blockchain,
|
||||||
},
|
},
|
||||||
GenesisBlockIdentifier: lbry.MainnetGenesisBlockIdentifier,
|
GenesisBlockIdentifier: bitcoin.MainnetGenesisBlockIdentifier,
|
||||||
IndexerPath: newDir,
|
IndexerPath: newDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,13 +458,13 @@ func TestIndexer_Reorg(t *testing.T) {
|
||||||
CurrentBlockIdentifier: &types.BlockIdentifier{
|
CurrentBlockIdentifier: &types.BlockIdentifier{
|
||||||
Index: 1000,
|
Index: 1000,
|
||||||
},
|
},
|
||||||
GenesisBlockIdentifier: lbry.MainnetGenesisBlockIdentifier,
|
GenesisBlockIdentifier: bitcoin.MainnetGenesisBlockIdentifier,
|
||||||
}, nil)
|
}, nil)
|
||||||
|
|
||||||
// Add blocks
|
// Add blocks
|
||||||
waitForCheck := make(chan struct{})
|
waitForCheck := make(chan struct{})
|
||||||
type coinBankEntry struct {
|
type coinBankEntry struct {
|
||||||
Script *lbry.ScriptPubKey
|
Script *bitcoin.ScriptPubKey
|
||||||
Coin *types.Coin
|
Coin *types.Coin
|
||||||
Account *types.AccountIdentifier
|
Account *types.AccountIdentifier
|
||||||
}
|
}
|
||||||
|
@ -489,7 +490,7 @@ func TestIndexer_Reorg(t *testing.T) {
|
||||||
rawHash := fmt.Sprintf("block %d transaction %d", i, j)
|
rawHash := fmt.Sprintf("block %d transaction %d", i, j)
|
||||||
hash := fmt.Sprintf("%x", sha256.Sum256([]byte(rawHash)))
|
hash := fmt.Sprintf("%x", sha256.Sum256([]byte(rawHash)))
|
||||||
coinIdentifier := fmt.Sprintf("%s:%d", hash, index0)
|
coinIdentifier := fmt.Sprintf("%s:%d", hash, index0)
|
||||||
scriptPubKey := &lbry.ScriptPubKey{
|
scriptPubKey := &bitcoin.ScriptPubKey{
|
||||||
ASM: coinIdentifier,
|
ASM: coinIdentifier,
|
||||||
}
|
}
|
||||||
marshal, err := types.MarshalMap(scriptPubKey)
|
marshal, err := types.MarshalMap(scriptPubKey)
|
||||||
|
@ -504,14 +505,14 @@ func TestIndexer_Reorg(t *testing.T) {
|
||||||
Index: 0,
|
Index: 0,
|
||||||
NetworkIndex: &index0,
|
NetworkIndex: &index0,
|
||||||
},
|
},
|
||||||
Status: types.String(bitcoin.SuccessStatus),
|
Status: bitcoin.SuccessStatus,
|
||||||
Type: bitcoin.OutputOpType,
|
Type: bitcoin.OutputOpType,
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: rawHash,
|
Address: rawHash,
|
||||||
},
|
},
|
||||||
Amount: &types.Amount{
|
Amount: &types.Amount{
|
||||||
Value: fmt.Sprintf("%d", rand.Intn(1000)),
|
Value: fmt.Sprintf("%d", rand.Intn(1000)),
|
||||||
Currency: lbry.TestnetCurrency,
|
Currency: bitcoin.TestnetCurrency,
|
||||||
},
|
},
|
||||||
CoinChange: &types.CoinChange{
|
CoinChange: &types.CoinChange{
|
||||||
CoinAction: types.CoinCreated,
|
CoinAction: types.CoinCreated,
|
||||||
|
@ -540,7 +541,7 @@ func TestIndexer_Reorg(t *testing.T) {
|
||||||
transactions = append(transactions, tx)
|
transactions = append(transactions, tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
block := &lbry.Block{
|
block := &bitcoin.Block{
|
||||||
Hash: identifier.Hash,
|
Hash: identifier.Hash,
|
||||||
Height: identifier.Index,
|
Height: identifier.Index,
|
||||||
PreviousBlockHash: parentIdentifier.Hash,
|
PreviousBlockHash: parentIdentifier.Hash,
|
||||||
|
@ -601,9 +602,9 @@ func TestIndexer_Reorg(t *testing.T) {
|
||||||
Transactions: transactions,
|
Transactions: transactions,
|
||||||
}
|
}
|
||||||
|
|
||||||
coinMap := map[string]*types.AccountCoin{}
|
coinMap := map[string]*storage.AccountCoin{}
|
||||||
for _, coinIdentifier := range requiredCoins {
|
for _, coinIdentifier := range requiredCoins {
|
||||||
coinMap[coinIdentifier] = &types.AccountCoin{
|
coinMap[coinIdentifier] = &storage.AccountCoin{
|
||||||
Account: coinBank[coinIdentifier].Account,
|
Account: coinBank[coinIdentifier].Account,
|
||||||
Coin: coinBank[coinIdentifier].Coin,
|
Coin: coinBank[coinIdentifier].Coin,
|
||||||
}
|
}
|
||||||
|
@ -684,10 +685,10 @@ func TestIndexer_HeaderReorg(t *testing.T) {
|
||||||
mockClient := &mocks.Client{}
|
mockClient := &mocks.Client{}
|
||||||
cfg := &configuration.Configuration{
|
cfg := &configuration.Configuration{
|
||||||
Network: &types.NetworkIdentifier{
|
Network: &types.NetworkIdentifier{
|
||||||
Network: lbry.MainnetNetwork,
|
Network: bitcoin.MainnetNetwork,
|
||||||
Blockchain: lbry.Blockchain,
|
Blockchain: bitcoin.Blockchain,
|
||||||
},
|
},
|
||||||
GenesisBlockIdentifier: lbry.MainnetGenesisBlockIdentifier,
|
GenesisBlockIdentifier: bitcoin.MainnetGenesisBlockIdentifier,
|
||||||
IndexerPath: newDir,
|
IndexerPath: newDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,7 +700,7 @@ func TestIndexer_HeaderReorg(t *testing.T) {
|
||||||
CurrentBlockIdentifier: &types.BlockIdentifier{
|
CurrentBlockIdentifier: &types.BlockIdentifier{
|
||||||
Index: 1000,
|
Index: 1000,
|
||||||
},
|
},
|
||||||
GenesisBlockIdentifier: lbry.MainnetGenesisBlockIdentifier,
|
GenesisBlockIdentifier: bitcoin.MainnetGenesisBlockIdentifier,
|
||||||
}, nil)
|
}, nil)
|
||||||
|
|
||||||
// Add blocks
|
// Add blocks
|
||||||
|
@ -719,7 +720,7 @@ func TestIndexer_HeaderReorg(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
transactions := []*types.Transaction{}
|
transactions := []*types.Transaction{}
|
||||||
block := &lbry.Block{
|
block := &bitcoin.Block{
|
||||||
Hash: identifier.Hash,
|
Hash: identifier.Hash,
|
||||||
Height: identifier.Index,
|
Height: identifier.Index,
|
||||||
PreviousBlockHash: parentIdentifier.Hash,
|
PreviousBlockHash: parentIdentifier.Hash,
|
||||||
|
@ -746,7 +747,7 @@ func TestIndexer_HeaderReorg(t *testing.T) {
|
||||||
mock.Anything,
|
mock.Anything,
|
||||||
&types.PartialBlockIdentifier{Index: &identifier.Index},
|
&types.PartialBlockIdentifier{Index: &identifier.Index},
|
||||||
).Return(
|
).Return(
|
||||||
&lbry.Block{
|
&bitcoin.Block{
|
||||||
Hash: identifier.Hash,
|
Hash: identifier.Hash,
|
||||||
Height: identifier.Index,
|
Height: identifier.Index,
|
||||||
PreviousBlockHash: "blah",
|
PreviousBlockHash: "blah",
|
||||||
|
@ -773,7 +774,7 @@ func TestIndexer_HeaderReorg(t *testing.T) {
|
||||||
Transactions: transactions,
|
Transactions: transactions,
|
||||||
}
|
}
|
||||||
|
|
||||||
coinMap := map[string]*types.AccountCoin{}
|
coinMap := map[string]*storage.AccountCoin{}
|
||||||
if i == 400 {
|
if i == 400 {
|
||||||
mockClient.On(
|
mockClient.On(
|
||||||
"ParseBlock",
|
"ParseBlock",
|
||||||
|
|
10
install.sh
10
install.sh
|
@ -20,7 +20,7 @@ set -e
|
||||||
usage() {
|
usage() {
|
||||||
this=$1
|
this=$1
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
$this: download pre-compiled Docker images for lbryio/rosetta-lbry
|
$this: download pre-compiled Docker images for coinbase/rosetta-bitcoin
|
||||||
|
|
||||||
Usage: $this [-d]
|
Usage: $this [-d]
|
||||||
-d turns on debug logging
|
-d turns on debug logging
|
||||||
|
@ -44,8 +44,8 @@ execute() {
|
||||||
log_info "downloading image into ${tmpdir}"
|
log_info "downloading image into ${tmpdir}"
|
||||||
http_download "${tmpdir}/${TARBALL}" "${TARBALL_URL}" "" "1"
|
http_download "${tmpdir}/${TARBALL}" "${TARBALL_URL}" "" "1"
|
||||||
docker load --input "${tmpdir}/${TARBALL}"
|
docker load --input "${tmpdir}/${TARBALL}"
|
||||||
docker tag "rosetta-lbry:${TAG}" "rosetta-lbry:latest"
|
docker tag "rosetta-bitcoin:${TAG}" "rosetta-bitcoin:latest"
|
||||||
log_info "loaded rosetta-lbry:${TAG} and tagged as rosetta-lbry:latest"
|
log_info "loaded rosetta-bitcoin:${TAG} and tagged as rosetta-bitcoin:latest"
|
||||||
rm -rf "${tmpdir}"
|
rm -rf "${tmpdir}"
|
||||||
log_info "removed temporary directory ${tmpdir}"
|
log_info "removed temporary directory ${tmpdir}"
|
||||||
}
|
}
|
||||||
|
@ -196,10 +196,10 @@ End of functions from https://github.com/client9/shlib
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
BINARY=rosetta-lbry
|
BINARY=rosetta-bitcoin
|
||||||
FORMAT=tar.gz
|
FORMAT=tar.gz
|
||||||
OWNER=coinbase
|
OWNER=coinbase
|
||||||
REPO="rosetta-lbry"
|
REPO="rosetta-bitcoin"
|
||||||
PREFIX="$OWNER/$REPO"
|
PREFIX="$OWNER/$REPO"
|
||||||
|
|
||||||
# use in logging routines
|
# use in logging routines
|
||||||
|
|
172
lbry/config.go
172
lbry/config.go
|
@ -1,172 +0,0 @@
|
||||||
package lbry
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/big"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/chaincfg"
|
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
|
||||||
"github.com/btcsuite/btcd/wire"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
if err := chaincfg.Register(&LbryMainnetParams); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if err := chaincfg.Register(&LbryTestnetParams); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
bigOne = big.NewInt(1)
|
|
||||||
mainPowLimit = new(big.Int).Sub(new(big.Int).Lsh(bigOne, 224), bigOne)
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// DeploymentTestDummy ...
|
|
||||||
DeploymentTestDummy = iota
|
|
||||||
|
|
||||||
// DeploymentCSV ...
|
|
||||||
DeploymentCSV
|
|
||||||
|
|
||||||
// DeploymentSegwit ...
|
|
||||||
DeploymentSegwit
|
|
||||||
|
|
||||||
// DefinedDeployments ...
|
|
||||||
DefinedDeployments
|
|
||||||
)
|
|
||||||
|
|
||||||
// genesisCoinbaseTx is the coinbase transaction for the genesis blocks for
|
|
||||||
// the main network, regression test network, and test network (version 3).
|
|
||||||
var genesisCoinbaseTx = wire.MsgTx{
|
|
||||||
Version: 1,
|
|
||||||
TxIn: []*wire.TxIn{
|
|
||||||
{
|
|
||||||
PreviousOutPoint: wire.OutPoint{
|
|
||||||
Hash: chainhash.Hash{},
|
|
||||||
Index: 0xffffffff,
|
|
||||||
},
|
|
||||||
SignatureScript: []byte{
|
|
||||||
0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, 0x17,
|
|
||||||
0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x20, 0x74,
|
|
||||||
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
|
|
||||||
0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
|
|
||||||
},
|
|
||||||
Sequence: 0xffffffff,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
TxOut: []*wire.TxOut{
|
|
||||||
{
|
|
||||||
Value: 0x12a05f200,
|
|
||||||
PkScript: []byte{ // ToDo
|
|
||||||
0x76, 0xa9, 0x14, 0x34, 0x59, 0x91, 0xdb, 0xf5,
|
|
||||||
0x7b, 0xfb, 0x01, 0x4b, 0x87, 0x00, 0x6a, 0xcd,
|
|
||||||
0xfa, 0xfb, 0xfc, 0x5f, 0xe8, 0x29, 0x2f, 0x88,
|
|
||||||
0xac,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
LockTime: 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/lbryio/lbrycrd/blob/master/src/chainparams.cpp#L19
|
|
||||||
var genesisMerkleRoot = chainhash.Hash([chainhash.HashSize]byte{ // Make go vet happy.
|
|
||||||
0xcc, 0x59, 0xe5, 0x9f, 0xf9, 0x7a, 0xc0, 0x92,
|
|
||||||
0xb5, 0x5e, 0x42, 0x3a, 0xa5, 0x49, 0x51, 0x51,
|
|
||||||
0xed, 0x6f, 0xb8, 0x05, 0x70, 0xa5, 0xbb, 0x78,
|
|
||||||
0xcd, 0x5b, 0xd1, 0xc3, 0x82, 0x1c, 0x21, 0xb8,
|
|
||||||
})
|
|
||||||
|
|
||||||
var genesisBlock = wire.MsgBlock{
|
|
||||||
Header: wire.BlockHeader{
|
|
||||||
Version: 1,
|
|
||||||
PrevBlock: chainhash.Hash{}, // 0000000000000000000000000000000000000000000000000000000000000000
|
|
||||||
MerkleRoot: genesisMerkleRoot, // b8211c82c3d15bcd78bba57005b86fed515149a53a425eb592c07af99fe559cc
|
|
||||||
Timestamp: time.Unix(1446058291, 0), // Wednesday, October 28, 2015 6:51:31 PM GMT
|
|
||||||
Bits: 0x1f00ffff,
|
|
||||||
Nonce: 1287,
|
|
||||||
},
|
|
||||||
Transactions: []*wire.MsgTx{&genesisCoinbaseTx},
|
|
||||||
}
|
|
||||||
|
|
||||||
var genesisHash = chainhash.Hash([chainhash.HashSize]byte{ // Make go vet happy.
|
|
||||||
0x63, 0xf4, 0x34, 0x6a, 0x4d, 0xb3, 0x4f, 0xdf,
|
|
||||||
0xce, 0x29, 0xa7, 0x0f, 0x5e, 0x8d, 0x11, 0xf0,
|
|
||||||
0x65, 0xf6, 0xb9, 0x16, 0x02, 0xb7, 0x03, 0x6c,
|
|
||||||
0x7f, 0x22, 0xf3, 0xa0, 0x3b, 0x28, 0x89, 0x9c,
|
|
||||||
})
|
|
||||||
|
|
||||||
func newHashFromStr(hexStr string) *chainhash.Hash {
|
|
||||||
hash, err := chainhash.NewHashFromStr(hexStr)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return hash
|
|
||||||
}
|
|
||||||
|
|
||||||
// MainNetParams returns the chain configuration for mainnet
|
|
||||||
var LbryMainnetParams = chaincfg.Params{
|
|
||||||
Name: "mainnet",
|
|
||||||
Net: 0xfae4aaf1,
|
|
||||||
DefaultPort: "9246",
|
|
||||||
|
|
||||||
// Chain parameters
|
|
||||||
GenesisBlock: &genesisBlock,
|
|
||||||
GenesisHash: &genesisHash,
|
|
||||||
|
|
||||||
// Human-readable part for Bech32 encoded segwit addresses, as defined in
|
|
||||||
// BIP 173.
|
|
||||||
Bech32HRPSegwit: "lbc",
|
|
||||||
|
|
||||||
// Address encoding magics
|
|
||||||
PubKeyHashAddrID: 85,
|
|
||||||
ScriptHashAddrID: 122,
|
|
||||||
PrivateKeyID: 28,
|
|
||||||
WitnessPubKeyHashAddrID: 0x06, // starts with p2
|
|
||||||
WitnessScriptHashAddrID: 0x0A, // starts with 7Xh
|
|
||||||
BIP0034Height: 1,
|
|
||||||
BIP0065Height: 200000,
|
|
||||||
BIP0066Height: 200000,
|
|
||||||
|
|
||||||
// BIP32 hierarchical deterministic extended key magics
|
|
||||||
HDPrivateKeyID: [4]byte{0x04, 0x88, 0xad, 0xe4}, // starts with xprv
|
|
||||||
HDPublicKeyID: [4]byte{0x04, 0x88, 0xb2, 0x1e}, // starts with xpub
|
|
||||||
|
|
||||||
// BIP44 coin type used in the hierarchical deterministic path for
|
|
||||||
// address generation.
|
|
||||||
HDCoinType: 0x8c,
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestnetParams returns the chain configuration for testnet
|
|
||||||
var LbryTestnetParams = chaincfg.Params{
|
|
||||||
Name: "testnet",
|
|
||||||
Net: 0xfae4aae1,
|
|
||||||
DefaultPort: "19246",
|
|
||||||
|
|
||||||
// Chain parameters
|
|
||||||
GenesisBlock: &genesisBlock,
|
|
||||||
GenesisHash: &genesisHash,
|
|
||||||
|
|
||||||
// Human-readable part for Bech32 encoded segwit addresses, as defined in
|
|
||||||
// BIP 173.
|
|
||||||
Bech32HRPSegwit: "tlbc", // always bc for main net
|
|
||||||
|
|
||||||
// Address encoding magics
|
|
||||||
PubKeyHashAddrID: 111,
|
|
||||||
ScriptHashAddrID: 196,
|
|
||||||
PrivateKeyID: 239,
|
|
||||||
WitnessPubKeyHashAddrID: 0x06, // starts with p2
|
|
||||||
WitnessScriptHashAddrID: 0x0A, // starts with 7Xh
|
|
||||||
BIP0034Height: 1,
|
|
||||||
BIP0065Height: 200000,
|
|
||||||
BIP0066Height: 200000,
|
|
||||||
|
|
||||||
// BIP32 hierarchical deterministic extended key magics
|
|
||||||
HDPrivateKeyID: [4]byte{0x04, 0x35, 0x83, 0x94}, // starts with xprv
|
|
||||||
HDPublicKeyID: [4]byte{0x04, 0x35, 0x87, 0xcf}, // starts with xpub
|
|
||||||
|
|
||||||
// BIP44 coin type used in the hierarchical deterministic path for
|
|
||||||
// address generation.
|
|
||||||
HDCoinType: 0x8c,
|
|
||||||
}
|
|
27
main.go
27
main.go
|
@ -24,11 +24,11 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/lbryio/rosetta-lbry/configuration"
|
"github.com/coinbase/rosetta-bitcoin/bitcoin"
|
||||||
"github.com/lbryio/rosetta-lbry/indexer"
|
"github.com/coinbase/rosetta-bitcoin/configuration"
|
||||||
"github.com/lbryio/rosetta-lbry/lbry"
|
"github.com/coinbase/rosetta-bitcoin/indexer"
|
||||||
"github.com/lbryio/rosetta-lbry/services"
|
"github.com/coinbase/rosetta-bitcoin/services"
|
||||||
"github.com/lbryio/rosetta-lbry/utils"
|
"github.com/coinbase/rosetta-bitcoin/utils"
|
||||||
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/asserter"
|
"github.com/coinbase/rosetta-sdk-go/asserter"
|
||||||
"github.com/coinbase/rosetta-sdk-go/server"
|
"github.com/coinbase/rosetta-sdk-go/server"
|
||||||
|
@ -79,15 +79,15 @@ func startOnlineDependencies(
|
||||||
cancel context.CancelFunc,
|
cancel context.CancelFunc,
|
||||||
cfg *configuration.Configuration,
|
cfg *configuration.Configuration,
|
||||||
g *errgroup.Group,
|
g *errgroup.Group,
|
||||||
) (*lbry.Client, *indexer.Indexer, error) {
|
) (*bitcoin.Client, *indexer.Indexer, error) {
|
||||||
client := lbry.NewClient(
|
client := bitcoin.NewClient(
|
||||||
lbry.LocalhostURL(cfg.RPCPort),
|
bitcoin.LocalhostURL(cfg.RPCPort),
|
||||||
cfg.GenesisBlockIdentifier,
|
cfg.GenesisBlockIdentifier,
|
||||||
cfg.Currency,
|
cfg.Currency,
|
||||||
)
|
)
|
||||||
|
|
||||||
g.Go(func() error {
|
g.Go(func() error {
|
||||||
return lbry.Startlbrycrdd(ctx, cfg.ConfigPath, g)
|
return bitcoin.StartBitcoind(ctx, cfg.ConfigPath, g)
|
||||||
})
|
})
|
||||||
|
|
||||||
i, err := indexer.Initialize(
|
i, err := indexer.Initialize(
|
||||||
|
@ -142,7 +142,7 @@ func main() {
|
||||||
})
|
})
|
||||||
|
|
||||||
var i *indexer.Indexer
|
var i *indexer.Indexer
|
||||||
var client *lbry.Client
|
var client *bitcoin.Client
|
||||||
if cfg.Mode == configuration.Online {
|
if cfg.Mode == configuration.Online {
|
||||||
client, i, err = startOnlineDependencies(ctx, cancel, cfg, g)
|
client, i, err = startOnlineDependencies(ctx, cancel, cfg, g)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -153,11 +153,10 @@ func main() {
|
||||||
// The asserter automatically rejects incorrectly formatted
|
// The asserter automatically rejects incorrectly formatted
|
||||||
// requests.
|
// requests.
|
||||||
asserter, err := asserter.NewServer(
|
asserter, err := asserter.NewServer(
|
||||||
lbry.OperationTypes,
|
bitcoin.OperationTypes,
|
||||||
services.HistoricalBalanceLookup,
|
services.HistoricalBalanceLookup,
|
||||||
[]*types.NetworkIdentifier{cfg.Network},
|
[]*types.NetworkIdentifier{cfg.Network},
|
||||||
nil,
|
nil,
|
||||||
services.MempoolCoins,
|
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalw("unable to create new server asserter", "error", err)
|
logger.Fatalw("unable to create new server asserter", "error", err)
|
||||||
|
@ -197,10 +196,10 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if signalReceived {
|
if signalReceived {
|
||||||
logger.Fatalw("rosetta-lbry halted")
|
logger.Fatalw("rosetta-bitcoin halted")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalw("rosetta-lbry sync failed", "error", err)
|
logger.Fatalw("rosetta-bitcoin sync failed", "error", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,12 @@ package indexer
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
|
|
||||||
lbry "github.com/lbryio/rosetta-lbry/lbry"
|
bitcoin "github.com/coinbase/rosetta-bitcoin/bitcoin"
|
||||||
|
|
||||||
mock "github.com/stretchr/testify/mock"
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
|
storage "github.com/coinbase/rosetta-sdk-go/storage"
|
||||||
|
|
||||||
types "github.com/coinbase/rosetta-sdk-go/types"
|
types "github.com/coinbase/rosetta-sdk-go/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,15 +20,15 @@ type Client struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRawBlock provides a mock function with given fields: _a0, _a1
|
// GetRawBlock provides a mock function with given fields: _a0, _a1
|
||||||
func (_m *Client) GetRawBlock(_a0 context.Context, _a1 *types.PartialBlockIdentifier) (*lbry.Block, []string, error) {
|
func (_m *Client) GetRawBlock(_a0 context.Context, _a1 *types.PartialBlockIdentifier) (*bitcoin.Block, []string, error) {
|
||||||
ret := _m.Called(_a0, _a1)
|
ret := _m.Called(_a0, _a1)
|
||||||
|
|
||||||
var r0 *lbry.Block
|
var r0 *bitcoin.Block
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, *types.PartialBlockIdentifier) *lbry.Block); ok {
|
if rf, ok := ret.Get(0).(func(context.Context, *types.PartialBlockIdentifier) *bitcoin.Block); ok {
|
||||||
r0 = rf(_a0, _a1)
|
r0 = rf(_a0, _a1)
|
||||||
} else {
|
} else {
|
||||||
if ret.Get(0) != nil {
|
if ret.Get(0) != nil {
|
||||||
r0 = ret.Get(0).(*lbry.Block)
|
r0 = ret.Get(0).(*bitcoin.Block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,11 +75,11 @@ func (_m *Client) NetworkStatus(_a0 context.Context) (*types.NetworkStatusRespon
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseBlock provides a mock function with given fields: _a0, _a1, _a2
|
// ParseBlock provides a mock function with given fields: _a0, _a1, _a2
|
||||||
func (_m *Client) ParseBlock(_a0 context.Context, _a1 *bitcoin.Block, _a2 map[string]*types.AccountCoin) (*types.Block, error) {
|
func (_m *Client) ParseBlock(_a0 context.Context, _a1 *bitcoin.Block, _a2 map[string]*storage.AccountCoin) (*types.Block, error) {
|
||||||
ret := _m.Called(_a0, _a1, _a2)
|
ret := _m.Called(_a0, _a1, _a2)
|
||||||
|
|
||||||
var r0 *types.Block
|
var r0 *types.Block
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, *bitcoin.Block, map[string]*types.AccountCoin) *types.Block); ok {
|
if rf, ok := ret.Get(0).(func(context.Context, *bitcoin.Block, map[string]*storage.AccountCoin) *types.Block); ok {
|
||||||
r0 = rf(_a0, _a1, _a2)
|
r0 = rf(_a0, _a1, _a2)
|
||||||
} else {
|
} else {
|
||||||
if ret.Get(0) != nil {
|
if ret.Get(0) != nil {
|
||||||
|
@ -86,7 +88,7 @@ func (_m *Client) ParseBlock(_a0 context.Context, _a1 *bitcoin.Block, _a2 map[st
|
||||||
}
|
}
|
||||||
|
|
||||||
var r1 error
|
var r1 error
|
||||||
if rf, ok := ret.Get(1).(func(context.Context, *bitcoin.Block, map[string]*types.AccountCoin) error); ok {
|
if rf, ok := ret.Get(1).(func(context.Context, *bitcoin.Block, map[string]*storage.AccountCoin) error); ok {
|
||||||
r1 = rf(_a0, _a1, _a2)
|
r1 = rf(_a0, _a1, _a2)
|
||||||
} else {
|
} else {
|
||||||
r1 = ret.Error(1)
|
r1 = ret.Error(1)
|
||||||
|
|
|
@ -5,7 +5,7 @@ package services
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
|
|
||||||
lbry "github.com/lbryio/rosetta-lbry/lbry"
|
bitcoin "github.com/coinbase/rosetta-bitcoin/bitcoin"
|
||||||
|
|
||||||
mock "github.com/stretchr/testify/mock"
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
|
@ -128,15 +128,15 @@ func (_m *Indexer) GetCoins(_a0 context.Context, _a1 *types.AccountIdentifier) (
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetScriptPubKeys provides a mock function with given fields: _a0, _a1
|
// GetScriptPubKeys provides a mock function with given fields: _a0, _a1
|
||||||
func (_m *Indexer) GetScriptPubKeys(_a0 context.Context, _a1 []*types.Coin) ([]*lbry.ScriptPubKey, error) {
|
func (_m *Indexer) GetScriptPubKeys(_a0 context.Context, _a1 []*types.Coin) ([]*bitcoin.ScriptPubKey, error) {
|
||||||
ret := _m.Called(_a0, _a1)
|
ret := _m.Called(_a0, _a1)
|
||||||
|
|
||||||
var r0 []*lbry.ScriptPubKey
|
var r0 []*bitcoin.ScriptPubKey
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, []*types.Coin) []*lbry.ScriptPubKey); ok {
|
if rf, ok := ret.Get(0).(func(context.Context, []*types.Coin) []*bitcoin.ScriptPubKey); ok {
|
||||||
r0 = rf(_a0, _a1)
|
r0 = rf(_a0, _a1)
|
||||||
} else {
|
} else {
|
||||||
if ret.Get(0) != nil {
|
if ret.Get(0) != nil {
|
||||||
r0 = ret.Get(0).([]*lbry.ScriptPubKey)
|
r0 = ret.Get(0).([]*bitcoin.ScriptPubKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,40 @@
|
||||||
{
|
{
|
||||||
"network": {
|
"network": {
|
||||||
"blockchain": "lbry",
|
"blockchain": "Bitcoin",
|
||||||
"network": "Mainnet"
|
"network": "Mainnet"
|
||||||
},
|
},
|
||||||
"data_directory": "cli-data",
|
"data_directory": "cli-data",
|
||||||
"http_timeout": 300,
|
"http_timeout": 300,
|
||||||
"max_retries": 5,
|
"max_retries": 5,
|
||||||
"max_online_connections": 1000,
|
"retry_elapsed_time": 0,
|
||||||
"tip_delay": 1800,
|
"max_online_connections": 1000,
|
||||||
"compression_disabled": true,
|
"max_sync_concurrency": 0,
|
||||||
"memory_limit_disabled": true,
|
"tip_delay": 1800,
|
||||||
"data": {
|
"log_configuration": false,
|
||||||
"initial_balance_fetch_disabled": true,
|
"compression_disabled": true,
|
||||||
"end_conditions": {
|
"memory_limit_disabled": true,
|
||||||
"reconciliation_coverage": {
|
"data": {
|
||||||
"coverage": 0.95,
|
"active_reconciliation_concurrency": 0,
|
||||||
"from_tip": true
|
"inactive_reconciliation_concurrency": 0,
|
||||||
}
|
"inactive_reconciliation_frequency": 0,
|
||||||
|
"log_blocks": false,
|
||||||
|
"log_transactions": false,
|
||||||
|
"log_balance_changes": false,
|
||||||
|
"log_reconciliations": false,
|
||||||
|
"ignore_reconciliation_error": false,
|
||||||
|
"exempt_accounts": "",
|
||||||
|
"bootstrap_balances": "",
|
||||||
|
"interesting_accounts": "",
|
||||||
|
"reconciliation_disabled": false,
|
||||||
|
"inactive_discrepency_search_disabled": false,
|
||||||
|
"balance_tracking_disabled": false,
|
||||||
|
"coin_tracking_disabled": false,
|
||||||
|
"end_conditions": {
|
||||||
|
"reconciliation_coverage": {
|
||||||
|
"coverage": 0.95,
|
||||||
|
"from_tip": true
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"results_output_file": ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
request_funds(1){
|
request_funds(1){
|
||||||
find_account{
|
find_account{
|
||||||
currency = {"symbol":"tLBC", "decimals":8};
|
currency = {"symbol":"tBTC", "decimals":8};
|
||||||
random_account = find_balance({
|
random_account = find_balance({
|
||||||
"minimum_balance":{
|
"minimum_balance":{
|
||||||
"value": "0",
|
"value": "0",
|
||||||
|
@ -27,7 +27,7 @@ request_funds(1){
|
||||||
|
|
||||||
create_account(1){
|
create_account(1){
|
||||||
create{
|
create{
|
||||||
network = {"network":"Testnet3", "blockchain":"LBRY"};
|
network = {"network":"Testnet3", "blockchain":"Bitcoin"};
|
||||||
key = generate_key({"curve_type": "secp256k1"});
|
key = generate_key({"curve_type": "secp256k1"});
|
||||||
account = derive({
|
account = derive({
|
||||||
"network_identifier": {{network}},
|
"network_identifier": {{network}},
|
||||||
|
@ -44,8 +44,8 @@ create_account(1){
|
||||||
|
|
||||||
transfer(10){
|
transfer(10){
|
||||||
transfer_dry_run{
|
transfer_dry_run{
|
||||||
transfer_dry_run.network = {"network":"Testnet3", "blockchain":"LBRY"};
|
transfer_dry_run.network = {"network":"Testnet3", "blockchain":"Bitcoin"};
|
||||||
currency = {"symbol":"tLBC", "decimals":8};
|
currency = {"symbol":"tBTC", "decimals":8};
|
||||||
|
|
||||||
// We set the max_fee_amount to know how much buffer we should
|
// We set the max_fee_amount to know how much buffer we should
|
||||||
// leave for fee payment when selecting a sender account.
|
// leave for fee payment when selecting a sender account.
|
||||||
|
@ -165,10 +165,10 @@ transfer(10){
|
||||||
|
|
||||||
return_funds(10){
|
return_funds(10){
|
||||||
transfer_dry_run{
|
transfer_dry_run{
|
||||||
transfer_dry_run.network = {"network":"Testnet3", "blockchain":"LBRY"};
|
transfer_dry_run.network = {"network":"Testnet3", "blockchain":"Bitcoin"};
|
||||||
currency = {"symbol":"tLBC", "decimals":8};
|
currency = {"symbol":"tBTC", "decimals":8};
|
||||||
|
|
||||||
// We look for a sender that is able to pay the
|
// We look for a sender that is able to pay the
|
||||||
// max_fee_amount + min_utxo size (reserved_amount is max_fee_amount + min_utxo size).
|
// max_fee_amount + min_utxo size (reserved_amount is max_fee_amount + min_utxo size).
|
||||||
max_fee_amount = "1200";
|
max_fee_amount = "1200";
|
||||||
reserved_amount = "1800";
|
reserved_amount = "1800";
|
|
@ -1,29 +1,55 @@
|
||||||
{
|
{
|
||||||
"network": {
|
"network": {
|
||||||
"blockchain": "lbry",
|
"blockchain": "Bitcoin",
|
||||||
"network": "Testnet3"
|
"network": "Testnet3"
|
||||||
},
|
},
|
||||||
"data_directory": "cli-data",
|
"data_directory": "cli-data",
|
||||||
"http_timeout": 300,
|
"http_timeout": 300,
|
||||||
"max_retries": 5,
|
"max_retries": 5,
|
||||||
"max_online_connections": 1000,
|
"retry_elapsed_time": 0,
|
||||||
"tip_delay": 1800,
|
"max_online_connections": 1000,
|
||||||
"memory_limit_disabled": true,
|
"max_sync_concurrency": 0,
|
||||||
"compression_disabled": true,
|
"tip_delay": 1800,
|
||||||
"construction": {
|
"log_configuration": false,
|
||||||
"constructor_dsl_file": "lbry.ros",
|
"compression_disabled": true,
|
||||||
"end_conditions": {
|
"memory_limit_disabled": true,
|
||||||
"create_account": 10,
|
"construction": {
|
||||||
"transfer": 10
|
"max_offline_connections": 0,
|
||||||
}
|
"stale_depth": 0,
|
||||||
},
|
"broadcast_limit": 0,
|
||||||
"data": {
|
"ignore_broadcast_failures": false,
|
||||||
"initial_balance_fetch_disabled": true,
|
"clear_broadcasts": false,
|
||||||
"end_conditions": {
|
"broadcast_behind_tip": false,
|
||||||
"reconciliation_coverage": {
|
"block_broadcast_limit": 0,
|
||||||
"coverage": 0.95,
|
"rebroadcast_all": false,
|
||||||
"from_tip": true
|
"constructor_dsl_file": "bitcoin.ros",
|
||||||
}
|
"end_conditions": {
|
||||||
}
|
"create_account": 10,
|
||||||
|
"transfer": 10
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"active_reconciliation_concurrency": 0,
|
||||||
|
"inactive_reconciliation_concurrency": 0,
|
||||||
|
"inactive_reconciliation_frequency": 0,
|
||||||
|
"log_blocks": false,
|
||||||
|
"log_transactions": false,
|
||||||
|
"log_balance_changes": false,
|
||||||
|
"log_reconciliations": false,
|
||||||
|
"ignore_reconciliation_error": false,
|
||||||
|
"exempt_accounts": "",
|
||||||
|
"bootstrap_balances": "",
|
||||||
|
"interesting_accounts": "",
|
||||||
|
"reconciliation_disabled": false,
|
||||||
|
"inactive_discrepency_search_disabled": false,
|
||||||
|
"balance_tracking_disabled": false,
|
||||||
|
"coin_tracking_disabled": false,
|
||||||
|
"end_conditions": {
|
||||||
|
"reconciliation_coverage": {
|
||||||
|
"coverage": 0.95,
|
||||||
|
"from_tip": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"results_output_file": ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ package services
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/lbryio/rosetta-lbry/configuration"
|
"github.com/coinbase/rosetta-bitcoin/configuration"
|
||||||
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/server"
|
"github.com/coinbase/rosetta-sdk-go/server"
|
||||||
"github.com/coinbase/rosetta-sdk-go/types"
|
"github.com/coinbase/rosetta-sdk-go/types"
|
||||||
|
@ -49,7 +49,34 @@ func (s *AccountAPIService) AccountBalance(
|
||||||
return nil, wrapErr(ErrUnavailableOffline, nil)
|
return nil, wrapErr(ErrUnavailableOffline, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: filter balances by request currencies
|
// If we are fetching the current balance,
|
||||||
|
// return all coins for an address and calculate
|
||||||
|
// the balance from those coins.
|
||||||
|
if request.BlockIdentifier == nil {
|
||||||
|
coins, block, err := s.i.GetCoins(ctx, request.AccountIdentifier)
|
||||||
|
if err != nil {
|
||||||
|
return nil, wrapErr(ErrUnableToGetCoins, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
balance := "0"
|
||||||
|
for _, coin := range coins {
|
||||||
|
balance, err = types.AddValues(balance, coin.Amount.Value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, wrapErr(ErrUnableToParseIntermediateResult, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.AccountBalanceResponse{
|
||||||
|
BlockIdentifier: block,
|
||||||
|
Coins: coins,
|
||||||
|
Balances: []*types.Amount{
|
||||||
|
{
|
||||||
|
Value: balance,
|
||||||
|
Currency: s.config.Currency,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// If we are fetching a historical balance,
|
// If we are fetching a historical balance,
|
||||||
// use balance storage and don't return coins.
|
// use balance storage and don't return coins.
|
||||||
|
@ -70,31 +97,3 @@ func (s *AccountAPIService) AccountBalance(
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AccountCoins implements /account/coins.
|
|
||||||
func (s *AccountAPIService) AccountCoins(
|
|
||||||
ctx context.Context,
|
|
||||||
request *types.AccountCoinsRequest,
|
|
||||||
) (*types.AccountCoinsResponse, *types.Error) {
|
|
||||||
if s.config.Mode != configuration.Online {
|
|
||||||
return nil, wrapErr(ErrUnavailableOffline, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: filter coins by request currencies
|
|
||||||
|
|
||||||
// TODO: support include_mempool query
|
|
||||||
// https://github.com/coinbase/rosetta-sdk-go-bitcoin/issues/36#issuecomment-724992022
|
|
||||||
// Once mempoolcoins are supported also change the bool service/types.go:MempoolCoins to true
|
|
||||||
|
|
||||||
coins, block, err := s.i.GetCoins(ctx, request.AccountIdentifier)
|
|
||||||
if err != nil {
|
|
||||||
return nil, wrapErr(ErrUnableToGetCoins, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
result := &types.AccountCoinsResponse{
|
|
||||||
BlockIdentifier: block,
|
|
||||||
Coins: coins,
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -18,9 +18,9 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/lbryio/rosetta-lbry/configuration"
|
"github.com/coinbase/rosetta-bitcoin/bitcoin"
|
||||||
"github.com/lbryio/rosetta-lbry/lbry"
|
"github.com/coinbase/rosetta-bitcoin/configuration"
|
||||||
mocks "github.com/lbryio/rosetta-lbry/mocks/services"
|
mocks "github.com/coinbase/rosetta-bitcoin/mocks/services"
|
||||||
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/types"
|
"github.com/coinbase/rosetta-sdk-go/types"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -38,103 +38,13 @@ func TestAccountBalance_Offline(t *testing.T) {
|
||||||
assert.Nil(t, bal)
|
assert.Nil(t, bal)
|
||||||
assert.Equal(t, ErrUnavailableOffline.Code, err.Code)
|
assert.Equal(t, ErrUnavailableOffline.Code, err.Code)
|
||||||
|
|
||||||
coins, err := servicer.AccountCoins(ctx, &types.AccountCoinsRequest{})
|
|
||||||
assert.Nil(t, coins)
|
|
||||||
assert.Equal(t, ErrUnavailableOffline.Code, err.Code)
|
|
||||||
|
|
||||||
mockIndexer.AssertExpectations(t)
|
mockIndexer.AssertExpectations(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccountBalance_Online_Current(t *testing.T) {
|
func TestAccountBalance_Online_Current(t *testing.T) {
|
||||||
cfg := &configuration.Configuration{
|
cfg := &configuration.Configuration{
|
||||||
Mode: configuration.Online,
|
Mode: configuration.Online,
|
||||||
Currency: lbry.MainnetCurrency,
|
Currency: bitcoin.MainnetCurrency,
|
||||||
}
|
|
||||||
mockIndexer := &mocks.Indexer{}
|
|
||||||
servicer := NewAccountAPIService(cfg, mockIndexer)
|
|
||||||
ctx := context.Background()
|
|
||||||
account := &types.AccountIdentifier{
|
|
||||||
Address: "hello",
|
|
||||||
}
|
|
||||||
block := &types.BlockIdentifier{
|
|
||||||
Index: 1000,
|
|
||||||
Hash: "block 1000",
|
|
||||||
}
|
|
||||||
amount := &types.Amount{
|
|
||||||
Value: "25",
|
|
||||||
Currency: lbry.MainnetCurrency,
|
|
||||||
}
|
|
||||||
|
|
||||||
mockIndexer.On(
|
|
||||||
"GetBalance",
|
|
||||||
ctx,
|
|
||||||
account,
|
|
||||||
bitcoin.MainnetCurrency,
|
|
||||||
(*types.PartialBlockIdentifier)(nil),
|
|
||||||
).Return(amount, block, nil).Once()
|
|
||||||
bal, err := servicer.AccountBalance(ctx, &types.AccountBalanceRequest{
|
|
||||||
AccountIdentifier: account,
|
|
||||||
})
|
|
||||||
assert.Nil(t, err)
|
|
||||||
assert.Equal(t, &types.AccountBalanceResponse{
|
|
||||||
BlockIdentifier: block,
|
|
||||||
Balances: []*types.Amount{
|
|
||||||
amount,
|
|
||||||
},
|
|
||||||
}, bal)
|
|
||||||
|
|
||||||
mockIndexer.AssertExpectations(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAccountBalance_Online_Historical(t *testing.T) {
|
|
||||||
cfg := &configuration.Configuration{
|
|
||||||
Mode: configuration.Online,
|
|
||||||
Currency: lbry.MainnetCurrency,
|
|
||||||
}
|
|
||||||
mockIndexer := &mocks.Indexer{}
|
|
||||||
servicer := NewAccountAPIService(cfg, mockIndexer)
|
|
||||||
ctx := context.Background()
|
|
||||||
account := &types.AccountIdentifier{
|
|
||||||
Address: "hello",
|
|
||||||
}
|
|
||||||
block := &types.BlockIdentifier{
|
|
||||||
Index: 1000,
|
|
||||||
Hash: "block 1000",
|
|
||||||
}
|
|
||||||
partialBlock := &types.PartialBlockIdentifier{
|
|
||||||
Index: &block.Index,
|
|
||||||
}
|
|
||||||
amount := &types.Amount{
|
|
||||||
Value: "25",
|
|
||||||
Currency: lbry.MainnetCurrency,
|
|
||||||
}
|
|
||||||
|
|
||||||
mockIndexer.On(
|
|
||||||
"GetBalance",
|
|
||||||
ctx,
|
|
||||||
account,
|
|
||||||
lbry.MainnetCurrency,
|
|
||||||
partialBlock,
|
|
||||||
).Return(amount, block, nil).Once()
|
|
||||||
bal, err := servicer.AccountBalance(ctx, &types.AccountBalanceRequest{
|
|
||||||
AccountIdentifier: account,
|
|
||||||
BlockIdentifier: partialBlock,
|
|
||||||
})
|
|
||||||
assert.Nil(t, err)
|
|
||||||
assert.Equal(t, &types.AccountBalanceResponse{
|
|
||||||
BlockIdentifier: block,
|
|
||||||
Balances: []*types.Amount{
|
|
||||||
amount,
|
|
||||||
},
|
|
||||||
}, bal)
|
|
||||||
|
|
||||||
mockIndexer.AssertExpectations(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAccountCoins_Online(t *testing.T) {
|
|
||||||
cfg := &configuration.Configuration{
|
|
||||||
Mode: configuration.Online,
|
|
||||||
Currency: lbry.MainnetCurrency,
|
|
||||||
}
|
}
|
||||||
mockIndexer := &mocks.Indexer{}
|
mockIndexer := &mocks.Indexer{}
|
||||||
servicer := NewAccountAPIService(cfg, mockIndexer)
|
servicer := NewAccountAPIService(cfg, mockIndexer)
|
||||||
|
@ -176,14 +86,65 @@ func TestAccountCoins_Online(t *testing.T) {
|
||||||
}
|
}
|
||||||
mockIndexer.On("GetCoins", ctx, account).Return(coins, block, nil).Once()
|
mockIndexer.On("GetCoins", ctx, account).Return(coins, block, nil).Once()
|
||||||
|
|
||||||
bal, err := servicer.AccountCoins(ctx, &types.AccountCoinsRequest{
|
bal, err := servicer.AccountBalance(ctx, &types.AccountBalanceRequest{
|
||||||
AccountIdentifier: account,
|
AccountIdentifier: account,
|
||||||
})
|
})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
assert.Equal(t, &types.AccountCoinsResponse{
|
assert.Equal(t, &types.AccountBalanceResponse{
|
||||||
BlockIdentifier: block,
|
BlockIdentifier: block,
|
||||||
Coins: coins,
|
Coins: coins,
|
||||||
|
Balances: []*types.Amount{
|
||||||
|
{
|
||||||
|
Value: "25",
|
||||||
|
Currency: bitcoin.MainnetCurrency,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, bal)
|
||||||
|
|
||||||
|
mockIndexer.AssertExpectations(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccountBalance_Online_Historical(t *testing.T) {
|
||||||
|
cfg := &configuration.Configuration{
|
||||||
|
Mode: configuration.Online,
|
||||||
|
Currency: bitcoin.MainnetCurrency,
|
||||||
|
}
|
||||||
|
mockIndexer := &mocks.Indexer{}
|
||||||
|
servicer := NewAccountAPIService(cfg, mockIndexer)
|
||||||
|
ctx := context.Background()
|
||||||
|
account := &types.AccountIdentifier{
|
||||||
|
Address: "hello",
|
||||||
|
}
|
||||||
|
block := &types.BlockIdentifier{
|
||||||
|
Index: 1000,
|
||||||
|
Hash: "block 1000",
|
||||||
|
}
|
||||||
|
partialBlock := &types.PartialBlockIdentifier{
|
||||||
|
Index: &block.Index,
|
||||||
|
}
|
||||||
|
amount := &types.Amount{
|
||||||
|
Value: "25",
|
||||||
|
Currency: bitcoin.MainnetCurrency,
|
||||||
|
}
|
||||||
|
|
||||||
|
mockIndexer.On(
|
||||||
|
"GetBalance",
|
||||||
|
ctx,
|
||||||
|
account,
|
||||||
|
bitcoin.MainnetCurrency,
|
||||||
|
partialBlock,
|
||||||
|
).Return(amount, block, nil).Once()
|
||||||
|
bal, err := servicer.AccountBalance(ctx, &types.AccountBalanceRequest{
|
||||||
|
AccountIdentifier: account,
|
||||||
|
BlockIdentifier: partialBlock,
|
||||||
|
})
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, &types.AccountBalanceResponse{
|
||||||
|
BlockIdentifier: block,
|
||||||
|
Balances: []*types.Amount{
|
||||||
|
amount,
|
||||||
|
},
|
||||||
}, bal)
|
}, bal)
|
||||||
|
|
||||||
mockIndexer.AssertExpectations(t)
|
mockIndexer.AssertExpectations(t)
|
||||||
|
|
|
@ -17,7 +17,7 @@ package services
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/lbryio/rosetta-lbry/configuration"
|
"github.com/coinbase/rosetta-bitcoin/configuration"
|
||||||
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/server"
|
"github.com/coinbase/rosetta-sdk-go/server"
|
||||||
"github.com/coinbase/rosetta-sdk-go/types"
|
"github.com/coinbase/rosetta-sdk-go/types"
|
||||||
|
|
|
@ -19,8 +19,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/lbryio/rosetta-lbry/configuration"
|
"github.com/coinbase/rosetta-bitcoin/configuration"
|
||||||
mocks "github.com/lbryio/rosetta-lbry/mocks/services"
|
mocks "github.com/coinbase/rosetta-bitcoin/mocks/services"
|
||||||
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/types"
|
"github.com/coinbase/rosetta-sdk-go/types"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
|
@ -24,8 +24,8 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/lbryio/rosetta-lbry/configuration"
|
"github.com/coinbase/rosetta-bitcoin/bitcoin"
|
||||||
"github.com/lbryio/rosetta-lbry/lbry"
|
"github.com/coinbase/rosetta-bitcoin/configuration"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec"
|
"github.com/btcsuite/btcd/btcec"
|
||||||
"github.com/btcsuite/btcd/txscript"
|
"github.com/btcsuite/btcd/txscript"
|
||||||
|
@ -37,7 +37,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// bytesInKB is the number of bytes in a KB. In lbry, this is
|
// bytesInKB is the number of bytes in a KB. In Bitcoin, this is
|
||||||
// considered to be 1000.
|
// considered to be 1000.
|
||||||
bytesInKb = float64(1000) // nolint:gomnd
|
bytesInKb = float64(1000) // nolint:gomnd
|
||||||
|
|
||||||
|
@ -88,22 +88,22 @@ func (s *ConstructionAPIService) ConstructionDerive(
|
||||||
|
|
||||||
// estimateSize returns the estimated size of a transaction in vBytes.
|
// estimateSize returns the estimated size of a transaction in vBytes.
|
||||||
func (s *ConstructionAPIService) estimateSize(operations []*types.Operation) float64 {
|
func (s *ConstructionAPIService) estimateSize(operations []*types.Operation) float64 {
|
||||||
size := lbry.TransactionOverhead
|
size := bitcoin.TransactionOverhead
|
||||||
for _, operation := range operations {
|
for _, operation := range operations {
|
||||||
switch operation.Type {
|
switch operation.Type {
|
||||||
case lbry.InputOpType:
|
case bitcoin.InputOpType:
|
||||||
size += lbry.InputSize
|
size += bitcoin.InputSize
|
||||||
case lbry.OutputOpType:
|
case bitcoin.OutputOpType:
|
||||||
size += lbry.OutputOverhead
|
size += bitcoin.OutputOverhead
|
||||||
addr, err := btcutil.DecodeAddress(operation.Account.Address, s.config.Params)
|
addr, err := btcutil.DecodeAddress(operation.Account.Address, s.config.Params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
size += lbry.P2PKHScriptPubkeySize
|
size += bitcoin.P2PKHScriptPubkeySize
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
script, err := txscript.PayToAddrScript(addr)
|
script, err := txscript.PayToAddrScript(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
size += lbry.P2PKHScriptPubkeySize
|
size += bitcoin.P2PKHScriptPubkeySize
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ func (s *ConstructionAPIService) ConstructionPreprocess(
|
||||||
descriptions := &parser.Descriptions{
|
descriptions := &parser.Descriptions{
|
||||||
OperationDescriptions: []*parser.OperationDescription{
|
OperationDescriptions: []*parser.OperationDescription{
|
||||||
{
|
{
|
||||||
Type: lbry.InputOpType,
|
Type: bitcoin.InputOpType,
|
||||||
Account: &parser.AccountDescription{
|
Account: &parser.AccountDescription{
|
||||||
Exists: true,
|
Exists: true,
|
||||||
},
|
},
|
||||||
|
@ -192,12 +192,12 @@ func (s *ConstructionAPIService) ConstructionMetadata(
|
||||||
if options.FeeMultiplier != nil {
|
if options.FeeMultiplier != nil {
|
||||||
feePerKB *= *options.FeeMultiplier
|
feePerKB *= *options.FeeMultiplier
|
||||||
}
|
}
|
||||||
if feePerKB < lbry.MinFeeRate {
|
if feePerKB < bitcoin.MinFeeRate {
|
||||||
feePerKB = lbry.MinFeeRate
|
feePerKB = bitcoin.MinFeeRate
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculated the estimated fee in Satoshis
|
// Calculated the estimated fee in Satoshis
|
||||||
satoshisPerB := (feePerKB * float64(lbry.SatoshisInlbry)) / bytesInKb
|
satoshisPerB := (feePerKB * float64(bitcoin.SatoshisInBitcoin)) / bytesInKb
|
||||||
estimatedFee := satoshisPerB * options.EstimatedSize
|
estimatedFee := satoshisPerB * options.EstimatedSize
|
||||||
suggestedFee := &types.Amount{
|
suggestedFee := &types.Amount{
|
||||||
Value: fmt.Sprintf("%d", int64(estimatedFee)),
|
Value: fmt.Sprintf("%d", int64(estimatedFee)),
|
||||||
|
@ -228,7 +228,7 @@ func (s *ConstructionAPIService) ConstructionPayloads(
|
||||||
descriptions := &parser.Descriptions{
|
descriptions := &parser.Descriptions{
|
||||||
OperationDescriptions: []*parser.OperationDescription{
|
OperationDescriptions: []*parser.OperationDescription{
|
||||||
{
|
{
|
||||||
Type: lbry.InputOpType,
|
Type: bitcoin.InputOpType,
|
||||||
Account: &parser.AccountDescription{
|
Account: &parser.AccountDescription{
|
||||||
Exists: true,
|
Exists: true,
|
||||||
},
|
},
|
||||||
|
@ -241,7 +241,7 @@ func (s *ConstructionAPIService) ConstructionPayloads(
|
||||||
CoinAction: types.CoinSpent,
|
CoinAction: types.CoinSpent,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: lbry.OutputOpType,
|
Type: bitcoin.OutputOpType,
|
||||||
Account: &parser.AccountDescription{
|
Account: &parser.AccountDescription{
|
||||||
Exists: true,
|
Exists: true,
|
||||||
},
|
},
|
||||||
|
@ -267,7 +267,7 @@ func (s *ConstructionAPIService) ConstructionPayloads(
|
||||||
return nil, wrapErr(ErrUnclearIntent, errors.New("CoinChange cannot be nil"))
|
return nil, wrapErr(ErrUnclearIntent, errors.New("CoinChange cannot be nil"))
|
||||||
}
|
}
|
||||||
|
|
||||||
transactionHash, index, err := lbry.ParseCoinIdentifier(input.CoinChange.CoinIdentifier)
|
transactionHash, index, err := bitcoin.ParseCoinIdentifier(input.CoinChange.CoinIdentifier)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, wrapErr(ErrInvalidCoin, err)
|
return nil, wrapErr(ErrInvalidCoin, err)
|
||||||
}
|
}
|
||||||
|
@ -324,7 +324,7 @@ func (s *ConstructionAPIService) ConstructionPayloads(
|
||||||
return nil, wrapErr(ErrUnableToDecodeScriptPubKey, err)
|
return nil, wrapErr(ErrUnableToDecodeScriptPubKey, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
class, _, err := lbry.ParseSingleAddress(s.config.Params, script)
|
class, _, err := bitcoin.ParseSingleAddress(s.config.Params, script)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, wrapErr(
|
return nil, wrapErr(
|
||||||
ErrUnableToDecodeAddress,
|
ErrUnableToDecodeAddress,
|
||||||
|
@ -413,7 +413,7 @@ func (s *ConstructionAPIService) ConstructionCombine(
|
||||||
if err := json.Unmarshal(decodedTx, &unsigned); err != nil {
|
if err := json.Unmarshal(decodedTx, &unsigned); err != nil {
|
||||||
return nil, wrapErr(
|
return nil, wrapErr(
|
||||||
ErrUnableToParseIntermediateResult,
|
ErrUnableToParseIntermediateResult,
|
||||||
fmt.Errorf("%w unable to unmarshal lbry transaction", err),
|
fmt.Errorf("%w unable to unmarshal bitcoin transaction", err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,7 +439,7 @@ func (s *ConstructionAPIService) ConstructionCombine(
|
||||||
return nil, wrapErr(ErrUnableToDecodeScriptPubKey, err)
|
return nil, wrapErr(ErrUnableToDecodeScriptPubKey, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
class, _, err := lbry.ParseSingleAddress(s.config.Params, decodedScript)
|
class, _, err := bitcoin.ParseSingleAddress(s.config.Params, decodedScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, wrapErr(
|
return nil, wrapErr(
|
||||||
ErrUnableToDecodeAddress,
|
ErrUnableToDecodeAddress,
|
||||||
|
@ -499,7 +499,7 @@ func (s *ConstructionAPIService) ConstructionHash(
|
||||||
if err := json.Unmarshal(decodedTx, &signed); err != nil {
|
if err := json.Unmarshal(decodedTx, &signed); err != nil {
|
||||||
return nil, wrapErr(
|
return nil, wrapErr(
|
||||||
ErrUnableToParseIntermediateResult,
|
ErrUnableToParseIntermediateResult,
|
||||||
fmt.Errorf("%w unable to unmarshal signed lbry transaction", err),
|
fmt.Errorf("%w unable to unmarshal signed bitcoin transaction", err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,7 +541,7 @@ func (s *ConstructionAPIService) parseUnsignedTransaction(
|
||||||
if err := json.Unmarshal(decodedTx, &unsigned); err != nil {
|
if err := json.Unmarshal(decodedTx, &unsigned); err != nil {
|
||||||
return nil, wrapErr(
|
return nil, wrapErr(
|
||||||
ErrUnableToParseIntermediateResult,
|
ErrUnableToParseIntermediateResult,
|
||||||
fmt.Errorf("%w unable to unmarshal lbry transaction", err),
|
fmt.Errorf("%w unable to unmarshal bitcoin transaction", err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,7 +569,7 @@ func (s *ConstructionAPIService) parseUnsignedTransaction(
|
||||||
Index: int64(len(ops)),
|
Index: int64(len(ops)),
|
||||||
NetworkIndex: &networkIndex,
|
NetworkIndex: &networkIndex,
|
||||||
},
|
},
|
||||||
Type: lbry.InputOpType,
|
Type: bitcoin.InputOpType,
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: unsigned.InputAddresses[i],
|
Address: unsigned.InputAddresses[i],
|
||||||
},
|
},
|
||||||
|
@ -592,7 +592,7 @@ func (s *ConstructionAPIService) parseUnsignedTransaction(
|
||||||
|
|
||||||
for i, output := range tx.TxOut {
|
for i, output := range tx.TxOut {
|
||||||
networkIndex := int64(i)
|
networkIndex := int64(i)
|
||||||
_, addr, err := lbry.ParseSingleAddress(s.config.Params, output.PkScript)
|
_, addr, err := bitcoin.ParseSingleAddress(s.config.Params, output.PkScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, wrapErr(
|
return nil, wrapErr(
|
||||||
ErrUnableToDecodeAddress,
|
ErrUnableToDecodeAddress,
|
||||||
|
@ -605,7 +605,7 @@ func (s *ConstructionAPIService) parseUnsignedTransaction(
|
||||||
Index: int64(len(ops)),
|
Index: int64(len(ops)),
|
||||||
NetworkIndex: &networkIndex,
|
NetworkIndex: &networkIndex,
|
||||||
},
|
},
|
||||||
Type: lbry.OutputOpType,
|
Type: bitcoin.OutputOpType,
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: addr.String(),
|
Address: addr.String(),
|
||||||
},
|
},
|
||||||
|
@ -637,7 +637,7 @@ func (s *ConstructionAPIService) parseSignedTransaction(
|
||||||
if err := json.Unmarshal(decodedTx, &signed); err != nil {
|
if err := json.Unmarshal(decodedTx, &signed); err != nil {
|
||||||
return nil, wrapErr(
|
return nil, wrapErr(
|
||||||
ErrUnableToParseIntermediateResult,
|
ErrUnableToParseIntermediateResult,
|
||||||
fmt.Errorf("%w unable to unmarshal signed lbry transaction", err),
|
fmt.Errorf("%w unable to unmarshal signed bitcoin transaction", err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -668,7 +668,7 @@ func (s *ConstructionAPIService) parseSignedTransaction(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, addr, err := lbry.ParseSingleAddress(s.config.Params, pkScript.Script())
|
_, addr, err := bitcoin.ParseSingleAddress(s.config.Params, pkScript.Script())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, wrapErr(
|
return nil, wrapErr(
|
||||||
ErrUnableToDecodeAddress,
|
ErrUnableToDecodeAddress,
|
||||||
|
@ -685,7 +685,7 @@ func (s *ConstructionAPIService) parseSignedTransaction(
|
||||||
Index: int64(len(ops)),
|
Index: int64(len(ops)),
|
||||||
NetworkIndex: &networkIndex,
|
NetworkIndex: &networkIndex,
|
||||||
},
|
},
|
||||||
Type: lbry.InputOpType,
|
Type: bitcoin.InputOpType,
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: addr.EncodeAddress(),
|
Address: addr.EncodeAddress(),
|
||||||
},
|
},
|
||||||
|
@ -708,7 +708,7 @@ func (s *ConstructionAPIService) parseSignedTransaction(
|
||||||
|
|
||||||
for i, output := range tx.TxOut {
|
for i, output := range tx.TxOut {
|
||||||
networkIndex := int64(i)
|
networkIndex := int64(i)
|
||||||
_, addr, err := lbry.ParseSingleAddress(s.config.Params, output.PkScript)
|
_, addr, err := bitcoin.ParseSingleAddress(s.config.Params, output.PkScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, wrapErr(
|
return nil, wrapErr(
|
||||||
ErrUnableToDecodeAddress,
|
ErrUnableToDecodeAddress,
|
||||||
|
@ -721,7 +721,7 @@ func (s *ConstructionAPIService) parseSignedTransaction(
|
||||||
Index: int64(len(ops)),
|
Index: int64(len(ops)),
|
||||||
NetworkIndex: &networkIndex,
|
NetworkIndex: &networkIndex,
|
||||||
},
|
},
|
||||||
Type: lbry.OutputOpType,
|
Type: bitcoin.OutputOpType,
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: addr.String(),
|
Address: addr.String(),
|
||||||
},
|
},
|
||||||
|
@ -771,13 +771,13 @@ func (s *ConstructionAPIService) ConstructionSubmit(
|
||||||
if err := json.Unmarshal(decodedTx, &signed); err != nil {
|
if err := json.Unmarshal(decodedTx, &signed); err != nil {
|
||||||
return nil, wrapErr(
|
return nil, wrapErr(
|
||||||
ErrUnableToParseIntermediateResult,
|
ErrUnableToParseIntermediateResult,
|
||||||
fmt.Errorf("%w unable to unmarshal signed lbry transaction", err),
|
fmt.Errorf("%w unable to unmarshal signed bitcoin transaction", err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
txHash, err := s.client.SendRawTransaction(ctx, signed.Transaction)
|
txHash, err := s.client.SendRawTransaction(ctx, signed.Transaction)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, wrapErr(ErrLbrycrdd, fmt.Errorf("%w unable to submit transaction", err))
|
return nil, wrapErr(ErrBitcoind, fmt.Errorf("%w unable to submit transaction", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
return &types.TransactionIdentifierResponse{
|
return &types.TransactionIdentifierResponse{
|
||||||
|
|
|
@ -19,9 +19,9 @@ import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/lbryio/rosetta-lbry/configuration"
|
"github.com/coinbase/rosetta-bitcoin/bitcoin"
|
||||||
"github.com/lbryio/rosetta-lbry/lbry"
|
"github.com/coinbase/rosetta-bitcoin/configuration"
|
||||||
mocks "github.com/lbryio/rosetta-lbry/mocks/services"
|
mocks "github.com/coinbase/rosetta-bitcoin/mocks/services"
|
||||||
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/types"
|
"github.com/coinbase/rosetta-sdk-go/types"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -47,15 +47,15 @@ func forceMarshalMap(t *testing.T, i interface{}) map[string]interface{} {
|
||||||
|
|
||||||
func TestConstructionService(t *testing.T) {
|
func TestConstructionService(t *testing.T) {
|
||||||
networkIdentifier = &types.NetworkIdentifier{
|
networkIdentifier = &types.NetworkIdentifier{
|
||||||
Network: lbry.TestnetNetwork,
|
Network: bitcoin.TestnetNetwork,
|
||||||
Blockchain: lbry.Blockchain,
|
Blockchain: bitcoin.Blockchain,
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := &configuration.Configuration{
|
cfg := &configuration.Configuration{
|
||||||
Mode: configuration.Online,
|
Mode: configuration.Online,
|
||||||
Network: networkIdentifier,
|
Network: networkIdentifier,
|
||||||
Params: lbry.TestnetParams,
|
Params: bitcoin.TestnetParams,
|
||||||
Currency: lbry.TestnetCurrency,
|
Currency: bitcoin.TestnetCurrency,
|
||||||
}
|
}
|
||||||
|
|
||||||
mockIndexer := &mocks.Indexer{}
|
mockIndexer := &mocks.Indexer{}
|
||||||
|
@ -88,13 +88,13 @@ func TestConstructionService(t *testing.T) {
|
||||||
OperationIdentifier: &types.OperationIdentifier{
|
OperationIdentifier: &types.OperationIdentifier{
|
||||||
Index: 0,
|
Index: 0,
|
||||||
},
|
},
|
||||||
Type: lbry.InputOpType,
|
Type: bitcoin.InputOpType,
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: "tb1qcqzmqzkswhfshzd8kedhmtvgnxax48z4fklhvm",
|
Address: "tb1qcqzmqzkswhfshzd8kedhmtvgnxax48z4fklhvm",
|
||||||
},
|
},
|
||||||
Amount: &types.Amount{
|
Amount: &types.Amount{
|
||||||
Value: "-1000000",
|
Value: "-1000000",
|
||||||
Currency: lbry.TestnetCurrency,
|
Currency: bitcoin.TestnetCurrency,
|
||||||
},
|
},
|
||||||
CoinChange: &types.CoinChange{
|
CoinChange: &types.CoinChange{
|
||||||
CoinIdentifier: &types.CoinIdentifier{
|
CoinIdentifier: &types.CoinIdentifier{
|
||||||
|
@ -107,26 +107,26 @@ func TestConstructionService(t *testing.T) {
|
||||||
OperationIdentifier: &types.OperationIdentifier{
|
OperationIdentifier: &types.OperationIdentifier{
|
||||||
Index: 1,
|
Index: 1,
|
||||||
},
|
},
|
||||||
Type: lbry.OutputOpType,
|
Type: bitcoin.OutputOpType,
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: "tb1q3r8xjf0c2yazxnq9ey3wayelygfjxpfqjvj5v7",
|
Address: "tb1q3r8xjf0c2yazxnq9ey3wayelygfjxpfqjvj5v7",
|
||||||
},
|
},
|
||||||
Amount: &types.Amount{
|
Amount: &types.Amount{
|
||||||
Value: "954843",
|
Value: "954843",
|
||||||
Currency: lbry.TestnetCurrency,
|
Currency: bitcoin.TestnetCurrency,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
OperationIdentifier: &types.OperationIdentifier{
|
OperationIdentifier: &types.OperationIdentifier{
|
||||||
Index: 2,
|
Index: 2,
|
||||||
},
|
},
|
||||||
Type: lbry.OutputOpType,
|
Type: bitcoin.OutputOpType,
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: "tb1qjsrjvk2ug872pdypp33fjxke62y7awpgefr6ua",
|
Address: "tb1qjsrjvk2ug872pdypp33fjxke62y7awpgefr6ua",
|
||||||
},
|
},
|
||||||
Amount: &types.Amount{
|
Amount: &types.Amount{
|
||||||
Value: "44657",
|
Value: "44657",
|
||||||
Currency: lbry.TestnetCurrency,
|
Currency: bitcoin.TestnetCurrency,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -148,7 +148,7 @@ func TestConstructionService(t *testing.T) {
|
||||||
},
|
},
|
||||||
Amount: &types.Amount{
|
Amount: &types.Amount{
|
||||||
Value: "-1000000",
|
Value: "-1000000",
|
||||||
Currency: lbry.TestnetCurrency,
|
Currency: bitcoin.TestnetCurrency,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -161,7 +161,7 @@ func TestConstructionService(t *testing.T) {
|
||||||
|
|
||||||
// Test Metadata
|
// Test Metadata
|
||||||
metadata := &constructionMetadata{
|
metadata := &constructionMetadata{
|
||||||
ScriptPubKeys: []*lbry.ScriptPubKey{
|
ScriptPubKeys: []*bitcoin.ScriptPubKey{
|
||||||
{
|
{
|
||||||
ASM: "0 c005b00ad075d30b89a7b65b7dad8899ba6a9c55",
|
ASM: "0 c005b00ad075d30b89a7b65b7dad8899ba6a9c55",
|
||||||
Hex: "0014c005b00ad075d30b89a7b65b7dad8899ba6a9c55",
|
Hex: "0014c005b00ad075d30b89a7b65b7dad8899ba6a9c55",
|
||||||
|
@ -188,7 +188,7 @@ func TestConstructionService(t *testing.T) {
|
||||||
ctx,
|
ctx,
|
||||||
defaultConfirmationTarget,
|
defaultConfirmationTarget,
|
||||||
).Return(
|
).Return(
|
||||||
lbry.MinFeeRate*10,
|
bitcoin.MinFeeRate*10,
|
||||||
nil,
|
nil,
|
||||||
).Once()
|
).Once()
|
||||||
metadataResponse, err := servicer.ConstructionMetadata(ctx, &types.ConstructionMetadataRequest{
|
metadataResponse, err := servicer.ConstructionMetadata(ctx, &types.ConstructionMetadataRequest{
|
||||||
|
@ -201,7 +201,7 @@ func TestConstructionService(t *testing.T) {
|
||||||
SuggestedFee: []*types.Amount{
|
SuggestedFee: []*types.Amount{
|
||||||
{
|
{
|
||||||
Value: "1065", // 1,420 * 0.75
|
Value: "1065", // 1,420 * 0.75
|
||||||
Currency: lbry.TestnetCurrency,
|
Currency: bitcoin.TestnetCurrency,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, metadataResponse)
|
}, metadataResponse)
|
||||||
|
@ -220,7 +220,7 @@ func TestConstructionService(t *testing.T) {
|
||||||
ctx,
|
ctx,
|
||||||
defaultConfirmationTarget,
|
defaultConfirmationTarget,
|
||||||
).Return(
|
).Return(
|
||||||
lbry.MinFeeRate,
|
bitcoin.MinFeeRate,
|
||||||
nil,
|
nil,
|
||||||
).Once()
|
).Once()
|
||||||
metadataResponse, err = servicer.ConstructionMetadata(ctx, &types.ConstructionMetadataRequest{
|
metadataResponse, err = servicer.ConstructionMetadata(ctx, &types.ConstructionMetadataRequest{
|
||||||
|
@ -233,7 +233,7 @@ func TestConstructionService(t *testing.T) {
|
||||||
SuggestedFee: []*types.Amount{
|
SuggestedFee: []*types.Amount{
|
||||||
{
|
{
|
||||||
Value: "142", // we don't go below minimum fee rate
|
Value: "142", // we don't go below minimum fee rate
|
||||||
Currency: lbry.TestnetCurrency,
|
Currency: bitcoin.TestnetCurrency,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, metadataResponse)
|
}, metadataResponse)
|
||||||
|
@ -253,13 +253,13 @@ func TestConstructionService(t *testing.T) {
|
||||||
Index: 0,
|
Index: 0,
|
||||||
NetworkIndex: &val0,
|
NetworkIndex: &val0,
|
||||||
},
|
},
|
||||||
Type: lbry.InputOpType,
|
Type: bitcoin.InputOpType,
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: "tb1qcqzmqzkswhfshzd8kedhmtvgnxax48z4fklhvm",
|
Address: "tb1qcqzmqzkswhfshzd8kedhmtvgnxax48z4fklhvm",
|
||||||
},
|
},
|
||||||
Amount: &types.Amount{
|
Amount: &types.Amount{
|
||||||
Value: "-1000000",
|
Value: "-1000000",
|
||||||
Currency: lbry.TestnetCurrency,
|
Currency: bitcoin.TestnetCurrency,
|
||||||
},
|
},
|
||||||
CoinChange: &types.CoinChange{
|
CoinChange: &types.CoinChange{
|
||||||
CoinIdentifier: &types.CoinIdentifier{
|
CoinIdentifier: &types.CoinIdentifier{
|
||||||
|
@ -273,13 +273,13 @@ func TestConstructionService(t *testing.T) {
|
||||||
Index: 1,
|
Index: 1,
|
||||||
NetworkIndex: &val0,
|
NetworkIndex: &val0,
|
||||||
},
|
},
|
||||||
Type: lbry.OutputOpType,
|
Type: bitcoin.OutputOpType,
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: "tb1q3r8xjf0c2yazxnq9ey3wayelygfjxpfqjvj5v7",
|
Address: "tb1q3r8xjf0c2yazxnq9ey3wayelygfjxpfqjvj5v7",
|
||||||
},
|
},
|
||||||
Amount: &types.Amount{
|
Amount: &types.Amount{
|
||||||
Value: "954843",
|
Value: "954843",
|
||||||
Currency: lbry.TestnetCurrency,
|
Currency: bitcoin.TestnetCurrency,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -287,13 +287,13 @@ func TestConstructionService(t *testing.T) {
|
||||||
Index: 2,
|
Index: 2,
|
||||||
NetworkIndex: &val1,
|
NetworkIndex: &val1,
|
||||||
},
|
},
|
||||||
Type: lbry.OutputOpType,
|
Type: bitcoin.OutputOpType,
|
||||||
Account: &types.AccountIdentifier{
|
Account: &types.AccountIdentifier{
|
||||||
Address: "tb1qjsrjvk2ug872pdypp33fjxke62y7awpgefr6ua",
|
Address: "tb1qjsrjvk2ug872pdypp33fjxke62y7awpgefr6ua",
|
||||||
},
|
},
|
||||||
Amount: &types.Amount{
|
Amount: &types.Amount{
|
||||||
Value: "44657",
|
Value: "44657",
|
||||||
Currency: lbry.TestnetCurrency,
|
Currency: bitcoin.TestnetCurrency,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -376,11 +376,11 @@ func TestConstructionService(t *testing.T) {
|
||||||
}, hashResponse)
|
}, hashResponse)
|
||||||
|
|
||||||
// Test Submit
|
// Test Submit
|
||||||
lbryTransaction := "010000000001017f9cf50b02dd5258f80cd5c3437302e027dd1336172a20cdc80305c5a55741b10100000000ffffffff02db910e000000000016001488ce6925f8513a234c05c922ee933f221323052071ae000000000000160014940726595c41fca0b4810c62991ad9d289eeb82802473044022025876ec8b9f51d343a5a56ac549c0c828005ef45ebe9da166db645c09157223f02204cd08b7278a8889a81135915bce10d1ef3bb92b217f81a0de7e79ffb3dfd6ac501210325c9a4252789b31dbb3454ec647e9516e7c596bcde2bd5da71a60fab8644e43800000000" // nolint
|
bitcoinTransaction := "010000000001017f9cf50b02dd5258f80cd5c3437302e027dd1336172a20cdc80305c5a55741b10100000000ffffffff02db910e000000000016001488ce6925f8513a234c05c922ee933f221323052071ae000000000000160014940726595c41fca0b4810c62991ad9d289eeb82802473044022025876ec8b9f51d343a5a56ac549c0c828005ef45ebe9da166db645c09157223f02204cd08b7278a8889a81135915bce10d1ef3bb92b217f81a0de7e79ffb3dfd6ac501210325c9a4252789b31dbb3454ec647e9516e7c596bcde2bd5da71a60fab8644e43800000000" // nolint
|
||||||
mockClient.On(
|
mockClient.On(
|
||||||
"SendRawTransaction",
|
"SendRawTransaction",
|
||||||
ctx,
|
ctx,
|
||||||
lbryTransaction,
|
bitcoinTransaction,
|
||||||
).Return(
|
).Return(
|
||||||
transactionIdentifier.Hash,
|
transactionIdentifier.Hash,
|
||||||
nil,
|
nil,
|
||||||
|
|
|
@ -25,7 +25,7 @@ var (
|
||||||
ErrUnimplemented,
|
ErrUnimplemented,
|
||||||
ErrUnavailableOffline,
|
ErrUnavailableOffline,
|
||||||
ErrNotReady,
|
ErrNotReady,
|
||||||
ErrLbrycrdd,
|
ErrBitcoind,
|
||||||
ErrBlockNotFound,
|
ErrBlockNotFound,
|
||||||
ErrUnableToDerive,
|
ErrUnableToDerive,
|
||||||
ErrUnclearIntent,
|
ErrUnclearIntent,
|
||||||
|
@ -57,19 +57,19 @@ var (
|
||||||
Message: "Endpoint unavailable offline",
|
Message: "Endpoint unavailable offline",
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrNotReady is returned when Lbrycrdd is not
|
// ErrNotReady is returned when bitcoind is not
|
||||||
// yet ready to serve queries.
|
// yet ready to serve queries.
|
||||||
ErrNotReady = &types.Error{
|
ErrNotReady = &types.Error{
|
||||||
Code: 2, //nolint
|
Code: 2, //nolint
|
||||||
Message: "Lbrycrdd is not ready",
|
Message: "Bitcoind is not ready",
|
||||||
Retriable: true,
|
Retriable: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrLbrycrdd is returned when lbrycrdd
|
// ErrBitcoind is returned when bitcoind
|
||||||
// errors on a request.
|
// errors on a request.
|
||||||
ErrLbrycrdd = &types.Error{
|
ErrBitcoind = &types.Error{
|
||||||
Code: 3, //nolint
|
Code: 3, //nolint
|
||||||
Message: "LBRYcrdd error",
|
Message: "Bitcoind error",
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrBlockNotFound is returned when a block
|
// ErrBlockNotFound is returned when a block
|
||||||
|
@ -104,7 +104,7 @@ var (
|
||||||
|
|
||||||
// ErrScriptPubKeysMissing is returned when
|
// ErrScriptPubKeysMissing is returned when
|
||||||
// the indexer cannot populate the required
|
// the indexer cannot populate the required
|
||||||
// lbry.ScriptPubKeys to construct a transaction.
|
// bitcoin.ScriptPubKeys to construct a transaction.
|
||||||
ErrScriptPubKeysMissing = &types.Error{
|
ErrScriptPubKeysMissing = &types.Error{
|
||||||
Code: 8, //nolint
|
Code: 8, //nolint
|
||||||
Message: "Missing ScriptPubKeys",
|
Message: "Missing ScriptPubKeys",
|
||||||
|
@ -125,7 +125,7 @@ var (
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrUnableToDecodeScriptPubKey is returned when a
|
// ErrUnableToDecodeScriptPubKey is returned when a
|
||||||
// lbry.ScriptPubKey cannot be parsed during construction.
|
// bitcoin.ScriptPubKey cannot be parsed during construction.
|
||||||
ErrUnableToDecodeScriptPubKey = &types.Error{
|
ErrUnableToDecodeScriptPubKey = &types.Error{
|
||||||
Code: 11, //nolint
|
Code: 11, //nolint
|
||||||
Message: "Unable to decode ScriptPubKey",
|
Message: "Unable to decode ScriptPubKey",
|
||||||
|
|
|
@ -17,7 +17,7 @@ package services
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/lbryio/rosetta-lbry/configuration"
|
"github.com/coinbase/rosetta-bitcoin/configuration"
|
||||||
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/server"
|
"github.com/coinbase/rosetta-sdk-go/server"
|
||||||
"github.com/coinbase/rosetta-sdk-go/types"
|
"github.com/coinbase/rosetta-sdk-go/types"
|
||||||
|
@ -51,7 +51,7 @@ func (s *MempoolAPIService) Mempool(
|
||||||
|
|
||||||
mempoolTransactions, err := s.client.RawMempool(ctx)
|
mempoolTransactions, err := s.client.RawMempool(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, wrapErr(ErrLbrycrdd, err)
|
return nil, wrapErr(ErrBitcoind, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
transactionIdentifiers := make([]*types.TransactionIdentifier, len(mempoolTransactions))
|
transactionIdentifiers := make([]*types.TransactionIdentifier, len(mempoolTransactions))
|
||||||
|
|
|
@ -18,8 +18,8 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/lbryio/rosetta-lbry/configuration"
|
"github.com/coinbase/rosetta-bitcoin/configuration"
|
||||||
mocks "github.com/lbryio/rosetta-lbry/mocks/services"
|
mocks "github.com/coinbase/rosetta-bitcoin/mocks/services"
|
||||||
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/types"
|
"github.com/coinbase/rosetta-sdk-go/types"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
|
@ -17,8 +17,8 @@ package services
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/lbryio/rosetta-lbry/configuration"
|
"github.com/coinbase/rosetta-bitcoin/bitcoin"
|
||||||
"github.com/lbryio/rosetta-lbry/lbry"
|
"github.com/coinbase/rosetta-bitcoin/configuration"
|
||||||
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/server"
|
"github.com/coinbase/rosetta-sdk-go/server"
|
||||||
"github.com/coinbase/rosetta-sdk-go/types"
|
"github.com/coinbase/rosetta-sdk-go/types"
|
||||||
|
@ -67,7 +67,7 @@ func (s *NetworkAPIService) NetworkStatus(
|
||||||
|
|
||||||
peers, err := s.client.GetPeers(ctx)
|
peers, err := s.client.GetPeers(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, wrapErr(ErrLbrycrdd, err)
|
return nil, wrapErr(ErrBitcoind, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cachedBlockResponse, err := s.i.GetBlockLazy(ctx, nil)
|
cachedBlockResponse, err := s.i.GetBlockLazy(ctx, nil)
|
||||||
|
@ -92,14 +92,13 @@ func (s *NetworkAPIService) NetworkOptions(
|
||||||
Version: &types.Version{
|
Version: &types.Version{
|
||||||
RosettaVersion: types.RosettaAPIVersion,
|
RosettaVersion: types.RosettaAPIVersion,
|
||||||
NodeVersion: NodeVersion,
|
NodeVersion: NodeVersion,
|
||||||
MiddlewareVersion: types.String(MiddlewareVersion),
|
MiddlewareVersion: &MiddlewareVersion,
|
||||||
},
|
},
|
||||||
Allow: &types.Allow{
|
Allow: &types.Allow{
|
||||||
OperationStatuses: lbry.OperationStatuses,
|
OperationStatuses: bitcoin.OperationStatuses,
|
||||||
OperationTypes: lbry.OperationTypes,
|
OperationTypes: bitcoin.OperationTypes,
|
||||||
Errors: Errors,
|
Errors: Errors,
|
||||||
HistoricalBalanceLookup: HistoricalBalanceLookup,
|
HistoricalBalanceLookup: HistoricalBalanceLookup,
|
||||||
MempoolCoins: MempoolCoins,
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,16 +18,16 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/lbryio/rosetta-lbry/configuration"
|
"github.com/coinbase/rosetta-bitcoin/bitcoin"
|
||||||
"github.com/lbryio/rosetta-lbry/lbry"
|
"github.com/coinbase/rosetta-bitcoin/configuration"
|
||||||
mocks "github.com/lbryio/rosetta-lbry/mocks/services"
|
mocks "github.com/coinbase/rosetta-bitcoin/mocks/services"
|
||||||
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/types"
|
"github.com/coinbase/rosetta-sdk-go/types"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
middlewareVersion = "0.0.8"
|
middlewareVersion = "0.0.5"
|
||||||
defaultNetworkOptions = &types.NetworkOptionsResponse{
|
defaultNetworkOptions = &types.NetworkOptionsResponse{
|
||||||
Version: &types.Version{
|
Version: &types.Version{
|
||||||
RosettaVersion: types.RosettaAPIVersion,
|
RosettaVersion: types.RosettaAPIVersion,
|
||||||
|
@ -35,16 +35,16 @@ var (
|
||||||
MiddlewareVersion: &middlewareVersion,
|
MiddlewareVersion: &middlewareVersion,
|
||||||
},
|
},
|
||||||
Allow: &types.Allow{
|
Allow: &types.Allow{
|
||||||
OperationStatuses: lbry.OperationStatuses,
|
OperationStatuses: bitcoin.OperationStatuses,
|
||||||
OperationTypes: lbry.OperationTypes,
|
OperationTypes: bitcoin.OperationTypes,
|
||||||
Errors: Errors,
|
Errors: Errors,
|
||||||
HistoricalBalanceLookup: HistoricalBalanceLookup,
|
HistoricalBalanceLookup: HistoricalBalanceLookup,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
networkIdentifier = &types.NetworkIdentifier{
|
networkIdentifier = &types.NetworkIdentifier{
|
||||||
Network: lbry.MainnetNetwork,
|
Network: bitcoin.MainnetNetwork,
|
||||||
Blockchain: lbry.Blockchain,
|
Blockchain: bitcoin.Blockchain,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ func TestNetworkEndpoints_Online(t *testing.T) {
|
||||||
cfg := &configuration.Configuration{
|
cfg := &configuration.Configuration{
|
||||||
Mode: configuration.Online,
|
Mode: configuration.Online,
|
||||||
Network: networkIdentifier,
|
Network: networkIdentifier,
|
||||||
GenesisBlockIdentifier: lbry.MainnetGenesisBlockIdentifier,
|
GenesisBlockIdentifier: bitcoin.MainnetGenesisBlockIdentifier,
|
||||||
}
|
}
|
||||||
mockIndexer := &mocks.Indexer{}
|
mockIndexer := &mocks.Indexer{}
|
||||||
mockClient := &mocks.Client{}
|
mockClient := &mocks.Client{}
|
||||||
|
@ -104,7 +104,7 @@ func TestNetworkEndpoints_Online(t *testing.T) {
|
||||||
}
|
}
|
||||||
mockClient.On("GetPeers", ctx).Return([]*types.Peer{
|
mockClient.On("GetPeers", ctx).Return([]*types.Peer{
|
||||||
{
|
{
|
||||||
PeerID: "34.231.101.5:9246",
|
PeerID: "77.93.223.9:8333",
|
||||||
},
|
},
|
||||||
}, nil)
|
}, nil)
|
||||||
mockIndexer.On(
|
mockIndexer.On(
|
||||||
|
@ -118,11 +118,11 @@ func TestNetworkEndpoints_Online(t *testing.T) {
|
||||||
networkStatus, err := servicer.NetworkStatus(ctx, nil)
|
networkStatus, err := servicer.NetworkStatus(ctx, nil)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, &types.NetworkStatusResponse{
|
assert.Equal(t, &types.NetworkStatusResponse{
|
||||||
GenesisBlockIdentifier: lbry.MainnetGenesisBlockIdentifier,
|
GenesisBlockIdentifier: bitcoin.MainnetGenesisBlockIdentifier,
|
||||||
CurrentBlockIdentifier: blockResponse.Block.BlockIdentifier,
|
CurrentBlockIdentifier: blockResponse.Block.BlockIdentifier,
|
||||||
Peers: []*types.Peer{
|
Peers: []*types.Peer{
|
||||||
{
|
{
|
||||||
PeerID: "34.231.101.5:9246",
|
PeerID: "77.93.223.9:8333",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, networkStatus)
|
}, networkStatus)
|
||||||
|
|
|
@ -17,7 +17,7 @@ package services
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/lbryio/rosetta-lbry/configuration"
|
"github.com/coinbase/rosetta-bitcoin/configuration"
|
||||||
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/asserter"
|
"github.com/coinbase/rosetta-sdk-go/asserter"
|
||||||
"github.com/coinbase/rosetta-sdk-go/server"
|
"github.com/coinbase/rosetta-sdk-go/server"
|
||||||
|
|
|
@ -17,35 +17,32 @@ package services
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/lbryio/rosetta-lbry/lbry"
|
"github.com/coinbase/rosetta-bitcoin/bitcoin"
|
||||||
|
|
||||||
"github.com/coinbase/rosetta-sdk-go/types"
|
"github.com/coinbase/rosetta-sdk-go/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// NodeVersion is the version of
|
// NodeVersion is the version of
|
||||||
// lbry core we are using.
|
// bitcoin core we are using.
|
||||||
NodeVersion = "0.19.1.2"
|
NodeVersion = "0.20.1"
|
||||||
|
|
||||||
// HistoricalBalanceLookup indicates
|
// HistoricalBalanceLookup indicates
|
||||||
// that historical balance lookup is supported.
|
// that historical balance lookup is supported.
|
||||||
HistoricalBalanceLookup = true
|
HistoricalBalanceLookup = true
|
||||||
|
|
||||||
// MempoolCoins indicates that
|
|
||||||
// including mempool coins in the /account/coins
|
|
||||||
// response is not supported.
|
|
||||||
MempoolCoins = false
|
|
||||||
|
|
||||||
// inlineFetchLimit is the maximum number
|
// inlineFetchLimit is the maximum number
|
||||||
// of transactions to fetch inline.
|
// of transactions to fetch inline.
|
||||||
inlineFetchLimit = 100
|
inlineFetchLimit = 100
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
// MiddlewareVersion is the version
|
// MiddlewareVersion is the version
|
||||||
// of rosetta-lbry. We set this as a
|
// of rosetta-bitcoin. We set this as a
|
||||||
// variable instead of a constant because
|
// variable instead of a constant because
|
||||||
// we typically need the pointer of this
|
// we typically need the pointer of this
|
||||||
// value.
|
// value.
|
||||||
MiddlewareVersion = "0.0.8"
|
MiddlewareVersion = "0.0.5"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client is used by the servicers to get Peer information
|
// Client is used by the servicers to get Peer information
|
||||||
|
@ -75,7 +72,7 @@ type Indexer interface {
|
||||||
GetScriptPubKeys(
|
GetScriptPubKeys(
|
||||||
context.Context,
|
context.Context,
|
||||||
[]*types.Coin,
|
[]*types.Coin,
|
||||||
) ([]*lbry.ScriptPubKey, error)
|
) ([]*bitcoin.ScriptPubKey, error)
|
||||||
GetBalance(
|
GetBalance(
|
||||||
context.Context,
|
context.Context,
|
||||||
*types.AccountIdentifier,
|
*types.AccountIdentifier,
|
||||||
|
@ -85,10 +82,10 @@ type Indexer interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type unsignedTransaction struct {
|
type unsignedTransaction struct {
|
||||||
Transaction string `json:"transaction"`
|
Transaction string `json:"transaction"`
|
||||||
ScriptPubKeys []*lbry.ScriptPubKey `json:"scriptPubKeys"`
|
ScriptPubKeys []*bitcoin.ScriptPubKey `json:"scriptPubKeys"`
|
||||||
InputAmounts []string `json:"input_amounts"`
|
InputAmounts []string `json:"input_amounts"`
|
||||||
InputAddresses []string `json:"input_addresses"`
|
InputAddresses []string `json:"input_addresses"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type preprocessOptions struct {
|
type preprocessOptions struct {
|
||||||
|
@ -98,7 +95,7 @@ type preprocessOptions struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type constructionMetadata struct {
|
type constructionMetadata struct {
|
||||||
ScriptPubKeys []*lbry.ScriptPubKey `json:"script_pub_keys"`
|
ScriptPubKeys []*bitcoin.ScriptPubKey `json:"script_pub_keys"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type signedTransaction struct {
|
type signedTransaction struct {
|
||||||
|
@ -109,5 +106,5 @@ type signedTransaction struct {
|
||||||
// ParseOperationMetadata is returned from
|
// ParseOperationMetadata is returned from
|
||||||
// ConstructionParse.
|
// ConstructionParse.
|
||||||
type ParseOperationMetadata struct {
|
type ParseOperationMetadata struct {
|
||||||
ScriptPubKey *lbry.ScriptPubKey `json:"scriptPubKey"`
|
ScriptPubKey *bitcoin.ScriptPubKey `json:"scriptPubKey"`
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue