From d7c2d92174382b42cea973269275c84a97945344 Mon Sep 17 00:00:00 2001 From: Oren Laadan Date: Wed, 11 Jan 2023 23:19:34 +0800 Subject: [PATCH 1/7] CNS-150: dockerize lavad build Update the Makefile and intorduce Dockerfile to improve lavad build. Notable make targets (for all targets - see Makefile): make build - local build (output in ./build/) make test - run unit-tests make lint - run the linter make docker-build - local build with docker image (host arch) make build-images - build and produce docker images (all archs) make build-image-amd64 - build and produce docker image (linux/amd64) make build-image-amd64 - build and produce docker image (linux/arm64) Other notable changes: - See Makefile for options to turn on/off via LAVA_BUILD_OPTIONS variable - Use LAVA_BUILD_OPTIONS="static" to build static binary - Use LAVA_BUILD_OPTIONS="static,release" to build static binary for release Also updated .dockerignore (notably, added .git/ to avoid the cost). Anyway, the copy only affects the builder stage in docker - nothing is copied to the final image. Also updates .gitignote (primarily some cleanup). --- .dockerignore | 31 +++------ .gitignore | 43 +++++++------ Dockerfile | 108 +++++++++++++++++++++++++++++++ Dockerfile-base | 4 -- Makefile | 167 ++++++++++++++++++++++++++++++++++++++++++------ 5 files changed, 287 insertions(+), 66 deletions(-) create mode 100644 Dockerfile delete mode 100644 Dockerfile-base diff --git a/.dockerignore b/.dockerignore index 59fd76eceb..c6b2ceda9b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,25 +1,12 @@ -vue/node_modules -vue/dist release/ -.idea/ -.vscode/ -.DS_Store -notes.txt -vue/src/store/generated/* -vue/src/store/generated/lavanet/lava/lavanet.lava.servicer/index.js -vue/src/store/generated/lavanet/lava/lavanet.lava.servicer/index.ts -vue/src/store/generated/lavanet/lava/lavanet.lava.servicer/module/index.d.ts -vue/src/store/generated/lavanet/lava/lavanet.lava.servicer/module/index.js -vue/src/store/generated/lavanet/lava/lavanet.lava.servicer/module/index.ts -vue/src/store/generated/lavanet/lava/lavanet.lava.user/index.js -vue/src/store/generated/lavanet/lava/lavanet.lava.user/index.ts -vue/src/store/generated/lavanet/lava/lavanet.lava.user/module/index.d.ts -vue/src/store/generated/lavanet/lava/lavanet.lava.user/module/index.js -vue/src/store/generated/lavanet/lava/lavanet.lava.user/module/index.ts -relayer/cmd/relayer/__debug_bin -relayer/.env -testutil/e2e/logs/ -ptnet/ +build/ +vue/src/store/generated/ +vue/node_modules/ +vue/dist/ scripts/vars/ +testutil/e2e/logs/ testutil/debugging/ -ts-client/ +.github/ +.git/ +.idea/ +.vscode/ diff --git a/.gitignore b/.gitignore index 0138bd5cf4..fcff6001f3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,26 +1,27 @@ -vue/node_modules -vue/dist +build/ release/ + +# Intellij .idea/ -.vscode/ + +# macOS .DS_Store -notes.txt -vue/src/store/generated/* -vue/src/store/generated/lavanet/lava/lavanet.lava.servicer/index.js -vue/src/store/generated/lavanet/lava/lavanet.lava.servicer/index.ts -vue/src/store/generated/lavanet/lava/lavanet.lava.servicer/module/index.d.ts -vue/src/store/generated/lavanet/lava/lavanet.lava.servicer/module/index.js -vue/src/store/generated/lavanet/lava/lavanet.lava.servicer/module/index.ts -vue/src/store/generated/lavanet/lava/lavanet.lava.user/index.js -vue/src/store/generated/lavanet/lava/lavanet.lava.user/index.ts -vue/src/store/generated/lavanet/lava/lavanet.lava.user/module/index.d.ts -vue/src/store/generated/lavanet/lava/lavanet.lava.user/module/index.js -vue/src/store/generated/lavanet/lava/lavanet.lava.user/module/index.ts -relayer/cmd/relayer/__debug_bin -relayer/.env + +# vscode +.vscode/ + +# vim +.*.sw? + +# Vue +vue/src/store/generated/ +vue/node_modules +vue/dist + +# Logs and debug +scripts/automation_scripts/automation_results* testutil/e2e/logs/ -ptnet/ -scripts/vars/ testutil/debugging/ -ts-client/ -scripts/automation_scripts/automation_results* \ No newline at end of file + +# Misc +scripts/vars/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..8b1c418511 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,108 @@ +# syntax = docker/dockerfile:1.2 +# WARNING! Use with `docker buildx ...` or `DOCKER_BUILDKIT=1 docker build ...` +# to enable --mount feature used below. + +######################################################################## +# Dockerfile for reproducible build of lavad binary and docker image +######################################################################## + +ARG GO_VERSION="1.18.2" +ARG RUNNER_IMAGE="debian:11-slim" + +# -------------------------------------------------------- +# Base +# -------------------------------------------------------- + +FROM --platform=$BUILDPLATFORM golang:${GO_VERSION} as base + +ARG GIT_VERSION +ARG GIT_COMMIT + +# Download debian packages for building +RUN --mount=type=cache,target=/var/cache/apt \ + rm -f /etc/apt/apt.conf.d/docker-clean && \ + apt-get update && \ + apt-get install -yqq --no-install-recommends \ + build-essential \ + ca-certificates \ + curl + +# -------------------------------------------------------- +# Builder +# -------------------------------------------------------- + +FROM --platform=$BUILDPLATFORM base as builder + +ARG TARGETOS +ARG TARGETARCH + +# set GIT_CLONE=true to force 'git clone' of sources from repository +# (useful to compile a specific version, combined with GIT_VERSION). +ARG GIT_CLONE=false + +# Download go dependencies +WORKDIR /lava +COPY go.mod go.sum ./ +RUN --mount=type=cache,target=/root/.cache/go-build \ + --mount=type=cache,target=/go/pkg/mod \ + go mod download + +# Copy the remaining files +COPY . . + +# Git clone the sources if requested +# NOTE TODO: after reset of chain (lava-testnet-1) prefix 'v' to ${GIT_VERISON} +RUN if [ "${GIT_CLONE}" = true ]; then \ + find . -mindepth 1 -delete && \ + git clone --depth 1 --branch ${GIT_VERSION} https://github.com/lavanet/lava . \ + ; fi + +# Remove tag v0.4.0 (same v0.4.0-rc2, which was used in the upgrade proposal +# and must always be reported) to not eclipse the v0.4.0-rc2 tag. +# NOTE TODO: after reset of chain (lava-testnet-1) remove this +RUN git tag -d v0.4.0 || true + +# Fix glitch in Makefile for versions < 0.4.3 +# NOTE TODO: after reset of chain (lava-testnet-1) remove this +RUN sed -i 's/whitespace += $(whitespace)/whitespace := $(whitespace) $(whitespace)/g' Makefile + +# Export our version/commit for the Makefile to know (the .git directory +# is not here, so the Makefile cannot infer them). +ENV BUILD_VERSION=${GIT_VERSION} +ENV BUILD_COMMIT=${GIT_COMMIT} + +ENV GOOS=${TARGETOS} +ENV GOARCH=${TARGETARCH} + +# Build lavad binary +RUN --mount=type=cache,target=/root/.cache/go-build \ + --mount=type=cache,target=/go/pkg/mod \ + LAVA_BUILD_OPTIONS="static" make build + +# -------------------------------------------------------- +# Cosmovisor +# -------------------------------------------------------- + +FROM --platform=$BUILDPLATFORM builder as cosmovisor + +# Download Cosmovisor +RUN --mount=type=cache,target=/root/.cache/go-build \ + --mount=type=cache,target=/go/pkg/mod \ + go get github.com/cosmos/cosmos-sdk/cosmovisor/cmd/cosmovisor@v1.0.0 \ + && go install github.com/cosmos/cosmos-sdk/cosmovisor/cmd/cosmovisor@v1.0.0 + + +# -------------------------------------------------------- +# Runner-base +# -------------------------------------------------------- + +# Download debian packages for runner + +FROM ${RUNNER_IMAGE} + +COPY --from=builder /lava/build/lavad /bin/lavad + +ENV HOME /lava +WORKDIR $HOME + +ENTRYPOINT ["/bin/lavad"] diff --git a/Dockerfile-base b/Dockerfile-base deleted file mode 100644 index 08f6c7eae0..0000000000 --- a/Dockerfile-base +++ /dev/null @@ -1,4 +0,0 @@ -FROM golang:1.18.3-alpine as build - -WORKDIR /lava -COPY . . diff --git a/Makefile b/Makefile index ae28a914ec..d926a49f8d 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,74 @@ #!/usr/bin/make -f -VERSION ?= $(shell echo $(shell git describe --tags) | sed 's/^v//') -COMMIT ?= $(shell git log -1 --format='%H') +# Usage: and targets: +# [LAVA_BUILD_OPTIONS=...] make [TARGET...] +# +# Targets: +# +# build - local build (output: `build/lavad`) +# docker-build - docker build (output: `build/lavad`) with docker image +# +# build-images - build both amd64,arm64 lavad(s) and docker image(s) +# build-image-amd64 - docker build (output: `build/lavad-linux-amd64`) with docker image +# build-image-arm64 - docker build (output: `build/lavad-linux-arm64`) with docker image +# +# test - run unit-tests +# lint - run the linter +# +# Options: +# (comma separated list of options to turn on specific features) +# +# static - build static binary +# release - generate release build +# nostrip - do not strip binary from paths) +# +# debug_mutex - (debug) enable debug mutex +# mask_consumer_logs - (debug) enable debug mutex + +# do we have .git/ directory? +have_dot_git := $(if $(shell test -d .git && echo true),true,false) + +# If we have .git/ directory, then grab the VERSION and COMMIT from git. +# (And if current commit is not tagged, also remove the commit count). +# If we don't have .git/ (like when called from our Makefile), then expect +# VERSION and COMMIT explicitly provided (via BUILD_VERSION, BUILD_COMMIT). + +ifeq (true,$(have_dot_git)) + VERSION := $(shell git describe --tags --abbrev=7 --dirty | sed 's/-[0-9]*-g/-/') + COMMIT := $(shell git log -1 --format='%H') +else + BUILD_VERSION ?= unknown + BUILD_COMMIT ?= unknown + VERSION := $(BUILD_VERSION) + COMMIT := $(BUILD_COMMIT) +endif + +# If we have .git/ directory and 'release' option selected, then we examine +# the currently checked-out code to confirm that it is - +# - clean (no local uncommitted changes, no untracked files) +# - matching in version to the desired tag (no extra commit) + +ifeq (true,$(have_dot_git)) + ifeq (release,$(findstring release,$(LAVA_BUILD_OPTIONS))) + version_real := $(shell git describe --tags --exact-match 2> /dev/null || echo "none") + ifneq '$(VERSION)' '$(version_real)' + $(error Current checked-out code does not match requested release version) + endif + ifeq (-dirty,$(findstring -dirty,$(VERSION))) + $(error Current checked-out code has uncommitted changes or untracked files) + endif + endif +endif + +# strip the leading 'v' +VERSION := $(subst v,,$(VERSION)) + LEDGER_ENABLED ?= true SDK_PACK := $(shell go list -m github.com/cosmos/cosmos-sdk | sed 's/ /\@/g') +GO_VERSION := $(shell cat go.mod | grep -E 'go [0-9].[0-9]+' | cut -d ' ' -f 2) DOCKER := $(shell which docker) BUILDDIR ?= $(CURDIR)/build -DEBUG_MUTEX ?= false -MASK_CONSUMER_LOGS ?= false + export GO111MODULE = on # process build tags @@ -44,19 +105,31 @@ endif build_tags += $(BUILD_TAGS) build_tags := $(strip $(build_tags)) -whitespace := -whitespace := $(whitespace) $(whitespace) +null := +whitespace += $(null) $(null) comma := , build_tags_comma_sep := $(subst $(whitespace),$(comma),$(build_tags)) # process linker flags + ldflags = -X github.com/cosmos/cosmos-sdk/version.Name=lava \ -X github.com/cosmos/cosmos-sdk/version.AppName=lavad \ -X github.com/cosmos/cosmos-sdk/version.Version=$(VERSION) \ -X github.com/cosmos/cosmos-sdk/version.Commit=$(COMMIT) \ - -X github.com/cosmos/cosmos-sdk/version.BuildTags=$(build_tags_comma_sep) \ - -X github.com/lavanet/lava/relayer/chainproxy.ReturnMaskedErrors=$(MASK_CONSUMER_LOGS) \ - -X github.com/lavanet/lava/utils.TimeoutMutex=$(DEBUG_MUTEX) \ + -X "github.com/cosmos/cosmos-sdk/version.BuildTags=$(build_tags_comma_sep)" + +# For static binaries just set CGO_ENABLED=0. +# (Using only '-link-mode=external -extldflags ...' does not work). +ifeq (static,$(findstring static,$(LAVA_BUILD_OPTIONS))) + export CGO_ENABLED = 0 +endif + +ifeq (mask_consumer_logs,$(findstring mask_consumer_logs,$(LAVA_BUILD_OPTIONS))) + ldflags += -X github.com/lavanet/lava/relayer/chainproxy.ReturnMaskedErrors=true +endif +ifeq (debug_mutex,$(findstring debug_mutex,$(LAVA_BUILD_OPTIONS))) + ldflags += -X github.com/lavanet/lava/utils.TimeoutMutex=true +endif ifeq (cleveldb,$(findstring cleveldb,$(LAVA_BUILD_OPTIONS))) ldflags += -X github.com/cosmos/cosmos-sdk/types.DBBackend=cleveldb @@ -66,9 +139,7 @@ endif ifeq (,$(findstring nostrip,$(LAVA_BUILD_OPTIONS))) ldflags += -w -s endif -ifeq ($(LINK_STATICALLY),true) - ldflags += -linkmode=external -extldflags "-Wl,-z,muldefs -static" -endif + ldflags += $(LDFLAGS) ldflags := $(strip $(ldflags)) @@ -82,23 +153,63 @@ endif ### Build ### ############################################################################### +all: lint test + BUILD_TARGETS := build install build: BUILD_ARGS=-o $(BUILDDIR)/ -.PHONY: lint -lint: - golangci-lint run --config .golangci.yml - -.PHONY: $(BUILD_TARGETS) $(BUILD_TARGETS): go.sum $(BUILDDIR)/ go $@ -mod=readonly $(BUILD_FLAGS) $(BUILD_ARGS) ./... $(BUILDDIR)/: mkdir -p $(BUILDDIR)/ -build-linux: go.sum - LEDGER_ENABLED=false GOOS=linux GOARCH=amd64 $(MAKE) build +# build lavad within docker (reproducible) and docker image +docker-build: build-docker-helper build-docker-copier + +# build lavad within docker (repducible) for both archs +build-images: build-image_amd64 build-image-arm64 + +# build lavad-linux-amd64 within docker (reproducible) and docker image +build-image-amd64: TARGETARCH=amd64 +build-image-amd64: build-docker-helper build-docker-copier + +# build lavad-linux-arm64 within docker (reproducible) and docker image +build-image-arm64: TARGETARCH=arm64 +build-image-arm64: build-docker-helper build-docker-copier + +RUNNER_IMAGE_DEBIAN := debian:11-slim + +define autogen_targetarch +$(if $(TARGETARCH),$(TARGETARCH),$(shell GOARCH= go env GOARCH)) +endef + +# Note: this target expects TARGETARCH to be defined +build-docker-helper: $(BUILDDIR)/ + $(DOCKER) buildx create --name lavabuilder || true + $(DOCKER) buildx use lavabuilder + $(DOCKER) buildx build \ + --build-arg GO_VERSION=$(GO_VERSION) \ + --build-arg GIT_VERSION=$(VERSION) \ + --build-arg GIT_COMMIT=$(COMMIT) \ + --build-arg RUNNER_IMAGE=$(RUNNER_IMAGE_DEBIAN) \ + --platform linux/$(call autogen_targetarch) \ + -t lava:$(VERSION) \ + --load \ + -f Dockerfile . + $(DOCKER) image tag lava:$(VERSION) lava:latest + +define autogen_extraver +$(if $(TARGETARCH),-linux-$(TARGETARCH),) +endef + +# Note: this target expects TARGETARCH to be defined +build-docker-copier: $(BUILDDIR)/ + $(DOCKER) rm -f lavabinary 2> /dev/null || true + $(DOCKER) create -ti --name lavabinary lava:$(VERSION) + $(DOCKER) cp lavabinary:/bin/lavad $(BUILDDIR)/lavad$(call autogen_extraver) + $(DOCKER) rm -f lavabinary go-mod-cache: go.sum @echo "--> Download go modules to local cache" @@ -108,4 +219,22 @@ go.sum: go.mod @echo "--> Ensure dependencies have not been modified" @go mod verify +draw-deps: + @# requires brew install graphviz or apt-get install graphviz + go get github.com/RobotsAndPencils/goviz + @goviz -i ./cmd/lavad -d 2 | dot -Tpng -o dependency-graph.png + +test: + @echo "--> Running tests" + @go test -v ./x/... + +lint: + @echo "--> Running linter" + golangci-lint run --config .golangci.yml + + +.PHONY: all build docker-build install lint test \ + go-mod-cache go.sum draw-deps \ + build-docker-helper build-docker-copier \ + build-images build-image-amd64 build-image-arm64 \ From 62cd4c380e1f8d276f407c8fa29aa48298acc540 Mon Sep 17 00:00:00 2001 From: Oren Laadan Date: Tue, 17 Jan 2023 21:45:55 +0800 Subject: [PATCH 2/7] CNS-140: dockerize lavad setup Update the Dockerfile to generate docker image that can run lava node. (Implemented using the artifacts in docker/ directory.) To start a lava node in a container, run the command: docker-compose --profile node --env-file env -f docker/docker-compose.yml up Edit the file `env` to adjust the (external) ports used by this node (see that file for the defaults). It will execute the script `start_node.sh` (from docker/), which follows the instructions for starting a node (with cosmovisor). --- Dockerfile | 35 +++++++++++++- docker/docker-compose.yml | 28 +++++++++++ docker/entrypoint.sh | 47 +++++++++++++++++++ docker/env | 18 +++++++ docker/start_node.sh | 99 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 225 insertions(+), 2 deletions(-) create mode 100644 docker/docker-compose.yml create mode 100755 docker/entrypoint.sh create mode 100644 docker/env create mode 100755 docker/start_node.sh diff --git a/Dockerfile b/Dockerfile index 8b1c418511..d77bc7b5cc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -98,11 +98,42 @@ RUN --mount=type=cache,target=/root/.cache/go-build \ # Download debian packages for runner -FROM ${RUNNER_IMAGE} +FROM ${RUNNER_IMAGE} as runner-base +RUN apt-get update \ + && apt-get install -yqq --no-install-recommends \ + git curl unzip ca-certificates \ + && apt-get -y purge \ + && apt-get -y clean \ + && apt-get -y autoremove \ + && rm -rf /var/lib/apt/lists/* + +# -------------------------------------------------------- +# Runner +# -------------------------------------------------------- + +FROM runner-base + +COPY --from=cosmovisor /go/bin/cosmovisor /bin/cosmovisor COPY --from=builder /lava/build/lavad /bin/lavad ENV HOME /lava WORKDIR $HOME -ENTRYPOINT ["/bin/lavad"] +COPY docker/entrypoint.sh / +COPY docker/start_node.sh start_node.sh + +# lava api +EXPOSE 1317 +# rosetta +EXPOSE 8080 +# grpc +EXPOSE 9090 +# grpc-web +EXPOSE 9090 +# tendermint p2p +EXPOSE 26656 +# tendermint rpc +EXPOSE 26657 + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000000..694b968fb4 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,28 @@ +version: '3.9' + +x-env: &env-common + environment: + - LAVA_LISTEN_IP=${LAVA_LISTEN_IP:-0.0.0.0} + - LAVA_LOG_LEVEL=${LAVA_LOG_LEVEL:-"info"} + +services: + + lava-node: + build: .. + image: lava:latest + command: "node" + <<: *env-common + ports: + - '${LAVA_LISTEN_IP:-0.0.0.0}:${LAVA_NODE_PORT_API:-1317}:1317' + - '${LAVA_LISTEN_IP:-0.0.0.0}:${LAVA_NODE_PORT_GRPC:-9090}:9090' + - '${LAVA_LISTEN_IP:-0.0.0.0}:${LAVA_NODE_PORT_GRPC_WEB:-9091}:9091' + - '${LAVA_LISTEN_IP:-0.0.0.0}:${LAVA_NODE_PORT_P2P:-26656}:26656' + - '${LAVA_LISTEN_IP:-0.0.0.0}:${LAVA_NODE_PORT_RPC:-26657}:26657' + deploy: + resources: + limits: + cpus: '4' + memory: '8gb' + restart: unless-stopped + profiles: ["node"] + diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100755 index 0000000000..82963dbc82 --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,47 @@ +#!/bin/sh +# vim:sw=4:ts=4:et + +set -e + +if [ -z "${LAVA_QUIET_LOGS:-}" ]; then + exec 3>&1 +else + exec 3>/dev/null +fi + +if /usr/bin/find "/entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then + echo >&3 "$0: Looking for shell scripts in /entrypoint.d/" + find "/entrypoint.d/" -follow -type f -print | sort -n | while read -r f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + echo >&3 "$0: Launching $f"; + "$f" + else + # warn on shell scripts without exec bit + echo >&3 "$0: Ignoring $f, not executable"; + fi + ;; + *) echo >&3 "$0: Ignoring $f";; + esac + done + echo >&3 "$0: Configuration complete; ready for start up" +else + echo >&3 "$0: No files found in /entrypoint.d/, skipping configuration" +fi + +if [ $# -lt 1 ]; then + echo >&3 "$0: No command given" + exit 1 +fi + +case _"$1" in + _node) cmd="/lava/start_node.sh" ;; + *) cmd="$1" ;; +esac + +shift + +echo >&3 "$0: Launching $cmd $@" + +exec "$cmd" "$@" diff --git a/docker/env b/docker/env new file mode 100644 index 0000000000..244b0f153c --- /dev/null +++ b/docker/env @@ -0,0 +1,18 @@ +# lava environment variables for docker-compose + +# listen address for services [mandatory] +# (normally should be to '0.0.0.0' since services run in container network; +# may set to the host's external address when using 'host' network mode for +# the container). +LAVA_LISTEN_IP='0.0.0.0' + +# listen ports for services [mandatory: node] +LAVA_NODE_PORT_API=1317 +LAVA_NODE_PORT_GRPC=9090 +LAVA_NODE_PORT_GRPC_WEB=9091 +LAVA_NODE_PORT_P2P=26656 +LAVA_NODE_PORT_RPC=26657 + +# lavad log level [mandatory] +LAVA_LOG_LEVEL='info' + diff --git a/docker/start_node.sh b/docker/start_node.sh new file mode 100755 index 0000000000..9205085178 --- /dev/null +++ b/docker/start_node.sh @@ -0,0 +1,99 @@ +#!/bin/sh +# vim:sw=4:ts=4:et + +set -e + +SETUP_CONFIG_GIT_URL='https://github.com/K433QLtr6RA9ExEq/GHFkqmTzpdNLDd6T.git' +COSMOVISOR_ZIP_URL='https://lava-binary-upgrades.s3.amazonaws.com/testnet/cosmovisor-upgrades/cosmovisor-upgrades.zip' + +debug() { + echo "DBG: $@" +} + +error() { + echo "ERR: $@" + exit 1 +} + +setup_node() { + setup_config_dir=$(basename ${SETUP_CONFIG_GIT_URL}) + + # remove old data (if any) + rm -rf ${setup_config_dir} + + # download setup configuration + git clone --depth 1 ${SETUP_CONFIG_GIT_URL} ${setup_config_dir} || \ + error "setup: failed to clone setup configuration" + + cd ${setup_config_dir}/testnet-1 + . setup_config/setup_config.sh + + # keep a copy handy for when we restart + cp setup_config/setup_config.sh ${HOME} + + # remove old config (if any) + rm -rf ${lavad_home_folder} + + # copy initial configuration and genesis data + mkdir -p ${lavad_home_folder} + mkdir -p ${lava_config_folder} + cp default_lavad_config_files/* ${lava_config_folder} + cp genesis_json/genesis.json ${lava_config_folder}/genesis.json +} + +setup_env() { + # environment variables for cosmovisor + export DAEMON_NAME=lavad + export CHAIN_ID=lava-testnet-1 + export DAEMON_HOME=$HOME/.lava + export DAEMON_ALLOW_DOWNLOAD_BINARIES=true + export DAEMON_LOG_BUFFER_SIZE=512 + export DAEMON_RESTART_AFTER_UPGRADE=true + export UNSAFE_SKIP_BACKUP=true +} + +# note: expected to run in the setup config directory - see setup_node()) +setup_cosmovisor() { + # download latest cosmovisor-upgrades + curl -L --progress-bar -o cosmovisor-upgrades.zip "${COSMOVISOR_ZIP_URL}" || \ + error "setup: failed to download cosmovisor upgrades" + unzip cosmovisor-upgrades.zip || \ + error "setup: failed to unzip cosmovisor upgrades" + + # copy cosmovisor configuration + mkdir -p ${lavad_home_folder}/cosmovisor + cp -r cosmovisor-upgrades/* ${lavad_home_folder}/cosmovisor + + # initialize the chain + output=$( \ + ${lavad_home_folder}/cosmovisor/genesis/bin/lavad init \ + my-node \ + --chain-id lava-testnet-1 \ + --home ${lavad_home_folder} \ + --overwrite \ + ) + + # an error message about missing upgrade-info.json is expected; + # anything else is unexpected and should abort. + if [ $? -ne 0 ]; then + case "$output" in + "*upgrade-info.json: no such file or directory*") ;; + "*") error "setup: failed to initialize the chain" ;; + esac + fi + + # copy genesis data again + cp genesis_json/genesis.json ${lava_config_folder}/genesis.json +} + +setup_env + +if [ ! -e ${HOME}/.lava/cosmovisor/current ]; then + setup_node + setup_cosmovisor +else + . ${HOME}/setup_config.sh +fi + +exec /bin/cosmovisor start --home=${lavad_home_folder} --p2p.seeds ${seed_node} + From 7b766f39c3f1c40374e23feae177abcdde473228 Mon Sep 17 00:00:00 2001 From: Oren Laadan Date: Wed, 18 Jan 2023 17:37:19 +0800 Subject: [PATCH 3/7] CNS-140: dockerize lavad setup: portal Update the Dockerfile to generate docker image that can run lava portal. (Implemented using the artifacts in docker/ directory.) To start a lava portal in a container, run the command: docker-compose --profile portal --env-file env -f docker/docker-compose.yml up Edit the file `env` to adjust the portal parameters used by this portal (see that file for the defaults). It will execute the script `start_portal.sh` (from docker/), which follows the instructions for starting a portal. If needed, it will also do stake-client (including if the stake amount is to be raised). --- Dockerfile | 26 ++++++++ docker/docker-compose.yml | 46 +++++++++++++-- docker/entrypoint.sh | 1 + docker/env | 41 ++++++++++++- docker/start_portal.sh | 121 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 228 insertions(+), 7 deletions(-) create mode 100755 docker/start_portal.sh diff --git a/Dockerfile b/Dockerfile index d77bc7b5cc..ac1c47a798 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,6 +19,7 @@ ARG GIT_VERSION ARG GIT_COMMIT # Download debian packages for building +ARG DEBIAN_FRONTEND=noninteractive RUN --mount=type=cache,target=/var/cache/apt \ rm -f /etc/apt/apt.conf.d/docker-clean && \ apt-get update && \ @@ -100,6 +101,7 @@ RUN --mount=type=cache,target=/root/.cache/go-build \ FROM ${RUNNER_IMAGE} as runner-base +ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update \ && apt-get install -yqq --no-install-recommends \ git curl unzip ca-certificates \ @@ -122,6 +124,30 @@ WORKDIR $HOME COPY docker/entrypoint.sh / COPY docker/start_node.sh start_node.sh +COPY docker/start_portal.sh start_portal.sh + +ENV LAVA_HOME_DIR= \ + LAVA_USER= \ + LAVA_ADDRESS= \ + LAVA_KEYRING= \ + LAVA_STAKE_AMOUNT= \ + LAVA_GAS_MODE= \ + LAVA_GAS_ADJUST= \ + LAVA_GAS_PRICE= \ + LAVA_GEOLOCATION= \ + LAVA_RPC_NODE= \ + LAVA_CHAIN_ID= \ + LAVA_LISTEN_IP= \ + LAVA_NODE_PORT_API= \ + LAVA_NODE_PORT_GRPC= \ + LAVA_NODE_PORT_GRPC_WEB= \ + LAVA_NODE_PORT_P2P= \ + LAVA_NODE_PORT_RPC= \ + LAVA_PORTAL_PORT= \ + LAVA_RELAY_CHAIN_ID= \ + LAVA_RELAY_IFACE= \ + LAVA_RELAY_NODE_URL= \ + LAVA_LOG_LEVEL= # lava api EXPOSE 1317 diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 694b968fb4..bd7137c89f 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,9 +1,8 @@ version: '3.9' -x-env: &env-common - environment: - - LAVA_LISTEN_IP=${LAVA_LISTEN_IP:-0.0.0.0} - - LAVA_LOG_LEVEL=${LAVA_LOG_LEVEL:-"info"} +x-vol: + - &vol-lava + ${LAVA_HOME_DIR:-.lava}:/lava/.lava services: @@ -11,7 +10,10 @@ services: build: .. image: lava:latest command: "node" - <<: *env-common + environment: + # common env + - LAVA_LISTEN_IP=${LAVA_LISTEN_IP:-0.0.0.0} + - LAVA_LOG_LEVEL=${LAVA_LOG_LEVEL:-info} ports: - '${LAVA_LISTEN_IP:-0.0.0.0}:${LAVA_NODE_PORT_API:-1317}:1317' - '${LAVA_LISTEN_IP:-0.0.0.0}:${LAVA_NODE_PORT_GRPC:-9090}:9090' @@ -26,3 +28,37 @@ services: restart: unless-stopped profiles: ["node"] + lava-portal: + build: .. + image: lava:latest + command: "portal" + volumes: + - *vol-lava + environment: + # common env + - LAVA_LISTEN_IP=${LAVA_LISTEN_IP:-0.0.0.0} + - LAVA_LOG_LEVEL=${LAVA_LOG_LEVEL:-info} + # portal env + - LAVA_USER + - LAVA_KEYRING + - LAVA_ADDRESS + - LAVA_STAKE_AMOUNT + - LAVA_GAS_MODE + - LAVA_GAS_ADJUST + - LAVA_GAS_PRICE + - LAVA_GEOLOCATION + - LAVA_RPC_NODE + - LAVA_CHAIN_ID + - LAVA_RELAY_CHAIN_ID + - LAVA_RELAY_IFACE + - LAVA_PORTAL_PORT + ports: + - '${LAVA_LISTEN_IP:-0.0.0.0}:${LAVA_PORTAL_PORT:-8080}:${LAVA_PORTAL_PORT:-8080}' + deploy: + resources: + limits: + cpus: '2' + memory: '2gb' + restart: unless-stopped + profiles: ["portal"] + diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 82963dbc82..2dc38beea0 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -37,6 +37,7 @@ fi case _"$1" in _node) cmd="/lava/start_node.sh" ;; + _portal) cmd="/lava/start_portal.sh" ;; *) cmd="$1" ;; esac diff --git a/docker/env b/docker/env index 244b0f153c..ef225c0db2 100644 --- a/docker/env +++ b/docker/env @@ -1,10 +1,37 @@ # lava environment variables for docker-compose +# lava home directory, usually ~/.lava [mandatory: portal, provider] +LAVA_HOME_DIR=.lava + +# lava user address -or- user name [mandatory: portal, provider] +# note: at least one must be set (address takes precedence if both are set) +LAVA_USER= +LAVA_ADDRESS= + +# lava keyring backend [mandatory: portal, provider] +LAVA_KEYRING=test + +# stake amount [mandatory: portal, provider] +# (if bigger than existing stake then we would try to increase it) +LAVA_STAKE_AMOUNT=0ulava + +# gas parameters for stakin [mandatory: portal, provider] +LAVA_GAS_MODE=auto +LAVA_GAS_ADJUST=1.5 +LAVA_GAS_PRICE=0.000000001ulava + +# service geo-location [mandatory: portal, provider] +LAVA_GEOLOCATION=1 + +# lava rpc node for queries, and the chain id [mandatory: portal, provider] +LAVA_RPC_NODE=http://public-rpc.lavanet.xyz:80/rpc/ +LAVA_CHAIN_ID=lava-testnet-1 + # listen address for services [mandatory] # (normally should be to '0.0.0.0' since services run in container network; # may set to the host's external address when using 'host' network mode for # the container). -LAVA_LISTEN_IP='0.0.0.0' +LAVA_LISTEN_IP=0.0.0.0 # listen ports for services [mandatory: node] LAVA_NODE_PORT_API=1317 @@ -13,6 +40,16 @@ LAVA_NODE_PORT_GRPC_WEB=9091 LAVA_NODE_PORT_P2P=26656 LAVA_NODE_PORT_RPC=26657 +# listen ports for services [mandatory: portal] +LAVA_PORTAL_PORT=8080 + +# relay chain id, and api interface [mandatory: portal, provider] +LAVA_RELAY_CHAIN_ID= +LAVA_RELAY_IFACE=jsonrpc + +# relay node URL [mandatory: provider] +LAVA_RELAY_NODE_URL= + # lavad log level [mandatory] -LAVA_LOG_LEVEL='info' +LAVA_LOG_LEVEL=info diff --git a/docker/start_portal.sh b/docker/start_portal.sh new file mode 100755 index 0000000000..0520db6922 --- /dev/null +++ b/docker/start_portal.sh @@ -0,0 +1,121 @@ +#!/bin/sh +# vim:sw=4:ts=4:et + +set -e + +info() { + echo "INF: $@" +} + +debug() { + echo "DBG: $@" +} + +error() { + echo "ERR: $@" + exit 1 +} + +check_env_vars() { + # no need to check LAVA_USER and LAVA_ADDRESS: see check_lava_addr() + + env_vars="LAVA_KEYRING \ + LAVA_STAKE_AMOUNT \ + LAVA_GEOLOCATION \ + LAVA_RPC_NODE \ + LAVA_CHAIN_ID \ + LAVA_GAS_MODE \ + LAVA_GAS_ADJUST \ + LAVA_GAS_PRICE \ + LAVA_LISTEN_IP \ + LAVA_PORTAL_PORT \ + LAVA_RELAY_CHAIN_ID \ + LAVA_RELAY_IFACE \ + LAVA_LOG_LEVEL \ + " + + for ev in $env_vars; do + eval "v=\$$ev" + test -z "${v}" && errmsg="${errmsg} ${ev}\n" + done + + if [ -n "$errmsg" ]; then + error "some env variables not defined:\n${errmsg%%\\n}" + fi +} + +check_lava_addr() { + lavad keys list --keyring-backend "${LAVA_KEYRING}" + + if [ -z "${LAVA_ADDRESS}" ]; then + LAVA_ADDRESS=$(lavad keys show "${LAVA_USER}" --keyring-backend "${LAVA_KEYRING}" | \ + grep address | awk '{print $2}') + + if [ -z "${LAVA_ADDRESS}" ]; then + error "unable to fetch the user's lava address" + fi + else + lavad keys list --keyring-backend "${LAVA_KEYRING}" | \ + grep -q ${LAVA_ADDRESS} || \ + error "unable to find the requested lava address" + fi +} + +client_staked_amount() { + lavad query pairing clients \ + "${LAVA_RELAY_CHAIN_ID}" \ + --node "${LAVA_RPC_NODE}" \ + --chain-id "${LAVA_CHAIN_ID}" \ + | sed -n '/Staked Clients:/{n;p}' \ + | grep "${LAVA_ADDRESS}" \ + | sed 's/^.*{\([0-9]*ulava\).*$/\1/' +} + +stake_client() { + info "staking client - this may take a while" + lavad tx pairing stake-client -y \ + "${LAVA_RELAY_CHAIN_ID}" \ + "${LAVA_STAKE_AMOUNT}" \ + "${LAVA_GEOLOCATION}" \ + --from "${LAVA_ADDRESS}" \ + --node "${LAVA_RPC_NODE}" \ + --chain-id "${LAVA_CHAIN_ID}" \ + --keyring-backend "${LAVA_KEYRING}" \ + --gas-adjustment "${LAVA_GAS_ADJUST}" \ + --gas-prices "${LAVA_GAS_PRICE}" \ + --gas "${LAVA_GAS_MODE}" \ + --log_level "${LAVA_LOG_LEVEL}" || + error "unable to stake client" +} + +# check sanity of env vars +check_env_vars + +# check (and maybe get) lava address +check_lava_addr + +# check that client is staked with right amount +stake_amount=$(client_staked_amount) + +if [ -z $stake_amount ]; then + info "client not staked: staking client" + stake_client +elif [ $stake_amount -lt ${LAVA_STAKE_AMOUNT} ]; then + info "client staked amount to small: increasing amount" + stake_client +fi + +debug "starting portal server" + +exec lavad portal_server \ + "${LAVA_LISTEN_IP}" \ + "${LAVA_PORTAL_PORT}" \ + "${LAVA_RELAY_CHAIN_ID}" \ + "${LAVA_RELAY_IFACE}" \ + --from "${LAVA_ADDRESS}" \ + --node "${LAVA_RPC_NODE}" \ + --chain-id "${LAVA_CHAIN_ID}" \ + --geolocation "${LAVA_GEOLOCATION}" \ + --log_level "${LAVA_LOG_LEVEL}" || + error "unable to start portal" + From f8547f232369f7b49e288894c8047f146f221d8f Mon Sep 17 00:00:00 2001 From: Oren Laadan Date: Wed, 18 Jan 2023 19:24:31 +0800 Subject: [PATCH 4/7] CNS-150: dockerize lavad build: better handling of 'release' Propagete LAVA_BUILD_OPTIONS env var and GIT_CLONE build-arg to the docker build. This ensures that the build in docker indeeds generates the release. Also allow user to select release version using LAVA_VERSION env variable. Add examples in the Makefile for how to run. --- Dockerfile | 8 ++++++-- Makefile | 54 ++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index ac1c47a798..845cd8e686 100644 --- a/Dockerfile +++ b/Dockerfile @@ -41,6 +41,10 @@ ARG TARGETARCH # (useful to compile a specific version, combined with GIT_VERSION). ARG GIT_CLONE=false +# set LAVA_BUILD_OPTIONS to control the Makefile behavior (see there). +ARG BUILD_OPTIONS +ENV LAVA_BUILD_OPTIONS=${BUILD_OPTIONS} + # Download go dependencies WORKDIR /lava COPY go.mod go.sum ./ @@ -52,10 +56,10 @@ RUN --mount=type=cache,target=/root/.cache/go-build \ COPY . . # Git clone the sources if requested -# NOTE TODO: after reset of chain (lava-testnet-1) prefix 'v' to ${GIT_VERISON} +# NOTE TODO: after reset of chain (lava-testnet-1) prefix 'v' to ${GIT_VERSION} RUN if [ "${GIT_CLONE}" = true ]; then \ find . -mindepth 1 -delete && \ - git clone --depth 1 --branch ${GIT_VERSION} https://github.com/lavanet/lava . \ + git clone --depth 1 --branch v${GIT_VERSION} https://github.com/lavanet/lava . \ ; fi # Remove tag v0.4.0 (same v0.4.0-rc2, which was used in the upgrade proposal diff --git a/Makefile b/Makefile index d926a49f8d..175939afa3 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,24 @@ # # debug_mutex - (debug) enable debug mutex # mask_consumer_logs - (debug) enable debug mutex +# +# Examples: +# +# Build locally and run unit tests +# make test build +# +# Build locally a static binary (runs on any distributions and in containers) +# LAVA_BUILD_OPTIONS="static" make build +# +# Build and generate docker image +# LAVA_BUILD_OPTIONS="static" make docker-build +# +# Build release [and optionally generate docker image] +# LAVA_BUILD_OPTIONS="static,release" make build +# LAVA_BUILD_OPTIONS="static,release" make docker-build +# +# Build release of specific version, and generate docker image +# LAVA_VERSION=0.4.3 LAVA_BUILD_OPTIONS="static,release" make docker-build # do we have .git/ directory? have_dot_git := $(if $(shell test -d .git && echo true),true,false) @@ -43,26 +61,44 @@ else COMMIT := $(BUILD_COMMIT) endif -# If we have .git/ directory and 'release' option selected, then we examine -# the currently checked-out code to confirm that it is - +GIT_CLONE := false + +# If we have .git/ directory and 'release' option selected, then we consult +# LAVA_VERSION for the desired version; If not set, then we infer the version +# from the currnently checked-out code - and then we examine that it is - # - clean (no local uncommitted changes, no untracked files) # - matching in version to the desired tag (no extra commit) +# +# Also, if 'release' option selected, then set GIT_COMMIT=true so that that +# the Dockerfile would clone the repository from scratch. ifeq (true,$(have_dot_git)) ifeq (release,$(findstring release,$(LAVA_BUILD_OPTIONS))) - version_real := $(shell git describe --tags --exact-match 2> /dev/null || echo "none") - ifneq '$(VERSION)' '$(version_real)' - $(error Current checked-out code does not match requested release version) - endif - ifeq (-dirty,$(findstring -dirty,$(VERSION))) - $(error Current checked-out code has uncommitted changes or untracked files) + ifneq (,$(LAVA_VERSION)) + VERSION := v$(LAVA_VERSION) + COMMIT := $(shell git log -1 --format='%H' $(VERSION)) + else + version_real := $(shell git describe --tags --exact-match 2> /dev/null || echo "none") + ifneq '$(VERSION)' '$(version_real)' + $(error Current checked-out code does not match requested release version) + endif + ifeq (-dirty,$(findstring -dirty,$(VERSION))) + $(error Current checked-out code has uncommitted changes or untracked files) + endif endif + GIT_CLONE := true endif endif # strip the leading 'v' VERSION := $(subst v,,$(VERSION)) +ifeq (release,$(findstring release,$(LAVA_BUILD_OPTIONS))) + $(info ----------------------------------------------------------------) + $(info Building for release: VERSION=$(VERSION) COMMIT=$(COMMIT)) + $(info ----------------------------------------------------------------) +endif + LEDGER_ENABLED ?= true SDK_PACK := $(shell go list -m github.com/cosmos/cosmos-sdk | sed 's/ /\@/g') GO_VERSION := $(shell cat go.mod | grep -E 'go [0-9].[0-9]+' | cut -d ' ' -f 2) @@ -193,6 +229,8 @@ build-docker-helper: $(BUILDDIR)/ --build-arg GO_VERSION=$(GO_VERSION) \ --build-arg GIT_VERSION=$(VERSION) \ --build-arg GIT_COMMIT=$(COMMIT) \ + --build-arg GIT_CLONE=$(GIT_CLONE) \ + --build-arg BUILD_OPTIONS=$(LAVA_BUILD_OPTIONS) \ --build-arg RUNNER_IMAGE=$(RUNNER_IMAGE_DEBIAN) \ --platform linux/$(call autogen_targetarch) \ -t lava:$(VERSION) \ From 3ad29e424696f5b27f3451ceb556692ce05abcf5 Mon Sep 17 00:00:00 2001 From: Oren Laadan Date: Wed, 18 Jan 2023 20:39:05 +0800 Subject: [PATCH 5/7] CNS-150: dockerize lavad build: minor fixes and docs Fix use of LAVA_BULID_OPTIONS in Dockerfile's call to 'make'. Build cosmovisor independent of the builder stage (image). Document the env variables of the Makefile, and unused options. --- Dockerfile | 21 ++++++++++++--------- Makefile | 11 +++++++++-- docker/docker-compose.yml | 4 ++-- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index 845cd8e686..e33a5ff5c2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -48,8 +48,8 @@ ENV LAVA_BUILD_OPTIONS=${BUILD_OPTIONS} # Download go dependencies WORKDIR /lava COPY go.mod go.sum ./ -RUN --mount=type=cache,target=/root/.cache/go-build \ - --mount=type=cache,target=/go/pkg/mod \ +RUN --mount=type=cache,sharing=private,target=/root/.cache/go-build \ + --mount=type=cache,sharing=private,target=/go/pkg/mod \ go mod download # Copy the remaining files @@ -80,20 +80,23 @@ ENV GOOS=${TARGETOS} ENV GOARCH=${TARGETARCH} # Build lavad binary -RUN --mount=type=cache,target=/root/.cache/go-build \ - --mount=type=cache,target=/go/pkg/mod \ - LAVA_BUILD_OPTIONS="static" make build +RUN --mount=type=cache,sharing=private,target=/root/.cache/go-build \ + --mount=type=cache,sharing=private,target=/go/pkg/mod \ + LAVA_BUILD_OPTIONS="${LAVA_BUILD_OPTIONS},static" make build # -------------------------------------------------------- # Cosmovisor # -------------------------------------------------------- -FROM --platform=$BUILDPLATFORM builder as cosmovisor +FROM --platform=$BUILDPLATFORM base as cosmovisor + +WORKDIR /lava # Download Cosmovisor -RUN --mount=type=cache,target=/root/.cache/go-build \ - --mount=type=cache,target=/go/pkg/mod \ - go get github.com/cosmos/cosmos-sdk/cosmovisor/cmd/cosmovisor@v1.0.0 \ +RUN --mount=type=cache,sharing=private,target=/root/.cache/go-build \ + --mount=type=cache,sharing=private,target=/go/pkg/mod \ + go mod init disposable \ + && go get github.com/cosmos/cosmos-sdk/cosmovisor/cmd/cosmovisor@v1.0.0 \ && go install github.com/cosmos/cosmos-sdk/cosmovisor/cmd/cosmovisor@v1.0.0 diff --git a/Makefile b/Makefile index 175939afa3..833a8d8094 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ #!/usr/bin/make -f # Usage: and targets: -# [LAVA_BUILD_OPTIONS=...] make [TARGET...] +# [LAVA_BUILD_OPTIONS=...] [ENV...] make [TARGET...] # # Targets: # @@ -20,11 +20,18 @@ # # static - build static binary # release - generate release build -# nostrip - do not strip binary from paths) +# nostrip - do not strip binary from paths # # debug_mutex - (debug) enable debug mutex # mask_consumer_logs - (debug) enable debug mutex # +# cleveldb, rocksdb - (not to be used) +# +# Environment +# LAVA_VERSION=... - select lava version (for 'release') +# BUILDDIR=... - select local directory for build output +# LEDGER_ENABLED - (not to be used) +# # Examples: # # Build locally and run unit tests diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index bd7137c89f..9d68cd60d4 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -25,7 +25,7 @@ services: limits: cpus: '4' memory: '8gb' - restart: unless-stopped + restart: on-failure:5 profiles: ["node"] lava-portal: @@ -59,6 +59,6 @@ services: limits: cpus: '2' memory: '2gb' - restart: unless-stopped + restart: on-failure:5 profiles: ["portal"] From f85a4e053b1fc0b89cf8e88c9c6c28fbe3609d3a Mon Sep 17 00:00:00 2001 From: Oren Laadan Date: Thu, 19 Jan 2023 02:08:58 +0800 Subject: [PATCH 6/7] CNS-140: dockerize lavad setup: provider Update the Dockerfile to generate docker image that can run lava provider. (Implemented using the artifacts in docker/ directory.) To start a lava provider in a container, run the command: docker-compose --profile provider \ --env-file docker/env -f docker/docker-compose.yml up Edit the file `env` to adjust the portal parameters used by this provider (see that file for the defaults). It will execute the script `start_provider.sh` (from docker/), which follows the instructions for starting a provider. If needed, it will also execute the stake-provider (including if the stake amount is to be raised). --- Dockerfile | 1 + docker/docker-compose.yml | 35 +++++++++++ docker/entrypoint.sh | 1 + docker/env | 3 + docker/start_provider.sh | 125 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 165 insertions(+) create mode 100755 docker/start_provider.sh diff --git a/Dockerfile b/Dockerfile index e33a5ff5c2..80e9ebcb5f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -154,6 +154,7 @@ ENV LAVA_HOME_DIR= \ LAVA_RELAY_CHAIN_ID= \ LAVA_RELAY_IFACE= \ LAVA_RELAY_NODE_URL= \ + LAVA_RELAY_ENDPOINT= \ LAVA_LOG_LEVEL= # lava api diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 9d68cd60d4..9eefc78618 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -62,3 +62,38 @@ services: restart: on-failure:5 profiles: ["portal"] + lava-provider: + build: .. + image: lava:latest + command: "provider" + volumes: + - *vol-lava + environment: + # common env + - LAVA_LISTEN_IP=${LAVA_LISTEN_IP:-0.0.0.0} + - LAVA_LOG_LEVEL=${LAVA_LOG_LEVEL:-info} + # portal env + - LAVA_USER + - LAVA_KEYRING + - LAVA_ADDRESS + - LAVA_STAKE_AMOUNT + - LAVA_GAS_MODE + - LAVA_GAS_ADJUST + - LAVA_GAS_PRICE + - LAVA_GEOLOCATION + - LAVA_RPC_NODE + - LAVA_CHAIN_ID + - LAVA_RELAY_ENDPOINT + - LAVA_RELAY_NODE_URL + - LAVA_RELAY_CHAIN_ID + - LAVA_RELAY_IFACE + - LAVA_PORTAL_PORT + ports: + - '${LAVA_LISTEN_IP:-0.0.0.0}:${LAVA_PORTAL_PORT:-8080}:${LAVA_PORTAL_PORT:-8080}' + deploy: + resources: + limits: + cpus: '2' + memory: '4gb' + restart: on-failure:5 + profiles: ["provider"] diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 2dc38beea0..fbcd886eb9 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -38,6 +38,7 @@ fi case _"$1" in _node) cmd="/lava/start_node.sh" ;; _portal) cmd="/lava/start_portal.sh" ;; + _provider) cmd="/lava/start_provider.sh" ;; *) cmd="$1" ;; esac diff --git a/docker/env b/docker/env index ef225c0db2..aca27142b0 100644 --- a/docker/env +++ b/docker/env @@ -50,6 +50,9 @@ LAVA_RELAY_IFACE=jsonrpc # relay node URL [mandatory: provider] LAVA_RELAY_NODE_URL= +# relay endpoint(s) [mandatory: provider] +LAVA_RELAY_ENDPOINT= + # lavad log level [mandatory] LAVA_LOG_LEVEL=info diff --git a/docker/start_provider.sh b/docker/start_provider.sh new file mode 100755 index 0000000000..2ce96ebe0c --- /dev/null +++ b/docker/start_provider.sh @@ -0,0 +1,125 @@ +#!/bin/sh +# vim:sw=4:ts=4:et + +set -e + +info() { + echo "INF: $@" +} + +debug() { + echo "DBG: $@" +} + +error() { + echo "ERR: $@" + exit 1 +} + +check_env_vars() { + # no need to check LAVA_USER and LAVA_ADDRESS: see check_lava_addr() + + env_vars="LAVA_KEYRING \ + LAVA_STAKE_AMOUNT \ + LAVA_GEOLOCATION \ + LAVA_RPC_NODE \ + LAVA_CHAIN_ID \ + LAVA_GAS_MODE \ + LAVA_GAS_ADJUST \ + LAVA_GAS_PRICE \ + LAVA_LISTEN_IP \ + LAVA_PORTAL_PORT \ + LAVA_RELAY_ENDPOINT \ + LAVA_RELAY_NODE_URL \ + LAVA_RELAY_CHAIN_ID \ + LAVA_RELAY_IFACE \ + LAVA_LOG_LEVEL \ + " + + for ev in $env_vars; do + eval "v=\$$ev" + test -z "${v}" && errmsg="${errmsg} ${ev}\n" + done + + if [ -n "$errmsg" ]; then + error "some env variables not defined:\n${errmsg%%\\n}" + fi +} + +check_lava_addr() { + lavad keys list --keyring-backend "${LAVA_KEYRING}" + + if [ -z "${LAVA_ADDRESS}" ]; then + LAVA_ADDRESS=$(lavad keys show "${LAVA_USER}" --keyring-backend "${LAVA_KEYRING}" | \ + grep address | awk '{print $2}') + + if [ -z "${LAVA_ADDRESS}" ]; then + error "unable to fetch the user's lava address" + fi + else + lavad keys list --keyring-backend "${LAVA_KEYRING}" | \ + grep -q ${LAVA_ADDRESS} || \ + error "unable to find the requested lava address" + fi +} + +provider_staked_amount() { + lavad query pairing providers \ + "${LAVA_RELAY_CHAIN_ID}" \ + --node "${LAVA_RPC_NODE}" \ + --chain-id "${LAVA_CHAIN_ID}" \ + | sed -n '/Staked Providers:/{n;p}' \ + | grep "${LAVA_ADDRESS}" \ + | sed 's/^.*{\([0-9]*ulava\).*$/\1/' +} + +stake_provider() { + info "staking provider - this may take a while" + lavad tx pairing stake-provider -y \ + "${LAVA_RELAY_CHAIN_ID}" \ + "${LAVA_STAKE_AMOUNT}" \ + "${LAVA_RELAY_ENDPOINT}" \ + "${LAVA_GEOLOCATION}" \ + --from "${LAVA_ADDRESS}" \ + --node "${LAVA_RPC_NODE}" \ + --chain-id "${LAVA_CHAIN_ID}" \ + --keyring-backend "${LAVA_KEYRING}" \ + --gas-adjustment "${LAVA_GAS_ADJUST}" \ + --gas-prices "${LAVA_GAS_PRICE}" \ + --gas "${LAVA_GAS_MODE}" \ + --log_level "${LAVA_LOG_LEVEL}" || + error "unable to stake provider" +} + +# check sanity of env vars +check_env_vars + +# check (and maybe get) lava address +check_lava_addr + +# check that provider is staked with right amount +stake_amount=$(provider_staked_amount) + +if [ -z $stake_amount ]; then + info "provider not staked: staking provider" + stake_provider +elif [ $stake_amount -lt ${LAVA_STAKE_AMOUNT} ]; then + info "provider staked amount to small: increasing amount" + stake_provider +fi + +debug "starting provider server" + +exec lavad portal_server \ + "${LAVA_LISTEN_IP}" \ + "${LAVA_PORTAL_PORT}" \ + "${LAVA_RELAY_NODE_URL}" \ + "${LAVA_RELAY_CHAIN_ID}" \ + "${LAVA_RELAY_IFACE}" \ + --from "${LAVA_ADDRESS}" \ + --node "${LAVA_RPC_NODE}" \ + --chain-id "${LAVA_CHAIN_ID}" \ + --geolocation "${LAVA_GEOLOCATION}" \ + --log_level "${LAVA_LOG_LEVEL}" || + error "unable to start provider" + From 6457a99b5cd002429519be46205a308830959e3f Mon Sep 17 00:00:00 2001 From: Oren Laadan Date: Thu, 19 Jan 2023 02:14:03 +0800 Subject: [PATCH 7/7] CNS-140: dockerize lavad setup: add initial README.md --- docker/README.md | 79 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 docker/README.md diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000000..ea3fe8c67d --- /dev/null +++ b/docker/README.md @@ -0,0 +1,79 @@ +# How to use the lava docker images + +## Building lava docker images + +1. Download the lava sources: + git clone https://github.com/lavanet/lava.git + +2. Build the lava docker image locally + # to build from the current checked-out code: + make docker-build + + # to build a specific lava version + LAVA_BUILD_OPTIONS="release" LAVA_VERSION=0.4.3 make docker-build + +The result would be a docker image names `lava` tagged with the version. +For example the output of `docker images` after the above: + lava 0.4.3 bc3a85c7623f 2 hours ago 256MB + lava latest bc3a85c7623f 2 hours ago 256MB + lava 0.4.3-a5e1202-dirty 5ff644084c3d 2 hours ago 257MB + +## Running lava containers with docker + +**TODO** + +## Running lava containers with docker-compose + +**Run Lava Node** + +1. Review the settings in `docker/env`. The default settings are usually +suitable for all deployments. + +2. Use the following the commands to create/start/stop/destroy the node: + +To start the node: + docker-compose --profile node --env-file docker/env -f docker/docker-compose.yml up + +To stop/start the node: + docker-compose --profile node --env-file docker/env -f docker/docker-compose.yml stop + docker-compose --profile node --env-file docker/env -f docker/docker-compose.yml start + +To destroy the node: + docker-compose --profile node --env-file docker/env -f docker/docker-compose.yml down + +**Run Lava Portal \ Provider** + +1. Create a lava user and fund it. + + export LAVA_HOME='.lava' + export LAVA_USER='my-user' + + # create a new user, and then show its address + build/lavad keys add $LAVA_USER --home $LAVA_HOME --keyring-backend test + build/lavad keys list --home $LAVA_HOME --keyring-backend test list + + LAVA_ADDR=$(lavad keys show "${LAVA_USER}" --home $LAVA_HOME --keyring-backend test | \ + grep address | awk '{print $2}') + + # fund the new user: see https://docs.lavanet.xyz/faucet + + # verify the user has funds + build/lavad query bank balances $LAVA_ADDR --home $LAVA_HOME --denom ulava \ + --node http://public-rpc.lavanet.xyz:80/rpc/ + +2. Review the settings in `docker/env`. Fill in all the mandatory values +for the 'provider' role. + +3. Use the following the commands to create/start/stop/destroy the node (for +'provider' replace the role 'portal' with 'provider'): + +To start the portal/provider: + docker-compose --profile portal --env-file docker/env -f docker/docker-compose.yml up + +To stop/start the portal/provider: + docker-compose --profile portal --env-file docker/env -f docker/docker-compose.yml stop + docker-compose --profile portal --env-file docker/env -f docker/docker-compose.yml start + +To destroy the portal/provider: + docker-compose --profile portal --env-file docker/env -f docker/docker-compose.yml down +