diff --git a/Dockerfile b/Dockerfile index 8405115..7ae05e4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,6 +19,7 @@ RUN mkdir -p /app \ && chown -R nobody:nogroup /app WORKDIR /app +# Source: https://github.com/bitcoin/bitcoin/blob/master/doc/build-unix.md#ubuntu--debian RUN apt-get update && apt-get install -y make gcc g++ autoconf autotools-dev bsdmainutils build-essential git libboost-all-dev \ libcurl4-openssl-dev libdb++-dev libevent-dev libssl-dev libtool pkg-config python python-pip libzmq3-dev wget @@ -68,7 +69,9 @@ RUN cd src \ ## Build Final Image FROM ubuntu:18.04 -RUN apt-get update && apt-get install -y libevent-dev libboost-system-dev libboost-filesystem-dev libboost-test-dev libboost-thread-dev +RUN apt-get update && \ + apt-get install --no-install-recommends -y libevent-dev libboost-system-dev libboost-filesystem-dev libboost-test-dev libboost-thread-dev && \ + apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* RUN mkdir -p /app \ && chown -R nobody:nogroup /app \ @@ -77,10 +80,10 @@ RUN mkdir -p /app \ WORKDIR /app -# Copy binaries from build containers -COPY --from=bitcoind-builder /app/* /app/ +# Copy binary from bitcoind-builder +COPY --from=bitcoind-builder /app/bitcoind /app/bitcoind -# Copy configuration files and set permissions +# Copy binary from rosetta-builder COPY --from=rosetta-builder /app/* /app/ # Set permissions for everything added to /app diff --git a/Makefile b/Makefile index c0a20a7..e2a812d 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,11 @@ build: build-local: docker build -t rosetta-bitcoin:latest . +build-release: + # make sure to always set version with vX.X.X + docker build -t rosetta-bitcoin:$(version) .; + docker save rosetta-bitcoin:$(version) | gzip > rosetta-bitcoin-$(version).tar.gz; + run-mainnet-online: docker run -d --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 diff --git a/README.md b/README.md index 3c0762b..3593dda 100644 --- a/README.md +++ b/README.md @@ -34,15 +34,54 @@ As specified in the [Rosetta API Principles](https://www.rosetta-api.org/docs/au 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). -To build a Docker image from this repository, run the command `make build`. To start -`rosetta-bitcoin`, you can run: -* `make run-mainnet-online` -* `make run-mainnet-offline` -* `make run-testnet-online` -* `make run testnet-offline` +**YOU MUST INSTALL DOCKER FOR THE FOLLOWING INSTRUCTIONS TO WORK. YOU CAN DOWNLOAD +DOCKER [HERE](https://www.docker.com/get-started).** -By default, running these commands will create a data directory at `/bitcoin-data` -and start the `rosetta-bitcoin` server at port `8080`. +### Install +Running the following commands will create a Docker image called `rosetta-bitcoin:latest`. + +#### From GitHub +To download the pre-built Docker image from the latest release, run: +```text +curl -sSfL https://raw.githubusercontent.com/coinbase/rosetta-bitcoin/master/install.sh | sh -s +``` +_Do not try to install rosetta-bitcoin using GitHub Packages!_ + +#### From Source +After cloning this repository, run: +```text +make build-local +``` + +### Run +Running the following commands will start a Docker container in +[detached mode](https://docs.docker.com/engine/reference/run/#detached--d) with +a data directory at `/bitcoin-data` and the Rosetta API accessible +at port `8080`. + +#### Mainnet:Online +```text +docker run -d --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`._ + +#### Mainnet:Offline +```text +docker run -d -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`._ + +#### Testnet:Online +```text +docker run -d --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`._ + +#### Testnet:Offline +```text +docker run -d -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`._ ## System Requirements `rosetta-bitcoin` has been tested on an [AWS c5.2xlarge instance](https://aws.amazon.com/ec2/instance-types/c5). diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..5f9b4b3 --- /dev/null +++ b/install.sh @@ -0,0 +1,221 @@ +#!/bin/sh +# Copyright 2020 Coinbase, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +# Inspired by: https://github.com/golangci/golangci-lint/blob/master/install.sh + +usage() { + this=$1 + cat </dev/null +} +echoerr() { + echo "$@" 1>&2 +} +log_prefix() { + echo "$0" +} +_logp=6 +log_set_priority() { + _logp="$1" +} +log_priority() { + if test -z "$1"; then + echo "$_logp" + return + fi + [ "$1" -le "$_logp" ] +} +log_tag() { + case $1 in + 0) echo "emerg" ;; + 1) echo "alert" ;; + 2) echo "crit" ;; + 3) echo "err" ;; + 4) echo "warning" ;; + 5) echo "notice" ;; + 6) echo "info" ;; + 7) echo "debug" ;; + *) echo "$1" ;; + esac +} +log_debug() { + log_priority 7 || return 0 + echoerr "$(log_prefix)" "$(log_tag 7)" "$@" +} +log_info() { + log_priority 6 || return 0 + echoerr "$(log_prefix)" "$(log_tag 6)" "$@" +} +log_err() { + log_priority 3 || return 0 + echoerr "$(log_prefix)" "$(log_tag 3)" "$@" +} +log_crit() { + log_priority 2 || return 0 + echoerr "$(log_prefix)" "$(log_tag 2)" "$@" +} +untar() { + tarball=$1 + case "${tarball}" in + *.tar.gz | *.tgz) tar --no-same-owner -xzf "${tarball}" ;; + *.tar) tar --no-same-owner -xf "${tarball}" ;; + *.zip) unzip "${tarball}" ;; + *) + log_err "untar unknown archive format for ${tarball}" + return 1 + ;; + esac +} +http_download_curl() { + local_file=$1 + source_url=$2 + header=$3 + loud=$4 + quiet_var="-L" + if [ -z "$loud" ]; then + quiet_var="-sL" + fi + if [ -z "$header" ]; then + code=$(curl -w '%{http_code}' "$quiet_var" -o "$local_file" "$source_url") + else + code=$(curl -w '%{http_code}' "$quiet_var" -H "$header" -o "$local_file" "$source_url") + fi + if [ "$code" != "200" ]; then + log_debug "http_download_curl received HTTP status $code" + return 1 + fi + return 0 +} +http_download_wget() { + local_file=$1 + source_url=$2 + header=$3 + loud=$4 + quiet_var="" + if [ -z "$loud" ]; then + quiet_var="-q" + fi + + if [ -z "$header" ]; then + wget "$quiet_var" -O "$local_file" "$source_url" + else + wget "$quiet_var" --header "$header" -O "$local_file" "$source_url" + fi +} +http_download() { + log_debug "http_download $2" + if is_command curl; then + http_download_curl "$@" + return + elif is_command wget; then + http_download_wget "$@" + return + fi + log_crit "http_download unable to find wget or curl" + return 1 +} +http_copy() { + tmp=$(mktemp) + http_download "${tmp}" "$1" "$2" || return 1 + body=$(cat "$tmp") + rm -f "${tmp}" + echo "$body" +} +github_release() { + owner_repo=$1 + version=$2 + test -z "$version" && version="latest" + giturl="https://github.com/${owner_repo}/releases/${version}" + json=$(http_copy "$giturl" "Accept:application/json") + test -z "$json" && return 1 + version=$(echo "$json" | tr -s '\n' ' ' | sed 's/.*"tag_name":"//' | sed 's/".*//') + test -z "$version" && return 1 + echo "$version" +} +cat /dev/null <