diff --git a/.gitignore b/.gitignore index 64528233c9..ed80b92a73 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,6 @@ target *.*~ # dotfiles -.dockerignore .editorconfig .DS_Store @@ -31,11 +30,11 @@ waves_logback.xml *.csv *.dat -# standalone docker -Dockerfile +# Docker +docker/temp package !src/package native -!lang/jvm/lib/*.jar \ No newline at end of file +!lang/jvm/lib/*.jar diff --git a/build-with-docker.sh b/build-with-docker.sh new file mode 100755 index 0000000000..c2760061c4 --- /dev/null +++ b/build-with-docker.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +NETWORK="Mainnet" + +if [[ -n $1 ]]; then + NETWORK=$1 +fi + +echo "Building with network: $NETWORK" +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" +USER=$(id -u) +GROUP=$(id -g) + +docker run --mount type=bind,source="$DIR",target=/src -i mozilla/sbt:8u232_1.3.8 /bin/sh -c " + cd /src && + COURSIER_CACHE=\"$DIR/target/docker/coursier\" sbt \"-Dsbt.boot.directory=$DIR/target/docker/sbt_cache\" \"set ThisBuild/network := $NETWORK\" packageAll && + chown -R $USER:$GROUP . +" diff --git a/build.sbt b/build.sbt index 674a3285ad..b57fdc3feb 100644 --- a/build.sbt +++ b/build.sbt @@ -7,7 +7,7 @@ */ import sbt.Keys._ -import sbt.{Project, _} +import sbt.{File, IO, Project, _} import sbtcrossproject.CrossPlugin.autoImport.{CrossType, crossProject} val langPublishSettings = Seq( @@ -147,17 +147,15 @@ git.useGitDescribe := true git.uncommittedSignifier := Some("DIRTY") lazy val packageAll = taskKey[Unit]("Package all artifacts") -packageAll := Def - .sequential( - root / clean, - Def.task { - (node / assembly).value - (node / Debian / packageBin).value - (`grpc-server` / Universal / packageZipTarball).value - (`grpc-server` / Debian / packageBin).value - } - ) - .value +packageAll := { + (node / assembly).value + (`grpc-server` / Universal / packageZipTarball).value + + val nodeDebFile = (node / Debian / packageBin).value + val grpcDebFile = (`grpc-server` / Debian / packageBin).value + IO.copyFile(nodeDebFile, new File(baseDirectory.value, "docker/target/waves.deb")) + IO.copyFile(grpcDebFile, new File(baseDirectory.value, "docker/target/grpc-server.deb")) +} lazy val checkPRRaw = taskKey[Unit]("Build a project and run unit tests") checkPRRaw := Def diff --git a/docker/Dockerfile b/docker/Dockerfile index 85d6ce7f0f..ad2cbe42e1 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,81 +1,30 @@ -FROM openjdk:8-jdk-stretch as builder -ARG SBT_VERSION=1.2.8 -ARG WAVES_VERSION="latest" -ARG BRANCH="version-1.1.x" -ARG DEB_PACKAGE_NETWORKS - -RUN \ -{ \ - WAVES_VERSION=$WAVES_VERSION && \ - test $WAVES_VERSION = "latest" && \ - WAVES_VERSION=$(curl -fsSL \ - https://api.github.com/repos/wavesplatform/Waves/releases/latest \ - | tac | grep -m 1 'tag_name.:' | tr -cd '[0-9\.]') && \ - echo "Using latest version '${WAVES_VERSION}'" \ -;} ; \ -{ \ - curl -fsSL https://api.github.com/repos/wavesplatform/Waves/releases \ - | tac | grep -q "tag_name.*${WAVES_VERSION}" && \ - echo "GitHub release '${WAVES_VERSION}' found" \ -;} && \ -{ \ - echo "Downloading Waves '${WAVES_VERSION}' from GitHub" && \ - mkdir -p /waves/node/target && \ - releaseUrl="https://github.com/wavesplatform/Waves/releases/download" && \ - \ - echo "Downloading jar file" && \ - curl -fL ${releaseUrl}/v${WAVES_VERSION}/waves-all-${WAVES_VERSION}.jar \ - -o /waves/node/target/waves-all-${WAVES_VERSION}.jar \ -;} || \ -{ \ - echo "Downloading sbt '${SBT_VERSION}'" && \ - curl -fL -o sbt-$SBT_VERSION.deb \ - https://dl.bintray.com/sbt/debian/sbt-$SBT_VERSION.deb && \ - dpkg -i sbt-$SBT_VERSION.deb && rm sbt-$SBT_VERSION.deb && \ - git clone https://github.com/wavesplatform/Waves.git \ - --branch $BRANCH waves && cd waves && \ - git config --global user.name "Sbt Builder" && \ - git config --global user.email "sbt@builder.docker" && \ - git tag -a "v${WAVES_VERSION}" -m "Docker build" && \ - SBT_OPTS="-Xmx2g -XX:MaxPermSize=256m -XX:ReservedCodeCacheSize=128m" \ - sbt "node/assembly" && \ - for network in $DEB_PACKAGE_NETWORKS ; do \ - echo "Building '${network}' package" && \ - SBT_OPTS="-XX:ReservedCodeCacheSize=128m \ - -Xmx2g -Dnetwork=${network}" sbt 'packageAll' && \ - mkdir -p /out/${network} && \ - mv node/target/waves*.deb /out/${network}/ && \ - cp node/target/waves-all*.jar /out/${network}/ && \ - mv grpc-server/target/universal/grpc-server*.tgz /out/${network}/ && \ - mv grpc-server/target/grpc-server*.deb /out/${network}/ ; \ - done \ -;} - -FROM openjdk:11-jre-slim -ARG WAVES_VERSION="latest" +FROM debian:stable-slim ARG WAVES_LOG_LEVEL="INFO" ARG WAVES_HEAP_SIZE="2g" ARG WAVES_NETWORK="mainnet" +ARG ENABLE_GRPC="true" -ENV WAVES_VERSION=$WAVES_VERSION ENV WAVES_LOG_LEVEL=$WAVES_LOG_LEVEL ENV WAVES_HEAP_SIZE=$WAVES_HEAP_SIZE ENV WAVES_NETWORK=$WAVES_NETWORK +ENV ENABLE_GRPC=$ENABLE_GRPC -COPY --from=builder /waves/node/target/waves-all-*.jar /usr/share/waves/lib/ -COPY entrypoint.sh /usr/share/waves/bin/ +COPY build-scripts /tmp/ -RUN groupadd -g 143 waves && \ - useradd -d /var/lib/waves -g 143 -u 143 -s /bin/bash -M waves && \ - mkdir -p /var/lib/waves /etc/waves /usr/share/waves/lib/plugins && \ - chown -R 143:143 /var/lib/waves /usr/share/waves /etc/waves && \ - chmod -R 755 /var/lib/waves /usr/share/waves /etc/waves && \ - ln -fs /var/lib/waves/log /var/log/waves +# Additional dependencies +RUN /bin/bash /tmp/setup-deps.sh -WORKDIR /var/lib/waves -EXPOSE 6869 6868 6863 6862 +# Node DEB files +ENV WVDATA=/var/lib/waves +ENV WVLOG=/var/log/waves +COPY target /tmp/ +RUN /bin/bash /tmp/setup-node.sh -USER waves +EXPOSE 6869 6868 6863 6862 6870 VOLUME /var/lib/waves +VOLUME /var/log/waves VOLUME /usr/share/waves/lib/plugins +WORKDIR /var/lib/waves + +STOPSIGNAL SIGINT ENTRYPOINT ["/usr/share/waves/bin/entrypoint.sh"] diff --git a/docker/README.md b/docker/README.md index 960c028901..af71dcdce3 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,7 +1,7 @@ # Waves Node in Docker ## About Waves -Waves is a decentralized platform that allows any user to issue, transfer, swap and trade custom blockchain tokens on an integrated peer-to-peer exchange. You can find more information about Waves at [wavesplatform.com](https://wavesplatform.com) and in the official [documentation]((https://docs.wavesplatform.com)). +Waves is a decentralized platform that allows any user to issue, transfer, swap and trade custom blockchain tokens on an integrated peer-to-peer exchange. You can find more information about Waves at [waves.tech](https://waves.tech/) and in the official [documentation](https://docs.waves.tech). ## About the image @@ -11,15 +11,10 @@ The image is focused on fast and convenient deployment of Waves Node. GitHub repository: https://github.com/wavesplatform/Waves/tree/master/docker ## Prerequisites -It is highly recommended to read more about [Waves Node configuration](https://docs.wavesplatform.com/en/waves-Node/Node-configuration.html) before running the container. +It is highly recommended to read more about [Waves Node configuration](https://docs.waves.tech/en/waves-node/node-configuration) before running the container. ## Building Docker image - -Dockerfile supports 3 main scenarios: -1. Basic scenario `docker build -t wavesplatform/wavesnode .` - build an image with the latest Waves Node release available -*Note*: pre-releases are skipped -2. Existing Version scenario `docker build --build-arg WAVES_VERSION=1.1.1` - specify the version of Waves Node available in GitHub Releases. If this version does not exist, this is the next scenario. -3. Build scenario `docker build --build-arg WAVES_VERSION=99.99.99 --build-arg BRANCH=version-0.17.x` - this scenario assumes that you want to build Waves Node from sources. Use `WAVES_VERSION` build argument to specify a Git tag ('v' is added automatically) and `BRANCH` to specify a Git branch to checkout to. Make sure you specify a tag that does not exist in the repo, otherwise it is the previous scenario. +`./build-with-docker.sh && docker build -t wavesplatform/wavesnode docker` (from the repository root) - builds an image with the current local repository **You can specify following arguments when building the image:** @@ -27,10 +22,7 @@ Dockerfile supports 3 main scenarios: |Argument | Default value |Description | |----------------------|-------------------|--------------| |`WAVES_NETWORK` | `mainnet` | Waves Blockchain network. Available values are `mainnet`, `testnet`, `stagenet`. Can be overridden in a runtime using environment variable with the same name.| -|`WAVES_VERSION` | `latest` | A node version which corresponds to the Git tag we want to use/create. | -|`BRANCH` | `version-0.17.x` | Relevant if Git tag 'v`WAVES_VERSION`' does not exist in the public repository. This option represents a Git branch we will use to compile Waves node and set a Git tag on.| -|`SBT_VERSION` | `1.2.8` | Scala build tool version.| -|`WAVES_LOG_LEVEL` | `DEBUG` | Default Waves Node log level. Available values: `OFF`, `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`. More details about logging are available [here](https://docs.wavesplatform.com/en/waves-Node/logging-configuration.html). Can be overridden in a runtime using environment variable with the same name. | +|`WAVES_LOG_LEVEL` | `DEBUG` | Default Waves Node log level. Available values: `OFF`, `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`. More details about logging are available [here](https://docs.waves.tech/en/waves-node/logging-configuration). Can be overridden in a runtime using environment variable with the same name. | |`WAVES_HEAP_SIZE` | `2g` | Default Waves Node JVM Heap Size limit in -X Command-line Options notation (`-Xms=[your value]`). More details [here](https://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/jrdocs/refman/optionX.html). Can be overridden in a runtime using environment variable with the same name. | **Note: All build arguments are optional.** @@ -57,7 +49,7 @@ docker run -v /docker/waves/waves-data:/var/lib/waves -v /docker/waves/waves-con |-----------------------------------|--------------| | `WAVES_WALLET_SEED` | Base58 encoded seed. Overrides `-Dwaves.wallet.seed` JVM config option. | | `WAVES_WALLET_PASSWORD` | Password for the wallet file. Overrides `-Dwaves.wallet.password` JVM config option. | -| `WAVES_LOG_LEVEL` | Node logging level. Available values: `OFF`, `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`. More details about logging are available [here](https://docs.wavesplatform.com/en/waves-Node/logging-configuration.html).| +| `WAVES_LOG_LEVEL` | Node logging level. Available values: `OFF`, `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`. More details about logging are available [here](https://docs.waves.tech/en/waves-node/logging-configuration).| | `WAVES_HEAP_SIZE` | Default Java Heap Size limit in -X Command-line Options notation (`-Xms=[your value]`). More details [here](https://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/jrdocs/refman/optionX.html). | |`WAVES_NETWORK` | Waves Blockchain network. Available values are `mainnet`, `testnet`, `stagenet`.| |`JAVA_OPTS` | Additional Waves Node JVM configuration options. | @@ -93,18 +85,7 @@ Once container is launched it will create: 3. If you already have Waves Node configuration/data - place it in the corresponsing directories - -4. *Configure access permissions*. We use `waves` user with predefined uid/gid `143/143` to launch the container. As such, either change permissions of the created directories or change their owner: - -``` -sudo chmod -R 777 /docker/waves -``` -or -``` -sudo chown -R 143:143 /docker/waves <-- prefered -``` - -5. Add the appropriate arguments to ```docker run``` command: +4. Add the appropriate arguments to ```docker run``` command: ``` docker run -v /docker/waves/waves-data:/var/lib/waves -v /docker/waves/waves-config:/etc/waves -e WAVES_NETWORK=stagenet -e WAVES_WALLET_PASSWORD=myWalletSuperPassword -ti wavesplatform/wavesnode ``` @@ -119,27 +100,25 @@ You can speed this process up by downloading a compressed blockchain state from |Network |Link | |------------|--------------| -|`mainnet` | http://blockchain.wavesplatform.com/blockchain_last.tar | -|`testnet` | http://blockchain-testnet.wavesplatform.com/blockchain_last.tar | -|`stagenet` | http://blockchain-stagenet.wavesplatform.com/blockchain_last.tar | +|`mainnet` | http://blockchain.wavesnodes.com/blockchain_last.tar | +|`testnet` | http://blockchain-testnet.wavesnodes.com/blockchain_last.tar | +|`stagenet` | http://blockchain-stagenet.wavesnodes.com/blockchain_last.tar | **Example:** ``` mkdir -p /docker/waves/waves-data -wget -qO- http://blockchain-stagenet.wavesplatform.com/blockchain_last.tar --show-progress | tar -xvf - -C /docker/waves/waves-data - -chown -R 143:143 /docker/waves/waves-data +wget -qO- http://blockchain-stagenet.wavesnodes.com/blockchain_last.tar --show-progress | tar -xvf - -C /docker/waves/waves-data docker run -v /docker/waves/waves-data:/var/lib/waves wavesplatform/Node -e WAVES_NETWORK=stagenet -e WAVES_WALLET_PASSWORD=myWalletSuperPassword -ti wavesplatform/wavesnode ``` ### Network Ports -1. REST-API interaction with Node. Details are available [here](https://docs.wavesplatform.com/en/waves-Node/Node-configuration.html#section-530adfd0788eec3f856da976e4ce7ce7). +1. REST-API interaction with Node. Details are available [here](https://docs.waves.tech/en/waves-node/node-configuration#rest-api-settings). -2. Waves Node communication port for incoming connections. Details are available [here](https://docs.wavesplatform.com/en/waves-Node/Node-configuration.html#section-fd33d7a83e3b2854f614fd9d5ae733ba). +2. Waves Node communication port for incoming connections. Details are available [here](https://docs.waves.tech/en/waves-node/node-configuration#network-settings). **Example:** @@ -149,7 +128,7 @@ Below command will launch a container: - Ports `6868` and `6870` mapped from the host to the container ``` -docker run -v /docker/waves/waves-data:/var/lib/waves -v /docker/waves/waves-config:/etc/waves -p 6870:6870 -p 6868:6868 -e JAVA_OPTS="-Dwaves.network.declared-address=0.0.0.0:6868 -Dwaves.rest-api.port=6870 -Dwaves.rest-api.bind-address=0.0.0.0 -Dwaves.rest-api.enable=yes" -e WAVES_WALLET_PASSWORD=myWalletSuperPassword -ti wavesplatform/wavesnode +docker run -v /docker/waves/waves-data:/var/lib/waves -v /docker/waves/waves-config:/etc/waves -p 6870:6870 -p 6868:6868 -e JAVA_OPTS="-Dwaves.network.declared-address=0.0.0.0:6868 -Dwaves.rest-api.port=6870 -Dwaves.rest-api.bind-address=0.0.0.0 -Dwaves.rest-api.enable=yes" -e WAVES_WALLET_PASSWORD=myWalletSuperPassword -e WAVES_NETWORK=stagenet -ti wavesplatform/wavesnode ``` Check that REST API is up by navigating to the following URL from the host side: diff --git a/docker/build-scripts/entrypoint.sh b/docker/build-scripts/entrypoint.sh new file mode 100644 index 0000000000..5d04920be9 --- /dev/null +++ b/docker/build-scripts/entrypoint.sh @@ -0,0 +1,58 @@ +#!/bin/bash +shopt -s nullglob +NETWORKS="mainnet testnet stagenet" + +logEcho() { + echo $1 | gosu waves tee -a /var/log/waves/waves.log +} + +mkdir -p $WVDATA $WVLOG +chmod 700 $WVDATA $WVLOG || : + +user="$(id -u)" +if [ "$user" = '0' ]; then + find $WVDATA \! -user waves -exec chown waves '{}' + + find $WVLOG \! -user waves -exec chown waves '{}' + +fi + +[ -z "${WAVES_CONFIG}" ] && WAVES_CONFIG="/etc/waves/waves.conf" +if [[ ! -f "$WAVES_CONFIG" ]]; then + logEcho "Custom '$WAVES_CONFIG' not found. Using a default one for '${WAVES_NETWORK,,}' network." + if [[ $NETWORKS == *"${WAVES_NETWORK,,}"* ]]; then + touch "$WAVES_CONFIG" + echo "waves.blockchain.type=${WAVES_NETWORK}" >>$WAVES_CONFIG + + sed -i 's/include "local.conf"//' "$WAVES_CONFIG" + for f in /etc/waves/ext/*.conf; do + echo "Adding $f extension config to waves.conf" + echo "include required(\"$f\")" >>$WAVES_CONFIG + done + echo 'include "local.conf"' >>$WAVES_CONFIG + else + echo "Network '${WAVES_NETWORK,,}' not found. Exiting." + exit 1 + fi +else + echo "Found custom '$WAVES_CONFIG'. Using it." +fi + +[ -n "${WAVES_WALLET_PASSWORD}" ] && JAVA_OPTS="${JAVA_OPTS} -Dwaves.wallet.password=${WAVES_WALLET_PASSWORD}" +[ -n "${WAVES_WALLET_SEED}" ] && JAVA_OPTS="${JAVA_OPTS} -Dwaves.wallet.seed=${WAVES_WALLET_SEED}" +JAVA_OPTS="${JAVA_OPTS} -Dwaves.data-directory=$WVDATA/data -Dwaves.directory=$WVDATA" + +logEcho "Node is starting..." +logEcho "WAVES_HEAP_SIZE='${WAVES_HEAP_SIZE}'" +logEcho "WAVES_LOG_LEVEL='${WAVES_LOG_LEVEL}'" +logEcho "WAVES_NETWORK='${WAVES_NETWORK}'" +logEcho "WAVES_WALLET_SEED='${WAVES_WALLET_SEED}'" +logEcho "WAVES_WALLET_PASSWORD='${WAVES_WALLET_PASSWORD}'" +logEcho "WAVES_CONFIG='${WAVES_CONFIG}'" +logEcho "JAVA_OPTS='${JAVA_OPTS}'" + +JAVA_OPTS="-Dlogback.stdout.level=${WAVES_LOG_LEVEL} + -XX:+ExitOnOutOfMemoryError + -Xmx${WAVES_HEAP_SIZE} + -Dlogback.file.directory=$WVLOG + -Dconfig.override_with_env_vars=true + ${JAVA_OPTS} + -cp '/usr/share/waves/lib/plugins/*:/usr/share/waves/lib/*'" exec gosu waves waves "$WAVES_CONFIG" diff --git a/docker/build-scripts/setup-deps.sh b/docker/build-scripts/setup-deps.sh new file mode 100644 index 0000000000..f8f0e97b6a --- /dev/null +++ b/docker/build-scripts/setup-deps.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +mkdir -p /usr/share/man/man1 +apt-get update && apt-get install -y wget unzip default-jre-headless gosu || exit 1 + +YOURKIT_ARCHIVE="YourKit-JavaProfiler-2019.8-docker.zip" +wget --quiet "https://www.yourkit.com/download/docker/$YOURKIT_ARCHIVE" -P /tmp/ && unzip /tmp/$YOURKIT_ARCHIVE -d /usr/local + +# Clean +apt-get remove -y wget unzip && apt-get autoremove -y && apt-get autoclean && rm -rf /var/lib/apt/lists/* diff --git a/docker/build-scripts/setup-node.sh b/docker/build-scripts/setup-node.sh new file mode 100644 index 0000000000..a32aa9fd99 --- /dev/null +++ b/docker/build-scripts/setup-node.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# Create user +groupadd -r waves --gid=999 +useradd -r -g waves --uid=999 --home-dir=$WVDATA --shell=/bin/bash waves + +# Install DEB packages +dpkg -i /tmp/waves.deb || exit 1 +if [[ $ENABLE_GRPC == "true" ]]; then + echo "Installing gRPC server" + dpkg -i /tmp/grpc-server.deb || exit 1 +fi + +# Set permissions +chown -R waves:waves $WVDATA $WVLOG && chmod 777 $WVDATA $WVLOG + +rm /etc/waves/waves.conf # Remove example config +cp /tmp/entrypoint.sh /usr/share/waves/bin/entrypoint.sh +chmod +x /usr/share/waves/bin/entrypoint.sh + +# Cleanup +rm -rf /tmp/* diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh deleted file mode 100644 index 8434deb33f..0000000000 --- a/docker/entrypoint.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/bash -shopt -s nullglob -NETWORKS="mainnet testnet stagenet" - -mkdir -p /var/lib/waves/log -if [ ! -f /etc/waves/waves.conf ]; then - echo "Custom '/etc/waves/waves.conf' not found. Using a default one for '${WAVES_NETWORK,,}' network." | tee -a /var/log/waves/waves.log - if [[ $NETWORKS == *"${WAVES_NETWORK,,}"* ]]; then - touch /etc/waves/waves.conf - echo "waves.blockchain.type=${WAVES_NETWORK}" >> /etc/waves/waves.conf - - sed -i 's/include "local.conf"//' /etc/waves/waves.conf - for f in /etc/waves/ext/*.conf; do - echo "Adding $f extension config to waves.conf"; - echo "include required(\"$f\")" >> /etc/waves/waves.conf - done - echo 'include "local.conf"' >> /etc/waves/waves.conf - else - echo "Network '${WAVES_NETWORK,,}' not found. Exiting." - exit 1 - fi -else - echo "Found custom '/etc/waves/waves.conf'. Using it." -fi - -if [ "${WAVES_VERSION}" == "latest" ]; then - filename=$(find /usr/share/waves/lib -name 'waves-all*' -printf '%f\n') - export WAVES_VERSION=$(echo ${filename##*-} | cut -d\. -f1-3) -fi - -[ -n "${WAVES_WALLET_PASSWORD}" ] && JAVA_OPTS="${JAVA_OPTS} -Dwaves.wallet.password=${WAVES_WALLET_PASSWORD}" -[ -n "${WAVES_WALLET_SEED}" ] && JAVA_OPTS="${JAVA_OPTS} -Dwaves.wallet.seed=${WAVES_WALLET_SEED}" - -JAVA_OPTS="${JAVA_OPTS} -Dwaves.data-directory=/var/lib/waves/data -Dwaves.directory=/var/lib/waves" - -echo "Node is starting..." | tee -a /var/log/waves/waves.log -echo "WAVES_HEAP_SIZE='${WAVES_HEAP_SIZE}'" | tee -a /var/log/waves/waves.log -echo "WAVES_LOG_LEVEL='${WAVES_LOG_LEVEL}'" | tee -a /var/log/waves/waves.log -echo "WAVES_VERSION='${WAVES_VERSION}'" | tee -a /var/log/waves/waves.log -echo "WAVES_NETWORK='${WAVES_NETWORK}'" | tee -a /var/log/waves/waves.log -echo "WAVES_WALLET_SEED='${WAVES_WALLET_SEED}'" | tee -a /var/log/waves/waves.log -echo "WAVES_WALLET_PASSWORD='${WAVES_WALLET_PASSWORD}'" | tee -a /var/log/waves/waves.log -echo "JAVA_OPTS='${JAVA_OPTS}'" | tee -a /var/log/waves/waves.log - -exec java -Dlogback.stdout.level=${WAVES_LOG_LEVEL} \ - -XX:+ExitOnOutOfMemoryError \ - -Xmx${WAVES_HEAP_SIZE} \ - -Dlogback.file.directory=/var/log/waves \ - -Dconfig.override_with_env_vars=true \ - ${JAVA_OPTS} \ - -cp "/usr/share/waves/lib/plugins/*:/usr/share/waves/lib/*" \ - com.wavesplatform.Application \ - /etc/waves/waves.conf diff --git a/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesSpec.scala b/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesSpec.scala index d38468f46b..7419e91c41 100644 --- a/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesSpec.scala +++ b/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesSpec.scala @@ -56,6 +56,7 @@ class BlockchainUpdatesSpec extends FreeSpec with Matchers with WithDomain with val subscription = repo.createSubscription(request) for (_ <- 1 until count) d.appendBlock() + Thread.sleep(1000) subscription.cancel() val result = subscription.futureValue diff --git a/node-it/build.sbt b/node-it/build.sbt index 24e3cc1c6b..7c53350bbf 100644 --- a/node-it/build.sbt +++ b/node-it/build.sbt @@ -1,24 +1,18 @@ -import WavesDockerKeys._ - -enablePlugins(WavesDockerPlugin, IntegrationTestsPlugin) +enablePlugins(IntegrationTestsPlugin, sbtdocker.DockerPlugin) description := "NODE integration tests" libraryDependencies ++= Dependencies.it -def stageFiles(ref: ProjectReference): TaskKey[File] = - ref / Universal / stage +imageNames in docker := Seq(ImageName("com.wavesplatform/node-it")) + +dockerfile in docker := NativeDockerfile(baseDirectory.value.getParentFile / "docker" / "Dockerfile") -(Test / test) := (Test / test).dependsOn(Docker / docker).value +buildOptions in docker := BuildOptions() -inTask(docker)( - Seq( - imageNames := Seq(ImageName("com.wavesplatform/node-it")), - exposedPorts := Set(6863, 6869, 6870), // NetworkApi, RestApi, gRPC - additionalFiles ++= Seq( - stageFiles(LocalProject("node")).value, - stageFiles(LocalProject("grpc-server")).value, - (Test / resourceDirectory).value / "template.conf", - (Test / sourceDirectory).value / "container" / "start-waves.sh" - ) - ) +dockerBuildArguments := Map( + "ENABLE_GRPC" -> "true" ) + +val packageAll = taskKey[Unit]("build all packages") +docker := docker.dependsOn(packageAll in LocalProject("root")).value + diff --git a/node-it/src/test/container/start-waves.sh b/node-it/src/test/container/start-waves.sh deleted file mode 100644 index 8f4548f156..0000000000 --- a/node-it/src/test/container/start-waves.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -echo Options: $WAVES_OPTS -exec java $WAVES_OPTS -cp "/opt/waves/lib/*" com.wavesplatform.Application /opt/waves/template.conf diff --git a/node-it/src/test/resources/template.conf b/node-it/src/test/resources/template.conf index a8a6c224b2..5050c280d3 100644 --- a/node-it/src/test/resources/template.conf +++ b/node-it/src/test/resources/template.conf @@ -94,8 +94,8 @@ waves { api-key-different-host = yes } wallet { - file = null - password = "some string as password" + file = "wallet" + password = test } utx { max-scripted-size = 100000 diff --git a/node-it/src/test/scala/com/wavesplatform/it/Docker.scala b/node-it/src/test/scala/com/wavesplatform/it/Docker.scala index e705542856..bc90ccd1ef 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/Docker.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/Docker.scala @@ -33,10 +33,10 @@ import org.apache.commons.compress.archivers.tar.TarArchiveEntry import org.apache.commons.io.IOUtils import org.asynchttpclient.Dsl._ -import scala.jdk.CollectionConverters._ import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.duration._ import scala.concurrent.{Await, Future, blocking} +import scala.jdk.CollectionConverters._ import scala.util.control.NonFatal import scala.util.{Random, Try} @@ -210,18 +210,14 @@ class Docker(suiteConfig: Config = empty, tag: String = "", enableProfiling: Boo .withFallback(nodeConfig) .withFallback(suiteConfig) .withFallback(genesisOverride) + .withFallback(configTemplate) val actualConfig = overrides - .withFallback(configTemplate) .withFallback(defaultApplication()) .withFallback(defaultReference()) .resolve() val networkPort = actualConfig.getString("waves.network.port") - val hostConfig = HostConfig - .builder() - .publishAllPorts(true) - .build() val nodeNumber = nodeName.replace("node", "").toInt val ip = ipForNode(nodeNumber) @@ -240,22 +236,25 @@ class Docker(suiteConfig: Config = empty, tag: String = "", enableProfiling: Boo s"sampling,monitors,sessionname=WavesNode,dir=$ContainerRoot/profiler,logdir=$ContainerRoot,onexit=snapshot " } - val withAspectJ = Option(System.getenv("WITH_ASPECTJ")).fold(false)(_.toBoolean) - if (withAspectJ) config += s"-javaagent:$ContainerRoot/aspectjweaver.jar " config } + val hostConfig = HostConfig + .builder() + .publishAllPorts(true) + .build() + val containerConfig = ContainerConfig .builder() .image(imageName) .networkingConfig(ContainerConfig.NetworkingConfig.create(Map(wavesNetwork.name() -> endpointConfigFor(nodeName)).asJava)) .hostConfig(hostConfig) - .env(s"WAVES_OPTS=$configOverrides") + .env(s"JAVA_OPTS=$configOverrides") .build() val containerId = { val jenkinsJobIdFromEnv = sys.env.get("JENKINS_JOB_ID").fold("")(s => s"-$s") - val containerName = s"${wavesNetwork.name()}-$nodeName$jenkinsJobIdFromEnv" + val containerName = s"${wavesNetwork.name()}-$nodeName$jenkinsJobIdFromEnv" dumpContainers( client.listContainers(DockerClient.ListContainersParam.filter("name", containerName)), "Containers with same name" @@ -349,10 +348,11 @@ class Docker(suiteConfig: Config = empty, tag: String = "", enableProfiling: Boo if (configUpdates != empty) { val renderedConfig = renderProperties(asProperties(configUpdates)) - log.debug("Set new config directly in the script for starting node") - val shPath = "/opt/waves/start-waves.sh" + // Docker do not allow updating ENV https://github.com/moby/moby/issues/8838 :( + log.debug("Set new config directly in the entrypoint.sh script") + val shPath = "/usr/share/waves/bin/entrypoint.sh" val scriptCmd: Array[String] = - Array("sh", "-c", s"sed -i 's|$$WAVES_OPTS.*-cp|$$WAVES_OPTS $renderedConfig -cp|' $shPath && chmod +x $shPath") + Array("sh", "-c", s"sed -i 's|$${JAVA_OPTS}|$${JAVA_OPTS} $renderedConfig|' $shPath && cat $shPath") val execScriptCmd = client.execCreate(node.containerId, scriptCmd).id() client.execStart(execScriptCmd) @@ -525,7 +525,7 @@ class Docker(suiteConfig: Config = empty, tag: String = "", enableProfiling: Boo object Docker { val NodeImageName: String = "com.wavesplatform/node-it:latest" - private val ContainerRoot = Paths.get("/opt/waves") + private val ContainerRoot = Paths.get("/usr/share/waves") private val ProfilerPort = 10001 private val RunId = Option(System.getenv("RUN_ID")).getOrElse(DateTimeFormatter.ofPattern("MM-dd--HH_mm_ss").format(LocalDateTime.now())) @@ -557,7 +557,7 @@ object Docker { def apply(owner: Class[_]): Docker = new Docker(tag = owner.getSimpleName) private def asProperties(config: Config): Properties = { - val jsonConfig = config.root().render(ConfigRenderOptions.concise()) + val jsonConfig = config.resolve().root().render(ConfigRenderOptions.concise()) propsMapper.writeValueAsProperties(jsonMapper.readTree(jsonConfig)) } diff --git a/node/build.sbt b/node/build.sbt index 40322edd4e..4fc1dacd63 100644 --- a/node/build.sbt +++ b/node/build.sbt @@ -22,28 +22,6 @@ inConfig(Compile)( ) ) -val aopMerge: MergeStrategy = new MergeStrategy { - import scala.xml._ - import scala.xml.dtd._ - - override val name = "aopMerge" - override def apply(tempDir: File, path: String, files: Seq[File]): Either[String, Seq[(File, String)]] = { - val dt = DocType("aspectj", PublicID("-//AspectJ//DTD//EN", "http://www.eclipse.org/aspectj/dtd/aspectj.dtd"), Nil) - val file = MergeStrategy.createMergeTarget(tempDir, path) - val xmls: Seq[Elem] = files.map(XML.loadFile) - val aspectsChildren: Seq[Node] = xmls.flatMap(_ \\ "aspectj" \ "aspects" \ "_") - val weaverChildren: Seq[Node] = xmls.flatMap(_ \\ "aspectj" \ "weaver" \ "_") - val options: String = xmls.map(x => (x \\ "aspectj" \ "weaver" \ "@options").text).mkString(" ").trim - val weaverAttr = if (options.isEmpty) Null else new UnprefixedAttribute("options", options, Null) - val aspects = new Elem(null, "aspects", Null, TopScope, false, aspectsChildren: _*) - val weaver = new Elem(null, "weaver", weaverAttr, TopScope, false, weaverChildren: _*) - val aspectj = new Elem(null, "aspectj", Null, TopScope, false, aspects, weaver) - XML.save(file.toString, aspectj, "UTF-8", xmlDecl = false, dt) - IO.append(file, IO.Newline.getBytes(IO.defaultCharset)) - Right(Seq(file -> path)) - } -} - inTask(assembly)( Seq( test := {}, @@ -51,7 +29,6 @@ inTask(assembly)( assemblyMergeStrategy := { case "module-info.class" => MergeStrategy.discard case PathList("META-INF", "io.netty.versions.properties") => MergeStrategy.concat - case PathList("META-INF", "aop.xml") => aopMerge case other => (assemblyMergeStrategy in assembly).value(other) } ) diff --git a/node/src/main/resources/logback.xml b/node/src/main/resources/logback.xml index 7d463dbc04..6c3e185f73 100644 --- a/node/src/main/resources/logback.xml +++ b/node/src/main/resources/logback.xml @@ -10,7 +10,6 @@ - diff --git a/node/src/main/scala/com/wavesplatform/Application.scala b/node/src/main/scala/com/wavesplatform/Application.scala index 2d9a8894de..73e314ce97 100644 --- a/node/src/main/scala/com/wavesplatform/Application.scala +++ b/node/src/main/scala/com/wavesplatform/Application.scala @@ -517,10 +517,6 @@ object Application extends ScorexLogging { Security.setProperty("networkaddress.cache.ttl", "0") Security.setProperty("networkaddress.cache.negative.ttl", "0") - // specify aspectj to use it's build-in infrastructure - // http://www.eclipse.org/aspectj/doc/released/pdguide/trace.html - System.setProperty("org.aspectj.tracing.factory", "default") - args.headOption.getOrElse("") match { case "export" => Exporter.main(args.tail) case "import" => Importer.main(args.tail) diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeScriptTransactionDiffTest.scala b/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeScriptTransactionDiffTest.scala index ef724c8f17..8f03aea75e 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeScriptTransactionDiffTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeScriptTransactionDiffTest.scala @@ -1,7 +1,10 @@ package com.wavesplatform.state.diffs.ci +import scala.collection.immutable + import cats.kernel.Monoid import com.google.protobuf.ByteString +import com.wavesplatform.{NoShrink, TransactionGen} import com.wavesplatform.account._ import com.wavesplatform.block.{Block, BlockHeader, SignedBlockHeader} import com.wavesplatform.common.state.ByteStr @@ -9,48 +12,45 @@ import com.wavesplatform.common.utils.EitherExt2 import com.wavesplatform.db.{DBCacheSettings, WithState} import com.wavesplatform.features.BlockchainFeatures import com.wavesplatform.lagonaki.mocks.TestBlock +import com.wavesplatform.lang.{utils, Global} import com.wavesplatform.lang.contract.DApp import com.wavesplatform.lang.contract.DApp.{CallableAnnotation, CallableFunction} -import com.wavesplatform.lang.directives.values.{DApp => DAppType, _} import com.wavesplatform.lang.directives.{DirectiveDictionary, DirectiveSet} -import com.wavesplatform.lang.script.v1.ExprScript +import com.wavesplatform.lang.directives.values.{DApp => DAppType, _} import com.wavesplatform.lang.script.{ContractScript, Script} +import com.wavesplatform.lang.script.v1.ExprScript +import com.wavesplatform.lang.v1.{compiler, ContractLimits, FunctionHeader} import com.wavesplatform.lang.v1.FunctionHeader.{Native, User} import com.wavesplatform.lang.v1.compiler.Terms import com.wavesplatform.lang.v1.compiler.Terms._ import com.wavesplatform.lang.v1.estimator.v3.ScriptEstimatorV3 +import com.wavesplatform.lang.v1.evaluator.{FunctionIds, ScriptResultV3} import com.wavesplatform.lang.v1.evaluator.FunctionIds.{CREATE_LIST, THROW} -import com.wavesplatform.lang.v1.evaluator.ctx.impl.waves.{FieldNames, WavesContext} import com.wavesplatform.lang.v1.evaluator.ctx.impl.{CryptoContext, PureContext} -import com.wavesplatform.lang.v1.evaluator.{FunctionIds, ScriptResultV3} +import com.wavesplatform.lang.v1.evaluator.ctx.impl.waves.{FieldNames, WavesContext} import com.wavesplatform.lang.v1.parser.{Expressions, Parser} import com.wavesplatform.lang.v1.traits.Environment -import com.wavesplatform.lang.v1.{ContractLimits, FunctionHeader, compiler} -import com.wavesplatform.lang.{Global, utils} import com.wavesplatform.protobuf.dapp.DAppMeta import com.wavesplatform.settings.{TestFunctionalitySettings, TestSettings} import com.wavesplatform.state._ +import com.wavesplatform.state.diffs.{produce, ENOUGH_AMT, FeeValidation} import com.wavesplatform.state.diffs.FeeValidation.FeeConstants import com.wavesplatform.state.diffs.invoke.{InvokeDiffsCommon, InvokeScriptTransactionDiff} -import com.wavesplatform.state.diffs.{ENOUGH_AMT, FeeValidation, produce} +import com.wavesplatform.transaction.{Asset, _} import com.wavesplatform.transaction.Asset.{IssuedAsset, Waves} import com.wavesplatform.transaction.TxValidationError._ import com.wavesplatform.transaction.assets._ +import com.wavesplatform.transaction.smart.{InvokeScriptTransaction, SetScriptTransaction} import com.wavesplatform.transaction.smart.InvokeScriptTransaction.Payment import com.wavesplatform.transaction.smart.script.ScriptCompiler import com.wavesplatform.transaction.smart.script.trace.{AssetVerifierTrace, InvokeScriptTrace} -import com.wavesplatform.transaction.smart.{InvokeScriptTransaction, SetScriptTransaction} import com.wavesplatform.transaction.transfer.TransferTransaction -import com.wavesplatform.transaction.{Asset, _} import com.wavesplatform.utils._ -import com.wavesplatform.{NoShrink, TransactionGen} import org.scalacheck.{Arbitrary, Gen} import org.scalamock.scalatest.MockFactory import org.scalatest.{EitherValues, Inside, Matchers, PropSpec} import org.scalatestplus.scalacheck.{ScalaCheckPropertyChecks => PropertyChecks} -import scala.collection.immutable - class InvokeScriptTransactionDiffTest extends PropSpec with PropertyChecks @@ -1444,7 +1444,7 @@ class InvokeScriptTransactionDiffTest } forAll(for { - proofsCount <- Gen.choose(2, 9) + proofsCount <- Gen.choose(2, 8) r <- preconditionsAndSetContractWithVerifier(multiSigCheckDApp(proofsCount), writeSetWithKeyLength(_)) } yield (r._1, r._2, r._3, r._4, proofsCount)) { case (genesis, setVerifier, setContract, ci, proofsCount) => diff --git a/project/WavesDockerPlugin.scala b/project/WavesDockerPlugin.scala deleted file mode 100644 index 6e774a7814..0000000000 --- a/project/WavesDockerPlugin.scala +++ /dev/null @@ -1,47 +0,0 @@ -import java.io.File - -import WavesDockerKeys._ -import sbt.plugins.JvmPlugin -import sbt.{AutoPlugin, Def, Plugins, inTask, taskKey} -import sbtdocker.DockerPlugin -import sbtdocker.DockerPlugin.autoImport._ - -object WavesDockerPlugin extends AutoPlugin { - override def requires: Plugins = JvmPlugin && DockerPlugin - - override def projectSettings: Seq[Def.Setting[_]] = - inTask(docker)( - Seq( - additionalFiles := Seq.empty, - exposedPorts := Set.empty, - baseImage := "anapsix/alpine-java:8_server-jre", - dockerfile := { - val yourKitArchive = "YourKit-JavaProfiler-2019.8-docker.zip" - val bin = "/opt/waves/start-waves.sh" - - new Dockerfile { - from(baseImage.value) - - runRaw(s"""mkdir -p /opt/waves && \\ - |apk update && \\ - |apk add --no-cache openssl ca-certificates && \\ - |wget --quiet "https://search.maven.org/remotecontent?filepath=org/aspectj/aspectjweaver/1.9.1/aspectjweaver-1.9.1.jar" -O /opt/waves/aspectjweaver.jar && \\ - |wget --quiet "https://www.yourkit.com/download/docker/$yourKitArchive" -P /tmp/ && \\ - |unzip /tmp/$yourKitArchive -d /usr/local && \\ - |rm -f /tmp/$yourKitArchive""".stripMargin) - - add(additionalFiles.value, "/opt/waves/") - runShell("chmod", "+x", bin) - entryPoint(bin) - expose(exposedPorts.value.toSeq: _*) - } - }, - buildOptions := BuildOptions(removeIntermediateContainers = BuildOptions.Remove.OnSuccess) - )) -} - -object WavesDockerKeys { - val additionalFiles = taskKey[Seq[File]]("Additional files to copy to /opt/waves") - val exposedPorts = taskKey[Set[Int]]("Exposed ports") - val baseImage = taskKey[String]("A base image for this container") -} diff --git a/project/plugins.sbt b/project/plugins.sbt index 43195ce887..b9f5504cd4 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -13,7 +13,7 @@ Seq( "com.typesafe.sbt" % "sbt-native-packager" % "1.3.25", "org.scalastyle" %% "scalastyle-sbt-plugin" % "1.0.0", "org.scoverage" % "sbt-scoverage" % "1.6.1", - "se.marcuslonnberg" % "sbt-docker" % "1.4.1", + "se.marcuslonnberg" % "sbt-docker" % "1.8.1", "com.typesafe.sbt" % "sbt-git" % "1.0.0", "org.scala-js" % "sbt-scalajs" % "0.6.33", "org.portable-scala" % "sbt-scalajs-crossproject" % "0.6.0", @@ -24,7 +24,7 @@ Seq( ).map(addSbtPlugin) libraryDependencies ++= Seq( - "com.fasterxml.jackson.module" % "jackson-module-scala_2.12" % "2.9.9", + "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.12.1", "org.hjson" % "hjson" % "3.0.0", "org.vafer" % "jdeb" % "1.5" artifacts Artifact("jdeb", "jar", "jar"), "org.slf4j" % "jcl-over-slf4j" % "1.7.30",