diff --git a/.github/workflows/check-pr.yaml b/.github/workflows/check-pr.yaml index 0cb67e1254..1c26684e1e 100644 --- a/.github/workflows/check-pr.yaml +++ b/.github/workflows/check-pr.yaml @@ -1,33 +1,22 @@ name: Check PR on: - push: - branches: - - version-[0-9].[0-9]+.x - tags: - - v[0-9].[0-9]+.[0-9]+ pull_request: jobs: check-pr: - runs-on: ubuntu-latest + name: Check PR + runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: - distribution: 'zulu' + distribution: 'temurin' java-version: '11' - - name: Cache SBT - uses: actions/cache@v3 - with: - path: ~/.sbt - key: sbt-cache-${{ hashFiles('project/build.properties') }} - - name: Cache Coursier - uses: actions/cache@v3 - with: - path: ~/.cache/coursier - key: coursier-cache + cache: 'sbt' + gpg-private-key: ${{ secrets.OSSRH_GPG_KEY }} + gpg-passphrase: ${{ secrets.OSSRH_GPG_PASSPHRASE }} - name: Check PR - run: sbt --mem 6144 --batch ";checkPR;completeQaseRun" + run: sbt -J-Xlog:gc*=debug:file=./gc.log --mem 8096 --batch ";checkPR;completeQaseRun" env: QASE_ENABLE: true QASE_RUN_NAME: checkPR @@ -35,7 +24,7 @@ jobs: QASE_PROJECT_CODE: PR QASE_API_TOKEN: ${{ secrets.QASE_API_TOKEN }} CHECKPR_RUN_ID: ${{ github.run_id }} - - uses: dorny/paths-filter@v2 + - uses: dorny/paths-filter@v3 id: filter with: filters: | @@ -57,33 +46,23 @@ jobs: find swopfi-smart-contracts/dApps -name "*.ride" -type f -exec java -jar lang/jvm/target/file-compiler.jar {} +; - name: Clean cache run: find ~/.cache/coursier -type d -name '*SNAPSHOT' | xargs rm -vrf {} \; - - name: Prepare version - if: false # steps.filter.outputs.lang == 'true' - id: sbt-version - run: | - sbt_version=$(cut -d\" -f2 version.sbt) - git_ref=${GITHUB_REF##*/} - echo ${{ github.event }} - pr_number=${{ github.event.number }} - if [[ $git_ref =~ v[0-9]+\.[0-9]+\.[0-9]+$ ]] ; then - if [[ v$sbt_version != $git_ref ]] ; then - echo SBT version $sbt_version does not match tag $git_ref - exit 1 - fi - else - if [[ $pr_number != "" ]] ; then - sbt_version=$sbt_version-$pr_number-SNAPSHOT - else - sbt_version=$sbt_version-SNAPSHOT - fi - echo "ThisBuild / version := \"$sbt_version\"" >> version.sbt - echo Setting version to $sbt_version - fi - - name: Publish lang - run: sbt ci-release - if: false # steps.filter.outputs.lang == 'true' + - name: Publish snapshots + if: ${{ contains(github.event.pull_request.labels.*.name, 'publish-snapshots') }} env: - PGP_PASSPHRASE: ${{ secrets.OSSRH_GPG_PASSPHRASE }} - PGP_SECRET: ${{ secrets.OSSRH_GPG_KEY_BASE64 }} SONATYPE_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} SONATYPE_USERNAME: ${{ secrets.OSSRH_USERNAME }} + PGP_PASSPHRASE: ${{ secrets.OSSRH_GPG_PASSPHRASE }} + run: | + version=$(echo ${{ github.base_ref }} | awk -F '[-\.]' '{print $2"."$3}') + pr_number=${{ github.event.number }} + sbt -Dproject.version=$version-$pr_number-SNAPSHOT --mem 4096 --batch publishSigned + - name: Save debug data + uses: actions/upload-artifact@v4 + if: always() + with: + if-no-files-found: ignore + name: debug-data + path: | + gc.log + hs*.log + core* diff --git a/.github/workflows/publish-docker-image.yml b/.github/workflows/publish-docker-image.yml new file mode 100644 index 0000000000..ecf996bc27 --- /dev/null +++ b/.github/workflows/publish-docker-image.yml @@ -0,0 +1,62 @@ +name: Publish Docker image + +on: + workflow_dispatch: + inputs: + dockerTag: + description: 'Docker tag' + required: true + type: string + baseImage: + description: 'Base image' + required: true + default: 'eclipse-temurin:11-jre-noble' + type: string + +env: + IMAGE_NAME: ghcr.io/${{ github.repository }} + +jobs: + build: + runs-on: ubuntu-22.04 + permissions: + contents: read + packages: write + attestations: write + id-token: write + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '11' + cache: 'sbt' + - run: sbt --mem 4096 --batch buildTarballsForDocker + - uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - uses: docker/setup-buildx-action@v3 + - uses: docker/metadata-action@v5 + id: meta + with: + images: ${{ env.IMAGE_NAME }} + flavor: latest=false + tags: type=raw,value=${{ inputs.dockerTag }} + labels: | + org.opencontainers.image.source=https://github.com/${{ github.repository }} + org.opencontainers.image.licenses=MIT + org.opencontainers.image.description="Waves Node" + - uses: docker/build-push-action@v5 + id: push + with: + context: ./docker + platforms: linux/amd64,linux/arm64 + push: true + pull: true + build-args: baseImage=${{ inputs.baseImage }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/publish-docker-node.yaml b/.github/workflows/publish-docker-node.yaml deleted file mode 100644 index 8fddb878c9..0000000000 --- a/.github/workflows/publish-docker-node.yaml +++ /dev/null @@ -1,105 +0,0 @@ -name: Build docker images for node - -on: - release: - types: [published] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Setup Java - uses: actions/setup-java@v3 - with: - distribution: 'zulu' - java-version: '11' - - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Cache SBT - uses: actions/cache@v3 - with: - path: ~/.sbt - key: sbt-cache-${{ hashFiles('project/build.properties') }} - - - name: Cache Coursier - uses: actions/cache@v3 - with: - path: ~/.cache/coursier - key: coursier-cache - - - name: Build sources - run: | - sbt --mem 2048 -J-XX:+UseG1GC -Dcoursier.cache=~/.cache/coursier -Dsbt.boot.directory=~/.sbt ;buildTarballsForDocker;buildRIDERunnerForDocker - - - name: Setup Docker buildx - uses: docker/setup-buildx-action@v2 - - - name: Log into Docker Hub registry - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USER }} - password: ${{ secrets.DOCKERHUB_PASSWORD }} - - - name: Extract Docker public node metadata - id: meta-public - uses: docker/metadata-action@v4 - with: - images: wavesplatform/wavesnode - flavor: | - latest=false - tags: | - type=match,pattern=v(.*),group=1 - type=raw,value=latest,enable=${{ github.event.release.prerelease == false }} - - - name: Extract Docker private node metadata - id: meta-private - uses: docker/metadata-action@v4 - with: - images: wavesplatform/waves-private-node - flavor: | - latest=false - tags: | - type=ref,event=tag - type=raw,value=latest,enable=${{ github.event.release.prerelease == false }} - - - name: Extract Docker RIDE runner metadata - id: meta-ride-runner - uses: docker/metadata-action@v4 - with: - images: wavesplatform/ride-runner - flavor: | - latest=false - tags: | - type=match,pattern=v(.*),group=1 - type=raw,value=latest,enable=${{ github.event.release.prerelease == false }} - - - name: Build and push Docker public image - id: build-and-push-public - uses: docker/build-push-action@v3 - with: - context: ./docker - push: true - pull: true - tags: ${{ steps.meta-public.outputs.tags }} - - - name: Build and push Docker private image - id: build-and-push-private - uses: docker/build-push-action@v3 - with: - context: ./docker/private - push: true - pull: true - tags: ${{ steps.meta-private.outputs.tags }} - build-args: | - NODE_TAG=${{ steps.meta-public.outputs.version }} - - - name: Build and push Docker RIDE runner image - id: build-and-push-ride-runner - uses: docker/build-push-action@v3 - with: - context: ./ride-runner/docker - push: true - pull: true - tags: ${{ steps.meta-ride-runner.outputs.tags }} diff --git a/.github/workflows/publish-node-sbt-builder.yml b/.github/workflows/publish-node-sbt-builder.yml deleted file mode 100644 index 91e3a2ab44..0000000000 --- a/.github/workflows/publish-node-sbt-builder.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Build SBT docker builder for node - -on: - release: - types: [published] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - id: extract-versions - run: | - echo "waves-version=$(cut -d\" -f2 version.sbt)" >> $GITHUB_OUTPUT - echo "sbt-version=$(cut -d= -f2 project/build.properties)" >> $GITHUB_OUTPUT - - uses: docker/setup-buildx-action@v2 - - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USER }} - password: ${{ secrets.DOCKERHUB_PASSWORD }} - - uses: docker/build-push-action@v3 - with: - context: ./docker - file: ./docker/node-sbt-builder.Dockerfile - push: true - pull: true - tags: wavesplatform/node-sbt-builder:${{ steps.extract-versions.outputs.waves-version }} - build-args: | - WAVES_VERSION=${{ steps.extract-versions.outputs.waves-version }} - SBT_VERSION=${{ steps.extract-versions.outputs.sbt-version }} diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml new file mode 100644 index 0000000000..4db33b70be --- /dev/null +++ b/.github/workflows/publish-release.yml @@ -0,0 +1,147 @@ +name: Publish Release + +on: + release: + types: [published] + +jobs: + publish-node-image: + name: Publish node image + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '11' + cache: 'sbt' + + - name: Build tarballs for Docker + run: sbt --mem 4096 --batch ';buildTarballsForDocker;buildRIDERunnerForDocker' + + - name: Setup Docker buildx + uses: docker/setup-buildx-action@v3 + + - name: Log into Docker Hub registry + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USER }} + password: ${{ secrets.DOCKERHUB_PASSWORD }} + + - name: Extract Docker public node metadata + id: meta-public + uses: docker/metadata-action@v5 + with: + images: wavesplatform/wavesnode + flavor: | + latest=false + tags: | + type=match,pattern=v(.*),group=1 + type=raw,value=latest,enable=${{ github.event.release.prerelease == false }} + + - name: Extract Docker private node metadata + id: meta-private + uses: docker/metadata-action@v5 + with: + images: wavesplatform/waves-private-node + flavor: | + latest=false + tags: | + type=ref,event=tag + type=raw,value=latest,enable=${{ github.event.release.prerelease == false }} + + - name: Extract Docker RIDE runner metadata + id: meta-ride-runner + uses: docker/metadata-action@v5 + with: + images: wavesplatform/ride-runner + flavor: | + latest=false + tags: | + type=match,pattern=v(.*),group=1 + type=raw,value=latest,enable=${{ github.event.release.prerelease == false }} + + - name: Build and push Docker public image + id: build-and-push-public + uses: docker/build-push-action@v5 + with: + context: ./docker + push: true + pull: true + tags: ${{ steps.meta-public.outputs.tags }} + + - name: Build and push Docker private image + id: build-and-push-private + uses: docker/build-push-action@v5 + with: + context: ./docker/private + push: true + pull: true + tags: ${{ steps.meta-private.outputs.tags }} + build-args: | + NODE_TAG=${{ steps.meta-public.outputs.version }} + + - name: Build and push Docker RIDE runner image + id: build-and-push-ride-runner + uses: docker/build-push-action@v5 + with: + context: ./ride-runner/docker + push: true + pull: true + tags: ${{ steps.meta-ride-runner.outputs.tags }} + + publish-node-sbt-builder-image: + name: Publish node SBT builder image + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + - id: extract-versions + run: | + echo "waves-version=$(cut -d\" -f2 version.sbt)" >> $GITHUB_OUTPUT + echo "sbt-version=$(cut -d= -f2 project/build.properties)" >> $GITHUB_OUTPUT + - uses: docker/setup-buildx-action@v3 + - uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USER }} + password: ${{ secrets.DOCKERHUB_PASSWORD }} + - uses: docker/build-push-action@v5 + with: + context: ./docker + file: ./docker/node-sbt-builder.Dockerfile + push: true + pull: true + tags: wavesplatform/node-sbt-builder:${{ steps.extract-versions.outputs.waves-version }} + build-args: | + WAVES_VERSION=${{ steps.extract-versions.outputs.waves-version }} + SBT_VERSION=${{ steps.extract-versions.outputs.sbt-version }} + + publish-release-jars: + name: Publish jars to Sonatype + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - id: sbt-version + run: | + sbt_version=$(cut -d\" -f2 version.sbt) + echo "sbt_version=$sbt_version" >> "$GITHUB_OUTPUT" + - if: ${{ format('v{0}', steps.sbt-version.outputs.sbt_version) != github.ref_name }} + env: + SBT_VERSION: ${{ steps.sbt-version.outputs.sbt_version }} + RELEASE_VERSION: ${{ github.ref_name }} + run: | + echo "::error::Release version $RELEASE_VERSION does not match SBT version $SBT_VERSION" + exit 1 + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '11' + cache: 'sbt' + gpg-private-key: ${{ secrets.OSSRH_GPG_KEY }} + gpg-passphrase: ${{ secrets.OSSRH_GPG_PASSPHRASE }} + - name: Publish release jars + env: + SONATYPE_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} + SONATYPE_USERNAME: ${{ secrets.OSSRH_USERNAME }} + PGP_PASSPHRASE: ${{ secrets.OSSRH_GPG_PASSPHRASE }} + run: | + sbt --mem 4096 --batch ";publishSigned;sonatypeBundleRelease" diff --git a/.github/workflows/push-default-branch.yml b/.github/workflows/push-default-branch.yml new file mode 100644 index 0000000000..e8b7a810ff --- /dev/null +++ b/.github/workflows/push-default-branch.yml @@ -0,0 +1,36 @@ +name: Publish Artifacts + +on: + push: + branches: + - 'version-1.*.*' + +jobs: + update-graph: + name: Update Dependency Graph + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - uses: scalacenter/sbt-dependency-submission@v3 + with: + configs-ignore: test compile-internal provided + publish-snapshot: + name: Publish Snapshots to Sonatype + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '11' + cache: 'sbt' + gpg-private-key: ${{ secrets.OSSRH_GPG_KEY }} + gpg-passphrase: ${{ secrets.OSSRH_GPG_PASSPHRASE }} + - name: Publish snapshots + env: + SONATYPE_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} + SONATYPE_USERNAME: ${{ secrets.OSSRH_USERNAME }} + PGP_PASSPHRASE: ${{ secrets.OSSRH_GPG_PASSPHRASE }} + run: | + version=$(echo ${{ github.ref }} | awk -F '[-.]' '{print $2"."$3}')-SNAPSHOT + sbt -Dproject.version=$version --mem 4096 --batch publishSigned diff --git a/.gitignore b/.gitignore index 690d21a5dc..37bf424325 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ .ensime .ensime_cache/ .bsp +.bloop +.metals # scala build folders and files target diff --git a/README.md b/README.md index 7776c20a6f..bcac3effac 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@

-> Waves is an open source [blockchain protocol](https://waves.tech/waves-protocol).
+> Waves is an open source [blockchain protocol](https://waves.tech).
You can use it to build your own decentralized applications. Waves provides full blockchain ecosystem including smart contracts language called RIDE. diff --git a/benchmark/src/main/scala/com/wavesplatform/state/bench/DataTestData.scala b/benchmark/src/main/scala/com/wavesplatform/state/bench/DataTestData.scala index a8fef7b3ef..74324b8d73 100644 --- a/benchmark/src/main/scala/com/wavesplatform/state/bench/DataTestData.scala +++ b/benchmark/src/main/scala/com/wavesplatform/state/bench/DataTestData.scala @@ -4,7 +4,7 @@ import java.nio.charset.StandardCharsets import com.wavesplatform.common.state.ByteStr import com.wavesplatform.lang.v1.traits.DataType -import scodec.Codec +import scodec.{Codec, ValueCodecEnrichedWithHListSupport, HListCodecEnrichedWithHListSupport, TransformSyntax} import scodec.bits.* import scodec.codecs.* diff --git a/benchmark/src/test/scala/com/wavesplatform/lang/v1/BigIntOpsBenchmark.scala b/benchmark/src/test/scala/com/wavesplatform/lang/v1/BigIntOpsBenchmark.scala index 0ae875124d..47892fe9cc 100644 --- a/benchmark/src/test/scala/com/wavesplatform/lang/v1/BigIntOpsBenchmark.scala +++ b/benchmark/src/test/scala/com/wavesplatform/lang/v1/BigIntOpsBenchmark.scala @@ -196,7 +196,7 @@ class BigIntOpsSt { val maxSqrt = CONST_BIGINT(BigInt("57896044618658097711785492504343953926634992332820282019728792003956564819968")) val three = CONST_BIGINT(3) val two = CONST_BIGINT(2) - val list = ARR((PureContext.BigIntMin to PureContext.BigIntMin + PureContext.MaxListLengthV4 - 1).map(CONST_BIGINT), limited = true).explicitGet() + val list = ARR((PureContext.BigIntMin to PureContext.BigIntMin + PureContext.MaxListLengthV4 - 1).map(CONST_BIGINT.apply), limited = true).explicitGet() val listReversed = ARR(list.xs.reverse, limited = true).explicitGet() val maxBytes = PureContext.BigIntMax.toByteArray diff --git a/benchmark/src/test/scala/com/wavesplatform/lang/v1/CompilerBenchmark.scala b/benchmark/src/test/scala/com/wavesplatform/lang/v1/CompilerBenchmark.scala index 7f9dfd00d3..6eef7baa20 100644 --- a/benchmark/src/test/scala/com/wavesplatform/lang/v1/CompilerBenchmark.scala +++ b/benchmark/src/test/scala/com/wavesplatform/lang/v1/CompilerBenchmark.scala @@ -18,7 +18,7 @@ import org.openjdk.jmh.infra.Blackhole class CompilerBenchmark { @Benchmark - def serialize_test(st: St, bh: Blackhole): Unit = bh.consume(ScriptCompiler(st.scriptString, isAssetScript = false, ScriptEstimatorV2).explicitGet()._1) + def serialize_test(st: St, bh: Blackhole): Unit = bh.consume(ScriptCompiler.compile(st.scriptString, ScriptEstimatorV2).explicitGet()._1) } object CompilerBenchmark { diff --git a/build-with-docker.sh b/build-with-docker.sh index c2cc34110e..9bc3f10eb6 100755 --- a/build-with-docker.sh +++ b/build-with-docker.sh @@ -7,4 +7,4 @@ docker run \ -e HOME=/opt/sbt/home \ -w /src \ --rm -it wavesplatform/node-sbt-builder:$WAVES_VERSION \ - /bin/sh -c "sbt --batch --mem 2048 packageAll" + /bin/sh -c "sbt --batch --mem 4096 packageAll" diff --git a/build.sbt b/build.sbt index f56a44abf2..f30f343293 100644 --- a/build.sbt +++ b/build.sbt @@ -13,7 +13,7 @@ enablePlugins(GitVersioning) git.uncommittedSignifier := Some("DIRTY") git.useGitDescribe := true ThisBuild / git.useGitDescribe := true -ThisBuild / PB.protocVersion := "3.25.1" // https://protobuf.dev/support/version-support/#java +ThisBuild / PB.protocVersion := "3.25.5" // https://protobuf.dev/support/version-support/#java lazy val lang = crossProject(JSPlatform, JVMPlatform) @@ -69,13 +69,23 @@ lazy val `lang-tests-js` = project testFrameworks += new TestFramework("utest.runner.Framework") ) -lazy val node = project.dependsOn(`lang-jvm`, `lang-testkit` % "test;test->test") +lazy val node = project.dependsOn(`lang-jvm`) -lazy val `grpc-server` = project.dependsOn(node % "compile;test->test;runtime->provided") -lazy val `ride-runner` = project.dependsOn(node % "compile;test->test", `grpc-server`) -lazy val `node-it` = project.dependsOn(node % "compile;test->test", `lang-testkit`, `repl-jvm`, `grpc-server`) -lazy val `node-generator` = project.dependsOn(node % "compile->test") -lazy val benchmark = project.dependsOn(node % "compile;test->test") +lazy val `node-testkit` = project + .in(file("node/testkit")) + .dependsOn(`node`, `lang-testkit`) + +lazy val `node-tests` = project + .in(file("node/tests")) + .dependsOn(`lang-testkit` % "test->test", `node-testkit`) + .settings(libraryDependencies ++= Dependencies.nodeTests) + +lazy val `grpc-server` = + project.dependsOn(node % "compile;runtime->provided", `node-testkit`, `node-tests` % "test->test") +lazy val `ride-runner` = project.dependsOn(node, `grpc-server`, `node-tests` % "test->test") +lazy val `node-it` = project.dependsOn(`repl-jvm`, `grpc-server`, `node-tests` % "test->test") +lazy val `node-generator` = project.dependsOn(node, `node-testkit`, `node-tests` % "compile->test") +lazy val benchmark = project.dependsOn(node, `node-tests` % "test->test") lazy val repl = crossProject(JSPlatform, JVMPlatform) .withoutSuffixFor(JVMPlatform) @@ -105,7 +115,8 @@ lazy val `repl-jvm` = repl.jvm ) ) -lazy val `repl-js` = repl.js.dependsOn(`lang-js`) +lazy val `repl-js` = repl.js + .dependsOn(`lang-js`) .settings( libraryDependencies += "org.scala-js" %%% "scala-js-macrotask-executor" % "1.1.1" ) @@ -123,6 +134,8 @@ lazy val `waves-node` = (project in file(".")) `repl-jvm`, node, `node-it`, + `node-testkit`, + `node-tests`, `node-generator`, benchmark, `repl-js`, @@ -132,7 +145,7 @@ lazy val `waves-node` = (project in file(".")) inScope(Global)( Seq( - scalaVersion := "2.13.12", + scalaVersion := "2.13.15", organization := "com.wavesplatform", organizationName := "Waves Platform", organizationHomepage := Some(url("https://wavesplatform.com")), @@ -150,7 +163,8 @@ inScope(Global)( "-Xlint", "-Wconf:cat=deprecation&site=com.wavesplatform.api.grpc.*:s", // Ignore gRPC warnings "-Wconf:cat=deprecation&site=com.wavesplatform.protobuf.transaction.InvokeScriptResult.*:s", // Ignore deprecated argsBytes - "-Wconf:cat=deprecation&site=com.wavesplatform.state.InvokeScriptResult.*:s" + "-Wconf:cat=deprecation&site=com.wavesplatform.state.InvokeScriptResult.*:s", + "-Wconf:cat=deprecation&site=com\\.wavesplatform\\.(lang\\..*|JsApiUtils)&origin=com\\.wavesplatform\\.lang\\.v1\\.compiler\\.Terms\\.LET_BLOCK:s" ), crossPaths := false, cancelable := true, @@ -168,7 +182,6 @@ inScope(Global)( network := Network.default(), instrumentation := false, resolvers ++= Resolver.sonatypeOssRepos("releases") ++ Resolver.sonatypeOssRepos("snapshots") ++ Seq(Resolver.mavenLocal), - Compile / doc / sources := Seq.empty, Compile / packageDoc / publishArtifact := false, concurrentRestrictions := Seq(Tags.limit(Tags.Test, math.min(EvaluateTask.SystemProcessors, 8))), excludeLintKeys ++= Set( @@ -217,8 +230,8 @@ checkPRRaw := Def (`repl-jvm` / Test / test).value (`lang-js` / Compile / fastOptJS).value (`lang-tests-js` / Test / test).value -// (`grpc-server` / Test / test).value - (node / Test / test).value + (`grpc-server` / Test / test).value + (`node-tests` / Test / test).value (`repl-js` / Compile / fastOptJS).value (`node-it` / Test / compile).value (benchmark / Test / compile).value diff --git a/docker/Dockerfile b/docker/Dockerfile index c9ee2f66f0..1ffdf2a56a 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,27 +1,18 @@ -FROM eclipse-temurin:11-jre-jammy +ARG baseImage=eclipse-temurin:11-jre-noble +FROM $baseImage ENV WAVES_LOG_LEVEL=INFO ENV WAVES_HEAP_SIZE=2g ENV WAVES_NETWORK=mainnet -ENV YOURKIT_VERSION=2023.5 - SHELL ["/bin/bash", "-c"] -# Additional dependencies -RUN apt-get update && apt-get install -y wget unzip gosu || exit 1; \ - export YOURKIT_ARCHIVE="YourKit-JavaProfiler-$YOURKIT_VERSION-docker.zip"; \ - wget --quiet "https://www.yourkit.com/download/docker/$YOURKIT_ARCHIVE" -P /tmp/ && unzip /tmp/$YOURKIT_ARCHIVE -d /usr/local || exit 1; \ - # Clean - apt-get remove -y wget unzip && apt-get autoremove -y && apt-get autoclean && rm -rf /var/lib/apt/lists/* - # Node files ENV WVDATA=/var/lib/waves ENV WVLOG=/var/log/waves ENV WAVES_INSTALL_PATH=/usr/share/waves ENV WAVES_CONFIG=/etc/waves/waves.conf COPY target /tmp/ -COPY waves.conf.template $WAVES_CONFIG # Setup node COPY entrypoint.sh $WAVES_INSTALL_PATH/bin/entrypoint.sh diff --git a/docker/README.md b/docker/README.md index c616c8ddb9..031b2a6d65 100644 --- a/docker/README.md +++ b/docker/README.md @@ -28,39 +28,39 @@ It is highly recommended to read more about [Waves Node configuration](https://d ## Running Docker image + + ### Configuration options 1. The image supports Waves Node config customization. To change a config field use corresponding JVM options. JVM options can be sent to JVM using `JAVA_OPTS` environment variable. Please refer to ([complete configuration file](https://github.com/wavesplatform/Waves/blob/master/node/src/main/resources/application.conf)) to get the full path of the configuration item you want to change. -``` -docker run -v /docker/waves/waves-data:/var/lib/waves -v /docker/waves/waves-config:/etc/waves -p 6869:6869 -p 6862:6862 -e JAVA_OPTS="-Dwaves.rest-api.enable=yes -Dwaves.wallet.password=myWalletSuperPassword" -ti wavesplatform/wavesnode -``` + ``` + docker run -v /docker/waves/waves-data:/var/lib/waves -v /docker/waves/waves-config:/etc/waves -p 6869:6869 -p 6862:6862 -e JAVA_OPTS="-Dwaves.rest-api.enable=yes -Dwaves.wallet.password=myWalletSuperPassword" -ti wavesplatform/wavesnode + ``` -2. Waves Node is looking for a config in the directory `/etc/waves/waves.conf` which can be mounted using Docker volumes. During image build, a default configuration will be copied to this directory. While running container if the value of `WAVES_NETWORK` is not `mainnet`, `testnet` or `stagenet`, default configuration won't be enough for correct node working. This is a scenario of using `CUSTOM` network - correct configuration must be provided when running container. If you use `CUSTOM` network and `/etc/waves/waves.conf` is NOT found Waves Node container will exit. +2. Waves Node is looking for a config in the directory `/etc/waves/waves.conf` which can be mounted using Docker volumes. For custom networks, correct configuration file must be provided when running container. If you use `CUSTOM` network and `/etc/waves/waves.conf` is NOT found Waves Node container will exit. -3. By default, `/etc/waves/waves.conf` config includes `/etc/waves/local.conf`. Custom `/etc/waves/local.conf` can be used to override default config entries. Custom `/etc/waves/waves.conf` can be used to override or the whole configuration. For additional information about Docker volumes mapping please refer to `Managing data` item. +3. You can use custom config to override or the whole configuration. For additional information about Docker volumes mapping please refer to `Managing data` item. 4. You can override the default executable by using the following syntax: -``` -docker run -it wavesplatform/wavesnode [command] [args] -``` + ``` + docker run -it wavesplatform/wavesnode [command] [args] + ``` ### Environment variables -**You can run container with predefined environment variables:** - -| Env variable | Description | -|-----------------------------------|--------------| -| `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.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. | +The following environment variables can be passed to the container: -**Note: All variables are optional.** +| Env variable | Description | +|-------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `WAVES_WALLET_SEED` | Base58 encoded seed, sets `-Dwaves.wallet.seed` system property. | +| `WAVES_WALLET_PASSWORD` | Password for the wallet file, sets `-Dwaves.wallet.password` system property. | +| `WAVES_LOG_LEVEL` | Node stdout 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 (`-Xmx=[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. | -**Note: Environment variables override values in the configuration file.** +All environment variables are optional, however you need to specify at least the desired network and wallet password (via environment variables, additional system properties defined in the `JAVA_OPTS` environment variable, or in the config file). ### Managing data We recommend to store the blockchain state as well as Waves configuration on the host side. As such, consider using Docker volumes mapping to map host directories inside the container: @@ -86,7 +86,7 @@ Once container is launched it will create: - `/docker/waves/waves-config/waves.conf` - default Waves config -3. If you already have Waves Node configuration/data - place it in the corresponsing directories +3. If you already have Waves Node configuration/data - place it in the corresponding directories 4. Add the appropriate arguments to ```docker run``` command: ``` @@ -188,5 +188,5 @@ Full node configuration is available on Github in `waves.custom.conf`: https://g You can use the following tags: -- `latest` - currrent version of Mainnet +- `latest` - current version of Mainnet - `vX.X.X` - specific version of Waves Node diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 1fd46715e4..9d01196ea0 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -1,29 +1,30 @@ #!/bin/bash -shopt -s nullglob -logEcho() { - echo $1 | gosu waves tee -a /var/log/waves/waves.log -} -[ -n "${YOURKIT_OPTS}" ] && JAVA_OPTS="$JAVA_OPTS -agentpath:/usr/local/YourKit-JavaProfiler-$YOURKIT_VERSION/bin/linux-x86-64/libyjpagent.so=$YOURKIT_OPTS" -JAVA_OPTS="${JAVA_OPTS} -Dwaves.defaults.blockchain.type=$WAVES_NETWORK -Dwaves.defaults.directory=$WVDATA" - -logEcho "Node is starting..." -logEcho "WAVES_HEAP_SIZE='${WAVES_HEAP_SIZE}'" -logEcho "WAVES_LOG_LEVEL='${WAVES_LOG_LEVEL}'" -logEcho "JAVA_OPTS='${JAVA_OPTS}'" - -JAVA_OPTS="-Dlogback.stdout.level=${WAVES_LOG_LEVEL} - -XX:+ExitOnOutOfMemoryError +JAVA_OPTS="-XX:+ExitOnOutOfMemoryError -Xmx${WAVES_HEAP_SIZE} - -Dlogback.file.directory=$WVLOG - -Dconfig.override_with_env_vars=true + --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED + -Dlogback.stdout.level=${WAVES_LOG_LEVEL} + -Dlogback.file.directory=${WVLOG} + -Dwaves.config.directory=/etc/waves + -Dwaves.defaults.blockchain.type=${WAVES_NETWORK} + -Dwaves.directory=${WVDATA} + -Dwaves.rest-api.bind-address=0.0.0.0 ${JAVA_OPTS}" -if [ $# -eq 0 ] - then - ARGS="$WAVES_CONFIG" - else - ARGS=$@ +echo "JAVA_OPTS=${JAVA_OPTS}" | tee -a ${WVLOG}/waves.log + +if [ -n "$WAVES_WALLET_SEED" ] ; then + JAVA_OPTS="-Dwaves.wallet.seed=${WAVES_WALLET_SEED} ${JAVA_OPTS}" +fi + +if [ -n "$WAVES_WALLET_PASSWORD" ] ; then + JAVA_OPTS="-Dwaves.wallet.password=${WAVES_WALLET_PASSWORD} ${JAVA_OPTS}" +fi + +if [ $# -eq 0 ] && [ -f /etc/waves/waves.conf ] ; then + ARGS="/etc/waves/waves.conf" +else + ARGS=$@ fi -exec java $JAVA_OPTS -cp "${WAVES_INSTALL_PATH}/lib/plugins/*:$WAVES_INSTALL_PATH/lib/*" com.wavesplatform.Application $ARGS +exec java $JAVA_OPTS -cp "$WAVES_INSTALL_PATH/lib/plugins/*:$WAVES_INSTALL_PATH/lib/*" com.wavesplatform.Application $ARGS diff --git a/docker/waves.conf.template b/docker/waves.conf.template deleted file mode 100644 index 14efef70fb..0000000000 --- a/docker/waves.conf.template +++ /dev/null @@ -1,10 +0,0 @@ -waves { - directory = ${WVDATA} - wallet { - seed = ${?WAVES_WALLET_SEED} - password = ${?WAVES_WALLET_PASSWORD} - } - rest-api.bind-address = "0.0.0.0" -} - -include "local.conf" diff --git a/grpc-server/build.sbt b/grpc-server/build.sbt index ac2780adbf..95e2ec2ad8 100644 --- a/grpc-server/build.sbt +++ b/grpc-server/build.sbt @@ -22,7 +22,7 @@ inConfig(Compile)( ) enablePlugins(RunApplicationSettings, ExtensionPackaging) - +Universal / maintainer := "com.wavesplatform" Debian / debianControlFile := { val generatedFile = (Debian / debianControlFile).value IO.append(generatedFile, s"""Conflicts: grpc-server${network.value.packageSuffix} diff --git a/grpc-server/src/main/resources/application.conf b/grpc-server/src/main/resources/application.conf index 29b5cd9262..d8f39a8922 100644 --- a/grpc-server/src/main/resources/application.conf +++ b/grpc-server/src/main/resources/application.conf @@ -2,10 +2,12 @@ waves { grpc { host = localhost port = 6870 + worker-threads = 4 } blockchain-updates { grpc-port = 6881 min-keep-alive = 5m + worker-threads = 4 } } diff --git a/grpc-server/src/main/scala/com/wavesplatform/api/grpc/GRPCServerExtension.scala b/grpc-server/src/main/scala/com/wavesplatform/api/grpc/GRPCServerExtension.scala index 5c8841eaa4..efd9aaa230 100644 --- a/grpc-server/src/main/scala/com/wavesplatform/api/grpc/GRPCServerExtension.scala +++ b/grpc-server/src/main/scala/com/wavesplatform/api/grpc/GRPCServerExtension.scala @@ -1,7 +1,6 @@ package com.wavesplatform.api.grpc -import java.net.InetSocketAddress -import scala.concurrent.Future +import com.google.common.util.concurrent.ThreadFactoryBuilder import com.wavesplatform.extensions.{Extension, Context as ExtensionContext} import com.wavesplatform.settings.GRPCSettings import com.wavesplatform.utils.ScorexLogging @@ -9,15 +8,22 @@ import io.grpc.Server import io.grpc.netty.NettyServerBuilder import io.grpc.protobuf.services.ProtoReflectionService import monix.execution.Scheduler +import net.ceedubs.ficus.readers.namemappers.implicits.hyphenCase import net.ceedubs.ficus.Ficus.* import net.ceedubs.ficus.readers.ArbitraryTypeReader.* +import java.net.InetSocketAddress +import java.util.concurrent.Executors +import scala.concurrent.Future + class GRPCServerExtension(context: ExtensionContext) extends Extension with ScorexLogging { - private implicit val apiScheduler: Scheduler = Scheduler(context.actorSystem.dispatcher) - private val settings = context.settings.config.as[GRPCSettings]("waves.grpc") + private val settings = context.settings.config.as[GRPCSettings]("waves.grpc") + private val executor = Executors.newFixedThreadPool(settings.workerThreads, new ThreadFactoryBuilder().setDaemon(true).setNameFormat("grpc-server-worker-%d").build()) + private implicit val apiScheduler: Scheduler = Scheduler(executor) private val bindAddress = new InetSocketAddress(settings.host, settings.port) private val server: Server = NettyServerBuilder .forAddress(bindAddress) + .executor(executor) .addService(TransactionsApiGrpc.bindService(new TransactionsApiGrpcImpl(context.blockchain, context.transactionsApi), apiScheduler)) .addService(BlocksApiGrpc.bindService(new BlocksApiGrpcImpl(context.blocksApi), apiScheduler)) .addService(AccountsApiGrpc.bindService(new AccountsApiGrpcImpl(context.accountsApi), apiScheduler)) @@ -34,6 +40,6 @@ class GRPCServerExtension(context: ExtensionContext) extends Extension with Scor override def shutdown(): Future[Unit] = { log.debug("Shutting down gRPC server") server.shutdown() - Future(server.awaitTermination())(context.actorSystem.dispatcher) + Future(server.awaitTermination())(apiScheduler) } } diff --git a/grpc-server/src/main/scala/com/wavesplatform/events/BlockchainUpdates.scala b/grpc-server/src/main/scala/com/wavesplatform/events/BlockchainUpdates.scala index 270a99986f..7cf25acde8 100644 --- a/grpc-server/src/main/scala/com/wavesplatform/events/BlockchainUpdates.scala +++ b/grpc-server/src/main/scala/com/wavesplatform/events/BlockchainUpdates.scala @@ -12,7 +12,9 @@ import io.grpc.protobuf.services.ProtoReflectionService import io.grpc.{Metadata, Server, ServerStreamTracer, Status} import monix.execution.schedulers.SchedulerService import monix.execution.{ExecutionModel, Scheduler, UncaughtExceptionReporter} +import net.ceedubs.ficus.readers.namemappers.implicits.hyphenCase import net.ceedubs.ficus.Ficus.* +import net.ceedubs.ficus.readers.ArbitraryTypeReader.* import org.rocksdb.RocksDB import java.net.InetSocketAddress @@ -22,15 +24,14 @@ import scala.concurrent.duration.* import scala.util.Try class BlockchainUpdates(private val context: Context) extends Extension with ScorexLogging with BlockchainUpdateTriggers { + private[this] val settings = context.settings.config.as[BlockchainUpdatesSettings]("waves.blockchain-updates") private[this] implicit val scheduler: SchedulerService = Schedulers.fixedPool( - sys.runtime.availableProcessors(), + settings.workerThreads, "blockchain-updates", UncaughtExceptionReporter(err => log.error("Uncaught exception in BlockchainUpdates scheduler", err)), ExecutionModel.Default, rejectedExecutionHandler = new akka.dispatch.SaneRejectedExecutionHandler ) - - private[this] val settings = context.settings.config.as[BlockchainUpdatesSettings]("waves.blockchain-updates") private[this] val rdb = RocksDB.open(context.settings.directory + "/blockchain-updates") private[this] val repo = new Repo(rdb, context.blocksApi) diff --git a/grpc-server/src/main/scala/com/wavesplatform/events/Repo.scala b/grpc-server/src/main/scala/com/wavesplatform/events/Repo.scala index e1435c0bd4..2da480a6eb 100644 --- a/grpc-server/src/main/scala/com/wavesplatform/events/Repo.scala +++ b/grpc-server/src/main/scala/com/wavesplatform/events/Repo.scala @@ -172,6 +172,7 @@ class Repo(db: RocksDB, blocksApi: CommonBlocksApi)(implicit s: Scheduler) } override def onMicroBlockRollback(blockchainBefore: Blockchain, toBlockId: ByteStr): Unit = monitor.synchronized { + log.trace(s"Rolling back liquid microblock to $toBlockId") liquidState match { case Some(ls) => val discardedMicroBlocks = if (ls.keyBlock.id == toBlockId) { diff --git a/grpc-server/src/main/scala/com/wavesplatform/events/events.scala b/grpc-server/src/main/scala/com/wavesplatform/events/events.scala index 62324eaaf1..614a643fb4 100644 --- a/grpc-server/src/main/scala/com/wavesplatform/events/events.scala +++ b/grpc-server/src/main/scala/com/wavesplatform/events/events.scala @@ -623,8 +623,7 @@ object BlockAppended { // updatedWavesAmount can change as a result of either genesis transactions or miner rewards val wavesAmount = blockchainBeforeWithReward.wavesAmount(height).toLong - val updatedWavesAmount = wavesAmount + reward.filter(_ => height > 0).getOrElse(0L) - + val updatedWavesAmount = wavesAmount + reward.filter(_ => height > 0).getOrElse(0L) * blockchainBeforeWithReward.blockRewardBoost(height + 1) val activatedFeatures = blockchainBeforeWithReward.activatedFeatures.collect { case (id, activationHeight) if activationHeight == height + 1 => id.toInt }.toSeq diff --git a/grpc-server/src/main/scala/com/wavesplatform/events/settings/BlockchainUpdatesSettings.scala b/grpc-server/src/main/scala/com/wavesplatform/events/settings/BlockchainUpdatesSettings.scala index 0aa0247542..eae111d2e2 100644 --- a/grpc-server/src/main/scala/com/wavesplatform/events/settings/BlockchainUpdatesSettings.scala +++ b/grpc-server/src/main/scala/com/wavesplatform/events/settings/BlockchainUpdatesSettings.scala @@ -1,13 +1,9 @@ package com.wavesplatform.events.settings import scala.concurrent.duration.FiniteDuration -import net.ceedubs.ficus.Ficus._ -import net.ceedubs.ficus.readers.ArbitraryTypeReader.arbitraryTypeValueReader -import net.ceedubs.ficus.readers.{Generated, ValueReader} -import net.ceedubs.ficus.readers.namemappers.implicits.hyphenCase -case class BlockchainUpdatesSettings(grpcPort: Int, minKeepAlive: FiniteDuration) - -object BlockchainUpdatesSettings { - implicit val valueReader: Generated[ValueReader[BlockchainUpdatesSettings]] = arbitraryTypeValueReader -} +case class BlockchainUpdatesSettings( + grpcPort: Int, + minKeepAlive: FiniteDuration, + workerThreads: Int +) 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 8806ba561c..62ca697f79 100644 --- a/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesSpec.scala +++ b/grpc-server/src/test/scala/com/wavesplatform/events/BlockchainUpdatesSpec.scala @@ -27,8 +27,8 @@ import com.wavesplatform.lang.v1.compiler.Terms.FUNCTION_CALL import com.wavesplatform.lang.v1.compiler.TestCompiler import com.wavesplatform.protobuf.* import com.wavesplatform.protobuf.block.PBBlocks -import com.wavesplatform.protobuf.transaction.{DataEntry, InvokeScriptResult} import com.wavesplatform.protobuf.transaction.InvokeScriptResult.{Call, Invocation, Payment} +import com.wavesplatform.protobuf.transaction.{DataEntry, InvokeScriptResult} import com.wavesplatform.settings.{Constants, WavesSettings} import com.wavesplatform.state.{AssetDescription, BlockRewardCalculator, EmptyDataEntry, Height, LeaseBalance, StringDataEntry} import com.wavesplatform.test.* @@ -1093,6 +1093,33 @@ class BlockchainUpdatesSpec extends FreeSpec with WithBUDomain with ScalaFutures ) } } + + "should return correct updated_waves_amount when reward boost is active" in { + val settings = ConsensusImprovements + .setFeaturesHeight( + BlockchainFeatures.BlockReward -> 0, + BlockchainFeatures.BlockRewardDistribution -> 0, + BlockchainFeatures.BoostBlockReward -> 5 + ) + .configure(fs => + fs.copy(blockRewardBoostPeriod = 10) + ) + + withDomainAndRepo(settings) { case (d, repo) => + d.appendBlock() + val subscription = repo.createFakeObserver(SubscribeRequest.of(1, 0)) + + (1 to 15).foreach(_ => d.appendBlock()) + + + subscription + .fetchAllEvents(d.blockchain) + .map(_.getUpdate.getAppend.getBlock.updatedWavesAmount) shouldBe + (2 to 16).scanLeft(100_000_000.waves) { (total, height) => total + 6.waves * d.blockchain.blockRewardBoost(height) } + + + } + } } private def assertCommon(rollback: RollbackResult): Assertion = { diff --git a/grpc-server/src/test/scala/com/wavesplatform/events/package.scala b/grpc-server/src/test/scala/com/wavesplatform/events/package.scala index a553213091..df9993dc47 100644 --- a/grpc-server/src/test/scala/com/wavesplatform/events/package.scala +++ b/grpc-server/src/test/scala/com/wavesplatform/events/package.scala @@ -12,8 +12,8 @@ package object events { implicit class BlockchainUpdatedExt(val se: PBBlockchainUpdated) extends Matchers { def append(implicit pos: Position): Append = se.update match { - case Update.Append(a) => a - case other => fail(s"${other.getClass.getSimpleName} is not an Append") + case Update.Append(append) => append + case other => fail(s"${other.getClass.getSimpleName} is not an Append") } } diff --git a/lang/js/src/main/scala/com/wavesplatform/JsApiUtils.scala b/lang/js/src/main/scala/com/wavesplatform/JsApiUtils.scala index 7189d52260..02d277d171 100644 --- a/lang/js/src/main/scala/com/wavesplatform/JsApiUtils.scala +++ b/lang/js/src/main/scala/com/wavesplatform/JsApiUtils.scala @@ -8,6 +8,7 @@ import com.wavesplatform.lang.v1.compiler.{CompilationError, CompilerContext} import com.wavesplatform.lang.v1.parser.Expressions import com.wavesplatform.lang.v1.parser.Expressions.{PART, Type} +import scala.annotation.nowarn import scala.scalajs.js import scala.scalajs.js.Any import scala.scalajs.js.Dynamic.literal as jObj @@ -244,6 +245,7 @@ object JsApiUtils { jObj("posStart" -> err.start, "posEnd" -> err.end, "msg" -> err.message) } + @nowarn("cat=deprecation") def toJs(ast: EXPR): js.Object = { def r(expr: EXPR): js.Object = { expr match { diff --git a/lang/js/src/main/scala/com/wavesplatform/lang/Global.scala b/lang/js/src/main/scala/com/wavesplatform/lang/Global.scala index 60f573fb05..e275004fa0 100644 --- a/lang/js/src/main/scala/com/wavesplatform/lang/Global.scala +++ b/lang/js/src/main/scala/com/wavesplatform/lang/Global.scala @@ -9,7 +9,7 @@ import com.wavesplatform.lang.v1.evaluator.ctx.impl.crypto.RSA.DigestAlgorithm import java.math.{BigInteger, BigDecimal as BD} import scala.collection.mutable import scala.scalajs.js.JSConverters.* -import scala.scalajs.js.typedarray.{ArrayBuffer, Int8Array} +import scala.scalajs.js.typedarray.{ArrayBuffer, Int8Array, TA2AB} import scala.util.Try object Global extends BaseGlobal { diff --git a/lang/jvm/build.sbt b/lang/jvm/build.sbt index 25f4f660a3..1a9664f9a2 100644 --- a/lang/jvm/build.sbt +++ b/lang/jvm/build.sbt @@ -1,5 +1,15 @@ -ThisProject / publishTo := sonatypePublishToBundle.value -ThisProject / publish / skip := false +publishTo := sonatypePublishToBundle.value +publish / skip := false +homepage := Some(url("https://docs.waves.tech/en/ride/")) +developers := List( + Developer("ismagin", "Ilya Smagin", "ilya.smagin@gmail.com", url("https://github.com/ismagin")), + Developer("asayadyan", "Artyom Sayadyan", "xrtm000@gmail.com", url("https://github.com/xrtm000")), + Developer("mpotanin", "Mike Potanin", "mpotanin@wavesplatform.com", url("https://github.com/potan")), + Developer("irakitnykh", "Ivan Rakitnykh", "mrkr.reg@gmail.com", url("https://github.com/mrkraft")) +) + +Compile / packageDoc / publishArtifact := true +Test / packageDoc / publishArtifact := false inTask(assembly)( Seq( diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/contract/meta/TypeBitMapper.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/contract/meta/TypeBitMapper.scala index a5e2f2fbf8..b3b4f95301 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/contract/meta/TypeBitMapper.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/contract/meta/TypeBitMapper.scala @@ -71,7 +71,7 @@ case class ListTypeMapper(bitMapper: TypeBitMapper) extends TypeBitMapper { override def fromIndex(i: Int): Either[String, FINAL] = if ((i >> bitMapper.length) % 2 == 1) - bitMapper.fromIndex(i ^ (1 << bitMapper.length)).map(LIST) + bitMapper.fromIndex(i ^ (1 << bitMapper.length)).map(LIST.apply) else bitMapper.fromIndex(i) diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/script/ScriptReader.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/script/ScriptReader.scala index 0ad91ba282..da42f73173 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/script/ScriptReader.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/script/ScriptReader.scala @@ -68,7 +68,7 @@ object ScriptReader { s <- ContractScript(stdLibVersion, dapp) } yield s }).left - .map(ScriptParseError) + .map(ScriptParseError.apply) } yield s } } diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/BaseGlobal.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/BaseGlobal.scala index 9e5002fdba..241823ceb4 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/BaseGlobal.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/BaseGlobal.scala @@ -269,7 +269,7 @@ trait BaseGlobal { } def dAppFuncTypes(dApp: DApp): Either[ScriptParseError, FunctionSignatures] = - MetaMapper.dicFromProto(dApp).bimap(ScriptParseError, combineMetaWithDApp(_, dApp)) + MetaMapper.dicFromProto(dApp).bimap(ScriptParseError.apply, combineMetaWithDApp(_, dApp)) private def combineMetaWithDApp(meta: ParsedMeta, dApp: DApp): FunctionSignatures = { val argTypesWithFuncName = diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/CompilerContext.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/CompilerContext.scala index 5c27cbf20c..c37df1f886 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/CompilerContext.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/CompilerContext.scala @@ -7,7 +7,6 @@ import com.wavesplatform.lang.v1.compiler.Types.* import com.wavesplatform.lang.v1.evaluator.ctx.FunctionTypeSignature import com.wavesplatform.lang.v1.parser.Expressions.Pos import com.wavesplatform.lang.v1.parser.Expressions.Pos.AnyPos -import shapeless.* case class CompilerContext( predefTypes: Map[String, FINAL], @@ -60,9 +59,5 @@ object CompilerContext { y.provideRuntimeTypeOnCastError ) - val types: Lens[CompilerContext, Map[String, FINAL]] = lens[CompilerContext] >> Symbol("predefTypes") - val vars: Lens[CompilerContext, VariableTypes] = lens[CompilerContext] >> Symbol("varDefs") - val functions: Lens[CompilerContext, FunctionTypes] = lens[CompilerContext] >> Symbol("functionDefs") - val empty = CompilerContext(Map(), Map(), Map(), true) } diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ContractCompiler.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ContractCompiler.scala index 1240d5aae7..0ce09fabad 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ContractCompiler.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ContractCompiler.scala @@ -12,7 +12,7 @@ import com.wavesplatform.lang.contract.DApp.* import com.wavesplatform.lang.contract.meta.{MetaMapper, V1 as MetaV1, V2 as MetaV2} import com.wavesplatform.lang.directives.values.{StdLibVersion, V3, V6} import com.wavesplatform.lang.v1.compiler.CompilationError.{AlreadyDefined, Generic, UnionNotAllowedForCallableArgs, WrongArgumentType} -import com.wavesplatform.lang.v1.compiler.CompilerContext.{VariableInfo, vars} +import com.wavesplatform.lang.v1.compiler.CompilerContext.VariableInfo import com.wavesplatform.lang.v1.compiler.ContractCompiler.* import com.wavesplatform.lang.v1.compiler.ScriptResultSource.FreeCall import com.wavesplatform.lang.v1.compiler.Terms.EXPR @@ -87,7 +87,7 @@ class ContractCompiler(version: StdLibVersion) extends ExpressionCompiler(versio .getOrElse(List.empty) unionInCallableErrs <- checkCallableUnions(af, annotationsWithErr._1.toList.flatten) compiledBody <- local { - modify[Id, CompilerContext, CompilationError](vars.modify(_)(_ ++ annotationBindings)).flatMap(_ => + modify[Id, CompilerContext, CompilationError](ctx => ctx.copy(varDefs = ctx.varDefs ++ annotationBindings)).flatMap(_ => compileFunc(af.f.position, af.f, saveExprContext, annotationBindings.map(_._1), allowIllFormedStrings) ) } diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Decompiler.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Decompiler.scala index 759af4e1de..ce7f870ffd 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Decompiler.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Decompiler.scala @@ -229,7 +229,7 @@ object Decompiler { .flatMap(m => (m.group(1), m.group(2)) match { case ("User", name) => Some(User(name)) - case ("Native", id) => Try(id.toShort).toOption.map(Native) + case ("Native", id) => Try(id.toShort).toOption.map(Native.apply) case _ => None } ) diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ExpressionCompiler.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ExpressionCompiler.scala index 9a9ae79997..bf26813b1e 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ExpressionCompiler.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/ExpressionCompiler.scala @@ -144,7 +144,7 @@ class ExpressionCompiler(val version: StdLibVersion) { private def findGenericType(p: Pos, t: String): Either[CompilationError, FINAL => FINAL] = t match { - case Type.ListTypeName => Right(LIST) + case Type.ListTypeName => Right(LIST.apply) case _ => Left(GenericTypeNotFound(p.start, p.end, t)) } @@ -345,7 +345,7 @@ class ExpressionCompiler(val version: StdLibVersion) { .handleError() compiledFuncBody <- local { val newArgs: VariableTypes = argTypesWithErr._1.getOrElse(List.empty).toMap - modify[Id, CompilerContext, CompilationError](vars.modify(_)(_ ++ newArgs)) + modify[Id, CompilerContext, CompilationError](ctx1 => ctx1.copy(varDefs = ctx1.varDefs ++ newArgs)) .flatMap(_ => compileExprWithCtx(func.expr, saveExprContext, allowIllFormedStrings)) } @@ -368,10 +368,10 @@ class ExpressionCompiler(val version: StdLibVersion) { } protected def updateCtx(letName: String, letType: Types.FINAL, p: Pos): CompileM[Unit] = - modify[Id, CompilerContext, CompilationError](vars.modify(_)(_ + (letName -> VariableInfo(p, letType)))) + modify[Id, CompilerContext, CompilationError](ctx => ctx.copy(varDefs = ctx.varDefs + (letName -> VariableInfo(p, letType)))) protected def updateCtx(funcName: String, typeSig: FunctionTypeSignature, p: Pos): CompileM[Unit] = - modify[Id, CompilerContext, CompilationError](functions.modify(_)(_ + (funcName -> FunctionInfo(p, List(typeSig))))) + modify[Id, CompilerContext, CompilationError](ctx => ctx.copy(functionDefs = ctx.functionDefs + (funcName -> FunctionInfo(p, List(typeSig))))) private def compileLetBlock( p: Pos, @@ -789,9 +789,9 @@ class ExpressionCompiler(val version: StdLibVersion) { .collect { case Expressions.Single(t, None) => Expressions.FUNCTION_CALL(pos, PART.VALID(pos, IsInstanceOf), List(v, Expressions.CONST_STRING(pos, t))) - case Expressions.Single(PART.VALID(pos, Type.ListTypeName), Some(PART.VALID(_, Expressions.AnyType(_)))) => + case Expressions.Single(PART.VALID(vpos, Type.ListTypeName), Some(PART.VALID(_, Expressions.AnyType(_)))) => val t = PART.VALID(pos, "List[Any]") - Expressions.FUNCTION_CALL(pos, PART.VALID(pos, IsInstanceOf), List(v, Expressions.CONST_STRING(pos, t))) + Expressions.FUNCTION_CALL(vpos, PART.VALID(vpos, IsInstanceOf), List(v, Expressions.CONST_STRING(vpos, t))) } .reduceRight[Expressions.EXPR](BINARY_OP(pos, _, BinaryOperation.OR_OP, _)) Right(r) diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Terms.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Terms.scala index 2413fd86a2..1cfcd70ab8 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Terms.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/Terms.scala @@ -8,7 +8,7 @@ import com.wavesplatform.lang.v1.ContractLimits.* import com.wavesplatform.lang.v1.FunctionHeader import com.wavesplatform.lang.v1.compiler.Types.* import com.wavesplatform.lang.v1.evaluator.ctx.impl.PureContext.MaxListLengthV4 -import com.wavesplatform.lang.{CommonError, ExecutionError} +import com.wavesplatform.lang.* import monix.eval.Coeval import java.nio.charset.StandardCharsets @@ -165,7 +165,7 @@ object Terms { var body: EXPR } - @Deprecated + @deprecated("use BLOCK instead", "1.0") case class LET_BLOCK(let: LET, var body: EXPR) extends EXPR with BLOCK_DEF { def toStr: Coeval[String] = for { diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/TypeInferrer.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/TypeInferrer.scala index 7989103cfa..2593e3ed03 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/TypeInferrer.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/compiler/TypeInferrer.scala @@ -62,7 +62,7 @@ object TypeInferrer { (groupByPosition(matchingTuples.map(_.types)) zip commonTuple.types) .forall { case (groupedTypes, t: TUPLE) => - checkTuplesCommonType(groupedTypes.collect { case t: TUPLE => t }, t) + checkTuplesCommonType(groupedTypes.collect { case tt: TUPLE => tt }, t) case (groupedTypes, singleType) => singleType.typeList.length < groupedTypes.map(_.typeList.length).sum } diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/estimator/v2/EstimatorContext.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/estimator/v2/EstimatorContext.scala index 10080f74c8..29b96b25f1 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/estimator/v2/EstimatorContext.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/estimator/v2/EstimatorContext.scala @@ -1,27 +1,18 @@ package com.wavesplatform.lang.v1.estimator.v2 - import com.wavesplatform.lang.v1.FunctionHeader import com.wavesplatform.lang.v1.compiler.Terms.FUNC import com.wavesplatform.lang.v1.estimator.EstimationError import com.wavesplatform.lang.v1.estimator.v2.EstimatorContext.EvalM import com.wavesplatform.lang.v1.task.TaskM -import shapeless.{Lens, lens} private[v2] case class EstimatorContext( - letDefs: Map[String, (Boolean, EvalM[Long])], - predefFuncs: Map[FunctionHeader, Long], - userFuncs: Map[FunctionHeader, FUNC] = Map.empty, - overlappedRefs: Map[String, (Boolean, EvalM[Long])] = Map.empty + letDefs: Map[String, (Boolean, EvalM[Long])], + predefFuncs: Map[FunctionHeader, Long], + userFuncs: Map[FunctionHeader, FUNC] = Map.empty, + overlappedRefs: Map[String, (Boolean, EvalM[Long])] = Map.empty ) private[v2] object EstimatorContext { type EvalM[A] = TaskM[EstimatorContext, EstimationError, A] - - object Lenses { - val lets: Lens[EstimatorContext, Map[String, (Boolean, EvalM[Long])]] = lens[EstimatorContext] >> Symbol("letDefs") - val userFuncs: Lens[EstimatorContext, Map[FunctionHeader, FUNC]] = lens[EstimatorContext] >> Symbol("userFuncs") - val predefFuncs: Lens[EstimatorContext, Map[FunctionHeader, Long]] = lens[EstimatorContext] >> Symbol("predefFuncs") - val overlappedRefs: Lens[EstimatorContext, Map[String, (Boolean, EvalM[Long])]] = lens[EstimatorContext] >> Symbol("overlappedRefs") - } } diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/estimator/v2/ScriptEstimatorV2.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/estimator/v2/ScriptEstimatorV2.scala index b0e2124b93..bf02ab8ab8 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/estimator/v2/ScriptEstimatorV2.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/estimator/v2/ScriptEstimatorV2.scala @@ -7,7 +7,6 @@ import com.wavesplatform.lang.v1.FunctionHeader import com.wavesplatform.lang.v1.compiler.Terms._ import com.wavesplatform.lang.v1.estimator.{EstimationError, ScriptEstimator} import com.wavesplatform.lang.v1.estimator.v2.EstimatorContext.EvalM -import com.wavesplatform.lang.v1.estimator.v2.EstimatorContext.Lenses._ import com.wavesplatform.lang.v1.task.imports._ import monix.eval.Coeval @@ -45,7 +44,7 @@ object ScriptEstimatorV2 extends ScriptEstimator { local { val letResult = (false, evalExpr(let.value)) for { - _ <- update(lets.modify(_)(_.updated(let.name, letResult))) + _ <- update(ctx => ctx.copy(letDefs = ctx.letDefs.updated(let.name, letResult))) r <- evalExpr(inner) } yield r + 5 } @@ -61,7 +60,7 @@ object ScriptEstimatorV2 extends ScriptEstimator { local { for { _ <- checkFuncCtx(func) - _ <- update(userFuncs.modify(_)(_ + (FunctionHeader.User(func.name) -> func))) + _ <- update(ctx => ctx.copy(userFuncs = ctx.userFuncs + (FunctionHeader.User(func.name) -> func))) r <- evalExpr(inner) } yield r + 5 } @@ -69,7 +68,7 @@ object ScriptEstimatorV2 extends ScriptEstimator { private def checkFuncCtx(func: FUNC): EvalM[Unit] = local { for { - _ <- update(lets.modify(_)(_ ++ func.args.map((_, (true, const(0)))).toMap)) + _ <- update(ctx => ctx.copy(letDefs = ctx.letDefs ++ func.args.map((_, (true, const(0)))).toMap)) _ <- evalExpr(func.body) } yield () } @@ -77,7 +76,7 @@ object ScriptEstimatorV2 extends ScriptEstimator { private def evalRef(key: String): EvalM[Long] = for { ctx <- get[Id, EstimatorContext, EstimationError] - r <- lets.get(ctx).get(key) match { + r <- ctx.letDefs.get(key) match { case Some((false, lzy)) => setRefEvaluated(key, lzy) case Some((true, _)) => const(0) case None => raiseError[Id, EstimatorContext, EstimationError, Long](s"A definition of '$key' not found") @@ -85,7 +84,7 @@ object ScriptEstimatorV2 extends ScriptEstimator { } yield r + 2 private def setRefEvaluated(key: String, lzy: EvalM[Long]): EvalM[Long] = - update(lets.modify(_)(_.updated(key, (true, lzy)))) + update(ctx => ctx.copy(letDefs = ctx.letDefs.updated(key, (true, lzy)))) .flatMap(_ => lzy) private def evalGetter(expr: EXPR): EvalM[Long] = @@ -94,11 +93,10 @@ object ScriptEstimatorV2 extends ScriptEstimator { private def evalFuncCall(header: FunctionHeader, args: List[EXPR]): EvalM[Long] = for { ctx <- get[Id, EstimatorContext, EstimationError] - bodyComplexity <- predefFuncs - .get(ctx) + bodyComplexity <- ctx.predefFuncs .get(header) .map(bodyComplexity => evalFuncArgs(args).map(_ + bodyComplexity)) - .orElse(userFuncs.get(ctx).get(header).map(evalUserFuncCall(_, args))) + .orElse(ctx.userFuncs.get(header).map(evalUserFuncCall(_, args))) .getOrElse(raiseError[Id, EstimatorContext, EstimationError, Long](s"function '$header' not found")) } yield bodyComplexity @@ -106,14 +104,25 @@ object ScriptEstimatorV2 extends ScriptEstimator { for { argsComplexity <- evalFuncArgs(args) ctx <- get[Id, EstimatorContext, EstimationError] - _ <- update(lets.modify(_)(_ ++ ctx.overlappedRefs)) + _ <- update(ctx1 => ctx1.copy(letDefs = ctx1.letDefs ++ ctx.overlappedRefs)) overlapped = func.args.flatMap(arg => ctx.letDefs.get(arg).map((arg, _))).toMap ctxArgs = func.args.map((_, (false, const(1)))).toMap - _ <- update((lets ~ overlappedRefs).modify(_) { case (l, or) => (l ++ ctxArgs, or ++ overlapped) }) + _ <- update(ctx1 => + ctx1.copy( + letDefs = ctx1.letDefs ++ ctxArgs, + overlappedRefs = ctx1.overlappedRefs ++ overlapped + ) + ) + bodyComplexity <- evalExpr(func.body).map(_ + func.args.size * 5) evaluatedCtx <- get[Id, EstimatorContext, EstimationError] overlappedChanges = overlapped.map { case ref @ (name, _) => evaluatedCtx.letDefs.get(name).map((name, _)).getOrElse(ref) } - _ <- update((lets ~ overlappedRefs).modify(_) { case (l, or) => (l -- ctxArgs.keys ++ overlapped, or ++ overlappedChanges) }) + _ <- update(ctx1 => + ctx1.copy( + letDefs = ctx1.letDefs -- ctxArgs.keys ++ overlapped, + overlappedRefs = ctx1.overlappedRefs ++ overlappedChanges + ) + ) } yield bodyComplexity + argsComplexity private def evalFuncArgs(args: List[EXPR]): EvalM[Long] = diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/estimator/v3/EstimatorContext.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/estimator/v3/EstimatorContext.scala index 67a33cdc4c..8199a70418 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/estimator/v3/EstimatorContext.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/estimator/v3/EstimatorContext.scala @@ -5,7 +5,6 @@ import com.wavesplatform.lang.v1.estimator.EstimationError import com.wavesplatform.lang.v1.estimator.v3.EstimatorContext.EvalM import com.wavesplatform.lang.v1.task.TaskM import monix.eval.Coeval -import shapeless.{Lens, lens} private[v3] case class EstimatorContext( funcs: Map[FunctionHeader, (Coeval[Long], Set[String])], @@ -18,9 +17,4 @@ private[v3] case class EstimatorContext( private[v3] object EstimatorContext { type EvalM[A] = TaskM[EstimatorContext, EstimationError, A] - - object Lenses { - val funcs: Lens[EstimatorContext, Map[FunctionHeader, (Coeval[Long], Set[String])]] = lens[EstimatorContext] >> Symbol("funcs") - val usedRefs: Lens[EstimatorContext, Set[String]] = lens[EstimatorContext] >> Symbol("usedRefs") - } } diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/estimator/v3/ScriptEstimatorV3.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/estimator/v3/ScriptEstimatorV3.scala index 6d8dc07344..17d13e8bec 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/estimator/v3/ScriptEstimatorV3.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/estimator/v3/ScriptEstimatorV3.scala @@ -7,7 +7,6 @@ import com.wavesplatform.lang.v1.FunctionHeader import com.wavesplatform.lang.v1.FunctionHeader.User import com.wavesplatform.lang.v1.compiler.Terms.* import com.wavesplatform.lang.v1.estimator.v3.EstimatorContext.EvalM -import com.wavesplatform.lang.v1.estimator.v3.EstimatorContext.Lenses.* import com.wavesplatform.lang.v1.estimator.{EstimationError, ScriptEstimator} import com.wavesplatform.lang.v1.task.imports.* import monix.eval.Coeval @@ -82,7 +81,7 @@ case class ScriptEstimatorV3(fixOverflow: Boolean, overhead: Boolean, letFixes: letCosts <- usedRefs.toSeq.traverse { ref => local { for { - _ <- update(funcs.set(_)(startCtx.funcs)) + _ <- update(ctx1 => ctx1.copy(funcs = startCtx.funcs)) cost <- ctx.globalLetEvals.getOrElse(ref, zero) } yield cost } @@ -100,22 +99,18 @@ case class ScriptEstimatorV3(fixOverflow: Boolean, overhead: Boolean, letFixes: } private def beforeNextExprEval(let: LET, eval: EvalM[Long]): EvalM[Unit] = - update(ctx => - usedRefs - .modify(ctx)(_ - let.name) - .copy(refsCosts = ctx.refsCosts + (let.name -> local(eval))) - ) + update(ctx => ctx.copy(usedRefs = ctx.usedRefs - let.name, refsCosts = ctx.refsCosts + (let.name -> local(eval)))) private def afterNextExprEval(let: LET, startCtx: EstimatorContext): EvalM[Unit] = update(ctx => - usedRefs - .modify(ctx)(r => if (startCtx.usedRefs.contains(let.name)) r + let.name else r - let.name) - .copy(refsCosts = + ctx.copy( + usedRefs = if (startCtx.usedRefs.contains(let.name)) ctx.usedRefs + let.name else ctx.usedRefs - let.name, + refsCosts = if (startCtx.refsCosts.contains(let.name)) ctx.refsCosts + (let.name -> startCtx.refsCosts(let.name)) else ctx.refsCosts - let.name - ) + ) ) private def evalFuncBlock(func: FUNC, nextExpr: EXPR, activeFuncArgs: Set[String], globalDeclarationsMode: Boolean): EvalM[Long] = @@ -142,14 +137,12 @@ case class ScriptEstimatorV3(fixOverflow: Boolean, overhead: Boolean, letFixes: _ <- set[Id, EstimatorContext, EstimationError](ctx.copy(globalFunctionsCosts = ctx.globalFunctionsCosts + (name -> totalCost))) } yield () - private def handleUsedRefs(name: String, cost: Long, ctx: EstimatorContext, refsUsedInBody: Set[String]): EvalM[Unit] = - update( - (funcs ~ usedRefs).modify(_) { case (funcs, _) => - ( - funcs + (User(name) -> (Coeval.now(cost), refsUsedInBody)), - ctx.usedRefs - ) - } + private def handleUsedRefs(name: String, cost: Long, startCtx: EstimatorContext, refsUsedInBody: Set[String]): EvalM[Unit] = + update(ctx => + ctx.copy( + funcs = ctx.funcs + (User(name) -> (Coeval.now(cost), refsUsedInBody)), + usedRefs = startCtx.usedRefs + ) ) private def evalIF(cond: EXPR, ifTrue: EXPR, ifFalse: EXPR, activeFuncArgs: Set[String]): EvalM[Long] = @@ -165,7 +158,7 @@ case class ScriptEstimatorV3(fixOverflow: Boolean, overhead: Boolean, letFixes: if (activeFuncArgs.contains(key) && letFixes) const(overheadCost) else - update(usedRefs.modify(_)(_ + key)).map(_ => overheadCost) + update(ctx => ctx.copy(usedRefs = ctx.usedRefs + key)).map(_ => overheadCost) private def evalGetter(expr: EXPR, activeFuncArgs: Set[String]): EvalM[Long] = evalExpr(expr, activeFuncArgs).flatMap(sum(_, overheadCost)) @@ -187,18 +180,15 @@ case class ScriptEstimatorV3(fixOverflow: Boolean, overhead: Boolean, letFixes: } yield result private def setFuncToCtx(header: FunctionHeader, bodyCost: Coeval[Long], bodyUsedRefs: Set[EstimationError]): EvalM[Unit] = - update( - (funcs ~ usedRefs).modify(_) { case (funcs, usedRefs) => - ( - funcs + (header -> (bodyCost, Set())), - usedRefs ++ bodyUsedRefs - ) - } + update(ctx => + ctx.copy( + funcs = ctx.funcs + (header -> (bodyCost, Set())), + usedRefs = ctx.usedRefs ++ bodyUsedRefs + ) ) private def getFuncCost(header: FunctionHeader, ctx: EstimatorContext): EvalM[(Coeval[Long], Set[EstimationError])] = - funcs - .get(ctx) + ctx.funcs .get(header) .map(const) .getOrElse( @@ -217,9 +207,9 @@ case class ScriptEstimatorV3(fixOverflow: Boolean, overhead: Boolean, letFixes: ): EvalM[Long] = for { startCtx <- get[Id, EstimatorContext, EstimationError] - _ <- ctxFuncsOpt.fold(doNothing.void)(ctxFuncs => update(funcs.set(_)(ctxFuncs))) + _ <- ctxFuncsOpt.fold(doNothing.void)(ctxFuncs => update(ctx => ctx.copy(funcs = ctxFuncs))) cost <- evalExpr(expr, activeFuncArgs) - _ <- update(funcs.set(_)(startCtx.funcs)) + _ <- update(ctx => ctx.copy(funcs = startCtx.funcs)) } yield cost private def withUsedRefs[A](eval: EvalM[A]): EvalM[(A, Set[String])] = diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/EvaluatorV1.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/EvaluatorV1.scala index cb75053058..386388a194 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/EvaluatorV1.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/EvaluatorV1.scala @@ -8,10 +8,9 @@ import com.wavesplatform.lang.v1.compiler.Terms.* import com.wavesplatform.lang.v1.compiler.Types.{CASETYPEREF, NOTHING} import com.wavesplatform.lang.v1.evaluator.ContextfulNativeFunction.{Extended, Simple} import com.wavesplatform.lang.v1.evaluator.ctx.* -import com.wavesplatform.lang.v1.evaluator.ctx.EnabledLogEvaluationContext.Lenses import com.wavesplatform.lang.v1.task.imports.* import com.wavesplatform.lang.v1.traits.Environment -import com.wavesplatform.lang.{CoevalF, CommonError, EvalF, ExecutionError} +import com.wavesplatform.lang.* import scala.collection.mutable.ListBuffer import scala.util.Try @@ -30,8 +29,6 @@ object EvaluatorV1 { } class EvaluatorV1[F[_]: Monad, C[_[_]]](implicit ev: Monad[EvalF[F, *]], ev2: Monad[CoevalF[F, *]]) { - private val lenses = new Lenses[F, C] - import lenses.* private def evalLetBlock(let: LET, inner: EXPR): EvalM[F, C, (EvaluationContext[C, F], EVALUATED)] = for { @@ -39,7 +36,9 @@ class EvaluatorV1[F[_]: Monad, C[_[_]]](implicit ev: Monad[EvalF[F, *]], ev2: Mo blockEvaluation = evalExpr(let.value) lazyBlock = LazyVal(blockEvaluation.ter(ctx), ctx.l(let.name)) result <- local { - modify[F, EnabledLogEvaluationContext[C, F], ExecutionError](lets.modify(_)(_.updated(let.name, lazyBlock))) + modify[F, EnabledLogEvaluationContext[C, F], ExecutionError](ctx1 => + ctx1.copy(ec = ctx1.ec.copy(letDefs = ctx1.ec.letDefs.updated(let.name, lazyBlock))) + ) .flatMap(_ => evalExprWithCtx(inner)) } } yield result @@ -49,7 +48,9 @@ class EvaluatorV1[F[_]: Monad, C[_[_]]](implicit ev: Monad[EvalF[F, *]], ev2: Mo val function = UserFunction(func.name, 0, NOTHING, func.args.map(n => (n, NOTHING))*)(func.body) .asInstanceOf[UserFunction[C]] local { - modify[F, EnabledLogEvaluationContext[C, F], ExecutionError](funcs.modify(_)(_.updated(funcHeader, function))) + modify[F, EnabledLogEvaluationContext[C, F], ExecutionError](ctx => + ctx.copy(ec = ctx.ec.copy(functions = ctx.ec.functions.updated(funcHeader, function))) + ) .flatMap(_ => evalExprWithCtx(inner)) } } @@ -57,7 +58,7 @@ class EvaluatorV1[F[_]: Monad, C[_[_]]](implicit ev: Monad[EvalF[F, *]], ev2: Mo private def evalRef(key: String): EvalM[F, C, (EvaluationContext[C, F], EVALUATED)] = for { ctx <- get[F, EnabledLogEvaluationContext[C, F], ExecutionError] - r <- lets.get(ctx).get(key) match { + r <- ctx.ec.letDefs.get(key) match { case Some(lzy) => liftTER[F, C, EVALUATED](lzy.value) case None => raiseError[F, EnabledLogEvaluationContext[C, F], ExecutionError, EVALUATED](s"A definition of '$key' not found") } @@ -83,8 +84,7 @@ class EvaluatorV1[F[_]: Monad, C[_[_]]](implicit ev: Monad[EvalF[F, *]], ev2: Mo private def evalFunctionCall(header: FunctionHeader, args: List[EXPR]): EvalM[F, C, (EvaluationContext[C, F], EVALUATED)] = for { ctx <- get[F, EnabledLogEvaluationContext[C, F], ExecutionError] - result <- funcs - .get(ctx) + result <- ctx.ec.functions .get(header) .map { case func: UserFunction[C] => @@ -94,7 +94,7 @@ class EvaluatorV1[F[_]: Monad, C[_[_]]](implicit ev: Monad[EvalF[F, *]], ev2: Mo } local { val newState: EvalM[F, C, Unit] = - set[F, EnabledLogEvaluationContext[C, F], ExecutionError](lets.set(ctx)(letDefsWithArgs)).map(_.pure[F]) + set[F, EnabledLogEvaluationContext[C, F], ExecutionError](ctx.copy(ec = ctx.ec.copy(letDefs = letDefsWithArgs))).map(_.pure[F]) Monad[EvalM[F, C, *]].flatMap(newState)(_ => evalExpr(func.ev(ctx.ec.environment, args))) } }: EvalM[F, C, EVALUATED] @@ -118,7 +118,7 @@ class EvaluatorV1[F[_]: Monad, C[_[_]]](implicit ev: Monad[EvalF[F, *]], ev2: Mo // no such function, try data constructor header match { case FunctionHeader.User(typeName, _) => - types.get(ctx).get(typeName).collect { case t @ CASETYPEREF(_, fields, _) => + ctx.ec.typeDefs.get(typeName).collect { case t @ CASETYPEREF(_, fields, _) => args .traverse[EvalM[F, C, *], EVALUATED](evalExpr) .map(values => CaseObj(t, fields.map(_._1).zip(values).toMap): EVALUATED) diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/EvaluatorV2.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/EvaluatorV2.scala index 77c16ee5f5..cf623bddce 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/EvaluatorV2.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/EvaluatorV2.scala @@ -15,7 +15,7 @@ import com.wavesplatform.lang.v1.evaluator.EvaluatorV2.logFunc import com.wavesplatform.lang.v1.evaluator.ctx.impl.waves.Bindings import com.wavesplatform.lang.v1.evaluator.ctx.* import com.wavesplatform.lang.v1.traits.Environment -import com.wavesplatform.lang.{CommonError, ExecutionError, ThrownError} +import com.wavesplatform.lang.* import monix.eval.Coeval import shapeless.syntax.std.tuple.* diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ScriptResult.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ScriptResult.scala index 48c31a3e87..9e3e9e07d6 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ScriptResult.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ScriptResult.scala @@ -1,19 +1,19 @@ package com.wavesplatform.lang.v1.evaluator import cats.Id -import cats.implicits._ +import cats.implicits.* import com.wavesplatform.common.state.ByteStr -import com.wavesplatform.lang.{ExecutionError, CommonError} +import com.wavesplatform.lang.* import com.wavesplatform.lang.directives.values.{StdLibVersion, V3, V4, V5} import com.wavesplatform.lang.v1.compiler.ScriptResultSource.CallableFunction -import com.wavesplatform.lang.v1.compiler.Terms._ +import com.wavesplatform.lang.v1.compiler.Terms.* import com.wavesplatform.lang.v1.compiler.Types.CASETYPEREF import com.wavesplatform.lang.v1.evaluator.ctx.EvaluationContext -import com.wavesplatform.lang.v1.evaluator.ctx.impl._ +import com.wavesplatform.lang.v1.evaluator.ctx.impl.* import com.wavesplatform.lang.v1.evaluator.ctx.impl.waves.{FieldNames, Types} import com.wavesplatform.lang.v1.traits.Environment +import com.wavesplatform.lang.v1.traits.domain.* import com.wavesplatform.lang.v1.traits.domain.Recipient.{Address, Alias} -import com.wavesplatform.lang.v1.traits.domain._ sealed trait ScriptResult { def returnedValue: EVALUATED = unit diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/EvaluationContext.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/EvaluationContext.scala index 1013b3bae4..863cbaa99c 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/EvaluationContext.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/EvaluationContext.scala @@ -8,7 +8,6 @@ import com.wavesplatform.lang.v1.compiler.Terms.LET import com.wavesplatform.lang.v1.compiler.Types.FINAL import com.wavesplatform.lang.v1.evaluator.Contextful.NoContext import com.wavesplatform.lang.v1.evaluator.{Contextful, LetExecResult, LetLogCallback} -import shapeless.{Lens, lens} import java.util @@ -51,17 +50,6 @@ case class EnabledLogEvaluationContext[C[_[_]], F[_]: Monad](l: LetLogCallback[F loggedLets.computeIfAbsent(let, _ => l(let.name)(result)) } -object EnabledLogEvaluationContext { - class Lenses[F[_]: Monad, C[_[_]]] { - val types: Lens[EnabledLogEvaluationContext[C, F], Map[String, FINAL]] = - lens[EnabledLogEvaluationContext[C, F]] >> Symbol("ec") >> Symbol("typeDefs") - val lets: Lens[EnabledLogEvaluationContext[C, F], Map[String, LazyVal[F]]] = - lens[EnabledLogEvaluationContext[C, F]] >> Symbol("ec") >> Symbol("letDefs") - val funcs: Lens[EnabledLogEvaluationContext[C, F], Map[FunctionHeader, BaseFunction[C]]] = - lens[EnabledLogEvaluationContext[C, F]] >> Symbol("ec") >> Symbol("functions") - } -} - case class DisabledLogEvaluationContext[C[_[_]], F[_]](ec: EvaluationContext[C, F]) extends LoggedEvaluationContext[C, F] { override def log(let: LET, result: LetExecResult[F]): Unit = () } diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/CryptoContext.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/CryptoContext.scala index 52b0a4a6a9..58dc4f8030 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/CryptoContext.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/CryptoContext.scala @@ -14,7 +14,7 @@ import com.wavesplatform.lang.v1.evaluator.FunctionIds.* import com.wavesplatform.lang.v1.evaluator.ctx.impl.crypto.RSA.DigestAlgorithm import com.wavesplatform.lang.v1.evaluator.ctx.{BaseFunction, EvaluationContext, NativeFunction} import com.wavesplatform.lang.v1.{BaseGlobal, CTX} -import com.wavesplatform.lang.{CommonError, ExecutionError, ThrownError} +import com.wavesplatform.lang.* import scala.collection.mutable import scala.util.Try diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/PureContext.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/PureContext.scala index 2fbb5dc0d9..619290fd2b 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/PureContext.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/PureContext.scala @@ -220,7 +220,7 @@ object PureContext { r => r >= BigIntMin && r <= BigIntMax, s"$a ${op.func} $b is out of range." ) - .map(CONST_BIGINT) + .map(CONST_BIGINT.apply) .leftMap(CommonError(_)) case args => Left(s"Unexpected args $args for BigInt operator '${op.func}'") @@ -1356,7 +1356,7 @@ object PureContext { body: (BigInt, BigInt) => Boolean ): BaseFunction[NoContext] = NativeFunction(opsToFunctions(op), Map(V5 -> 8L, V6 -> 8L, V7 -> 8L, V8 -> 1L), func, BOOLEAN, ("a", BIGINT), ("b", BIGINT)) { - case CONST_BIGINT(a) :: CONST_BIGINT(b) :: Nil => Try(body(a, b)).toEither.bimap(_.getMessage, CONST_BOOLEAN) + case CONST_BIGINT(a) :: CONST_BIGINT(b) :: Nil => Try(body(a, b)).toEither.bimap(_.getMessage, CONST_BOOLEAN.apply) case xs => notImplemented[Id, EVALUATED](s"${opsToFunctions(op)}(a: BIGINT, b: BIGINT)", xs) } @@ -1598,7 +1598,7 @@ object PureContext { ) { Left("pow: scale out of range 0-8") } else { - global.pow(b, bp.toInt, e, ep.toInt, rp.toInt, Rounding.byValue(round), useNewPrecision).map(CONST_LONG).leftMap(CommonError(_)) + global.pow(b, bp.toInt, e, ep.toInt, rp.toInt, Rounding.byValue(round), useNewPrecision).map(CONST_LONG.apply).leftMap(CommonError(_)) } case xs => notImplemented[Id, EVALUATED]("pow(base: Int, bp: Int, exponent: Int, ep: Int, rp: Int, round: Rounds)", xs) } @@ -1632,7 +1632,7 @@ object PureContext { ) { Left(CommonError("log: scale out of range 0-8")) } else { - global.log(b, bp, e, ep, rp, Rounding.byValue(round)).map(CONST_LONG).leftMap(CommonError(_)) + global.log(b, bp, e, ep, rp, Rounding.byValue(round)).map(CONST_LONG.apply).leftMap(CommonError(_)) } case xs => notImplemented[Id, EVALUATED]("log(exponent: Int, ep: Int, base: Int, bp: Int, rp: Int, round: Rounds)", xs) } @@ -1665,7 +1665,7 @@ object PureContext { global .powBigInt(b, bp, e, ep, rp, Rounding.byValue(round), useNewPrecision) .filterOrElse(v => v <= BigIntMax && v >= BigIntMin, "Result out of 512-bit range") - .bimap(e => s"$e on BigInt pow calculation", CONST_BIGINT) + .bimap(e => s"$e on BigInt pow calculation", CONST_BIGINT.apply) } case xs => notImplemented[Id, EVALUATED]("pow(base: BigInt, bp: Int, exponent:Big Int, ep: Int, rp: Int, round: Rounds)", xs) } @@ -1719,7 +1719,7 @@ object PureContext { ) { Left("Scale out of range 0-18") } else { - global.logBigInt(b, bp, e, ep, rp, Rounding.byValue(round)).map(CONST_BIGINT) + global.logBigInt(b, bp, e, ep, rp, Rounding.byValue(round)).map(CONST_BIGINT.apply) } r.leftMap(e => s"$e on BigInt log calculation") case xs => notImplemented[Id, EVALUATED]("log(exponent: BigInt, ep: Int, base:Big Int, bp: Int, rp: Int, round: Rounds)", xs) diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/converters/package.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/converters/package.scala index 02aa47b249..bbf1f85e39 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/converters/package.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/converters/package.scala @@ -17,9 +17,9 @@ package object converters { implicit def c(is: Seq[EVALUATED]): EVALUATED = ARR(is.toIndexedSeq, false).explicitGet() implicit def fromOptionBV(v: Option[ByteStr]): EVALUATED = v.flatMap(CONST_BYTESTR(_).toOption).getOrElse(unit) - implicit def fromOptionL(v: Option[Long]): EVALUATED = v.map(CONST_LONG).getOrElse(unit) + implicit def fromOptionL(v: Option[Long]): EVALUATED = v.map(CONST_LONG.apply).getOrElse(unit) implicit def fromOptionS(v: Option[String]): EVALUATED = v.flatMap(CONST_STRING(_).toOption).getOrElse(unit) - implicit def fromOptionB(v: Option[Boolean]): EVALUATED = v.map(CONST_BOOLEAN).getOrElse(unit) + implicit def fromOptionB(v: Option[Boolean]): EVALUATED = v.map(CONST_BOOLEAN.apply).getOrElse(unit) implicit def fromOptionCO(v: Option[CaseObj]): EVALUATED = v.getOrElse(unit) implicit def pure[F[_]: Monad, A <: EVALUATED]( diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/package.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/package.scala index 8668e5965b..d1f5311c89 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/package.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/package.scala @@ -33,7 +33,7 @@ package object impl { val arrayDataByKeyHeaders: Set[FunctionHeader] = Set(DATA_LONG_FROM_ARRAY, DATA_BOOLEAN_FROM_ARRAY, DATA_BYTES_FROM_ARRAY, DATA_STRING_FROM_ARRAY) - .map(Native) + .map(Native.apply) val arrayDataByIndexHeaders: Set[FunctionHeader] = Set("getInteger", "getBoolean", "getBinary", "getString") diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/waves/Bindings.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/waves/Bindings.scala index eabe11c0c7..c3efce308c 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/waves/Bindings.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/waves/Bindings.scala @@ -228,7 +228,7 @@ object Bindings { buildPaymentTransactionType(proofsEnabled), Map("amount" -> CONST_LONG(amount)) ++ provenTxPart(p, proofsEnabled, version) + mapRecipient(recipient) ) - case transfer: Tx.Transfer => transferTransactionObject(transfer, proofsEnabled, version) + case ttx: Tx.Transfer => transferTransactionObject(ttx, proofsEnabled, version) case Tx.Issue(p, quantity, name, description, reissuable, decimals, scriptOpt) => CaseObj( buildIssueTransactionType(proofsEnabled, version), diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/waves/Functions.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/waves/Functions.scala index d748f02c83..271cef3986 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/waves/Functions.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/waves/Functions.scala @@ -23,7 +23,7 @@ import com.wavesplatform.lang.v1.evaluator.{ContextfulNativeFunction, Contextful import com.wavesplatform.lang.v1.traits.domain.{Issue, Lease, Recipient} import com.wavesplatform.lang.v1.traits.{DataType, Environment} import com.wavesplatform.lang.v1.{BaseGlobal, FunctionHeader} -import com.wavesplatform.lang.{CoevalF, CommonError, ExecutionError, FailOrRejectError, ThrownError} +import com.wavesplatform.lang.{CoevalF, CommonError, ExecutionError, FailOrRejectError, ThrownError, toError} import monix.eval.Coeval import shapeless.Coproduct.unsafeGet @@ -440,13 +440,13 @@ object Functions { caseObjToRecipient(c) .fold( _.asLeft[EVALUATED].pure[F], - r => env.accountBalanceOf(r, None).map(_.map(CONST_LONG).leftMap(CommonError(_))) + r => env.accountBalanceOf(r, None).map(_.map(CONST_LONG.apply).leftMap(CommonError(_))) ) case (c: CaseObj) :: CONST_BYTESTR(assetId: ByteStr) :: Nil => caseObjToRecipient(c) .fold( _.asLeft[EVALUATED].pure[F], - r => env.accountBalanceOf(r, Some(assetId.arr)).map(_.map(CONST_LONG).leftMap(CommonError(_))) + r => env.accountBalanceOf(r, Some(assetId.arr)).map(_.map(CONST_LONG.apply).leftMap(CommonError(_))) ) case xs => notImplemented[F, EVALUATED](s"assetBalance(a: Address|Alias, u: ByteVector|Unit)", xs) @@ -470,7 +470,7 @@ object Functions { caseObjToRecipient(c) .fold( _.asLeft[EVALUATED].pure[F], - r => env.accountBalanceOf(r, Some(assetId.arr)).map(_.map(CONST_LONG).leftMap(CommonError(_))) + r => env.accountBalanceOf(r, Some(assetId.arr)).map(_.map(CONST_LONG.apply).leftMap(CommonError(_))) ) case xs => notImplemented[F, EVALUATED](s"assetBalance(a: Address|Alias, u: ByteVector)", xs) @@ -628,7 +628,7 @@ object Functions { } case (dApp: CaseObj) :: _ if dApp.caseType == aliasType => dApp.fields.get("alias") match { - case Some(CONST_STRING(a)) => env.resolveAlias(a).map(_.bimap(ThrownError, _.bytes)) + case Some(CONST_STRING(a)) => env.resolveAlias(a).map(_.bimap(ThrownError.apply, _.bytes)) case arg => thrown(s"Unexpected alias arg $arg") } case arg :: _ => diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/parser/Parser.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/parser/Parser.scala index 45667b8781..c1a75b9c31 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/parser/Parser.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/parser/Parser.scala @@ -48,8 +48,9 @@ class Parser(stdLibVersion: StdLibVersion)(implicit offset: LibrariesOffset) { def unusedText[A: P] = comment ~ directive ~ comment def escapedUnicodeSymbolP[A: P]: P[(Int, String, Int)] = P(Index ~~ (NoCut(unicodeSymbolP) | specialSymbols).! ~~ Index) + def escapedUnicodeOrEndOfString[A: P]: P[Any] = escapedUnicodeSymbolP[A] | notEndOfString def stringP[A: P]: P[EXPR] = - P(Index ~~ "\"" ~/ Pass ~~ (escapedUnicodeSymbolP | notEndOfString).!.repX ~~ "\"" ~~ Index) + P(Index ~~ "\"" ~/ Pass ~~ (escapedUnicodeOrEndOfString).!.repX ~~ "\"" ~~ Index) .map { case (start, xs, end) => var errors = Vector.empty[String] val consumedString = new StringBuilder @@ -245,7 +246,7 @@ class Parser(stdLibVersion: StdLibVersion)(implicit offset: LibrariesOffset) { ContractLimits.MaxTupleSize ) ~ comment ~/ ")") - .map(Tuple) + .map(Tuple.apply) def funcP(implicit c: fastparse.P[Any]): P[FUNC] = { def funcName = anyVarName(check = true) @@ -255,9 +256,9 @@ class Parser(stdLibVersion: StdLibVersion)(implicit offset: LibrariesOffset) { def funcBody = singleBaseExpr def correctFunc = Index ~~ funcKWAndName ~ comment ~/ args(min = 0) ~ ("=" ~ funcBody | "=" ~/ Fail.opaque("function body")) ~~ Index def noKeyword = { - def noArgs = "(" ~ comment ~ ")" ~ comment - def validName = NoCut(funcName).filter(_.isInstanceOf[VALID[?]]) - def argsOrEqual = (NoCut(args(min = 1)) ~ "=".?) | (noArgs ~ "=" ~~ !"=") + def noArgs = "(" ~ comment ~ ")" ~ comment + def validName = NoCut(funcName).filter(_.isInstanceOf[VALID[?]]) + def argsOrEqual: P[Any] = (NoCut(args(min = 1)) ~ "=".?) | (noArgs ~ "=" ~~ !"=") (validName ~ comment ~ argsOrEqual ~/ funcBody.? ~~ Fail) .asInstanceOf[P[Nothing]] .opaque(""""func" keyword""") @@ -381,13 +382,13 @@ class Parser(stdLibVersion: StdLibVersion)(implicit offset: LibrariesOffset) { } def accessP[A: P]: P[(Int, Accessor, Int)] = P( - (("" ~ comment ~ Index ~ "." ~/ comment ~ getterOrOOPCall) ~~ Index) | (Index ~~ "[" ~/ baseExpr.map(ListIndex) ~ "]" ~~ Index) + (("" ~ comment ~ Index ~ "." ~/ comment ~ getterOrOOPCall) ~~ Index) | (Index ~~ "[" ~/ baseExpr.map(ListIndex.apply) ~ "]" ~~ Index) ) def getterOrOOPCall[A: P]: P[Accessor] = (genericMethodName ~~/ ("[" ~ unionTypeP ~/ "]")).map { case (name, tpe) => GenericMethod(name, tpe) - } | (accessOrName.map(Getter) ~/ comment ~~ ("(" ~/ comment ~ functionCallArgs.opaque("""")"""") ~ comment ~/ ")").?).map { + } | (accessOrName.map(Getter.apply) ~/ comment ~~ ("(" ~/ comment ~ functionCallArgs.opaque("""")"""") ~ comment ~/ ")").?).map { case (g @ Getter(name), args) => args.fold(g: Accessor)(Method(name, _)) } diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/serialization/SerdeV1.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/serialization/SerdeV1.scala index 66299dd1e6..f891b1f586 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/serialization/SerdeV1.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/serialization/SerdeV1.scala @@ -68,7 +68,7 @@ object SerdeV1 extends Serde[ByteBuffer, ByteArrayOutputStream] { case E_LONG => Coeval.now(CONST_LONG(bb.getLong)) case E_BYTES => Coeval.now(CONST_BYTESTR(ByteStr(bb.getBytes)).explicitGet()) case E_STRING => Coeval.now(CONST_STRING(bb.getString).explicitGet()) - case E_IF => (desAuxR(bb, allowObjects, acc), desAuxR(bb, allowObjects, acc), desAuxR(bb, allowObjects, acc)).mapN(IF) + case E_IF => (desAuxR(bb, allowObjects, acc), desAuxR(bb, allowObjects, acc), desAuxR(bb, allowObjects, acc)).mapN(IF.apply) case E_BLOCK => for { name <- Coeval.now(bb.getString) diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/serialization/SerdeV2.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/serialization/SerdeV2.scala index b03c14ec41..14c76ff47e 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/serialization/SerdeV2.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/serialization/SerdeV2.scala @@ -69,7 +69,7 @@ object SerdeV2 extends Serde[CodedInputStream, CodedOutputStream] { case E_LONG => Coeval.now(CONST_LONG(in.readInt64())) case E_BYTES => Coeval.now(CONST_BYTESTR(ByteStr(in.readByteArray())).explicitGet()) case E_STRING => Coeval.now(CONST_STRING(in.readString()).explicitGet()) - case E_IF => (desAuxR(in, allowObjects, acc), desAuxR(in, allowObjects, acc), desAuxR(in, allowObjects, acc)).mapN(IF) + case E_IF => (desAuxR(in, allowObjects, acc), desAuxR(in, allowObjects, acc), desAuxR(in, allowObjects, acc)).mapN(IF.apply) case E_BLOCK => for { name <- Coeval.now(in.readString()) diff --git a/lang/testkit/build.sbt b/lang/testkit/build.sbt new file mode 100644 index 0000000000..7a40cca71f --- /dev/null +++ b/lang/testkit/build.sbt @@ -0,0 +1,12 @@ +publishTo := sonatypePublishToBundle.value +publish / skip := false +homepage := Some(url("https://docs.waves.tech/en/ride/")) +developers := List( + Developer("ismagin", "Ilya Smagin", "ilya.smagin@gmail.com", url("https://github.com/ismagin")), + Developer("asayadyan", "Artyom Sayadyan", "xrtm000@gmail.com", url("https://github.com/xrtm000")), + Developer("mpotanin", "Mike Potanin", "mpotanin@wavesplatform.com", url("https://github.com/potan")), + Developer("irakitnykh", "Ivan Rakitnykh", "mrkr.reg@gmail.com", url("https://github.com/mrkraft")) +) + +Compile / packageDoc / publishArtifact := true +Test / packageDoc / publishArtifact := false diff --git a/lang/testkit/src/main/scala/com/wavesplatform/lang/Common.scala b/lang/testkit/src/main/scala/com/wavesplatform/lang/Common.scala index ed520803c2..0d394b3444 100644 --- a/lang/testkit/src/main/scala/com/wavesplatform/lang/Common.scala +++ b/lang/testkit/src/main/scala/com/wavesplatform/lang/Common.scala @@ -38,7 +38,7 @@ object Common { val multiplierFunction: NativeFunction[NoContext] = NativeFunction("MULTIPLY", 1L, 10005.toShort, LONG, ("x1", LONG), ("x2", LONG)) { - case CONST_LONG(x1: Long) :: CONST_LONG(x2: Long) :: Nil => Try(x1 * x2).map(CONST_LONG).toEither.left.map(_.toString) + case CONST_LONG(x1: Long) :: CONST_LONG(x2: Long) :: Nil => Try(x1 * x2).map(CONST_LONG.apply).toEither.left.map(_.toString) case _ => ??? // suppress pattern match warning } diff --git a/lang/testkit/src/main/scala/com/wavesplatform/lang/v1/compiler/TestCompiler.scala b/lang/testkit/src/main/scala/com/wavesplatform/lang/v1/compiler/TestCompiler.scala index deebef973c..58e3cf5743 100644 --- a/lang/testkit/src/main/scala/com/wavesplatform/lang/v1/compiler/TestCompiler.scala +++ b/lang/testkit/src/main/scala/com/wavesplatform/lang/v1/compiler/TestCompiler.scala @@ -96,6 +96,7 @@ class TestCompiler(version: StdLibVersion) { object TestCompiler { private val compilerByVersion = mutable.HashMap.empty[StdLibVersion, TestCompiler] + lazy val DefaultVersion: TestCompiler = TestCompiler(StdLibVersion.VersionDic.default) def apply(version: StdLibVersion): TestCompiler = compilerByVersion.getOrElse( version, diff --git a/lang/testkit/src/main/scala/com/wavesplatform/lang/v1/testing/TypedScriptGen.scala b/lang/testkit/src/main/scala/com/wavesplatform/lang/v1/testing/TypedScriptGen.scala index e605b2c578..f014b32a96 100644 --- a/lang/testkit/src/main/scala/com/wavesplatform/lang/v1/testing/TypedScriptGen.scala +++ b/lang/testkit/src/main/scala/com/wavesplatform/lang/v1/testing/TypedScriptGen.scala @@ -86,7 +86,7 @@ trait TypedScriptGen { private def LONGgen(gas: Int): Gen[EXPR] = if (gas > 0) Gen.oneOf(CONST_LONGgen, BLOCK_LONGgen(gas - 1), IF_LONGgen(gas - 1), FUNCTION_CALLgen(LONG)) else CONST_LONGgen - private def CONST_LONGgen: Gen[EXPR] = Gen.choose(Long.MinValue, Long.MaxValue).map(CONST_LONG) + private def CONST_LONGgen: Gen[EXPR] = Gen.choose(Long.MinValue, Long.MaxValue).map(CONST_LONG.apply) private def BLOCK_LONGgen(gas: Int): Gen[EXPR] = for { diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/IntegrationTest.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/IntegrationTest.scala index 1905a9fa6a..316752d0dd 100755 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/IntegrationTest.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/IntegrationTest.scala @@ -1459,12 +1459,12 @@ class IntegrationTest extends PropSpec with Inside { """.stripMargin val constructingTooBigBytes = constructingMaxBytes + "+ base58'a'" - inside(eval[EVALUATED](constructingMaxBytes, version = V3)) { case Right(CONST_BYTESTR(bytes)) => - bytes.size shouldBe Terms.DataEntryValueMax + inside(eval[EVALUATED](constructingMaxBytes, version = V3)) { case Right(CONST_BYTESTR(bs)) => + bs.size shouldBe Terms.DataEntryValueMax } - inside(eval[EVALUATED](constructingMaxBytes, version = V4)) { case Right(CONST_BYTESTR(bytes)) => - bytes.size shouldBe Terms.DataEntryValueMax + inside(eval[EVALUATED](constructingMaxBytes, version = V4)) { case Right(CONST_BYTESTR(bs)) => + bs.size shouldBe Terms.DataEntryValueMax } eval(constructingTooBigBytes, version = V3) should produce("ByteVector size = 32768 bytes exceeds 32767") diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/estimator/ScriptEstimatorV2Test.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/estimator/ScriptEstimatorV2Test.scala index a5e71db79b..09bfe8172e 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/estimator/ScriptEstimatorV2Test.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/estimator/ScriptEstimatorV2Test.scala @@ -5,6 +5,8 @@ import com.wavesplatform.lang.directives.values.V3 import com.wavesplatform.lang.utils.* import com.wavesplatform.lang.v1.estimator.v2.ScriptEstimatorV2 +import java.util.concurrent.Semaphore + class ScriptEstimatorV2Test extends ScriptEstimatorTestBase(ScriptEstimatorV2) { property("transitive ref usage") { def estimateRefUsage(ref: String): Long = { @@ -62,16 +64,18 @@ class ScriptEstimatorV2Test extends ScriptEstimatorTestBase(ScriptEstimatorV2) { """.stripMargin @volatile var r: Either[String, Long] = Right(0) + val s = new Semaphore(0) val run: Runnable = { () => + s.release() r = estimate(functionCosts(V3), compile(hangingScript)) } val t = new Thread(run) t.setDaemon(true) t.start() - Thread.sleep(5000) + s.acquire() t.interrupt() - Thread.sleep(500) + t.join() r shouldBe Left("Script estimation was interrupted") t.getState shouldBe Thread.State.TERMINATED diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV1V2Test.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV1V2Test.scala index 93359c2b6e..50dccf6104 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV1V2Test.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/EvaluatorV1V2Test.scala @@ -30,7 +30,7 @@ import com.wavesplatform.lang.v1.evaluator.{Contextful, ContextfulVal, Evaluator import com.wavesplatform.lang.v1.parser.Parser.LibrariesOffset.NoLibraries import com.wavesplatform.lang.v1.traits.Environment import com.wavesplatform.lang.v1.{CTX, ContractLimits, FunctionHeader} -import com.wavesplatform.lang.{Common, EvalF, ExecutionError, Global} +import com.wavesplatform.lang.{Common, EvalF, ExecutionError, Global, toError} import com.wavesplatform.test.* import org.scalacheck.{Arbitrary, Gen} import org.scalatest.EitherValues diff --git a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/string/MakeStringTest.scala b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/string/MakeStringTest.scala index b2b2c9f9ec..96fb048f31 100644 --- a/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/string/MakeStringTest.scala +++ b/lang/tests/src/test/scala/com/wavesplatform/lang/evaluator/string/MakeStringTest.scala @@ -27,10 +27,10 @@ class MakeStringTest extends EvaluatorSpec { case Nil => REF(GlobalValNames.Nil) - case value :: rest => + case head :: rest => FUNCTION_CALL( Native(1100), - List(value, mkConsList(rest)) + List(head, mkConsList(rest)) ) } diff --git a/node-generator/src/main/scala/com/wavesplatform/generator/utils/Gen.scala b/node-generator/src/main/scala/com/wavesplatform/generator/utils/Gen.scala index 85c77160c4..d9437c4be6 100644 --- a/node-generator/src/main/scala/com/wavesplatform/generator/utils/Gen.scala +++ b/node-generator/src/main/scala/com/wavesplatform/generator/utils/Gen.scala @@ -35,7 +35,7 @@ object Gen { |${recString(10)} || true """.stripMargin - val script = ScriptCompiler(s, isAssetScript = false, estimator).explicitGet() + val script = ScriptCompiler.compile(s, estimator).explicitGet() script._1 } @@ -65,7 +65,7 @@ object Gen { |} """.stripMargin - val script = ScriptCompiler(src, isAssetScript = false, estimator).explicitGet() + val script = ScriptCompiler.compile(src, estimator).explicitGet() script._1 } @@ -101,7 +101,7 @@ object Gen { |$finalStatement """.stripMargin - val (script, _) = ScriptCompiler(src, isAssetScript = false, estimator) + val (script, _) = ScriptCompiler.compile(src, estimator) .explicitGet() script 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 a5c6761987..04f496b7c0 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/Docker.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/Docker.scala @@ -27,7 +27,7 @@ import org.asynchttpclient.Dsl.* import java.io.{FileOutputStream, IOException} import java.net.{InetAddress, InetSocketAddress, URL} import java.nio.file.{Files, Path, Paths} -import java.time.LocalDateTime +import java.time.{LocalDateTime, Duration as JDuration} import java.time.format.DateTimeFormatter import java.util.Collections.* import java.util.concurrent.ConcurrentHashMap @@ -58,9 +58,9 @@ class Docker( .setMaxConnections(18) .setMaxConnectionsPerHost(3) .setMaxRequestRetry(1) - .setReadTimeout(10000) + .setReadTimeout(JDuration.ofSeconds(10)) .setKeepAlive(false) - .setRequestTimeout(10000) + .setRequestTimeout(JDuration.ofSeconds(10)) ) private val client = DefaultDockerClient.fromEnv().build() @@ -305,7 +305,8 @@ class Docker( private def getNodeInfo(containerId: String, settings: WavesSettings): NodeInfo = { val restApiPort = settings.restAPISettings.port - val networkPort = settings.networkSettings.bindAddress.getPort + // assume test nodes always have an open port + val networkPort = settings.networkSettings.bindAddress.get.getPort val containerInfo = inspectContainer(containerId) val wavesIpAddress = containerInfo.networkSettings().networks().get(wavesNetwork.name()).ipAddress() diff --git a/node-it/src/test/scala/com/wavesplatform/it/IntegrationSuiteWithThreeAddresses.scala b/node-it/src/test/scala/com/wavesplatform/it/IntegrationSuiteWithThreeAddresses.scala index 25ea0cc843..156add8431 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/IntegrationSuiteWithThreeAddresses.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/IntegrationSuiteWithThreeAddresses.scala @@ -49,7 +49,7 @@ trait IntegrationSuiteWithThreeAddresses extends BaseSuite with ScalaFutures wit def setContract(contractText: Option[String], acc: KeyPair): String = { val script = contractText.map { x => val scriptText = x.stripMargin - ScriptCompiler(scriptText, isAssetScript = false, ScriptEstimatorV2).explicitGet()._1 + ScriptCompiler.compile(scriptText, ScriptEstimatorV2).explicitGet()._1 } val setScriptTransaction = SetScriptTransaction .selfSigned(1.toByte, acc, script, 0.014.waves, System.currentTimeMillis()) diff --git a/node-it/src/test/scala/com/wavesplatform/it/api/AsyncHttpApi.scala b/node-it/src/test/scala/com/wavesplatform/it/api/AsyncHttpApi.scala index d2d26afa7b..4e2f4bf832 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/api/AsyncHttpApi.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/api/AsyncHttpApi.scala @@ -4,6 +4,7 @@ import java.io.IOException import java.net.{InetSocketAddress, URLEncoder} import java.util.concurrent.TimeoutException import java.util.{NoSuchElementException, UUID} +import java.time.{Duration as JDuration} import com.google.protobuf.ByteString import com.wavesplatform.account.{AddressOrAlias, AddressScheme, KeyPair, SeedKeyPair} import com.wavesplatform.api.http.DebugMessage.* @@ -12,7 +13,7 @@ import com.wavesplatform.api.http.requests.{IssueRequest, TransferRequest} import com.wavesplatform.api.http.{ConnectReq, DebugMessage, RollbackParams, `X-Api-Key`} import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.{Base58, Base64, EitherExt2} -import com.wavesplatform.features.api.ActivationStatus +import com.wavesplatform.features.api.{ActivationStatus, activationStatusFormat} import com.wavesplatform.it.Node import com.wavesplatform.it.sync.invokeExpressionFee import com.wavesplatform.it.util.* @@ -41,7 +42,9 @@ import com.wavesplatform.transaction.{ TxExchangePrice, TxNonNegativeAmount, TxPositiveAmount, - TxVersion + TxVersion, + TransactionSignOps, + TransactionValidationOps } import org.asynchttpclient.* import org.asynchttpclient.Dsl.{delete as _delete, get as _get, post as _post, put as _put} @@ -181,8 +184,8 @@ object AsyncHttpApi extends Assertions { def request = _get(s"${n.nodeApiEndpoint}/blocks/height?${System.currentTimeMillis()}") - .setReadTimeout(timeout) - .setRequestTimeout(timeout) + .setReadTimeout(JDuration.ofMillis(timeout)) + .setRequestTimeout(JDuration.ofMillis(timeout)) .build() def send(): Future[Option[Response]] = @@ -691,7 +694,7 @@ object AsyncHttpApi extends Assertions { ) def removeData(sender: KeyPair, data: Seq[String], fee: Long, version: Byte = 2): Future[Transaction] = - broadcastData(sender, data.map[DataEntry[?]](EmptyDataEntry), fee, version) + broadcastData(sender, data.map[DataEntry[?]](EmptyDataEntry.apply), fee, version) def getData(address: String, amountsAsStrings: Boolean = false): Future[List[DataEntry[?]]] = get(s"/addresses/data/$address", amountsAsStrings).as[List[DataEntry[?]]](amountsAsStrings) diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/ScriptLogSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/ScriptLogSuite.scala index b00508e12f..44a1cbcd62 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/ScriptLogSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/ScriptLogSuite.scala @@ -66,7 +66,7 @@ class ScriptLogSuite extends BaseTransactionSuite with CancelAfterFailure { sender.putData(firstKeyPair, data, ENOUGH_FEE, waitForTx = true).id - val script = ScriptCompiler(scriptSrc, isAssetScript = false, ScriptEstimatorV2).explicitGet()._1 + val script = ScriptCompiler.compile(scriptSrc, ScriptEstimatorV2).explicitGet()._1 val setScriptTransaction = SetScriptTransaction .selfSigned(1.toByte, firstKeyPair, Some(script), setScriptFee, System.currentTimeMillis()) .explicitGet() diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/FailedTransactionGrpcSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/FailedTransactionGrpcSuite.scala deleted file mode 100644 index cc611ee78b..0000000000 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/FailedTransactionGrpcSuite.scala +++ /dev/null @@ -1,274 +0,0 @@ -package com.wavesplatform.it.sync.grpc - -import com.google.protobuf.ByteString -import com.typesafe.config.Config -import com.wavesplatform.account.{Address, KeyPair} -import com.wavesplatform.common.state.ByteStr -import com.wavesplatform.common.utils.{Base58, EitherExt2} -import com.wavesplatform.it.api.SyncGrpcApi.* -import com.wavesplatform.it.sync.* -import com.wavesplatform.it.sync.transactions.FailedTransactionSuiteLike -import com.wavesplatform.lang.v1.FunctionHeader -import com.wavesplatform.lang.v1.compiler.Terms.FUNCTION_CALL -import com.wavesplatform.lang.v1.estimator.v3.ScriptEstimatorV3 -import com.wavesplatform.protobuf.Amount -import com.wavesplatform.protobuf.transaction.DataEntry -import com.wavesplatform.protobuf.transaction.{PBRecipients, PBSignedTransaction, PBTransactions, Recipient} -import com.wavesplatform.state.{BinaryDataEntry, StringDataEntry} -import com.wavesplatform.test.* -import com.wavesplatform.transaction.smart.script.ScriptCompiler - -class FailedTransactionGrpcSuite extends GrpcBaseTransactionSuite with FailedTransactionSuiteLike[PBSignedTransaction] { - import FailedTransactionSuiteLike.* - import grpcApi.* - - private val contract = KeyPair("thirdContract".getBytes("UTF-8")) - private val contractAddr = PBRecipients.create(Address.fromPublicKey(contract.publicKey)).getPublicKeyHash - private val caller = thirdAcc - private val callerAddr = PBRecipients.create(Address.fromPublicKey(thirdAcc.publicKey)).getPublicKeyHash - - private val assetAmount = 1000000000L - private var smartAsset = "" - private var sponsoredAsset = "" - - protected override def beforeAll(): Unit = { - super.beforeAll() - - sender.broadcastTransfer(sender.keyPair, Recipient().withPublicKeyHash(contractAddr), 100.waves, minFee, waitForTx = true) - - smartAsset = PBTransactions - .vanillaUnsafe( - sender - .broadcastIssue( - contract, - "Asset", - assetAmount, - 8, - reissuable = true, - issueFee, - description = "Description", - script = Right(ScriptCompiler.compile("true", ScriptEstimatorV3.latest).toOption.map(_._1)), - waitForTx = true - ) - ) - .id() - .toString - - sponsoredAsset = PBTransactions - .vanillaUnsafe( - sender - .broadcastIssue( - contract, - "Sponsored Asset", - assetAmount, - 8, - reissuable = true, - issueFee, - "Description", - script = Right(None), - waitForTx = true - ) - ) - .id() - .toString - - val scriptTextV4 = - s""" - |{-# STDLIB_VERSION 4 #-} - |{-# CONTENT_TYPE DAPP #-} - | - |let asset = base58'$smartAsset' - | - |@Callable(inv) - |func tikTok() = { - | let action = valueOrElse(getString(this, "tikTok"), "unknown") - | let check = ${"sigVerify(base58'', base58'', base58'') ||" * 16} false - | if (check) then [] - | else if (action == "transfer") then [ScriptTransfer(inv.caller, 15, asset)] - | else if (action == "issue") then [Issue("new asset", "", 100, 8, true, unit, 0)] - | else if (action == "reissue") then [Reissue(asset, 15, true)] - | else if (action == "burn") then [Burn(asset, 15)] - | else [] - |} - | - |@Callable(inv) - |func transferAndWrite(x: Int) = { - | let check = ${"sigVerify(base58'', base58'', base58'') ||" * 16} false - | if (check) then [] - | else if (x % 4 == 0) then [ScriptTransfer(inv.caller, 15, asset), IntegerEntry("n", x)] - | else if (x % 4 == 1) then [ScriptTransfer(inv.caller, 15, asset), BooleanEntry("b", x % 2 == 0)] - | else if (x % 4 == 2) then [ScriptTransfer(inv.caller, 15, asset), BinaryEntry("bn", toBytes(x))] - | else if (x % 4 == 3) then [ScriptTransfer(inv.caller, 15, asset), StringEntry("s", toString(x))] - | else [] - |} - | - |@Callable(inv) - |func canThrow() = { - | let action = valueOrElse(getString(this, "crash"), "no") - | let check = ${"sigVerify(base58'', base58'', base58'') ||" * 16} true - | - | if (action == "yes") - | then { - | if (check) - | then throw("Crashed by dApp") - | else throw("Crashed by dApp") - | } - | else [] - |} - | - """.stripMargin - val script = ScriptCompiler.compile(scriptTextV4, ScriptEstimatorV3.latest).explicitGet()._1 - sender.setScript(contract, Right(Some(script)), setScriptFee, waitForTx = true) - } - - test("InvokeScriptTransaction: invoke script error in payment asset propagates failed transaction") { - val invokeFee = 0.005.waves + smartFee - val setAssetScriptMinFee = setAssetScriptFee + smartFee - val priorityFee = setAssetScriptMinFee + invokeFee - - val paymentAsset = PBTransactions - .vanillaUnsafe( - sender - .broadcastIssue( - caller, - "paymentAsset", - assetAmount, - 8, - reissuable = true, - script = Right(ScriptCompiler.compile("true", ScriptEstimatorV3.latest).toOption.map(_._1)), - fee = issueFee + smartFee, - waitForTx = true - ) - ) - .id() - - updateAssetScript(result = true, smartAsset, contract, setAssetScriptMinFee) - updateTikTok("unknown", setAssetScriptMinFee) - - overflowBlock() - sendTxsAndThenPriorityTx( - _ => - sender - .broadcastInvokeScript( - caller, - Recipient().withPublicKeyHash(contractAddr), - Some(FUNCTION_CALL(FunctionHeader.User("tikTok"), List.empty)), - payments = Seq(Amount(ByteString.copyFrom(paymentAsset.arr), 15)), - fee = invokeFee - ), - () => updateAssetScript(result = false, paymentAsset.toString, caller, priorityFee, waitForTx = false) - )((txs, _) => assertFailedTxs(txs)) - } - - test("InvokeScriptTransaction: sponsored fee on failed transaction should be charged correctly") { - val invokeFee = 0.005.waves + smartFee - val invokeFeeInAsset = invokeFee / 100000 // assetFee = feeInWaves / feeUnit * sponsorship - val setAssetScriptMinFee = setAssetScriptFee + smartFee * 2 - val priorityFee = setAssetScriptMinFee + invokeFee - - updateAssetScript(result = true, smartAsset, contract, setAssetScriptMinFee) - updateTikTok("reissue", setAssetScriptMinFee) - - sender.broadcastSponsorFee( - contract, - Some(Amount.of(ByteString.copyFrom(Base58.decode(sponsoredAsset)), 1)), - sponsorFee + smartFee, - waitForTx = true - ) - sender.broadcastTransfer( - contract, - Recipient().withPublicKeyHash(callerAddr), - assetAmount, - smartMinFee, - assetId = sponsoredAsset, - waitForTx = true - ) - val prevBalance = sender.wavesBalance(contractAddr).regular - - sendTxsAndThenPriorityTx( - _ => - sender.broadcastInvokeScript( - caller, - Recipient().withPublicKeyHash(contractAddr), - Some(FUNCTION_CALL(FunctionHeader.User("tikTok"), List.empty)), - fee = invokeFeeInAsset, - feeAssetId = ByteString.copyFrom(Base58.decode(sponsoredAsset)) - ), - () => updateAssetScript(result = false, smartAsset, contract, priorityFee) - ) { (txs, _) => - sender.wavesBalance(contractAddr).regular shouldBe prevBalance - invokeFee * txs.size - priorityFee - assertFailedTxs(txs) - } - } - - test("InvokeScriptTransaction: reject transactions if account script failed") { - val invokeFee = 0.005.waves - val setAssetScriptMinFee = setAssetScriptFee + smartFee * 2 - val priorityFee = setAssetScriptMinFee + invokeFee - - updateTikTok("unknown", setAssetScriptMinFee) - updateAssetScript(result = true, smartAsset, contract, setAssetScriptMinFee) - - overflowBlock() - val prevBalance = sender.wavesBalance(callerAddr).regular - sendTxsAndThenPriorityTx( - _ => - sender.broadcastInvokeScript( - caller, - Recipient().withPublicKeyHash(contractAddr), - Some(FUNCTION_CALL(FunctionHeader.User("tikTok"), List.empty)), - fee = invokeFee - ), - () => - sender.setScript( - caller, - Right( - ScriptCompiler - .compile( - s""" - |{-# STDLIB_VERSION 3 #-} - |{-# CONTENT_TYPE EXPRESSION #-} - |{-# SCRIPT_TYPE ACCOUNT #-} - | - |match (tx) { - |case _: InvokeScriptTransaction => false - |case _ => true - |} - |""".stripMargin, - ScriptEstimatorV3.latest - ) - .toOption - .map(_._1) - ), - fee = priorityFee - ) - ) { (txs, _) => - val invalid = assertInvalidTxs(txs) - sender.wavesBalance(callerAddr).regular shouldBe prevBalance - (txs.size - invalid.size) * invokeFee - priorityFee - invalid - } - } - - def overflowBlock(): Unit = { - val entries = List.tabulate(4)(n => PBTransactions.toPBDataEntry(BinaryDataEntry("test" + n, ByteStr(Array.fill(32767)(n.toByte))))) - val fee = calcDataFee(entries) - waitForEmptyUtx() - waitForHeightArise() - for (_ <- 1 to 8) sender.putData(sender.keyPair, entries, fee) - waitForEmptyUtx() - } - - private def calcDataFee(data: List[DataEntry]): Long = { - val dataSize = data.map(_.toByteArray.length).sum + 128 - if (dataSize > 1024) { - minFee * (dataSize / 1024 + 1) - } else minFee - } - - private def updateTikTok(result: String, fee: Long, waitForTx: Boolean = true): PBSignedTransaction = - sender.putData(contract, List(StringDataEntry("tikTok", result)).map(PBTransactions.toPBDataEntry), fee = fee, waitForTx = waitForTx) - - override protected def waitForHeightArise(): Unit = sender.waitForHeightArise() - - override protected def nodeConfigs: Seq[Config] = Configs -} diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/SetAssetScriptGrpcSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/SetAssetScriptGrpcSuite.scala index 5a20efc6f4..aacb257d94 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/SetAssetScriptGrpcSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/SetAssetScriptGrpcSuite.scala @@ -1,30 +1,25 @@ package com.wavesplatform.it.sync.grpc import com.wavesplatform.common.utils.EitherExt2 -import com.wavesplatform.it.api.SyncGrpcApi._ -import com.wavesplatform.it.sync._ -import com.wavesplatform.lang.v1.estimator.v2.ScriptEstimatorV2 +import com.wavesplatform.it.api.SyncGrpcApi.* +import com.wavesplatform.it.sync.* +import com.wavesplatform.lang.v1.compiler.TestCompiler import com.wavesplatform.protobuf.transaction.PBTransactions -import com.wavesplatform.transaction.smart.script.ScriptCompiler import io.grpc.Status.Code -import scala.concurrent.duration._ +import scala.concurrent.duration.* class SetAssetScriptGrpcSuite extends GrpcBaseTransactionSuite { - val estimator = ScriptEstimatorV2 - var assetWOScript = "" var assetWScript = "" - private val unchangeableScript = ScriptCompiler( + private val unchangeableScript = TestCompiler.DefaultVersion.compileAsset( s""" |match tx { | case _: SetAssetScriptTransaction => false | case _ => true |} - """.stripMargin, - isAssetScript = true, - estimator - ).explicitGet()._1 + """.stripMargin + ) test("issuer cannot change script on asset w/o initial script") { val firstBalance = sender.wavesBalance(firstAddress).available @@ -57,16 +52,14 @@ class SetAssetScriptGrpcSuite extends GrpcBaseTransactionSuite { fee = issueFee, script = Right( Some( - ScriptCompiler( + TestCompiler.DefaultVersion.compileAsset( s""" - |match tx { - | case s: SetAssetScriptTransaction => s.sender == addressFromPublicKey(base58'${secondAcc.publicKey}') - | case _ => false - |} - """.stripMargin, - isAssetScript = true, - estimator - ).explicitGet()._1 + |match tx { + | case s: SetAssetScriptTransaction => s.sender == addressFromPublicKey(base58'${secondAcc.publicKey}') + | case _ => false + |} + """.stripMargin + ) ) ), waitForTx = true @@ -85,16 +78,14 @@ class SetAssetScriptGrpcSuite extends GrpcBaseTransactionSuite { } test("sender's waves balance is decreased by fee") { - val script2 = ScriptCompiler( + val script2 = TestCompiler.DefaultVersion.compileAsset( s""" |match tx { | case _: SetAssetScriptTransaction => true | case _ => false |} - """.stripMargin, - isAssetScript = true, - estimator - ).explicitGet()._1 + """.stripMargin + ) val firstBalance = sender.wavesBalance(firstAddress).available val firstEffBalance = sender.wavesBalance(firstAddress).effective diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/SetScriptTransactionGrpcSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/SetScriptTransactionGrpcSuite.scala index af49a060fc..e35bfc25e1 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/SetScriptTransactionGrpcSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/SetScriptTransactionGrpcSuite.scala @@ -41,7 +41,7 @@ class SetScriptTransactionGrpcSuite extends GrpcBaseTransactionSuite { } """.stripMargin - val script = ScriptCompiler(scriptText, isAssetScript = false, ScriptEstimatorV2).explicitGet()._1 + val script = ScriptCompiler.compile(scriptText, ScriptEstimatorV2).explicitGet()._1 val estimatorV3 = ScriptEstimatorV3(fixOverflow = true, overhead = true, letFixes = false) val scriptComplexity = Script .estimate( @@ -183,7 +183,7 @@ class SetScriptTransactionGrpcSuite extends GrpcBaseTransactionSuite { test("not able to broadcast tx from scripted acc if tx fee doesn't include smart fee") { for (v <- setScrTxSupportedVersions) { val (contract, contractAddr) = if (v < 2) (firstAcc, firstAddress) else (secondAcc, secondAddress) - val script = ScriptCompiler(s"true", isAssetScript = false, ScriptEstimatorV2).explicitGet()._1 + val script = ScriptCompiler.compile(s"true", ScriptEstimatorV2).explicitGet()._1 sender.setScript(contract, Right(Some(script)), setScriptFee, waitForTx = true) val contractBalance = sender.wavesBalance(contractAddr).available diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/UpdateAssetInfoTransactionGrpcSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/UpdateAssetInfoTransactionGrpcSuite.scala index a77fac82ac..bc81e23aaa 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/UpdateAssetInfoTransactionGrpcSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/grpc/UpdateAssetInfoTransactionGrpcSuite.scala @@ -5,10 +5,9 @@ import com.wavesplatform.common.utils.EitherExt2 import com.wavesplatform.it.NodeConfigs.Miners import com.wavesplatform.it.api.SyncGrpcApi.* import com.wavesplatform.it.sync.* -import com.wavesplatform.lang.v1.estimator.v2.ScriptEstimatorV2 +import com.wavesplatform.lang.v1.compiler.TestCompiler import com.wavesplatform.protobuf.transaction.PBTransactions import com.wavesplatform.transaction.assets.IssueTransaction.{MaxAssetDescriptionLength, MaxAssetNameLength, MinAssetNameLength} -import com.wavesplatform.transaction.smart.script.ScriptCompiler import io.grpc.Status.Code import org.scalatest.prop.TableDrivenPropertyChecks @@ -108,7 +107,7 @@ class UpdateAssetInfoTransactionGrpcSuite extends GrpcBaseTransactionSuite with test("can update asset only with description which have valid length") { val invalidDescs = Seq("a" * (MaxAssetDescriptionLength + 1)) - val validDescs = Seq("", "a" * MaxAssetDescriptionLength) + val validDescs = Seq("", "a" * MaxAssetDescriptionLength) invalidDescs.foreach { desc => assertGrpcError( sender.updateAssetInfo(issuer, assetId, "updatedName", desc, minFee), @@ -152,7 +151,7 @@ class UpdateAssetInfoTransactionGrpcSuite extends GrpcBaseTransactionSuite with test("check increased fee for smart sender/asset") { val scriptText = s"""true""".stripMargin - val script = ScriptCompiler(scriptText, isAssetScript = true, ScriptEstimatorV2).explicitGet()._1 + val script = TestCompiler.DefaultVersion.compileAsset(scriptText) val smartAssetId = PBTransactions .vanilla( diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/package.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/package.scala index 703bc7f608..1ca8c7b3ff 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/package.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/package.scala @@ -65,7 +65,7 @@ package object sync { val aliasTxSupportedVersions: List[Byte] = List(1, 2, 3) val reissueTxSupportedVersions: List[Byte] = List(1, 2, 3) - val script: Script = ScriptCompiler(s"""true""".stripMargin, isAssetScript = false, ScriptEstimatorV2).explicitGet()._1 + val script: Script = ScriptCompiler.compile(s"""true""".stripMargin, ScriptEstimatorV2).explicitGet()._1 val scriptBase64: String = script.bytes().base64 val scriptBase64Raw: String = script.bytes().base64Raw diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/AtomicSwapSmartContractSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/AtomicSwapSmartContractSuite.scala index 878b48eb00..74c5b2e159 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/AtomicSwapSmartContractSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/AtomicSwapSmartContractSuite.scala @@ -73,7 +73,7 @@ class AtomicSwapSmartContractSuite extends BaseTransactionSuite with CancelAfter }""".stripMargin val pkSwapBC1 = swapBC1 - val script = ScriptCompiler(scriptText, isAssetScript = false, ScriptEstimatorV2).explicitGet()._1 + val script = ScriptCompiler.compile(scriptText, ScriptEstimatorV2).explicitGet()._1 val sc1SetTx = SetScriptTransaction .selfSigned(1.toByte, sender = pkSwapBC1, script = Some(script), fee = setScriptFee, timestamp = System.currentTimeMillis()) .explicitGet() diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/BigStringSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/BigStringSuite.scala index cccf4b886a..abee10e7f6 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/BigStringSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/BigStringSuite.scala @@ -43,7 +43,7 @@ class BigStringSuite extends BaseTransactionSuite with CancelAfterFailure { } """.stripMargin - val script = ScriptCompiler(scriptText, isAssetScript = false, ScriptEstimatorV2).explicitGet()._1 + val script = ScriptCompiler.compile(scriptText, ScriptEstimatorV2).explicitGet()._1 val setScriptTransaction = SetScriptTransaction .selfSigned(1.toByte, acc0, Some(script), setScriptFee, System.currentTimeMillis()) .explicitGet() diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/InvokePaymentsAvailabilitySuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/InvokePaymentsAvailabilitySuite.scala index 209cf54282..ee96f54719 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/InvokePaymentsAvailabilitySuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/InvokePaymentsAvailabilitySuite.scala @@ -33,7 +33,7 @@ class InvokePaymentsAvailabilitySuite extends BaseTransactionSuite { private lazy val (proxyDApp, proxyDAppAddress) = (thirdKeyPair, thirdAddress) private def syncDApp(dApp: String) = - ScriptCompiler( + ScriptCompiler.compile( s""" |{-# STDLIB_VERSION 5 #-} |{-# CONTENT_TYPE DAPP #-} @@ -52,12 +52,11 @@ class InvokePaymentsAvailabilitySuite extends BaseTransactionSuite { | } | """.stripMargin, - isAssetScript = false, ScriptEstimatorV3.latest ).explicitGet()._1.bytes().base64 private val dApp = - ScriptCompiler( + ScriptCompiler.compile( s""" | {-# STDLIB_VERSION 5 #-} | {-# CONTENT_TYPE DAPP #-} @@ -72,7 +71,6 @@ class InvokePaymentsAvailabilitySuite extends BaseTransactionSuite { | ] | } """.stripMargin, - isAssetScript = false, ScriptEstimatorV3.latest ).explicitGet()._1.bytes().base64 diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/LeaseSmartContractsTestSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/LeaseSmartContractsTestSuite.scala index b1edaa3c1b..08c5c52d40 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/LeaseSmartContractsTestSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/LeaseSmartContractsTestSuite.scala @@ -38,7 +38,7 @@ class LeaseSmartContractsTestSuite extends BaseTransactionSuite with CancelAfter } """.stripMargin - val script = ScriptCompiler(scriptText, isAssetScript = false, ScriptEstimatorV2).explicitGet()._1.bytes().base64 + val script = ScriptCompiler.compile(scriptText, ScriptEstimatorV2).explicitGet()._1.bytes().base64 sender.setScript(acc0, Some(script), setScriptFee, waitForTx = true).id val unsignedLeasing = diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/MassTransferSmartContractSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/MassTransferSmartContractSuite.scala index 104b0c6245..4da481244a 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/MassTransferSmartContractSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/MassTransferSmartContractSuite.scala @@ -59,7 +59,7 @@ class MassTransferSmartContractSuite extends BaseTransactionSuite with CancelAft |""".stripMargin // set script - val script = ScriptCompiler(scriptText, isAssetScript = false, ScriptEstimatorV2).explicitGet()._1.bytes().base64 + val script = ScriptCompiler.compile(scriptText, ScriptEstimatorV2).explicitGet()._1.bytes().base64 notMiner.setScript(notMiner.keyPair, Some(script), setScriptFee, waitForTx = true).id notMiner.addressScriptInfo(notMiner.address).scriptText.isEmpty shouldBe false diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/PaymentValidationSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/PaymentValidationSuite.scala index 63a20f67f4..5d1bb8dc7d 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/PaymentValidationSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/PaymentValidationSuite.scala @@ -3,9 +3,11 @@ package com.wavesplatform.it.sync.smartcontract import com.wavesplatform.api.http.ApiError.ScriptExecutionError import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.{Base58, EitherExt2} -import com.wavesplatform.it.api.SyncHttpApi._ +import com.wavesplatform.it.api.SyncHttpApi.* import com.wavesplatform.it.sync.{issueFee, setScriptFee, smartFee} import com.wavesplatform.it.transactions.BaseTransactionSuite +import com.wavesplatform.lang.directives.values.V4 +import com.wavesplatform.lang.v1.compiler.TestCompiler import com.wavesplatform.lang.v1.estimator.v3.ScriptEstimatorV3 import com.wavesplatform.transaction.Asset.IssuedAsset import com.wavesplatform.transaction.smart.InvokeScriptTransaction.Payment @@ -31,17 +33,9 @@ class PaymentValidationSuite extends BaseTransactionSuite { val scriptV4 = ScriptCompiler.compile(sourceV4, ScriptEstimatorV3.latest).explicitGet()._1.bytes().base64 sender.setScript(dApp, Some(scriptV4), setScriptFee, waitForTx = true) - val scr = ScriptCompiler( - s""" - |{-# STDLIB_VERSION 4 #-} - |{-# CONTENT_TYPE EXPRESSION #-} - |{-# SCRIPT_TYPE ASSET #-} - | - |getStringValue(addressFromString("${dApp.toAddress.toString}").value(), "$wrKey") == "$wrValue" - """.stripMargin, - isAssetScript = true, - ScriptEstimatorV3.latest - ).explicitGet()._1.bytes().base64 + val scr = TestCompiler(V4).compileAsset( + s"""getStringValue(addressFromString("${dApp.toAddress.toString}").value(), "$wrKey") == "$wrValue"""" + ).bytes().base64 val smartAssetId = sender.issue(caller, script = Some(scr), fee = issueFee + smartFee, waitForTx = true).id assertApiError( diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/PseudoTransactionSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/PseudoTransactionSuite.scala index 0a664db74e..5ff0e2215f 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/PseudoTransactionSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/PseudoTransactionSuite.scala @@ -3,11 +3,11 @@ package com.wavesplatform.it.sync.smartcontract import com.wavesplatform.account.AddressOrAlias import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.EitherExt2 -import com.wavesplatform.it.api.SyncHttpApi._ -import com.wavesplatform.it.sync._ +import com.wavesplatform.it.api.SyncHttpApi.* +import com.wavesplatform.it.sync.* import com.wavesplatform.it.transactions.BaseTransactionSuite import com.wavesplatform.lang.v1.FunctionHeader -import com.wavesplatform.lang.v1.compiler.Terms +import com.wavesplatform.lang.v1.compiler.{Terms, TestCompiler} import com.wavesplatform.lang.v1.compiler.Terms.{EXPR, FUNCTION_CALL} import com.wavesplatform.lang.v1.estimator.v3.ScriptEstimatorV3 import com.wavesplatform.transaction.Asset.Waves @@ -30,7 +30,7 @@ class PseudoTransactionSuite extends BaseTransactionSuite { super.beforeAll() smartAssetId = sender.issue(firstDApp, fee = issueFee, script = Some(scriptBase64), waitForTx = true).id - val dAppScript = ScriptCompiler( + val dAppScript = ScriptCompiler.compile( s""" |{-# STDLIB_VERSION 4 #-} |{-# CONTENT_TYPE DAPP #-} @@ -48,7 +48,6 @@ class PseudoTransactionSuite extends BaseTransactionSuite { |@Callable (i) |func transferAssetByAlias(r: String, a: ByteVector, q: Int) = [ScriptTransfer(Alias(r), q, a)] """.stripMargin, - isAssetScript = false, ScriptEstimatorV3.latest ).explicitGet()._1.bytes().base64 @@ -132,7 +131,7 @@ class PseudoTransactionSuite extends BaseTransactionSuite { } private def smartAssetScript(invokeId: String): String = - ScriptCompiler( + TestCompiler.DefaultVersion.compileAsset( s""" |{-# STDLIB_VERSION 4 #-} |{-# CONTENT_TYPE EXPRESSION #-} @@ -169,10 +168,8 @@ class PseudoTransactionSuite extends BaseTransactionSuite { | && b.quantity == 100000 | case _ => true | } - """.stripMargin, - isAssetScript = true, - ScriptEstimatorV3.latest - ).explicitGet()._1.bytes().base64 + """.stripMargin + ).bytes().base64 private def invokeScriptTransaction(func: String, args: List[EXPR]): InvokeScriptTransaction = Signed.invokeScript( diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/RideFuncSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/RideFuncSuite.scala index 3428023af4..744fefdf87 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/RideFuncSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/RideFuncSuite.scala @@ -42,7 +42,7 @@ class RideFuncSuite extends BaseTransactionSuite with CancelAfterFailure { |} """.stripMargin - val compiled = ScriptCompiler(scriptSrc, isAssetScript = false, estimator).explicitGet()._1 + val compiled = ScriptCompiler.compile(scriptSrc, estimator).explicitGet()._1 val tx = sender.signedBroadcast( @@ -94,7 +94,7 @@ class RideFuncSuite extends BaseTransactionSuite with CancelAfterFailure { |} """.stripMargin - val updated = ScriptCompiler(udpatedScript, isAssetScript = false, estimator).explicitGet()._1 + val updated = ScriptCompiler.compile(udpatedScript, estimator).explicitGet()._1 val updTx = sender.signedBroadcast( diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/ScriptExecutionErrorSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/ScriptExecutionErrorSuite.scala index 201e2fca5d..d3248e8e87 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/ScriptExecutionErrorSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/ScriptExecutionErrorSuite.scala @@ -32,7 +32,7 @@ class ScriptExecutionErrorSuite extends BaseTransactionSuite with CancelAfterFai |} """.stripMargin - val compiled = ScriptCompiler(scriptSrc, isAssetScript = false, ScriptEstimatorV2).explicitGet()._1 + val compiled = ScriptCompiler.compile(scriptSrc, ScriptEstimatorV2).explicitGet()._1 val tx = sender.signedBroadcast(SetScriptTransaction.selfSigned(1.toByte, thirdKeyPair, Some(compiled), setScriptFee, ts).explicitGet().json()) nodes.waitForHeightAriseAndTxPresent(tx.id) diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/SelfPaymentDappToDappSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/SelfPaymentDappToDappSuite.scala index 064d9809ae..96817d3bdc 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/SelfPaymentDappToDappSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/SelfPaymentDappToDappSuite.scala @@ -30,7 +30,7 @@ class SelfPaymentDappToDappSuite extends BaseTransactionSuite { private lazy val (dApp1, dAppAddress1) = (secondKeyPair, secondAddress) private lazy val (dApp2, dAppAddress2) = (thirdKeyPair, thirdAddress) - private val dAppScript1 = ScriptCompiler( + private val dAppScript1 = ScriptCompiler.compile( s""" |{-# STDLIB_VERSION 5 #-} |{-# CONTENT_TYPE DAPP #-} @@ -48,11 +48,10 @@ class SelfPaymentDappToDappSuite extends BaseTransactionSuite { |} | """.stripMargin, - isAssetScript = false, ScriptEstimatorV3.latest ).explicitGet()._1.bytes().base64 - private val dAppScript2 = ScriptCompiler( + private val dAppScript2 = ScriptCompiler.compile( s""" |{-# STDLIB_VERSION 5 #-} |{-# CONTENT_TYPE DAPP #-} @@ -71,7 +70,6 @@ class SelfPaymentDappToDappSuite extends BaseTransactionSuite { |} | """.stripMargin, - isAssetScript = false, ScriptEstimatorV3.latest ).explicitGet()._1.bytes().base64 diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/SetScriptTransactionSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/SetScriptTransactionSuite.scala index b5f3c0470b..cca93a25ee 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/SetScriptTransactionSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/SetScriptTransactionSuite.scala @@ -50,7 +50,7 @@ class SetScriptTransactionSuite extends BaseTransactionSuite with CancelAfterFai """.stripMargin val (contractBalance, contractEffBalance) = sender.accountBalances(contract.toAddress.toString) - val script = ScriptCompiler(scriptText, isAssetScript = false, ScriptEstimatorV2).explicitGet()._1.bytes().base64 + val script = ScriptCompiler.compile(scriptText, ScriptEstimatorV2).explicitGet()._1.bytes().base64 val setScriptId = sender.setScript(contract, Some(script), setScriptFee, version = v).id nodes.waitForHeightAriseAndTxPresent(setScriptId) diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/SponsorshipForContactsSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/SponsorshipForContactsSuite.scala index acacb6846c..a6b07f66db 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/SponsorshipForContactsSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/SponsorshipForContactsSuite.scala @@ -15,7 +15,7 @@ class SponsorshipForContactsSuite extends BaseTransactionSuite with CancelAfterF sender.sponsorAsset(firstKeyPair, assetId, 100, sponsorReducedFee, waitForTx = true) sender.transfer(firstKeyPair, secondAddress, someAssetAmount / 2, minFee, Some(assetId), None, waitForTx = true) - val script = ScriptCompiler(s"""false""".stripMargin, isAssetScript = false, ScriptEstimatorV2).explicitGet()._1.bytes().base64 + val script = ScriptCompiler.compile(s"""false""".stripMargin, ScriptEstimatorV2).explicitGet()._1.bytes().base64 val _ = sender.setScript(acc0, Some(script), setScriptFee, waitForTx = true) val firstAddressBalance = sender.accountBalances(firstAddress)._1 diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/TypeEntrySuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/TypeEntrySuite.scala index 55268517eb..538632eb88 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/TypeEntrySuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/TypeEntrySuite.scala @@ -2,9 +2,10 @@ package com.wavesplatform.it.sync.smartcontract import com.wavesplatform.api.http.ApiError.ScriptExecutionError import com.wavesplatform.common.utils.EitherExt2 -import com.wavesplatform.it.api.SyncHttpApi._ +import com.wavesplatform.it.api.SyncHttpApi.* import com.wavesplatform.it.sync.{issueFee, smartMinFee} import com.wavesplatform.it.transactions.BaseTransactionSuite +import com.wavesplatform.lang.v1.compiler.TestCompiler import com.wavesplatform.lang.v1.estimator.v3.ScriptEstimatorV3 import com.wavesplatform.transaction.smart.script.ScriptCompiler @@ -21,7 +22,7 @@ class TypeEntrySuite extends BaseTransactionSuite { protected override def beforeAll(): Unit = { super.beforeAll() - val smartAssetScript = ScriptCompiler( + val smartAssetScript =TestCompiler.DefaultVersion.compileAsset( s""" |{-# STDLIB_VERSION 4 #-} |{-# CONTENT_TYPE EXPRESSION #-} @@ -31,14 +32,12 @@ class TypeEntrySuite extends BaseTransactionSuite { | && getIntegerValue(addressFromStringValue(""), "int") == 1 | && getBooleanValue(addressFromStringValue(""), "bool") == true | && getStringValue(addressFromStringValue(""), "str") == "string" - """.stripMargin, - isAssetScript = true, - ScriptEstimatorV3.latest - ).explicitGet()._1.bytes().base64 + """.stripMargin + ).bytes().base64 firstAssetId = sender.issue(firstDApp, fee = issueFee, script = Some(smartAssetScript), waitForTx = true).id - val dAppScript = ScriptCompiler( + val dAppScript = ScriptCompiler.compile( s""" |{-# STDLIB_VERSION 4 #-} |{-# CONTENT_TYPE DAPP #-} @@ -95,11 +94,10 @@ class TypeEntrySuite extends BaseTransactionSuite { |} | """.stripMargin, - isAssetScript = false, ScriptEstimatorV3.latest ).explicitGet()._1.bytes().base64 - val accountScript = ScriptCompiler( + val accountScript = ScriptCompiler.compile( s""" {-# STDLIB_VERSION 4 #-} |{-# CONTENT_TYPE EXPRESSION #-} @@ -111,7 +109,6 @@ class TypeEntrySuite extends BaseTransactionSuite { | && getStringValue(addressFromStringValue("${firstDApp.toAddress.toString}"), "str") == "string" | """.stripMargin, - isAssetScript = false, ScriptEstimatorV3.latest ).explicitGet()._1.bytes().base64 diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/UTXAllowance.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/UTXAllowance.scala index c078ea6432..86ad62b8d2 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/UTXAllowance.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/UTXAllowance.scala @@ -25,7 +25,7 @@ class UTXAllowance extends BaseFreeSpec with WaitForHeight2 { i.transfer(i.keyPair, acc.toAddress.toString, 10.waves, 0.005.waves, None, waitForTx = true) val scriptText = s"""true""".stripMargin - val script = ScriptCompiler(scriptText, isAssetScript = false, ScriptEstimatorV2).explicitGet()._1.bytes().base64 + val script = ScriptCompiler.compile(scriptText, ScriptEstimatorV2).explicitGet()._1.bytes().base64 i.setScript(acc, Some(script), setScriptFee, waitForTx = true) acc diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/smartasset/AssetSupportedTransactionsSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/smartasset/AssetSupportedTransactionsSuite.scala index 95bec90363..610ac8195c 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/smartasset/AssetSupportedTransactionsSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/smartasset/AssetSupportedTransactionsSuite.scala @@ -1,22 +1,20 @@ package com.wavesplatform.it.sync.smartcontract.smartasset -import scala.concurrent.duration._ - import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.EitherExt2 -import com.wavesplatform.it.api.SyncHttpApi._ -import com.wavesplatform.it.sync._ +import com.wavesplatform.it.api.SyncHttpApi.* +import com.wavesplatform.it.sync.* import com.wavesplatform.it.transactions.BaseTransactionSuite -import com.wavesplatform.lang.v1.estimator.v2.ScriptEstimatorV2 +import com.wavesplatform.lang.v1.compiler.TestCompiler import com.wavesplatform.state.IntegerDataEntry import com.wavesplatform.transaction.Asset.{IssuedAsset, Waves} -import com.wavesplatform.transaction.smart.script.ScriptCompiler import com.wavesplatform.transaction.transfer.MassTransferTransaction.Transfer import com.wavesplatform.transaction.transfer.TransferTransaction +import scala.concurrent.duration.* + class AssetSupportedTransactionsSuite extends BaseTransactionSuite { - private val estimator = ScriptEstimatorV2 - var asset = "" + var asset = "" protected override def beforeAll(): Unit = { super.beforeAll() @@ -48,18 +46,19 @@ class AssetSupportedTransactionsSuite extends BaseTransactionSuite { sender.transfer(secondKeyPair, thirdAddress, 100, smartMinFee, Some(asset), waitForTx = true) - //deprecate transfers with amount > 99 - val scr = ScriptCompiler( - s""" - |match tx { - | case _ : SetAssetScriptTransaction => true - | case t: TransferTransaction => t.amount <= 99 - | case _ => false - |} - """.stripMargin, - isAssetScript = true, - estimator - ).explicitGet()._1.bytes().base64 + // deprecate transfers with amount > 99 + val scr = TestCompiler.DefaultVersion + .compileAsset( + s""" + |match tx { + | case _ : SetAssetScriptTransaction => true + | case t: TransferTransaction => t.amount <= 99 + | case _ => false + |} + """.stripMargin + ) + .bytes() + .base64 sender.setAssetScript(asset, firstKeyPair, setAssetScriptFee + smartFee, Some(scr), waitForTx = true) assertApiError(sender.transfer(firstKeyPair, secondAddress, 100, smartMinFee, Some(asset)), errNotAllowedByTokenApiError) @@ -73,17 +72,18 @@ class AssetSupportedTransactionsSuite extends BaseTransactionSuite { } test("transfer goes only to addresses from list (white or black)") { - val scr = ScriptCompiler( - s""" - |match tx { - | case _: SetAssetScriptTransaction => true - | case t: TransferTransaction => t.recipient == addressFromPublicKey(base58'${secondKeyPair.publicKey}') - | case _ => false - |} - """.stripMargin, - isAssetScript = true, - estimator - ).explicitGet()._1.bytes().base64 + val scr = TestCompiler.DefaultVersion + .compileAsset( + s""" + |match tx { + | case _: SetAssetScriptTransaction => true + | case t: TransferTransaction => t.recipient == addressFromPublicKey(base58'${secondKeyPair.publicKey}') + | case _ => false + |} + """.stripMargin + ) + .bytes() + .base64 sender.setAssetScript(asset, firstKeyPair, setAssetScriptFee + smartFee, Some(scr), waitForTx = true) sender.transfer(firstKeyPair, secondAddress, 100, smartMinFee, Some(asset), waitForTx = true) @@ -92,17 +92,18 @@ class AssetSupportedTransactionsSuite extends BaseTransactionSuite { assertApiError(sender.transfer(firstKeyPair, firstAddress, 1, smartMinFee, Some(asset)), errNotAllowedByTokenApiError) - val scr1 = ScriptCompiler( - s""" - |match tx { - | case _: SetAssetScriptTransaction => true - | case t: TransferTransaction => t.recipient != addressFromPublicKey(base58'${secondKeyPair.publicKey}') && t.recipient != addressFromPublicKey(base58'${firstKeyPair.publicKey}') - | case _ => false - |} - """.stripMargin, - isAssetScript = true, - estimator - ).explicitGet()._1.bytes().base64 + val scr1 = TestCompiler.DefaultVersion + .compileAsset( + s""" + |match tx { + | case _: SetAssetScriptTransaction => true + | case t: TransferTransaction => t.recipient != addressFromPublicKey(base58'${secondKeyPair.publicKey}') && t.recipient != addressFromPublicKey(base58'${firstKeyPair.publicKey}') + | case _ => false + |} + """.stripMargin + ) + .bytes() + .base64 sender.setAssetScript(asset, firstKeyPair, setAssetScriptFee + smartFee, Some(scr1), waitForTx = true) sender.transfer(firstKeyPair, thirdAddress, 100, smartMinFee, Some(asset), waitForTx = true) @@ -119,17 +120,18 @@ class AssetSupportedTransactionsSuite extends BaseTransactionSuite { sender.sponsorAsset(firstKeyPair, feeAsset, baseFee = 2, fee = sponsorReducedFee + smartFee, waitForTx = true) - val scr = ScriptCompiler( - s""" - |match tx { - | case _: SetAssetScriptTransaction => true - | case t: TransferTransaction => t.feeAssetId == base58'$feeAsset' - | case _ => false - |} - """.stripMargin, - isAssetScript = true, - estimator - ).explicitGet()._1.bytes().base64 + val scr = TestCompiler.DefaultVersion + .compileAsset( + s""" + |match tx { + | case _: SetAssetScriptTransaction => true + | case t: TransferTransaction => t.feeAssetId == base58'$feeAsset' + | case _ => false + |} + """.stripMargin + ) + .bytes() + .base64 sender.setAssetScript(asset, firstKeyPair, setAssetScriptFee + smartFee, Some(scr), waitForTx = true) assertApiError(sender.transfer(firstKeyPair, thirdAddress, 100, 2, Some(asset), feeAssetId = Some(feeAsset))) { error => @@ -160,18 +162,19 @@ class AssetSupportedTransactionsSuite extends BaseTransactionSuite { sender.transfer(firstKeyPair, secondAddress, 100, smartMinFee, Some(blackAsset), waitForTx = true) - val scr = ScriptCompiler( - s""" - |match tx { - | case _: SetAssetScriptTransaction => true - | case t: TransferTransaction => let issuer = extract(addressFromString("$firstAddress")) - | isDefined(getInteger(issuer,toBase58String(t.id))) == true - | case _ => false - |} - """.stripMargin, - isAssetScript = true, - estimator - ).explicitGet()._1.bytes().base64 + val scr = TestCompiler.DefaultVersion + .compileAsset( + s""" + |match tx { + | case _: SetAssetScriptTransaction => true + | case t: TransferTransaction => let issuer = extract(addressFromString("$firstAddress")) + | isDefined(getInteger(issuer,toBase58String(t.id))) == true + | case _ => false + |} + """.stripMargin + ) + .bytes() + .base64 sender.setAssetScript(blackAsset, firstKeyPair, setAssetScriptFee + smartFee, Some(scr), waitForTx = true) val blackTx = TransferTransaction @@ -217,34 +220,36 @@ class AssetSupportedTransactionsSuite extends BaseTransactionSuite { sender.transfer(firstKeyPair, thirdAddress, 100, smartMinFee, Some(asset), waitForTx = true) - val scr = ScriptCompiler( - s""" - |match tx { - | case _ : SetAssetScriptTransaction => true - | case b: BurnTransaction => b.sender == addressFromPublicKey(base58'${secondKeyPair.publicKey}') - | case _ => false - |} - """.stripMargin, - isAssetScript = true, - estimator - ).explicitGet()._1.bytes().base64 + val scr = TestCompiler.DefaultVersion + .compileAsset( + s""" + |match tx { + | case _ : SetAssetScriptTransaction => true + | case b: BurnTransaction => b.sender == addressFromPublicKey(base58'${secondKeyPair.publicKey}') + | case _ => false + |} + """.stripMargin + ) + .bytes() + .base64 sender.setAssetScript(asset, firstKeyPair, setAssetScriptFee + smartFee, Some(scr), waitForTx = true) sender.burn(secondKeyPair, asset, 10, smartMinFee, waitForTx = true) assertApiError(sender.burn(firstKeyPair, asset, 10, smartMinFee), errNotAllowedByTokenApiError) - val scr1 = ScriptCompiler( - s""" - |match tx { - | case _: SetAssetScriptTransaction => true - | case b: BurnTransaction => b.sender != addressFromPublicKey(base58'${secondKeyPair.publicKey}') - | case _ => false - |} - """.stripMargin, - isAssetScript = true, - estimator - ).explicitGet()._1.bytes().base64 + val scr1 = TestCompiler.DefaultVersion + .compileAsset( + s""" + |match tx { + | case _: SetAssetScriptTransaction => true + | case b: BurnTransaction => b.sender != addressFromPublicKey(base58'${secondKeyPair.publicKey}') + | case _ => false + |} + """.stripMargin + ) + .bytes() + .base64 sender.setAssetScript(asset, firstKeyPair, setAssetScriptFee + smartFee, Some(scr1), waitForTx = true) sender.burn(thirdKeyPair, asset, 10, smartMinFee, waitForTx = true) @@ -255,17 +260,18 @@ class AssetSupportedTransactionsSuite extends BaseTransactionSuite { } ignore("burn by some height") { - val scr = ScriptCompiler( - s""" - |match tx { - | case _: SetAssetScriptTransaction => true - | case _: BurnTransaction => height % 2 == 0 - | case _ => false - |} - """.stripMargin, - isAssetScript = true, - estimator - ).explicitGet()._1.bytes().base64 + val scr = TestCompiler.DefaultVersion + .compileAsset( + s""" + |match tx { + | case _: SetAssetScriptTransaction => true + | case _: BurnTransaction => height % 2 == 0 + | case _ => false + |} + """.stripMargin + ) + .bytes() + .base64 sender.setAssetScript(asset, firstKeyPair, setAssetScriptFee + smartFee, Some(scr), waitForTx = true) if (nodes.map(_.height).max % 2 != 0) nodes.waitForHeightArise() @@ -291,16 +297,17 @@ class AssetSupportedTransactionsSuite extends BaseTransactionSuite { issueFee, 2, Some( - ScriptCompiler( - s""" - |match tx { - | case _: BurnTransaction => false - | case _ => true - |} - """.stripMargin, - isAssetScript = true, - estimator - ).explicitGet()._1.bytes().base64 + TestCompiler.DefaultVersion + .compileAsset( + s""" + |match tx { + | case _: BurnTransaction => false + | case _ => true + |} + """.stripMargin + ) + .bytes() + .base64 ), waitForTx = true ) @@ -310,21 +317,22 @@ class AssetSupportedTransactionsSuite extends BaseTransactionSuite { } test("masstransfer - taxation") { - val scr = ScriptCompiler( - s""" - |match tx { - | case _: SetAssetScriptTransaction => true - | case m: MassTransferTransaction => - | let twoTransfers = size(m.transfers) == 2 - | let issuerIsRecipient = m.transfers[0].recipient == addressFromString("$firstAddress") - | let taxesPaid = m.transfers[0].amount >= m.transfers[1].amount / 10 - | twoTransfers && issuerIsRecipient && taxesPaid - | case _ => false - |} - """.stripMargin, - isAssetScript = true, - estimator - ).explicitGet()._1.bytes().base64 + val scr = TestCompiler.DefaultVersion + .compileAsset( + s""" + |match tx { + | case _: SetAssetScriptTransaction => true + | case m: MassTransferTransaction => + | let twoTransfers = size(m.transfers) == 2 + | let issuerIsRecipient = m.transfers[0].recipient == addressFromString("$firstAddress") + | let taxesPaid = m.transfers[0].amount >= m.transfers[1].amount / 10 + | twoTransfers && issuerIsRecipient && taxesPaid + | case _ => false + |} + """.stripMargin + ) + .bytes() + .base64 sender.setAssetScript(asset, firstKeyPair, setAssetScriptFee + smartFee, Some(scr), waitForTx = true) val transfers = List(Transfer(firstAddress, 10), Transfer(secondAddress, 100)) @@ -336,18 +344,19 @@ class AssetSupportedTransactionsSuite extends BaseTransactionSuite { } test("masstransfer - transferCount <=2") { - val scr = ScriptCompiler( - s""" - |match tx { - | case _: SetAssetScriptTransaction => true - | case m: MassTransferTransaction => - | m.transferCount <= 2 - | case _ => false - |} - """.stripMargin, - isAssetScript = true, - estimator - ).explicitGet()._1.bytes().base64 + val scr = TestCompiler.DefaultVersion + .compileAsset( + s""" + |match tx { + | case _: SetAssetScriptTransaction => true + | case m: MassTransferTransaction => + | m.transferCount <= 2 + | case _ => false + |} + """.stripMargin + ) + .bytes() + .base64 sender.setAssetScript(asset, firstKeyPair, setAssetScriptFee + smartFee, Some(scr), waitForTx = true) val transfers = List(Transfer(firstAddress, 10), Transfer(secondAddress, 100), Transfer(firstAddress, 10)) @@ -365,17 +374,18 @@ class AssetSupportedTransactionsSuite extends BaseTransactionSuite { error.message should include("Reason: Asset was issued by other address") } - val scr = ScriptCompiler( - s""" - |match tx { - | case _: SetAssetScriptTransaction => true - | case r: ReissueTransaction => r.sender == addressFromPublicKey(base58'${secondKeyPair.publicKey}') - | case _ => false - |} - """.stripMargin, - isAssetScript = true, - estimator - ).explicitGet()._1.bytes().base64 + val scr = TestCompiler.DefaultVersion + .compileAsset( + s""" + |match tx { + | case _: SetAssetScriptTransaction => true + | case r: ReissueTransaction => r.sender == addressFromPublicKey(base58'${secondKeyPair.publicKey}') + | case _ => false + |} + """.stripMargin + ) + .bytes() + .base64 sender.setAssetScript(asset, firstKeyPair, setAssetScriptFee + smartFee, Some(scr), waitForTx = true) assertApiError(sender.reissue(secondKeyPair, asset, someAssetAmount, reissuable = true, fee = issueFee + smartFee)) { error => @@ -399,16 +409,17 @@ class AssetSupportedTransactionsSuite extends BaseTransactionSuite { ) .id - val scr = ScriptCompiler( - s""" - |match tx { - | case _: SetAssetScriptTransaction => true - | case r: ReissueTransaction => r.sender == addressFromPublicKey(base58'${secondKeyPair.publicKey}') - | case _ => false - |}""".stripMargin, - isAssetScript = true, - estimator - ).explicitGet()._1.bytes().base64 + val scr = TestCompiler.DefaultVersion + .compileAsset( + s""" + |match tx { + | case _: SetAssetScriptTransaction => true + | case r: ReissueTransaction => r.sender == addressFromPublicKey(base58'${secondKeyPair.publicKey}') + | case _ => false + |}""".stripMargin + ) + .bytes() + .base64 sender.setAssetScript(assetNonReissue, firstKeyPair, setAssetScriptFee + smartFee, Some(scr), waitForTx = true) assertApiError( @@ -433,7 +444,7 @@ class AssetSupportedTransactionsSuite extends BaseTransactionSuite { reissuable = false, issueFee, 2, - script = Some(ScriptCompiler(s"false".stripMargin, isAssetScript = true, estimator).explicitGet()._1.bytes().base64), + script = Some(TestCompiler.DefaultVersion.compileAsset(s"false".stripMargin).bytes().base64), waitForTx = true ) .id diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/smartasset/AssetUnsupportedTransactionsSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/smartasset/AssetUnsupportedTransactionsSuite.scala index 9c1836173c..1cdf4f0cb5 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/smartasset/AssetUnsupportedTransactionsSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/smartasset/AssetUnsupportedTransactionsSuite.scala @@ -1,11 +1,9 @@ package com.wavesplatform.it.sync.smartcontract.smartasset -import com.wavesplatform.common.utils.EitherExt2 -import com.wavesplatform.it.api.SyncHttpApi._ -import com.wavesplatform.it.sync.{someAssetAmount, _} +import com.wavesplatform.it.api.SyncHttpApi.* +import com.wavesplatform.it.sync.* import com.wavesplatform.it.transactions.BaseTransactionSuite -import com.wavesplatform.lang.v1.estimator.v2.ScriptEstimatorV2 -import com.wavesplatform.transaction.smart.script.ScriptCompiler +import com.wavesplatform.lang.v1.compiler.TestCompiler import org.scalatest.prop.TableDrivenPropertyChecks class AssetUnsupportedTransactionsSuite extends BaseTransactionSuite with TableDrivenPropertyChecks { @@ -34,15 +32,16 @@ class AssetUnsupportedTransactionsSuite extends BaseTransactionSuite with TableD issueFee, 2, Some( - ScriptCompiler( - s""" - |match tx { - | case _: $tx => true - | case _ => true - |}""".stripMargin, - isAssetScript = true, - ScriptEstimatorV2 - ).explicitGet()._1.bytes().base64 + TestCompiler.DefaultVersion + .compileAsset( + s""" + |match tx { + | case _: $tx => true + | case _ => true + |}""".stripMargin + ) + .bytes() + .base64 ), waitForTx = true ) diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/smartasset/ExchangeSmartAssetsSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/smartasset/ExchangeSmartAssetsSuite.scala index 5fa833dc98..0f5e953a14 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/smartasset/ExchangeSmartAssetsSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/smartasset/ExchangeSmartAssetsSuite.scala @@ -43,13 +43,12 @@ class ExchangeSmartAssetsSuite extends BaseTransactionSuite with CancelAfterFail combination of smart accounts and smart assets */ val s = Some( - ScriptCompiler( - s""" + ScriptCompiler.compile( + s"""{-# SCRIPT_TYPE ASSET #-} |match tx { |case _: SetAssetScriptTransaction => true |case e: ExchangeTransaction => e.sender == addressFromPublicKey(base58'${acc2.publicKey}') |case _ => false}""".stripMargin, - isAssetScript = true, estimator ).explicitGet()._1.bytes().base64 ) @@ -74,13 +73,12 @@ class ExchangeSmartAssetsSuite extends BaseTransactionSuite with CancelAfterFail } val sUpdated = Some( - ScriptCompiler( - s""" + ScriptCompiler.compile( + s"""{-# SCRIPT_TYPE ASSET #-} |match tx { |case _: SetAssetScriptTransaction => true |case e: ExchangeTransaction => e.sender == addressFromPublicKey(base58'${acc1.publicKey}') |case _ => false}""".stripMargin, - isAssetScript = true, estimator ).explicitGet()._1.bytes().base64 ) @@ -108,15 +106,14 @@ class ExchangeSmartAssetsSuite extends BaseTransactionSuite with CancelAfterFail sender.transfer(firstKeyPair, secondAddress, 1000, minFee + smartFee, Some(assetA), waitForTx = true) val script = Some( - ScriptCompiler( - s""" + ScriptCompiler.compile( + s"""{-# SCRIPT_TYPE ASSET #-} |let assetA = base58'$assetA' |let assetB = base58'$assetB' |match tx { |case _: SetAssetScriptTransaction => true |case e: ExchangeTransaction => (e.sellOrder.assetPair.priceAsset == assetA || e.sellOrder.assetPair.amountAsset == assetA) && (e.sellOrder.assetPair.priceAsset == assetB || e.sellOrder.assetPair.amountAsset == assetB) |case _ => false}""".stripMargin, - isAssetScript = true, estimator ).explicitGet()._1.bytes().base64 ) @@ -164,9 +161,9 @@ class ExchangeSmartAssetsSuite extends BaseTransactionSuite with CancelAfterFail } test("use all functions from RIDE for asset script") { - val script1 = Some(ScriptCompiler(cryptoContextScript(false), isAssetScript = true, estimator).explicitGet()._1.bytes().base64) - val script2 = Some(ScriptCompiler(pureContextScript(dtx, false), isAssetScript = true, estimator).explicitGet()._1.bytes().base64) - val script3 = Some(ScriptCompiler(wavesContextScript(dtx, false), isAssetScript = true, estimator).explicitGet()._1.bytes().base64) + val script1 = Some(ScriptCompiler.compile("{-# SCRIPT_TYPE ASSET #-}" + cryptoContextScript(false), estimator).explicitGet()._1.bytes().base64) + val script2 = Some(ScriptCompiler.compile("{-# SCRIPT_TYPE ASSET #-}" + pureContextScript(dtx, false), estimator).explicitGet()._1.bytes().base64) + val script3 = Some(ScriptCompiler.compile("{-# SCRIPT_TYPE ASSET #-}" + wavesContextScript(dtx, false), estimator).explicitGet()._1.bytes().base64) List(script1, script2, script3) .map { i => diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/smartasset/NoOrderProofsSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/smartasset/NoOrderProofsSuite.scala index 310b8e8e2d..5af7a8fd9d 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/smartasset/NoOrderProofsSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/smartcontract/smartasset/NoOrderProofsSuite.scala @@ -3,9 +3,10 @@ package com.wavesplatform.it.sync.smartcontract.smartasset import com.wavesplatform.account.AddressScheme import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.EitherExt2 -import com.wavesplatform.it.api.SyncHttpApi._ -import com.wavesplatform.it.sync.{someAssetAmount, _} +import com.wavesplatform.it.api.SyncHttpApi.* +import com.wavesplatform.it.sync.{someAssetAmount, *} import com.wavesplatform.it.transactions.BaseTransactionSuite +import com.wavesplatform.lang.v1.compiler.TestCompiler import com.wavesplatform.lang.v1.estimator.v2.ScriptEstimatorV2 import com.wavesplatform.transaction.Asset.{IssuedAsset, Waves} import com.wavesplatform.transaction.{Proofs, TxPositiveAmount} @@ -13,7 +14,7 @@ import com.wavesplatform.transaction.assets.BurnTransaction import com.wavesplatform.transaction.smart.script.ScriptCompiler import com.wavesplatform.transaction.transfer.TransferTransaction -import scala.concurrent.duration._ +import scala.concurrent.duration.* class NoOrderProofsSuite extends BaseTransactionSuite { val estimator = ScriptEstimatorV2 @@ -29,15 +30,13 @@ class NoOrderProofsSuite extends BaseTransactionSuite { issueFee, 2: Byte, script = Some( - ScriptCompiler( + TestCompiler.DefaultVersion.compileAsset( s""" |match tx { | case _: Order => true | case _ => false |}""".stripMargin, - isAssetScript = true, - estimator - ).explicitGet()._1.bytes().base64 + ).bytes().base64 ) ) @@ -61,14 +60,13 @@ class NoOrderProofsSuite extends BaseTransactionSuite { issueFee, 2: Byte, script = Some( - ScriptCompiler( + ScriptCompiler.compile( s""" let proof = base58'assetWProofs' match tx { case _: SetAssetScriptTransaction | TransferTransaction | ReissueTransaction | BurnTransaction => tx.proofs[0] == proof case _ => false }""".stripMargin, - false, estimator ).explicitGet()._1.bytes().base64 ), diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/AliasTransactionSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/AliasTransactionSuite.scala index 84120ef17c..a03e93ef16 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/AliasTransactionSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/AliasTransactionSuite.scala @@ -16,9 +16,9 @@ import com.wavesplatform.it.transactions.BaseTransactionSuite import com.wavesplatform.lang.directives.values.V6 import com.wavesplatform.lang.v1.compiler.TestCompiler import com.wavesplatform.test.* -import com.wavesplatform.transaction.{CreateAliasTransaction, Proofs, TxPositiveAmount} +import com.wavesplatform.transaction.* import org.scalatest.prop.TableDrivenPropertyChecks -import play.api.libs.json.Json +import play.api.libs.json.* class AliasTransactionSuite extends BaseTransactionSuite with TableDrivenPropertyChecks { override protected def nodeConfigs: Seq[Config] = diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/FailedTransactionSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/FailedTransactionSuite.scala deleted file mode 100644 index e7de960af5..0000000000 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/FailedTransactionSuite.scala +++ /dev/null @@ -1,262 +0,0 @@ -package com.wavesplatform.it.sync.transactions - -import com.typesafe.config.Config -import com.wavesplatform.api.http.ApiError.TransactionNotAllowedByAssetScript -import com.wavesplatform.api.http.DebugMessage -import com.wavesplatform.common.utils.EitherExt2 -import com.wavesplatform.it.api.SyncHttpApi.* -import com.wavesplatform.it.sync.* -import com.wavesplatform.it.transactions.BaseTransactionSuite -import com.wavesplatform.lang.v1.estimator.v3.ScriptEstimatorV3 -import com.wavesplatform.state.StringDataEntry -import com.wavesplatform.test.* -import com.wavesplatform.transaction.assets.exchange.AssetPair -import com.wavesplatform.transaction.smart.script.ScriptCompiler -import org.scalatest.CancelAfterFailure - -import scala.concurrent.duration.* - -class FailedTransactionSuite extends BaseTransactionSuite with CancelAfterFailure with FailedTransactionSuiteLike[String] with OverflowBlock { - import FailedTransactionSuite.* - import FailedTransactionSuiteLike.* - import restApi.* - - private lazy val contract = sender.createKeyPair() - private def caller = thirdKeyPair - - private val assetAmount = 1000000000L - private var smartAsset = "" - - private def seller = firstKeyPair - private def buyer = secondKeyPair - private def matcher = thirdKeyPair - - private def sellerAddress = firstKeyPair - private def buyerAddress = secondKeyPair - private def matcherAddress = thirdKeyPair - - private lazy val contractAddress: String = contract.toAddress.toString - - protected override def beforeAll(): Unit = { - super.beforeAll() - - sender.transfer(sender.keyPair, contractAddress, 100.waves, minFee, waitForTx = true) - - smartAsset = sender - .issue( - contract, - "Asset", - "Description", - assetAmount, - 8, - script = Some(ScriptCompiler.compile("true", ScriptEstimatorV3.latest).explicitGet()._1.bytes().base64), - waitForTx = true - ) - .id - - val scriptTextV4 = - s""" - |{-# STDLIB_VERSION 4 #-} - |{-# CONTENT_TYPE DAPP #-} - | - |let asset = base58'$smartAsset' - | - |@Callable(inv) - |func tikTok() = { - | let check = ${"sigVerify(base58'', base58'', base58'') ||" * 16} false - | let action = valueOrElse(getString(this, "tikTok"), "unknown") - | if (check) then [] - | else if (action == "transfer") then [ScriptTransfer(inv.caller, 15, asset)] - | else if (action == "issue") then [Issue("new asset", "", 100, 8, true, unit, 0)] - | else if (action == "reissue") then [Reissue(asset, 15, true)] - | else if (action == "burn") then [Burn(asset, 15)] - | else [] - |} - | - |@Callable(inv) - |func transferAndWrite(x: Int) = { - | if (x % 4 == 0) then [ScriptTransfer(inv.caller, 15, asset), IntegerEntry("n", x)] - | else if (x % 4 == 1) then [ScriptTransfer(inv.caller, 15, asset), BooleanEntry("b", x % 2 == 0)] - | else if (x % 4 == 2) then [ScriptTransfer(inv.caller, 15, asset), BinaryEntry("bn", toBytes(x))] - | else if (x % 4 == 3) then [ScriptTransfer(inv.caller, 15, asset), StringEntry("s", toString(x))] - | else [] - |} - | - |@Callable(inv) - |func canThrow() = { - | let action = valueOrElse(getString(this, "crash"), "no") - | let check = ${"sigVerify(base58'', base58'', base58'') ||" * 16} true - | - | if (action == "yes") - | then { - | if (check) - | then throw("Crashed by dApp") - | else throw("Crashed by dApp") - | } - | else [] - |} - | - |@Callable(inv) - |func defineTxHeight(id: ByteVector) = [BooleanEntry(toBase58String(id), transactionHeightById(id).isDefined())] - | - |@Callable(inv) - |func failAfterFirstCallHeight() = { - | strict c = ${"sigVerify(base58'', base58'', base58'') ||" * 16} true - | let heightEntry = match this.getInteger("heightEntry") { - | case _: Unit => height - | case h => if (h == height) then h else throw("height differs") - | } - | [IntegerEntry("heightEntry", heightEntry)] - |} - | - """.stripMargin - - val script = ScriptCompiler.compile(scriptTextV4, ScriptEstimatorV3.latest).explicitGet()._1.bytes().base64 - sender.setScript(contract, Some(script), setScriptFee, waitForTx = true).id - } - - test("InvokeScriptTransaction: reject transactions if account script failed") { - val invokeFee = 0.005.waves - val setAssetScriptMinFee = setAssetScriptFee + smartFee - val priorityFee = setAssetScriptMinFee + invokeFee - - updateTikTok("unknown", setAssetScriptMinFee) - updateAssetScript(result = true, smartAsset, contract, setAssetScriptMinFee) - - val prevBalance = sender.balance(caller.toAddress.toString).balance - - overflowBlock() - sendTxsAndThenPriorityTx( - _ => sender.invokeScript(caller, contractAddress, Some("tikTok"), fee = invokeFee)._1.id, - () => - sender - .setScript( - caller, - Some( - ScriptCompiler - .compile( - s""" - |{-# STDLIB_VERSION 3 #-} - |{-# CONTENT_TYPE EXPRESSION #-} - |{-# SCRIPT_TYPE ACCOUNT #-} - | - |match (tx) { - | case _: InvokeScriptTransaction => false - | case _ => true - |} - |""".stripMargin, - ScriptEstimatorV3.latest - ) - .explicitGet() - ._1 - .bytes() - .base64 - ), - fee = priorityFee - ) - .id - ) { (txs, priorityTx) => - logPriorityTx(priorityTx) - val invalid = assertInvalidTxs(txs) - sender.balance(caller.toAddress.toString).balance shouldBe prevBalance - (txs.size - invalid.size) * invokeFee - priorityFee - invalid - } - } - - test("ExchangeTransaction: invalid exchange tx when asset script fails on broadcast") { - val init = Seq( - sender.setScript(firstKeyPair, None, setScriptFee + smartFee).id, - sender.setScript(secondKeyPair, None, setScriptFee + smartFee).id, - sender.setScript(thirdKeyPair, None, setScriptFee + smartFee).id - ) - waitForTxs(init) - - val Precondition(amountAsset, priceAsset, buyFeeAsset, sellFeeAsset) = - exchangePreconditions( - Some(ScriptCompiler.compile("true", ScriptEstimatorV3.latest).explicitGet()._1.bytes().base64) - ) - - val assetPair = AssetPair.createAssetPair(amountAsset, priceAsset).get - val fee = 0.003.waves + 4 * smartFee - val sellMatcherFee = fee / 100000L - val buyMatcherFee = fee / 100000L - - val allCases = - Seq((amountAsset, sellerAddress), (priceAsset, buyerAddress), (sellFeeAsset, matcherAddress), (buyFeeAsset, matcherAddress)) - - for ((invalidScriptAsset, owner) <- allCases) { - updateAssetScript(result = false, invalidScriptAsset, owner, setAssetScriptFee + smartFee) - val tx = mkExchange(buyer, seller, matcher, assetPair, fee, buyFeeAsset, sellFeeAsset, buyMatcherFee, sellMatcherFee) - assertApiError( - sender.signedBroadcast(tx.json()), - AssertiveApiError(TransactionNotAllowedByAssetScript.Id, "Transaction is not allowed by token-script") - ) - assertInvalidTxs(Seq(tx.id().toString)) - updateAssetScript(result = true, invalidScriptAsset, owner, setAssetScriptFee + smartFee) - } - } - - test("InvokeScriptTransaction: revalidate transactions returned to UTXPool because of `min-micro-block-age`") { - docker.restartNode(dockerNodes().head, configForMinMicroblockAge) - - val caller = sender.createKeyPair() - sender.transfer(sender.keyPair, caller.toAddress.toString, 100.waves, minFee, waitForTx = true) - - val txs = (1 to 9).map { _ => sender.invokeScript(caller, contractAddress, Some("failAfterFirstCallHeight"), fee = invokeFee) } - - val failHeight = txs.map(tx => sender.waitForTransaction(tx._1.id)).map(_.height).max - val failedTxs = sender.blockAt(failHeight).transactions.map(_.id) - - assertFailedTxs(failedTxs) - } - - def updateTikTok(result: String, fee: Long, waitForTx: Boolean = true): String = - sender.broadcastData(contract, List(StringDataEntry("tikTok", result)), fee = fee, waitForTx = waitForTx).id - - private def waitForTxs(txs: Seq[String]): Unit = - nodes.waitFor("preconditions", 500.millis)(_.transactionStatus(txs).forall(_.status == "confirmed"))(_.forall(identity)) - - private def exchangePreconditions(initScript: Option[String]): Precondition = { - val transfers = Seq( - sender.transfer(sender.keyPair, sellerAddress.toAddress.toString, 100.waves).id, - sender.transfer(sender.keyPair, buyerAddress.toAddress.toString, 100.waves).id, - sender.transfer(sender.keyPair, matcherAddress.toAddress.toString, 100.waves).id - ) - - val amountAsset = sender.issue(sellerAddress, "Amount asset", script = initScript, decimals = 8).id - val priceAsset = sender.issue(buyerAddress, "Price asset", script = initScript, decimals = 8).id - val sellFeeAsset = sender.issue(matcherAddress, "Seller fee asset", script = initScript, decimals = 8).id - val buyFeeAsset = sender.issue(matcherAddress, "Buyer fee asset", script = initScript, decimals = 8).id - - val preconditions = transfers ++ Seq( - amountAsset, - priceAsset, - sellFeeAsset, - buyFeeAsset - ) - - waitForTxs(preconditions) - - val transferToSeller = - sender.transfer(matcherAddress, sellerAddress.toAddress.toString, 1000000000, fee = minFee + smartFee, assetId = Some(sellFeeAsset)).id - val transferToBuyer = - sender.transfer(matcherAddress, buyerAddress.toAddress.toString, 1000000000, fee = minFee + smartFee, assetId = Some(buyFeeAsset)).id - - waitForTxs(Seq(transferToSeller, transferToBuyer)) - - Precondition(amountAsset, priceAsset, buyFeeAsset, sellFeeAsset) - } - - private def logPriorityTx(tx: String): Unit = { - log.debug(s"Priority transaction: $tx") - sender.printDebugMessage(DebugMessage(s"Priority transaction: $tx")) - } - - override protected def waitForHeightArise(): Unit = nodes.waitForHeightArise() - - override protected def nodeConfigs: Seq[Config] = Configs -} - -object FailedTransactionSuite { - case class Precondition(amountAsset: String, priceAsset: String, buyFeeAsset: String, sellFeeAsset: String) -} diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/IssueTransactionSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/IssueTransactionSuite.scala index 0f14dbf434..5a4641d33c 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/IssueTransactionSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/IssueTransactionSuite.scala @@ -82,7 +82,7 @@ class IssueTransactionSuite extends BaseTransactionSuite with TableDrivenPropert "version" -> version, "timestamp" -> System.currentTimeMillis(), "proofs" -> Json.arr(), - "script" -> scriptOpt.fold[JsValue](JsNull)(JsString) + "script" -> scriptOpt.fold[JsValue](JsNull)(JsString.apply) ) ) diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/SetAssetScriptTransactionSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/SetAssetScriptTransactionSuite.scala index 25c3e4b0a4..1e83b9caba 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/SetAssetScriptTransactionSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/SetAssetScriptTransactionSuite.scala @@ -6,19 +6,20 @@ import com.wavesplatform.api.http.ApiError.{Mistiming, StateCheckFailed, WrongJs import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.{Base58, EitherExt2} import com.wavesplatform.crypto -import com.wavesplatform.it.api.SyncHttpApi._ -import com.wavesplatform.it.sync.{script, someAssetAmount, _} +import com.wavesplatform.it.api.SyncHttpApi.* +import com.wavesplatform.it.sync.* import com.wavesplatform.it.transactions.BaseTransactionSuite +import com.wavesplatform.lang.v1.compiler.TestCompiler import com.wavesplatform.lang.v1.estimator.ScriptEstimatorV1 -import com.wavesplatform.test._ +import com.wavesplatform.test.* import com.wavesplatform.transaction.Asset.IssuedAsset -import com.wavesplatform.transaction.{Proofs, TxPositiveAmount} import com.wavesplatform.transaction.assets.SetAssetScriptTransaction import com.wavesplatform.transaction.smart.SetScriptTransaction import com.wavesplatform.transaction.smart.script.ScriptCompiler -import play.api.libs.json._ +import com.wavesplatform.transaction.{Proofs, TxPositiveAmount} +import play.api.libs.json.* -import scala.concurrent.duration._ +import scala.concurrent.duration.* import scala.util.Random class SetAssetScriptTransactionSuite extends BaseTransactionSuite { @@ -28,15 +29,13 @@ class SetAssetScriptTransactionSuite extends BaseTransactionSuite { var assetWScript = "" var assetWScript2 = "" private def accountB = secondKeyPair - private val unchangeableScript = ScriptCompiler( + private val unchangeableScript = TestCompiler.DefaultVersion.compileAsset( s"""match tx { | case _: SetAssetScriptTransaction => false | case _ => true |} - |""".stripMargin, - isAssetScript = true, - estimator - ).explicitGet()._1 + |""".stripMargin + ) protected override def beforeAll(): Unit = { super.beforeAll() @@ -117,7 +116,7 @@ class SetAssetScriptTransactionSuite extends BaseTransactionSuite { "sender" -> issuer.toAddress, "senderPublicKey" -> issuer.publicKey, "fee" -> fee, - "script" -> script.fold[JsValue](JsNull)(JsString), + "script" -> script.fold[JsValue](JsNull)(JsString.apply), "timestamp" -> System.currentTimeMillis() ) ) @@ -137,15 +136,16 @@ class SetAssetScriptTransactionSuite extends BaseTransactionSuite { issueFee, 2.toByte, script = Some( - ScriptCompiler( - s"""match tx { - |case s : SetAssetScriptTransaction => s.sender == addressFromPublicKey(base58'${secondKeyPair.publicKey}') - |case _ => false - |} - |""".stripMargin, - isAssetScript = true, - estimator - ).explicitGet()._1.bytes().base64 + TestCompiler.DefaultVersion + .compileAsset( + s"""match tx { + |case s : SetAssetScriptTransaction => s.sender == addressFromPublicKey(base58'${secondKeyPair.publicKey}') + |case _ => false + |} + |""".stripMargin + ) + .bytes() + .base64 ) ) .id @@ -178,16 +178,17 @@ class SetAssetScriptTransactionSuite extends BaseTransactionSuite { } test("sender's waves balance is decreased by fee") { - val script2 = ScriptCompiler( - s""" - |match tx { - | case _: SetAssetScriptTransaction => true - | case _ => false - |} - """.stripMargin, - isAssetScript = true, - estimator - ).explicitGet()._1.bytes().base64 + val script2 = TestCompiler.DefaultVersion + .compileAsset( + s""" + |match tx { + | case _: SetAssetScriptTransaction => true + | case _ => false + |} + """.stripMargin + ) + .bytes() + .base64 val details = miner.assetsDetails(assetWScript, true).scriptDetails.getOrElse(fail("Expecting to get asset details")) assert(details.scriptComplexity == 1) @@ -358,16 +359,18 @@ class SetAssetScriptTransactionSuite extends BaseTransactionSuite { version = v, accountA, Some( - ScriptCompiler( - s"""|let pkB = base58'${accountB.publicKey}' - |match tx { - | case s: SetAssetScriptTransaction => sigVerify(s.bodyBytes,s.proofs[0],pkB) - | case _ => true - |} + ScriptCompiler + .compile( + s"""|let pkB = base58'${accountB.publicKey}' + |match tx { + | case s: SetAssetScriptTransaction => sigVerify(s.bodyBytes,s.proofs[0],pkB) + | case _ => true + |} """.stripMargin, - isAssetScript = false, - estimator - ).explicitGet()._1 + estimator + ) + .explicitGet() + ._1 ), setScriptFee + smartFee, System.currentTimeMillis() diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/TransferTransactionSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/TransferTransactionSuite.scala index 2e712a613a..b5a0c88cf0 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/TransferTransactionSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/TransferTransactionSuite.scala @@ -11,7 +11,7 @@ import com.wavesplatform.test.* import com.wavesplatform.transaction.Asset.Waves import com.wavesplatform.transaction.transfer.* import com.wavesplatform.transaction.transfer.TransferTransaction.MaxAttachmentSize -import com.wavesplatform.transaction.{Proofs, TxPositiveAmount, TxVersion} +import com.wavesplatform.transaction.{Proofs, TxPositiveAmount, TxVersion, TransactionSignOps} import org.scalatest.CancelAfterFailure import play.api.libs.json.Json diff --git a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/UpdateAssetInfoTransactionSuite.scala b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/UpdateAssetInfoTransactionSuite.scala index 812b03fdc7..a591ae5d1c 100644 --- a/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/UpdateAssetInfoTransactionSuite.scala +++ b/node-it/src/test/scala/com/wavesplatform/it/sync/transactions/UpdateAssetInfoTransactionSuite.scala @@ -1,6 +1,5 @@ package com.wavesplatform.it.sync.transactions -import scala.concurrent.duration.* import com.typesafe.config.{Config, ConfigFactory} import com.wavesplatform.account.AddressScheme import com.wavesplatform.api.http.ApiError.{InvalidName, StateCheckFailed, TooBigArrayAllocation} @@ -8,20 +7,22 @@ import com.wavesplatform.api.http.requests.UpdateAssetInfoRequest import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.EitherExt2 import com.wavesplatform.it.NodeConfigs.{Miners, NotMiner} -import com.wavesplatform.it.api.{Transaction, TransactionInfo} import com.wavesplatform.it.api.SyncHttpApi.* +import com.wavesplatform.it.api.{Transaction, TransactionInfo} import com.wavesplatform.it.sync.* import com.wavesplatform.it.transactions.BaseTransactionSuite -import com.wavesplatform.lang.v1.compiler.Terms -import com.wavesplatform.lang.v1.estimator.v2.ScriptEstimatorV2 +import com.wavesplatform.lang.directives.values.V4 +import com.wavesplatform.lang.v1.compiler.{Terms, TestCompiler} import com.wavesplatform.lang.v1.estimator.v3.ScriptEstimatorV3 import com.wavesplatform.transaction.assets.IssueTransaction.{MaxAssetDescriptionLength, MaxAssetNameLength, MinAssetNameLength} -import com.wavesplatform.transaction.{TransactionType, TxVersion} import com.wavesplatform.transaction.smart.script.ScriptCompiler +import com.wavesplatform.transaction.{TransactionType, TxVersion} import org.scalatest.CancelAfterFailure import org.scalatest.prop.TableDrivenPropertyChecks import play.api.libs.json.{JsObject, Json} +import scala.concurrent.duration.* + class UpdateAssetInfoTransactionSuite extends BaseTransactionSuite with CancelAfterFailure with TableDrivenPropertyChecks { import UpdateAssetInfoTransactionSuite.* val updateInterval = 2 @@ -330,7 +331,7 @@ class UpdateAssetInfoTransactionSuite extends BaseTransactionSuite with CancelAf test("asset script can read asset info") { val scriptTextT = s"""true""".stripMargin - val scriptT = ScriptCompiler(scriptTextT, isAssetScript = true, ScriptEstimatorV2).explicitGet()._1.bytes().base64 + val scriptT = TestCompiler.DefaultVersion.compileAsset(scriptTextT).bytes().base64 val smartAssetId1 = sender.broadcastIssue(issuer, "smartAsset", "description", someAssetAmount, 8, reissuable = true, script = Some(scriptT), waitForTx = true).id @@ -361,7 +362,7 @@ class UpdateAssetInfoTransactionSuite extends BaseTransactionSuite with CancelAf | this.minSponsoredFee == unit |case _ => false |}""".stripMargin - val script1 = ScriptCompiler(scriptText1, isAssetScript = true, ScriptEstimatorV2).explicitGet()._1.bytes().base64 + val script1 = TestCompiler(V4).compileAsset(scriptText1).bytes().base64 sender.setAssetScript(smartAssetId1, issuer, setAssetScriptFee, Some(script1), waitForTx = true) sender.burn(issuer, smartAssetId1, 1, minFee + 2 * smartFee, waitForTx = true) @@ -369,7 +370,7 @@ class UpdateAssetInfoTransactionSuite extends BaseTransactionSuite with CancelAf test("check increased fee for smart sender/asset") { val scriptText = s"""true""".stripMargin - val script = ScriptCompiler(scriptText, isAssetScript = true, ScriptEstimatorV2).explicitGet()._1.bytes().base64 + val script = TestCompiler.DefaultVersion.compileAsset(scriptText).bytes().base64 val smartAssetId = sender.broadcastIssue(issuer, "smartAsset", "description", someAssetAmount, 8, reissuable = true, script = Some(script), waitForTx = true).id sender.waitForHeight(sender.height + updateInterval + 1, 3.minutes) diff --git a/node-it/src/test/scala/com/wavesplatform/test/BlockchainGenerator.scala b/node-it/src/test/scala/com/wavesplatform/test/BlockchainGenerator.scala index a8932b09bc..4697c59a41 100644 --- a/node-it/src/test/scala/com/wavesplatform/test/BlockchainGenerator.scala +++ b/node-it/src/test/scala/com/wavesplatform/test/BlockchainGenerator.scala @@ -21,7 +21,7 @@ import com.wavesplatform.transaction.assets.exchange.ExchangeTransaction import com.wavesplatform.transaction.lease.{LeaseCancelTransaction, LeaseTransaction} import com.wavesplatform.transaction.smart.{InvokeScriptTransaction, SetScriptTransaction} import com.wavesplatform.transaction.transfer.{MassTransferTransaction, TransferTransaction} -import com.wavesplatform.transaction.{CreateAliasTransaction, DataTransaction, EthTxGenerator, EthereumTransaction, PaymentTransaction, Transaction, TxHelpers} +import com.wavesplatform.transaction.* import com.wavesplatform.utils.{Schedulers, ScorexLogging, Time} import com.wavesplatform.utx.UtxPoolImpl import com.wavesplatform.wallet.Wallet diff --git a/node-it/src/test/scala/com/wavesplatform/test/Signed.scala b/node-it/src/test/scala/com/wavesplatform/test/Signed.scala index 80facac4e1..59cb67c1bb 100644 --- a/node-it/src/test/scala/com/wavesplatform/test/Signed.scala +++ b/node-it/src/test/scala/com/wavesplatform/test/Signed.scala @@ -4,7 +4,7 @@ import com.wavesplatform.account.{AddressOrAlias, KeyPair} import com.wavesplatform.common.utils.* import com.wavesplatform.lang.v1.compiler.Terms import com.wavesplatform.transaction.smart.InvokeScriptTransaction -import com.wavesplatform.transaction.{Asset, Proofs, TxTimestamp} +import com.wavesplatform.transaction.{Asset, Proofs, TxTimestamp, TransactionSignOps} object Signed { def invokeScript( diff --git a/node/build.sbt b/node/build.sbt index 7c9e0642b4..949d93a5d3 100644 --- a/node/build.sbt +++ b/node/build.sbt @@ -1,5 +1,3 @@ -name := "waves" - enablePlugins( RunApplicationSettings, JavaServerAppPackaging, @@ -20,6 +18,26 @@ javaAgents ++= { } } +publishTo := sonatypePublishToBundle.value +publish / skip := false +homepage := Some(url("https://waves.tech/")) +developers := List( + Developer("ismagin", "Ilya Smagin", "ilya.smagin@gmail.com", url("https://github.com/ismagin")), + Developer("asayadyan", "Artyom Sayadyan", "xrtm000@gmail.com", url("https://github.com/xrtm000")), + Developer("mpotanin", "Mike Potanin", "mpotanin@wavesplatform.com", url("https://github.com/potan")), + Developer("irakitnykh", "Ivan Rakitnykh", "mrkr.reg@gmail.com", url("https://github.com/mrkraft")), + Developer("akiselev", "Alexey Kiselev", "alexey.kiselev@gmail.com>", url("https://github.com/alexeykiselev")), + Developer("phearnot", "Sergey Nazarov", "snazarov@web3tech.ru", url("https://github.com/phearnot")), + Developer("tolsi", "Sergey Tolmachev", "tolsi.ru@gmail.com", url("https://github.com/tolsi")), + Developer("vsuharnikov", "Vyatcheslav Suharnikov", "arz.freezy@gmail.com", url("https://github.com/vsuharnikov")), + Developer("ivan-mashonskiy", "Ivan Mashonskii", "ivan.mashonsky@gmail.com", url("https://github.com/ivan-mashonskiy")) +) +versionScheme := Some("pvp") + +Compile / packageDoc / publishArtifact := true +Test / packageDoc / publishArtifact := false +Compile / packageDoc / mappings := Seq() + inConfig(Compile)( Seq( PB.targets += scalapb.gen(flatPackage = true) -> sourceManaged.value, @@ -27,35 +45,11 @@ inConfig(Compile)( PB.generate / includeFilter := { (f: File) => (** / "waves" / "*.proto").matches(f.toPath) }, - PB.deleteTargetDirectory := false, - packageDoc / publishArtifact := false, - packageSrc / publishArtifact := false + PB.deleteTargetDirectory := false ) ) -inTask(assembly)( - Seq( - test := {}, - assemblyJarName := s"waves-all-${version.value}.jar", - assemblyMergeStrategy := { - case p - if p.endsWith(".proto") || - p.endsWith("module-info.class") || - p.endsWith("io.netty.versions.properties") || - p.endsWith(".kotlin_module") => - MergeStrategy.discard - - case "scala-collection-compat.properties" => - MergeStrategy.discard - case p - if Set("scala/util/control/compat", "scala/collection/compat") - .exists(p.replace('\\', '/').contains) => - MergeStrategy.last - - case other => (assembly / assemblyMergeStrategy).value(other) - } - ) -) +inTask(assembly)(Seq(name := "waves") ++ CommonSettings.assemblySettings) // Adds "$lib_dir/*" to app_classpath in the executable file, this is needed for extensions scriptClasspath += "*" @@ -95,6 +89,8 @@ linuxScriptReplacements += ("network" -> network.value.toString) inConfig(Universal)( Seq( + maintainer := "com.wavesplatform", + packageName := s"waves-${version.value}", mappings += (baseDirectory.value / s"waves-sample.conf" -> "doc/waves.conf.sample"), javaOptions ++= Seq( // -J prefix is required by the bash script @@ -115,7 +111,7 @@ inConfig(Linux)( Seq( packageSummary := "Waves node", packageDescription := "Waves node", - name := s"${name.value}${network.value.packageSuffix}", + name := s"waves${network.value.packageSuffix}", normalizedName := name.value, packageName := normalizedName.value ) diff --git a/node/src/main/resources/application.conf b/node/src/main/resources/application.conf index 8501dbf4b1..1d9383d0be 100644 --- a/node/src/main/resources/application.conf +++ b/node/src/main/resources/application.conf @@ -47,8 +47,9 @@ waves { api-cache-size=16M write-buffer-size = 128M enable-statistics = false - # When enabled, after writing every SST file of the default column family, reopen it and read all the keys. - paranoid-checks = off + allow-mmap-reads = off + parallelism = 2 + max-open-files = 100 } } @@ -60,6 +61,11 @@ waves { # Peers and blacklist storage file file = ${waves.directory}"/peers.dat" + # If defined, the node will bind to this address and accept the incoming connections. When commented out, the node + # will not accept any incoming connections and will only establish outgoing ones. If you're using UPnP for port + # mapping, make sure to specify the correct address here. + bind-address = "0.0.0.0" + # String with IP address and port to send as external address during handshake. Could be set automatically if UPnP # is enabled. # @@ -67,8 +73,6 @@ waves { # listen to incoming connections on `bind-address:port` and broadcast its `declared-address` to its peers. UPnP # is supposed to be disabled in this scenario. # - # If declared address is not set and UPnP is not enabled, the node will not listen to incoming connections at all. - # # If declared address is not set and UPnP is enabled, the node will attempt to connect to an IGD, retrieve its # external IP address and configure the gateway to allow traffic through. If the node succeeds, the IGD's external # IP address becomes the node's declared address. @@ -78,9 +82,6 @@ waves { # to `bind-address:port`. Please note, however, that this setup is not recommended. # declared-address = "1.2.3.4:6863" - # Network address - bind-address = "0.0.0.0" - # Port number port = 6863 @@ -191,7 +192,7 @@ waves { # Required number of connections (both incoming and outgoing) to attempt block generation. Setting this value to 0 # enables "off-line generation". - quorum = 1 + quorum = 3 # Enable block generation only in the last block is not older the given period of time interval-after-last-block-then-generation-is-allowed = 1d @@ -206,7 +207,7 @@ waves { max-transactions-in-micro-block = 255 # Miner references the best microblock which is at least this age - min-micro-block-age = 2s + min-micro-block-age = 500ms # Minimal block generation offset minimal-block-generation-offset = 0 diff --git a/node/src/main/resources/network-defaults.conf b/node/src/main/resources/network-defaults.conf index 689557ac9b..2412bdf84a 100644 --- a/node/src/main/resources/network-defaults.conf +++ b/node/src/main/resources/network-defaults.conf @@ -4,12 +4,10 @@ waves.defaults { network { port = 6863 + min-connections = 5 + known-peers = [ - "159.69.126.149:6868" - "94.130.105.239:6868" - "159.69.126.153:6868" - "94.130.172.201:6868" - "35.157.247.122:6868" + "peers-testnet.wavesnodes.com:6868" ] } } @@ -139,11 +137,10 @@ waves.defaults { # Node name to send during handshake. Comment this string out to set random node name. # node-name = "My MAINNET node" + min-connections = 5 + known-peers = [ - "168.119.116.189:6868" - "135.181.87.72:6868" - "162.55.39.115:6868" - "168.119.155.201:6868" + "peers.wavesnodes.com:6868" ] } @@ -159,12 +156,10 @@ waves.defaults { network { port = 6862 + min-connections = 3 + known-peers = [ - "88.99.185.128:6868" - "95.216.205.3:6868" - "49.12.15.166:6868" - "88.198.179.16:6868" - "52.58.254.101:6868" + "peers-stagenet.wavesnodes.com:6868" ] } } diff --git a/node/src/main/scala/com/wavesplatform/Application.scala b/node/src/main/scala/com/wavesplatform/Application.scala index 01d727aaa9..ab767812d5 100644 --- a/node/src/main/scala/com/wavesplatform/Application.scala +++ b/node/src/main/scala/com/wavesplatform/Application.scala @@ -47,7 +47,7 @@ import kamon.Kamon import kamon.instrumentation.executor.ExecutorInstrumentation import monix.eval.{Coeval, Task} import monix.execution.schedulers.{ExecutorScheduler, SchedulerService} -import monix.execution.{Scheduler, UncaughtExceptionReporter} +import monix.execution.{ExecutionModel, Scheduler, UncaughtExceptionReporter} import monix.reactive.Observable import monix.reactive.subjects.ConcurrentSubject import org.influxdb.dto.Point @@ -103,11 +103,13 @@ class Application(val actorSystem: ActorSystem, val settings: WavesSettings, con private[this] val (blockchainUpdater, rocksDB) = StorageFactory(settings, rdb, time, BlockchainUpdateTriggers.combined(triggers), bc => miner.scheduleMining(bc)) + private[this] val messageObserver = new MessageObserverL1 + @volatile private[this] var maybeUtx: Option[UtxPool] = None @volatile - private[this] var maybeNetworkServer: Option[NS] = None + private[this] var maybeNetworkServer: Option[NetworkServer] = None @volatile private[this] var serverBinding: ServerBinding = _ @@ -201,7 +203,7 @@ class Application(val actorSystem: ActorSystem, val settings: WavesSettings, con rdb ) - val historyReplier = new HistoryReplier(blockchainUpdater.score, history, settings.synchronizationSettings)(historyRepliesScheduler) + val historyReplier = new HistoryReplierL1(blockchainUpdater.score, history, settings.synchronizationSettings)(historyRepliesScheduler) val transactionPublisher = TransactionPublisher.timeBounded( @@ -237,7 +239,6 @@ class Application(val actorSystem: ActorSystem, val settings: WavesSettings, con override def utx: UtxPool = utxStorage override def broadcastTransaction(tx: Transaction): TracedResult[ValidationError, Boolean] = Await.result(transactionPublisher.validateAndBroadcast(tx, None), Duration.Inf) // TODO: Replace with async if possible - override def actorSystem: ActorSystem = app.actorSystem override def utxEvents: Observable[UtxEvent] = app.utxEvents override val transactionsApi: CommonTransactionsApi = CommonTransactionsApi( @@ -272,17 +273,18 @@ class Application(val actorSystem: ActorSystem, val settings: WavesSettings, con // Network server should be started only after all extensions initialized val networkServer = - NetworkServer( + NetworkServerL1( settings, lastBlockInfo, historyReplier, peerDatabase, + messageObserver, allChannels, establishedConnections ) maybeNetworkServer = Some(networkServer) val (signatures, blocks, blockchainScores, microblockInvs, microblockResponses, transactions, blockSnapshots, microblockSnapshots) = - networkServer.messages + messageObserver.messages val timeoutSubject: ConcurrentSubject[Channel, Channel] = ConcurrentSubject.publish[Channel] @@ -371,7 +373,8 @@ class Application(val actorSystem: ActorSystem, val settings: WavesSettings, con val heavyRequestScheduler = Scheduler( if (settings.config.getBoolean("kamon.enable")) ExecutorInstrumentation.instrument(heavyRequestExecutor, "heavy-request-executor") - else heavyRequestExecutor + else heavyRequestExecutor, + ExecutionModel.BatchedExecution(100) ) val serverRequestTimeout = FiniteDuration(settings.config.getDuration("akka.http.server.request-timeout").getSeconds, TimeUnit.SECONDS) @@ -512,6 +515,7 @@ class Application(val actorSystem: ActorSystem, val settings: WavesSettings, con log.info("Stopping network services") network.shutdown() } + messageObserver.shutdown() shutdownAndWait(appenderScheduler, "Appender", 5.minutes.some) @@ -563,7 +567,7 @@ object Application extends ScorexLogging { .map(_.toUpperCase) .getOrElse("TESTNET") - log.warn(s"Config file not defined, default $currentBlockchainType config will be used") + log.info(s"Config file not specified, default $currentBlockchainType config will be used") case Failure(exception) => log.error(s"Couldn't read ${external.get.toPath.toAbsolutePath}", exception) forceStopApplication(Misconfiguration) @@ -600,12 +604,12 @@ object Application extends ScorexLogging { } private[wavesplatform] def loadBlockAt(rdb: RDB, blockchainUpdater: BlockchainUpdaterImpl)( - height: Int + height: Int ): Option[(BlockMeta, Seq[(TxMeta, Transaction)])] = loadBlockInfoAt(rdb, blockchainUpdater)(height) private[wavesplatform] def loadBlockInfoAt(rdb: RDB, blockchainUpdater: BlockchainUpdaterImpl)( - height: Int + height: Int ): Option[(BlockMeta, Seq[(TxMeta, Transaction)])] = loadBlockMetaAt(rdb.db, blockchainUpdater)(height).map { meta => meta -> blockchainUpdater @@ -619,7 +623,10 @@ object Application extends ScorexLogging { .orElse(db.get(Keys.blockMetaAt(Height(height))).flatMap(BlockMeta.fromPb)) .map { blockMeta => val rewardShares = BlockRewardCalculator.getSortedBlockRewardShares(height, blockMeta.header.generator.toAddress, blockchainUpdater) - blockMeta.copy(rewardShares = rewardShares) + blockMeta.copy( + rewardShares = rewardShares, + reward = blockMeta.reward.map(_ * blockchainUpdater.blockRewardBoost(height)) + ) } def main(args: Array[String]): Unit = { @@ -636,7 +643,8 @@ object Application extends ScorexLogging { case "import" => Importer.main(args.tail) case "explore" => Explorer.main(args.tail) case "util" => UtilApp.main(args.tail) - case "help" | "--help" | "-h" => println("Usage: waves | export | import | explore | util") + case "gengen" => GenesisBlockGenerator.main(args.tail) + case "help" | "--help" | "-h" => println("Usage: waves | export | import | explore | util | gengen") case _ => startNode(args.headOption) } } diff --git a/node/src/main/scala/com/wavesplatform/Explorer.scala b/node/src/main/scala/com/wavesplatform/Explorer.scala index b51f99e5e9..6d34a20960 100644 --- a/node/src/main/scala/com/wavesplatform/Explorer.scala +++ b/node/src/main/scala/com/wavesplatform/Explorer.scala @@ -231,7 +231,7 @@ object Explorer extends ScorexLogging { val result = new util.HashMap[Short, Stats] Seq(rdb.db.getDefaultColumnFamily, rdb.txHandle.handle, rdb.txSnapshotHandle.handle, rdb.txMetaHandle.handle).foreach { cf => Using.Manager { use => - val ro = use(new ReadOptions().setTotalOrderSeek(true)) + val ro = use(new ReadOptions().setTotalOrderSeek(true).setVerifyChecksums(false)) val iterator = use(rdb.db.newIterator(cf, ro)) iterator.seekToFirst() @@ -373,7 +373,7 @@ object Explorer extends ScorexLogging { log.info("Counting transaction IDs") var counter = 0 Using.Manager { use => - val ro = use(new ReadOptions().setTotalOrderSeek(true)) + val ro = use(new ReadOptions().setTotalOrderSeek(true).setVerifyChecksums(false)) val iter = use(rdb.db.newIterator(rdb.txMetaHandle.handle, ro)) iter.seekToFirst() // iter.seek(KeyTags.TransactionMetaById.prefixBytes) // Doesn't work, because of CappedPrefixExtractor(10) diff --git a/node/src/main/scala/com/wavesplatform/Importer.scala b/node/src/main/scala/com/wavesplatform/Importer.scala index 2b959f8030..529287f931 100644 --- a/node/src/main/scala/com/wavesplatform/Importer.scala +++ b/node/src/main/scala/com/wavesplatform/Importer.scala @@ -1,6 +1,5 @@ package com.wavesplatform -import akka.actor.ActorSystem import cats.implicits.catsSyntaxOption import cats.syntax.apply.* import com.google.common.io.ByteStreams @@ -123,7 +122,6 @@ object Importer extends ScorexLogging { extensionTime: Time, utxPool: UtxPool, rdb: RDB, - extensionActorSystem: ActorSystem ): Seq[Extension] = if (wavesSettings.extensions.isEmpty) Seq.empty else { @@ -139,7 +137,6 @@ object Importer extends ScorexLogging { override def broadcastTransaction(tx: Transaction): TracedResult[ValidationError, Boolean] = TracedResult.wrapE(Left(GenericError("Not implemented during import"))) - override def actorSystem: ActorSystem = extensionActorSystem override def utxEvents: Observable[UtxEvent] = Observable.empty override def transactionsApi: CommonTransactionsApi = CommonTransactionsApi( @@ -348,7 +345,6 @@ object Importer extends ScorexLogging { val scheduler = Schedulers.singleThread("appender") val time = new NTP(settings.ntpServer) - val actorSystem = ActorSystem("wavesplatform-import") val rdb = RDB.open(settings.dbSettings) val (blockchainUpdater, rdbWriter) = StorageFactory(settings, rdb, time, BlockchainUpdateTriggers.combined(triggers)) @@ -357,7 +353,7 @@ object Importer extends ScorexLogging { val extAppender: (Block, Option[BlockSnapshotResponse]) => Task[Either[ValidationError, BlockApplyResult]] = BlockAppender(blockchainUpdater, time, utxPool, pos, scheduler, importOptions.verify, txSignParCheck = false) - val extensions = initExtensions(settings, blockchainUpdater, scheduler, time, utxPool, rdb, actorSystem) + val extensions = initExtensions(settings, blockchainUpdater, scheduler, time, utxPool, rdb) checkGenesis(settings, blockchainUpdater, Miner.Disabled) val blocksFileOffset = @@ -392,7 +388,6 @@ object Importer extends ScorexLogging { sys.addShutdownHook { quit = true - Await.result(actorSystem.terminate(), 10.second) lock.synchronized { if (blockchainUpdater.isFeatureActivated(BlockchainFeatures.NG) && blockchainUpdater.liquidBlockMeta.nonEmpty) { // Force store liquid block in rocksdb diff --git a/node/src/main/scala/com/wavesplatform/api/common/AddressTransactions.scala b/node/src/main/scala/com/wavesplatform/api/common/AddressTransactions.scala index bfbc56bd26..4fb8afb8d8 100644 --- a/node/src/main/scala/com/wavesplatform/api/common/AddressTransactions.scala +++ b/node/src/main/scala/com/wavesplatform/api/common/AddressTransactions.scala @@ -135,7 +135,7 @@ object AddressTransactions { types: Set[Transaction.Type] ) extends AbstractIterator[Seq[(TxMeta, Transaction, Option[TxNum])]] { private val seqNr = db.get(Keys.addressTransactionSeqNr(addressId, apiHandle)) - db.withSafePrefixIterator(_.seekForPrev(Keys.addressTransactionHN(addressId, seqNr, apiHandle).keyBytes))() + db.withSafePrefixIterator(_.seekForPrev(Keys.addressTransactionHN(addressId, seqNr, apiHandle).keyBytes))(()) final override def computeNext(): Seq[(TxMeta, Transaction, Option[TxNum])] = db.withSafePrefixIterator { dbIterator => val keysBuffer = new ArrayBuffer[Key[Option[(TxMeta, Transaction)]]]() diff --git a/node/src/main/scala/com/wavesplatform/api/common/CommonAccountsApi.scala b/node/src/main/scala/com/wavesplatform/api/common/CommonAccountsApi.scala index 4faaf1b6c1..299d738c27 100644 --- a/node/src/main/scala/com/wavesplatform/api/common/CommonAccountsApi.scala +++ b/node/src/main/scala/com/wavesplatform/api/common/CommonAccountsApi.scala @@ -141,7 +141,7 @@ object CommonAccountsApi { private val length: Int = entriesFromDiff.length - db.withSafePrefixIterator(_.seek(prefix))() + db.withSafePrefixIterator(_.seek(prefix))(()) private var nextIndex = 0 private var nextDbEntry: Option[DataEntry[?]] = None diff --git a/node/src/main/scala/com/wavesplatform/api/common/lease/LeaseByAddressIterator.scala b/node/src/main/scala/com/wavesplatform/api/common/lease/LeaseByAddressIterator.scala index f9821a7d21..97211b5b57 100644 --- a/node/src/main/scala/com/wavesplatform/api/common/lease/LeaseByAddressIterator.scala +++ b/node/src/main/scala/com/wavesplatform/api/common/lease/LeaseByAddressIterator.scala @@ -9,7 +9,7 @@ import com.wavesplatform.state.LeaseDetails private class LeaseByAddressIterator(resource: DBResource, apiHandle: RDB.ApiHandle, addressId: AddressId) extends AbstractIterator[Seq[(ByteStr, LeaseDetails)]] { private val seqNr = resource.get(Keys.addressLeaseSeqNr(addressId, apiHandle)) - resource.withSafePrefixIterator(_.seekForPrev(Keys.addressLeaseSeq(addressId, seqNr, apiHandle).keyBytes))() + resource.withSafePrefixIterator(_.seekForPrev(Keys.addressLeaseSeq(addressId, seqNr, apiHandle).keyBytes))(()) final override def computeNext(): Seq[(ByteStr, LeaseDetails)] = resource.withSafePrefixIterator { iterator => diff --git a/node/src/main/scala/com/wavesplatform/api/http/ApiError.scala b/node/src/main/scala/com/wavesplatform/api/http/ApiError.scala index 33301d6828..3e53942255 100644 --- a/node/src/main/scala/com/wavesplatform/api/http/ApiError.scala +++ b/node/src/main/scala/com/wavesplatform/api/http/ApiError.scala @@ -26,8 +26,8 @@ trait ApiError { //noinspection TypeAnnotation object ApiError { - implicit def fromValidationError(e: ValidationError): ApiError = { - e match { + implicit def fromValidationError(ve: ValidationError): ApiError = { + ve match { case TxValidationError.InvalidAddress(_) => InvalidAddress case TxValidationError.NegativeAmount(x, of) => NegativeAmount(s"$x of $of") case TxValidationError.NonPositiveAmount(x, of) => NonPositiveAmount(s"$x of $of") @@ -52,8 +52,8 @@ object ApiError { case TxValidationError.WrongChain(ex, pr) => InvalidChainId(ex, pr) case err: TxValidationError.TooManyProofs => InvalidProofs(err.toString()) case err: TxValidationError.ToBigProof => InvalidProofs(err.toString()) - case TransactionValidationError(error, tx) => - error match { + case TransactionValidationError(cause, tx) => + cause match { case e: TxValidationError.TransactionNotAllowedByScript => if (e.isAssetScript) TransactionNotAllowedByAssetScript(tx) else TransactionNotAllowedByAccountScript(tx) diff --git a/node/src/main/scala/com/wavesplatform/api/http/DebugApiRoute.scala b/node/src/main/scala/com/wavesplatform/api/http/DebugApiRoute.scala index 590a6fa708..ffc2848a9f 100644 --- a/node/src/main/scala/com/wavesplatform/api/http/DebugApiRoute.scala +++ b/node/src/main/scala/com/wavesplatform/api/http/DebugApiRoute.scala @@ -49,7 +49,7 @@ case class DebugApiRoute( rollbackTask: (ByteStr, Boolean) => Task[Either[ValidationError, Unit]], utxStorage: UtxPool, miner: Miner & MinerDebugInfo, - historyReplier: HistoryReplier, + historyReplier: HistoryReplierL1, extLoaderStateReporter: Coeval[RxExtensionLoader.State], mbsCacheSizesReporter: Coeval[MicroBlockSynchronizer.CacheSizes], scoreReporter: Coeval[RxScoreObserver.Stats], @@ -303,7 +303,7 @@ object DebugApiRoute { implicit val addressWrites: Writes[Address] = Writes((a: Address) => JsString(a.toString)) - implicit val hrCacheSizesFormat: Format[HistoryReplier.CacheSizes] = Json.format + implicit val hrCacheSizesFormat: Format[HistoryReplierL1.CacheSizes] = Json.format implicit val mbsCacheSizesFormat: Format[MicroBlockSynchronizer.CacheSizes] = Json.format implicit val BigIntWrite: Writes[BigInt] = (bigInt: BigInt) => JsNumber(BigDecimal(bigInt)) implicit val scoreReporterStatsWrite: Writes[RxScoreObserver.Stats] = Json.writes[RxScoreObserver.Stats] diff --git a/node/src/main/scala/com/wavesplatform/api/http/RewardApiRoute.scala b/node/src/main/scala/com/wavesplatform/api/http/RewardApiRoute.scala index 6be41e9ba2..bb50469c60 100644 --- a/node/src/main/scala/com/wavesplatform/api/http/RewardApiRoute.scala +++ b/node/src/main/scala/com/wavesplatform/api/http/RewardApiRoute.scala @@ -45,7 +45,7 @@ case class RewardApiRoute(blockchain: Blockchain) extends ApiRoute { } yield RewardStatus( height, amount, - reward, + reward * blockchain.blockRewardBoost(height), rewardsSettings.minIncrement, term, nextCheck, diff --git a/node/src/main/scala/com/wavesplatform/api/http/RouteTimeout.scala b/node/src/main/scala/com/wavesplatform/api/http/RouteTimeout.scala index 8649789f35..295d8b66b8 100644 --- a/node/src/main/scala/com/wavesplatform/api/http/RouteTimeout.scala +++ b/node/src/main/scala/com/wavesplatform/api/http/RouteTimeout.scala @@ -2,17 +2,20 @@ package com.wavesplatform.api.http import akka.NotUsed import akka.http.scaladsl.marshalling.{ToResponseMarshallable, ToResponseMarshaller} -import akka.http.scaladsl.server.Directives.{complete, handleExceptions} +import akka.http.scaladsl.server.Directives.{complete, handleExceptions, withExecutionContext} import akka.http.scaladsl.server.{ExceptionHandler, Route} import akka.stream.scaladsl.Source +import com.typesafe.scalalogging.LazyLogging import monix.eval.Task import monix.execution.Scheduler import monix.reactive.Observable +import scala.concurrent.ExecutionContext.fromExecutor import scala.concurrent.TimeoutException import scala.concurrent.duration.FiniteDuration -class RouteTimeout(timeout: FiniteDuration)(implicit sc: Scheduler) extends ApiMarshallers { +class RouteTimeout(timeout: FiniteDuration)(implicit sc: Scheduler) extends ApiMarshallers with LazyLogging { + private val ece = fromExecutor(sc, t => logger.warn(s"Exception in RouteTimeout", t)) private val handler = ExceptionHandler { case _: TimeoutException => complete(ApiError.ServerRequestTimeout) } @@ -27,10 +30,15 @@ class RouteTimeout(timeout: FiniteDuration)(implicit sc: Scheduler) extends ApiM .map(Source(_).map(f))(sc) } - def executeFromObservable[T](observable: Observable[T])(implicit m: ToResponseMarshaller[Source[T, NotUsed]]): Route = { - handleExceptions(handler) & complete(Source.fromPublisher(observable.toReactivePublisher(sc)).initialTimeout(timeout)) - } + def executeFromObservable[T](observable: Observable[T])(implicit m: ToResponseMarshaller[Source[T, NotUsed]]): Route = + withExecutionContext(ece) { + handleExceptions(handler) & + complete(Source.fromPublisher(observable.toReactivePublisher(sc)).initialTimeout(timeout)) + } - def execute[T](task: Task[T])(f: (Task[T], Scheduler) => ToResponseMarshallable): Route = - handleExceptions(handler) & complete(f(task.timeout(timeout), sc)) + def execute[T](task: Task[T])(f: (Task[T], Scheduler) => ToResponseMarshallable): Route = { + withExecutionContext(ece) { + handleExceptions(handler) & complete(f(task.timeout(timeout), sc)) + } + } } diff --git a/node/src/main/scala/com/wavesplatform/api/http/TransactionJsonSerializer.scala b/node/src/main/scala/com/wavesplatform/api/http/TransactionJsonSerializer.scala index 11d8287c09..95ac4f7011 100644 --- a/node/src/main/scala/com/wavesplatform/api/http/TransactionJsonSerializer.scala +++ b/node/src/main/scala/com/wavesplatform/api/http/TransactionJsonSerializer.scala @@ -221,7 +221,7 @@ final case class TransactionJsonSerializer(blockchain: Blockchain) { gen.writeStartObject() gen.writeStringField("dApp", inv.dApp.toString) gen.writeValueField("call")(callSerializer(numbersAsString).serialize(inv.call, _, serializers)) - gen.writeArrayField("payments", inv.payments)(attachedPaymentSerializer(numbersAsString), serializers) + gen.writeArrayField("payment", inv.payments)(attachedPaymentSerializer(numbersAsString), serializers) gen.writeValueField("stateChanges")(invokeScriptResultSerializer(numbersAsString).serialize(inv.stateChanges, _, serializers)) gen.writeEndObject() } @@ -258,7 +258,10 @@ final case class TransactionJsonSerializer(blockchain: Blockchain) { gen.writeNumberField("type", tx.tpe.id, numbersAsString) gen.writeStringField("id", tx.id().toString) gen.writeNumberField("fee", tx.assetFee._2, numbersAsString) - tx.assetFee._1.maybeBase58Repr.foreach(gen.writeStringField("feeAssetId", _)) + tx.feeAssetId match { + case IssuedAsset(id) => gen.writeStringField("feeAssetId", id.toString) + case Asset.Waves => gen.writeNullField("feeAssetId") + } gen.writeNumberField("timestamp", tx.timestamp, numbersAsString) gen.writeNumberField("version", tx.version, numbersAsString) if (PBSince.affects(tx)) gen.writeNumberField("chainId", tx.chainId, numbersAsString) diff --git a/node/src/main/scala/com/wavesplatform/api/http/assets/AssetsApiRoute.scala b/node/src/main/scala/com/wavesplatform/api/http/assets/AssetsApiRoute.scala index f7c447ad04..b76fd77abd 100644 --- a/node/src/main/scala/com/wavesplatform/api/http/assets/AssetsApiRoute.scala +++ b/node/src/main/scala/com/wavesplatform/api/http/assets/AssetsApiRoute.scala @@ -18,13 +18,7 @@ import com.wavesplatform.api.common.{CommonAccountsApi, CommonAssetsApi} import com.wavesplatform.api.http.* import com.wavesplatform.api.http.ApiError.* import com.wavesplatform.api.http.StreamSerializerUtils.* -import com.wavesplatform.api.http.assets.AssetsApiRoute.{ - AssetDetails, - AssetInfo, - DistributionParams, - assetDetailsSerializer, - assetDistributionSerializer -} +import com.wavesplatform.api.http.assets.AssetsApiRoute.* import com.wavesplatform.common.state.ByteStr import com.wavesplatform.lang.ValidationError import com.wavesplatform.settings.RestAPISettings @@ -38,6 +32,7 @@ import com.wavesplatform.transaction.{EthereumTransaction, TxTimestamp, TxVersio import com.wavesplatform.utils.Time import com.wavesplatform.wallet.Wallet import io.netty.util.concurrent.DefaultThreadFactory +import monix.eval.Task import monix.execution.Scheduler import monix.reactive.Observable import play.api.libs.json.* @@ -93,11 +88,10 @@ case class AssetsApiRoute( } } ~ pathPrefix("details") { (anyParam("id", limit = settings.assetDetailsLimit) & parameter("full".as[Boolean] ? false)) { (ids, full) => - val result = Either - .cond(ids.nonEmpty, (), AssetIdNotSpecified) - .map(_ => multipleDetails(ids.toList, full)) - - complete(result) + if (ids.isEmpty) complete(AssetIdNotSpecified) + else { + routeTimeout.executeToFuture(Task(multipleDetails(ids.toList, full))) + } } ~ (get & path(AssetId) & parameter("full".as[Boolean] ? false)) { (assetId, full) => singleDetails(assetId, full) } diff --git a/node/src/main/scala/com/wavesplatform/api/http/package.scala b/node/src/main/scala/com/wavesplatform/api/http/package.scala index 635aaa1953..284da7f764 100644 --- a/node/src/main/scala/com/wavesplatform/api/http/package.scala +++ b/node/src/main/scala/com/wavesplatform/api/http/package.scala @@ -124,8 +124,8 @@ package object http { } } - val TransactionId: PathMatcher1[ByteStr] = idOrHash(InvalidTransactionId) - val BlockId: PathMatcher1[ByteStr] = idOrHash(InvalidBlockId) + val TransactionId: PathMatcher1[ByteStr] = idOrHash(InvalidTransactionId.apply) + val BlockId: PathMatcher1[ByteStr] = idOrHash(InvalidBlockId.apply) val AssetId: PathMatcher1[IssuedAsset] = base58Segment(Some(crypto.DigestLength), _ => InvalidAssetId).map(IssuedAsset(_)) @@ -170,7 +170,7 @@ package object http { case NonFatal(e) => logger.error("Uncaught error", e); complete(ApiError.Unknown) } - /** Handles all [[scala.util.control.NonFatal non-fatal]] exceptions and tries to handle fatal errors. + /** Handles all [[scala.util.control.NonFatal]] exceptions and tries to handle fatal errors. * * This directive can't handle __fatal__ errors from: * diff --git a/node/src/main/scala/com/wavesplatform/block/MicroBlock.scala b/node/src/main/scala/com/wavesplatform/block/MicroBlock.scala index faf6d9ae92..ff480fedf1 100644 --- a/node/src/main/scala/com/wavesplatform/block/MicroBlock.scala +++ b/node/src/main/scala/com/wavesplatform/block/MicroBlock.scala @@ -17,7 +17,7 @@ case class MicroBlock( sender: PublicKey, transactionData: Seq[Transaction], reference: BlockId, - totalResBlockSig: BlockId, + totalResBlockSig: ByteStr, signature: ByteStr, stateHash: Option[ByteStr] ) extends Signed { diff --git a/node/src/main/scala/com/wavesplatform/database/Caches.scala b/node/src/main/scala/com/wavesplatform/database/Caches.scala index 5129ce7c6b..4ee6f9d097 100644 --- a/node/src/main/scala/com/wavesplatform/database/Caches.scala +++ b/node/src/main/scala/com/wavesplatform/database/Caches.scala @@ -7,7 +7,7 @@ import com.wavesplatform.account.{Address, Alias} import com.wavesplatform.block.{Block, SignedBlockHeader} import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.EitherExt2 -import com.wavesplatform.database.protobuf.BlockMeta as PBBlockMeta +import com.wavesplatform.database.protobuf.{BlockMeta as PBBlockMeta, BlockMetaExt} import com.wavesplatform.protobuf.ByteStringExt import com.wavesplatform.protobuf.block.PBBlocks import com.wavesplatform.settings.DBSettings @@ -245,7 +245,8 @@ abstract class Caches extends Blockchain with Storage { reward.getOrElse(0), if (block.header.version >= Block.ProtoBlockVersion) ByteString.copyFrom(hitSource.arr) else ByteString.EMPTY, ByteString.copyFrom(newScore.toByteArray), - current.meta.fold(settings.genesisSettings.initialBalance)(_.totalWavesAmount) + reward.getOrElse(0L) + current.meta.fold(settings.genesisSettings.initialBalance)(_.totalWavesAmount) + + (reward.getOrElse(0L) * this.blockRewardBoost(newHeight)) ) current = CurrentBlockInfo(Height(newHeight), Some(newMeta), block.transactionData) diff --git a/node/src/main/scala/com/wavesplatform/database/DBResource.scala b/node/src/main/scala/com/wavesplatform/database/DBResource.scala index 7d3f17515b..0d5afe026a 100644 --- a/node/src/main/scala/com/wavesplatform/database/DBResource.scala +++ b/node/src/main/scala/com/wavesplatform/database/DBResource.scala @@ -5,55 +5,53 @@ import org.rocksdb.{ColumnFamilyHandle, ReadOptions, RocksDB, RocksIterator} import scala.collection.View import scala.collection.mutable.ArrayBuffer -trait DBResource extends AutoCloseable { - def get[V](key: Key[V]): V - def get(key: Array[Byte]): Array[Byte] - def multiGet[A](keys: ArrayBuffer[Key[A]], valBufferSizes: ArrayBuffer[Int]): View[A] - def multiGet[A](keys: ArrayBuffer[Key[A]], valBufferSize: Int): View[A] - def multiGetFlat[A](keys: ArrayBuffer[Key[Option[A]]], valBufferSizes: ArrayBuffer[Int]): Seq[A] - def prefixIterator: RocksIterator // Should have a single instance - def fullIterator: RocksIterator // Should have a single instance - def withSafePrefixIterator[A](ifNotClosed: RocksIterator => A)(ifClosed: => A = ()): A - def withSafeFullIterator[A](ifNotClosed: RocksIterator => A)(ifClosed: => A = ()): A -} - -object DBResource { - def apply(db: RocksDB, iteratorCfHandle: Option[ColumnFamilyHandle] = None): DBResource = new DBResource { - private[this] val snapshot = db.getSnapshot - private[this] val readOptions = new ReadOptions().setSnapshot(snapshot) +class DBResource(db: RocksDB, iteratorCfHandle: Option[ColumnFamilyHandle] = None) extends AutoCloseable { + private[this] val snapshot = db.getSnapshot + // checksum verification is **very** expensive, so it's explicitly disabled + private[this] val readOptions = new ReadOptions().setSnapshot(snapshot).setVerifyChecksums(false) - override def get[V](key: Key[V]): V = key.parse(db.get(key.columnFamilyHandle.getOrElse(db.getDefaultColumnFamily), readOptions, key.keyBytes)) + def get[V](key: Key[V]): V = key.parse(db.get(key.columnFamilyHandle.getOrElse(db.getDefaultColumnFamily), readOptions, key.keyBytes)) - override def get(key: Array[Byte]): Array[Byte] = db.get(readOptions, key) + def get(key: Array[Byte]): Array[Byte] = db.get(readOptions, key) - override def multiGetFlat[A](keys: ArrayBuffer[Key[Option[A]]], valBufferSizes: ArrayBuffer[Int]): Seq[A] = - db.multiGetFlat(readOptions, keys, valBufferSizes) + def multiGetFlat[A](keys: ArrayBuffer[Key[Option[A]]], valBufferSizes: ArrayBuffer[Int]): Seq[A] = + db.multiGetFlat(readOptions, keys, valBufferSizes) - def multiGet[A](keys: ArrayBuffer[Key[A]], valBufferSizes: ArrayBuffer[Int]): View[A] = - db.multiGet(readOptions, keys, valBufferSizes) + def multiGet[A](keys: ArrayBuffer[Key[A]], valBufferSizes: ArrayBuffer[Int]): View[A] = + db.multiGet(readOptions, keys, valBufferSizes) - def multiGet[A](keys: ArrayBuffer[Key[A]], valBufferSize: Int): View[A] = - db.multiGet(readOptions, keys, valBufferSize) + def multiGet[A](keys: ArrayBuffer[Key[A]], valBufferSize: Int): View[A] = + db.multiGet(readOptions, keys, valBufferSize) - override lazy val prefixIterator: RocksIterator = - db.newIterator(iteratorCfHandle.getOrElse(db.getDefaultColumnFamily), readOptions.setTotalOrderSeek(false).setPrefixSameAsStart(true)) + @volatile private var prefixIteratorWasOpened = false + /** + * Finds the exact key for iter.seek(key) if key.length < 10 and becomes invalid on iter.next(). + * Works as intended if prefix(key).length >= 10. + * @see RDB.newColumnFamilyOptions + */ + lazy val prefixIterator: RocksIterator = { + prefixIteratorWasOpened = true + db.newIterator(iteratorCfHandle.getOrElse(db.getDefaultColumnFamily), readOptions.setTotalOrderSeek(false).setPrefixSameAsStart(true)) + } - override lazy val fullIterator: RocksIterator = - db.newIterator(iteratorCfHandle.getOrElse(db.getDefaultColumnFamily), readOptions.setTotalOrderSeek(true)) + @volatile private var fullIteratorWasOpened = false + lazy val fullIterator: RocksIterator = { + fullIteratorWasOpened = true + db.newIterator(iteratorCfHandle.getOrElse(db.getDefaultColumnFamily), readOptions.setTotalOrderSeek(true)) + } - override def withSafePrefixIterator[A](ifNotClosed: RocksIterator => A)(ifClosed: => A): A = prefixIterator.synchronized { - if (prefixIterator.isOwningHandle) ifNotClosed(prefixIterator) else ifClosed - } + def withSafePrefixIterator[A](ifNotClosed: RocksIterator => A)(ifClosed: => A): A = prefixIterator.synchronized { + if (prefixIterator.isOwningHandle) ifNotClosed(prefixIterator) else ifClosed + } - override def withSafeFullIterator[A](ifNotClosed: RocksIterator => A)(ifClosed: => A): A = fullIterator.synchronized { - if (fullIterator.isOwningHandle) ifNotClosed(fullIterator) else ifClosed - } + def withSafeFullIterator[A](ifNotClosed: RocksIterator => A)(ifClosed: => A): A = fullIterator.synchronized { + if (fullIterator.isOwningHandle) ifNotClosed(fullIterator) else ifClosed + } - override def close(): Unit = { - prefixIterator.synchronized(prefixIterator.close()) - fullIterator.synchronized(fullIterator.close()) - db.releaseSnapshot(snapshot) - readOptions.close() - } + override def close(): Unit = { + if (prefixIteratorWasOpened) prefixIterator.synchronized(prefixIterator.close()) + if (fullIteratorWasOpened) fullIterator.synchronized(fullIterator.close()) + db.releaseSnapshot(snapshot) + readOptions.close() } } diff --git a/node/src/main/scala/com/wavesplatform/database/RDB.scala b/node/src/main/scala/com/wavesplatform/database/RDB.scala index 7c9bb13a79..98c7168875 100644 --- a/node/src/main/scala/com/wavesplatform/database/RDB.scala +++ b/node/src/main/scala/com/wavesplatform/database/RDB.scala @@ -137,13 +137,13 @@ object RDB extends StrictLogging { private def createDbOptions(settings: DBSettings): OptionsWithResources[DBOptions] = { val dbOptions = new DBOptions() .setCreateIfMissing(true) - .setParanoidChecks(settings.rocksdb.paranoidChecks) - .setIncreaseParallelism(6) + .setIncreaseParallelism(settings.rocksdb.parallelism) .setBytesPerSync(2 << 20) .setCreateMissingColumnFamilies(true) - .setMaxOpenFiles(100) + .setMaxOpenFiles(settings.rocksdb.maxOpenFiles) .setMaxSubcompactions(2) // Write stalls expected without this option. Can lead to max_background_jobs * max_subcompactions background threads .setMaxManifestFileSize(200 << 20) + .setAllowMmapReads(settings.rocksdb.allowMmapReads) if (settings.rocksdb.enableStatistics) { val statistics = new Statistics() diff --git a/node/src/main/scala/com/wavesplatform/database/RocksDBWriter.scala b/node/src/main/scala/com/wavesplatform/database/RocksDBWriter.scala index c2f8361fce..2d4b0f8ccb 100644 --- a/node/src/main/scala/com/wavesplatform/database/RocksDBWriter.scala +++ b/node/src/main/scala/com/wavesplatform/database/RocksDBWriter.scala @@ -14,7 +14,7 @@ import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.EitherExt2 import com.wavesplatform.database import com.wavesplatform.database.patch.DisableHijackedAliases -import com.wavesplatform.database.protobuf.{StaticAssetInfo, TransactionMeta, BlockMeta as PBBlockMeta} +import com.wavesplatform.database.protobuf.{BlockMetaExt, StaticAssetInfo, TransactionMeta, BlockMeta as PBBlockMeta} import com.wavesplatform.features.BlockchainFeatures import com.wavesplatform.lang.ValidationError import com.wavesplatform.protobuf.block.PBBlocks @@ -1239,7 +1239,7 @@ class RocksDBWriter( tx <- db .get(Keys.transactionAt(Height(tm.height), TxNum(tm.num.toShort), rdb.txHandle)) .collect { - case (tm, t: TransferTransaction) if tm.status == TxMeta.Status.Succeeded => t + case (m, t: TransferTransaction) if m.status == TxMeta.Status.Succeeded => t case (_, e @ EthereumTransaction(transfer: Transfer, _, _, _)) if tm.status == PBStatus.SUCCEEDED => val asset = transfer.tokenAddress.fold[Asset](Waves)(resolveERC20Address(_).get) e.toTransferLike(TxPositiveAmount.unsafeFrom(transfer.amount), transfer.recipient, asset) @@ -1315,28 +1315,16 @@ class RocksDBWriter( .build[(Int, AddressId), LeaseBalanceNode]() override def balanceAtHeight(address: Address, height: Int, assetId: Asset = Waves): Option[(Int, Long)] = readOnly { db => - @tailrec - def getBalanceAtHeight(h: Height, key: Height => Key[BalanceNode]): (Int, Long) = { - val balance = db.get(key(h)) - if (h <= height) { - h -> balance.balance - } else { - getBalanceAtHeight(balance.prevHeight, key) - } - } - - db.get(Keys.addressId(address)).map { aid => - val (balance, balanceNodeKey) = - assetId match { - case Waves => (db.get(Keys.wavesBalance(aid)), Keys.wavesBalanceAt(aid, _)) - case asset @ IssuedAsset(_) => (db.get(Keys.assetBalance(aid, asset)), Keys.assetBalanceAt(aid, asset, _)) - } - - if (balance.height > height) { - getBalanceAtHeight(balance.prevHeight, balanceNodeKey) - } else { - balance.height -> balance.balance + db.get(Keys.addressId(address)).flatMap { aid => + val key = assetId match { + case Waves => Keys.wavesBalanceAt(aid, Height(height)) + case asset: IssuedAsset => Keys.assetBalanceAt(aid, asset, Height(height)) } + Using(db.newIterator) { iter => + iter.seekForPrev(key.keyBytes) + require(iter.isValid && iter.key().startsWith(key.keyBytes.dropRight(Ints.BYTES))) + Ints.fromByteArray(iter.key().takeRight(Ints.BYTES)) -> key.parse(iter.value()).balance + }.toOption } } diff --git a/node/src/main/scala/com/wavesplatform/database/package.scala b/node/src/main/scala/com/wavesplatform/database/package.scala index b0fc6bc540..59a768b73f 100644 --- a/node/src/main/scala/com/wavesplatform/database/package.scala +++ b/node/src/main/scala/com/wavesplatform/database/package.scala @@ -423,7 +423,8 @@ package object database { def withReadOptions[A](f: ReadOptions => A): A = { val snapshot = db.getSnapshot - val ro = new ReadOptions().setSnapshot(snapshot) + // checksum may be verification is **very** expensive, so it's explicitly disabled + val ro = new ReadOptions().setSnapshot(snapshot).setVerifyChecksums(false) try f(ro) finally { ro.close() @@ -529,27 +530,29 @@ package object database { } else () } - val iterator = db.newIterator(cfh.getOrElse(db.getDefaultColumnFamily), new ReadOptions().setTotalOrderSeek(true)) - try { - iterator.seek(prefix) - loop(iterator) - } finally iterator.close() + withReadOptions { ro => + val iterator = db.newIterator(cfh.getOrElse(db.getDefaultColumnFamily), ro.setTotalOrderSeek(true)) + try { + iterator.seek(prefix) + loop(iterator) + } finally iterator.close() + } } def resourceObservable: Observable[DBResource] = - Observable.resource(Task(DBResource(db, None)))(r => Task(r.close())) + Observable.resource(Task(new DBResource(db, None)))(r => Task(r.close())) def resourceObservable(iteratorCfHandle: ColumnFamilyHandle): Observable[DBResource] = - Observable.resource(Task(DBResource(db, Some(iteratorCfHandle))))(r => Task(r.close())) + Observable.resource(Task(new DBResource(db, Some(iteratorCfHandle))))(r => Task(r.close())) def withResource[A](f: DBResource => A): A = { - val resource = DBResource(db) + val resource = new DBResource(db) try f(resource) finally resource.close() } def withResource[A](iteratorCfHandle: ColumnFamilyHandle)(f: DBResource => A): A = { - val resource = DBResource(db, Some(iteratorCfHandle)) + val resource = new DBResource(db, Some(iteratorCfHandle)) try f(resource) finally resource.close() } diff --git a/node/src/main/scala/com/wavesplatform/extensions/Context.scala b/node/src/main/scala/com/wavesplatform/extensions/Context.scala index c0c2e9e900..bfa690d02e 100644 --- a/node/src/main/scala/com/wavesplatform/extensions/Context.scala +++ b/node/src/main/scala/com/wavesplatform/extensions/Context.scala @@ -1,6 +1,5 @@ package com.wavesplatform.extensions -import akka.actor.ActorSystem import com.wavesplatform.api.common.* import com.wavesplatform.common.state.ByteStr import com.wavesplatform.events.UtxEvent @@ -30,5 +29,4 @@ trait Context { def broadcastTransaction(tx: Transaction): TracedResult[ValidationError, Boolean] def utxEvents: Observable[UtxEvent] - def actorSystem: ActorSystem } diff --git a/node/src/main/scala/com/wavesplatform/features/BlockchainFeature.scala b/node/src/main/scala/com/wavesplatform/features/BlockchainFeature.scala index 4667f77767..5a255eb3a4 100644 --- a/node/src/main/scala/com/wavesplatform/features/BlockchainFeature.scala +++ b/node/src/main/scala/com/wavesplatform/features/BlockchainFeature.scala @@ -26,10 +26,11 @@ object BlockchainFeatures { val CappedReward = BlockchainFeature(20, "Capped XTN buy-back & DAO amounts") val CeaseXtnBuyback = BlockchainFeature(21, "Cease XTN buy-back") val LightNode = BlockchainFeature(22, "Light Node") + val BoostBlockReward = BlockchainFeature(23, "Boost Block Reward") // Not exposed - val ContinuationTransaction = BlockchainFeature(23, "Continuation Transaction") - val LeaseExpiration = BlockchainFeature(24, "Lease Expiration") + val ContinuationTransaction = BlockchainFeature(24, "Continuation Transaction") + val LeaseExpiration = BlockchainFeature(25, "Lease Expiration") // When next fork-parameter is created, you must replace all uses of the DummyFeature with the new one. val Dummy = BlockchainFeature(-1, "Non Votable!") @@ -56,7 +57,8 @@ object BlockchainFeatures { BlockRewardDistribution, CappedReward, CeaseXtnBuyback, - LightNode + LightNode, + BoostBlockReward ).map(f => f.id -> f).toMap val implemented: Set[Short] = dict.keySet diff --git a/node/src/main/scala/com/wavesplatform/metrics/HttpSpanLogger.scala b/node/src/main/scala/com/wavesplatform/metrics/HttpSpanLogger.scala index 44dbedac3f..21b179d743 100644 --- a/node/src/main/scala/com/wavesplatform/metrics/HttpSpanLogger.scala +++ b/node/src/main/scala/com/wavesplatform/metrics/HttpSpanLogger.scala @@ -57,11 +57,11 @@ class HttpSpanLogger extends CombinedReporter with LazyLogging { Json .obj( "@timestamp" -> LocalDateTime.ofInstant(snapshot.from, ZoneId.systemDefault()), - "executor_queue_duration_max" -> dist.max.toDouble / 10e6, - "executor_queue_duration_min" -> dist.min.toDouble / 10e6, - "executor_queue_duration_sum" -> dist.sum.toDouble / 10e6, + "executor_queue_duration_max" -> dist.max, + "executor_queue_duration_min" -> dist.min, + "executor_queue_duration_sum" -> dist.sum, "executor_queue_duration_count" -> dist.count, - "executor_queue_duration_avg" -> dist.sum.toDouble / dist.count / 10e6 + "executor_queue_duration_avg" -> dist.sum.toDouble / dist.count ) .toString ) @@ -81,9 +81,9 @@ object HttpSpanLogger { val TimeInQueueMetricKey = "executor.time-in-queue" - case class Mark(key: String, duration: Double) + case class Mark(key: String, durationMillis: Long) - def millisBetween(from: Instant, to: Instant): Double = Duration.between(from, to).toNanos * 1e-6 + def millisBetween(from: Instant, to: Instant): Long = Duration.between(from, to).toMillis implicit class FinishedSpanExt(val span: Span.Finished) extends AnyVal { def isAkkaHttpServer: Boolean = span.metricTags.get(Lookups.option("component")).contains("akka.http.server") def method: String = span.metricTags.get(Lookups.plain(TagKeys.HttpMethod)) diff --git a/node/src/main/scala/com/wavesplatform/mining/microblocks/MicroBlockMinerImpl.scala b/node/src/main/scala/com/wavesplatform/mining/microblocks/MicroBlockMinerImpl.scala index c40f321377..22b87d9b02 100644 --- a/node/src/main/scala/com/wavesplatform/mining/microblocks/MicroBlockMinerImpl.scala +++ b/node/src/main/scala/com/wavesplatform/mining/microblocks/MicroBlockMinerImpl.scala @@ -174,10 +174,10 @@ class MicroBlockMinerImpl( stateHash = if (blockchainUpdater.supportsLightNodeBlockFields()) stateHash else None, challengedHeader = None ) - .leftMap(BlockBuildError) + .leftMap(BlockBuildError.apply) microBlock <- MicroBlock .buildAndSign(signedBlock.header.version, account, unconfirmed, accumulatedBlock.id(), signedBlock.signature, stateHash) - .leftMap(MicroBlockBuildError) + .leftMap(MicroBlockBuildError.apply) } yield (signedBlock, microBlock) } } diff --git a/node/src/main/scala/com/wavesplatform/network/BasicMessagesRepo.scala b/node/src/main/scala/com/wavesplatform/network/BasicMessagesRepo.scala index db699fb41f..cd6f9bcd87 100644 --- a/node/src/main/scala/com/wavesplatform/network/BasicMessagesRepo.scala +++ b/node/src/main/scala/com/wavesplatform/network/BasicMessagesRepo.scala @@ -1,12 +1,9 @@ package com.wavesplatform.network -import java.net.{InetAddress, InetSocketAddress} -import java.util -import scala.util.Try import com.google.common.primitives.{Bytes, Ints} import com.wavesplatform.account.PublicKey -import com.wavesplatform.block.{Block, MicroBlock} import com.wavesplatform.block.serialization.MicroBlockSerializer +import com.wavesplatform.block.{Block, MicroBlock} import com.wavesplatform.common.state.ByteStr import com.wavesplatform.crypto import com.wavesplatform.crypto.* @@ -19,6 +16,11 @@ import com.wavesplatform.protobuf.snapshot.{BlockSnapshot as PBBlockSnapshot, Mi import com.wavesplatform.protobuf.transaction.{PBSignedTransaction, PBTransactions} import com.wavesplatform.transaction.{DataTransaction, EthereumTransaction, Transaction, TransactionParsers} +import java.net.{InetAddress, InetSocketAddress} +import java.util +import scala.reflect.ClassTag +import scala.util.Try + object GetPeersSpec extends MessageSpec[GetPeers.type] { override val messageCode: Message.MessageCode = 1: Byte @@ -33,7 +35,7 @@ object GetPeersSpec extends MessageSpec[GetPeers.type] { override def serializeData(data: GetPeers.type): Array[Byte] = Array() } -object PeersSpec extends MessageSpec[KnownPeers] { +abstract class InetSocketAddressSeqSpec[A <: AnyRef : ClassTag] extends MessageSpec[A] { private val AddressLength = 4 private val PortLength = 4 private val DataLength = 4 @@ -42,36 +44,46 @@ object PeersSpec extends MessageSpec[KnownPeers] { override val maxLength: Int = DataLength + 1000 * (AddressLength + PortLength) - override def deserializeData(bytes: Array[Byte]): Try[KnownPeers] = Try { + protected def unwrap(v: A): Seq[InetSocketAddress] + protected def wrap(addresses: Seq[InetSocketAddress]): A + + override def deserializeData(bytes: Array[Byte]): Try[A] = Try { val lengthBytes = util.Arrays.copyOfRange(bytes, 0, DataLength) val length = Ints.fromByteArray(lengthBytes) - assert(bytes.length == DataLength + (length * (AddressLength + PortLength)), "Data does not match length") + val expectedMessageLength = DataLength + (length * (AddressLength + PortLength)) + assert( + bytes.length == expectedMessageLength, + s"Invalid KnownPeers message length ${bytes.length}, expecting $expectedMessageLength for $length peers" + ) - KnownPeers((0 until length).map { i => + (0 until length).map { i => val position = lengthBytes.length + (i * (AddressLength + PortLength)) val addressBytes = util.Arrays.copyOfRange(bytes, position, position + AddressLength) val address = InetAddress.getByAddress(addressBytes) val portBytes = util.Arrays.copyOfRange(bytes, position + AddressLength, position + AddressLength + PortLength) new InetSocketAddress(address, Ints.fromByteArray(portBytes)) - }) - } - - override def serializeData(peers: KnownPeers): Array[Byte] = { - val length = peers.peers.size - val lengthBytes = Ints.toByteArray(length) + } + }.map(wrap) - val xs = for { - inetAddress <- peers.peers + def serializeData(value: A): Array[Byte] = { + val peersWithResolvedAddresses = for { + inetAddress <- unwrap(value) address <- Option(inetAddress.getAddress) } yield (address.getAddress, inetAddress.getPort) - xs.foldLeft(lengthBytes) { case (bs, (peerAddress, peerPort)) => + peersWithResolvedAddresses.foldLeft(Ints.toByteArray(peersWithResolvedAddresses.size)) { case (bs, (peerAddress, peerPort)) => Bytes.concat(bs, peerAddress, Ints.toByteArray(peerPort)) } } } +object PeersSpec extends InetSocketAddressSeqSpec[KnownPeers] { + override protected def unwrap(v: KnownPeers): Seq[InetSocketAddress] = v.peers + + override protected def wrap(addresses: Seq[InetSocketAddress]): KnownPeers = KnownPeers(addresses) +} + trait SignaturesSeqSpec[A <: AnyRef] extends MessageSpec[A] { private val DataLength = 4 @@ -355,7 +367,7 @@ object HandshakeSpec { object BasicMessagesRepo { type Spec = MessageSpec[? <: AnyRef] - val specs: Seq[Spec] = Seq( + private val specs: Seq[Spec] = Seq( GetPeersSpec, PeersSpec, GetSignaturesSpec, diff --git a/node/src/main/scala/com/wavesplatform/network/HandshakeHandler.scala b/node/src/main/scala/com/wavesplatform/network/HandshakeHandler.scala index 834f06fee3..ad74206b20 100644 --- a/node/src/main/scala/com/wavesplatform/network/HandshakeHandler.scala +++ b/node/src/main/scala/com/wavesplatform/network/HandshakeHandler.scala @@ -1,8 +1,5 @@ package com.wavesplatform.network -import java.util -import java.util.concurrent.{ConcurrentMap, TimeUnit} - import com.wavesplatform.network.Handshake.InvalidHandshakeException import com.wavesplatform.utils.ScorexLogging import io.netty.buffer.ByteBuf @@ -13,6 +10,9 @@ import io.netty.handler.codec.ReplayingDecoder import io.netty.util.AttributeKey import io.netty.util.concurrent.ScheduledFuture +import java.net.InetSocketAddress +import java.util +import java.util.concurrent.{ConcurrentMap, TimeUnit} import scala.concurrent.duration.FiniteDuration class HandshakeDecoder(peerDatabase: PeerDatabase) extends ReplayingDecoder[Void] with ScorexLogging { @@ -80,16 +80,37 @@ abstract class HandshakeHandler( import HandshakeHandler.* + protected def suspendAndClose(msg: => String, verifiedRemoteAddress: Option[InetSocketAddress], ctx: ChannelHandlerContext): Unit = { + log.debug(s"${id(ctx)} $msg") + verifiedRemoteAddress.foreach(peerDatabase.suspend) + ctx.close() + } + override def channelRead(ctx: ChannelHandlerContext, msg: AnyRef): Unit = msg match { + case HandshakeTimeoutExpired => + log.trace(s"Timeout expired while waiting for handshake: ${id(ctx.channel())}") + ctx.channel().remoteAddress() match { + case isa: InetSocketAddress => peerDatabase.suspend(isa) + case _ => + } + ctx.close() case remoteHandshake: Handshake => + val verifiedDeclaredAddress = remoteHandshake.declaredAddress.filter(_ == ctx.channel().remoteAddress()) + if (localHandshake.applicationName != remoteHandshake.applicationName) - peerDatabase.blacklistAndClose( - ctx.channel(), - s"Remote application name ${remoteHandshake.applicationName} does not match local ${localHandshake.applicationName}" + suspendAndClose( + s"Remote application name ${remoteHandshake.applicationName} does not match local ${localHandshake.applicationName}", + verifiedDeclaredAddress, + ctx ) else if (!versionIsSupported(remoteHandshake.applicationVersion)) - peerDatabase.blacklistAndClose(ctx.channel(), s"Remote application version ${remoteHandshake.applicationVersion} is not supported") + suspendAndClose(s"Remote application version ${remoteHandshake.applicationVersion} is not supported", verifiedDeclaredAddress, ctx) else { + verifiedDeclaredAddress.foreach { vda => + ctx.channel().attr(NodeDeclaredAddressAttributeKey).set(vda) + peerDatabase.touch(vda) + } + PeerKey(ctx, remoteHandshake.nodeNonce) match { case None => log.warn(s"Can't get PeerKey from ${id(ctx)}") @@ -117,11 +138,12 @@ abstract class HandshakeHandler( connectionNegotiated(ctx) ctx.fireChannelRead(msg) } else { - val peerAddress = ctx.remoteAddress.getOrElse("unknown") - log.debug(s"${id(ctx)} Already connected to peer $peerAddress with nonce ${remoteHandshake.nodeNonce} on channel ${id(previousPeer)}") - peerDatabase.suspendAndClose(ctx.channel()) + suspendAndClose( + s"${id(ctx)} Already connected to peer with nonce ${remoteHandshake.nodeNonce} on channel ${id(previousPeer)}", + verifiedDeclaredAddress, + ctx + ) } - } } case _ => super.channelRead(ctx, msg) @@ -139,9 +161,11 @@ abstract class HandshakeHandler( object HandshakeHandler { - val NodeNameAttributeKey: AttributeKey[String] = AttributeKey.newInstance[String]("name") - val NodeVersionAttributeKey: AttributeKey[(Int, Int, Int)] = AttributeKey.newInstance[(Int, Int, Int)]("version") - private val ConnectionStartAttributeKey = AttributeKey.newInstance[Long]("connectionStart") + val NodeNameAttributeKey: AttributeKey[String] = AttributeKey.newInstance[String]("name") + val NodeVersionAttributeKey: AttributeKey[(Int, Int, Int)] = AttributeKey.newInstance[(Int, Int, Int)]("version") + val NodeDeclaredAddressAttributeKey: AttributeKey[InetSocketAddress] = AttributeKey.newInstance[InetSocketAddress]("declaredAddress") + + private val ConnectionStartAttributeKey = AttributeKey.newInstance[Long]("connectionStart") def versionIsSupported(remoteVersion: (Int, Int, Int)): Boolean = (remoteVersion._1 == 0 && remoteVersion._2 >= 13) || (remoteVersion._1 == 1 && remoteVersion._2 >= 0) @@ -169,15 +193,6 @@ object HandshakeHandler { peerDatabase: PeerDatabase, allChannels: ChannelGroup ) extends HandshakeHandler(handshake, establishedConnections, peerConnections, peerDatabase, allChannels) { - - override def channelRead(ctx: ChannelHandlerContext, msg: AnyRef): Unit = msg match { - case HandshakeTimeoutExpired => - peerDatabase.blacklistAndClose(ctx.channel(), "Timeout expired while waiting for handshake") - - case _ => - super.channelRead(ctx, msg) - } - override protected def connectionNegotiated(ctx: ChannelHandlerContext): Unit = { sendLocalHandshake(ctx) super.connectionNegotiated(ctx) @@ -192,16 +207,6 @@ object HandshakeHandler { peerDatabase: PeerDatabase, allChannels: ChannelGroup ) extends HandshakeHandler(handshake, establishedConnections, peerConnections, peerDatabase, allChannels) { - - override def channelRead(ctx: ChannelHandlerContext, msg: AnyRef): Unit = msg match { - case HandshakeTimeoutExpired => - log.trace(s"Timeout expired while waiting for handshake: ${id(ctx.channel())}") - peerDatabase.suspendAndClose(ctx.channel()) - - case _ => - super.channelRead(ctx, msg) - } - override def channelActive(ctx: ChannelHandlerContext): Unit = { sendLocalHandshake(ctx) ctx.channel().attr(ConnectionStartAttributeKey).set(System.currentTimeMillis()) diff --git a/node/src/main/scala/com/wavesplatform/network/HistoryReplier.scala b/node/src/main/scala/com/wavesplatform/network/HistoryReplierL1.scala similarity index 91% rename from node/src/main/scala/com/wavesplatform/network/HistoryReplier.scala rename to node/src/main/scala/com/wavesplatform/network/HistoryReplierL1.scala index e195d00a4c..6e21c3bfcb 100644 --- a/node/src/main/scala/com/wavesplatform/network/HistoryReplier.scala +++ b/node/src/main/scala/com/wavesplatform/network/HistoryReplierL1.scala @@ -2,7 +2,7 @@ package com.wavesplatform.network import com.wavesplatform.block.Block import com.wavesplatform.history.History -import com.wavesplatform.network.HistoryReplier.* +import com.wavesplatform.network.HistoryReplierL1.* import com.wavesplatform.settings.SynchronizationSettings import com.wavesplatform.utils.ScorexLogging import io.netty.channel.ChannelHandler.Sharable @@ -12,8 +12,8 @@ import scala.concurrent.{ExecutionContext, Future} import scala.util.{Failure, Success} @Sharable -class HistoryReplier(score: => BigInt, history: History, settings: SynchronizationSettings)(implicit ec: ExecutionContext) - extends ChannelInboundHandlerAdapter +class HistoryReplierL1(score: => BigInt, history: History, settings: SynchronizationSettings)(implicit ec: ExecutionContext) + extends ChannelInboundHandlerAdapter with ScorexLogging { private def respondWith(ctx: ChannelHandlerContext, value: Future[Message]): Unit = @@ -78,6 +78,6 @@ class HistoryReplier(score: => BigInt, history: History, settings: Synchronizati def cacheSizes: CacheSizes = CacheSizes(0, 0) } -object HistoryReplier { +object HistoryReplierL1 { case class CacheSizes(blocks: Long, microBlocks: Long) } diff --git a/node/src/main/scala/com/wavesplatform/network/InboundConnectionFilter.scala b/node/src/main/scala/com/wavesplatform/network/InboundConnectionFilter.scala index ffb2318c28..42b9363a7b 100644 --- a/node/src/main/scala/com/wavesplatform/network/InboundConnectionFilter.scala +++ b/node/src/main/scala/com/wavesplatform/network/InboundConnectionFilter.scala @@ -32,7 +32,7 @@ class InboundConnectionFilter(peerDatabase: PeerDatabase, maxInboundConnections: case Some(address) => val newTotal = inboundConnectionCount.incrementAndGet() val newCountPerHost = perHostConnectionCount.compute(address, (_, cnt) => Option(cnt).fold(1)(_ + 1)) - val isBlacklisted = peerDatabase.blacklistedHosts.contains(address) + val isBlacklisted = peerDatabase.isBlacklisted(address) val accepted = newTotal <= maxInboundConnections && newCountPerHost <= maxConnectionsPerHost && diff --git a/node/src/main/scala/com/wavesplatform/network/InvalidBlockStorage.scala b/node/src/main/scala/com/wavesplatform/network/InvalidBlockStorage.scala index 2bae04cd2d..5ad557f7ae 100644 --- a/node/src/main/scala/com/wavesplatform/network/InvalidBlockStorage.scala +++ b/node/src/main/scala/com/wavesplatform/network/InvalidBlockStorage.scala @@ -4,6 +4,7 @@ import com.google.common.cache.CacheBuilder import com.wavesplatform.common.state.ByteStr import com.wavesplatform.lang.ValidationError import com.wavesplatform.network.InvalidBlockStorageImpl.* +import com.wavesplatform.transaction.TxValidationError.BlockFromFuture import scala.concurrent.duration.FiniteDuration @@ -26,7 +27,11 @@ class InvalidBlockStorageImpl(settings: InvalidBlockStorageSettings) extends Inv .expireAfterWrite(settings.timeout.length, settings.timeout.unit) .build[ByteStr, ValidationError]() - override def add(blockId: ByteStr, validationError: ValidationError): Unit = cache.put(blockId, validationError) + override def add(blockId: ByteStr, validationError: ValidationError): Unit = + validationError match { + case _: BlockFromFuture => // ignore because it's a temporary error + case _ => cache.put(blockId, validationError) + } override def find(blockId: ByteStr): Option[ValidationError] = Option(cache.getIfPresent(blockId)) } diff --git a/node/src/main/scala/com/wavesplatform/network/LegacyFrameCodec.scala b/node/src/main/scala/com/wavesplatform/network/LegacyFrameCodec.scala index 9d1bccb6af..9e066e0418 100644 --- a/node/src/main/scala/com/wavesplatform/network/LegacyFrameCodec.scala +++ b/node/src/main/scala/com/wavesplatform/network/LegacyFrameCodec.scala @@ -6,6 +6,8 @@ import java.util import com.wavesplatform.block.Block import com.wavesplatform.common.utils.Base64 import com.wavesplatform.crypto +import com.wavesplatform.network.BasicMessagesRepo.Spec +import com.wavesplatform.network.LegacyFrameCodec.{Magic, MessageRawData} import com.wavesplatform.network.message.Message.* import com.wavesplatform.transaction.Transaction import com.wavesplatform.utils.ScorexLogging @@ -17,15 +19,12 @@ import io.netty.handler.codec.{ByteToMessageCodec, DecoderException} import scala.concurrent.duration.FiniteDuration import scala.util.control.NonFatal -class LegacyFrameCodec(peerDatabase: PeerDatabase, receivedTxsCacheTimeout: FiniteDuration) extends ByteToMessageCodec[Any] with ScorexLogging { +abstract class LegacyFrameCodec(peerDatabase: PeerDatabase) extends ByteToMessageCodec[Any] with ScorexLogging { - import BasicMessagesRepo.specsByCodes - import LegacyFrameCodec.* - - private val receivedTxsCache = CacheBuilder - .newBuilder() - .expireAfterWrite(receivedTxsCacheTimeout.length, receivedTxsCacheTimeout.unit) - .build[String, Object]() + protected def filterBySpecOrChecksum(spec: BasicMessagesRepo.Spec, checkSum: Array[Byte]): Boolean + protected def specsByCodes: Map[Byte, BasicMessagesRepo.Spec] + protected def messageToRawData(msg: Any): MessageRawData + protected def rawDataToMessage(rawData: MessageRawData): AnyRef override def exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable): Unit = cause match { case e: DecoderException => peerDatabase.blacklistAndClose(ctx.channel(), s"Corrupted message frame: $e") @@ -53,16 +52,10 @@ class LegacyFrameCodec(peerDatabase: PeerDatabase, receivedTxsCacheTimeout: Fini require(declaredChecksum.equals(actualChecksum), "invalid checksum") actualChecksum.release() - spec != TransactionSpec || { - val actualChecksumStr = Base64.encode(rawChecksum) - if (receivedTxsCache.getIfPresent(actualChecksumStr) == null) { - receivedTxsCache.put(actualChecksumStr, LegacyFrameCodec.dummy) - true - } else false - } + filterBySpecOrChecksum(spec, rawChecksum) } - if (pushToPipeline) out.add(RawBytes(code, dataBytes)) + if (pushToPipeline) out.add(rawDataToMessage(MessageRawData(code, dataBytes))) } catch { case NonFatal(e) => log.warn(s"${id(ctx)} Malformed network message", e) @@ -71,12 +64,7 @@ class LegacyFrameCodec(peerDatabase: PeerDatabase, receivedTxsCacheTimeout: Fini } override def encode(ctx: ChannelHandlerContext, msg1: Any, out: ByteBuf): Unit = { - val msg = (msg1: @unchecked) match { - case rb: RawBytes => rb - case tx: Transaction => RawBytes.fromTransaction(tx) - case block: Block => RawBytes.fromBlock(block) - case mb: MicroBlockResponse => RawBytes.fromMicroBlock(mb) - } + val msg = messageToRawData(msg1) out.writeInt(Magic) out.writeByte(msg.code) @@ -91,6 +79,43 @@ class LegacyFrameCodec(peerDatabase: PeerDatabase, receivedTxsCacheTimeout: Fini } object LegacyFrameCodec { - val Magic = 0x12345678 + val Magic = 0x12345678 + case class MessageRawData(code: Byte, data: Array[Byte]) +} + +class LegacyFrameCodecL1(peerDatabase: PeerDatabase, receivedTxsCacheTimeout: FiniteDuration) extends LegacyFrameCodec(peerDatabase) { + + private val receivedTxsCache = CacheBuilder + .newBuilder() + .expireAfterWrite(receivedTxsCacheTimeout.length, receivedTxsCacheTimeout.unit) + .build[String, Object]() + + protected def specsByCodes: Map[MessageCode, Spec] = BasicMessagesRepo.specsByCodes + + protected def filterBySpecOrChecksum(spec: BasicMessagesRepo.Spec, checkSum: Array[Byte]): Boolean = { + spec != TransactionSpec || { + val actualChecksumStr = Base64.encode(checkSum) + if (receivedTxsCache.getIfPresent(actualChecksumStr) == null) { + receivedTxsCache.put(actualChecksumStr, LegacyFrameCodecL1.dummy) + true + } else false + } + } + + protected def messageToRawData(msg: Any): MessageRawData = { + val rawBytes = (msg: @unchecked) match { + case rb: RawBytes => rb + case tx: Transaction => RawBytes.fromTransaction(tx) + case block: Block => RawBytes.fromBlock(block) + case mb: MicroBlockResponse => RawBytes.fromMicroBlock(mb) + } + MessageRawData(rawBytes.code, rawBytes.data) + } + + protected def rawDataToMessage(rawData: MessageRawData): AnyRef = + RawBytes(rawData.code, rawData.data) +} + +object LegacyFrameCodecL1 { private val dummy = new Object() } diff --git a/node/src/main/scala/com/wavesplatform/network/MessageCodec.scala b/node/src/main/scala/com/wavesplatform/network/MessageCodecL1.scala similarity index 96% rename from node/src/main/scala/com/wavesplatform/network/MessageCodec.scala rename to node/src/main/scala/com/wavesplatform/network/MessageCodecL1.scala index 3e2705b403..efcf5874f7 100644 --- a/node/src/main/scala/com/wavesplatform/network/MessageCodec.scala +++ b/node/src/main/scala/com/wavesplatform/network/MessageCodecL1.scala @@ -11,7 +11,7 @@ import io.netty.handler.codec.MessageToMessageCodec import scala.util.{Failure, Success} @Sharable -class MessageCodec(peerDatabase: PeerDatabase) extends MessageToMessageCodec[RawBytes, Message] with ScorexLogging { +class MessageCodecL1(peerDatabase: PeerDatabase) extends MessageToMessageCodec[RawBytes, Message] with ScorexLogging { import BasicMessagesRepo.specsByCodes diff --git a/node/src/main/scala/com/wavesplatform/network/MessageObserver.scala b/node/src/main/scala/com/wavesplatform/network/MessageObserverL1.scala similarity index 84% rename from node/src/main/scala/com/wavesplatform/network/MessageObserver.scala rename to node/src/main/scala/com/wavesplatform/network/MessageObserverL1.scala index 5182362201..6d9944c659 100644 --- a/node/src/main/scala/com/wavesplatform/network/MessageObserver.scala +++ b/node/src/main/scala/com/wavesplatform/network/MessageObserverL1.scala @@ -1,15 +1,16 @@ package com.wavesplatform.network import com.wavesplatform.block.Block +import com.wavesplatform.network.MessageObserverL1.Messages import com.wavesplatform.transaction.Transaction -import com.wavesplatform.utils.{Schedulers, ScorexLogging} +import com.wavesplatform.utils.Schedulers import io.netty.channel.ChannelHandler.Sharable import io.netty.channel.{Channel, ChannelHandlerContext, ChannelInboundHandlerAdapter} import monix.execution.schedulers.SchedulerService import monix.reactive.subjects.ConcurrentSubject @Sharable -class MessageObserver extends ChannelInboundHandlerAdapter with ScorexLogging { +class MessageObserverL1 extends ChannelInboundHandlerAdapter { private implicit val scheduler: SchedulerService = Schedulers.fixedPool(2, "message-observer") @@ -35,6 +36,19 @@ class MessageObserver extends ChannelInboundHandlerAdapter with ScorexLogging { } + def messages: Messages = { + ( + signatures, + blocks, + blockchainScores, + microblockInvs, + microblockResponses, + transactions, + blockSnapshots, + microblockSnapshots + ) + } + def shutdown(): Unit = { signatures.onComplete() blocks.onComplete() @@ -47,7 +61,7 @@ class MessageObserver extends ChannelInboundHandlerAdapter with ScorexLogging { } } -object MessageObserver { +object MessageObserverL1 { type Messages = ( ChannelObservable[Signatures], ChannelObservable[Block], @@ -58,21 +72,4 @@ object MessageObserver { ChannelObservable[BlockSnapshotResponse], ChannelObservable[MicroBlockSnapshotResponse] ) - - def apply(): (MessageObserver, Messages) = { - val mo = new MessageObserver() - ( - mo, - ( - mo.signatures, - mo.blocks, - mo.blockchainScores, - mo.microblockInvs, - mo.microblockResponses, - mo.transactions, - mo.blockSnapshots, - mo.microblockSnapshots - ) - ) - } } diff --git a/node/src/main/scala/com/wavesplatform/network/MicroBlockSynchronizer.scala b/node/src/main/scala/com/wavesplatform/network/MicroBlockSynchronizer.scala index 394260ae14..fd23a76b50 100644 --- a/node/src/main/scala/com/wavesplatform/network/MicroBlockSynchronizer.scala +++ b/node/src/main/scala/com/wavesplatform/network/MicroBlockSynchronizer.scala @@ -86,7 +86,7 @@ object MicroBlockSynchronizer extends ScorexLogging { } def tryDownloadNext(prevBlockId: ByteStr): Unit = Option(nextInvs.getIfPresent(prevBlockId)).foreach { inv => - requestData(inv.totalBlockId, inv, awaiting, successfullyReceived, MicroBlockRequest, "microblock") + requestData(inv.totalBlockId, inv, awaiting, successfullyReceived, MicroBlockRequest.apply, "microblock") } lastBlockIdEvents @@ -150,7 +150,7 @@ object MicroBlockSynchronizer extends ScorexLogging { .mapEval { case (ch, mbd @ MicroblockData(Some(mbInv), _, _)) => Task.evalAsync { - requestData(mbInv.totalBlockId, ch -> mbd, waitingForSnapshot, receivedSnapshots, MicroSnapshotRequest, "microblock snapshot") + requestData(mbInv.totalBlockId, ch -> mbd, waitingForSnapshot, receivedSnapshots, MicroSnapshotRequest.apply, "microblock snapshot") } case _ => Task.unit } diff --git a/node/src/main/scala/com/wavesplatform/network/NetworkServer.scala b/node/src/main/scala/com/wavesplatform/network/NetworkServer.scala index a552fbaa03..fab6019743 100644 --- a/node/src/main/scala/com/wavesplatform/network/NetworkServer.scala +++ b/node/src/main/scala/com/wavesplatform/network/NetworkServer.scala @@ -2,9 +2,8 @@ package com.wavesplatform.network import com.wavesplatform.Version import com.wavesplatform.metrics.Metrics -import com.wavesplatform.network.MessageObserver.Messages import com.wavesplatform.settings.* -import com.wavesplatform.transaction.* +import com.wavesplatform.state.Cast import com.wavesplatform.utils.ScorexLogging import io.netty.bootstrap.{Bootstrap, ServerBootstrap} import io.netty.channel.* @@ -16,17 +15,16 @@ import io.netty.util.concurrent.DefaultThreadFactory import monix.reactive.Observable import org.influxdb.dto.Point -import java.net.{InetSocketAddress, NetworkInterface} +import java.net.{InetSocketAddress, NetworkInterface, SocketAddress} import java.nio.channels.ClosedChannelException import java.util.concurrent.ConcurrentHashMap import scala.concurrent.duration.* import scala.jdk.CollectionConverters.* import scala.util.Random -trait NS { +trait NetworkServer { def connect(remoteAddress: InetSocketAddress): Unit def shutdown(): Unit - def messages: Messages def closedChannels: Observable[Channel] } @@ -36,40 +34,36 @@ object NetworkServer extends ScorexLogging { private[this] val LengthFieldSize = 4 def apply( - settings: WavesSettings, - lastBlockInfos: Observable[LastBlockInfo], - historyReplier: HistoryReplier, + applicationName: String, + networkSettings: NetworkSettings, peerDatabase: PeerDatabase, allChannels: ChannelGroup, - peerInfo: ConcurrentHashMap[Channel, PeerInfo] - ): NS = { + peerInfo: ConcurrentHashMap[Channel, PeerInfo], + protocolSpecificPipeline: => Seq[ChannelHandlerAdapter], + ): NetworkServer = { @volatile var shutdownInitiated = false val bossGroup = new NioEventLoopGroup(0, new DefaultThreadFactory("nio-boss-group", true)) val workerGroup = new NioEventLoopGroup(0, new DefaultThreadFactory("nio-worker-group", true)) val handshake = Handshake( - Constants.ApplicationName + settings.blockchainSettings.addressSchemeCharacter, + applicationName, Version.VersionTuple, - settings.networkSettings.nodeName, - settings.networkSettings.nonce, - settings.networkSettings.declaredAddress + networkSettings.nodeName, + networkSettings.nonce, + networkSettings.declaredAddress ) - val trafficWatcher = new TrafficWatcher - val trafficLogger = new TrafficLogger(settings.networkSettings.trafficLogger) - val messageCodec = new MessageCodec(peerDatabase) + val excludedAddresses: Set[InetSocketAddress] = + networkSettings.bindAddress.fold(Set.empty[InetSocketAddress]) { bindAddress => + val isLocal = Option(bindAddress.getAddress).exists(_.isAnyLocalAddress) + val localAddresses = if (isLocal) { + NetworkInterface.getNetworkInterfaces.asScala + .flatMap(_.getInetAddresses.asScala.map(a => new InetSocketAddress(a, bindAddress.getPort))) + .toSet + } else Set(bindAddress) - val excludedAddresses: Set[InetSocketAddress] = { - val bindAddress = settings.networkSettings.bindAddress - val isLocal = Option(bindAddress.getAddress).exists(_.isAnyLocalAddress) - val localAddresses = if (isLocal) { - NetworkInterface.getNetworkInterfaces.asScala - .flatMap(_.getInetAddresses.asScala.map(a => new InetSocketAddress(a, bindAddress.getPort))) - .toSet - } else Set(bindAddress) - - localAddresses ++ settings.networkSettings.declaredAddress.toSet - } + localAddresses ++ networkSettings.declaredAddress.toSet + } val lengthFieldPrepender = new LengthFieldPrepender(4) @@ -83,37 +77,20 @@ object NetworkServer extends ScorexLogging { val fatalErrorHandler = new FatalErrorHandler val inboundConnectionFilter = - new InboundConnectionFilter(peerDatabase, settings.networkSettings.maxInboundConnections, settings.networkSettings.maxConnectionsPerHost) + new InboundConnectionFilter(peerDatabase, networkSettings.maxInboundConnections, networkSettings.maxConnectionsPerHost) - val (messageObserver, networkMessages) = MessageObserver() val (channelClosedHandler, closedChannelsSubject) = ChannelClosedHandler() - val discardingHandler = new DiscardingHandler(lastBlockInfos.map(_.ready), settings.enableLightMode) val peerConnectionsMap = new ConcurrentHashMap[PeerKey, Channel](10, 0.9f, 10) val serverHandshakeHandler = new HandshakeHandler.Server(handshake, peerInfo, peerConnectionsMap, peerDatabase, allChannels) - def peerSynchronizer: ChannelHandlerAdapter = { - if (settings.networkSettings.enablePeersExchange) { - new PeerSynchronizer(peerDatabase, settings.networkSettings.peersBroadcastInterval) - } else PeerSynchronizer.Disabled - } - - def pipelineTail: Seq[ChannelHandlerAdapter] = Seq( - lengthFieldPrepender, - new LengthFieldBasedFrameDecoder(MaxFrameLength, 0, LengthFieldSize, 0, LengthFieldSize), - new LegacyFrameCodec(peerDatabase, settings.networkSettings.receivedTxsCacheTimeout), - channelClosedHandler, - trafficWatcher, - discardingHandler, - messageCodec, - trafficLogger, - writeErrorHandler, - peerSynchronizer, - historyReplier, - messageObserver, - fatalErrorHandler - ) + def pipelineTail: Seq[ChannelHandlerAdapter] = + Seq( + lengthFieldPrepender, + new LengthFieldBasedFrameDecoder(MaxFrameLength, 0, LengthFieldSize, 0, LengthFieldSize) + ) ++ protocolSpecificPipeline ++ + Seq(writeErrorHandler, channelClosedHandler, fatalErrorHandler) - val serverChannel = settings.networkSettings.declaredAddress.map { _ => + val serverChannel = networkSettings.bindAddress.map { bindAddress => new ServerBootstrap() .group(bossGroup, workerGroup) .channel(classOf[NioServerSocketChannel]) @@ -121,14 +98,14 @@ object NetworkServer extends ScorexLogging { new PipelineInitializer( Seq( inboundConnectionFilter, - new BrokenConnectionDetector(settings.networkSettings.breakIdleConnectionsTimeout), + new BrokenConnectionDetector(networkSettings.breakIdleConnectionsTimeout), new HandshakeDecoder(peerDatabase), - new HandshakeTimeoutHandler(settings.networkSettings.handshakeTimeout), + new HandshakeTimeoutHandler(networkSettings.handshakeTimeout), serverHandshakeHandler ) ++ pipelineTail ) ) - .bind(settings.networkSettings.bindAddress) + .bind(bindAddress) .channel() } @@ -137,15 +114,15 @@ object NetworkServer extends ScorexLogging { val clientHandshakeHandler = new HandshakeHandler.Client(handshake, peerInfo, peerConnectionsMap, peerDatabase, allChannels) val bootstrap = new Bootstrap() - .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, settings.networkSettings.connectionTimeout.toMillis.toInt: Integer) + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, networkSettings.connectionTimeout.toMillis.toInt: Integer) .group(workerGroup) .channel(classOf[NioSocketChannel]) .handler( new PipelineInitializer( Seq( - new BrokenConnectionDetector(settings.networkSettings.breakIdleConnectionsTimeout), + new BrokenConnectionDetector(networkSettings.breakIdleConnectionsTimeout), new HandshakeDecoder(peerDatabase), - new HandshakeTimeoutHandler(if (peerConnectionsMap.isEmpty) AverageHandshakePeriod else settings.networkSettings.handshakeTimeout), + new HandshakeTimeoutHandler(if (peerConnectionsMap.isEmpty) AverageHandshakePeriod else networkSettings.handshakeTimeout), clientHandshakeHandler ) ++ pipelineTail ) @@ -155,7 +132,7 @@ object NetworkServer extends ScorexLogging { def handleOutgoingChannelClosed(remoteAddress: InetSocketAddress)(closeFuture: ChannelFuture): Unit = { outgoingChannels.remove(remoteAddress, closeFuture.channel()) - if (!shutdownInitiated) peerDatabase.suspendAndClose(closeFuture.channel()) + if (!shutdownInitiated) peerDatabase.suspend(remoteAddress) if (closeFuture.isSuccess) log.trace(formatOutgoingChannelEvent(closeFuture.channel(), "Channel closed (expected)")) @@ -166,15 +143,16 @@ object NetworkServer extends ScorexLogging { s"Channel closed: ${Option(closeFuture.cause()).map(_.getMessage).getOrElse("no message")}" ) ) + + logConnections() } def handleConnectionAttempt(remoteAddress: InetSocketAddress)(thisConnFuture: ChannelFuture): Unit = { if (thisConnFuture.isSuccess) { log.trace(formatOutgoingChannelEvent(thisConnFuture.channel(), "Connection established")) - peerDatabase.touch(remoteAddress) thisConnFuture.channel().closeFuture().addListener(f => handleOutgoingChannelClosed(remoteAddress)(f)) } else if (thisConnFuture.cause() != null) { - peerDatabase.suspendAndClose(thisConnFuture.channel()) + peerDatabase.suspend(remoteAddress) outgoingChannels.remove(remoteAddress, thisConnFuture.channel()) thisConnFuture.cause() match { case e: ClosedChannelException => @@ -188,6 +166,7 @@ object NetworkServer extends ScorexLogging { case other => log.debug(formatOutgoingChannelEvent(thisConnFuture.channel(), other.getMessage)) } } + logConnections() } def doConnect(remoteAddress: InetSocketAddress): Unit = @@ -201,43 +180,47 @@ object NetworkServer extends ScorexLogging { } ) - def scheduleConnectTask(): Unit = if (!shutdownInitiated) { - val delay = (if (peerConnectionsMap.isEmpty) AverageHandshakePeriod else 5.seconds) + - (Random.nextInt(1000) - 500).millis // add some noise so that nodes don't attempt to connect to each other simultaneously - log.trace(s"Next connection attempt in $delay") + def logConnections(): Unit = { + def mkAddressString(addresses: IterableOnce[SocketAddress]) = + addresses.iterator.map(_.toString).toVector.sorted.mkString("[", ",", "]") - workerGroup.schedule(delay) { - val outgoing = outgoingChannels.keySet.iterator().asScala.toVector + val incoming = peerInfo.values().asScala.view.map(_.remoteAddress).filterNot(outgoingChannels.containsKey) - def outgoingStr = outgoing.map(_.toString).sorted.mkString("[", ", ", "]") + lazy val incomingStr = mkAddressString(incoming) + lazy val outgoingStr = mkAddressString(outgoingChannels.keySet.iterator().asScala) - val all = peerInfo.values().iterator().asScala.flatMap(_.declaredAddress).toVector - val incoming = all.filterNot(outgoing.contains) + val all = peerInfo.values().iterator().asScala.flatMap(_.remoteAddress.cast[InetSocketAddress]) - def incomingStr = incoming.map(_.toString).sorted.mkString("[", ", ", "]") + log.trace(s"Outgoing: $outgoingStr ++ incoming: $incomingStr") - log.trace(s"Outgoing: $outgoingStr ++ incoming: $incomingStr") - if (outgoingChannels.size() < settings.networkSettings.maxOutboundConnections) { + Metrics.write( + Point + .measurement("connections") + .addField("outgoing", outgoingStr) + .addField("incoming", incomingStr) + .addField("n", all.size) + ) + } + + def scheduleConnectTask(): Unit = if (!shutdownInitiated) { + val delay = (if (peerConnectionsMap.isEmpty || networkSettings.minConnections.exists(_ > peerConnectionsMap.size())) AverageHandshakePeriod else 5.seconds) + + (Random.nextInt(1000) - 500).millis // add some noise so that nodes don't attempt to connect to each other simultaneously + + workerGroup.schedule(delay) { + if (outgoingChannels.size() < networkSettings.maxOutboundConnections) { + val all = peerInfo.values().iterator().asScala.flatMap(_.remoteAddress.cast[InetSocketAddress]) peerDatabase - .randomPeer(excluded = excludedAddresses ++ all) + .nextCandidate(excluded = excludedAddresses ++ all) .foreach(doConnect) } - Metrics.write( - Point - .measurement("connections") - .addField("outgoing", outgoingStr) - .addField("incoming", incomingStr) - .addField("n", all.size) - ) - scheduleConnectTask() } } scheduleConnectTask() - new NS { + new NetworkServer { override def connect(remoteAddress: InetSocketAddress): Unit = doConnect(remoteAddress) override def shutdown(): Unit = @@ -250,11 +233,9 @@ object NetworkServer extends ScorexLogging { } finally { workerGroup.shutdownGracefully().await() bossGroup.shutdownGracefully().await() - messageObserver.shutdown() channelClosedHandler.shutdown() } - override val messages: Messages = networkMessages override val closedChannels: Observable[Channel] = closedChannelsSubject } } diff --git a/node/src/main/scala/com/wavesplatform/network/NetworkServerL1.scala b/node/src/main/scala/com/wavesplatform/network/NetworkServerL1.scala new file mode 100644 index 0000000000..7a5b9bd3e7 --- /dev/null +++ b/node/src/main/scala/com/wavesplatform/network/NetworkServerL1.scala @@ -0,0 +1,50 @@ +package com.wavesplatform.network + +import com.wavesplatform.settings.{Constants, WavesSettings} +import com.wavesplatform.transaction.LastBlockInfo +import io.netty.channel.Channel +import io.netty.channel.group.ChannelGroup +import monix.reactive.Observable + +import java.util.concurrent.ConcurrentHashMap + +object NetworkServerL1 { + + def apply( + settings: WavesSettings, + lastBlockInfos: Observable[LastBlockInfo], + historyReplier: HistoryReplierL1, + peerDatabase: PeerDatabase, + messageObserver: MessageObserverL1, + allChannels: ChannelGroup, + peerInfo: ConcurrentHashMap[Channel, PeerInfo] + ): NetworkServer = { + val applicationName = Constants.ApplicationName + settings.blockchainSettings.addressSchemeCharacter + + def peerSynchronizer = if (settings.networkSettings.enablePeersExchange) { + new PeerSynchronizer(peerDatabase, settings.networkSettings.peersBroadcastInterval) + } else PeerSynchronizer.Disabled + val trafficWatcher = new TrafficWatcher + val discardingHandler = new DiscardingHandler(lastBlockInfos.map(_.ready), settings.enableLightMode) + val messageCodec = new MessageCodecL1(peerDatabase) + val trafficLogger = new TrafficLoggerL1(settings.networkSettings.trafficLogger) + + NetworkServer( + applicationName, + settings.networkSettings, + peerDatabase, + allChannels, + peerInfo, + Seq( + new LegacyFrameCodecL1(peerDatabase, settings.networkSettings.receivedTxsCacheTimeout), + trafficWatcher, + discardingHandler, + messageCodec, + trafficLogger, + peerSynchronizer, + historyReplier, + messageObserver + ) + ) + } +} diff --git a/node/src/main/scala/com/wavesplatform/network/PeerDatabase.scala b/node/src/main/scala/com/wavesplatform/network/PeerDatabase.scala index f7d98da7e0..62a64046a9 100644 --- a/node/src/main/scala/com/wavesplatform/network/PeerDatabase.scala +++ b/node/src/main/scala/com/wavesplatform/network/PeerDatabase.scala @@ -4,33 +4,23 @@ import java.net.{InetAddress, InetSocketAddress} import io.netty.channel.Channel -trait PeerDatabase extends AutoCloseable { - +trait PeerDatabase { def addCandidate(socketAddress: InetSocketAddress): Boolean - def touch(socketAddress: InetSocketAddress): Unit + def nextCandidate(excluded: Set[InetSocketAddress]): Option[InetSocketAddress] + def blacklist(host: InetAddress, reason: String): Unit + def blacklistAndClose(channel: Channel, reason: String): Unit + def isBlacklisted(address: InetAddress): Boolean + def clearBlacklist(): Unit def knownPeers: Map[InetSocketAddress, Long] - def blacklistedHosts: Set[InetAddress] - - def suspendedHosts: Set[InetAddress] - - def randomPeer(excluded: Set[InetSocketAddress]): Option[InetSocketAddress] - def detailedBlacklist: Map[InetAddress, (Long, String)] - def detailedSuspended: Map[InetAddress, Long] - def clearBlacklist(): Unit - def suspend(host: InetSocketAddress): Unit - - def blacklistAndClose(channel: Channel, reason: String): Unit - - def suspendAndClose(channel: Channel): Unit } object PeerDatabase { @@ -44,9 +34,7 @@ object PeerDatabase { override def knownPeers: Map[InetSocketAddress, Long] = Map.empty - override def blacklistedHosts: Set[InetAddress] = Set.empty - - override def randomPeer(excluded: Set[InetSocketAddress]): Option[InetSocketAddress] = None + override def nextCandidate(excluded: Set[InetSocketAddress]): Option[InetSocketAddress] = None override def detailedBlacklist: Map[InetAddress, (Long, String)] = Map.empty @@ -54,14 +42,10 @@ object PeerDatabase { override def suspend(host: InetSocketAddress): Unit = {} - override val suspendedHosts: Set[InetAddress] = Set.empty + override def isBlacklisted(address: InetAddress): Boolean = false override val detailedSuspended: Map[InetAddress, Long] = Map.empty override def blacklistAndClose(channel: Channel, reason: String): Unit = channel.close() - - override def suspendAndClose(channel: Channel): Unit = channel.close() - - override def close(): Unit = {} } } diff --git a/node/src/main/scala/com/wavesplatform/network/PeerDatabaseImpl.scala b/node/src/main/scala/com/wavesplatform/network/PeerDatabaseImpl.scala index 99017da663..1330e241fd 100644 --- a/node/src/main/scala/com/wavesplatform/network/PeerDatabaseImpl.scala +++ b/node/src/main/scala/com/wavesplatform/network/PeerDatabaseImpl.scala @@ -1,68 +1,55 @@ package com.wavesplatform.network -import java.net.{InetAddress, InetSocketAddress} -import java.util.concurrent.TimeUnit - -import com.google.common.cache.{CacheBuilder, RemovalNotification} +import com.google.common.base.Ticker +import com.google.common.cache.CacheBuilder import com.google.common.collect.EvictingQueue import com.wavesplatform.settings.NetworkSettings import com.wavesplatform.utils.{JsonFileStorage, ScorexLogging} import io.netty.channel.Channel import io.netty.channel.socket.nio.NioSocketChannel -import scala.jdk.CollectionConverters.* +import java.net.{InetAddress, InetSocketAddress, URI} +import java.util.concurrent.TimeUnit +import scala.annotation.tailrec import scala.collection.* +import scala.collection.immutable.Seq import scala.concurrent.duration.FiniteDuration +import scala.jdk.CollectionConverters.* import scala.util.Random import scala.util.control.NonFatal -class PeerDatabaseImpl(settings: NetworkSettings) extends PeerDatabase with ScorexLogging { - - private type PeerRemoved[T] = RemovalNotification[T, java.lang.Long] - private type PeerRemovalListener[T] = PeerRemoved[T] => Unit - - private def cache[T <: AnyRef](timeout: FiniteDuration, removalListener: Option[PeerRemovalListener[T]] = None) = - removalListener.fold { - CacheBuilder - .newBuilder() - .expireAfterWrite(timeout.toMillis, TimeUnit.MILLISECONDS) - .build[T, java.lang.Long]() - } { listener => - CacheBuilder - .newBuilder() - .expireAfterWrite(timeout.toMillis, TimeUnit.MILLISECONDS) - .removalListener(listener(_)) - .build[T, java.lang.Long]() - } +class PeerDatabaseImpl(settings: NetworkSettings, ticker: Ticker = Ticker.systemTicker()) extends PeerDatabase with AutoCloseable with ScorexLogging { + private def cache[T <: AnyRef](timeout: FiniteDuration) = + CacheBuilder + .newBuilder() + .ticker(ticker) + .expireAfterWrite(timeout.toMillis, TimeUnit.MILLISECONDS) + .build[T, java.lang.Long]() private type PeersPersistenceType = Set[String] - private val peersPersistence = cache[InetSocketAddress](settings.peersDataResidenceTime, Some(nonExpiringKnownPeers)) + private val peersPersistence = cache[InetSocketAddress](settings.peersDataResidenceTime) private val blacklist = cache[InetAddress](settings.blackListResidenceTime) private val suspension = cache[InetAddress](settings.suspensionResidenceTime) private val reasons = mutable.Map.empty[InetAddress, String] private val unverifiedPeers = EvictingQueue.create[InetSocketAddress](settings.maxUnverifiedPeers) - private val knownPeersAddresses = settings.knownPeers.map(inetSocketAddress(_, 6863)) + private val IPAndPort = """(\d+)\.(\d+)\.(\d+)\.(\d+):(\d+)""".r - private def nonExpiringKnownPeers(n: PeerRemoved[InetSocketAddress]): Unit = - if (n.wasEvicted() && knownPeersAddresses.contains(n.getKey)) - peersPersistence.put(n.getKey, n.getValue) - - for (a <- knownPeersAddresses) { - // add peers from config with max timestamp so they never get evicted from the list of known peers - doTouch(a, Long.MaxValue) - } + for (f <- settings.file if f.exists && f.isFile && f.length > 0) try { + JsonFileStorage.load[PeersPersistenceType](f.getCanonicalPath).map { + case IPAndPort(a, b, c, d, port) => + addCandidate(new InetSocketAddress(InetAddress.getByAddress(Array(a, b, c, d).map(_.toInt.toByte)), port.toInt)) + case _ => + } - for (f <- settings.file if f.exists()) try { - JsonFileStorage.load[PeersPersistenceType](f.getCanonicalPath).foreach(a => touch(inetSocketAddress(a, 6863))) - log.info(s"Loaded ${peersPersistence.size} known peer(s) from ${f.getName}") + log.info(s"Loaded ${unverifiedPeers.size} known peer(s) from ${f.getName}") } catch { - case NonFatal(_) => log.info("Legacy or corrupted peers.dat, ignoring, starting all over from known-peers...") + case NonFatal(e) => log.info("Legacy or corrupted peers.dat, ignoring, starting all over from known-peers...", e) } override def addCandidate(socketAddress: InetSocketAddress): Boolean = unverifiedPeers.synchronized { val r = !socketAddress.getAddress.isAnyLocalAddress && - !(socketAddress.getAddress.isLoopbackAddress && socketAddress.getPort == settings.bindAddress.getPort) && + !(socketAddress.getAddress.isLoopbackAddress && settings.bindAddress.exists(_.getPort == socketAddress.getPort)) && Option(peersPersistence.getIfPresent(socketAddress)).isEmpty && !unverifiedPeers.contains(socketAddress) if (r) unverifiedPeers.add(socketAddress) @@ -79,19 +66,16 @@ class PeerDatabaseImpl(settings: NetworkSettings) extends PeerDatabase with Scor override def blacklist(inetAddress: InetAddress, reason: String): Unit = if (settings.enableBlacklisting) { unverifiedPeers.synchronized { - unverifiedPeers.removeIf { x => - Option(x.getAddress).contains(inetAddress) - } - blacklist.put(inetAddress, System.currentTimeMillis()) + unverifiedPeers.removeIf(_.getAddress == inetAddress) + blacklist.put(inetAddress, ticker.read()) reasons.put(inetAddress, reason) } } override def suspend(socketAddress: InetSocketAddress): Unit = getAddress(socketAddress).foreach { address => unverifiedPeers.synchronized { - unverifiedPeers.removeIf { x => - Option(x.getAddress).contains(address) - } + log.trace(s"Suspending $socketAddress") + unverifiedPeers.removeIf(_ == socketAddress) suspension.put(address, System.currentTimeMillis()) } } @@ -102,36 +86,51 @@ class PeerDatabaseImpl(settings: NetworkSettings) extends PeerDatabase with Scor .asMap() .asScala .collect { - case (addr, ts) if !(settings.enableBlacklisting && blacklistedHosts.contains(addr.getAddress)) => addr -> ts.toLong + case (addr, ts) if !(settings.enableBlacklisting && isBlacklisted(addr.getAddress)) => addr -> ts.toLong } .toMap } - override def blacklistedHosts: immutable.Set[InetAddress] = blacklist.asMap().asScala.keys.toSet - - override def suspendedHosts: immutable.Set[InetAddress] = suspension.asMap().asScala.keys.toSet + def isBlacklisted(address: InetAddress): Boolean = blacklist.asMap().containsKey(address) + def isSuspended(address: InetAddress): Boolean = suspension.asMap().containsKey(address) override def detailedBlacklist: immutable.Map[InetAddress, (Long, String)] = - blacklist.asMap().asScala.view.mapValues(_.toLong).map { case ((h, t)) => h -> ((t, Option(reasons(h)).getOrElse(""))) }.toMap + blacklist.asMap().asScala.view.mapValues(_.toLong).map { case (h, t) => h -> ((t, Option(reasons(h)).getOrElse(""))) }.toMap override def detailedSuspended: immutable.Map[InetAddress, Long] = suspension.asMap().asScala.view.mapValues(_.toLong).toMap - override def randomPeer(excluded: immutable.Set[InetSocketAddress]): Option[InetSocketAddress] = unverifiedPeers.synchronized { + private def resolvePeerAddress(addr: String): Seq[InetSocketAddress] = { + val uri = new URI(s"node://$addr") + require(uri.getPort > 0, s"invalid port ${uri.getPort}") + InetAddress + .getAllByName(uri.getHost) + .view + .map { ia => + new InetSocketAddress(ia, uri.getPort) + } + .toSeq + } + + override def nextCandidate(excluded: immutable.Set[InetSocketAddress]): Option[InetSocketAddress] = unverifiedPeers.synchronized { def excludeAddress(isa: InetSocketAddress): Boolean = { - excluded(isa) || Option(isa.getAddress).exists(blacklistedHosts) || suspendedHosts(isa.getAddress) + excluded(isa) || isBlacklisted(isa.getAddress) || isSuspended(isa.getAddress) } - // excluded only contains local addresses, our declared address, and external declared addresses we already have - // connection to, so it's safe to filter out all matching candidates - unverifiedPeers.removeIf(excluded(_)) - val unverified = Option(unverifiedPeers.peek()).filterNot(excludeAddress) - val verified = Random.shuffle(knownPeers.keySet.diff(excluded).toSeq).headOption.filterNot(excludeAddress) - - (unverified, verified) match { - case (Some(_), v @ Some(_)) => if (Random.nextBoolean()) Some(unverifiedPeers.poll()) else v - case (Some(_), None) => Some(unverifiedPeers.poll()) - case (None, v @ Some(_)) => v - case _ => None + + @tailrec + def nextUnverified(): Option[InetSocketAddress] = { + unverifiedPeers.poll() match { + case null => None + case nonNull => + if (!excludeAddress(nonNull)) Some(nonNull) else nextUnverified() + } } + + settings.knownPeers + .flatMap(p => resolvePeerAddress(p)) + .filterNot(excludeAddress) + .headOption + .orElse(nextUnverified()) + .orElse(Random.shuffle(knownPeers.keySet.filterNot(excludeAddress)).headOption) } def clearBlacklist(): Unit = { @@ -140,11 +139,9 @@ class PeerDatabaseImpl(settings: NetworkSettings) extends PeerDatabase with Scor } override def close(): Unit = settings.file.foreach { f => - log.info(s"Saving ${knownPeers.size} known peer(s) to ${f.getName}") - val rawPeers = for { - inetAddress <- knownPeers.keySet - address <- Option(inetAddress.getAddress) - } yield s"${address.getHostAddress}:${inetAddress.getPort}" + val rawPeers = knownPeers.keySet.map(address => s"${address.getAddress.getHostAddress}:${address.getPort}") + + log.info(s"Saving ${rawPeers.size} known peer(s) to ${f.getName}") JsonFileStorage.save[PeersPersistenceType](rawPeers, f.getCanonicalPath) } @@ -155,12 +152,6 @@ class PeerDatabaseImpl(settings: NetworkSettings) extends PeerDatabase with Scor channel.close() } - override def suspendAndClose(channel: Channel): Unit = getRemoteAddress(channel).foreach { x => - log.debug(s"Suspending ${id(channel)}") - suspend(x) - channel.close() - } - private def getAddress(socketAddress: InetSocketAddress): Option[InetAddress] = { val r = Option(socketAddress.getAddress) if (r.isEmpty) log.debug(s"Can't obtain an address from $socketAddress") diff --git a/node/src/main/scala/com/wavesplatform/network/PeerSynchronizer.scala b/node/src/main/scala/com/wavesplatform/network/PeerSynchronizer.scala index 3d3247a44d..7d0814e004 100644 --- a/node/src/main/scala/com/wavesplatform/network/PeerSynchronizer.scala +++ b/node/src/main/scala/com/wavesplatform/network/PeerSynchronizer.scala @@ -1,7 +1,5 @@ package com.wavesplatform.network -import java.net.InetSocketAddress - import com.wavesplatform.utils.ScorexLogging import io.netty.channel.ChannelHandler.Sharable import io.netty.channel.{ChannelHandlerContext, ChannelInboundHandlerAdapter} @@ -9,11 +7,9 @@ import io.netty.channel.{ChannelHandlerContext, ChannelInboundHandlerAdapter} import scala.concurrent.duration.FiniteDuration class PeerSynchronizer(peerDatabase: PeerDatabase, peerRequestInterval: FiniteDuration) extends ChannelInboundHandlerAdapter with ScorexLogging { + private var peersRequested = false - private var peersRequested = false - private var declaredAddress = Option.empty[InetSocketAddress] - - def requestPeers(ctx: ChannelHandlerContext): Unit = if (ctx.channel().isActive) { + private def requestPeers(ctx: ChannelHandlerContext): Unit = if (ctx.channel().isActive) { peersRequested = true ctx.writeAndFlush(GetPeers) @@ -23,24 +19,9 @@ class PeerSynchronizer(peerDatabase: PeerDatabase, peerRequestInterval: FiniteDu } override def channelRead(ctx: ChannelHandlerContext, msg: AnyRef): Unit = { - declaredAddress.foreach(peerDatabase.touch) + Option(ctx.channel().attr(HandshakeHandler.NodeDeclaredAddressAttributeKey).get()).foreach(peerDatabase.touch) msg match { - case hs: Handshake => - val rda = for { - rda <- hs.declaredAddress - rdaAddress <- Option(rda.getAddress) - ctxAddress <- ctx.remoteAddress.map(_.getAddress) - if rdaAddress == ctxAddress - } yield rda - - rda match { - case None => log.debug(s"${id(ctx)} Declared address $rda does not match actual remote address ${ctx.remoteAddress.map(_.getAddress)}") - case Some(x) => - log.trace(s"${id(ctx)} Touching declared address") - peerDatabase.touch(x) - declaredAddress = Some(x) - } - + case _: Handshake => requestPeers(ctx) super.channelRead(ctx, msg) case GetPeers => diff --git a/node/src/main/scala/com/wavesplatform/network/TrafficLogger.scala b/node/src/main/scala/com/wavesplatform/network/TrafficLogger.scala index 98413c53c0..c7cb4d5b79 100644 --- a/node/src/main/scala/com/wavesplatform/network/TrafficLogger.scala +++ b/node/src/main/scala/com/wavesplatform/network/TrafficLogger.scala @@ -3,29 +3,15 @@ package com.wavesplatform.network import com.wavesplatform.block.Block import com.wavesplatform.block.serialization.BlockHeaderSerializer import com.wavesplatform.network.BasicMessagesRepo.specsByCodes -import com.wavesplatform.network.message.{Message => ScorexMessage} +import com.wavesplatform.network.message.Message as ScorexMessage import com.wavesplatform.transaction.Transaction import com.wavesplatform.utils.ScorexLogging import io.netty.channel.ChannelHandler.Sharable import io.netty.channel.{ChannelDuplexHandler, ChannelHandlerContext, ChannelPromise} -@Sharable -class TrafficLogger(settings: TrafficLogger.Settings) extends ChannelDuplexHandler with ScorexLogging { - - import BasicMessagesRepo.specsByClasses - - private val codeOf: AnyRef => Option[Byte] = { - val aux: PartialFunction[AnyRef, Byte] = { - case x: RawBytes => x.code - case _: Transaction => TransactionSpec.messageCode - case _: BigInt | _: LocalScoreChanged => ScoreSpec.messageCode - case _: Block | _: BlockForged => BlockSpec.messageCode - case x: Message => specsByClasses(x.getClass).messageCode - case _: Handshake => HandshakeSpec.messageCode - } - - aux.lift - } +abstract class TrafficLogger(settings: TrafficLogger.Settings) extends ChannelDuplexHandler with ScorexLogging { + protected def codeOf(msg: AnyRef): Option[Byte] + protected def stringify(msg: Any): String override def write(ctx: ChannelHandlerContext, msg: AnyRef, promise: ChannelPromise): Unit = { codeOf(msg).filterNot(settings.ignoreTxMessages).foreach { code => @@ -42,10 +28,29 @@ class TrafficLogger(settings: TrafficLogger.Settings) extends ChannelDuplexHandl super.channelRead(ctx, msg) } +} + +@Sharable +class TrafficLoggerL1(settings: TrafficLogger.Settings) extends TrafficLogger(settings) { + + import BasicMessagesRepo.specsByClasses + + protected def codeOf(msg: AnyRef): Option[Byte] = { + val aux: PartialFunction[AnyRef, Byte] = { + case x: RawBytes => x.code + case _: Transaction => TransactionSpec.messageCode + case _: BigInt | _: LocalScoreChanged => ScoreSpec.messageCode + case _: Block | _: BlockForged => BlockSpec.messageCode + case x: Message => specsByClasses(x.getClass).messageCode + case _: Handshake => HandshakeSpec.messageCode + } + + aux.lift(msg) + } - private def stringify(msg: Any): String = msg match { - case tx: Transaction => s"Transaction(${tx.id()})" - case b: Block => s"${b.id()}, header: ${BlockHeaderSerializer.toJson(b.header, b.bytes().length, b.transactionData.length, b.signature).toString}" + protected def stringify(msg: Any): String = msg match { + case tx: Transaction => s"Transaction(${tx.id()})" + case b: Block => s"${b.id()}, header: ${BlockHeaderSerializer.toJson(b.header, b.bytes().length, b.transactionData.length, b.signature).toString}" case RawBytes(code, data) => s"RawBytes(${specsByCodes(code).messageName}, ${data.length} bytes)" case other => other.toString } diff --git a/node/src/main/scala/com/wavesplatform/network/TrafficWatcher.scala b/node/src/main/scala/com/wavesplatform/network/TrafficWatcher.scala index c078baec19..9385229593 100644 --- a/node/src/main/scala/com/wavesplatform/network/TrafficWatcher.scala +++ b/node/src/main/scala/com/wavesplatform/network/TrafficWatcher.scala @@ -11,14 +11,12 @@ class TrafficWatcher extends ChannelDuplexHandler { import BasicMessagesRepo.specsByCodes - private val outgoing: Map[ScorexMessage.MessageCode, Histogram] = specsByCodes.map { - case (code, spec) => - code -> createHistogram("outgoing", spec) + private val outgoing: Map[ScorexMessage.MessageCode, Histogram] = specsByCodes.map { case (code, spec) => + code -> createHistogram("outgoing", spec) } - private val incoming: Map[ScorexMessage.MessageCode, Histogram] = specsByCodes.map { - case (code, spec) => - code -> createHistogram("incoming", spec) + private val incoming: Map[ScorexMessage.MessageCode, Histogram] = specsByCodes.map { case (code, spec) => + code -> createHistogram("incoming", spec) } private def createHistogram(dir: String, spec: BasicMessagesRepo.Spec): Histogram = diff --git a/node/src/main/scala/com/wavesplatform/network/client/LegacyChannelInitializer.scala b/node/src/main/scala/com/wavesplatform/network/client/LegacyChannelInitializer.scala index 8e16bdd7cb..1d4ab6c8ee 100644 --- a/node/src/main/scala/com/wavesplatform/network/client/LegacyChannelInitializer.scala +++ b/node/src/main/scala/com/wavesplatform/network/client/LegacyChannelInitializer.scala @@ -2,14 +2,14 @@ package com.wavesplatform.network.client import java.io.IOException -import com.wavesplatform.network._ +import com.wavesplatform.network.* import com.wavesplatform.utils.ScorexLogging -import io.netty.channel._ +import io.netty.channel.* import io.netty.channel.socket.SocketChannel import io.netty.handler.codec.{LengthFieldBasedFrameDecoder, LengthFieldPrepender} import scala.concurrent.Promise -import scala.concurrent.duration._ +import scala.concurrent.duration.* class ClientHandshakeHandler(handshake: Handshake, promise: Promise[Channel]) extends ChannelInboundHandlerAdapter with ScorexLogging { @@ -43,7 +43,7 @@ class ClientHandshakeHandler(handshake: Handshake, promise: Promise[Channel]) ex // Used only in tests and Generator class LegacyChannelInitializer(trafficLoggerSettings: TrafficLogger.Settings, handshake: Handshake, promise: Promise[Channel]) - extends ChannelInitializer[SocketChannel] { + extends ChannelInitializer[SocketChannel] { private val lengthFieldLength = 4 private val maxFieldLength = 1024 * 1024 @@ -55,7 +55,7 @@ class LegacyChannelInitializer(trafficLoggerSettings: TrafficLogger.Settings, ha new ClientHandshakeHandler(handshake, promise), new LengthFieldPrepender(lengthFieldLength), new LengthFieldBasedFrameDecoder(maxFieldLength, 0, lengthFieldLength, 0, lengthFieldLength), - new LegacyFrameCodec(PeerDatabase.NoOp, 3.minutes), - new TrafficLogger(trafficLoggerSettings) + new LegacyFrameCodecL1(PeerDatabase.NoOp, 3.minutes), + new TrafficLoggerL1(trafficLoggerSettings) ) } diff --git a/node/src/main/scala/com/wavesplatform/network/package.scala b/node/src/main/scala/com/wavesplatform/network/package.scala index 344b6958b5..4333b43809 100644 --- a/node/src/main/scala/com/wavesplatform/network/package.scala +++ b/node/src/main/scala/com/wavesplatform/network/package.scala @@ -1,8 +1,5 @@ package com.wavesplatform -import java.net.{InetSocketAddress, SocketAddress, URI} -import java.util.concurrent.Callable - import cats.Eq import com.typesafe.scalalogging.Logger import com.wavesplatform.block.Block @@ -20,6 +17,8 @@ import monix.execution.Scheduler import monix.reactive.Observable import org.slf4j.LoggerFactory +import java.net.{InetSocketAddress, SocketAddress} +import java.util.concurrent.Callable import scala.concurrent.duration.* package object network { @@ -27,12 +26,6 @@ package object network { private lazy val logger: Logger = Logger(LoggerFactory.getLogger(getClass.getName)) - def inetSocketAddress(addr: String, defaultPort: Int): InetSocketAddress = { - val uri = new URI(s"node://$addr") - if (uri.getPort < 0) new InetSocketAddress(addr, defaultPort) - else new InetSocketAddress(uri.getHost, uri.getPort) - } - implicit class EventExecutorGroupExt(val e: EventExecutorGroup) extends AnyVal { def scheduleWithFixedDelay(initialDelay: FiniteDuration, delay: FiniteDuration)(f: => Unit): ScheduledFuture[?] = e.scheduleWithFixedDelay((() => f): Runnable, initialDelay.toNanos, delay.toNanos, NANOSECONDS) @@ -78,9 +71,12 @@ package object network { logBroadcast(message, except) val st = broadcastTimeStats.withTag("object", message.getClass.getSimpleName).start() allChannels - .writeAndFlush(message, { (channel: Channel) => - !except.contains(channel) - }) + .writeAndFlush( + message, + { (channel: Channel) => + !except.contains(channel) + } + ) .addListener { (_: ChannelGroupFuture) => st.stop() } diff --git a/node/src/main/scala/com/wavesplatform/settings/BlockchainSettings.scala b/node/src/main/scala/com/wavesplatform/settings/BlockchainSettings.scala index 5ac37553bd..d2c33fa514 100644 --- a/node/src/main/scala/com/wavesplatform/settings/BlockchainSettings.scala +++ b/node/src/main/scala/com/wavesplatform/settings/BlockchainSettings.scala @@ -77,7 +77,9 @@ case class FunctionalitySettings( daoAddress: Option[String] = None, xtnBuybackAddress: Option[String] = None, xtnBuybackRewardPeriod: Int = Int.MaxValue, - lightNodeBlockFieldsAbsenceInterval: Int = 1000 + lightNodeBlockFieldsAbsenceInterval: Int = 1000, + blockRewardBoostPeriod: Int = 1000, + paymentsCheckHeight: Int = 0 ) { val allowLeasedBalanceTransferUntilHeight: Int = blockVersion3AfterHeight val allowTemporaryNegativeUntil: Long = lastTimeBasedForkParameter @@ -130,7 +132,9 @@ object FunctionalitySettings { enforceTransferValidationAfter = 2959447, daoAddress = Some("3PEgG7eZHLFhcfsTSaYxgRhZsh4AxMvA4Ms"), xtnBuybackAddress = Some("3PFjHWuH6WXNJbwnfLHqNFBpwBS5dkYjTfv"), - xtnBuybackRewardPeriod = 100000 + xtnBuybackRewardPeriod = 100000, + blockRewardBoostPeriod = 300_000, + paymentsCheckHeight = 4303300 ) val TESTNET: FunctionalitySettings = apply( @@ -145,7 +149,8 @@ object FunctionalitySettings { enforceTransferValidationAfter = 1698800, daoAddress = Some("3Myb6G8DkdBb8YcZzhrky65HrmiNuac3kvS"), xtnBuybackAddress = Some("3N13KQpdY3UU7JkWUBD9kN7t7xuUgeyYMTT"), - xtnBuybackRewardPeriod = 2000 + xtnBuybackRewardPeriod = 2000, + blockRewardBoostPeriod = 2_000 ) val STAGENET: FunctionalitySettings = apply( @@ -159,7 +164,8 @@ object FunctionalitySettings { ethInvokePaymentsCheckHeight = 1311110, daoAddress = Some("3MaFVH1vTv18FjBRugSRebx259D7xtRh9ic"), xtnBuybackAddress = Some("3MbhiRiLFLJ1EVKNP9npRszcLLQDjwnFfZM"), - xtnBuybackRewardPeriod = 1000 + xtnBuybackRewardPeriod = 1000, + paymentsCheckHeight = 2195900 ) } diff --git a/node/src/main/scala/com/wavesplatform/settings/GRPCSettings.scala b/node/src/main/scala/com/wavesplatform/settings/GRPCSettings.scala index 254b21b127..ea55ddfac3 100644 --- a/node/src/main/scala/com/wavesplatform/settings/GRPCSettings.scala +++ b/node/src/main/scala/com/wavesplatform/settings/GRPCSettings.scala @@ -1,3 +1,7 @@ package com.wavesplatform.settings -final case class GRPCSettings(host: String, port: Int) +final case class GRPCSettings( + host: String, + port: Int, + workerThreads: Int +) diff --git a/node/src/main/scala/com/wavesplatform/settings/NetworkSettings.scala b/node/src/main/scala/com/wavesplatform/settings/NetworkSettings.scala index e547185bf2..a7fd766a0d 100644 --- a/node/src/main/scala/com/wavesplatform/settings/NetworkSettings.scala +++ b/node/src/main/scala/com/wavesplatform/settings/NetworkSettings.scala @@ -1,15 +1,14 @@ package com.wavesplatform.settings -import java.io.File -import java.net.{InetSocketAddress, URI} - import com.typesafe.config.Config import com.wavesplatform.network.TrafficLogger -import com.wavesplatform.utils._ -import net.ceedubs.ficus.Ficus._ -import net.ceedubs.ficus.readers.ArbitraryTypeReader._ +import com.wavesplatform.utils.* +import net.ceedubs.ficus.Ficus.* +import net.ceedubs.ficus.readers.ArbitraryTypeReader.* import net.ceedubs.ficus.readers.ValueReader +import java.io.File +import java.net.{InetSocketAddress, URI} import scala.concurrent.duration.FiniteDuration import scala.util.Random @@ -17,7 +16,7 @@ case class UPnPSettings(enable: Boolean, gatewayTimeout: FiniteDuration, discove case class NetworkSettings( file: Option[File], - bindAddress: InetSocketAddress, + bindAddress: Option[InetSocketAddress], declaredAddress: Option[InetSocketAddress], nodeName: String, nonce: Long, @@ -28,6 +27,7 @@ case class NetworkSettings( maxInboundConnections: Int, maxOutboundConnections: Int, maxConnectionsPerHost: Int, + minConnections: Option[Int], connectionTimeout: FiniteDuration, maxUnverifiedPeers: Int, enablePeersExchange: Boolean, @@ -48,7 +48,7 @@ object NetworkSettings { private[this] def fromConfig(config: Config): NetworkSettings = { val file = config.getAs[File]("file") - val bindAddress = new InetSocketAddress(config.as[String]("bind-address"), config.as[Int]("port")) + val bindAddress = config.getAs[String]("bind-address").map(addr => new InetSocketAddress(addr, config.as[Int]("port"))) val nonce = config.getOrElse("nonce", randomNonce) val nodeName = config.getOrElse("node-name", s"Node-$nonce") require(nodeName.utf8Bytes.length <= MaxNodeNameBytesLength, s"Node name should have length less than $MaxNodeNameBytesLength bytes") @@ -64,6 +64,7 @@ object NetworkSettings { val maxInboundConnections = config.as[Int]("max-inbound-connections") val maxOutboundConnections = config.as[Int]("max-outbound-connections") val maxConnectionsFromSingleHost = config.as[Int]("max-single-host-connections") + val minConnections = config.getAs[Int]("min-connections") val connectionTimeout = config.as[FiniteDuration]("connection-timeout") val maxUnverifiedPeers = config.as[Int]("max-unverified-peers") val enablePeersExchange = config.as[Boolean]("enable-peers-exchange") @@ -88,6 +89,7 @@ object NetworkSettings { maxInboundConnections, maxOutboundConnections, maxConnectionsFromSingleHost, + minConnections, connectionTimeout, maxUnverifiedPeers, enablePeersExchange, diff --git a/node/src/main/scala/com/wavesplatform/settings/RocksDBSettings.scala b/node/src/main/scala/com/wavesplatform/settings/RocksDBSettings.scala index 30ad8d172a..3692e164f2 100644 --- a/node/src/main/scala/com/wavesplatform/settings/RocksDBSettings.scala +++ b/node/src/main/scala/com/wavesplatform/settings/RocksDBSettings.scala @@ -8,5 +8,7 @@ case class RocksDBSettings( apiCacheSize: SizeInBytes, writeBufferSize: SizeInBytes, enableStatistics: Boolean, - paranoidChecks: Boolean + allowMmapReads: Boolean, + parallelism: Int, + maxOpenFiles: Int ) diff --git a/node/src/main/scala/com/wavesplatform/state/BlockRewardCalculator.scala b/node/src/main/scala/com/wavesplatform/state/BlockRewardCalculator.scala index 4b1f5c606e..124b5068a1 100644 --- a/node/src/main/scala/com/wavesplatform/state/BlockRewardCalculator.scala +++ b/node/src/main/scala/com/wavesplatform/state/BlockRewardCalculator.scala @@ -8,7 +8,13 @@ import com.wavesplatform.state.diffs.BlockDiffer.Fraction object BlockRewardCalculator { - case class BlockRewardShares(miner: Long, daoAddress: Long, xtnBuybackAddress: Long) + case class BlockRewardShares(miner: Long, daoAddress: Long, xtnBuybackAddress: Long) { + private[BlockRewardCalculator] def multiply(by: Long): BlockRewardShares = BlockRewardShares( + miner = miner * by, + daoAddress = daoAddress * by, + xtnBuybackAddress = xtnBuybackAddress * by + ) + } val CurrentBlockRewardPart: Fraction = Fraction(1, 3) val RemaindRewardAddressPart: Fraction = Fraction(1, 2) @@ -16,6 +22,7 @@ object BlockRewardCalculator { val FullRewardInit: Long = 6 * Constants.UnitsInWave val MaxAddressReward: Long = 2 * Constants.UnitsInWave val GuaranteedMinerReward: Long = 2 * Constants.UnitsInWave + val RewardBoost = 10 def getBlockRewardShares( height: Int, @@ -50,7 +57,7 @@ object BlockRewardCalculator { calculateRewards(fullBlockReward, CurrentBlockRewardPart.apply(fullBlockReward), daoAddress, modifiedXtnBuybackAddress) } } else BlockRewardShares(fullBlockReward, 0, 0) - } + }.multiply(blockchain.blockRewardBoost(height)) def getSortedBlockRewardShares(height: Int, fullBlockReward: Long, generator: Address, blockchain: Blockchain): Seq[(Address, Long)] = { val daoAddress = blockchain.settings.functionalitySettings.daoAddressParsed.toOption.flatten diff --git a/node/src/main/scala/com/wavesplatform/state/Blockchain.scala b/node/src/main/scala/com/wavesplatform/state/Blockchain.scala index 3e7471e6fc..ab6283ea2a 100644 --- a/node/src/main/scala/com/wavesplatform/state/Blockchain.scala +++ b/node/src/main/scala/com/wavesplatform/state/Blockchain.scala @@ -226,5 +226,12 @@ object Blockchain { def supportsLightNodeBlockFields(height: Int = blockchain.height): Boolean = blockchain.featureActivationHeight(LightNode.id).exists(height >= _ + blockchain.settings.functionalitySettings.lightNodeBlockFieldsAbsenceInterval) + + def blockRewardBoost(height: Int): Int = + blockchain + .featureActivationHeight(BlockchainFeatures.BoostBlockReward.id) + .filter { boostHeight => + boostHeight <= height && height < boostHeight + blockchain.settings.functionalitySettings.blockRewardBoostPeriod + }.fold(1)(_ => BlockRewardCalculator.RewardBoost) } } diff --git a/node/src/main/scala/com/wavesplatform/state/BlockchainUpdaterImpl.scala b/node/src/main/scala/com/wavesplatform/state/BlockchainUpdaterImpl.scala index 26e694c766..46a381d035 100644 --- a/node/src/main/scala/com/wavesplatform/state/BlockchainUpdaterImpl.scala +++ b/node/src/main/scala/com/wavesplatform/state/BlockchainUpdaterImpl.scala @@ -347,12 +347,15 @@ class BlockchainUpdaterImpl( ) miner.scheduleMining(Some(tempBlockchain)) + log.trace( + s"Persisting block ${referencedForgedBlock.id()}, discarded microblock refs: ${discarded.map(_._1.reference).mkString("[", ",", "]")}" + ) + if (discarded.nonEmpty) { blockchainUpdateTriggers.onMicroBlockRollback(this, block.header.reference) metrics.microBlockForkStats.increment() metrics.microBlockForkHeightStats.record(discarded.size) } - blockchainUpdateTriggers.onProcessBlock(block, differResult.keyBlockSnapshot, reward, hitSource, this) rocksdb.append( liquidSnapshotWithCancelledLeases, @@ -365,6 +368,7 @@ class BlockchainUpdaterImpl( ) BlockStats.appended(referencedForgedBlock, referencedLiquidSnapshot.scriptsComplexity) TxsInBlockchainStats.record(ng.transactions.size) + blockchainUpdateTriggers.onProcessBlock(block, differResult.keyBlockSnapshot, reward, hitSource, rocksdb) val (discardedMbs, discardedSnapshots) = discarded.unzip if (discardedMbs.nonEmpty) { log.trace(s"Discarded microblocks: $discardedMbs") @@ -627,7 +631,8 @@ class BlockchainUpdaterImpl( override def wavesAmount(height: Int): BigInt = readLock { ngState match { case Some(ng) if this.height == height => - rocksdb.wavesAmount(height - 1) + BigInt(ng.reward.getOrElse(0L)) + rocksdb.wavesAmount(height - 1) + + BigInt(ng.reward.getOrElse(0L)) * this.blockRewardBoost(height) case _ => rocksdb.wavesAmount(height) } diff --git a/node/src/main/scala/com/wavesplatform/state/DataEntry.scala b/node/src/main/scala/com/wavesplatform/state/DataEntry.scala index d4c4558fd5..d827c4d176 100644 --- a/node/src/main/scala/com/wavesplatform/state/DataEntry.scala +++ b/node/src/main/scala/com/wavesplatform/state/DataEntry.scala @@ -89,20 +89,20 @@ object DataEntry { gen.writeStartObject() value match { case BinaryDataEntry(key, value) => - gen.writeStringField("type", "binary") gen.writeStringField("key", key) + gen.writeStringField("type", "binary") gen.writeStringField("value", value.base64) case IntegerDataEntry(key, value) => - gen.writeStringField("type", "integer") gen.writeStringField("key", key) + gen.writeStringField("type", "integer") gen.writeNumberField("value", value, numberAsString) case BooleanDataEntry(key, value) => - gen.writeStringField("type", "boolean") gen.writeStringField("key", key) + gen.writeStringField("type", "boolean") gen.writeBooleanField("value", value) case StringDataEntry(key, value) => - gen.writeStringField("type", "string") gen.writeStringField("key", key) + gen.writeStringField("type", "string") gen.writeStringField("value", value) case EmptyDataEntry(key) => gen.writeStringField("key", key) diff --git a/node/src/main/scala/com/wavesplatform/state/SnapshotBlockchain.scala b/node/src/main/scala/com/wavesplatform/state/SnapshotBlockchain.scala index d379243af3..183a9df3f0 100644 --- a/node/src/main/scala/com/wavesplatform/state/SnapshotBlockchain.scala +++ b/node/src/main/scala/com/wavesplatform/state/SnapshotBlockchain.scala @@ -141,7 +141,7 @@ case class SnapshotBlockchain( snapshot.orderFills.getOrElse(orderId, inner.filledVolumeAndFee(orderId)) override def balanceAtHeight(address: Address, h: Int, assetId: Asset = Waves): Option[(Int, Long)] = - if (maybeSnapshot.isEmpty || h < this.height) { + if (maybeSnapshot.forall(!_.balances.contains(address -> assetId)) || h < this.height) { inner.balanceAtHeight(address, h, assetId) } else { val balance = this.balance(address, assetId) diff --git a/node/src/main/scala/com/wavesplatform/state/diffs/invoke/InvokeScriptDiff.scala b/node/src/main/scala/com/wavesplatform/state/diffs/invoke/InvokeScriptDiff.scala index 427ae759f8..5ed706179d 100644 --- a/node/src/main/scala/com/wavesplatform/state/diffs/invoke/InvokeScriptDiff.scala +++ b/node/src/main/scala/com/wavesplatform/state/diffs/invoke/InvokeScriptDiff.scala @@ -28,7 +28,6 @@ import com.wavesplatform.metrics.* import com.wavesplatform.state.* import com.wavesplatform.state.diffs.BalanceDiffValidation import com.wavesplatform.state.diffs.invoke.CallArgumentPolicy.* -import com.wavesplatform.state.SnapshotBlockchain import com.wavesplatform.transaction.Asset.{IssuedAsset, Waves} import com.wavesplatform.transaction.TxValidationError.* import com.wavesplatform.transaction.smart.DAppEnvironment.ActionLimits @@ -217,6 +216,13 @@ object InvokeScriptDiff { wrapDAppEnv )) for { + _ <- + if ( + blockchain.height >= blockchain.settings.functionalitySettings.paymentsCheckHeight && blockchain + .isFeatureActivated(BlockchainFeatures.LightNode) + ) + validateIntermediateBalances(blockchain, paymentsPartInsideDApp, 0, Nil) + else traced(Right(())) evaluated <- CoevalR( evaluateV2( version, diff --git a/node/src/main/scala/com/wavesplatform/transaction/EthABIConverter.scala b/node/src/main/scala/com/wavesplatform/transaction/EthABIConverter.scala index e8dcbfe69d..806a6b57a6 100644 --- a/node/src/main/scala/com/wavesplatform/transaction/EthABIConverter.scala +++ b/node/src/main/scala/com/wavesplatform/transaction/EthABIConverter.scala @@ -40,9 +40,9 @@ final case class EthABIConverter(script: Script) { ): Either[ValidationError, (List[EVALUATED], Seq[InvokeScriptTransaction.Payment])] = { val arr = FastHex.decode(data) val func = new Function(ethSignature) - val tuple = func.decodeCall(arr) + val tuple: Tuple = func.decodeCall(arr) - tuple.asScala.toList + (tuple: java.lang.Iterable[AnyRef]).asScala.toList .zip(args.map(_.rideType) :+ EthABIConverter.PaymentListType) .traverse { case (ethArg, rideT) => EthABIConverter.toRideValue(ethArg, rideT) } .flatMap(checkLen(func, tuple, arr.length, blockchain).as(_)) diff --git a/node/src/main/scala/com/wavesplatform/transaction/smart/Verifier.scala b/node/src/main/scala/com/wavesplatform/transaction/smart/Verifier.scala index 2c220a1da8..c9a989f446 100644 --- a/node/src/main/scala/com/wavesplatform/transaction/smart/Verifier.scala +++ b/node/src/main/scala/com/wavesplatform/transaction/smart/Verifier.scala @@ -62,7 +62,7 @@ object Verifier extends ScorexLogging { if (limitedExecution) ContractLimits.FailFreeInvokeComplexity else Int.MaxValue, enableExecutionLog ) - case (tx: SigProofsSwitch, Some(_)) if tx.usesLegacySignature => + case (sps: SigProofsSwitch, Some(_)) if sps.usesLegacySignature => Left(GenericError("Can't process transaction with signature from scripted account")) case (_: PaymentTransaction, Some(_)) => Left(GenericError("Can't process transaction with signature from scripted account")) diff --git a/node/src/main/scala/com/wavesplatform/transaction/smart/script/ScriptCompiler.scala b/node/src/main/scala/com/wavesplatform/transaction/smart/script/ScriptCompiler.scala index a225952a44..c09bbcf3a6 100644 --- a/node/src/main/scala/com/wavesplatform/transaction/smart/script/ScriptCompiler.scala +++ b/node/src/main/scala/com/wavesplatform/transaction/smart/script/ScriptCompiler.scala @@ -8,7 +8,7 @@ import com.wavesplatform.lang.v1.estimator.ScriptEstimator import com.wavesplatform.lang.{API, CompileResult} object ScriptCompiler { - @Deprecated + @deprecated("use ScriptCompiler.compile instead", "1.0") def apply( scriptText: String, isAssetScript: Boolean, diff --git a/node/src/main/scala/com/wavesplatform/transaction/smart/script/trace/TraceStep.scala b/node/src/main/scala/com/wavesplatform/transaction/smart/script/trace/TraceStep.scala index bf70d8a85d..fc5bcc4f6c 100644 --- a/node/src/main/scala/com/wavesplatform/transaction/smart/script/trace/TraceStep.scala +++ b/node/src/main/scala/com/wavesplatform/transaction/smart/script/trace/TraceStep.scala @@ -112,7 +112,7 @@ object TraceStep { private def errorJson(e: ValidationError): JsObject = e match { case see: ScriptExecutionError => Json.obj(logJson(see.log), "error" -> see.message) case tne: TransactionNotAllowedByScript => Json.obj(logJson(tne.log), "error" -> JsNull) - case fte: FailedTransactionError => Json.obj(logJson(fte.log), "error" -> fte.error.map(JsString)) + case fte: FailedTransactionError => Json.obj(logJson(fte.log), "error" -> fte.error.map(JsString.apply)) case a => Json.obj("error" -> a.toString) } diff --git a/node/src/main/scala/com/wavesplatform/transaction/utils/Signed.scala b/node/src/main/scala/com/wavesplatform/transaction/utils/Signed.scala index 6c64283ebd..52762c9fbd 100644 --- a/node/src/main/scala/com/wavesplatform/transaction/utils/Signed.scala +++ b/node/src/main/scala/com/wavesplatform/transaction/utils/Signed.scala @@ -6,7 +6,7 @@ import com.wavesplatform.lang.script.Script import com.wavesplatform.lang.v1.compiler.Terms import com.wavesplatform.transaction.assets.IssueTransaction import com.wavesplatform.transaction.smart.{InvokeScriptTransaction, SetScriptTransaction} -import com.wavesplatform.transaction.{Asset, Proofs, TxTimestamp} +import com.wavesplatform.transaction.{Asset, Proofs, TxTimestamp, TransactionSignOps} object Signed { def invokeScript( diff --git a/node/src/main/scala/com/wavesplatform/utils/UtilApp.scala b/node/src/main/scala/com/wavesplatform/utils/UtilApp.scala index c46f87e406..8e4a0802a1 100644 --- a/node/src/main/scala/com/wavesplatform/utils/UtilApp.scala +++ b/node/src/main/scala/com/wavesplatform/utils/UtilApp.scala @@ -7,10 +7,10 @@ import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.{Base58, Base64, FastBase58} import com.wavesplatform.features.EstimatorProvider.* import com.wavesplatform.lang.script.{Script, ScriptReader} -import com.wavesplatform.settings.WavesSettings +import com.wavesplatform.settings.{WalletSettings, WavesSettings} import com.wavesplatform.transaction.TxValidationError.GenericError import com.wavesplatform.transaction.smart.script.ScriptCompiler -import com.wavesplatform.transaction.{Transaction, TransactionFactory, TransactionType} +import com.wavesplatform.transaction.{Transaction, TransactionFactory, TransactionSignOps, TransactionType} import com.wavesplatform.wallet.Wallet import com.wavesplatform.{Application, Version} import play.api.libs.json.{JsObject, Json} @@ -19,6 +19,7 @@ import scopt.OParser import java.io.{ByteArrayInputStream, File, FileInputStream, FileOutputStream} import java.nio.charset.StandardCharsets import java.nio.file.{Files, Paths} +import scala.annotation.nowarn //noinspection ScalaStyle // TODO: Consider remove implemented methods from REST API @@ -41,6 +42,7 @@ object UtilApp { case class VerifyOptions(publicKey: PublicKey = null, signature: ByteStr = ByteStr.empty, checkWeakPk: Boolean = false) case class HashOptions(mode: String = "fast") case class SignTxOptions(signerAddress: String = "") + case class KeyPairOptions(seedType: String = "account", nonce: Int = 0) sealed trait Input object Input { @@ -49,6 +51,8 @@ object UtilApp { final case class Str(str: String) extends Input } + sealed trait SeedType + case class Command( mode: Command.Mode = null, configFile: Option[String] = None, @@ -60,14 +64,15 @@ object UtilApp { signOptions: SignOptions = SignOptions(), verifyOptions: VerifyOptions = VerifyOptions(), hashOptions: HashOptions = HashOptions(), - signTxOptions: SignTxOptions = SignTxOptions() + signTxOptions: SignTxOptions = SignTxOptions(), + keyPairOptions: KeyPairOptions = KeyPairOptions() ) def main(args: Array[String]): Unit = { OParser.parse(commandParser, args, Command()) match { case Some(cmd) => val settings = Application.loadApplicationConfig(cmd.configFile.map(new File(_))) - val inBytes = IO.readInput(cmd) + val inBytes = IO.readInput(cmd) val result = { val doAction = cmd.mode match { case Command.CompileScript => Actions.doCompile(settings) _ @@ -182,6 +187,16 @@ object UtilApp { cmd("create-keys") .text("Generate key pair from seed") .action((_, c) => c.copy(mode = Command.CreateKeyPair)) + .children( + opt[String]("seed-type") + .validate { + case "account" | "wallet" => success + case _ => failure("Invalid seed format") + } + .action((t, c) => c.copy(keyPairOptions = c.keyPairOptions.copy(seedType = t))), + opt[Int]("nonce") + .action((n, c) => c.copy(keyPairOptions = c.keyPairOptions.copy(nonce = n))) + ) ), cmd("transaction").children( cmd("serialize") @@ -224,7 +239,7 @@ object UtilApp { private[this] object Actions { type ActionResult = Either[String, Array[Byte]] - // noinspection ScalaDeprecation + @nowarn("cat=deprecation") def doCompile(settings: WavesSettings)(c: Command, str: Array[Byte]): ActionResult = { ScriptCompiler(new String(str), c.compileOptions.assetScript, settings.estimator) .map(_._1.bytes().arr) @@ -250,12 +265,29 @@ object UtilApp { "Invalid signature" ) - def doCreateKeyPair(c: Command, data: Array[Byte]): ActionResult = - KeyPair - .fromSeed(new String(data)) - .left + def doCreateKeyPair(c: Command, data: Array[Byte]): ActionResult = { + import com.wavesplatform.utils.byteStrFormat + (c.keyPairOptions.seedType match { + case "account" => + KeyPair.fromSeed(new String(data)) + case "wallet" => + Wallet(WalletSettings(None, Some("123"), Some(ByteStr(data)))) + .generateNewAccount(c.keyPairOptions.nonce) + .toRight("Could not generate account") + }).left .map(_.toString) - .map(kp => Json.toBytes(Json.toJson(kp))) + .map(kp => + Json.toBytes( + Json.obj( + "publicKey" -> kp.publicKey, + "privateKey" -> kp.privateKey, + "address" -> kp.publicKey.toAddress, + "walletSeed" -> ByteStr(data), + "nonce" -> c.keyPairOptions.nonce + ) + ) + ) + } def doHash(c: Command, data: Array[Byte]): ActionResult = c.hashOptions.mode match { case "fast" => Right(com.wavesplatform.crypto.fastHash(data)) diff --git a/node/src/test/scala/com/wavesplatform/network/peer/PeerDatabaseImplSpecification.scala b/node/src/test/scala/com/wavesplatform/network/peer/PeerDatabaseImplSpecification.scala deleted file mode 100644 index bb7715d09c..0000000000 --- a/node/src/test/scala/com/wavesplatform/network/peer/PeerDatabaseImplSpecification.scala +++ /dev/null @@ -1,195 +0,0 @@ -package com.wavesplatform.network.peer - -import java.io.File -import java.net.InetSocketAddress -import java.nio.file.Files - -import com.typesafe.config.ConfigFactory -import com.wavesplatform.network.{PeerDatabase, PeerDatabaseImpl} -import com.wavesplatform.settings.NetworkSettings -import com.wavesplatform.test.FreeSpec -import net.ceedubs.ficus.Ficus.* - -class PeerDatabaseImplSpecification extends FreeSpec { - - val host1 = "1.1.1.1" - val host2 = "2.2.2.2" - val address1 = new InetSocketAddress(host1, 1) - val address2 = new InetSocketAddress(host2, 2) - - private val config1 = ConfigFactory - .parseString("""waves.network { - | file = null - | known-peers = [] - | peers-data-residence-time: 2s - |}""".stripMargin) - .withFallback(ConfigFactory.load()) - .resolve() - private val settings1 = config1.as[NetworkSettings]("waves.network") - - private val config2 = ConfigFactory - .parseString("""waves.network { - | file = null - | known-peers = [] - | peers-data-residence-time = 10s - |}""".stripMargin) - .withFallback(ConfigFactory.load()) - .resolve() - private val settings2 = config2.as[NetworkSettings]("waves.network") - - private val config3 = ConfigFactory - .parseString(s"""waves.network { - | file = null - | known-peers = ["$host1:1"] - | peers-data-residence-time = 2s - | enable-peers-exchange = no - |}""".stripMargin) - .withFallback(ConfigFactory.load()) - .resolve() - private val settings3 = config3.as[NetworkSettings]("waves.network") - - private def withDatabase(settings: NetworkSettings)(f: PeerDatabase => Unit): Unit = { - val pdb = new PeerDatabaseImpl(settings) - f(pdb) - pdb.close() - } - - "Peer database" - { - "new peer should not appear in internal buffer but does not appear in database" in withDatabase(settings1) { database => - database.knownPeers shouldBe empty - database.addCandidate(address1) - database.randomPeer(Set()) should contain(address1) - database.knownPeers shouldBe empty - } - - "new peer should move from internal buffer to database" in withDatabase(settings1) { database => - database.knownPeers shouldBe empty - database.addCandidate(address1) - database.knownPeers shouldBe empty - database.touch(address1) - database.knownPeers.keys should contain(address1) - } - - "peer should should became obsolete after time" in withDatabase(settings1) { database => - database.touch(address1) - database.knownPeers.keys should contain(address1) - sleepLong() - database.knownPeers shouldBe empty - database.randomPeer(Set()) shouldBe empty - } - - "known-peers should be always in database" in withDatabase(settings3) { database3 => - database3.knownPeers.keys should contain(address1) - sleepLong() - database3.knownPeers.keys should contain(address1) - sleepShort() - database3.knownPeers.keys should contain(address1) - } - - "touching peer prevent it from obsoleting" in withDatabase(settings1) { database => - database.addCandidate(address1) - database.touch(address1) - sleepLong() - database.touch(address1) - sleepShort() - database.knownPeers.keys should contain(address1) - } - - "blacklisted peer should disappear from internal buffer and database" in withDatabase(settings1) { database => - database.touch(address1) - database.addCandidate(address2) - database.knownPeers.keys should contain(address1) - database.knownPeers.keys should not contain address2 - - database.blacklist(address1.getAddress, "") - database.knownPeers.keys should not contain address1 - database.knownPeers should be(empty) - - database.randomPeer(Set()) should contain(address2) - database.blacklist(address2.getAddress, "") - database.randomPeer(Set()) should not contain address2 - database.randomPeer(Set()) should be(empty) - } - - "random peer should return peers from both from database and buffer" in withDatabase(settings2) { database2 => - database2.touch(address1) - database2.addCandidate(address2) - val keys = database2.knownPeers.keys - keys should contain(address1) - keys should not contain address2 - - val set = (1 to 10).flatMap(i => database2.randomPeer(Set())).toSet - - set should contain(address1) - set should contain(address2) - } - - "filters out excluded candidates" in withDatabase(settings1) { database => - database.addCandidate(address1) - database.addCandidate(address1) - database.addCandidate(address2) - - database.randomPeer(Set(address1)) should contain(address2) - } - - "filters out wildcard addresses" in withDatabase(settings1) { database => - database.addCandidate(new InetSocketAddress("0.0.0.0", 6863)) - database.randomPeer(Set(address1, address2)) shouldBe None - } - - "if blacklisting is disabled" - { - "should clear blacklist at start" in { - val databaseFile = Files.createTempFile("waves-tests", "PeerDatabaseImplSpecification-blacklisting-clear").toAbsolutePath.toString - val path = if (File.separatorChar == '\\') databaseFile.replace('\\', '/') else databaseFile - val prevConfig = ConfigFactory - .parseString(s"""waves.network { - | file = "$path" - | known-peers = [] - | peers-data-residence-time = 100s - |}""".stripMargin) - .withFallback(ConfigFactory.load()) - .resolve() - val prevSettings = prevConfig.as[NetworkSettings]("waves.network") - val prevDatabase = new PeerDatabaseImpl(prevSettings) - prevDatabase.blacklist(address1.getAddress, "I don't like it") - prevDatabase.close() - - val config = ConfigFactory - .parseString(s"""waves.network { - | file = "$path" - | known-peers = [] - | peers-data-residence-time = 100s - | enable-blacklisting = no - |}""".stripMargin) - .withFallback(ConfigFactory.load()) - .resolve() - val settings = config.as[NetworkSettings]("waves.network") - val database = new PeerDatabaseImpl(settings) - - database.blacklistedHosts shouldBe empty - } - - "should not add nodes to the blacklist" in { - val config = ConfigFactory - .parseString(s"""waves.network { - | file = null - | known-peers = [] - | peers-data-residence-time = 100s - | enable-blacklisting = no - |}""".stripMargin) - .withFallback(ConfigFactory.load()) - .resolve() - val settings = config.as[NetworkSettings]("waves.network") - val database = new PeerDatabaseImpl(settings) - database.blacklist(address1.getAddress, "I don't like it") - - database.blacklistedHosts shouldBe empty - } - } - } - - private def sleepLong() = Thread.sleep(2200) - - private def sleepShort() = Thread.sleep(200) - -} diff --git a/node/testkit/build.sbt b/node/testkit/build.sbt new file mode 100644 index 0000000000..11b4405d36 --- /dev/null +++ b/node/testkit/build.sbt @@ -0,0 +1,17 @@ +publishTo := sonatypePublishToBundle.value +publish / skip := false +homepage := Some(url("https://waves.tech/")) +developers := List( + Developer("ismagin", "Ilya Smagin", "ilya.smagin@gmail.com", url("https://github.com/ismagin")), + Developer("asayadyan", "Artyom Sayadyan", "xrtm000@gmail.com", url("https://github.com/xrtm000")), + Developer("mpotanin", "Mike Potanin", "mpotanin@wavesplatform.com", url("https://github.com/potan")), + Developer("irakitnykh", "Ivan Rakitnykh", "mrkr.reg@gmail.com", url("https://github.com/mrkraft")), + Developer("akiselev", "Alexey Kiselev", "alexey.kiselev@gmail.com>", url("https://github.com/alexeykiselev")), + Developer("phearnot", "Sergey Nazarov", "snazarov@web3tech.ru", url("https://github.com/phearnot")), + Developer("tolsi", "Sergey Tolmachev", "tolsi.ru@gmail.com", url("https://github.com/tolsi")), + Developer("vsuharnikov", "Vyatcheslav Suharnikov", "arz.freezy@gmail.com", url("https://github.com/vsuharnikov")), + Developer("ivan-mashonskiy", "Ivan Mashonskii", "ivan.mashonsky@gmail.com", url("https://github.com/ivan-mashonskiy")) +) + +Compile / packageDoc / publishArtifact := true +Test / packageDoc / publishArtifact := false diff --git a/node/src/test/scala/com/wavesplatform/EitherMatchers.scala b/node/testkit/src/main/scala/com/wavesplatform/EitherMatchers.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/EitherMatchers.scala rename to node/testkit/src/main/scala/com/wavesplatform/EitherMatchers.scala diff --git a/node/src/test/scala/com/wavesplatform/NTPTime.scala b/node/testkit/src/main/scala/com/wavesplatform/NTPTime.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/NTPTime.scala rename to node/testkit/src/main/scala/com/wavesplatform/NTPTime.scala diff --git a/node/src/test/scala/com/wavesplatform/TestHelpers.scala b/node/testkit/src/main/scala/com/wavesplatform/TestHelpers.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/TestHelpers.scala rename to node/testkit/src/main/scala/com/wavesplatform/TestHelpers.scala diff --git a/node/src/test/scala/com/wavesplatform/TestValues.scala b/node/testkit/src/main/scala/com/wavesplatform/TestValues.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/TestValues.scala rename to node/testkit/src/main/scala/com/wavesplatform/TestValues.scala diff --git a/node/src/test/scala/com/wavesplatform/TransactionGen.scala b/node/testkit/src/main/scala/com/wavesplatform/TransactionGen.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/TransactionGen.scala rename to node/testkit/src/main/scala/com/wavesplatform/TransactionGen.scala diff --git a/node/src/test/scala/com/wavesplatform/database/TestStorageFactory.scala b/node/testkit/src/main/scala/com/wavesplatform/database/TestStorageFactory.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/database/TestStorageFactory.scala rename to node/testkit/src/main/scala/com/wavesplatform/database/TestStorageFactory.scala diff --git a/node/src/test/scala/com/wavesplatform/db/DBCacheSettings.scala b/node/testkit/src/main/scala/com/wavesplatform/db/DBCacheSettings.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/db/DBCacheSettings.scala rename to node/testkit/src/main/scala/com/wavesplatform/db/DBCacheSettings.scala diff --git a/node/src/test/scala/com/wavesplatform/db/WithState.scala b/node/testkit/src/main/scala/com/wavesplatform/db/WithState.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/db/WithState.scala rename to node/testkit/src/main/scala/com/wavesplatform/db/WithState.scala diff --git a/node/src/test/scala/com/wavesplatform/history/Domain.scala b/node/testkit/src/main/scala/com/wavesplatform/history/Domain.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/history/Domain.scala rename to node/testkit/src/main/scala/com/wavesplatform/history/Domain.scala diff --git a/node/src/test/scala/com/wavesplatform/history/MicroBlockWithTotalId.scala b/node/testkit/src/main/scala/com/wavesplatform/history/MicroBlockWithTotalId.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/history/MicroBlockWithTotalId.scala rename to node/testkit/src/main/scala/com/wavesplatform/history/MicroBlockWithTotalId.scala diff --git a/node/src/test/scala/com/wavesplatform/history/package.scala b/node/testkit/src/main/scala/com/wavesplatform/history/package.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/history/package.scala rename to node/testkit/src/main/scala/com/wavesplatform/history/package.scala diff --git a/node/src/test/scala/com/wavesplatform/lagonaki/mocks/TestBlock.scala b/node/testkit/src/main/scala/com/wavesplatform/lagonaki/mocks/TestBlock.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/lagonaki/mocks/TestBlock.scala rename to node/testkit/src/main/scala/com/wavesplatform/lagonaki/mocks/TestBlock.scala diff --git a/node/src/test/scala/com/wavesplatform/settings/TestFunctionalitySettings.scala b/node/testkit/src/main/scala/com/wavesplatform/settings/TestFunctionalitySettings.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/settings/TestFunctionalitySettings.scala rename to node/testkit/src/main/scala/com/wavesplatform/settings/TestFunctionalitySettings.scala diff --git a/node/src/test/scala/com/wavesplatform/settings/TestSettings.scala b/node/testkit/src/main/scala/com/wavesplatform/settings/TestSettings.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/settings/TestSettings.scala rename to node/testkit/src/main/scala/com/wavesplatform/settings/TestSettings.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/SnapshotProduceError.scala b/node/testkit/src/main/scala/com/wavesplatform/state/diffs/SnapshotProduceError.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/SnapshotProduceError.scala rename to node/testkit/src/main/scala/com/wavesplatform/state/diffs/SnapshotProduceError.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/package.scala b/node/testkit/src/main/scala/com/wavesplatform/state/diffs/package.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/package.scala rename to node/testkit/src/main/scala/com/wavesplatform/state/diffs/package.scala diff --git a/node/src/test/scala/com/wavesplatform/state/utils/package.scala b/node/testkit/src/main/scala/com/wavesplatform/state/utils/package.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/utils/package.scala rename to node/testkit/src/main/scala/com/wavesplatform/state/utils/package.scala diff --git a/node/src/test/scala/com/wavesplatform/test/DomainPresets.scala b/node/testkit/src/main/scala/com/wavesplatform/test/DomainPresets.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/test/DomainPresets.scala rename to node/testkit/src/main/scala/com/wavesplatform/test/DomainPresets.scala diff --git a/node/src/test/scala/com/wavesplatform/test/TestTime.scala b/node/testkit/src/main/scala/com/wavesplatform/test/TestTime.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/test/TestTime.scala rename to node/testkit/src/main/scala/com/wavesplatform/test/TestTime.scala diff --git a/node/src/test/scala/com/wavesplatform/test/specs.scala b/node/testkit/src/main/scala/com/wavesplatform/test/specs.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/test/specs.scala rename to node/testkit/src/main/scala/com/wavesplatform/test/specs.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/TxHelpers.scala b/node/testkit/src/main/scala/com/wavesplatform/transaction/TxHelpers.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/TxHelpers.scala rename to node/testkit/src/main/scala/com/wavesplatform/transaction/TxHelpers.scala diff --git a/node/src/test/scala/com/wavesplatform/utils/EmptyBlockchain.scala b/node/testkit/src/main/scala/com/wavesplatform/utils/EmptyBlockchain.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/utils/EmptyBlockchain.scala rename to node/testkit/src/main/scala/com/wavesplatform/utils/EmptyBlockchain.scala diff --git a/node/src/test/scala/com/wavesplatform/utils/SystemTime.scala b/node/testkit/src/main/scala/com/wavesplatform/utils/SystemTime.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/utils/SystemTime.scala rename to node/testkit/src/main/scala/com/wavesplatform/utils/SystemTime.scala diff --git a/node/src/test/resources/application.conf b/node/tests/src/test/resources/application.conf similarity index 83% rename from node/src/test/resources/application.conf rename to node/tests/src/test/resources/application.conf index 98841a94ec..04c4959d8c 100644 --- a/node/src/test/resources/application.conf +++ b/node/tests/src/test/resources/application.conf @@ -14,3 +14,9 @@ waves { } } } + +akka { + stdout-loglevel = "OFF" + loglevel = "OFF" + loggers = [] +} diff --git a/node/src/test/resources/genesis.dev.conf b/node/tests/src/test/resources/genesis.dev.conf similarity index 100% rename from node/src/test/resources/genesis.dev.conf rename to node/tests/src/test/resources/genesis.dev.conf diff --git a/node/src/test/resources/genesis.example.conf b/node/tests/src/test/resources/genesis.example.conf similarity index 100% rename from node/src/test/resources/genesis.example.conf rename to node/tests/src/test/resources/genesis.example.conf diff --git a/node/src/test/resources/genesis.it.conf b/node/tests/src/test/resources/genesis.it.conf similarity index 100% rename from node/src/test/resources/genesis.it.conf rename to node/tests/src/test/resources/genesis.it.conf diff --git a/node/src/test/resources/genesis.mainnet.conf b/node/tests/src/test/resources/genesis.mainnet.conf similarity index 100% rename from node/src/test/resources/genesis.mainnet.conf rename to node/tests/src/test/resources/genesis.mainnet.conf diff --git a/node/src/test/resources/logback-test.xml b/node/tests/src/test/resources/logback-test.xml similarity index 100% rename from node/src/test/resources/logback-test.xml rename to node/tests/src/test/resources/logback-test.xml diff --git a/node/src/test/resources/vrf-pos.json b/node/tests/src/test/resources/vrf-pos.json similarity index 100% rename from node/src/test/resources/vrf-pos.json rename to node/tests/src/test/resources/vrf-pos.json diff --git a/node/src/test/scala/com/wavesplatform/BlockGen.scala b/node/tests/src/test/scala/com/wavesplatform/BlockGen.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/BlockGen.scala rename to node/tests/src/test/scala/com/wavesplatform/BlockGen.scala diff --git a/node/src/test/scala/com/wavesplatform/BlockchainStubHelpers.scala b/node/tests/src/test/scala/com/wavesplatform/BlockchainStubHelpers.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/BlockchainStubHelpers.scala rename to node/tests/src/test/scala/com/wavesplatform/BlockchainStubHelpers.scala diff --git a/node/src/test/scala/com/wavesplatform/BlocksTransactionsHelpers.scala b/node/tests/src/test/scala/com/wavesplatform/BlocksTransactionsHelpers.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/BlocksTransactionsHelpers.scala rename to node/tests/src/test/scala/com/wavesplatform/BlocksTransactionsHelpers.scala diff --git a/node/src/test/scala/com/wavesplatform/DeserializationTests.scala b/node/tests/src/test/scala/com/wavesplatform/DeserializationTests.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/DeserializationTests.scala rename to node/tests/src/test/scala/com/wavesplatform/DeserializationTests.scala diff --git a/node/src/test/scala/com/wavesplatform/RequestGen.scala b/node/tests/src/test/scala/com/wavesplatform/RequestGen.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/RequestGen.scala rename to node/tests/src/test/scala/com/wavesplatform/RequestGen.scala diff --git a/node/src/test/scala/com/wavesplatform/RxScheduler.scala b/node/tests/src/test/scala/com/wavesplatform/RxScheduler.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/RxScheduler.scala rename to node/tests/src/test/scala/com/wavesplatform/RxScheduler.scala diff --git a/node/src/test/scala/com/wavesplatform/TestWallet.scala b/node/tests/src/test/scala/com/wavesplatform/TestWallet.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/TestWallet.scala rename to node/tests/src/test/scala/com/wavesplatform/TestWallet.scala diff --git a/node/src/test/scala/com/wavesplatform/WithNewDBForEachTest.scala b/node/tests/src/test/scala/com/wavesplatform/WithNewDBForEachTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/WithNewDBForEachTest.scala rename to node/tests/src/test/scala/com/wavesplatform/WithNewDBForEachTest.scala diff --git a/node/src/test/scala/com/wavesplatform/account/AccountOrAliasSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/account/AccountOrAliasSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/account/AccountOrAliasSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/account/AccountOrAliasSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/account/AccountOrAliasTests.scala b/node/tests/src/test/scala/com/wavesplatform/account/AccountOrAliasTests.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/account/AccountOrAliasTests.scala rename to node/tests/src/test/scala/com/wavesplatform/account/AccountOrAliasTests.scala diff --git a/node/src/test/scala/com/wavesplatform/account/AccountSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/account/AccountSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/account/AccountSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/account/AccountSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/account/AliasSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/account/AliasSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/account/AliasSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/account/AliasSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/api/common/AddressTransactionsSpec.scala b/node/tests/src/test/scala/com/wavesplatform/api/common/AddressTransactionsSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/common/AddressTransactionsSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/api/common/AddressTransactionsSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/api/common/CommonAccountApiSpec.scala b/node/tests/src/test/scala/com/wavesplatform/api/common/CommonAccountApiSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/common/CommonAccountApiSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/api/common/CommonAccountApiSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/api/common/CommonTransactionsApiSpec.scala b/node/tests/src/test/scala/com/wavesplatform/api/common/CommonTransactionsApiSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/common/CommonTransactionsApiSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/api/common/CommonTransactionsApiSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/api/eth/EthRpcRouteSpec.scala b/node/tests/src/test/scala/com/wavesplatform/api/eth/EthRpcRouteSpec.scala similarity index 97% rename from node/src/test/scala/com/wavesplatform/api/eth/EthRpcRouteSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/api/eth/EthRpcRouteSpec.scala index b50558097b..877ae3af80 100644 --- a/node/src/test/scala/com/wavesplatform/api/eth/EthRpcRouteSpec.scala +++ b/node/tests/src/test/scala/com/wavesplatform/api/eth/EthRpcRouteSpec.scala @@ -27,7 +27,7 @@ class EthRpcRouteSpec extends RouteSpec("/eth") with WithDomain with EthHelpers Post( routePath(""), Json.obj("method" -> method, "params" -> Json.arr(params*), "id" -> "test") - ) ~> new EthRpcRoute(d.blockchain, d.commonApi.transactions, ntpTime).route ~> check(body) + ).~>(new EthRpcRoute(d.blockchain, d.commonApi.transactions, ntpTime).route) ~> check(body) } "eth_chainId" in withDomain(DefaultWavesSettings) { d => @@ -327,14 +327,14 @@ class EthRpcRouteSpec extends RouteSpec("/eth") with WithDomain with EthHelpers "absence of id" in withDomain() { d => Post(routePath(""), Json.obj("method" -> "eth_chainId")) - ~> new EthRpcRoute(d.blockchain, d.commonApi.transactions, ntpTime).route - ~> check { responseAs[JsObject] shouldBe Json.obj("id" -> null, "jsonrpc" -> "2.0", "result" -> "0x54") } + .~>(new EthRpcRoute(d.blockchain, d.commonApi.transactions, ntpTime).route) + .~>(check{ responseAs[JsObject] shouldBe Json.obj("id" -> null, "jsonrpc" -> "2.0", "result" -> "0x54") }) } "absence of method" in withDomain() { d => Post(routePath(""), Json.obj()) - ~> new EthRpcRoute(d.blockchain, d.commonApi.transactions, ntpTime).route - ~> check { responseAs[JsObject] shouldBe Json.obj() } + .~>(new EthRpcRoute(d.blockchain, d.commonApi.transactions, ntpTime).route) + .~>(check { responseAs[JsObject] shouldBe Json.obj() }) } def resultJson: JsObject = (responseAs[JsObject] \ "result").as[JsObject] diff --git a/node/src/test/scala/com/wavesplatform/api/http/ApiRouteSpec.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/ApiRouteSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/ApiRouteSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/ApiRouteSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/CustomJsonMarshallerSpec.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/CustomJsonMarshallerSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/CustomJsonMarshallerSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/CustomJsonMarshallerSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/RouteTimeoutTest.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/RouteTimeoutTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/RouteTimeoutTest.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/RouteTimeoutTest.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/TraceResultJsonTest.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/TraceResultJsonTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/TraceResultJsonTest.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/TraceResultJsonTest.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/BurnV1Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/BurnV1Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/BurnV1Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/BurnV1Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/BurnV2Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/BurnV2Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/BurnV2Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/BurnV2Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/CreateAliasV1Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/CreateAliasV1Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/CreateAliasV1Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/CreateAliasV1Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/CreateAliasV2Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/CreateAliasV2Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/CreateAliasV2Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/CreateAliasV2Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/IssueV1Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/IssueV1Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/IssueV1Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/IssueV1Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/IssueV2Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/IssueV2Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/IssueV2Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/IssueV2Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/LeaseCancelV1Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/LeaseCancelV1Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/LeaseCancelV1Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/LeaseCancelV1Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/LeaseCancelV2Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/LeaseCancelV2Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/LeaseCancelV2Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/LeaseCancelV2Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/LeaseV1Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/LeaseV1Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/LeaseV1Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/LeaseV1Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/LeaseV2Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/LeaseV2Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/LeaseV2Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/LeaseV2Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/ReissueV1Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/ReissueV1Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/ReissueV1Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/ReissueV1Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/ReissueV2Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/ReissueV2Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/ReissueV2Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/ReissueV2Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/RequestsSpec.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/RequestsSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/RequestsSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/RequestsSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/SignedBurnV1Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedBurnV1Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/SignedBurnV1Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedBurnV1Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/SignedBurnV2Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedBurnV2Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/SignedBurnV2Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedBurnV2Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/SignedCreateAliasV1Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedCreateAliasV1Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/SignedCreateAliasV1Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedCreateAliasV1Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/SignedCreateAliasV2Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedCreateAliasV2Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/SignedCreateAliasV2Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedCreateAliasV2Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/SignedExchangeRequest.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedExchangeRequest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/SignedExchangeRequest.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedExchangeRequest.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/SignedExchangeRequestV2.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedExchangeRequestV2.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/SignedExchangeRequestV2.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedExchangeRequestV2.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/SignedIssueV1Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedIssueV1Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/SignedIssueV1Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedIssueV1Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/SignedIssueV2Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedIssueV2Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/SignedIssueV2Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedIssueV2Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/SignedLeaseCancelV1Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedLeaseCancelV1Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/SignedLeaseCancelV1Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedLeaseCancelV1Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/SignedLeaseCancelV2Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedLeaseCancelV2Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/SignedLeaseCancelV2Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedLeaseCancelV2Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/SignedLeaseV1Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedLeaseV1Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/SignedLeaseV1Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedLeaseV1Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/SignedLeaseV2Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedLeaseV2Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/SignedLeaseV2Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedLeaseV2Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/SignedReissueV1Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedReissueV1Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/SignedReissueV1Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedReissueV1Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/SignedReissueV2Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedReissueV2Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/SignedReissueV2Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedReissueV2Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/SignedTransferV1Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedTransferV1Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/SignedTransferV1Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedTransferV1Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/SignedTransferV2Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedTransferV2Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/SignedTransferV2Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/SignedTransferV2Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/TransferV1Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/TransferV1Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/TransferV1Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/TransferV1Request.scala diff --git a/node/src/test/scala/com/wavesplatform/api/http/requests/TransferV2Request.scala b/node/tests/src/test/scala/com/wavesplatform/api/http/requests/TransferV2Request.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/api/http/requests/TransferV2Request.scala rename to node/tests/src/test/scala/com/wavesplatform/api/http/requests/TransferV2Request.scala diff --git a/node/src/test/scala/com/wavesplatform/block/TransactionsRootSpec.scala b/node/tests/src/test/scala/com/wavesplatform/block/TransactionsRootSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/block/TransactionsRootSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/block/TransactionsRootSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/code/DirectiveSetConstructingTest.scala b/node/tests/src/test/scala/com/wavesplatform/code/DirectiveSetConstructingTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/code/DirectiveSetConstructingTest.scala rename to node/tests/src/test/scala/com/wavesplatform/code/DirectiveSetConstructingTest.scala diff --git a/node/src/test/scala/com/wavesplatform/code/PartialUnificationTests.scala b/node/tests/src/test/scala/com/wavesplatform/code/PartialUnificationTests.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/code/PartialUnificationTests.scala rename to node/tests/src/test/scala/com/wavesplatform/code/PartialUnificationTests.scala diff --git a/node/src/test/scala/com/wavesplatform/consensus/FPPoSSelectorTest.scala b/node/tests/src/test/scala/com/wavesplatform/consensus/FPPoSSelectorTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/consensus/FPPoSSelectorTest.scala rename to node/tests/src/test/scala/com/wavesplatform/consensus/FPPoSSelectorTest.scala diff --git a/node/src/test/scala/com/wavesplatform/consensus/FairPoSCalculatorTest.scala b/node/tests/src/test/scala/com/wavesplatform/consensus/FairPoSCalculatorTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/consensus/FairPoSCalculatorTest.scala rename to node/tests/src/test/scala/com/wavesplatform/consensus/FairPoSCalculatorTest.scala diff --git a/node/src/test/scala/com/wavesplatform/consensus/nxt/TransactionsOrderingSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/consensus/nxt/TransactionsOrderingSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/consensus/nxt/TransactionsOrderingSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/consensus/nxt/TransactionsOrderingSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/crypto/SigningFunctionsSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/crypto/SigningFunctionsSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/crypto/SigningFunctionsSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/crypto/SigningFunctionsSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/database/RocksDBWriterSpec.scala b/node/tests/src/test/scala/com/wavesplatform/database/RocksDBWriterSpec.scala similarity index 85% rename from node/src/test/scala/com/wavesplatform/database/RocksDBWriterSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/database/RocksDBWriterSpec.scala index 64b96624e8..18d85a5245 100644 --- a/node/src/test/scala/com/wavesplatform/database/RocksDBWriterSpec.scala +++ b/node/tests/src/test/scala/com/wavesplatform/database/RocksDBWriterSpec.scala @@ -300,6 +300,46 @@ class RocksDBWriterSpec extends FreeSpec with WithDomain { nonHistoricalKeys should contain theSameElementsInOrderAs nonHistoricalKeysWithoutCleanup } } + + "balanceAtHeight returns correct values" in { + val richAccount = TxHelpers.signer(1001) + val account1 = TxHelpers.signer(1002) + val account2 = TxHelpers.signer(1003) + withDomain(DomainPresets.TransactionStateSnapshot, Seq(AddrWithBalance(richAccount.toAddress, 10_000.waves))) { d => + val issueTx = TxHelpers.issue(richAccount, amount = 10000, decimals = 2.toByte, name = "IA01") + d.appendBlock(issueTx) + (1 to 3).foreach(_ => d.appendBlock()) + d.blockchain.height shouldBe 5 + + d.appendBlock(TxHelpers.transfer(richAccount, account1.toAddress, 10.waves)) + d.appendBlock(TxHelpers.transfer(richAccount, account1.toAddress, 100, asset = issueTx.asset)) + d.appendBlock() + d.appendBlock(TxHelpers.transfer(richAccount, account1.toAddress, 1.waves)) + d.appendBlock(TxHelpers.transfer(richAccount, account1.toAddress, 500, asset = issueTx.asset)) + d.blockchain.height shouldBe 10 + + d.blockchain.balanceAtHeight(account1.toAddress, 10) shouldBe Some(9 -> 11.waves) + d.blockchain.balanceAtHeight(account1.toAddress, 9) shouldBe Some(9 -> 11.waves) + d.blockchain.balanceAtHeight(account1.toAddress, 8) shouldBe Some(6 -> 10.waves) + d.blockchain.balanceAtHeight(account1.toAddress, 6) shouldBe Some(6 -> 10.waves) + d.blockchain.balanceAtHeight(account1.toAddress, 5) shouldBe None + + d.blockchain.balanceAtHeight(account1.toAddress, 10, issueTx.asset) shouldBe Some(10 -> 600) + d.blockchain.balanceAtHeight(account1.toAddress, 9, issueTx.asset) shouldBe Some(7 -> 100) + d.blockchain.balanceAtHeight(account1.toAddress, 8, issueTx.asset) shouldBe Some(7 -> 100) + d.blockchain.balanceAtHeight(account1.toAddress, 6, issueTx.asset) shouldBe None + + d.appendBlock(TxHelpers.transfer(richAccount, account2.toAddress, 20.waves)) + d.appendBlock(TxHelpers.transfer(richAccount, account2.toAddress, 700, issueTx.asset)) + + d.blockchain.balanceAtHeight(account2.toAddress, 12) shouldBe Some(11 -> 20.waves) + d.blockchain.balanceAtHeight(account2.toAddress, 11) shouldBe Some(11 -> 20.waves) + d.blockchain.balanceAtHeight(account2.toAddress, 10) shouldBe None + + d.blockchain.balanceAtHeight(account2.toAddress, 12, issueTx.asset) shouldBe Some(12 -> 700) + d.blockchain.balanceAtHeight(account2.toAddress, 11, issueTx.asset) shouldBe None + } + } } private val HistoricalKeyTags = Seq( diff --git a/node/src/test/scala/com/wavesplatform/db/InterferableDB.scala b/node/tests/src/test/scala/com/wavesplatform/db/InterferableDB.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/db/InterferableDB.scala rename to node/tests/src/test/scala/com/wavesplatform/db/InterferableDB.scala diff --git a/node/src/test/scala/com/wavesplatform/db/ScriptCacheTest.scala b/node/tests/src/test/scala/com/wavesplatform/db/ScriptCacheTest.scala similarity index 98% rename from node/src/test/scala/com/wavesplatform/db/ScriptCacheTest.scala rename to node/tests/src/test/scala/com/wavesplatform/db/ScriptCacheTest.scala index 520c0db373..ab2d8acd55 100644 --- a/node/src/test/scala/com/wavesplatform/db/ScriptCacheTest.scala +++ b/node/tests/src/test/scala/com/wavesplatform/db/ScriptCacheTest.scala @@ -24,14 +24,14 @@ class ScriptCacheTest extends FreeSpec with WithNewDBForEachTest { val AMOUNT = 10000000000L val FEE = 5000000 + def mkScripts(num: Int): List[(Script, Long)] = { (0 until num).map { ind => - ScriptCompiler( + ScriptCompiler.compile( s""" |let ind = $ind |true """.stripMargin, - isAssetScript = false, ScriptEstimatorV2 ).explicitGet() }.toList diff --git a/node/src/test/scala/com/wavesplatform/db/TxBloomFilterSpec.scala b/node/tests/src/test/scala/com/wavesplatform/db/TxBloomFilterSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/db/TxBloomFilterSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/db/TxBloomFilterSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/features/FeatureProviderTest.scala b/node/tests/src/test/scala/com/wavesplatform/features/FeatureProviderTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/features/FeatureProviderTest.scala rename to node/tests/src/test/scala/com/wavesplatform/features/FeatureProviderTest.scala diff --git a/node/src/test/scala/com/wavesplatform/features/RideV5LimitsChangeTest.scala b/node/tests/src/test/scala/com/wavesplatform/features/RideV5LimitsChangeTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/features/RideV5LimitsChangeTest.scala rename to node/tests/src/test/scala/com/wavesplatform/features/RideV5LimitsChangeTest.scala diff --git a/node/src/test/scala/com/wavesplatform/features/RideV6FailRejectTest.scala b/node/tests/src/test/scala/com/wavesplatform/features/RideV6FailRejectTest.scala similarity index 99% rename from node/src/test/scala/com/wavesplatform/features/RideV6FailRejectTest.scala rename to node/tests/src/test/scala/com/wavesplatform/features/RideV6FailRejectTest.scala index a3d1f9edf9..e20fe526d5 100644 --- a/node/src/test/scala/com/wavesplatform/features/RideV6FailRejectTest.scala +++ b/node/tests/src/test/scala/com/wavesplatform/features/RideV6FailRejectTest.scala @@ -18,7 +18,7 @@ import com.wavesplatform.transaction.assets.IssueTransaction import com.wavesplatform.transaction.smart.InvokeScriptTransaction import com.wavesplatform.transaction.smart.InvokeScriptTransaction.Payment import com.wavesplatform.transaction.utils.EthConverters.* -import com.wavesplatform.transaction.{EthTxGenerator, EthereumTransaction, Transaction, TxHelpers, TxVersion} +import com.wavesplatform.transaction.{EthTxGenerator, EthereumTransaction, Transaction, TxHelpers, TxVersion, TransactionSignOps} import org.scalatest.{EitherValues, OptionValues} import java.nio.charset.StandardCharsets diff --git a/node/src/test/scala/com/wavesplatform/history/BlockRewardSpec.scala b/node/tests/src/test/scala/com/wavesplatform/history/BlockRewardSpec.scala similarity index 92% rename from node/src/test/scala/com/wavesplatform/history/BlockRewardSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/history/BlockRewardSpec.scala index 1ace799fb1..a14ee7d4d3 100644 --- a/node/src/test/scala/com/wavesplatform/history/BlockRewardSpec.scala +++ b/node/tests/src/test/scala/com/wavesplatform/history/BlockRewardSpec.scala @@ -1,13 +1,14 @@ package com.wavesplatform.history import cats.syntax.option.* -import com.wavesplatform.account.KeyPair +import com.wavesplatform.account.{Address, KeyPair} import com.wavesplatform.api.http.RewardApiRoute import com.wavesplatform.block.Block import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.EitherExt2 -import com.wavesplatform.database.Keys +import com.wavesplatform.database.{Keys, DBExt} import com.wavesplatform.db.WithDomain +import com.wavesplatform.db.WithState.AddrWithBalance import com.wavesplatform.features.BlockchainFeatures import com.wavesplatform.features.BlockchainFeatures.{BlockReward, BlockRewardDistribution, ConsensusImprovements} import com.wavesplatform.history.Domain.BlockchainUpdaterExt @@ -16,12 +17,13 @@ import com.wavesplatform.mining.MiningConstraint import com.wavesplatform.settings.{Constants, FunctionalitySettings, RewardsSettings} import com.wavesplatform.state.diffs.BlockDiffer import com.wavesplatform.state.{BlockRewardCalculator, Blockchain, Height} -import com.wavesplatform.test.DomainPresets.{RideV6, WavesSettingsOps, BlockRewardDistribution as BlockRewardDistributionSettings} import com.wavesplatform.test.* +import com.wavesplatform.test.DomainPresets.{RideV6, WavesSettingsOps, BlockRewardDistribution as BlockRewardDistributionSettings} import com.wavesplatform.transaction.Asset.Waves import com.wavesplatform.transaction.transfer.TransferTransaction import com.wavesplatform.transaction.{GenesisTransaction, TxHelpers} import org.scalacheck.Gen +import org.scalactic.source.Position class BlockRewardSpec extends FreeSpec with WithDomain { @@ -1307,4 +1309,126 @@ class BlockRewardSpec extends FreeSpec with WithDomain { minerReward shouldBe fullBlockReward - daoAddressReward - xtnBuybackAddressReward } } + + private val daoAddress = TxHelpers.address(10002) + private val xtnBuybackAddress = TxHelpers.address(10003) + private val settingsWithRewardBoost = DomainPresets.BlockRewardDistribution + .setFeaturesHeight( + BlockchainFeatures.CappedReward -> 0, + BlockchainFeatures.BoostBlockReward -> 5 + ) + .configure(fs => + fs.copy( + blockRewardBoostPeriod = 10, + daoAddress = Some(daoAddress.toString), + xtnBuybackAddress = Some(xtnBuybackAddress.toString) + ) + ) + + private val blockMiner = TxHelpers.signer(10001) + private val initialMinerBalance = 100_000.waves + + private def assertBalances(blockchain: Blockchain, expectedBalances: (Address, Long)*)(implicit pos: Position): Unit = + expectedBalances.foreach { case (address, balance) => + withClue(address) { + blockchain.balance(address) shouldEqual balance + } + } + + "Boost block reward:" - { + "block reward is" - { + "increased after feature activation" in boostBlockRewardActivationScenario(0.5.waves, 2.waves) + "decreased after feature activation" in boostBlockRewardActivationScenario(-0.5.waves, 3.5.waves / 2) + "unchanged after feature activation" in boostBlockRewardActivationScenario(0, 2.waves) + } + } + + private def boostBlockRewardActivationScenario( + rewardDelta: Long, + addressShareAfterChange: Long + ): Unit = withDomain( + settingsWithRewardBoost.copy(blockchainSettings = + settingsWithRewardBoost.blockchainSettings.copy( + rewardsSettings = RewardsSettings(10, 10, 6.waves, 0.5.waves, 4) + ) + ), + Seq(AddrWithBalance(blockMiner.toAddress, initialMinerBalance)) + ) { d => + val minerRewardAfterChange = 2.waves + rewardDelta.max(0) + + (1 to 3).foreach(_ => d.appendKeyBlock(blockMiner)) + // height 4: before activation + d.blockchain.height shouldBe 4 + assertBalances( + d.blockchain, + blockMiner.toAddress -> (initialMinerBalance + 2.waves * 3), + daoAddress -> 2.waves * 3, + xtnBuybackAddress -> 2.waves * 3 + ) + + d.appendKeyBlock(blockMiner) + // height 5: activation height + val rewardAtActivationHeight = 2.waves * 3 + 2.waves * 10 + d.blockchain.height shouldBe 5 + assertBalances( + d.blockchain, + blockMiner.toAddress -> (initialMinerBalance + 2.waves * (3 + 10)), + daoAddress -> rewardAtActivationHeight, + xtnBuybackAddress -> rewardAtActivationHeight + ) + + d.appendKeyBlock(blockMiner) + // height 7: start voting + (1 to 3).foreach(_ => + d.appendBlock(d.createBlock(Block.RewardBlockVersion, Seq.empty, generator = blockMiner, rewardVote = 6.waves + rewardDelta)) + ) + d.blockchain.height shouldBe 9 + val rewardBeforeIncrease = rewardAtActivationHeight + 4 * 2.waves * 10 + assertBalances( + d.blockchain, + blockMiner.toAddress -> (initialMinerBalance + 2.waves * (3 + 10 * 5)), + daoAddress -> rewardBeforeIncrease, + xtnBuybackAddress -> rewardBeforeIncrease + ) + + // height 10: new base reward value = 65 waves + d.appendBlock(d.createBlock(Block.RewardBlockVersion, Seq.empty, generator = blockMiner, rewardVote = 7.waves)) + d.blockchain.height shouldBe 10 + val rewardAfterIncrease = rewardBeforeIncrease + addressShareAfterChange * 10 + assertBalances( + d.blockchain, + blockMiner.toAddress -> (initialMinerBalance + 2.waves * (3 + 10 * 5) + minerRewardAfterChange * 10), + daoAddress -> rewardAfterIncrease, + xtnBuybackAddress -> rewardAfterIncrease + ) + + (1 to 4).foreach(_ => d.appendKeyBlock(blockMiner)) + // height 14: before deactivation + d.blockchain.height shouldBe 14 + val rewardBeforeDeactivation = rewardAfterIncrease + 4 * addressShareAfterChange * 10 + assertBalances( + d.blockchain, + blockMiner.toAddress -> (initialMinerBalance + 2.waves * (3 + 10 * 5) + minerRewardAfterChange * 10 * 5), + daoAddress -> rewardBeforeDeactivation, + xtnBuybackAddress -> rewardBeforeDeactivation + ) + + d.appendKeyBlock(blockMiner) + // height 15: deactivation + d.blockchain.height shouldBe 15 + val rewardAfterDeactivation = rewardBeforeDeactivation + addressShareAfterChange + assertBalances( + d.blockchain, + blockMiner.toAddress -> (initialMinerBalance + 2.waves * (3 + 10 * 5) + minerRewardAfterChange * (10 * 5 + 1)), + daoAddress -> rewardAfterDeactivation, + xtnBuybackAddress -> rewardAfterDeactivation + ) + + d.blockchain.wavesAmount(15) shouldBe + BigInt(100_000_000.waves + // 1: genesis + 3 * 6.waves + // 2..4: before boost activation + 5 * 60.waves + // 5..9: boosted reward before change + 5 * (6.waves + rewardDelta) * 10 + // 10..14: boosted reward after change + 6.waves + rewardDelta) // 15: non-boosted after change + } } diff --git a/node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterBadReferencesTest.scala b/node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterBadReferencesTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterBadReferencesTest.scala rename to node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterBadReferencesTest.scala diff --git a/node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterBlockMicroblockSequencesSameTransactionsTest.scala b/node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterBlockMicroblockSequencesSameTransactionsTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterBlockMicroblockSequencesSameTransactionsTest.scala rename to node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterBlockMicroblockSequencesSameTransactionsTest.scala diff --git a/node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterBlockOnlyTest.scala b/node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterBlockOnlyTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterBlockOnlyTest.scala rename to node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterBlockOnlyTest.scala diff --git a/node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterBurnTest.scala b/node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterBurnTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterBurnTest.scala rename to node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterBurnTest.scala diff --git a/node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterGeneratorFeeNextBlockOrMicroBlockTest.scala b/node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterGeneratorFeeNextBlockOrMicroBlockTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterGeneratorFeeNextBlockOrMicroBlockTest.scala rename to node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterGeneratorFeeNextBlockOrMicroBlockTest.scala diff --git a/node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterGeneratorFeeSameBlockTest.scala b/node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterGeneratorFeeSameBlockTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterGeneratorFeeSameBlockTest.scala rename to node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterGeneratorFeeSameBlockTest.scala diff --git a/node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterInMemoryDiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterInMemoryDiffTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterInMemoryDiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterInMemoryDiffTest.scala diff --git a/node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterKeyAndMicroBlockConflictTest.scala b/node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterKeyAndMicroBlockConflictTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterKeyAndMicroBlockConflictTest.scala rename to node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterKeyAndMicroBlockConflictTest.scala diff --git a/node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterLiquidBlockTest.scala b/node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterLiquidBlockTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterLiquidBlockTest.scala rename to node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterLiquidBlockTest.scala diff --git a/node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterMicroblockBadSignaturesTest.scala b/node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterMicroblockBadSignaturesTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterMicroblockBadSignaturesTest.scala rename to node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterMicroblockBadSignaturesTest.scala diff --git a/node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterMicroblockSunnyDayTest.scala b/node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterMicroblockSunnyDayTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterMicroblockSunnyDayTest.scala rename to node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterMicroblockSunnyDayTest.scala diff --git a/node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterNFTTest.scala b/node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterNFTTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterNFTTest.scala rename to node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterNFTTest.scala diff --git a/node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterSponsoredFeeBlockTest.scala b/node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterSponsoredFeeBlockTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/history/BlockchainUpdaterSponsoredFeeBlockTest.scala rename to node/tests/src/test/scala/com/wavesplatform/history/BlockchainUpdaterSponsoredFeeBlockTest.scala diff --git a/node/src/test/scala/com/wavesplatform/history/DomainScenarioDrivenPropertyCheck.scala b/node/tests/src/test/scala/com/wavesplatform/history/DomainScenarioDrivenPropertyCheck.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/history/DomainScenarioDrivenPropertyCheck.scala rename to node/tests/src/test/scala/com/wavesplatform/history/DomainScenarioDrivenPropertyCheck.scala diff --git a/node/src/test/scala/com/wavesplatform/history/LeasingExpirySpec.scala b/node/tests/src/test/scala/com/wavesplatform/history/LeasingExpirySpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/history/LeasingExpirySpec.scala rename to node/tests/src/test/scala/com/wavesplatform/history/LeasingExpirySpec.scala diff --git a/node/src/test/scala/com/wavesplatform/http/AddressRouteSpec.scala b/node/tests/src/test/scala/com/wavesplatform/http/AddressRouteSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/http/AddressRouteSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/http/AddressRouteSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/http/ApiErrorMatchers.scala b/node/tests/src/test/scala/com/wavesplatform/http/ApiErrorMatchers.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/http/ApiErrorMatchers.scala rename to node/tests/src/test/scala/com/wavesplatform/http/ApiErrorMatchers.scala diff --git a/node/src/test/scala/com/wavesplatform/http/AssetsRouteSpec.scala b/node/tests/src/test/scala/com/wavesplatform/http/AssetsRouteSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/http/AssetsRouteSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/http/AssetsRouteSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/http/BlocksApiRouteSpec.scala b/node/tests/src/test/scala/com/wavesplatform/http/BlocksApiRouteSpec.scala similarity index 87% rename from node/src/test/scala/com/wavesplatform/http/BlocksApiRouteSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/http/BlocksApiRouteSpec.scala index 594765c03f..9a50e1c125 100644 --- a/node/src/test/scala/com/wavesplatform/http/BlocksApiRouteSpec.scala +++ b/node/tests/src/test/scala/com/wavesplatform/http/BlocksApiRouteSpec.scala @@ -19,10 +19,11 @@ import com.wavesplatform.state.{BlockRewardCalculator, Blockchain} import com.wavesplatform.test.* import com.wavesplatform.test.DomainPresets.* import com.wavesplatform.transaction.Asset.Waves -import com.wavesplatform.transaction.{TxHelpers, TxVersion} import com.wavesplatform.transaction.assets.exchange.{Order, OrderType} +import com.wavesplatform.transaction.{TxHelpers, TxVersion} import com.wavesplatform.utils.{SharedSchedulerMixin, SystemTime} import monix.reactive.Observable +import org.scalactic.source.Position import org.scalamock.scalatest.PathMockFactory import org.scalatest.Assertion import play.api.libs.json.* @@ -504,4 +505,78 @@ class BlocksApiRouteSpec .toMap shouldBe heightToResult } } + + "Boost block reward feature changes API response" in { + val miner = TxHelpers.signer(3001) + val daoAddress = TxHelpers.address(3002) + val xtnAddress = TxHelpers.address(3003) + + val settings = DomainPresets.ConsensusImprovements + .setFeaturesHeight( + BlockchainFeatures.BlockRewardDistribution -> 0, + BlockchainFeatures.CappedReward -> 0, + BlockchainFeatures.BoostBlockReward -> 5, + BlockchainFeatures.CeaseXtnBuyback -> 0 + ) + .configure(fs => + fs.copy( + xtnBuybackRewardPeriod = 10, + blockRewardBoostPeriod = 10, + xtnBuybackAddress = Some(xtnAddress.toString), + daoAddress = Some(daoAddress.toString) + ) + ) + + withDomain(settings, Seq(AddrWithBalance(miner.toAddress, 100_000.waves))) { d => + val route = new BlocksApiRoute(d.settings.restAPISettings, d.blocksApi, SystemTime, new RouteTimeout(60.seconds)(sharedScheduler)).route + + def checkRewardAndShares(height: Int, expectedReward: Long, expectedMinerShare: Long, expectedDaoShare: Long, expectedXtnShare: Option[Long])( + implicit pos: Position + ): Unit = { + Seq("/headers/at/", "/at/").foreach { prefix => + val path = routePath(s"$prefix$height") + withClue(path) { + Get(path) ~> route ~> check { + val jsonResp = responseAs[JsObject] + withClue(" reward:") { + (jsonResp \ "reward").as[Long] shouldBe expectedReward + } + val shares = (jsonResp \ "rewardShares").as[JsObject] + withClue(" miner share: ") { + (shares \ miner.toAddress.toString).as[Long] shouldBe expectedMinerShare + } + withClue(" dao share: ") { + (shares \ daoAddress.toString).as[Long] shouldBe expectedDaoShare + } + withClue(" XTN share: ") { + (shares \ xtnAddress.toString).asOpt[Long] shouldBe expectedXtnShare + } + } + } + } + } + + (1 to 3).foreach(_ => d.appendKeyBlock(miner)) + d.blockchain.height shouldBe 4 + (1 to 3).foreach { h => + checkRewardAndShares(h + 1, 6.waves, 2.waves, 2.waves, Some(2.waves)) + } + + // reward boost activation + (1 to 5).foreach(_ => d.appendKeyBlock(miner)) + (1 to 5).foreach { h => + checkRewardAndShares(h + 4, 60.waves, 20.waves, 20.waves, Some(20.waves)) + } + + // cease XTN buyback + (1 to 5).foreach(_ => d.appendKeyBlock(miner)) + (1 to 5).foreach { h => + checkRewardAndShares(h + 9, 60.waves, 40.waves, 20.waves, None) + } + + d.appendKeyBlock(miner) + d.blockchain.height shouldBe 15 + checkRewardAndShares(15, 6.waves, 4.waves, 2.waves, None) + } + } } diff --git a/node/src/test/scala/com/wavesplatform/http/DebugApiRouteSpec.scala b/node/tests/src/test/scala/com/wavesplatform/http/DebugApiRouteSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/http/DebugApiRouteSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/http/DebugApiRouteSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/http/DummyTransactionPublisher.scala b/node/tests/src/test/scala/com/wavesplatform/http/DummyTransactionPublisher.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/http/DummyTransactionPublisher.scala rename to node/tests/src/test/scala/com/wavesplatform/http/DummyTransactionPublisher.scala diff --git a/node/src/test/scala/com/wavesplatform/http/LeaseRouteSpec.scala b/node/tests/src/test/scala/com/wavesplatform/http/LeaseRouteSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/http/LeaseRouteSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/http/LeaseRouteSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/http/PeersRouteSpec.scala b/node/tests/src/test/scala/com/wavesplatform/http/PeersRouteSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/http/PeersRouteSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/http/PeersRouteSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/http/ProtoVersionTransactionsSpec.scala b/node/tests/src/test/scala/com/wavesplatform/http/ProtoVersionTransactionsSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/http/ProtoVersionTransactionsSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/http/ProtoVersionTransactionsSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/http/RestAPISettingsHelper.scala b/node/tests/src/test/scala/com/wavesplatform/http/RestAPISettingsHelper.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/http/RestAPISettingsHelper.scala rename to node/tests/src/test/scala/com/wavesplatform/http/RestAPISettingsHelper.scala diff --git a/node/src/test/scala/com/wavesplatform/http/RewardApiRouteSpec.scala b/node/tests/src/test/scala/com/wavesplatform/http/RewardApiRouteSpec.scala similarity index 76% rename from node/src/test/scala/com/wavesplatform/http/RewardApiRouteSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/http/RewardApiRouteSpec.scala index eaa56c17ae..53e9edd916 100644 --- a/node/src/test/scala/com/wavesplatform/http/RewardApiRouteSpec.scala +++ b/node/tests/src/test/scala/com/wavesplatform/http/RewardApiRouteSpec.scala @@ -3,12 +3,15 @@ package com.wavesplatform.http import com.wavesplatform.account.Address import com.wavesplatform.api.http.RewardApiRoute import com.wavesplatform.db.WithDomain +import com.wavesplatform.db.WithState.AddrWithBalance import com.wavesplatform.features.BlockchainFeatures import com.wavesplatform.history.Domain import com.wavesplatform.settings.WavesSettings +import com.wavesplatform.test.* import com.wavesplatform.test.DomainPresets.* import com.wavesplatform.transaction.TxHelpers -import play.api.libs.json.JsValue +import org.scalactic.source.Position +import play.api.libs.json.{JsObject, JsValue} class RewardApiRouteSpec extends RouteSpec("/blockchain") with WithDomain { @@ -166,4 +169,67 @@ class RewardApiRouteSpec extends RouteSpec("/blockchain") with WithDomain { (response \ "nextCheck").as[Int] shouldBe expectedNextCheck } } + + "Boost block reward feature changes API response" in { + val miner = TxHelpers.signer(3001) + val daoAddress = TxHelpers.address(3002) + val xtnAddress = TxHelpers.address(3003) + + val settings = DomainPresets.ConsensusImprovements + .setFeaturesHeight( + BlockchainFeatures.BlockRewardDistribution -> 0, + BlockchainFeatures.CappedReward -> 0, + BlockchainFeatures.BoostBlockReward -> 5, + BlockchainFeatures.CeaseXtnBuyback -> 0 + ) + .configure(fs => + fs.copy( + xtnBuybackRewardPeriod = 10, + blockRewardBoostPeriod = 10, + xtnBuybackAddress = Some(xtnAddress.toString), + daoAddress = Some(daoAddress.toString) + ) + ) + + withDomain(settings, Seq(AddrWithBalance(miner.toAddress, 100_000.waves))) { d => + val route = new RewardApiRoute(d.blockchain).route + + def checkRewardAndShares(height: Int, expectedReward: Long, expectedMinerShare: Long, expectedDaoShare: Long, expectedXtnShare: Option[Long])( + implicit pos: Position + ): Unit = { + + val path = routePath(s"/rewards/$height") + withClue(path) { + Get(path) ~> route ~> check { + val jsonResp = responseAs[JsObject] + withClue(" reward:") { + (jsonResp \ "currentReward").as[Long] shouldBe expectedReward + } + } + } + } + + (1 to 3).foreach(_ => d.appendKeyBlock(miner)) + d.blockchain.height shouldBe 4 + (1 to 3).foreach { h => + checkRewardAndShares(h + 1, 6.waves, 2.waves, 2.waves, Some(2.waves)) + } + + // reward boost activation + (1 to 5).foreach(_ => d.appendKeyBlock(miner)) + (1 to 5).foreach { h => + checkRewardAndShares(h + 4, 60.waves, 20.waves, 20.waves, Some(20.waves)) + } + + // cease XTN buyback + (1 to 5).foreach(_ => d.appendKeyBlock(miner)) + (1 to 5).foreach { h => + checkRewardAndShares(h + 9, 60.waves, 40.waves, 20.waves, None) + } + + d.appendKeyBlock(miner) + d.blockchain.height shouldBe 15 + checkRewardAndShares(15, 6.waves, 4.waves, 2.waves, None) + } + } } diff --git a/node/src/test/scala/com/wavesplatform/http/RouteSpec.scala b/node/tests/src/test/scala/com/wavesplatform/http/RouteSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/http/RouteSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/http/RouteSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/http/SpentComplexitySpec.scala b/node/tests/src/test/scala/com/wavesplatform/http/SpentComplexitySpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/http/SpentComplexitySpec.scala rename to node/tests/src/test/scala/com/wavesplatform/http/SpentComplexitySpec.scala diff --git a/node/src/test/scala/com/wavesplatform/http/TransactionBroadcastSpec.scala b/node/tests/src/test/scala/com/wavesplatform/http/TransactionBroadcastSpec.scala similarity index 99% rename from node/src/test/scala/com/wavesplatform/http/TransactionBroadcastSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/http/TransactionBroadcastSpec.scala index b805111e91..37b6eca666 100644 --- a/node/src/test/scala/com/wavesplatform/http/TransactionBroadcastSpec.scala +++ b/node/tests/src/test/scala/com/wavesplatform/http/TransactionBroadcastSpec.scala @@ -19,7 +19,7 @@ import com.wavesplatform.transaction.smart.InvokeScriptTransaction import com.wavesplatform.transaction.smart.InvokeScriptTransaction.Payment import com.wavesplatform.transaction.smart.script.ScriptCompiler import com.wavesplatform.transaction.smart.script.trace.{AccountVerifierTrace, TracedResult} -import com.wavesplatform.transaction.{Asset, AssetIdLength, Proofs, TxHelpers, TxPositiveAmount, TxVersion} +import com.wavesplatform.transaction.{Asset, AssetIdLength, Proofs, TxHelpers, TxPositiveAmount, TxVersion, TransactionSignOps} import com.wavesplatform.utils.{EthEncoding, EthHelpers, SharedSchedulerMixin} import com.wavesplatform.wallet.Wallet import org.scalamock.scalatest.PathMockFactory diff --git a/node/src/test/scala/com/wavesplatform/http/TransactionSnapshotsRouteSpec.scala b/node/tests/src/test/scala/com/wavesplatform/http/TransactionSnapshotsRouteSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/http/TransactionSnapshotsRouteSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/http/TransactionSnapshotsRouteSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/http/TransactionsRouteSpec.scala b/node/tests/src/test/scala/com/wavesplatform/http/TransactionsRouteSpec.scala similarity index 99% rename from node/src/test/scala/com/wavesplatform/http/TransactionsRouteSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/http/TransactionsRouteSpec.scala index 3b836b31dc..5a10e2d231 100644 --- a/node/src/test/scala/com/wavesplatform/http/TransactionsRouteSpec.scala +++ b/node/tests/src/test/scala/com/wavesplatform/http/TransactionsRouteSpec.scala @@ -30,7 +30,7 @@ import com.wavesplatform.transaction.smart.script.trace.AccountVerifierTrace import com.wavesplatform.transaction.transfer.TransferTransaction import com.wavesplatform.transaction.utils.EthConverters.* import com.wavesplatform.transaction.utils.Signed -import com.wavesplatform.transaction.{Asset, AssetIdLength, EthTxGenerator, TxHelpers, TxVersion} +import com.wavesplatform.transaction.{Asset, AssetIdLength, EthTxGenerator, TxHelpers, TxVersion, TransactionSignOps} import com.wavesplatform.utils.{EthEncoding, EthHelpers, SharedSchedulerMixin} import com.wavesplatform.{BlockGen, TestValues, crypto} import org.scalacheck.Gen.* diff --git a/node/src/test/scala/com/wavesplatform/http/UtilsRouteEvaluateSpec.scala b/node/tests/src/test/scala/com/wavesplatform/http/UtilsRouteEvaluateSpec.scala similarity index 99% rename from node/src/test/scala/com/wavesplatform/http/UtilsRouteEvaluateSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/http/UtilsRouteEvaluateSpec.scala index 8c29c457c3..8ca754e69d 100644 --- a/node/src/test/scala/com/wavesplatform/http/UtilsRouteEvaluateSpec.scala +++ b/node/tests/src/test/scala/com/wavesplatform/http/UtilsRouteEvaluateSpec.scala @@ -488,7 +488,7 @@ class UtilsRouteEvaluateSpec Post(routePath(s"/script/evaluate/$defaultAddress"), Json.obj("call" -> Json.obj("function" -> 1))) ~> route ~> check { val json = responseAs[JsValue] (json \ "message").as[String] shouldBe "failed to parse json message" - (json \ "validationErrors") match { + json \ "validationErrors" match { case JsDefined(validationErrors) => validationErrors should matchJson("""{ "obj.call": [ @@ -596,7 +596,7 @@ class UtilsRouteEvaluateSpec if (hasIssuedAsset) d.appendBlock(issueTx) // -1 to test insufficient funds - def collectLessBalance(asset: Asset): Long = paymentAssetWithAmounts.collect { case (a, x) if a == asset => x }.sum - 1 + def collectLessBalance(asset: Asset): Long = paymentAssetWithAmounts.collect { case (`asset`, x) => x }.sum - 1 val blockchainOverrides = Json.obj( "accounts" -> Json.obj( @@ -651,7 +651,7 @@ class UtilsRouteEvaluateSpec d.appendBlock(setScriptTx) if (hasIssuedAsset) d.appendBlock(issueTx) - def collectBalance(asset: Asset): Long = paymentAssetWithAmounts.collect { case (a, x) if a == asset => x }.sum + def collectBalance(asset: Asset): Long = paymentAssetWithAmounts.collect { case (`asset`, x) => x }.sum val blockchainOverrides = Json.obj( "accounts" -> Json.obj( @@ -749,7 +749,7 @@ class UtilsRouteEvaluateSpec val (invocationFeeInWaves, invocationFeeInAsset) = if (feeAsset == asset) (0, defaultInvocationFee) else (defaultInvocationFee, 0) // -1 to test insufficient funds - def collectLessBalance(asset: Asset): Long = paymentAssetWithAmounts.collect { case (a, x) if a == asset => x }.sum - 1 + def collectLessBalance(asset: Asset): Long = paymentAssetWithAmounts.collect { case (`asset`, x) => x }.sum - 1 val blockchainOverrides = Json.obj( "accounts" -> Json.obj( @@ -843,7 +843,7 @@ class UtilsRouteEvaluateSpec val (invocationFeeInWaves, invocationFeeInAsset) = if (feeAsset == asset) (0, defaultInvocationFee) else (defaultInvocationFee, 0) - def collectBalance(asset: Asset): Long = paymentAssetWithAmounts.collect { case (a, x) if a == asset => x }.sum + def collectBalance(asset: Asset): Long = paymentAssetWithAmounts.collect { case (`asset`, x) => x }.sum val callerWavesBalance = invocationFeeInWaves + collectBalance(Asset.Waves) val callerAssetBalance = invocationFeeInAsset + collectBalance(asset) diff --git a/node/src/test/scala/com/wavesplatform/http/UtilsRouteSpec.scala b/node/tests/src/test/scala/com/wavesplatform/http/UtilsRouteSpec.scala similarity index 99% rename from node/src/test/scala/com/wavesplatform/http/UtilsRouteSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/http/UtilsRouteSpec.scala index 8f2f0d9261..9941601904 100644 --- a/node/src/test/scala/com/wavesplatform/http/UtilsRouteSpec.scala +++ b/node/tests/src/test/scala/com/wavesplatform/http/UtilsRouteSpec.scala @@ -1,5 +1,6 @@ package com.wavesplatform.http +import akka.http.scaladsl.testkit.RouteTestTimeout import com.google.protobuf.ByteString import com.wavesplatform.api.http.ApiError.TooBigArrayAllocation import com.wavesplatform.api.http.requests.ScriptWithImportsRequest @@ -38,6 +39,7 @@ import scala.concurrent.duration.* class UtilsRouteSpec extends RouteSpec("/utils") with RestAPISettingsHelper with PropertyChecks with PathMockFactory with Inside with WithDomain { private val estimator = ScriptEstimatorV2 + protected override implicit val routeTestTimeout: RouteTestTimeout = RouteTestTimeout(20.seconds) private val timeBounded: SchedulerService = Schedulers.timeBoundedFixedPool( new HashedWheelTimer(), @@ -282,8 +284,8 @@ class UtilsRouteSpec extends RouteSpec("/utils") with RestAPISettingsHelper with |{-# CONTENT_TYPE DAPP #-} |{-# SCRIPT_TYPE ACCOUNT #-} | - |let looooooooooooooooooooooooongName = base58'${"a" * 3602}' - |${(1 to 18).map(i => s"let a$i = base58'${"a" * 12200}'").mkString("\n")} + |let looooooooooooooooooooooooongName = base64'${"A" * 3518}' # 2640 bytes + |${(1 to 18).map(i => s"let a$i = base64'${"A" * 11912}'").mkString("\n")} # 18 * 8934 bytes |func test() = looooooooooooooooooooooooongName == looooooooooooooooooooooooongName """.stripMargin diff --git a/node/src/test/scala/com/wavesplatform/http/WalletRouteSpec.scala b/node/tests/src/test/scala/com/wavesplatform/http/WalletRouteSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/http/WalletRouteSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/http/WalletRouteSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/http/package.scala b/node/tests/src/test/scala/com/wavesplatform/http/package.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/http/package.scala rename to node/tests/src/test/scala/com/wavesplatform/http/package.scala diff --git a/node/src/test/scala/com/wavesplatform/it/util/package.scala b/node/tests/src/test/scala/com/wavesplatform/it/util/package.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/it/util/package.scala rename to node/tests/src/test/scala/com/wavesplatform/it/util/package.scala diff --git a/node/src/test/scala/com/wavesplatform/lagonaki/unit/BlockSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/lagonaki/unit/BlockSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/lagonaki/unit/BlockSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/lagonaki/unit/BlockSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/lagonaki/unit/MicroBlockSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/lagonaki/unit/MicroBlockSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/lagonaki/unit/MicroBlockSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/lagonaki/unit/MicroBlockSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/lagonaki/unit/WalletSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/lagonaki/unit/WalletSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/lagonaki/unit/WalletSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/lagonaki/unit/WalletSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/mining/BlockV5Test.scala b/node/tests/src/test/scala/com/wavesplatform/mining/BlockV5Test.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/mining/BlockV5Test.scala rename to node/tests/src/test/scala/com/wavesplatform/mining/BlockV5Test.scala diff --git a/node/src/test/scala/com/wavesplatform/mining/BlockWithMaxBaseTargetTest.scala b/node/tests/src/test/scala/com/wavesplatform/mining/BlockWithMaxBaseTargetTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/mining/BlockWithMaxBaseTargetTest.scala rename to node/tests/src/test/scala/com/wavesplatform/mining/BlockWithMaxBaseTargetTest.scala diff --git a/node/src/test/scala/com/wavesplatform/mining/LightNodeBlockFieldsTest.scala b/node/tests/src/test/scala/com/wavesplatform/mining/LightNodeBlockFieldsTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/mining/LightNodeBlockFieldsTest.scala rename to node/tests/src/test/scala/com/wavesplatform/mining/LightNodeBlockFieldsTest.scala diff --git a/node/src/test/scala/com/wavesplatform/mining/MicroBlockMinerSpec.scala b/node/tests/src/test/scala/com/wavesplatform/mining/MicroBlockMinerSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/mining/MicroBlockMinerSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/mining/MicroBlockMinerSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/mining/MinerAccountScriptRestrictionsTest.scala b/node/tests/src/test/scala/com/wavesplatform/mining/MinerAccountScriptRestrictionsTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/mining/MinerAccountScriptRestrictionsTest.scala rename to node/tests/src/test/scala/com/wavesplatform/mining/MinerAccountScriptRestrictionsTest.scala diff --git a/node/src/test/scala/com/wavesplatform/mining/MinerBalanceOverflowTest.scala b/node/tests/src/test/scala/com/wavesplatform/mining/MinerBalanceOverflowTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/mining/MinerBalanceOverflowTest.scala rename to node/tests/src/test/scala/com/wavesplatform/mining/MinerBalanceOverflowTest.scala diff --git a/node/src/test/scala/com/wavesplatform/mining/MiningFailuresSuite.scala b/node/tests/src/test/scala/com/wavesplatform/mining/MiningFailuresSuite.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/mining/MiningFailuresSuite.scala rename to node/tests/src/test/scala/com/wavesplatform/mining/MiningFailuresSuite.scala diff --git a/node/src/test/scala/com/wavesplatform/mining/MiningWithRewardSuite.scala b/node/tests/src/test/scala/com/wavesplatform/mining/MiningWithRewardSuite.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/mining/MiningWithRewardSuite.scala rename to node/tests/src/test/scala/com/wavesplatform/mining/MiningWithRewardSuite.scala diff --git a/node/src/test/scala/com/wavesplatform/mining/MultiDimensionalMiningConstraintSuite.scala b/node/tests/src/test/scala/com/wavesplatform/mining/MultiDimensionalMiningConstraintSuite.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/mining/MultiDimensionalMiningConstraintSuite.scala rename to node/tests/src/test/scala/com/wavesplatform/mining/MultiDimensionalMiningConstraintSuite.scala diff --git a/node/src/test/scala/com/wavesplatform/mining/OneDimensionalMiningConstraintSuite.scala b/node/tests/src/test/scala/com/wavesplatform/mining/OneDimensionalMiningConstraintSuite.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/mining/OneDimensionalMiningConstraintSuite.scala rename to node/tests/src/test/scala/com/wavesplatform/mining/OneDimensionalMiningConstraintSuite.scala diff --git a/node/src/test/scala/com/wavesplatform/mining/ScriptComplexityMiningConstraintSuite.scala b/node/tests/src/test/scala/com/wavesplatform/mining/ScriptComplexityMiningConstraintSuite.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/mining/ScriptComplexityMiningConstraintSuite.scala rename to node/tests/src/test/scala/com/wavesplatform/mining/ScriptComplexityMiningConstraintSuite.scala diff --git a/node/src/test/scala/com/wavesplatform/mining/package.scala b/node/tests/src/test/scala/com/wavesplatform/mining/package.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/mining/package.scala rename to node/tests/src/test/scala/com/wavesplatform/mining/package.scala diff --git a/node/src/test/scala/com/wavesplatform/network/BasicMessagesRepoSpec.scala b/node/tests/src/test/scala/com/wavesplatform/network/BasicMessagesRepoSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/network/BasicMessagesRepoSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/network/BasicMessagesRepoSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/network/BlacklistParallelSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/network/BlacklistParallelSpecification.scala similarity index 85% rename from node/src/test/scala/com/wavesplatform/network/BlacklistParallelSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/network/BlacklistParallelSpecification.scala index eb0a37d5db..4c86f05d1d 100644 --- a/node/src/test/scala/com/wavesplatform/network/BlacklistParallelSpecification.scala +++ b/node/tests/src/test/scala/com/wavesplatform/network/BlacklistParallelSpecification.scala @@ -1,20 +1,20 @@ package com.wavesplatform.network -import java.net.{InetAddress, InetSocketAddress} - import com.typesafe.config.ConfigFactory import com.wavesplatform.settings.{NetworkSettings, loadConfig} import com.wavesplatform.test.FeatureSpec -import net.ceedubs.ficus.Ficus._ +import net.ceedubs.ficus.Ficus.* import org.scalatest.{GivenWhenThen, ParallelTestExecution} +import java.net.{InetAddress, InetSocketAddress} + class BlacklistParallelSpecification extends FeatureSpec with GivenWhenThen with ParallelTestExecution { private val config = loadConfig(ConfigFactory.parseString("""waves.network { - | known-peers = [] - | file = null - | black-list-residence-time: 1s - |}""".stripMargin)) + | known-peers = [] + | file = null + | black-list-residence-time: 1s + |}""".stripMargin)) private val networkSettings = config.as[NetworkSettings]("waves.network") @@ -34,24 +34,24 @@ class BlacklistParallelSpecification extends FeatureSpec with GivenWhenThen with val address3 = new InetSocketAddress(host3, 2) def isBlacklisted(address: InetSocketAddress): Boolean = - peerDatabase.blacklistedHosts.contains(address.getAddress) + peerDatabase.isBlacklisted(address.getAddress) Scenario("Peer blacklist another peer") { Given("Peer database is empty") assert(peerDatabase.knownPeers.isEmpty) - assert(peerDatabase.blacklistedHosts.isEmpty) + assert(peerDatabase.detailedBlacklist.isEmpty) When("Peer adds another peer to knownPeers") peerDatabase.touch(address1) assert(peerDatabase.knownPeers.contains(address1)) - assert(!peerDatabase.blacklistedHosts.contains(host1)) + assert(!peerDatabase.isBlacklisted(host1)) And("Peer blacklists another peer") val reason = "because" peerDatabase.blacklist(address1.getAddress, reason) assert(isBlacklisted(address1)) - assert(peerDatabase.blacklistedHosts.contains(host1)) + assert(peerDatabase.isBlacklisted(host1)) assert(peerDatabase.detailedBlacklist(host1)._2 == reason) assert(!peerDatabase.knownPeers.contains(address1)) assert(!peerDatabase.knownPeers.contains(address1)) @@ -70,7 +70,7 @@ class BlacklistParallelSpecification extends FeatureSpec with GivenWhenThen with Given("Peer database is empty") assert(peerDatabase.knownPeers.isEmpty) - assert(peerDatabase.blacklistedHosts.isEmpty) + assert(peerDatabase.detailedBlacklist.isEmpty) When("Peer adds other peers") peerDatabase.touch(address1) diff --git a/node/src/test/scala/com/wavesplatform/network/BlacklistSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/network/BlacklistSpecification.scala similarity index 67% rename from node/src/test/scala/com/wavesplatform/network/BlacklistSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/network/BlacklistSpecification.scala index 9d66f41e21..1aaf9696a9 100644 --- a/node/src/test/scala/com/wavesplatform/network/BlacklistSpecification.scala +++ b/node/tests/src/test/scala/com/wavesplatform/network/BlacklistSpecification.scala @@ -1,21 +1,26 @@ package com.wavesplatform.network -import java.net.{InetAddress, InetSocketAddress} - +import com.google.common.base.Ticker import com.typesafe.config.ConfigFactory import com.wavesplatform.settings.NetworkSettings import com.wavesplatform.test.FeatureSpec -import net.ceedubs.ficus.Ficus._ +import net.ceedubs.ficus.Ficus.* import org.scalatest.GivenWhenThen +import java.net.{InetAddress, InetSocketAddress} + class BlacklistSpecification extends FeatureSpec with GivenWhenThen { - private val config = ConfigFactory.parseString("""waves.network { - | known-peers = [] - | file = null - | black-list-residence-time: 1s - |}""".stripMargin).withFallback(ConfigFactory.load()).resolve() + private val config = ConfigFactory + .parseString("""waves.network { + | known-peers = [] + | file = null + | black-list-residence-time: 1s + |}""".stripMargin) + .withFallback(ConfigFactory.load()) + .resolve() private val networkSettings = config.as[NetworkSettings]("waves.network") + private var timestamp = 0L info("As a Peer") info("I want to blacklist other peers for certain time") @@ -23,14 +28,15 @@ class BlacklistSpecification extends FeatureSpec with GivenWhenThen { Feature("Blacklist") { Scenario("Peer blacklist another peer") { - Given("Peer database is empty") - val peerDatabase = new PeerDatabaseImpl(networkSettings) + val peerDatabase = new PeerDatabaseImpl(networkSettings, new Ticker { + override def read(): Long = timestamp + }) - def isBlacklisted(address: InetSocketAddress) = peerDatabase.blacklistedHosts.contains(address.getAddress) + def isBlacklisted(address: InetSocketAddress) = peerDatabase.isBlacklisted(address.getAddress) assert(peerDatabase.knownPeers.isEmpty) - assert(peerDatabase.blacklistedHosts.isEmpty) + assert(peerDatabase.detailedBlacklist.isEmpty) When("Peer adds another peer to knownPeers") val address = new InetSocketAddress(InetAddress.getByName("localhost"), 1234) @@ -44,7 +50,7 @@ class BlacklistSpecification extends FeatureSpec with GivenWhenThen { assert(!peerDatabase.knownPeers.contains(address)) And("Peer waits for some time") - Thread.sleep(networkSettings.blackListResidenceTime.toMillis + 500) + timestamp += networkSettings.blackListResidenceTime.toNanos + 500 Then("Another peer disappear from blacklist") assert(!isBlacklisted(address)) diff --git a/node/src/test/scala/com/wavesplatform/network/BrokenConnectionDetectorSpec.scala b/node/tests/src/test/scala/com/wavesplatform/network/BrokenConnectionDetectorSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/network/BrokenConnectionDetectorSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/network/BrokenConnectionDetectorSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/network/ChannelGroupExtSpec.scala b/node/tests/src/test/scala/com/wavesplatform/network/ChannelGroupExtSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/network/ChannelGroupExtSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/network/ChannelGroupExtSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/network/ClientSpec.scala b/node/tests/src/test/scala/com/wavesplatform/network/ClientSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/network/ClientSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/network/ClientSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/network/HandshakeDecoderSpec.scala b/node/tests/src/test/scala/com/wavesplatform/network/HandshakeDecoderSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/network/HandshakeDecoderSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/network/HandshakeDecoderSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/network/InMemoryInvalidBlockStorage.scala b/node/tests/src/test/scala/com/wavesplatform/network/InMemoryInvalidBlockStorage.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/network/InMemoryInvalidBlockStorage.scala rename to node/tests/src/test/scala/com/wavesplatform/network/InMemoryInvalidBlockStorage.scala diff --git a/node/src/test/scala/com/wavesplatform/network/LegacyFrameCodecSpec.scala b/node/tests/src/test/scala/com/wavesplatform/network/LegacyFrameCodecSpec.scala similarity index 92% rename from node/src/test/scala/com/wavesplatform/network/LegacyFrameCodecSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/network/LegacyFrameCodecSpec.scala index 9750dd7182..1b9a5cb317 100644 --- a/node/src/test/scala/com/wavesplatform/network/LegacyFrameCodecSpec.scala +++ b/node/tests/src/test/scala/com/wavesplatform/network/LegacyFrameCodecSpec.scala @@ -19,7 +19,7 @@ import scala.concurrent.duration.DurationInt class LegacyFrameCodecSpec extends FreeSpec with MockFactory { "should handle one message" in forAll(issueGen) { origTx => - val codec = new LegacyFrameCodec(PeerDatabase.NoOp, 3.minutes) + val codec = new LegacyFrameCodecL1(PeerDatabase.NoOp, 3.minutes) val buff = Unpooled.buffer write(buff, origTx, TransactionSpec) @@ -34,7 +34,7 @@ class LegacyFrameCodecSpec extends FreeSpec with MockFactory { } "should handle multiple messages" in forAll(Gen.nonEmptyListOf(issueGen)) { origTxs => - val codec = new LegacyFrameCodec(PeerDatabase.NoOp, 3.minutes) + val codec = new LegacyFrameCodecL1(PeerDatabase.NoOp, 3.minutes) val buff = Unpooled.buffer origTxs.foreach(write(buff, _, TransactionSpec)) @@ -55,7 +55,7 @@ class LegacyFrameCodecSpec extends FreeSpec with MockFactory { "should reject an already received transaction" in { val tx = issueGen.sample.getOrElse(throw new RuntimeException("Can't generate a sample transaction")) - val codec = new LegacyFrameCodec(PeerDatabase.NoOp, 3.minutes) + val codec = new LegacyFrameCodecL1(PeerDatabase.NoOp, 3.minutes) val ch = new EmbeddedChannel(codec) val buff1 = Unpooled.buffer @@ -71,7 +71,7 @@ class LegacyFrameCodecSpec extends FreeSpec with MockFactory { "should not reject an already received GetPeers" in { val msg = KnownPeers(Seq(InetSocketAddress.createUnresolved("127.0.0.1", 80))) - val codec = new LegacyFrameCodec(PeerDatabase.NoOp, 3.minutes) + val codec = new LegacyFrameCodecL1(PeerDatabase.NoOp, 3.minutes) val ch = new EmbeddedChannel(codec) val buff1 = Unpooled.buffer diff --git a/node/src/test/scala/com/wavesplatform/network/MessageCodecSpec.scala b/node/tests/src/test/scala/com/wavesplatform/network/MessageCodecSpec.scala similarity index 93% rename from node/src/test/scala/com/wavesplatform/network/MessageCodecSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/network/MessageCodecSpec.scala index 8c6e574323..a141d419b7 100644 --- a/node/src/test/scala/com/wavesplatform/network/MessageCodecSpec.scala +++ b/node/tests/src/test/scala/com/wavesplatform/network/MessageCodecSpec.scala @@ -31,7 +31,7 @@ class MessageCodecSpec extends FreeSpec { codec.blockCalls shouldBe 0 } - private class SpyingMessageCodec extends MessageCodec(PeerDatabase.NoOp) { + private class SpyingMessageCodec extends MessageCodecL1(PeerDatabase.NoOp) { var blockCalls = 0 override def block(ctx: ChannelHandlerContext, e: Throwable): Unit = { diff --git a/node/src/test/scala/com/wavesplatform/network/MicroBlockInvSpecSpec.scala b/node/tests/src/test/scala/com/wavesplatform/network/MicroBlockInvSpecSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/network/MicroBlockInvSpecSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/network/MicroBlockInvSpecSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/network/MicroBlockResponseSpec.scala b/node/tests/src/test/scala/com/wavesplatform/network/MicroBlockResponseSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/network/MicroBlockResponseSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/network/MicroBlockResponseSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/network/MicroBlockSynchronizerSpec.scala b/node/tests/src/test/scala/com/wavesplatform/network/MicroBlockSynchronizerSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/network/MicroBlockSynchronizerSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/network/MicroBlockSynchronizerSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/network/RxExtensionLoaderSpec.scala b/node/tests/src/test/scala/com/wavesplatform/network/RxExtensionLoaderSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/network/RxExtensionLoaderSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/network/RxExtensionLoaderSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/network/RxScoreObserverSpec.scala b/node/tests/src/test/scala/com/wavesplatform/network/RxScoreObserverSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/network/RxScoreObserverSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/network/RxScoreObserverSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/network/TimedTransactionPublisherSpec.scala b/node/tests/src/test/scala/com/wavesplatform/network/TimedTransactionPublisherSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/network/TimedTransactionPublisherSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/network/TimedTransactionPublisherSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/network/TransactionSynchronizerSpec.scala b/node/tests/src/test/scala/com/wavesplatform/network/TransactionSynchronizerSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/network/TransactionSynchronizerSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/network/TransactionSynchronizerSpec.scala diff --git a/node/tests/src/test/scala/com/wavesplatform/network/peer/PeerDatabaseImplSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/network/peer/PeerDatabaseImplSpecification.scala new file mode 100644 index 0000000000..d6cbe832e2 --- /dev/null +++ b/node/tests/src/test/scala/com/wavesplatform/network/peer/PeerDatabaseImplSpecification.scala @@ -0,0 +1,147 @@ +package com.wavesplatform.network.peer + +import com.google.common.base.Ticker +import com.typesafe.config.ConfigFactory +import com.wavesplatform.network.{PeerDatabase, PeerDatabaseImpl} +import com.wavesplatform.settings.NetworkSettings +import com.wavesplatform.test.FreeSpec +import net.ceedubs.ficus.Ficus.* + +import java.net.InetSocketAddress +import scala.concurrent.duration.* + +class PeerDatabaseImplSpecification extends FreeSpec { + + val host1 = "1.1.1.1" + val host2 = "2.2.2.2" + val address1 = new InetSocketAddress(host1, 1) + val address2 = new InetSocketAddress(host2, 2) + + private val config1 = ConfigFactory + .parseString("""waves.network { + | file = null + | known-peers = [] + | peers-data-residence-time: 2s + |}""".stripMargin) + .withFallback(ConfigFactory.load()) + .resolve() + private val settings1 = config1.as[NetworkSettings]("waves.network") + + private val config2 = ConfigFactory + .parseString("""waves.network { + | file = null + | known-peers = [] + | peers-data-residence-time = 10s + |}""".stripMargin) + .withFallback(ConfigFactory.load()) + .resolve() + private val settings2 = config2.as[NetworkSettings]("waves.network") + + private var ts = 0L + private def sleepLong(): Unit = { ts += 2200.millis.toNanos } + private def sleepShort(): Unit = { ts += 200.millis.toNanos } + private def withDatabase(settings: NetworkSettings)(f: PeerDatabase => Unit): Unit = { + val pdb = new PeerDatabaseImpl( + settings, + new Ticker { + override def read(): Long = ts + } + ) + f(pdb) + pdb.close() + } + + "Peer database" - { + "new candidate should be returned by nextCandidate, but should not be added to knownPeers" in withDatabase(settings1) { database => + database.knownPeers shouldBe empty + database.addCandidate(address1) + database.nextCandidate(Set()) should contain(address1) + database.knownPeers shouldBe empty + } + + "touch() should add the address to knownPeers" in withDatabase(settings1) { database => + database.knownPeers shouldBe empty + database.addCandidate(address1) + database.knownPeers shouldBe empty + database.touch(address1) + database.knownPeers.keys should contain(address1) + } + + "peer should should become obsolete after time" in withDatabase(settings1) { database => + database.touch(address1) + database.knownPeers.keys should contain(address1) + sleepLong() + database.knownPeers shouldBe empty + database.nextCandidate(Set()) shouldBe empty + } + + "touching peer prevent it from obsoleting" in withDatabase(settings1) { database => + database.addCandidate(address1) + database.touch(address1) + sleepLong() + database.touch(address1) + sleepShort() + database.knownPeers.keys should contain(address1) + } + + "blacklisted peer should disappear from internal buffer and database" in withDatabase(settings1) { database => + database.touch(address1) + database.addCandidate(address2) + database.knownPeers.keys should contain(address1) + database.knownPeers.keys should not contain address2 + + database.blacklist(address1.getAddress, "") + database.knownPeers.keys should not contain address1 + database.knownPeers should be(empty) + + database.nextCandidate(Set()) should contain(address2) + database.blacklist(address2.getAddress, "") + database.nextCandidate(Set()) should not contain address2 + database.nextCandidate(Set()) should be(empty) + } + + "random peer should return peers from both from database and buffer" in withDatabase(settings2) { database2 => + database2.touch(address1) + database2.addCandidate(address2) + val keys = database2.knownPeers.keys + keys should contain(address1) + keys should not contain address2 + + val set = (1 to 10).flatMap(i => database2.nextCandidate(Set())).toSet + + set should contain(address1) + set should contain(address2) + } + + "filters out excluded candidates" in withDatabase(settings1) { database => + database.addCandidate(address1) + database.addCandidate(address1) + database.addCandidate(address2) + + database.nextCandidate(Set(address1)) should contain(address2) + } + + "filters out wildcard addresses" in withDatabase(settings1) { database => + database.addCandidate(new InetSocketAddress("0.0.0.0", 6863)) + database.nextCandidate(Set(address1, address2)) shouldBe None + } + + "should not add nodes to the blacklist if blacklisting is disabled" in { + val config = ConfigFactory + .parseString(s"""waves.network { + | file = null + | known-peers = [] + | peers-data-residence-time = 100s + | enable-blacklisting = no + |}""".stripMargin) + .withFallback(ConfigFactory.load()) + .resolve() + val settings = config.as[NetworkSettings]("waves.network") + val database = new PeerDatabaseImpl(settings) + database.blacklist(address1.getAddress, "I don't like it") + + database.detailedBlacklist shouldBe empty + } + } + +} diff --git a/node/src/test/scala/com/wavesplatform/serialization/DeserTest.scala b/node/tests/src/test/scala/com/wavesplatform/serialization/DeserTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/serialization/DeserTest.scala rename to node/tests/src/test/scala/com/wavesplatform/serialization/DeserTest.scala diff --git a/node/src/test/scala/com/wavesplatform/serialization/EvaluatedPBSerializationTest.scala b/node/tests/src/test/scala/com/wavesplatform/serialization/EvaluatedPBSerializationTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/serialization/EvaluatedPBSerializationTest.scala rename to node/tests/src/test/scala/com/wavesplatform/serialization/EvaluatedPBSerializationTest.scala diff --git a/node/src/test/scala/com/wavesplatform/settings/BlockchainSettingsSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/settings/BlockchainSettingsSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/settings/BlockchainSettingsSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/settings/BlockchainSettingsSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/settings/FeaturesSettingsSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/settings/FeaturesSettingsSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/settings/FeaturesSettingsSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/settings/FeaturesSettingsSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/settings/MinerSettingsSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/settings/MinerSettingsSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/settings/MinerSettingsSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/settings/MinerSettingsSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/settings/NetworkSettingsSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/settings/NetworkSettingsSpecification.scala similarity index 97% rename from node/src/test/scala/com/wavesplatform/settings/NetworkSettingsSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/settings/NetworkSettingsSpecification.scala index 4c4c46f6fd..b2a7acda6c 100644 --- a/node/src/test/scala/com/wavesplatform/settings/NetworkSettingsSpecification.scala +++ b/node/tests/src/test/scala/com/wavesplatform/settings/NetworkSettingsSpecification.scala @@ -42,7 +42,7 @@ class NetworkSettingsSpecification extends FlatSpec { |}""".stripMargin)) val networkSettings = config.as[NetworkSettings]("waves.network") - networkSettings.bindAddress should be(new InetSocketAddress("127.0.0.1", 6868)) + networkSettings.bindAddress should be(Some(new InetSocketAddress("127.0.0.1", 6868))) networkSettings.nodeName should be("default-node-name") networkSettings.declaredAddress should be(Some(new InetSocketAddress("127.0.0.1", 6868))) networkSettings.nonce should be(0) diff --git a/node/src/test/scala/com/wavesplatform/settings/RestAPISettingsSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/settings/RestAPISettingsSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/settings/RestAPISettingsSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/settings/RestAPISettingsSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/settings/SynchronizationSettingsSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/settings/SynchronizationSettingsSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/settings/SynchronizationSettingsSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/settings/SynchronizationSettingsSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/settings/UtxSettingsSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/settings/UtxSettingsSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/settings/UtxSettingsSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/settings/UtxSettingsSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/settings/WalletSettingsSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/settings/WalletSettingsSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/settings/WalletSettingsSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/settings/WalletSettingsSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/settings/WavesSettingsSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/settings/WavesSettingsSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/settings/WavesSettingsSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/settings/WavesSettingsSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/state/BlockChallengeTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/BlockChallengeTest.scala similarity index 99% rename from node/src/test/scala/com/wavesplatform/state/BlockChallengeTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/BlockChallengeTest.scala index 7c5b1fbc2c..734f906a74 100644 --- a/node/src/test/scala/com/wavesplatform/state/BlockChallengeTest.scala +++ b/node/tests/src/test/scala/com/wavesplatform/state/BlockChallengeTest.scala @@ -23,7 +23,7 @@ import com.wavesplatform.lang.v1.compiler.Terms.{CONST_BYTESTR, CONST_LONG} import com.wavesplatform.lang.v1.compiler.TestCompiler import com.wavesplatform.mining.{BlockChallenger, BlockChallengerImpl} import com.wavesplatform.network.MicroBlockSynchronizer.MicroblockData -import com.wavesplatform.network.{ExtensionBlocks, InvalidBlockStorage, MessageCodec, PBBlockSpec, PeerDatabase, RawBytes} +import com.wavesplatform.network.{ExtensionBlocks, InvalidBlockStorage, MessageCodecL1, PBBlockSpec, PeerDatabase, RawBytes} import com.wavesplatform.protobuf.transaction.PBTransactions import com.wavesplatform.settings.WavesSettings import com.wavesplatform.state.BlockRewardCalculator.BlockRewardShares @@ -1885,8 +1885,8 @@ class BlockChallengeTest private def appendAndCheck(block: Block, d: Domain)(check: Block => Unit): Unit = { val channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE) - val channel1 = new EmbeddedChannel(new MessageCodec(PeerDatabase.NoOp)) - val channel2 = new EmbeddedChannel(new MessageCodec(PeerDatabase.NoOp)) + val channel1 = new EmbeddedChannel(new MessageCodecL1(PeerDatabase.NoOp)) + val channel2 = new EmbeddedChannel(new MessageCodecL1(PeerDatabase.NoOp)) channels.add(channel1) channels.add(channel2) val appenderWithChallenger: Block => Task[Unit] = diff --git a/node/tests/src/test/scala/com/wavesplatform/state/BlockchainTriggersSpec.scala b/node/tests/src/test/scala/com/wavesplatform/state/BlockchainTriggersSpec.scala new file mode 100644 index 0000000000..a4cea8e734 --- /dev/null +++ b/node/tests/src/test/scala/com/wavesplatform/state/BlockchainTriggersSpec.scala @@ -0,0 +1,61 @@ +package com.wavesplatform.state + +import cats.implicits.catsSyntaxSemigroup +import com.wavesplatform.block.{Block, MicroBlock, SignedBlockHeader} +import com.wavesplatform.common.state.ByteStr +import com.wavesplatform.db.WithDomain +import com.wavesplatform.db.WithState.AddrWithBalance +import com.wavesplatform.events.BlockchainUpdateTriggers +import com.wavesplatform.test.* +import com.wavesplatform.transaction.TxHelpers +import org.scalatest.OptionValues + +class BlockchainTriggersSpec extends PropSpec with WithDomain with OptionValues { + private val richAccount = TxHelpers.signer(2000) + + property("proper events") { + withDomain(DomainPresets.TransactionStateSnapshot, Seq(AddrWithBalance(richAccount.toAddress, 10_000.waves))) { d => + val rollbackTo = d.appendBlock(TxHelpers.dataEntry(richAccount, IntegerDataEntry("foo_key", 1))).id() + d.appendMicroBlock(TxHelpers.dataEntry(richAccount, IntegerDataEntry("foo_key", 2))) + + d.blockchain.accountData(richAccount.toAddress, "foo_key").value shouldEqual IntegerDataEntry("foo_key", 2) + + d.triggers :+= new BlockchainUpdateTriggers { + override def onProcessBlock( + block: Block, + snapshot: StateSnapshot, + reward: Option[Long], + hitSource: ByteStr, + blockchainBeforeWithReward: Blockchain + ): Unit = { + blockchainBeforeWithReward.accountData(richAccount.toAddress, "foo_key").value.cast[IntegerDataEntry].value.value shouldEqual 1 + val updated = + SnapshotBlockchain(blockchainBeforeWithReward, Some(snapshot), Some(SignedBlockHeader(block.header, block.signature) -> hitSource)) + updated.accountData(richAccount.toAddress, "foo_key").value.cast[IntegerDataEntry].value.value shouldEqual 1 + } + + override def onProcessMicroBlock( + microBlock: MicroBlock, + snapshot: StateSnapshot, + blockchainBeforeWithReward: Blockchain, + totalBlockId: ByteStr, + totalTransactionsRoot: ByteStr + ): Unit = { + val updated = SnapshotBlockchain( + blockchainBeforeWithReward, + Some(snapshot.transactions.values.foldLeft(StateSnapshot.empty) { (s, n2) => + s |+| n2.snapshot + }) + ) + updated.accountData(richAccount.toAddress, "foo_key").value.cast[IntegerDataEntry].value.value shouldEqual 5 + } + + override def onRollback(blockchainBefore: Blockchain, toBlockId: ByteStr, toHeight: Int): Unit = {} + + override def onMicroBlockRollback(blockchainBefore: Blockchain, toBlockId: ByteStr): Unit = {} + } + d.appendKeyBlock(ref = Some(rollbackTo)) + d.appendMicroBlock(TxHelpers.dataEntry(richAccount, IntegerDataEntry("foo_key", 5))) + } + } +} diff --git a/node/src/test/scala/com/wavesplatform/state/BlockchainUpdaterImplSpec.scala b/node/tests/src/test/scala/com/wavesplatform/state/BlockchainUpdaterImplSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/BlockchainUpdaterImplSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/state/BlockchainUpdaterImplSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/state/CommonSpec.scala b/node/tests/src/test/scala/com/wavesplatform/state/CommonSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/CommonSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/state/CommonSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/state/DataKeyRollback.scala b/node/tests/src/test/scala/com/wavesplatform/state/DataKeyRollback.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/DataKeyRollback.scala rename to node/tests/src/test/scala/com/wavesplatform/state/DataKeyRollback.scala diff --git a/node/src/test/scala/com/wavesplatform/state/HistoryTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/HistoryTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/HistoryTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/HistoryTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/LightNodeTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/LightNodeTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/LightNodeTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/LightNodeTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/NgStateTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/NgStateTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/NgStateTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/NgStateTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/PortfolioTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/PortfolioTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/PortfolioTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/PortfolioTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/RollbackSpec.scala b/node/tests/src/test/scala/com/wavesplatform/state/RollbackSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/RollbackSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/state/RollbackSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/state/StateHashSpec.scala b/node/tests/src/test/scala/com/wavesplatform/state/StateHashSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/StateHashSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/state/StateHashSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/state/TransactionsByAddressSpec.scala b/node/tests/src/test/scala/com/wavesplatform/state/TransactionsByAddressSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/TransactionsByAddressSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/state/TransactionsByAddressSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/state/appender/BlockAppenderSpec.scala b/node/tests/src/test/scala/com/wavesplatform/state/appender/BlockAppenderSpec.scala similarity index 90% rename from node/src/test/scala/com/wavesplatform/state/appender/BlockAppenderSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/state/appender/BlockAppenderSpec.scala index 5abc2feffd..a7d346b917 100644 --- a/node/src/test/scala/com/wavesplatform/state/appender/BlockAppenderSpec.scala +++ b/node/tests/src/test/scala/com/wavesplatform/state/appender/BlockAppenderSpec.scala @@ -4,7 +4,7 @@ import com.wavesplatform.block.Block import com.wavesplatform.common.utils.EitherExt2 import com.wavesplatform.db.WithDomain import com.wavesplatform.db.WithState.AddrWithBalance -import com.wavesplatform.network.{MessageCodec, PBBlockSpec, PeerDatabase, RawBytes} +import com.wavesplatform.network.{MessageCodecL1, PBBlockSpec, PeerDatabase, RawBytes} import com.wavesplatform.state.BlockchainUpdaterImpl.BlockApplyResult.Ignored import com.wavesplatform.test.{FlatSpec, TestTime} import com.wavesplatform.transaction.TxHelpers @@ -25,8 +25,8 @@ class BlockAppenderSpec extends FlatSpec with WithDomain with BeforeAndAfterAll val sender = TxHelpers.signer(1) withDomain(DomainPresets.ConsensusImprovements, AddrWithBalance.enoughBalances(sender)) { d => val channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE) - val channel1 = new EmbeddedChannel(new MessageCodec(PeerDatabase.NoOp)) - val channel2 = new EmbeddedChannel(new MessageCodec(PeerDatabase.NoOp)) + val channel1 = new EmbeddedChannel(new MessageCodecL1(PeerDatabase.NoOp)) + val channel2 = new EmbeddedChannel(new MessageCodecL1(PeerDatabase.NoOp)) channels.add(channel1) channels.add(channel2) val appender = BlockAppender( diff --git a/node/src/test/scala/com/wavesplatform/state/appender/ExtensionAppenderSpec.scala b/node/tests/src/test/scala/com/wavesplatform/state/appender/ExtensionAppenderSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/appender/ExtensionAppenderSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/state/appender/ExtensionAppenderSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/AssetTransactionsDiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/AssetTransactionsDiffTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/AssetTransactionsDiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/AssetTransactionsDiffTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/BalanceDiffValidationTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/BalanceDiffValidationTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/BalanceDiffValidationTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/BalanceDiffValidationTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/BlockDifferDetailedSnapshotTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/BlockDifferDetailedSnapshotTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/BlockDifferDetailedSnapshotTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/BlockDifferDetailedSnapshotTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/BlockDifferTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/BlockDifferTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/BlockDifferTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/BlockDifferTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/CommonValidationTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/CommonValidationTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/CommonValidationTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/CommonValidationTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/CommonValidationTimeTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/CommonValidationTimeTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/CommonValidationTimeTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/CommonValidationTimeTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/CreateAliasTransactionDiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/CreateAliasTransactionDiffTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/CreateAliasTransactionDiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/CreateAliasTransactionDiffTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/DataTransactionDiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/DataTransactionDiffTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/DataTransactionDiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/DataTransactionDiffTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/EthereumTransactionDiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/EthereumTransactionDiffTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/EthereumTransactionDiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/EthereumTransactionDiffTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ExchangeTransactionDiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ExchangeTransactionDiffTest.scala similarity index 99% rename from node/src/test/scala/com/wavesplatform/state/diffs/ExchangeTransactionDiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ExchangeTransactionDiffTest.scala index 233baedc0c..f200e257e7 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/ExchangeTransactionDiffTest.scala +++ b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ExchangeTransactionDiffTest.scala @@ -1226,10 +1226,10 @@ class ExchangeTransactionDiffTest extends PropSpec with Inside with WithDomain w property("Disable use Order on SmartAccount") { val enoughFee = 100000000 val script = "true" - val txScriptCompiled = ScriptCompiler(script, isAssetScript = false, estimator).explicitGet()._1 + val txScriptCompiled = ScriptCompiler.compile(script, estimator).explicitGet()._1 - val sellerScript = ScriptCompiler(script, isAssetScript = false, estimator).explicitGet()._1 - val buyerScript = ScriptCompiler(script, isAssetScript = false, estimator).explicitGet()._1 + val sellerScript = ScriptCompiler.compile(script, estimator).explicitGet()._1 + val buyerScript = ScriptCompiler.compile(script, estimator).explicitGet()._1 val buyer = TxHelpers.signer(1) val seller = TxHelpers.signer(2) @@ -2069,9 +2069,9 @@ class ExchangeTransactionDiffTest extends PropSpec with Inside with WithDomain w ): (GenesisTransaction, List[TransferTransaction], List[Transaction], ExchangeTransaction, KeyPair) = { val enoughFee = 100000000 - val txScriptCompiled = ScriptCompiler(txScript, isAssetScript = false, estimator).explicitGet()._1 - val sellerScript = ScriptCompiler(sellerScriptSrc, isAssetScript = false, estimator).explicitGet()._1 - val buyerScript = ScriptCompiler(buyerScriptSrc, isAssetScript = false, estimator).explicitGet()._1 + val txScriptCompiled = ScriptCompiler.compile(txScript, estimator).explicitGet()._1 + val sellerScript = ScriptCompiler.compile(sellerScriptSrc, estimator).explicitGet()._1 + val buyerScript = ScriptCompiler.compile(buyerScriptSrc, estimator).explicitGet()._1 val buyer = TxHelpers.signer(1) val seller = TxHelpers.signer(2) diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/GenesisTransactionDiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/GenesisTransactionDiffTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/GenesisTransactionDiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/GenesisTransactionDiffTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/LeaseTransactionsDiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/LeaseTransactionsDiffTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/LeaseTransactionsDiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/LeaseTransactionsDiffTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/MassTransferTransactionDiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/MassTransferTransactionDiffTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/MassTransferTransactionDiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/MassTransferTransactionDiffTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/OverflowTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/OverflowTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/OverflowTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/OverflowTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/PaymentTransactionDiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/PaymentTransactionDiffTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/PaymentTransactionDiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/PaymentTransactionDiffTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ReissueTransactionDiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ReissueTransactionDiffTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ReissueTransactionDiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ReissueTransactionDiffTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ScriptComplexityCountTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ScriptComplexityCountTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ScriptComplexityCountTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ScriptComplexityCountTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/SetScriptTransactionDiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/SetScriptTransactionDiffTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/SetScriptTransactionDiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/SetScriptTransactionDiffTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/SponsorshipDiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/SponsorshipDiffTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/SponsorshipDiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/SponsorshipDiffTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/TransactionValidationErrorPrintTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/TransactionValidationErrorPrintTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/TransactionValidationErrorPrintTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/TransactionValidationErrorPrintTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/TransactionVersionValidationTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/TransactionVersionValidationTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/TransactionVersionValidationTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/TransactionVersionValidationTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/TransferDiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/TransferDiffTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/TransferDiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/TransferDiffTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/TransferTransactionDiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/TransferTransactionDiffTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/TransferTransactionDiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/TransferTransactionDiffTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/BigIntInvokeTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/BigIntInvokeTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/BigIntInvokeTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/BigIntInvokeTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/CallableV4DiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/CallableV4DiffTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/CallableV4DiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/CallableV4DiffTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/CallableV5LimitTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/CallableV5LimitTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/CallableV5LimitTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/CallableV5LimitTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/DAppDataEntryTypeTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/DAppDataEntryTypeTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/DAppDataEntryTypeTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/DAppDataEntryTypeTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/DAppListArgTypesTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/DAppListArgTypesTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/DAppListArgTypesTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/DAppListArgTypesTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/EvaluatorFunctionCallScopeTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/EvaluatorFunctionCallScopeTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/EvaluatorFunctionCallScopeTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/EvaluatorFunctionCallScopeTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/IllegalAddressChainIdTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/IllegalAddressChainIdTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/IllegalAddressChainIdTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/IllegalAddressChainIdTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeActionsAvailabilityTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeActionsAvailabilityTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeActionsAvailabilityTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeActionsAvailabilityTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeActionsFeeTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeActionsFeeTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeActionsFeeTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeActionsFeeTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeAffectedAddressTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeAffectedAddressTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeAffectedAddressTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeAffectedAddressTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeAssetChecksTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeAssetChecksTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeAssetChecksTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeAssetChecksTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeDataEntriesBytesTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeDataEntriesBytesTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeDataEntriesBytesTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeDataEntriesBytesTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeFeeMultiplierTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeFeeMultiplierTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeFeeMultiplierTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeFeeMultiplierTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeFeeTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeFeeTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeFeeTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeFeeTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokePaymentsAvailabilityTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokePaymentsAvailabilityTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokePaymentsAvailabilityTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokePaymentsAvailabilityTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokePaymentsLimitTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokePaymentsLimitTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokePaymentsLimitTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokePaymentsLimitTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokePaymentsTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokePaymentsTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokePaymentsTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokePaymentsTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeReissueTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeReissueTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeReissueTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeReissueTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeScriptActionLimitsTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeScriptActionLimitsTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeScriptActionLimitsTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeScriptActionLimitsTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeScriptTransactionDiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeScriptTransactionDiffTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeScriptTransactionDiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeScriptTransactionDiffTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeSponsorFeeTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeSponsorFeeTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeSponsorFeeTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeSponsorFeeTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeTransferBalanceErrorTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeTransferBalanceErrorTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeTransferBalanceErrorTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeTransferBalanceErrorTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeValidationTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeValidationTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeValidationTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/InvokeValidationTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/LeaseActionDiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/LeaseActionDiffTest.scala similarity index 96% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/LeaseActionDiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/LeaseActionDiffTest.scala index 9d5819074a..a7f1d195f3 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/ci/LeaseActionDiffTest.scala +++ b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/LeaseActionDiffTest.scala @@ -15,7 +15,7 @@ import com.wavesplatform.lang.v1.ContractLimits import com.wavesplatform.lang.v1.compiler.TestCompiler import com.wavesplatform.lang.v1.traits.domain.{Lease, Recipient} import com.wavesplatform.settings.{FunctionalitySettings, TestFunctionalitySettings} -import com.wavesplatform.state.LeaseBalance +import com.wavesplatform.state.{LeaseBalance, unsafeSummarizer} import com.wavesplatform.state.diffs.FeeValidation.{FeeConstants, FeeUnit} import com.wavesplatform.state.diffs.{ENOUGH_AMT, produceRejectOrFailedDiff} import com.wavesplatform.test.* @@ -35,6 +35,8 @@ class LeaseActionDiffTest extends PropSpec with WithDomain { TestFunctionalitySettings.Enabled.copy(preActivatedFeatures = features) } + private def extractFee(sender: Address): PartialFunction[Transaction, Long] = { case z: Authorized if z.sender.toAddress == sender => z.assetFee._2 } + private val v4Features = features(V4) private val v5Features = features(V5) @@ -251,14 +253,14 @@ class LeaseActionDiffTest extends PropSpec with WithDomain { d.appendBlock(preparingTxs*) d.appendBlock(invoke) - val invokerSpentFee = preparingTxs.collect { case a: Authorized if a.sender.toAddress == invoker => a.assetFee._2 }.sum + val invokerSpentFee = preparingTxs.collect(extractFee(invoker)).sum val invokerPortfolio = d.blockchain.wavesPortfolio(invoker) invokerPortfolio.lease shouldBe LeaseBalance(leaseAmount, out = 0) invokerPortfolio.balance shouldBe ENOUGH_AMT - invokerSpentFee - invoke.fee.value invokerPortfolio.spendableBalance shouldBe ENOUGH_AMT - invokerSpentFee - invoke.fee.value invokerPortfolio.effectiveBalance(false).explicitGet() shouldBe ENOUGH_AMT - invokerSpentFee - invoke.fee.value + leaseAmount - val dAppSpentFee = preparingTxs.collect { case a: Authorized if a.sender.toAddress == dAppAcc => a.assetFee._2 }.sum + val dAppSpentFee = preparingTxs.collect(extractFee(dAppAcc)).sum val dAppPortfolio = d.blockchain.wavesPortfolio(dAppAcc) dAppPortfolio.lease shouldBe LeaseBalance(in = 0, leaseAmount) dAppPortfolio.balance shouldBe ENOUGH_AMT - dAppSpentFee @@ -277,8 +279,8 @@ class LeaseActionDiffTest extends PropSpec with WithDomain { leasePreconditions() match { case (preparingTxs, invoke, leaseAmount, dAppAcc, invoker, leaseTxFromDApp :: _, _) => withDomain(domainSettingsWithFS(v5Features)) { d => - val invokerSpentFee = preparingTxs.collect { case a: Authorized if a.sender.toAddress == invoker => a.assetFee._2 }.sum - val dAppSpentFee = (preparingTxs :+ leaseTxFromDApp).collect { case a: Authorized if a.sender.toAddress == dAppAcc => a.assetFee._2 }.sum + val invokerSpentFee = preparingTxs.collect(extractFee(invoker)).sum + val dAppSpentFee = (preparingTxs :+ leaseTxFromDApp).collect(extractFee(dAppAcc)).sum d.appendBlock(preparingTxs*) d.appendBlock(leaseTxFromDApp) @@ -317,9 +319,9 @@ class LeaseActionDiffTest extends PropSpec with WithDomain { withDomain(domainSettingsWithFS(v5Features)) { d => val invokerSpentFee = (preparingTxs ++ Seq(leaseTxToDApp, leaseTxToDAppCancel)).collect { - case a: Authorized if a.sender.toAddress == invoker => a.assetFee._2 + case z: Authorized if z.sender.toAddress == invoker => z.assetFee._2 }.sum - val dAppSpentFee = (preparingTxs :+ leaseTxFromDApp).collect { case a: Authorized if a.sender.toAddress == dAppAcc => a.assetFee._2 }.sum + val dAppSpentFee = (preparingTxs :+ leaseTxFromDApp).collect(extractFee(dAppAcc)).sum d.appendBlock(preparingTxs*) d.appendBlock(leaseTxFromDApp, leaseTxToDApp, leaseTxToDAppCancel) @@ -356,8 +358,8 @@ class LeaseActionDiffTest extends PropSpec with WithDomain { leasePreconditions() match { case (preparingTxs, invoke, leaseAmount, dAppAcc, invoker, _ :: leaseTxToDApp :: Nil, _) => withDomain(domainSettingsWithFS(v5Features)) { d => - val invokerSpentFee = (preparingTxs :+ leaseTxToDApp).collect { case a: Authorized if a.sender.toAddress == invoker => a.assetFee._2 }.sum - val dAppSpentFee = preparingTxs.collect { case a: Authorized if a.sender.toAddress == dAppAcc => a.assetFee._2 }.sum + val invokerSpentFee = (preparingTxs :+ leaseTxToDApp).collect(extractFee(invoker)).sum + val dAppSpentFee = preparingTxs.collect(extractFee(dAppAcc)).sum d.appendBlock(preparingTxs*) d.appendBlock(leaseTxToDApp) @@ -394,11 +396,9 @@ class LeaseActionDiffTest extends PropSpec with WithDomain { leasePreconditions() match { case (preparingTxs, invoke, leaseAmount, dAppAcc, invoker, leaseTxFromDApp :: leaseTxToDApp :: Nil, leaseTxFromDAppCancel) => withDomain(domainSettingsWithFS(v5Features)) { d => - val invokerSpentFee = (preparingTxs :+ leaseTxToDApp).collect { case a: Authorized if a.sender.toAddress == invoker => a.assetFee._2 }.sum + val invokerSpentFee = (preparingTxs :+ leaseTxToDApp).collect(extractFee(invoker)).sum val dAppSpentFee = - (preparingTxs ++ Seq(leaseTxFromDApp, leaseTxFromDAppCancel)).collect { - case a: Authorized if a.sender.toAddress == dAppAcc => a.assetFee._2 - }.sum + (preparingTxs ++ Seq(leaseTxFromDApp, leaseTxFromDAppCancel)).collect(extractFee(dAppAcc)).sum d.appendBlock(preparingTxs*) d.appendBlock(leaseTxToDApp, leaseTxFromDApp, leaseTxFromDAppCancel) @@ -431,7 +431,7 @@ class LeaseActionDiffTest extends PropSpec with WithDomain { -leaseTxFromDApp.fee.value - leaseTxFromDAppCancel.fee.value ) } - case a => throw new TestFailedException(s"Unexpected preconditions $a", 0) + case pc => throw new TestFailedException(s"Unexpected preconditions $pc", 0) } } @@ -439,8 +439,8 @@ class LeaseActionDiffTest extends PropSpec with WithDomain { leasePreconditions() match { case (preparingTxs, invoke, leaseAmount, dAppAcc, invoker, leaseTxFromDApp :: leaseTxToDApp :: Nil, _) => withDomain(domainSettingsWithFS(v5Features)) { d => - val invokerSpentFee = (preparingTxs :+ leaseTxToDApp).collect { case a: Authorized if a.sender.toAddress == invoker => a.assetFee._2 }.sum - val dAppSpentFee = (preparingTxs :+ leaseTxFromDApp).collect { case a: Authorized if a.sender.toAddress == dAppAcc => a.assetFee._2 }.sum + val invokerSpentFee = (preparingTxs :+ leaseTxToDApp).collect(extractFee(invoker)).sum + val dAppSpentFee = (preparingTxs :+ leaseTxFromDApp).collect(extractFee(dAppAcc)).sum d.appendBlock(preparingTxs*) d.appendBlock(leaseTxFromDApp, leaseTxToDApp) @@ -473,7 +473,7 @@ class LeaseActionDiffTest extends PropSpec with WithDomain { ) d.blockchain.generatingBalance(dAppAcc) shouldBe ENOUGH_AMT - dAppSpentFee + leaseTxFromDApp.fee.value.min(-leaseAmountDiff) } - case a => throw new TestFailedException(s"Unexpected preconditions $a", 0) + case other => throw new TestFailedException(s"Unexpected preconditions $other", 0) } } @@ -726,7 +726,7 @@ class LeaseActionDiffTest extends PropSpec with WithDomain { recipientPortfolio.spendableBalance shouldBe 0 recipientPortfolio.effectiveBalance(false).explicitGet() shouldBe 0 - val dAppSpentFee = preparingTxs.collect { case a: Authorized if a.sender.toAddress == dAppAcc => a.assetFee._2 }.sum + val dAppSpentFee = preparingTxs.collect(extractFee(dAppAcc)).sum val dAppPortfolio = d.blockchain.wavesPortfolio(dAppAcc) dAppPortfolio.lease shouldBe LeaseBalance.empty dAppPortfolio.balance shouldBe ENOUGH_AMT - dAppSpentFee diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/ListParamInvokeTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/ListParamInvokeTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/ListParamInvokeTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/ListParamInvokeTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/MultiPaymentInvokeDiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/MultiPaymentInvokeDiffTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/MultiPaymentInvokeDiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/MultiPaymentInvokeDiffTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/NegativeBurnTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/NegativeBurnTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/NegativeBurnTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/NegativeBurnTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/NegativeLeaseTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/NegativeLeaseTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/NegativeLeaseTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/NegativeLeaseTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/NegativeReissueTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/NegativeReissueTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/NegativeReissueTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/NegativeReissueTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/NegativeSponsorFeeTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/NegativeSponsorFeeTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/NegativeSponsorFeeTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/NegativeSponsorFeeTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/NegativeTransferAmountTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/NegativeTransferAmountTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/NegativeTransferAmountTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/NegativeTransferAmountTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/OverdraftTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/OverdraftTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/OverdraftTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/OverdraftTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/OverheadCallableCallTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/OverheadCallableCallTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/OverheadCallableCallTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/OverheadCallableCallTest.scala diff --git a/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/RideGeneratingBalanceSpec.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/RideGeneratingBalanceSpec.scala new file mode 100644 index 0000000000..96fefe2977 --- /dev/null +++ b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/RideGeneratingBalanceSpec.scala @@ -0,0 +1,128 @@ +package com.wavesplatform.state.diffs.ci + +import com.wavesplatform.block.Block +import com.wavesplatform.db.WithDomain +import com.wavesplatform.settings.WavesSettings +import com.wavesplatform.db.WithState.AddrWithBalance +import com.wavesplatform.lang.directives.values.StdLibVersion +import com.wavesplatform.lang.directives.values.* +import com.wavesplatform.lang.v1.compiler.Terms.CONST_LONG +import com.wavesplatform.test.{FreeSpec, NumericExt} +import com.wavesplatform.transaction.TxHelpers +import com.wavesplatform.transaction.smart.InvokeScriptTransaction +import org.scalatest.ParallelTestExecution + +class RideGeneratingBalanceSpec extends FreeSpec with WithDomain with ParallelTestExecution { + def testGBAffectedByTxInCurrentBlock(preset: WavesSettings, stdLibVersion: StdLibVersion): Block = { + + val dAppAccount = TxHelpers.signer(999) + val anotherAccount = TxHelpers.signer(1) + + val balances = Seq(AddrWithBalance(dAppAccount.toAddress, 100.01.waves), AddrWithBalance(anotherAccount.toAddress, 500.waves)) + + withDomain(preset, balances) { d => + val dAppScript = TxHelpers.script( + s"""{-# STDLIB_VERSION ${stdLibVersion.value} #-} + |{-# CONTENT_TYPE DAPP #-} + |{-# SCRIPT_TYPE ACCOUNT #-} + | + |@Callable(i) + |func assertBalances( + | expectedRegularBalance: Int, + | expectedAvailableBalance: Int, + | expectedEffectiveBalance: Int, + | expectedGeneratingBalance: Int + |) = { + | let actualRegularBalance = wavesBalance(this).regular + | let actualAvailableBalance = wavesBalance(this).available + | let actualEffectiveBalance = wavesBalance(this).effective + | let actualGeneratingBalance = wavesBalance(this).generating + | + | strict checkRegular = if (actualRegularBalance != expectedRegularBalance) + | then throw("Expected Regular balance to be: " + toString(expectedRegularBalance) + ", But got: " + toString(actualRegularBalance)) + | else unit + | + | strict checkAvailable = if (actualAvailableBalance != expectedAvailableBalance) + | then throw("Expected Available balance to be: " + toString(expectedAvailableBalance) + ", But got: " + toString(actualAvailableBalance)) + | else unit + | + | strict checkEffective = if (actualEffectiveBalance != expectedEffectiveBalance) + | then throw("Expected Effective balance to be: " + toString(expectedEffectiveBalance) + ", But got: " + toString(actualEffectiveBalance)) + | else unit + | + | strict checkGenerating = if (actualGeneratingBalance != expectedGeneratingBalance) + | then throw("Expected Generating balance to be: " + toString(expectedGeneratingBalance) + ", But got: " + toString(actualGeneratingBalance)) + | else unit + | ([], unit) + |}""".stripMargin + ) + + def assertBalancesInRide(regular: Long, available: Long, effective: Long, generating: Long): InvokeScriptTransaction = + TxHelpers.invoke( + dAppAccount.toAddress, + Some("assertBalances"), + Seq(CONST_LONG(regular), CONST_LONG(available), CONST_LONG(effective), CONST_LONG(generating)), + payments = Seq(), + invoker = anotherAccount + ) + + d.blockchain.height shouldBe 1 + + // Block 2 + d.appendBlock( + TxHelpers.setScript(dAppAccount, dAppScript), // Note: setScript costs 0.01.waves + assertBalancesInRide(100.waves, 100.waves, 100.waves, 100.waves) + ) + d.blockchain.height shouldBe 2 + + // Block 3 + d.appendBlock(TxHelpers.transfer(anotherAccount, dAppAccount.toAddress, 10.waves)) + d.blockchain.height shouldBe 3 + + // Fast-forward to block 1000 + Range.inclusive(3, 999).foreach(_ => d.appendBlock()) + d.blockchain.height shouldBe 1000 + + // Block 1001 + // This assertion tells us that the generating balance + // is not being updated until the block 1002, which is expected, + // because `10.waves` was sent on height = 3, + // and until height 1002 the balance is not updated + // (...the lowest of the last 1000 blocks, including 3 and 1002) + d.appendBlock(assertBalancesInRide(110.waves, 110.waves, 110.waves, 100.waves)) + d.blockchain.height shouldBe 1001 + + // Block 1002 + d.appendBlock( + // This assertion tells us that the generating balance + // was already updated after `10.waves` was sent on height = 3 + assertBalancesInRide(110.waves, 110.waves, 110.waves, 110.waves), + TxHelpers.transfer(dAppAccount, anotherAccount.toAddress, 50.waves), + // This assertion tells us that the generating balance + // was updated by a transaction in this block. + assertBalancesInRide(59.99.waves, 59.99.waves, 59.99.waves, 59.99.waves) + ) + } + } + + "The generating balance is affected by transactions in the current block" - { + "RideV5, STDLIB_VERSION 5" in + testGBAffectedByTxInCurrentBlock(DomainPresets.RideV5, V5) + + "RideV6, STDLIB_VERSION 6" in + testGBAffectedByTxInCurrentBlock(DomainPresets.RideV6, V6) + + "ConsensusImprovements, STDLIB_VERSION 6" in + testGBAffectedByTxInCurrentBlock(DomainPresets.ConsensusImprovements, V6) + + "ContinuationTransaction, STDLIB_VERSION 6" in + testGBAffectedByTxInCurrentBlock(DomainPresets.ContinuationTransaction, V6) + + "BlockRewardDistribution, STDLIB_VERSION 7" in + testGBAffectedByTxInCurrentBlock(DomainPresets.BlockRewardDistribution, V7) + + "TransactionStateSnapshot, STDLIB_VERSION 8" in + testGBAffectedByTxInCurrentBlock(DomainPresets.TransactionStateSnapshot, V8) + } + +} diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/RideV5FailRejectTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/RideV5FailRejectTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/RideV5FailRejectTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/RideV5FailRejectTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/ScriptActionsTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/ScriptActionsTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/ScriptActionsTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/ScriptActionsTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/ScriptTransferByAliasTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/ScriptTransferByAliasTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/ScriptTransferByAliasTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/ScriptTransferByAliasTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/ScriptTransferTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/ScriptTransferTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/ScriptTransferTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/ScriptTransferTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/TransactionAssetChecksTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/TransactionAssetChecksTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/TransactionAssetChecksTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/TransactionAssetChecksTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/package.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/package.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/package.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/package.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/InvokeScriptTransactionCrosscontractInvokeDiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/InvokeScriptTransactionCrosscontractInvokeDiffTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/InvokeScriptTransactionCrosscontractInvokeDiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/InvokeScriptTransactionCrosscontractInvokeDiffTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppBalanceCheckTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppBalanceCheckTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppBalanceCheckTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppBalanceCheckTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppBurnTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppBurnTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppBurnTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppBurnTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppComplexityCountTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppComplexityCountTest.scala similarity index 99% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppComplexityCountTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppComplexityCountTest.scala index a5e0a53508..669e7bd2d8 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppComplexityCountTest.scala +++ b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppComplexityCountTest.scala @@ -212,9 +212,9 @@ class SyncDAppComplexityCountTest extends PropSpec with WithDomain { val expectedPortfolios = if (exceeding || raiseError) basePortfolios else basePortfolios |+| additionalPortfolios expectedPortfolios .foreach { case (address, expectedPortfolio) => - expectedPortfolio.balance shouldBe snapshot.balances.get((address, Waves)).map(_ - db.balance(address)).getOrElse(0) + expectedPortfolio.balance shouldBe snapshot.balances.get((address, Waves)).map(_ - db.balance(address)).getOrElse(0L) expectedPortfolio.assets.foreach { case (asset, balance) => - balance shouldBe snapshot.balances.get((address, asset)).map(_ - db.balance(address, asset)).getOrElse(0) + balance shouldBe snapshot.balances.get((address, asset)).map(_ - db.balance(address, asset)).getOrElse(0L) } } } diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppDoubleIssueTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppDoubleIssueTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppDoubleIssueTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppDoubleIssueTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppErrorLogTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppErrorLogTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppErrorLogTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppErrorLogTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppForbidOldVersionsTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppForbidOldVersionsTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppForbidOldVersionsTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppForbidOldVersionsTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppGeneratingBalanceTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppGeneratingBalanceTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppGeneratingBalanceTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppGeneratingBalanceTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppLeaseBalanceCheckTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppLeaseBalanceCheckTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppLeaseBalanceCheckTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppLeaseBalanceCheckTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppLimits.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppLimits.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppLimits.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppLimits.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppListArgTypesTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppListArgTypesTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppListArgTypesTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppListArgTypesTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppMultiVersionTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppMultiVersionTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppMultiVersionTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppMultiVersionTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppNegativeIssueTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppNegativeIssueTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppNegativeIssueTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppNegativeIssueTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppNegativeLeaseTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppNegativeLeaseTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppNegativeLeaseTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppNegativeLeaseTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppNegativeSponsorFeeTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppNegativeSponsorFeeTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppNegativeSponsorFeeTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppNegativeSponsorFeeTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppPaymentTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppPaymentTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppPaymentTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppPaymentTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppRecursionTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppRecursionTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppRecursionTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppRecursionTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppReissueTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppReissueTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppReissueTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppReissueTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppTransferTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppTransferTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppTransferTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppTransferTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppTxFailOrRejectTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppTxFailOrRejectTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppTxFailOrRejectTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncDAppTxFailOrRejectTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeActionsTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeActionsTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeActionsTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeActionsTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeDiffTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeDiffTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeDiffTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeDiffTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeFailAndRejectTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeFailAndRejectTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeFailAndRejectTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeFailAndRejectTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeLeaseTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeLeaseTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeLeaseTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeLeaseTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokePaymentValidationOrderTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokePaymentValidationOrderTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokePaymentValidationOrderTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokePaymentValidationOrderTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeTotalPaymentsTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeTotalPaymentsTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeTotalPaymentsTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeTotalPaymentsTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeValidationTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeValidationTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeValidationTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeValidationTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/freecall/InvokeExpressionTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/freecall/InvokeExpressionTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/freecall/InvokeExpressionTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/freecall/InvokeExpressionTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/DiffComplexityCountTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/DiffComplexityCountTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/DiffComplexityCountTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/DiffComplexityCountTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/EstimationSwitchTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/EstimationSwitchTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/EstimationSwitchTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/EstimationSwitchTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/MaxCallableComplexityTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/MaxCallableComplexityTest.scala similarity index 99% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/MaxCallableComplexityTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/MaxCallableComplexityTest.scala index 025bcd8807..cfbf653781 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/smart/MaxCallableComplexityTest.scala +++ b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/MaxCallableComplexityTest.scala @@ -12,7 +12,7 @@ import com.wavesplatform.lang.v1.compiler.TestCompiler import com.wavesplatform.state.diffs.ENOUGH_AMT import com.wavesplatform.test.{NumericExt, PropSpec, TestTime} import com.wavesplatform.transaction.Asset.Waves -import com.wavesplatform.transaction.{GenesisTransaction, Proofs, TxVersion} +import com.wavesplatform.transaction.{GenesisTransaction, Proofs, TxVersion, TransactionSignOps} import com.wavesplatform.transaction.smart.{InvokeScriptTransaction, SetScriptTransaction} class MaxCallableComplexityTest extends PropSpec with WithDomain with TransactionGenBase { diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/RideExceptionsTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/RideExceptionsTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/RideExceptionsTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/RideExceptionsTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/SetScriptTransactionRideTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/SetScriptTransactionRideTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/SetScriptTransactionRideTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/SetScriptTransactionRideTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/SmartAccountFeeTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/SmartAccountFeeTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/SmartAccountFeeTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/SmartAccountFeeTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/SmartAssetEvalTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/SmartAssetEvalTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/SmartAssetEvalTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/SmartAssetEvalTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/VerifierComplexityLimitTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/VerifierComplexityLimitTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/VerifierComplexityLimitTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/VerifierComplexityLimitTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumInvokePaymentTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumInvokePaymentTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumInvokePaymentTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumInvokePaymentTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumInvokeTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumInvokeTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumInvokeTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumInvokeTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumTransferFeeTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumTransferFeeTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumTransferFeeTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumTransferFeeTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumTransferSmartTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumTransferSmartTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumTransferSmartTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/eth/EthereumTransferSmartTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/package.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/package.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/package.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/package.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/performance/SigVerifyPerformanceTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/performance/SigVerifyPerformanceTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/performance/SigVerifyPerformanceTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/performance/SigVerifyPerformanceTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/AddressTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/AddressTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/AddressTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/AddressTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/BrokenUnicodeTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/BrokenUnicodeTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/BrokenUnicodeTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/BrokenUnicodeTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/CalculateDelayTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/CalculateDelayTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/CalculateDelayTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/CalculateDelayTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/CommonFunctionsTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/CommonFunctionsTest.scala similarity index 98% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/CommonFunctionsTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/CommonFunctionsTest.scala index 7c52bf51ab..de63611500 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/CommonFunctionsTest.scala +++ b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/CommonFunctionsTest.scala @@ -140,7 +140,7 @@ class CommonFunctionsTest extends PropSpec { TxHelpers.issue(version = TxVersion.V1), createMassTransfer() ).foreach { tx => - Try[Either[String, ?]] { + Try { runScript( s""" |let t = 100 @@ -153,7 +153,7 @@ class CommonFunctionsTest extends PropSpec { |""".stripMargin, Coproduct(tx) ) - }.recover { + }.recover[Any] { case ex: MatchError => Assertions.assert(ex.getMessage().contains("Compilation failed: Value 't' already defined in the scope")) case _: Throwable => Assertions.fail("Some unexpected error") @@ -171,7 +171,7 @@ class CommonFunctionsTest extends PropSpec { | } |""".stripMargin ) - }.recover { + }.recover[Any] { case ex: MatchError => Assertions.assert(ex.getMessage().contains("Compilation failed: A definition of 'p' is not found")) case _: Throwable => Assertions.fail("Some unexpected error") } @@ -274,7 +274,7 @@ class CommonFunctionsTest extends PropSpec { (s"Addr(base58'$realAddr')", "Can't find a function 'Addr'") ) for ((clause, err) <- cases) { - Try[Either[String, ?]] { + Try { runScript( s""" |match tx { @@ -285,7 +285,7 @@ class CommonFunctionsTest extends PropSpec { |} |""".stripMargin ) - }.recover { + }.recover[Any] { case ex: MatchError => Assertions.assert(ex.getMessage().contains(err)) case e: Throwable => Assertions.fail("Unexpected error", e) } diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/ContextFunctionsTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/ContextFunctionsTest.scala similarity index 92% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/ContextFunctionsTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/ContextFunctionsTest.scala index 87a67f9824..8530f2136e 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/ContextFunctionsTest.scala +++ b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/ContextFunctionsTest.scala @@ -15,6 +15,7 @@ import com.wavesplatform.lang.Testing.* import com.wavesplatform.lang.directives.values.* import com.wavesplatform.lang.directives.{DirectiveDictionary, DirectiveSet} import com.wavesplatform.lang.script.ContractScript +import com.wavesplatform.lang.v1.compiler.Terms.CONST_LONG import com.wavesplatform.lang.v1.compiler.{ContractCompiler, TestCompiler} import com.wavesplatform.lang.v1.estimator.v2.ScriptEstimatorV2 import com.wavesplatform.lang.v1.evaluator.ctx.impl.waves.WavesContext @@ -31,6 +32,7 @@ import com.wavesplatform.transaction.smart.script.ScriptCompiler import com.wavesplatform.transaction.{TxHelpers, TxVersion} import com.wavesplatform.utils.* import org.scalatest.Assertion +import org.scalatest.OptionValues.convertOptionToValuable import shapeless.Coproduct class ContextFunctionsTest extends PropSpec with WithDomain with EthHelpers { @@ -618,6 +620,84 @@ class ContextFunctionsTest extends PropSpec with WithDomain with EthHelpers { } } + property("Block reward boost is visible in dApp scripts") { + val daoAddress = TxHelpers.address(1003).toString + val xtnAddress = TxHelpers.address(1004).toString + val miner = TxHelpers.signer(1005) + val invoker = TxHelpers.signer(1006) + val dapp = TxHelpers.signer(1007) + val settings = ConsensusImprovements + .setFeaturesHeight( + BlockchainFeatures.BlockRewardDistribution -> 0, + BlockchainFeatures.CappedReward -> 0, + BlockchainFeatures.BoostBlockReward -> 5 + ) + .configure(fs => + fs.copy( + blockRewardBoostPeriod = 10, + daoAddress = Some(daoAddress), + xtnBuybackAddress = Some(xtnAddress) + ) + ) + + withDomain( + settings, + Seq( + AddrWithBalance(miner.toAddress, 100_000.waves), + AddrWithBalance(invoker.toAddress, 100.waves), + AddrWithBalance(dapp.toAddress, 100.waves) + ) + ) { d => + d.appendBlock( + TxHelpers.setScript( + dapp, + TestCompiler(V7).compileContract(s""" + func findRewardsFor(rewards: List[(Address, Int)], addr: Address) = { + func check(prev: Int|Unit, next: (Address, Int)) = match prev { + case _: Unit => + let (thisAddr, share) = next + if (thisAddr == addr) then share else unit + case _ => prev + } + + FOLD<3>(rewards, unit, check) + } + + @Callable(i) + func storeBlockInfo(height: Int) = { + let prefix = i.transactionId.toBase58String() + "_" + let blockInfo = blockInfoByHeight(height).value() + [ + IntegerEntry(prefix + "miner", findRewardsFor(blockInfo.rewards, blockInfo.generator).valueOrElse(0)), + IntegerEntry(prefix + "dao", findRewardsFor(blockInfo.rewards, addressFromStringValue("$daoAddress")).valueOrElse(0)), + IntegerEntry(prefix + "xtn", findRewardsFor(blockInfo.rewards, addressFromStringValue("$xtnAddress")).valueOrElse(0)) + ] + }""") + ) + ) + + def checkHeight(height: Int, minerShare: Long, daoShare: Long, xtnShare: Long): Unit = { + val invocation = TxHelpers.invoke(dapp.toAddress, Some("storeBlockInfo"), Seq(CONST_LONG(height)), invoker = invoker) + + d.appendBlock(d.createBlock(Block.RewardBlockVersion, Seq(invocation), generator = miner)) + + d.blockchain.accountData(dapp.toAddress, invocation.id().toString + "_miner").value.value shouldBe minerShare + d.blockchain.accountData(dapp.toAddress, invocation.id().toString + "_dao").value.value shouldBe daoShare + d.blockchain.accountData(dapp.toAddress, invocation.id().toString + "_xtn").value.value shouldBe xtnShare + } + + checkHeight(3, 2.waves, 2.waves, 2.waves) + d.appendBlock() + (1 to 10).foreach(i => checkHeight(i + 4, 20.waves, 20.waves, 20.waves)) + checkHeight(15, 2.waves, 2.waves, 2.waves) + + // check historic blocks again after deactivation + checkHeight(3, 2.waves, 2.waves, 2.waves) + checkHeight(5, 20.waves, 20.waves, 20.waves) + checkHeight(15, 2.waves, 2.waves, 2.waves) + } + } + property("transfer transaction by id") { val (masterAcc, _, genesis, setScriptTransactions, dataTransaction, transferTx, transfer2) = preconditionsAndPayments setScriptTransactions.foreach { setScriptTransaction => diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/DAppVerifierRestrictionsTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/DAppVerifierRestrictionsTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/DAppVerifierRestrictionsTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/DAppVerifierRestrictionsTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/GenericRideActivationTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/GenericRideActivationTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/GenericRideActivationTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/GenericRideActivationTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/IsDataStorageUntouchedTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/IsDataStorageUntouchedTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/IsDataStorageUntouchedTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/IsDataStorageUntouchedTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/MatcherBlockchainTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/MatcherBlockchainTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/MatcherBlockchainTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/MatcherBlockchainTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/ObsoleteTransactionBindingsTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/ObsoleteTransactionBindingsTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/ObsoleteTransactionBindingsTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/ObsoleteTransactionBindingsTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/PowNewPrecisionTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/PowNewPrecisionTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/PowNewPrecisionTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/PowNewPrecisionTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/RideCreateMerkleRootTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/RideCreateMerkleRootTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/RideCreateMerkleRootTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/RideCreateMerkleRootTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/RideVersionDeactivationTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/RideVersionDeactivationTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/RideVersionDeactivationTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/RideVersionDeactivationTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/ScriptVersionsTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/ScriptVersionsTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/ScriptVersionsTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/ScriptVersionsTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/SerContextFunctionsTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/SerContextFunctionsTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/SerContextFunctionsTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/SerContextFunctionsTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/TransactionBindingsTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/TransactionBindingsTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/TransactionBindingsTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/TransactionBindingsTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/package.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/package.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/package.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/predef/package.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/AddressFromRecipientScenarioTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/AddressFromRecipientScenarioTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/AddressFromRecipientScenarioTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/AddressFromRecipientScenarioTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/BalancesV4Test.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/BalancesV4Test.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/BalancesV4Test.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/BalancesV4Test.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/MultiSig2of3Test.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/MultiSig2of3Test.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/MultiSig2of3Test.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/MultiSig2of3Test.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/NotaryControlledTransferScenarioTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/NotaryControlledTransferScenarioTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/NotaryControlledTransferScenarioTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/NotaryControlledTransferScenarioTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/OneProofForNonScriptedAccountTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/OneProofForNonScriptedAccountTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/OneProofForNonScriptedAccountTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/OneProofForNonScriptedAccountTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/OnlyTransferIsAllowedTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/OnlyTransferIsAllowedTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/OnlyTransferIsAllowedTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/OnlyTransferIsAllowedTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/OracleDataTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/OracleDataTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/OracleDataTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/OracleDataTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/ScriptedSponsorTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/ScriptedSponsorTest.scala similarity index 95% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/ScriptedSponsorTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/ScriptedSponsorTest.scala index 260f741954..b2be547195 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/ScriptedSponsorTest.scala +++ b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/ScriptedSponsorTest.scala @@ -82,7 +82,7 @@ class ScriptedSponsorTest extends PropSpec with WithState { val otherAcc = TxHelpers.signer(3) val genesis = Seq(contract, recipient).map(acc => TxHelpers.genesis(acc.toAddress)) - val (script, _) = ScriptCompiler(s"{-# STDLIB_VERSION 2 #-}\n true", isAssetScript = false, estimator).explicitGet() + val (script, _) = ScriptCompiler.compile(s"{-# STDLIB_VERSION 2 #-}\n true", estimator).explicitGet() val issue = TxHelpers.issue(contract, Long.MaxValue, fee = ENOUGH_FEE, version = TxVersion.V1) val asset = IssuedAsset(issue.id()) val sponsorTx = TxHelpers.sponsor(asset, Some(1), contract, fee = SPONSOR_FEE) @@ -98,7 +98,7 @@ class ScriptedSponsorTest extends PropSpec with WithState { val sponsor = TxHelpers.signer(2) val genesis = Seq(contract, sponsor).map(acc => TxHelpers.genesis(acc.toAddress)) - val (script, _) = ScriptCompiler(s"{-# STDLIB_VERSION 2 #-}\n true", isAssetScript = false, estimator).explicitGet() + val (script, _) = ScriptCompiler.compile(s"{-# STDLIB_VERSION 2 #-}\n true", estimator).explicitGet() val issue = TxHelpers.issue(sponsor, Long.MaxValue, fee = ENOUGH_FEE, version = TxVersion.V1) val asset = IssuedAsset(issue.id()) val sponsorTx = TxHelpers.sponsor(asset, Some(1), sponsor, fee = SPONSOR_FEE) diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/TransactionFieldAccessTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/TransactionFieldAccessTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/TransactionFieldAccessTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/TransactionFieldAccessTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/TransferByIdTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/TransferByIdTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/TransferByIdTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/TransferByIdTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/patch/CancelLeasesToDisabledAliasesSpec.scala b/node/tests/src/test/scala/com/wavesplatform/state/patch/CancelLeasesToDisabledAliasesSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/patch/CancelLeasesToDisabledAliasesSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/state/patch/CancelLeasesToDisabledAliasesSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/state/reader/StateReaderEffectiveBalancePropertyTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/reader/StateReaderEffectiveBalancePropertyTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/reader/StateReaderEffectiveBalancePropertyTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/reader/StateReaderEffectiveBalancePropertyTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/rollback/EthereumTransactionRollbackSpec.scala b/node/tests/src/test/scala/com/wavesplatform/state/rollback/EthereumTransactionRollbackSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/rollback/EthereumTransactionRollbackSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/state/rollback/EthereumTransactionRollbackSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/state/snapshot/StateSnapshotStorageTest.scala b/node/tests/src/test/scala/com/wavesplatform/state/snapshot/StateSnapshotStorageTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/snapshot/StateSnapshotStorageTest.scala rename to node/tests/src/test/scala/com/wavesplatform/state/snapshot/StateSnapshotStorageTest.scala diff --git a/node/src/test/scala/com/wavesplatform/state/snapshot/TxStateSnapshotHashSpec.scala b/node/tests/src/test/scala/com/wavesplatform/state/snapshot/TxStateSnapshotHashSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/state/snapshot/TxStateSnapshotHashSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/state/snapshot/TxStateSnapshotHashSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/test/RandomKeyPair.scala b/node/tests/src/test/scala/com/wavesplatform/test/RandomKeyPair.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/test/RandomKeyPair.scala rename to node/tests/src/test/scala/com/wavesplatform/test/RandomKeyPair.scala diff --git a/node/src/test/scala/com/wavesplatform/test/SharedDomain.scala b/node/tests/src/test/scala/com/wavesplatform/test/SharedDomain.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/test/SharedDomain.scala rename to node/tests/src/test/scala/com/wavesplatform/test/SharedDomain.scala diff --git a/node/src/test/scala/com/wavesplatform/test/node/package.scala b/node/tests/src/test/scala/com/wavesplatform/test/node/package.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/test/node/package.scala rename to node/tests/src/test/scala/com/wavesplatform/test/node/package.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/ABIConverterSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/ABIConverterSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/ABIConverterSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/ABIConverterSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/BlockchainUpdaterTest.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/BlockchainUpdaterTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/BlockchainUpdaterTest.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/BlockchainUpdaterTest.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/BurnTransactionSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/BurnTransactionSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/BurnTransactionSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/BurnTransactionSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/ChainIdSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/ChainIdSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/ChainIdSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/ChainIdSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/CreateAliasTransactionSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/CreateAliasTransactionSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/CreateAliasTransactionSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/CreateAliasTransactionSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/DataTransactionSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/DataTransactionSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/DataTransactionSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/DataTransactionSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/EthTxGenerator.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/EthTxGenerator.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/EthTxGenerator.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/EthTxGenerator.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/GenericTransactionSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/GenericTransactionSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/GenericTransactionSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/GenericTransactionSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/GenesisTransactionSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/GenesisTransactionSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/GenesisTransactionSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/GenesisTransactionSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/InvokeScriptComplexitySpec.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/InvokeScriptComplexitySpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/InvokeScriptComplexitySpec.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/InvokeScriptComplexitySpec.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/InvokeScriptTransactionSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/InvokeScriptTransactionSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/InvokeScriptTransactionSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/InvokeScriptTransactionSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/IssueTransactionV1Specification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/IssueTransactionV1Specification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/IssueTransactionV1Specification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/IssueTransactionV1Specification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/IssueTransactionV2Specification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/IssueTransactionV2Specification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/IssueTransactionV2Specification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/IssueTransactionV2Specification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/LeaseCancelTransactionSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/LeaseCancelTransactionSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/LeaseCancelTransactionSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/LeaseCancelTransactionSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/LeaseTransactionSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/LeaseTransactionSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/LeaseTransactionSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/LeaseTransactionSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/MassTransferTransactionSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/MassTransferTransactionSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/MassTransferTransactionSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/MassTransferTransactionSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/ProtoVersionTransactionsSpec.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/ProtoVersionTransactionsSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/ProtoVersionTransactionsSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/ProtoVersionTransactionsSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/ReissueTransactionV1Specification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/ReissueTransactionV1Specification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/ReissueTransactionV1Specification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/ReissueTransactionV1Specification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/ReissueTransactionV2Specification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/ReissueTransactionV2Specification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/ReissueTransactionV2Specification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/ReissueTransactionV2Specification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/SetAssetScriptTransactionSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/SetAssetScriptTransactionSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/SetAssetScriptTransactionSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/SetAssetScriptTransactionSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/SetScriptTransactionSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/SetScriptTransactionSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/SetScriptTransactionSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/SetScriptTransactionSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/SponsorFeeTransactionSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/SponsorFeeTransactionSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/SponsorFeeTransactionSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/SponsorFeeTransactionSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/TransactionFeeSpec.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/TransactionFeeSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/TransactionFeeSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/TransactionFeeSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/TransactionSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/TransactionSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/TransactionSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/TransactionSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/TransferTransactionV1Specification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/TransferTransactionV1Specification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/TransferTransactionV1Specification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/TransferTransactionV1Specification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/TransferTransactionV2Specification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/TransferTransactionV2Specification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/TransferTransactionV2Specification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/TransferTransactionV2Specification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/TxNonNegativeAmountTest.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/TxNonNegativeAmountTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/TxNonNegativeAmountTest.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/TxNonNegativeAmountTest.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/UpdateAssetInfoTransactionSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/UpdateAssetInfoTransactionSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/UpdateAssetInfoTransactionSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/UpdateAssetInfoTransactionSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/ValidationMatcher.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/ValidationMatcher.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/ValidationMatcher.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/ValidationMatcher.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/api/http/alias/AliasRequestTests.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/api/http/alias/AliasRequestTests.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/api/http/alias/AliasRequestTests.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/api/http/alias/AliasRequestTests.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/api/http/assets/SignedRequestsTest.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/api/http/assets/SignedRequestsTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/api/http/assets/SignedRequestsTest.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/api/http/assets/SignedRequestsTest.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/api/http/leasing/LeaseV1RequestsTests.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/api/http/leasing/LeaseV1RequestsTests.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/api/http/leasing/LeaseV1RequestsTests.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/api/http/leasing/LeaseV1RequestsTests.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/assets/Erc20NoConflictIssueTest.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/assets/Erc20NoConflictIssueTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/assets/Erc20NoConflictIssueTest.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/assets/Erc20NoConflictIssueTest.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/assets/exchange/EthOrderSpec.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/assets/exchange/EthOrderSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/assets/exchange/EthOrderSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/assets/exchange/EthOrderSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/assets/exchange/ExchangeTransactionSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/assets/exchange/ExchangeTransactionSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/assets/exchange/ExchangeTransactionSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/assets/exchange/ExchangeTransactionSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/assets/exchange/OrderJsonSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/assets/exchange/OrderJsonSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/assets/exchange/OrderJsonSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/assets/exchange/OrderJsonSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/assets/exchange/OrderSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/assets/exchange/OrderSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/assets/exchange/OrderSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/assets/exchange/OrderSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/assets/exchange/PBOrdersSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/assets/exchange/PBOrdersSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/assets/exchange/PBOrdersSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/assets/exchange/PBOrdersSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/data/DataTransactionNewLimitsSpec.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/data/DataTransactionNewLimitsSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/data/DataTransactionNewLimitsSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/data/DataTransactionNewLimitsSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/smart/EthereumTransactionSpec.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/smart/EthereumTransactionSpec.scala similarity index 99% rename from node/src/test/scala/com/wavesplatform/transaction/smart/EthereumTransactionSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/smart/EthereumTransactionSpec.scala index c3d1e65655..44dcb94514 100644 --- a/node/src/test/scala/com/wavesplatform/transaction/smart/EthereumTransactionSpec.scala +++ b/node/tests/src/test/scala/com/wavesplatform/transaction/smart/EthereumTransactionSpec.scala @@ -106,7 +106,7 @@ class EthereumTransactionSpec val assetTransfer = EthTxGenerator.generateEthTransfer(senderAccount, recipientAddress, Long.MaxValue, TestAsset) differ(assetTransfer).balances shouldBe Map( - (senderAddress, TestAsset) -> 0, + (senderAddress, TestAsset) -> 0L, (senderAddress, Waves) -> (LongMaxMinusFee + transfer.fee.longValue()), (recipientAddress, TestAsset) -> Long.MaxValue ) diff --git a/node/src/test/scala/com/wavesplatform/transaction/smart/EthereumTransactionStateChangesSpec.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/smart/EthereumTransactionStateChangesSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/smart/EthereumTransactionStateChangesSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/smart/EthereumTransactionStateChangesSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/smart/OrderProofTest.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/smart/OrderProofTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/smart/OrderProofTest.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/smart/OrderProofTest.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/smart/SubInvokeStateChangesSpec.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/smart/SubInvokeStateChangesSpec.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/smart/SubInvokeStateChangesSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/smart/SubInvokeStateChangesSpec.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/smart/VerifierSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/smart/VerifierSpecification.scala similarity index 98% rename from node/src/test/scala/com/wavesplatform/transaction/smart/VerifierSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/smart/VerifierSpecification.scala index 75e3e9f486..194bd4796d 100644 --- a/node/src/test/scala/com/wavesplatform/transaction/smart/VerifierSpecification.scala +++ b/node/tests/src/test/scala/com/wavesplatform/transaction/smart/VerifierSpecification.scala @@ -90,12 +90,11 @@ class VerifierSpecification extends PropSpec with NTPTime with WithDomain { 1.toByte, sender, Some( - ScriptCompiler( + ScriptCompiler.compile( """match tx { | case _: Order => height >= 0 | case _ => true |}""".stripMargin, - isAssetScript = false, ScriptEstimatorV2 ).explicitGet()._1 ), diff --git a/node/src/test/scala/com/wavesplatform/transaction/smart/script/ScriptCompilerV1Test.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/smart/script/ScriptCompilerV1Test.scala similarity index 95% rename from node/src/test/scala/com/wavesplatform/transaction/smart/script/ScriptCompilerV1Test.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/smart/script/ScriptCompilerV1Test.scala index 240ccdfbcc..ef401aaeaa 100644 --- a/node/src/test/scala/com/wavesplatform/transaction/smart/script/ScriptCompilerV1Test.scala +++ b/node/tests/src/test/scala/com/wavesplatform/transaction/smart/script/ScriptCompilerV1Test.scala @@ -12,33 +12,35 @@ import com.wavesplatform.lang.v1.evaluator.ctx.impl.PureContext import com.wavesplatform.test.* import org.scalatest.{EitherValues, Inside} +import scala.annotation.nowarn + class ScriptCompilerV1Test extends PropSpec with EitherValues with Inside { private val estimator = ScriptEstimatorV2 property("compile script with specified version") { val script = scriptWithVersion("1".some) - ScriptCompiler(script, isAssetScript = false, estimator) shouldBe Right((ExprScript(V1, expectedExpr).explicitGet(), 13)) + ScriptCompiler.compile(script, estimator) shouldBe Right((ExprScript(V1, expectedExpr).explicitGet(), 13)) } property("use version 3 if not specified") { val script = scriptWithVersion(none) - ScriptCompiler(script, isAssetScript = false, estimator) shouldBe Right((ExprScript(V3, expectedExpr).explicitGet(), 13)) + ScriptCompiler.compile(script, estimator) shouldBe Right((ExprScript(V3, expectedExpr).explicitGet(), 13)) } property("fails on unsupported version") { val unsupportedVersionStr = (StdLibVersion.VersionDic.all.max.id + 1).toString val script = scriptWithVersion(unsupportedVersionStr.some) - ScriptCompiler(script, isAssetScript = false, estimator) shouldBe Left(s"Illegal directive value $unsupportedVersionStr for key STDLIB_VERSION") + ScriptCompiler.compile(script, estimator) shouldBe Left(s"Illegal directive value $unsupportedVersionStr for key STDLIB_VERSION") } property("fails on incorrect version value") { val script = scriptWithVersion("oOooOps".some) - ScriptCompiler(script, isAssetScript = false, estimator) shouldBe Left("Illegal directive value oOooOps for key STDLIB_VERSION") + ScriptCompiler.compile(script, estimator) shouldBe Left("Illegal directive value oOooOps for key STDLIB_VERSION") } property("fails on incorrect content type value") { val script = scriptWithContentType("oOooOps".some) - ScriptCompiler(script, isAssetScript = false, estimator) shouldBe Left("Illegal directive value oOooOps for key CONTENT_TYPE") + ScriptCompiler.compile(script, estimator) shouldBe Left("Illegal directive value oOooOps for key CONTENT_TYPE") } property("fails on incorrect script type value") { @@ -143,6 +145,7 @@ class ScriptCompilerV1Test extends PropSpec with EitherValues with Inside { | a && b || c && d """.stripMargin + @nowarn("cat=deprecation") val resultExpr = LET_BLOCK( LET("a", TRUE), LET_BLOCK( @@ -420,6 +423,7 @@ class ScriptCompilerV1Test extends PropSpec with EitherValues with Inside { ScriptCompiler.compile(script, estimator) shouldBe Symbol("right") } + @nowarn private val expectedExpr = LET_BLOCK( LET("x", CONST_LONG(10)), FUNCTION_CALL( diff --git a/node/src/test/scala/com/wavesplatform/transaction/smart/script/ScriptReaderTest.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/smart/script/ScriptReaderTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/smart/script/ScriptReaderTest.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/smart/script/ScriptReaderTest.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/smart/script/ScriptV1Test.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/smart/script/ScriptV1Test.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/smart/script/ScriptV1Test.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/smart/script/ScriptV1Test.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/FunctionComplexityTest.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/FunctionComplexityTest.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/FunctionComplexityTest.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/FunctionComplexityTest.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/FunctionComplexityV1Test.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/FunctionComplexityV1Test.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/FunctionComplexityV1Test.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/FunctionComplexityV1Test.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/FunctionComplexityV2Test.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/FunctionComplexityV2Test.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/FunctionComplexityV2Test.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/FunctionComplexityV2Test.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/UserFunctionComplexityTest.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/UserFunctionComplexityTest.scala similarity index 97% rename from node/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/UserFunctionComplexityTest.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/UserFunctionComplexityTest.scala index 86a85bb7a4..65dad737ea 100644 --- a/node/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/UserFunctionComplexityTest.scala +++ b/node/tests/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/UserFunctionComplexityTest.scala @@ -19,6 +19,8 @@ import com.wavesplatform.transaction.smart.WavesEnvironment import com.wavesplatform.utils.EmptyBlockchain import monix.eval.Coeval +import scala.annotation.nowarn + class UserFunctionComplexityTest(estimator: ScriptEstimator) extends PropSpec { private val environment = WavesEnvironment(chainId, Coeval(???), null, EmptyBlockchain, null, DirectiveSet.contractDirectiveSet, ByteStr.empty) @@ -53,12 +55,14 @@ class UserFunctionComplexityTest(estimator: ScriptEstimator) extends PropSpec { val exprThrow = FUNCTION_CALL(PureContext.throwNoMessage, List()) est(exprThrow).explicitGet() shouldBe 2 + @nowarn("cat=deprecation") val exprExtract = LET_BLOCK( LET("x", CONST_LONG(2)), FUNCTION_CALL(PureContext.extract, List(REF("x"))) ) est(exprExtract).explicitGet() shouldBe 21 + @nowarn("cat=deprecation") val exprIsDefined = LET_BLOCK( LET("x", CONST_LONG(2)), FUNCTION_CALL(PureContext.isDefined, List(REF("x"))) @@ -120,12 +124,14 @@ class UserFunctionComplexityTest(estimator: ScriptEstimator) extends PropSpec { val exprThrow = FUNCTION_CALL(PureContext.throwNoMessage, List()) est(exprThrow).explicitGet() shouldBe 2 + @nowarn("cat=deprecation") val exprExtract = LET_BLOCK( LET("x", CONST_LONG(2)), FUNCTION_CALL(PureContext.extract, List(REF("x"))) ) est(exprExtract).explicitGet() shouldBe 21 + @nowarn("cat=deprecation") val exprIsDefined = LET_BLOCK( LET("x", CONST_LONG(2)), FUNCTION_CALL(PureContext.isDefined, List(REF("x"))) @@ -187,12 +193,14 @@ class UserFunctionComplexityTest(estimator: ScriptEstimator) extends PropSpec { val exprThrow = FUNCTION_CALL(PureContext.throwNoMessage, List()) est(exprThrow).explicitGet() shouldBe 1 + @nowarn("cat=deprecation") val exprExtract = LET_BLOCK( LET("x", CONST_LONG(2)), FUNCTION_CALL(PureContext.extract, List(REF("x"))) ) est(exprExtract).explicitGet() shouldBe 21 + @nowarn("cat=deprecation") val exprIsDefined = LET_BLOCK( LET("x", CONST_LONG(2)), FUNCTION_CALL(PureContext.isDefined, List(REF("x"))) @@ -217,6 +225,7 @@ class UserFunctionComplexityTest(estimator: ScriptEstimator) extends PropSpec { val exprUNot = FUNCTION_CALL(PureContext.uNot, List(TRUE)) est(exprUNot).explicitGet() shouldBe 2 + @nowarn("cat=deprecation") val exprDataByIndex = LET_BLOCK( LET("arr", FUNCTION_CALL(PureContext.listConstructor(checkSize = false), List(CONST_STRING("str_1").explicitGet(), REF(GlobalValNames.Nil)))), FUNCTION_CALL(User("getString"), List(REF("arr"), CONST_LONG(0))) diff --git a/node/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/UserFunctionComplexityV1Test.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/UserFunctionComplexityV1Test.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/UserFunctionComplexityV1Test.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/UserFunctionComplexityV1Test.scala diff --git a/node/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/UserFunctionComplexityV2Test.scala b/node/tests/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/UserFunctionComplexityV2Test.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/UserFunctionComplexityV2Test.scala rename to node/tests/src/test/scala/com/wavesplatform/transaction/smart/script/estimator/UserFunctionComplexityV2Test.scala diff --git a/node/src/test/scala/com/wavesplatform/utils/DiffMatchers.scala b/node/tests/src/test/scala/com/wavesplatform/utils/DiffMatchers.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/utils/DiffMatchers.scala rename to node/tests/src/test/scala/com/wavesplatform/utils/DiffMatchers.scala diff --git a/node/src/test/scala/com/wavesplatform/utils/EthHelpers.scala b/node/tests/src/test/scala/com/wavesplatform/utils/EthHelpers.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/utils/EthHelpers.scala rename to node/tests/src/test/scala/com/wavesplatform/utils/EthHelpers.scala diff --git a/node/src/test/scala/com/wavesplatform/utils/JsonMatchers.scala b/node/tests/src/test/scala/com/wavesplatform/utils/JsonMatchers.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/utils/JsonMatchers.scala rename to node/tests/src/test/scala/com/wavesplatform/utils/JsonMatchers.scala diff --git a/node/src/test/scala/com/wavesplatform/utils/ObservedLoadingCacheSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/utils/ObservedLoadingCacheSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/utils/ObservedLoadingCacheSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/utils/ObservedLoadingCacheSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/utils/SharedSchedulerMixin.scala b/node/tests/src/test/scala/com/wavesplatform/utils/SharedSchedulerMixin.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/utils/SharedSchedulerMixin.scala rename to node/tests/src/test/scala/com/wavesplatform/utils/SharedSchedulerMixin.scala diff --git a/node/src/test/scala/com/wavesplatform/utils/UtilsSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/utils/UtilsSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/utils/UtilsSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/utils/UtilsSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/utx/UtxFailedTxsSpec.scala b/node/tests/src/test/scala/com/wavesplatform/utx/UtxFailedTxsSpec.scala similarity index 86% rename from node/src/test/scala/com/wavesplatform/utx/UtxFailedTxsSpec.scala rename to node/tests/src/test/scala/com/wavesplatform/utx/UtxFailedTxsSpec.scala index c34dc6aaa3..24f436a08d 100644 --- a/node/src/test/scala/com/wavesplatform/utx/UtxFailedTxsSpec.scala +++ b/node/tests/src/test/scala/com/wavesplatform/utx/UtxFailedTxsSpec.scala @@ -193,7 +193,7 @@ class UtxFailedTxsSpec extends FlatSpec with WithDomain with Eventually { utx.packUnconfirmed(MultiDimensionalMiningConstraint.Unlimited, None)._1 shouldBe Some(Seq(tx)) } - it should "cleanup transaction when script result changes" in utxTest { (d, utx) => + it should s"cleanup transaction when script result changes and complexity < ${ContractLimits.FailFreeInvokeComplexity}" in utxTest { (d, utx) => val (script, _) = ScriptCompiler .compile( """ @@ -206,13 +206,8 @@ class UtxFailedTxsSpec extends FlatSpec with WithDomain with Eventually { | if (height % 2 == 0) then | [] | else - | if (!sigVerify(base58'', base58'', base58'') - | && !sigVerify(base58'', base58'', base58'') - | && !sigVerify(base58'', base58'', base58'') - | && !sigVerify(base58'', base58'', base58'')) then - | throw("height is odd") - | else [IntegerEntry("h", height)] - | } + | throw("height is odd") + |} | """.stripMargin, ScriptEstimatorV3.latest ) @@ -229,12 +224,61 @@ class UtxFailedTxsSpec extends FlatSpec with WithDomain with Eventually { utx.size shouldBe 100 d.appendBlock() // Height is odd utx.addAndScheduleCleanup(Nil) - eventually(timeout(10 seconds), interval(500 millis)) { + eventually(timeout(5 seconds), interval(500 millis)) { utx.size shouldBe 0 utx.all shouldBe Nil } } + it should s"not cleanup transaction when script result changes and complexity > ${ContractLimits.FailFreeInvokeComplexity}" in withFS( + TestFunctionalitySettings + .withFeatures( + BlockchainFeatures.NG, + BlockchainFeatures.BlockV5, + BlockchainFeatures.Ride4DApps, + BlockchainFeatures.SynchronousCalls, + BlockchainFeatures.SmartAccounts + ) + )(utxTest { (d, utx) => + val (script, _) = ScriptCompiler + .compile( + s"""{-# STDLIB_VERSION 5 #-} + |{-# CONTENT_TYPE DAPP #-} + |{-# SCRIPT_TYPE ACCOUNT #-} + | + |@Callable(i) + |func test1000() = { + | if (height % 2 == 0) then + | [] + | else + | if (${"sigVerify(base58'', base58'', base58'') ||" * 8} true) then + | throw("height is odd") + | else throw("smth wrong") + |} + |""".stripMargin, + ScriptEstimatorV3.latest + ) + .explicitGet() + + d.appendBlock(TxHelpers.setScript(dApp, script)) + assert(d.blockchainUpdater.height % 2 == 0) + val invoke = TxHelpers.invoke(dApp.toAddress, Some("test1000")) + utx.putIfNew(invoke, forceValidate = true).resultE.explicitGet() + + utx.size shouldBe 1 + d.appendKeyBlock() // Height is odd + utx.addAndScheduleCleanup(Nil) + eventually(timeout(3 seconds), interval(500 millis)) { + utx.size shouldBe 1 + utx.all shouldBe Seq(invoke) + } + + utx.packUnconfirmed(MultiDimensionalMiningConstraint.Unlimited, None)._1 shouldBe Some(Seq(invoke)) + d.appendMicroBlock(invoke) + + d.blockchain.transactionMeta(invoke.id()) shouldBe Some(TxMeta(Height(3), Status.Failed, 1614)) + }) + private[this] def genExpr(targetComplexity: Int, result: Boolean): String = { s""" |if ($result) then diff --git a/node/src/test/scala/com/wavesplatform/utx/UtxPoolSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/utx/UtxPoolSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/utx/UtxPoolSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/utx/UtxPoolSpecification.scala diff --git a/node/src/test/scala/com/wavesplatform/utx/UtxPriorityPoolSpecification.scala b/node/tests/src/test/scala/com/wavesplatform/utx/UtxPriorityPoolSpecification.scala similarity index 100% rename from node/src/test/scala/com/wavesplatform/utx/UtxPriorityPoolSpecification.scala rename to node/tests/src/test/scala/com/wavesplatform/utx/UtxPriorityPoolSpecification.scala diff --git a/node/src/test/scala/tools/FirstDifferentBlock.scala b/node/tests/src/test/scala/tools/FirstDifferentBlock.scala similarity index 100% rename from node/src/test/scala/tools/FirstDifferentBlock.scala rename to node/tests/src/test/scala/tools/FirstDifferentBlock.scala diff --git a/project/CommonSettings.scala b/project/CommonSettings.scala index db0472ff95..ed9b3a2a44 100644 --- a/project/CommonSettings.scala +++ b/project/CommonSettings.scala @@ -1,14 +1,36 @@ -import sbt.Keys._ -import sbt._ +import sbt.* +import sbt.Keys.{test, version, name} +import sbtassembly.AssemblyKeys.{assembly, assemblyMergeStrategy} +import sbtassembly.AssemblyPlugin.autoImport.assemblyJarName +import sbtassembly.{MergeStrategy, PathList} object CommonSettings extends AutoPlugin { object autoImport extends CommonKeys - import autoImport._ override def trigger: PluginTrigger = allRequirements // These options doesn't work for ScalaJS - override def projectSettings: Seq[Def.Setting[_]] = Seq() + override def projectSettings: Seq[Def.Setting[?]] = Seq() + + val assemblySettings: Seq[Def.Setting[?]] = Seq( + assemblyJarName := s"${name.value}-all-${version.value}.jar", + test := {}, + assemblyMergeStrategy := { + case p + if p.endsWith(".proto") || + p.endsWith("module-info.class") || + p.endsWith("io.netty.versions.properties") || + p.endsWith(".kotlin_module") => + MergeStrategy.discard + + case "scala-collection-compat.properties" => + MergeStrategy.discard + + case "logback.xml" | PathList("scala", "util", "control", "compat") | PathList("scala", "collection", "compat") | + PathList("swagger-ui", "openapi.yaml") => + MergeStrategy.last + case other => (assembly / assemblyMergeStrategy).value(other) + }) } trait CommonKeys { diff --git a/project/Dependencies.scala b/project/Dependencies.scala index e169b40121..ad232f5a97 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -12,7 +12,7 @@ object Dependencies { private def akkaHttpModule(module: String) = "com.typesafe.akka" %% module % "10.2.10" - private def kamonModule(module: String) = "io.kamon" %% s"kamon-$module" % "2.7.0" + private def kamonModule(module: String) = "io.kamon" %% s"kamon-$module" % "2.7.5" private def jacksonModule(group: String, module: String) = s"com.fasterxml.jackson.$group" % s"jackson-$module" % "2.15.3" @@ -20,31 +20,31 @@ object Dependencies { def monixModule(module: String): Def.Initialize[ModuleID] = Def.setting("io.monix" %%% s"monix-$module" % "3.4.1") - private def grpcModule(module: String) = "io.grpc" % module % "1.61.0" + private def grpcModule(module: String) = "io.grpc" % module % "1.68.0" - val kindProjector = compilerPlugin("org.typelevel" % "kind-projector" % "0.13.2" cross CrossVersion.full) + val kindProjector = compilerPlugin("org.typelevel" % "kind-projector" % "0.13.3" cross CrossVersion.full) val akkaHttp = akkaHttpModule("akka-http") - val googleGuava = "com.google.guava" % "guava" % "33.0.0-jre" + val googleGuava = "com.google.guava" % "guava" % "33.3.1-jre" val kamonCore = kamonModule("core") val machinist = "org.typelevel" %% "machinist" % "0.6.8" - val logback = "ch.qos.logback" % "logback-classic" % "1.4.14" - val janino = "org.codehaus.janino" % "janino" % "3.1.11" - val asyncHttpClient = "org.asynchttpclient" % "async-http-client" % "2.12.3" + val logback = "ch.qos.logback" % "logback-classic" % "1.5.11" + val janino = "org.codehaus.janino" % "janino" % "3.1.12" + val asyncHttpClient = "org.asynchttpclient" % "async-http-client" % "3.0.0" val curve25519 = "com.wavesplatform" % "curve25519-java" % "0.6.6" - val nettyHandler = "io.netty" % "netty-handler" % "4.1.106.Final" + val nettyHandler = "io.netty" % "netty-handler" % "4.1.110.Final" - val shapeless = Def.setting("com.chuusai" %%% "shapeless" % "2.3.10") + val shapeless = Def.setting("com.chuusai" %%% "shapeless" % "2.3.12") - val playJson = "com.typesafe.play" %% "play-json" % "2.10.4" + val playJson = "com.typesafe.play" %% "play-json" % "2.10.6" - val scalaTest = "org.scalatest" %% "scalatest" % "3.2.17" % Test - val scalaJsTest = Def.setting("com.lihaoyi" %%% "utest" % "0.8.2" % Test) + val scalaTest = "org.scalatest" %% "scalatest" % "3.2.19" % Test + val scalaJsTest = Def.setting("com.lihaoyi" %%% "utest" % "0.8.4" % Test) - val sttp3 = "com.softwaremill.sttp.client3" % "core_2.13" % "3.9.2" - val sttp3Monix = "com.softwaremill.sttp.client3" %% "monix" % "3.9.2" + val sttp3 = "com.softwaremill.sttp.client3" % "core_2.13" % "3.10.1" + val sttp3Monix = "com.softwaremill.sttp.client3" %% "monix" % "3.10.1" - val bouncyCastleProvider = "org.bouncycastle" % s"bcprov-jdk18on" % "1.77" + val bouncyCastleProvider = "org.bouncycastle" % s"bcprov-jdk18on" % "1.78.1" val console = Seq("com.github.scopt" %% "scopt" % "4.1.0") @@ -60,38 +60,38 @@ object Dependencies { // defined here because %%% can only be used within a task or setting macro // explicit dependency can likely be removed when monix 3 is released monixModule("eval").value, - "org.typelevel" %%% s"cats-core" % "2.10.0", - "com.lihaoyi" %%% "fastparse" % "3.0.2", + "org.typelevel" %%% s"cats-core" % "2.12.0", + "com.lihaoyi" %%% "fastparse" % "3.1.1", shapeless.value, - "org.typelevel" %%% "cats-mtl" % "1.4.0", + "org.typelevel" %%% "cats-mtl" % "1.5.0", "ch.obermuhlner" % "big-math" % "2.3.2", googleGuava, // BaseEncoding.base16() curve25519, bouncyCastleProvider, "com.wavesplatform" % "zwaves" % "0.2.1", - web3jModule("crypto").excludeAll(ExclusionRule("org.bouncycastle", "bcprov-jdk15on")), + web3jModule("crypto").excludeAll(ExclusionRule("org.bouncycastle", "bcprov-jdk15on")) ) ++ langCompilerPlugins.value ++ scalapbRuntime.value ++ protobuf.value ) lazy val it = scalaTest +: Seq( logback, - "com.github.jnr" % "jnr-unixsocket" % "0.38.21", // To support Apple ARM + "com.github.jnr" % "jnr-unixsocket" % "0.38.23", // To support Apple ARM "com.spotify" % "docker-client" % "8.16.0", - "com.fasterxml.jackson.dataformat" % "jackson-dataformat-properties" % "2.16.1", + "com.fasterxml.jackson.dataformat" % "jackson-dataformat-properties" % "2.18.0", asyncHttpClient ).map(_ % Test) lazy val test = scalaTest +: Seq( logback, "org.scalatestplus" %% "scalacheck-1-16" % "3.2.14.0", - "org.scalacheck" %% "scalacheck" % "1.17.0", + "org.scalacheck" %% "scalacheck" % "1.18.1", "org.mockito" % "mockito-all" % "1.10.19", - "org.scalamock" %% "scalamock" % "5.2.0" + "org.scalamock" %% "scalamock" % "6.0.0" ).map(_ % Test) lazy val qaseReportDeps = Seq( playJson, - ("io.qase" % "qase-api" % "3.2.0").excludeAll(ExclusionRule(organization = "javax.ws.rs")) + ("io.qase" % "qase-api" % "3.2.1").excludeAll(ExclusionRule(organization = "javax.ws.rs")) ).map(_ % Test) lazy val logDeps = Seq( @@ -100,16 +100,16 @@ object Dependencies { akkaModule("slf4j") % Runtime ) - private val rocksdb = "org.rocksdb" % "rocksdbjni" % "8.10.0" + private val rocksdb = "org.rocksdb" % "rocksdbjni" % "9.6.1" lazy val node = Def.setting( Seq( rocksdb, ("org.rudogma" %%% "supertagged" % "2.0-RC2").exclude("org.scala-js", "scalajs-library_2.13"), - "commons-net" % "commons-net" % "3.10.0", - "commons-io" % "commons-io" % "2.15.1", + "commons-net" % "commons-net" % "3.11.1", + "commons-io" % "commons-io" % "2.17.0", "com.iheart" %% "ficus" % "1.5.2", - "net.logstash.logback" % "logstash-logback-encoder" % "7.4" % Runtime, + "net.logstash.logback" % "logstash-logback-encoder" % "8.0" % Runtime, kamonCore, kamonModule("system-metrics"), kamonModule("influxdb"), @@ -127,16 +127,19 @@ object Dependencies { monixModule("reactive").value, nettyHandler, "com.typesafe.scala-logging" %% "scala-logging" % "3.9.5", - "eu.timepit" %% "refined" % "0.11.1" exclude ("org.scala-lang.modules", "scala-xml_2.13"), - "com.esaulpaugh" % "headlong" % "10.0.2", + "eu.timepit" %% "refined" % "0.11.2" exclude ("org.scala-lang.modules", "scala-xml_2.13"), + "com.esaulpaugh" % "headlong" % "12.3.1", "com.github.jbellis" % "jamm" % "0.4.0", // Weighing caches - web3jModule("abi").excludeAll(ExclusionRule("org.bouncycastle", "bcprov-jdk15on")), - akkaModule("testkit") % Test, - akkaHttpModule("akka-http-testkit") % Test - ) ++ test ++ console ++ logDeps ++ protobuf.value ++ langCompilerPlugins.value + web3jModule("abi").excludeAll(ExclusionRule("org.bouncycastle", "bcprov-jdk15on")) + ) ++ console ++ logDeps ++ protobuf.value ++ langCompilerPlugins.value ) - val gProto = "com.google.protobuf" % "protobuf-java" % "3.25.2" + lazy val nodeTests = Seq( + akkaModule("testkit") % Test, + akkaHttpModule("akka-http-testkit") % Test + ) ++ test + + val gProto = "com.google.protobuf" % "protobuf-java" % "3.25.5" // grpc 1.64.0 still requires 3.25 lazy val scalapbRuntime = Def.setting( Seq( @@ -162,12 +165,12 @@ object Dependencies { Seq( rocksdb, "com.github.ben-manes.caffeine" % "caffeine" % "3.1.8", - "net.logstash.logback" % "logstash-logback-encoder" % "7.4" % Runtime, + "net.logstash.logback" % "logstash-logback-encoder" % "8.0" % Runtime, kamonModule("caffeine"), kamonModule("prometheus"), sttp3, sttp3Monix, - "org.scala-lang.modules" %% "scala-xml" % "2.2.0", // JUnit reports + "org.scala-lang.modules" %% "scala-xml" % "2.3.0", // JUnit reports akkaHttpModule("akka-http-testkit") % Test, "com.softwaremill.diffx" %% "diffx-core" % "0.9.0" % Test, "com.softwaremill.diffx" %% "diffx-scalatest-should" % "0.9.0" % Test, @@ -176,7 +179,7 @@ object Dependencies { ) lazy val circe = Def.setting { - val circeVersion = "0.14.6" + val circeVersion = "0.14.10" Seq( "io.circe" %%% "circe-core", "io.circe" %%% "circe-generic", diff --git a/project/build.properties b/project/build.properties index abbbce5da4..ee4c672cd0 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.9.8 +sbt.version=1.10.1 diff --git a/project/plugins.sbt b/project/plugins.sbt index 9c052045cf..3ab212d589 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -4,26 +4,26 @@ resolvers ++= Seq( ) // Should go before Scala.js -addSbtPlugin("com.thesamet" % "sbt-protoc" % "1.0.6") +addSbtPlugin("com.thesamet" % "sbt-protoc" % "1.0.7") -libraryDependencies += "com.thesamet.scalapb" %% "compilerplugin" % "0.11.15" +libraryDependencies += "com.thesamet.scalapb" %% "compilerplugin" % "0.11.17" Seq( - "com.eed3si9n" % "sbt-assembly" % "2.1.5", - "com.github.sbt" % "sbt-native-packager" % "1.9.16", + "com.eed3si9n" % "sbt-assembly" % "2.3.0", + "com.github.sbt" % "sbt-native-packager" % "1.10.4", "se.marcuslonnberg" % "sbt-docker" % "1.11.0", - "org.scala-js" % "sbt-scalajs" % "1.15.0", + "org.scala-js" % "sbt-scalajs" % "1.17.0", "org.portable-scala" % "sbt-scalajs-crossproject" % "1.3.2", "pl.project13.scala" % "sbt-jmh" % "0.4.7", - "com.github.sbt" % "sbt-ci-release" % "1.5.12", + "com.github.sbt" % "sbt-ci-release" % "1.8.0", "com.lightbend.sbt" % "sbt-javaagent" % "0.1.6" ).map(addSbtPlugin) libraryDependencies ++= Seq( - "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.16.1", + "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.18.0", "org.hjson" % "hjson" % "3.1.0", - "org.vafer" % "jdeb" % "1.10" artifacts Artifact("jdeb", "jar", "jar"), - "org.slf4j" % "jcl-over-slf4j" % "2.0.11", + "org.vafer" % "jdeb" % "1.11" artifacts Artifact("jdeb", "jar", "jar"), + "org.slf4j" % "jcl-over-slf4j" % "2.0.16", ("com.spotify" % "docker-client" % "8.16.0") .exclude("commons-logging", "commons-logging") ) diff --git a/ride-runner/build.sbt b/ride-runner/build.sbt index 7c739a2f5f..63384aa177 100644 --- a/ride-runner/build.sbt +++ b/ride-runner/build.sbt @@ -86,28 +86,8 @@ inConfig(Debian)( // Fat JAR settings inTask(assembly)( - Seq( - test := {}, - mainClass := Some("com.wavesplatform.ride.runner.entrypoints.WavesRideRunnerWithPreparedStateApp"), - assemblyJarName := s"waves-ride-runner-all-${version.value}.jar", - assemblyMergeStrategy := { - case p - if p.endsWith(".proto") || - p.endsWith("module-info.class") || - p.endsWith("io.netty.versions.properties") || - p.endsWith(".kotlin_module") => - MergeStrategy.discard - - case "scala-collection-compat.properties" => - MergeStrategy.discard - case p - if Set("scala/util/control/compat", "scala/collection/compat") - .exists(p.replace('\\', '/').contains) => - MergeStrategy.last - - case "logback.xml" | "swagger-ui/openapi.yaml" => MergeStrategy.last - - case other => (assembly / assemblyMergeStrategy).value(other) - } - ) + CommonSettings.assemblySettings ++ + Seq( + mainClass := Some("com.wavesplatform.ride.runner.entrypoints.WavesRideRunnerWithPreparedStateApp") + ) ) diff --git a/ride-runner/docker/entrypoint.sh b/ride-runner/docker/entrypoint.sh index 095cf56046..5005e1c75c 100755 --- a/ride-runner/docker/entrypoint.sh +++ b/ride-runner/docker/entrypoint.sh @@ -5,7 +5,7 @@ shopt -s nullglob # -XX:+HeapDumpOnOutOfMemoryError # -XX:HeapDumpPath=${RDATA}/heap-dumps # Why are these options required? See ride-runner/build.sbt -JAVA_OPTS="-javaagent:${RIDE_INSTALL_PATH}/kanela-agent/kanela-agent-1.0.17.jar +JAVA_OPTS="-javaagent:${RIDE_INSTALL_PATH}/kanela-agent/kanela-agent-1.0.18.jar --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.math=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED diff --git a/ride-runner/src/main/resources/ride-runner-internal.conf b/ride-runner/src/main/resources/ride-runner-internal.conf index 22246ebb9e..225b7ceba0 100644 --- a/ride-runner/src/main/resources/ride-runner-internal.conf +++ b/ride-runner/src/main/resources/ride-runner-internal.conf @@ -24,6 +24,7 @@ waves { delay-before-force-restart-blockchain-updates = 1 s db { + enable-statistics = off default-column-family { bits-per-key = 12 diff --git a/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/DBResource.scala b/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/DBResource.scala deleted file mode 100644 index 6c3eca3c06..0000000000 --- a/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/DBResource.scala +++ /dev/null @@ -1,62 +0,0 @@ -package com.wavesplatform.database.rocksdb - -import org.rocksdb.{ReadOptions, RocksDB, RocksIterator} - -import scala.collection.View -import scala.collection.mutable.ArrayBuffer - -trait DBResource extends AutoCloseable { - def get[V](key: Key[V]): V - def get(key: Array[Byte]): Array[Byte] - def multiGet[A](keys: ArrayBuffer[Key[A]], valBufferSizes: ArrayBuffer[Int]): View[A] - def multiGet[A](keys: ArrayBuffer[Key[A]], valBufferSize: Int): View[A] - def multiGetFlat[A](keys: ArrayBuffer[Key[Option[A]]], valBufferSizes: ArrayBuffer[Int]): Seq[A] - def prefixIterator: RocksIterator // Should have a single instance - def fullIterator: RocksIterator - def withSafePrefixIterator[A](ifNotClosed: RocksIterator => A)(ifClosed: => A = ()): A - def withSafeFullIterator[A](ifNotClosed: RocksIterator => A)(ifClosed: => A = ()): A -} - -object DBResource { - def apply(db: RocksDB): DBResource = new DBResource { - private[this] val snapshot = db.getSnapshot - private[this] val readOptions = new ReadOptions().setSnapshot(snapshot).setVerifyChecksums(false) - - override def get[V](key: Key[V]): V = key.parse(db.get(readOptions, key.keyBytes)) - - override def get(key: Array[Byte]): Array[Byte] = db.get(readOptions, key) - - override def multiGetFlat[A](keys: ArrayBuffer[Key[Option[A]]], valBufferSizes: ArrayBuffer[Int]): Seq[A] = - db.multiGetFlat(readOptions, keys, valBufferSizes) - - def multiGet[A](keys: ArrayBuffer[Key[A]], valBufferSizes: ArrayBuffer[Int]): View[A] = - db.multiGet(readOptions, keys, valBufferSizes) - - def multiGet[A](keys: ArrayBuffer[Key[A]], valBufferSize: Int): View[A] = - db.multiGet(readOptions, keys, valBufferSize) - - /** - * Finds the exact key for iter.seek(key) if key.length < 10 and becomes invalid on iter.next(). - * Works as intended if prefix(key).length >= 10. - * @see RDB.newColumnFamilyOptions - */ - override lazy val prefixIterator: RocksIterator = db.newIterator(readOptions.setTotalOrderSeek(false).setPrefixSameAsStart(true)) - - override lazy val fullIterator: RocksIterator = db.newIterator(readOptions.setTotalOrderSeek(true)) - - override def withSafePrefixIterator[A](ifNotClosed: RocksIterator => A)(ifClosed: => A): A = prefixIterator.synchronized { - if (prefixIterator.isOwningHandle) ifNotClosed(prefixIterator) else ifClosed - } - - override def withSafeFullIterator[A](ifNotClosed: RocksIterator => A)(ifClosed: => A): A = fullIterator.synchronized { - if (fullIterator.isOwningHandle) ifNotClosed(fullIterator) else ifClosed - } - - override def close(): Unit = { - prefixIterator.synchronized(prefixIterator.close()) - fullIterator.synchronized(fullIterator.close()) - snapshot.close() - readOptions.close() - } - } -} diff --git a/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/Key.scala b/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/Key.scala deleted file mode 100644 index 6b113983f2..0000000000 --- a/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/Key.scala +++ /dev/null @@ -1,52 +0,0 @@ -package com.wavesplatform.database.rocksdb - -import com.google.common.base.CaseFormat -import com.google.common.io.BaseEncoding -import com.google.common.primitives.{Bytes, Shorts} -import org.rocksdb.ColumnFamilyHandle - -abstract class Key[V](prefix: Short, val name: String, val suffix: Array[Byte], val columnFamilyHandle: Option[ColumnFamilyHandle] = None) { - val keyBytes: Array[Byte] = Bytes.concat(Shorts.toByteArray(prefix), suffix) - def parse(bytes: Array[Byte]): V - def encode(v: V): Array[Byte] - - override lazy val toString: String = s"$name($prefix,${BaseEncoding.base16().encode(suffix)})" - - override def equals(obj: Any): Boolean = obj match { - case that: Key[?] => java.util.Arrays.equals(this.keyBytes, that.keyBytes) - case _ => false - } - - override def hashCode(): Int = java.util.Arrays.hashCode(keyBytes) -} -object Key { - private[this] val converter = CaseFormat.UPPER_CAMEL.converterTo(CaseFormat.LOWER_HYPHEN) - private[this] val keyTagToStr = KeyTags.values.toArray.sortBy(_.id).map(v => converter.convert(v.toString)) - - def apply[V]( - keyTag: KeyTags.KeyTag, - keySuffix: Array[Byte], - parser: Array[Byte] => V, - encoder: V => Array[Byte], - cfh: Option[ColumnFamilyHandle] = None - ): Key[V] = - new Key[V](keyTag.id.toShort, keyTagToStr(keyTag.id), keySuffix, cfh) { - override def parse(bytes: Array[Byte]): V = parser(bytes) - override def encode(v: V): Array[Byte] = encoder(v) - } - - def opt[V]( - keyTag: KeyTags.KeyTag, - keySuffix: Array[Byte], - parser: Array[Byte] => V, - encoder: V => Array[Byte], - cfh: Option[ColumnFamilyHandle] = None - ): Key[Option[V]] = - apply[Option[V]]( - keyTag, - keySuffix, - Option(_).map(parser), - _.fold[Array[Byte]](Array.emptyByteArray)(encoder), - cfh - ) -} diff --git a/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/KeyHelpers.scala b/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/KeyHelpers.scala index 607f612ae4..89bf7088b2 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/KeyHelpers.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/KeyHelpers.scala @@ -3,6 +3,7 @@ package com.wavesplatform.database.rocksdb import com.google.common.primitives.{Bytes, Ints, Longs, Shorts} import com.wavesplatform.database.AddressId import com.wavesplatform.state.TxNum +import com.wavesplatform.database.* import java.nio.ByteBuffer diff --git a/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/RW.scala b/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/RW.scala deleted file mode 100644 index d8b975561c..0000000000 --- a/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/RW.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.wavesplatform.database.rocksdb - -import com.wavesplatform.database.rocksdb.stats.RocksDBStats -import com.wavesplatform.database.rocksdb.stats.RocksDBStats.DbHistogramExt -import org.rocksdb.{ReadOptions, RocksDB, WriteBatch} - -class RW(db: RocksDB, readOptions: ReadOptions, batch: WriteBatch) extends ReadOnlyDB(db, readOptions) { - def put[V](key: Key[V], value: V): Int = { - val bytes = key.encode(value) - RocksDBStats.write.recordTagged(key, bytes) - batch.put(key.columnFamilyHandle.getOrElse(db.getDefaultColumnFamily), key.keyBytes, bytes) - bytes.length - } - - def put(key: Array[Byte], value: Array[Byte]): Unit = batch.put(key, value) - - def update[V](key: Key[V])(f: V => V): Unit = put(key, f(get(key))) - - def delete(key: Array[Byte]): Unit = batch.delete(key) - - def delete[V](key: Key[V]): Unit = - batch.delete(key.columnFamilyHandle.getOrElse(db.getDefaultColumnFamily), key.keyBytes) - - def filterHistory(key: Key[Seq[Int]], heightToRemove: Int): Unit = { - val newValue = get(key).filterNot(_ == heightToRemove) - if (newValue.nonEmpty) put(key, newValue) - else delete(key) - } -} diff --git a/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/ReadOnlyDB.scala b/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/ReadOnlyDB.scala deleted file mode 100644 index 9a065c73d3..0000000000 --- a/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/ReadOnlyDB.scala +++ /dev/null @@ -1,90 +0,0 @@ -package com.wavesplatform.database.rocksdb - -import com.google.common.collect.Maps -import com.wavesplatform.database.rocksdb.stats.RocksDBStats -import com.wavesplatform.database.{DBEntry, KeyTags} -import RocksDBStats.DbHistogramExt -import org.rocksdb.{ColumnFamilyHandle, ReadOptions, RocksDB, RocksIterator} - -import scala.annotation.tailrec -import scala.util.Using - -class ReadOnlyDB(db: RocksDB, readOptions: ReadOptions) { - def get[V](key: Key[V]): V = { - val bytes = db.get(key.columnFamilyHandle.getOrElse(db.getDefaultColumnFamily), readOptions, key.keyBytes) - RocksDBStats.read.recordTagged(key, bytes) - key.parse(bytes) - } - - def getOpt[V](key: Key[V]): Option[V] = { - val bytes = db.get(key.columnFamilyHandle.getOrElse(db.getDefaultColumnFamily), readOptions, key.keyBytes) - RocksDBStats.read.recordTagged(key, bytes) - if (bytes == null) None else Some(key.parse(bytes)) - } - - def multiGetOpt[V](keys: Seq[Key[Option[V]]], valBufferSize: Int): Seq[Option[V]] = - db.multiGetOpt(readOptions, keys, valBufferSize) - - def multiGet[V](keys: Seq[Key[V]], valBufferSize: Int): Seq[Option[V]] = - db.multiGet(readOptions, keys, valBufferSize) - - def multiGetOpt[V](keys: Seq[Key[Option[V]]], valBufSizes: Seq[Int]): Seq[Option[V]] = - db.multiGetOpt(readOptions, keys, valBufSizes) - - def multiGetInts(keys: Seq[Key[Int]]): Seq[Option[Int]] = - db.multiGetInts(readOptions, keys.map(_.keyBytes)) - - def has[V](key: Key[V]): Boolean = { - val bytes = db.get(readOptions, key.keyBytes) - RocksDBStats.read.recordTagged(key, bytes) - bytes != null - } - - def newIterator: RocksIterator = db.newIterator(readOptions.setTotalOrderSeek(true)) - - def newPrefixIterator: RocksIterator = db.newIterator(readOptions.setTotalOrderSeek(false).setPrefixSameAsStart(true)) - - def iterateOverPrefix(tag: KeyTags.KeyTag)(f: DBEntry => Unit): Unit = iterateOverPrefix(tag.prefixBytes)(f) - - def iterateOverPrefix(prefix: Array[Byte])(f: DBEntry => Unit): Unit = { - @tailrec - def loop(iter: RocksIterator): Unit = { - val key = iter.key() - if (iter.isValid) { - f(Maps.immutableEntry(key, iter.value())) - iter.next() - loop(iter) - } else () - } - - Using.resource(db.newIterator(readOptions.setTotalOrderSeek(false).setPrefixSameAsStart(true))) { iter => - iter.seek(prefix) - loop(iter) - } - } - - def iterateOver(prefix: Array[Byte], cfh: Option[ColumnFamilyHandle] = None)(f: DBEntry => Unit): Unit = - Using.resource(db.newIterator(cfh.getOrElse(db.getDefaultColumnFamily), readOptions.setTotalOrderSeek(true))) { iter => - iter.seek(prefix) - while (iter.isValid && iter.key().startsWith(prefix)) { - f(Maps.immutableEntry(iter.key(), iter.value())) - iter.next() - } - } - - def iterateFrom(prefix: Array[Byte], first: Array[Byte], cfh: Option[ColumnFamilyHandle] = None)(f: DBEntry => Boolean): Unit = { - Using.resource(db.newIterator(cfh.getOrElse(db.getDefaultColumnFamily), readOptions.setTotalOrderSeek(true))) { iter => - iter.seek(first) - while (iter.isValid && iter.key().startsWith(prefix)) { - f(Maps.immutableEntry(iter.key(), iter.value())) - iter.next() - } - } - } - - def prefixExists(prefix: Array[Byte]): Boolean = Using.resource(db.newIterator(readOptions.setTotalOrderSeek(false).setPrefixSameAsStart(true))) { - iter => - iter.seek(prefix) - iter.isValid - } -} diff --git a/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/package.scala b/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/package.scala deleted file mode 100644 index b05dbdf68e..0000000000 --- a/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/package.scala +++ /dev/null @@ -1,613 +0,0 @@ -package com.wavesplatform.database - -import com.google.common.base.Charsets.UTF_8 -import com.google.common.collect.{Interners, Maps} -import com.google.common.io.ByteStreams.{newDataInput, newDataOutput} -import com.google.common.io.{ByteArrayDataInput, ByteArrayDataOutput} -import com.google.common.primitives.{Bytes, Ints, Longs} -import com.google.protobuf.ByteString -import com.wavesplatform.account.AddressScheme -import com.wavesplatform.common.state.ByteStr -import com.wavesplatform.common.utils.EitherExt2 -import com.wavesplatform.database.protobuf as pb -import com.wavesplatform.database.protobuf.DataEntry.Value -import com.wavesplatform.lang.script.ScriptReader -import com.wavesplatform.protobuf.transaction.PBRecipients -import com.wavesplatform.protobuf.{ByteStrExt, ByteStringExt} -import com.wavesplatform.state.* -import com.wavesplatform.transaction -import com.wavesplatform.transaction.TxPositiveAmount -import com.wavesplatform.utils.* -import monix.eval.Task -import monix.reactive.Observable -import org.rocksdb.* -import sun.nio.ch.Util - -import java.nio.ByteBuffer -import java.util -import java.util.Map as JMap -import scala.annotation.tailrec -import scala.collection.View -import scala.collection.mutable.ArrayBuffer -import scala.jdk.CollectionConverters.* -import scala.util.Using - -//noinspection UnstableApiUsage -package object rocksdb { - final type DBEntry = JMap.Entry[Array[Byte], Array[Byte]] - - implicit class ByteArrayDataOutputExt(val output: ByteArrayDataOutput) extends AnyVal { - def writeByteStr(s: ByteStr): Unit = { - output.write(s.arr) - } - } - - implicit class ByteArrayDataInputExt(val input: ByteArrayDataInput) extends AnyVal { - def readBytes(len: Int): Array[Byte] = { - val arr = new Array[Byte](len) - input.readFully(arr) - arr - } - - def readByteStr(len: Int): ByteStr = { - ByteStr(readBytes(len)) - } - } - - def writeIntSeq(values: Seq[Int]): Array[Byte] = { - values.foldLeft(ByteBuffer.allocate(4 * values.length))(_ putInt _).array() - } - - def readIntSeq(data: Array[Byte]): Seq[Int] = Option(data).fold(Seq.empty[Int]) { d => - val in = ByteBuffer.wrap(data) - Seq.fill(d.length / 4)(in.getInt) - } - - def readAddressIds(data: Array[Byte]): Seq[AddressId] = Option(data).fold(Seq.empty[AddressId]) { d => - require(d.length % java.lang.Long.BYTES == 0, s"Invalid data length: ${d.length}") - val buffer = ByteBuffer.wrap(data) - Seq.fill(d.length / java.lang.Long.BYTES)(AddressId(buffer.getLong)) - } - - def writeAddressIds(values: Seq[AddressId]): Array[Byte] = - values.foldLeft(ByteBuffer.allocate(values.length * java.lang.Long.BYTES)) { case (buf, aid) => buf.putLong(aid.toLong) }.array() - - def readAssetIds(data: Array[Byte]): Seq[ByteStr] = Option(data).fold(Seq.empty[ByteStr]) { d => - require(d.length % transaction.AssetIdLength == 0, s"Invalid data length: ${d.length}") - val buffer = ByteBuffer.wrap(d) - Seq.fill(d.length / transaction.AssetIdLength) { - val idBytes = new Array[Byte](transaction.AssetIdLength) - buffer.get(idBytes) - ByteStr(idBytes) - } - } - - def writeAssetIds(values: Seq[ByteStr]): Array[Byte] = - values.foldLeft(ByteBuffer.allocate(values.length * transaction.AssetIdLength)) { case (buf, ai) => buf.put(ai.arr) }.array() - - def readStrings(data: Array[Byte]): Seq[String] = Option(data).fold(Seq.empty[String]) { _ => - var i = 0 - val s = Seq.newBuilder[String] - - while (i < data.length) { - val len = ((data(i) << 8) | (data(i + 1) & 0xff)).toShort // Optimization - s += new String(data, i + 2, len, UTF_8) - i += (2 + len) - } - s.result() - } - - def writeStrings(strings: Seq[String]): Array[Byte] = { - val utfBytes = strings.toVector.map(_.utf8Bytes) - utfBytes - .foldLeft(ByteBuffer.allocate(utfBytes.map(_.length + 2).sum)) { case (buf, bytes) => - buf.putShort(bytes.length.toShort).put(bytes) - } - .array() - } - - def readLeaseBalanceNode(data: Array[Byte]): LeaseBalanceNode = if (data != null && data.length == 20) - LeaseBalanceNode(Longs.fromByteArray(data.take(8)), Longs.fromByteArray(data.slice(8, 16)), Height(Ints.fromByteArray(data.takeRight(4)))) - else LeaseBalanceNode.Empty - - def writeLeaseBalanceNode(leaseBalanceNode: LeaseBalanceNode): Array[Byte] = - Longs.toByteArray(leaseBalanceNode.in) ++ Longs.toByteArray(leaseBalanceNode.out) ++ Ints.toByteArray(leaseBalanceNode.prevHeight) - - def readLeaseBalance(data: Array[Byte]): CurrentLeaseBalance = if (data != null && data.length == 24) - CurrentLeaseBalance( - Longs.fromByteArray(data.take(8)), - Longs.fromByteArray(data.slice(8, 16)), - Height(Ints.fromByteArray(data.slice(16, 20))), - Height(Ints.fromByteArray(data.takeRight(4))) - ) - else CurrentLeaseBalance.Unavailable - - def writeLeaseBalance(lb: CurrentLeaseBalance): Array[Byte] = - Longs.toByteArray(lb.in) ++ Longs.toByteArray(lb.out) ++ Ints.toByteArray(lb.height) ++ Ints.toByteArray(lb.prevHeight) - - def writeLeaseDetails(lde: Either[Boolean, LeaseDetails]): Array[Byte] = - lde.fold( - _ => throw new IllegalArgumentException("Can not write boolean flag instead of LeaseDetails"), - ld => - pb.LeaseDetails( - ByteString.copyFrom(ld.sender.arr), - Some(PBRecipients.create(ld.recipientAddress)), - ld.amount.value, - ByteString.copyFrom(ld.sourceId.arr), - ld.height, - ld.status match { - case LeaseDetails.Status.Active => pb.LeaseDetails.CancelReason.Empty - case LeaseDetails.Status.Cancelled(height, cancelTxId) => - pb.LeaseDetails.CancelReason - .Cancelled(pb.LeaseDetails.Cancelled(height, cancelTxId.fold(ByteString.EMPTY)(id => ByteString.copyFrom(id.arr)))) - case LeaseDetails.Status.Expired(height) => pb.LeaseDetails.CancelReason.Expired(pb.LeaseDetails.Expired(height)) - } - ).toByteArray - ) - - def readLeaseDetails(data: Array[Byte]): Either[Boolean, LeaseDetails] = - if (data.length == 1) Left(data(0) == 1) - else { - val d = pb.LeaseDetails.parseFrom(data) - Right( - LeaseDetails( - LeaseStaticInfo( - d.senderPublicKey.toPublicKey, - PBRecipients.toAddress(d.recipient.get, AddressScheme.current.chainId).explicitGet(), - TxPositiveAmount.unsafeFrom(d.amount), - d.sourceId.toByteStr, - d.height - ), - d.cancelReason match { - case pb.LeaseDetails.CancelReason.Empty => LeaseDetails.Status.Active - case pb.LeaseDetails.CancelReason.Expired(pb.LeaseDetails.Expired(height, _)) => LeaseDetails.Status.Expired(height) - case pb.LeaseDetails.CancelReason.Cancelled(pb.LeaseDetails.Cancelled(height, transactionId, _)) => - LeaseDetails.Status.Cancelled(height, Some(transactionId.toByteStr).filter(!_.isEmpty)) - } - - ) - ) - } - - def readVolumeAndFeeNode(data: Array[Byte]): VolumeAndFeeNode = if (data != null && data.length == 20) - VolumeAndFeeNode(Longs.fromByteArray(data.take(8)), Longs.fromByteArray(data.slice(8, 16)), Height(Ints.fromByteArray(data.takeRight(4)))) - else VolumeAndFeeNode.Empty - - def writeVolumeAndFeeNode(volumeAndFeeNode: VolumeAndFeeNode): Array[Byte] = - Longs.toByteArray(volumeAndFeeNode.volume) ++ Longs.toByteArray(volumeAndFeeNode.fee) ++ Ints.toByteArray(volumeAndFeeNode.prevHeight) - - def readVolumeAndFee(data: Array[Byte]): CurrentVolumeAndFee = if (data != null && data.length == 24) - CurrentVolumeAndFee( - Longs.fromByteArray(data.take(8)), - Longs.fromByteArray(data.slice(8, 16)), - Height(Ints.fromByteArray(data.slice(16, 20))), - Height(Ints.fromByteArray(data.takeRight(4))) - ) - else CurrentVolumeAndFee.Unavailable - - def writeVolumeAndFee(vf: CurrentVolumeAndFee): Array[Byte] = - Longs.toByteArray(vf.volume) ++ Longs.toByteArray(vf.fee) ++ Ints.toByteArray(vf.height) ++ Ints.toByteArray(vf.prevHeight) - - def readFeatureMap(data: Array[Byte]): Map[Short, Int] = Option(data).fold(Map.empty[Short, Int]) { _ => - val b = ByteBuffer.wrap(data) - val features = Map.newBuilder[Short, Int] - while (b.hasRemaining) { - features += b.getShort -> b.getInt - } - - features.result() - } - - def writeFeatureMap(features: Map[Short, Int]): Array[Byte] = { - val b = ByteBuffer.allocate(features.size * 6) - for ((featureId, height) <- features) - b.putShort(featureId).putInt(height) - - b.array() - } - - def readSponsorship(data: Array[Byte]): SponsorshipValue = { - val ndi = newDataInput(data) - SponsorshipValue(ndi.readLong()) - } - - def writeSponsorship(ai: SponsorshipValue): Array[Byte] = { - val ndo = newDataOutput() - ndo.writeLong(ai.minFee) - ndo.toByteArray - } - - def readAssetDetails(data: Array[Byte]): (AssetInfo, AssetVolumeInfo) = { - - val pbad = pb.AssetDetails.parseFrom(data) - - ( - AssetInfo(pbad.name, pbad.description, Height(pbad.lastRenamedAt)), - AssetVolumeInfo(pbad.reissuable, BigInt(pbad.totalVolume.toByteArray)) - ) - } - - def writeAssetDetails(ai: (AssetInfo, AssetVolumeInfo)): Array[Byte] = { - val (info, volumeInfo) = ai - - pb.AssetDetails( - info.name, - info.description, - info.lastUpdatedAt, - volumeInfo.isReissuable, - ByteString.copyFrom(volumeInfo.volume.toByteArray) - ).toByteArray - } - - def writeBlockMeta(data: pb.BlockMeta): Array[Byte] = data.toByteArray - - def readBlockMeta(bs: Array[Byte]): pb.BlockMeta = pb.BlockMeta.parseFrom(bs) - - def readTransactionHNSeqAndType(bs: Array[Byte]): (Height, Seq[(Byte, TxNum, Int)]) = { - val ndi = newDataInput(bs) - val height = Height(ndi.readInt()) - val numSeqLength = ndi.readInt() - - ( - height, - List.fill(numSeqLength) { - val tp = ndi.readByte() - val num = TxNum(ndi.readShort()) - val size = ndi.readInt() - (tp, num, size) - } - ) - } - - def oldReadTransactionHNSeqAndType(bs: Array[Byte]): (Height, Seq[(Byte, TxNum)]) = { - val ndi = newDataInput(bs) - val height = Height(ndi.readInt()) - val numSeqLength = ndi.readInt() - - ( - height, - List.fill(numSeqLength) { - val tp = ndi.readByte() - val num = TxNum(ndi.readShort()) - (tp, num) - } - ) - } - - def writeTransactionHNSeqAndType(v: (Height, Seq[(Byte, TxNum, Int)])): Array[Byte] = { - val (height, numSeq) = v - val numSeqLength = numSeq.length - - val outputLength = 4 + 4 + numSeqLength * (1 + 2 + 4) - val ndo = newDataOutput(outputLength) - - ndo.writeInt(height) - ndo.writeInt(numSeqLength) - numSeq.foreach { case (tp, num, size) => - ndo.writeByte(tp) - ndo.writeShort(num) - ndo.writeInt(size) - } - - ndo.toByteArray - } - - def oldWriteTransactionHNSeqAndType(v: (Height, Seq[(Byte, TxNum)])): Array[Byte] = { - val (height, numSeq) = v - val numSeqLength = numSeq.length - - val outputLength = 4 + 4 + numSeqLength * (4 + 1) - val ndo = newDataOutput(outputLength) - - ndo.writeInt(height) - ndo.writeInt(numSeqLength) - numSeq.foreach { case (tp, num) => - ndo.writeByte(tp) - ndo.writeShort(num) - } - - ndo.toByteArray - } - - private def readDataEntry(key: String)(bs: Array[Byte]): DataEntry[?] = - pb.DataEntry.parseFrom(bs).value match { - case Value.Empty => EmptyDataEntry(key) - case Value.IntValue(value) => IntegerDataEntry(key, value) - case Value.BoolValue(value) => BooleanDataEntry(key, value) - case Value.BinaryValue(value) => BinaryDataEntry(key, value.toByteStr) - case Value.StringValue(value) => StringDataEntry(key, value) - } - - private def writeDataEntry(e: DataEntry[?]): Array[Byte] = - pb.DataEntry(e match { - case IntegerDataEntry(_, value) => pb.DataEntry.Value.IntValue(value) - case BooleanDataEntry(_, value) => pb.DataEntry.Value.BoolValue(value) - case BinaryDataEntry(_, value) => pb.DataEntry.Value.BinaryValue(ByteString.copyFrom(value.arr)) - case StringDataEntry(_, value) => pb.DataEntry.Value.StringValue(value) - case _: EmptyDataEntry => pb.DataEntry.Value.Empty - }).toByteArray - - def readCurrentData(key: String)(bs: Array[Byte]): CurrentData = if (bs == null) CurrentData.empty(key) - else - CurrentData( - readDataEntry(key)(bs.drop(8)), - Height(Ints.fromByteArray(bs.take(4))), - Height(Ints.fromByteArray(bs.slice(4, 8))) - ) - - def writeCurrentData(cdn: CurrentData): Array[Byte] = - Ints.toByteArray(cdn.height) ++ Ints.toByteArray(cdn.prevHeight) ++ writeDataEntry(cdn.entry) - - def readDataNode(key: String)(bs: Array[Byte]): DataNode = if (bs == null) DataNode.empty(key) - else - DataNode(readDataEntry(key)(bs.drop(4)), Height(Ints.fromByteArray(bs.take(4)))) - - def writeDataNode(dn: DataNode): Array[Byte] = - Ints.toByteArray(dn.prevHeight) ++ writeDataEntry(dn.entry) - - def readCurrentBalance(bs: Array[Byte]): CurrentBalance = if (bs != null && bs.length == 16) - CurrentBalance(Longs.fromByteArray(bs.take(8)), Height(Ints.fromByteArray(bs.slice(8, 12))), Height(Ints.fromByteArray(bs.takeRight(4)))) - else CurrentBalance.Unavailable - - def writeCurrentBalance(balance: CurrentBalance): Array[Byte] = - Longs.toByteArray(balance.balance) ++ Ints.toByteArray(balance.height) ++ Ints.toByteArray(balance.prevHeight) - - def readBalanceNode(bs: Array[Byte]): BalanceNode = if (bs != null && bs.length == 12) - BalanceNode(Longs.fromByteArray(bs.take(8)), Height(Ints.fromByteArray(bs.takeRight(4)))) - else BalanceNode.Empty - - def writeBalanceNode(balance: BalanceNode): Array[Byte] = - Longs.toByteArray(balance.balance) ++ Ints.toByteArray(balance.prevHeight) - - implicit class DBExt(val db: RocksDB) extends AnyVal { - - def readOnly[A](f: ReadOnlyDB => A): A = { - Using.resource(db.getSnapshot) { s => - Using.resource(new ReadOptions().setSnapshot(s).setVerifyChecksums(false)) { ro => - f(new ReadOnlyDB(db, ro)) - } - }((resource: Snapshot) => db.releaseSnapshot(resource)) - } - - /** @note - * Runs operations in batch, so keep in mind, that previous changes don't appear lately in f - */ - def readWrite[A](f: RW => A): A = { - Using.resource(db.getSnapshot) { s => - Using.resource(new ReadOptions().setSnapshot(s).setVerifyChecksums(false)) { ro => - Using.resource(new WriteOptions().setSync(false).setDisableWAL(true)) { wo => - Using.resource(new WriteBatch()) { wb => - val r = f(new RW(db, ro, wb)) - db.write(wo, wb) - r - } - } - } - } { (resource: Snapshot) => - db.releaseSnapshot(resource) - resource.close() - } - } - - def multiGetOpt[A](readOptions: ReadOptions, keys: Seq[Key[Option[A]]], valBufSize: Int): Seq[Option[A]] = - multiGetOpt(readOptions, keys, getKeyBuffersFromKeys(keys), getValueBuffers(keys.size, valBufSize)) - - def multiGetOpt[A](readOptions: ReadOptions, keys: Seq[Key[Option[A]]], valBufSizes: Seq[Int]): Seq[Option[A]] = - multiGetOpt(readOptions, keys, getKeyBuffersFromKeys(keys), getValueBuffers(valBufSizes)) - - def multiGet[A](readOptions: ReadOptions, keys: ArrayBuffer[Key[A]], valBufSizes: ArrayBuffer[Int]): View[A] = - multiGet(readOptions, keys, getKeyBuffersFromKeys(keys), getValueBuffers(valBufSizes)) - - def multiGet[A](readOptions: ReadOptions, keys: ArrayBuffer[Key[A]], valBufSize: Int): View[A] = - multiGet(readOptions, keys, getKeyBuffersFromKeys(keys), getValueBuffers(keys.size, valBufSize)) - - def multiGet[A](readOptions: ReadOptions, keys: Seq[Key[A]], valBufSize: Int): Seq[Option[A]] = { - val keyBufs = getKeyBuffersFromKeys(keys) - val valBufs = getValueBuffers(keys.size, valBufSize) - - val result = keys.view - .zip(db.multiGetByteBuffers(readOptions, keyBufs, valBufs).asScala) - .map { case (parser, value) => - if (value.status.getCode == Status.Code.Ok) { - val arr = new Array[Byte](value.requiredSize) - value.value.get(arr) - Util.releaseTemporaryDirectBuffer(value.value) - Some(parser.parse(arr)) - } else None - } - .toSeq - - keyBufs.forEach(Util.releaseTemporaryDirectBuffer(_)) - result - } - - def multiGetInts(readOptions: ReadOptions, keys: Seq[Array[Byte]]): Seq[Option[Int]] = { - val keyBufs = getKeyBuffers(keys) - val valBufs = getValueBuffers(keys.size, 4) - - val result = db - .multiGetByteBuffers(readOptions, keyBufs, valBufs) - .asScala - .map { value => - if (value.status.getCode == Status.Code.Ok) { - val h = Some(value.value.getInt) - Util.releaseTemporaryDirectBuffer(value.value) - h - } else None - } - .toSeq - - keyBufs.forEach(Util.releaseTemporaryDirectBuffer(_)) - result - } - - def multiGetFlat[A](readOptions: ReadOptions, keys: ArrayBuffer[Key[Option[A]]], valBufSizes: ArrayBuffer[Int]): Seq[A] = { - val keyBufs = getKeyBuffersFromKeys(keys) - val valBufs = getValueBuffers(valBufSizes) - - val result = keys.view - .zip(db.multiGetByteBuffers(readOptions, keyBufs, valBufs).asScala) - .flatMap { case (parser, value) => - if (value.status.getCode == Status.Code.Ok) { - val arr = new Array[Byte](value.requiredSize) - value.value.get(arr) - Util.releaseTemporaryDirectBuffer(value.value) - parser.parse(arr) - } else None - } - .toSeq - - keyBufs.forEach(Util.releaseTemporaryDirectBuffer(_)) - result - } - - def get[A](key: Key[A]): A = key.parse(db.get(key.columnFamilyHandle.getOrElse(db.getDefaultColumnFamily), key.keyBytes)) - def get[A](key: Key[A], readOptions: ReadOptions): A = key.parse(db.get(readOptions, key.keyBytes)) - def has(key: Key[?]): Boolean = db.get(key.keyBytes) != null - - def iterateOver(tag: KeyTags.KeyTag)(f: DBEntry => Unit): Unit = iterateOver(tag.prefixBytes)(f) - - def iterateOver(prefix: Array[Byte], seekPrefix: Array[Byte] = Array.emptyByteArray, cfh: Option[ColumnFamilyHandle] = None)( - f: DBEntry => Unit - ): Unit = { - @tailrec - def loop(iter: RocksIterator): Unit = { - if (iter.isValid && iter.key().startsWith(prefix)) { - f(Maps.immutableEntry(iter.key(), iter.value())) - iter.next() - loop(iter) - } else () - } - - val iterator = db.newIterator(cfh.getOrElse(db.getDefaultColumnFamily), new ReadOptions().setTotalOrderSeek(true)) - try { - iterator.seek(Bytes.concat(prefix, seekPrefix)) - loop(iterator) - } finally iterator.close() - } - - def resourceObservable: Observable[DBResource] = Observable.resource(Task(DBResource(db)))(r => Task(r.close())) - - def withResource[A](f: DBResource => A): A = { - val resource = DBResource(db) - try f(resource) - finally resource.close() - } - - private def getKeyBuffersFromKeys(keys: collection.Seq[Key[?]]): util.List[ByteBuffer] = - keys.map { k => - val arr = k.keyBytes - val b = Util.getTemporaryDirectBuffer(arr.length) - b.put(k.keyBytes).flip() - b - }.asJava - - private def getKeyBuffers(keys: collection.Seq[Array[Byte]]): util.List[ByteBuffer] = - keys.map { k => - val b = Util.getTemporaryDirectBuffer(k.length) - b.put(k).flip() - b - }.asJava - - private def getValueBuffers(amount: Int, bufferSize: Int): util.List[ByteBuffer] = - List - .fill(amount) { - val buf = Util.getTemporaryDirectBuffer(bufferSize) - buf.limit(buf.capacity()) - buf - } - .asJava - - private def getValueBuffers(bufferSizes: collection.Seq[Int]): util.List[ByteBuffer] = - bufferSizes.map { size => - val buf = Util.getTemporaryDirectBuffer(size) - buf.limit(buf.capacity()) - buf - }.asJava - - private def multiGetOpt[A]( - readOptions: ReadOptions, - keys: Seq[Key[Option[A]]], - keyBufs: util.List[ByteBuffer], - valBufs: util.List[ByteBuffer] - ): Seq[Option[A]] = { - val result = keys.view - .zip(db.multiGetByteBuffers(readOptions, keyBufs, valBufs).asScala) - .map { case (parser, value) => - if (value.status.getCode == Status.Code.Ok) { - val arr = new Array[Byte](value.requiredSize) - value.value.get(arr) - Util.releaseTemporaryDirectBuffer(value.value) - parser.parse(arr) - } else None - } - .toSeq - - keyBufs.forEach(Util.releaseTemporaryDirectBuffer(_)) - result - } - - private def multiGet[A]( - readOptions: ReadOptions, - keys: ArrayBuffer[Key[A]], - keyBufs: util.List[ByteBuffer], - valBufs: util.List[ByteBuffer] - ): View[A] = { - val result = keys.view - .zip(db.multiGetByteBuffers(readOptions, keyBufs, valBufs).asScala) - .flatMap { case (parser, value) => - if (value.status.getCode == Status.Code.Ok) { - val arr = new Array[Byte](value.requiredSize) - value.value.get(arr) - Util.releaseTemporaryDirectBuffer(value.value) - Some(parser.parse(arr)) - } else None - } - - keyBufs.forEach(Util.releaseTemporaryDirectBuffer(_)) - result - } - } - - def writeAssetScript(script: AssetScriptInfo): Array[Byte] = - Longs.toByteArray(script.complexity) ++ script.script.bytes().arr - - def readAssetScript(b: Array[Byte]): AssetScriptInfo = - AssetScriptInfo(ScriptReader.fromBytes(b.drop(8)).explicitGet(), Longs.fromByteArray(b)) - - def writeAccountScriptInfo(scriptInfo: AccountScriptInfo): Array[Byte] = - pb.AccountScriptInfo.toByteArray( - pb.AccountScriptInfo( - scriptInfo.publicKey.toByteString, - scriptInfo.script.bytes().toByteString, - scriptInfo.verifierComplexity, - scriptInfo.complexitiesByEstimator.map { case (version, complexities) => - pb.AccountScriptInfo.ComplexityByVersion(version, complexities) - }.toSeq - ) - ) - - private val scriptInterner = Interners.newWeakInterner[AccountScriptInfo]() - - def readAccountScriptInfo(b: Array[Byte]): AccountScriptInfo = { - val asi = pb.AccountScriptInfo.parseFrom(b) - scriptInterner.intern( - AccountScriptInfo( - asi.publicKey.toPublicKey, - ScriptReader.fromBytes(asi.scriptBytes.toByteArray).explicitGet(), - asi.maxComplexity, - asi.callableComplexity.map { c => - c.version -> c.callableComplexity - }.toMap - ) - ) - } - - implicit final class Ops(private val value: AddressId) extends AnyVal { - def toByteArray: Array[Byte] = Longs.toByteArray(AddressId.raw(value)) - } - - implicit class LongExt(val l: Long) extends AnyVal { - def toByteArray: Array[Byte] = Longs.toByteArray(l) - } -} diff --git a/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/stats/RocksDBStats.scala b/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/stats/RocksDBStats.scala index 6504c914a2..897bfcc421 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/stats/RocksDBStats.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/stats/RocksDBStats.scala @@ -1,6 +1,6 @@ package com.wavesplatform.database.rocksdb.stats -import com.wavesplatform.database.rocksdb.Key +import com.wavesplatform.database.Key import kamon.Kamon import kamon.metric.{MeasurementUnit, Metric} diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/disk/DefaultDiskCaches.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/disk/DefaultDiskCaches.scala index 5efbdbe2a4..57639c12db 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/disk/DefaultDiskCaches.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/disk/DefaultDiskCaches.scala @@ -6,7 +6,7 @@ import com.wavesplatform.account.{Address, Alias} import com.wavesplatform.blockchain.SignedBlockHeaderWithVrf import com.wavesplatform.collections.syntax.* import com.wavesplatform.database.AddressId -import com.wavesplatform.database.rocksdb.Key +import com.wavesplatform.database.* import com.wavesplatform.ride.runner.caches.* import com.wavesplatform.ride.runner.db.{ReadOnly, ReadWrite, RideDbAccess} import com.wavesplatform.ride.runner.stats.KamonCaffeineStats diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/disk/KvPairs.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/disk/KvPairs.scala index 2fd554195a..a6645cc536 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/disk/KvPairs.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/disk/KvPairs.scala @@ -9,8 +9,7 @@ import com.wavesplatform.block.SignedBlockHeader import com.wavesplatform.blockchain.SignedBlockHeaderWithVrf import com.wavesplatform.common.utils.EitherExt2 import com.wavesplatform.database.protobuf.{StaticAssetInfo, BlockMeta as PBBlockMeta} -import com.wavesplatform.database.rocksdb.{Key, readAccountScriptInfo, readAssetDetails, readAssetScript, readBlockMeta, writeAccountScriptInfo, writeAssetDetails, writeAssetScript, writeBlockMeta} -import com.wavesplatform.database.{AddressId, toVanillaTransaction, protobuf as pb} +import com.wavesplatform.database.{protobuf as pb, *} import com.wavesplatform.protobuf.block.PBBlocks import com.wavesplatform.protobuf.transaction.PBTransactions import com.wavesplatform.protobuf.{ByteStrExt, ByteStringExt} @@ -23,6 +22,7 @@ import com.wavesplatform.state.{AccountScriptInfo, AssetDescription, AssetInfo, import com.wavesplatform.transaction.serialization.impl.DataTxSerializer import com.wavesplatform.transaction.{Asset, AssetIdLength, Transaction} import org.rocksdb.ColumnFamilyHandle +import com.wavesplatform.protobuf.snapshot.TransactionStatus as PBStatus import java.io.{ByteArrayOutputStream, OutputStream} import java.nio.ByteBuffer @@ -172,7 +172,7 @@ object KvPairs { } val weighedAssetDescriptionAsBytes: AsBytes[WeighedAssetDescription] = - AsBytes.tuple2(intAsBytes, assetDescriptionAsBytes).transform(Function.tupled(WeighedAssetDescription), x => (x.scriptWeight, x.assetDescription)) + AsBytes.tuple2(intAsBytes, assetDescriptionAsBytes).transform(Function.tupled(WeighedAssetDescription.apply), x => (x.scriptWeight, x.assetDescription)) object AssetDescriptions extends KvPair[(state.Height, Asset.IssuedAsset), Option[WeighedAssetDescription]](72)( implicitly, @@ -212,7 +212,8 @@ object KvPairs { implicit val dataEntryAsBytes: AsBytes[DataEntry[?]] = AsBytes.mk[DataEntry[?]]((os, x) => os.write(DataTxSerializer.serializeEntry(x)), DataTxSerializer.parseEntry) - implicit val txStatusAsBytes: AsBytes[TxMeta.Status] = ??? + implicit val txStatusAsBytes: AsBytes[TxMeta.Status] = + AsBytes.mk[TxMeta.Status]((os, st) => os.write(st.protobuf.value.toByte), r => TxMeta.Status.fromProtobuf(PBStatus.fromValue(r.get))) implicit val txMetaAsBytes: AsBytes[TxMeta] = AsBytes[(state.Height, TxMeta.Status, Long)].transform[TxMeta]( Function.tupled(TxMeta.apply), diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/disk/OutputStreamOps.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/disk/OutputStreamOps.scala index 13cb88fbd4..5febfb97b2 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/disk/OutputStreamOps.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/disk/OutputStreamOps.scala @@ -10,7 +10,7 @@ trait OutputStreamSyntax { } final class OutputStreamOps(private val self: OutputStream) extends AnyVal { - def writeOpt(xs: Option[Array[Byte]]): OutputStream = xs match { + def writeOpt(maybeXs: Option[Array[Byte]]): OutputStream = maybeXs match { case Some(xs) => writeBool(true).write(xs); self case None => writeBool(false) } diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/BatchedReadOnly.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/BatchedReadOnly.scala index d96062910e..4313528c2c 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/BatchedReadOnly.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/BatchedReadOnly.scala @@ -2,7 +2,7 @@ package com.wavesplatform.ride.runner.db import com.google.common.collect.Maps import com.wavesplatform.database.DBEntry -import com.wavesplatform.database.rocksdb.Key +import com.wavesplatform.database.Key import com.wavesplatform.database.rocksdb.stats.RocksDBStats import com.wavesplatform.database.rocksdb.stats.RocksDBStats.DbHistogramExt import org.rocksdb.* diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/BatchedReadWrite.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/BatchedReadWrite.scala index dbe0074e7a..f275e51942 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/BatchedReadWrite.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/BatchedReadWrite.scala @@ -1,6 +1,6 @@ package com.wavesplatform.ride.runner.db -import com.wavesplatform.database.rocksdb.Key +import com.wavesplatform.database.Key import com.wavesplatform.database.rocksdb.stats.RocksDBStats import com.wavesplatform.database.rocksdb.stats.RocksDBStats.DbHistogramExt import com.wavesplatform.utils.OptimisticLockable diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/DirectReadOnly.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/DirectReadOnly.scala index 2111e164b4..f33ce30924 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/DirectReadOnly.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/DirectReadOnly.scala @@ -2,7 +2,7 @@ package com.wavesplatform.ride.runner.db import com.google.common.collect.Maps import com.wavesplatform.database.DBEntry -import com.wavesplatform.database.rocksdb.Key +import com.wavesplatform.database.Key import com.wavesplatform.database.rocksdb.stats.RocksDBStats import com.wavesplatform.database.rocksdb.stats.RocksDBStats.DbHistogramExt import com.wavesplatform.ride.runner.caches.disk.KvPair diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/DirectReadWrite.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/DirectReadWrite.scala index 41b88e1562..d06d68aec6 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/DirectReadWrite.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/DirectReadWrite.scala @@ -1,6 +1,6 @@ package com.wavesplatform.ride.runner.db -import com.wavesplatform.database.rocksdb.Key +import com.wavesplatform.database.Key import com.wavesplatform.database.rocksdb.stats.RocksDBStats import com.wavesplatform.database.rocksdb.stats.RocksDBStats.DbHistogramExt import com.wavesplatform.utils.OptimisticLockable diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/HasDb.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/HasDb.scala index c084a9e5be..ac0c56b938 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/HasDb.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/HasDb.scala @@ -1,6 +1,6 @@ package com.wavesplatform.ride.runner.db -import com.wavesplatform.database.rocksdb.Key +import com.wavesplatform.database.Key import org.rocksdb.{ColumnFamilyHandle, RocksDB} trait HasDb { diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/ReadOnly.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/ReadOnly.scala index 1d05406b48..d3b5c1b692 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/ReadOnly.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/ReadOnly.scala @@ -1,7 +1,7 @@ package com.wavesplatform.ride.runner.db import com.wavesplatform.database.DBEntry -import com.wavesplatform.database.rocksdb.Key +import com.wavesplatform.database.Key import com.wavesplatform.ride.runner.caches.RemoteData import com.wavesplatform.ride.runner.caches.disk.{KvHistoryPair, KvPair} import com.wavesplatform.state.Height diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/ReadWrite.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/ReadWrite.scala index 93adc319f9..3c6d7c30b6 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/ReadWrite.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/ReadWrite.scala @@ -1,7 +1,7 @@ package com.wavesplatform.ride.runner.db import com.google.common.primitives.Ints -import com.wavesplatform.database.rocksdb.Key +import com.wavesplatform.database.Key import com.wavesplatform.ride.runner.caches.RemoteData import com.wavesplatform.ride.runner.caches.disk.KvHistoryPair import com.wavesplatform.ride.runner.db.Heights.{splitHeightsAt, splitHeightsAtRollback} diff --git a/ride-runner/src/test/scala/com/wavesplatform/it/BaseIntegrationTestSuite.scala b/ride-runner/src/test/scala/com/wavesplatform/it/BaseIntegrationTestSuite.scala index 3d9d18198a..1e28911eed 100644 --- a/ride-runner/src/test/scala/com/wavesplatform/it/BaseIntegrationTestSuite.scala +++ b/ride-runner/src/test/scala/com/wavesplatform/it/BaseIntegrationTestSuite.scala @@ -89,7 +89,7 @@ abstract class BaseIntegrationTestSuite extends BaseTestSuite with HasGrpc with ) val requestService = use( - new DefaultRequestService(requestServiceSettings, blockchain, allTags, use(new TestJobScheduler()), testScheduler) { + new DefaultRequestService(requestServiceSettings, blockchain, allTags, use(new TestJobScheduler[RideScriptRunRequest]()), testScheduler) { override def start(): Unit = { super.start() testScheduler.tick() diff --git a/ride-runner/src/test/scala/com/wavesplatform/ride/runner/RequestServiceTestSuite.scala b/ride-runner/src/test/scala/com/wavesplatform/ride/runner/RequestServiceTestSuite.scala index 8c874ca7e2..7987a85028 100644 --- a/ride-runner/src/test/scala/com/wavesplatform/ride/runner/RequestServiceTestSuite.scala +++ b/ride-runner/src/test/scala/com/wavesplatform/ride/runner/RequestServiceTestSuite.scala @@ -228,7 +228,7 @@ class RequestServiceTestSuite extends BaseTestSuite with HasGrpc with HasBasicGr ) } - val requestsService = use(new DefaultRequestService(requestServiceSettings, blockchain, allTags, use(new TestJobScheduler()), testScheduler)) + val requestsService = use(new DefaultRequestService(requestServiceSettings, blockchain, allTags, use(new TestJobScheduler[RideScriptRunRequest]()), testScheduler)) val processor = new BlockchainProcessor(blockchain, requestsService) val blockchainUpdatesStream = use(blockchainApi.mkBlockchainUpdatesStream(testScheduler)) diff --git a/ride-runner/src/test/scala/com/wavesplatform/ride/runner/entrypoints/RideRunnerWithPreparedStateTestSuite.scala b/ride-runner/src/test/scala/com/wavesplatform/ride/runner/entrypoints/RideRunnerWithPreparedStateTestSuite.scala index 1aea285473..360a8b2f56 100644 --- a/ride-runner/src/test/scala/com/wavesplatform/ride/runner/entrypoints/RideRunnerWithPreparedStateTestSuite.scala +++ b/ride-runner/src/test/scala/com/wavesplatform/ride/runner/entrypoints/RideRunnerWithPreparedStateTestSuite.scala @@ -10,6 +10,7 @@ class RideRunnerWithPreparedStateTestSuite extends BaseTestSuite with HasTestAcc val sampleInput = ConfigFactory.parseResources("sample-input.conf") val input = RideRunnerInputParser.from(RideRunnerInputParser.prepare(sampleInput)) val r = WavesRideRunnerWithPreparedStateApp.run(input) + println(r) (r \ "result" \ "value" \ "_2" \ "value").validate[BigInt] shouldBe JsSuccess(BigInt("9007199361531057")) } } diff --git a/version.sbt b/version.sbt index 73ee74eb8c..70b9438d79 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -git.baseVersion := "1.5.3" +git.baseVersion := "1.5.7"