From 5639545d691f56f11d38f12d46efbe5fc2cee34c Mon Sep 17 00:00:00 2001 From: Ivan Mashonskii Date: Wed, 4 Sep 2024 14:39:47 +0300 Subject: [PATCH 1/2] Create alt chain after invalid prevRandao (#4) --- src/main/scala/units/ELUpdater.scala | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/scala/units/ELUpdater.scala b/src/main/scala/units/ELUpdater.scala index 8c962488..4662a329 100644 --- a/src/main/scala/units/ELUpdater.scala +++ b/src/main/scala/units/ELUpdater.scala @@ -276,7 +276,7 @@ class ELUpdater( } } - private def checkRandao(networkBlock: NetworkL2Block, epochNumber: Int): Either[String, Unit] = + private def validateRandao(networkBlock: NetworkL2Block, epochNumber: Int): Either[String, Unit] = blockchain.vrf(epochNumber) match { case None => s"VRF of $epochNumber epoch is empty".asLeft case Some(vrf) => @@ -284,7 +284,7 @@ class ELUpdater( Either.cond( expectedPrevRandao == networkBlock.prevRandao, (), - s"expected prevRandao $expectedPrevRandao, got ${networkBlock.prevRandao}, VRF=$vrf of $epochNumber. Wrong epoch?" + s"expected prevRandao $expectedPrevRandao, got ${networkBlock.prevRandao}, VRF=$vrf of $epochNumber" ) } @@ -980,7 +980,7 @@ class ELUpdater( s"block miner ${networkBlock.minerRewardL2Address} doesn't equal to ${epochInfo.rewardAddress}" ) _ <- checkSignature(networkBlock, isConfirmed) - _ <- checkRandao(networkBlock, contractBlock.fold(epochInfo.number)(_.epoch)) + _ <- if (contractBlock.isEmpty) validateRandao(networkBlock, epochInfo.number) else Either.unit result <- preValidateWithdrawals(networkBlock, epochInfo, contractBlock) } yield result).leftMap { err => s"Block ${networkBlock.hash} validation error: $err, ignoring block" @@ -990,12 +990,14 @@ class ELUpdater( private def validateBlock( networkBlock: NetworkL2Block, parentEcBlock: EcBlock, + contractBlock: Option[ContractBlock], expectReward: Boolean, chainContractOptions: ChainContractOptions ): Job[Unit] = { (for { _ <- validateTimestamp(networkBlock, parentEcBlock) _ <- validateWithdrawals(networkBlock, parentEcBlock, expectReward, chainContractOptions) + _ <- contractBlock.fold(Either.unit[String])(cb => validateRandao(networkBlock, cb.epoch)) } yield ()).leftMap(err => ClientError(s"Network block ${networkBlock.hash} validation error: $err")) } @@ -1084,7 +1086,7 @@ class ELUpdater( logger.debug(err) case Right(preValidationResult) => val applyResult = for { - _ <- validateBlock(networkBlock, expectedParent, preValidationResult.expectReward, prevState.options) + _ <- validateBlock(networkBlock, expectedParent, contractBlock, preValidationResult.expectReward, prevState.options) _ = logger.debug(s"Block ${networkBlock.hash} was successfully validated, trying to apply and broadcast") _ <- engineApiClient.applyNewPayload(networkBlock.payload) } yield () From b110ff57de4287ada2b8daa2879581e9424a351f Mon Sep 17 00:00:00 2001 From: Sergey Nazarov Date: Wed, 4 Sep 2024 14:40:17 +0300 Subject: [PATCH 2/2] Fix contract invocation (#8) --- .github/workflows/publish-docker-image.yml | 2 + build.sbt | 65 +++++++++++++++---- .../client/contract/ContractFunction.scala | 5 +- 3 files changed, 59 insertions(+), 13 deletions(-) diff --git a/.github/workflows/publish-docker-image.yml b/.github/workflows/publish-docker-image.yml index af066035..4563687d 100644 --- a/.github/workflows/publish-docker-image.yml +++ b/.github/workflows/publish-docker-image.yml @@ -52,6 +52,8 @@ jobs: pull: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max - uses: actions/attest-build-provenance@v1 with: subject-name: ${{ env.IMAGE_NAME}} diff --git a/build.sbt b/build.sbt index d4671a1c..53441ab8 100644 --- a/build.sbt +++ b/build.sbt @@ -1,19 +1,20 @@ -enablePlugins(UniversalDeployPlugin, JavaAppPackaging, GitVersioning) +enablePlugins(UniversalDeployPlugin, GitVersioning) -git.useGitDescribe := true -git.baseVersion := "1.0.0" +git.useGitDescribe := true +git.baseVersion := "1.0.0" git.uncommittedSignifier := Some("DIRTY") -scalaVersion := "2.13.14" -organization := "network.units" +scalaVersion := "2.13.14" +organization := "network.units" organizationName := "Units Network" -name := "consensus-client" +name := "consensus-client" +maintainer := "Units Network Team" resolvers ++= Resolver.sonatypeOssRepos("releases") ++ Resolver.sonatypeOssRepos("snapshots") ++ Seq(Resolver.mavenLocal) libraryDependencies ++= Seq( - "com.wavesplatform" % "node" % "1.5.7" % "provided", - "com.softwaremill.sttp.client3" % "core_2.13" % "3.9.8", - "com.softwaremill.sttp.client3" %% "play-json" % "3.9.8", - "com.github.jwt-scala" %% "jwt-play-json" % "10.0.1" + "com.wavesplatform" % "node" % "1.5.7" % "provided", + "com.softwaremill.sttp.client3" % "core_2.13" % "3.9.8", + "com.softwaremill.sttp.client3" %% "play-json" % "3.9.8", + "com.github.jwt-scala" %% "jwt-play-json" % "10.0.1" ) scalacOptions ++= Seq( @@ -28,7 +29,49 @@ scalacOptions ++= Seq( "-Xlint" ) -lazy val buildTarballsForDocker = taskKey[Unit]("Package node and grpc-server tarballs and copy them to docker/target") +Compile / packageDoc / publishArtifact := false + +def makeJarName( + org: String, + name: String, + revision: String, + artifactName: String, + artifactClassifier: Option[String] +): String = + org + "." + + name + "-" + + Option(artifactName.replace(name, "")).filterNot(_.isEmpty).map(_ + "-").getOrElse("") + + revision + + artifactClassifier.filterNot(_.isEmpty).map("-" + _).getOrElse("") + + ".jar" + +def getJarFullFilename(dep: Attributed[File]): String = { + val filename: Option[String] = for { + module <- dep.metadata.get(AttributeKey[ModuleID]("moduleID")) + artifact <- dep.metadata.get(AttributeKey[Artifact]("artifact")) + } yield makeJarName(module.organization, module.name, module.revision, artifact.name, artifact.classifier) + filename.getOrElse(dep.data.getName) +} + +def universalDepMappings(deps: Seq[Attributed[File]]): Seq[(File, String)] = + for { + dep <- deps + } yield dep.data -> ("lib/" + getJarFullFilename(dep)) + +Universal / mappings += { + val jar = (Compile / packageBin).value + val id = projectID.value + val art = (Compile / packageBin / artifact).value + jar -> ("lib/" + makeJarName(id.organization, id.name, id.revision, art.name, art.classifier)) +} +Universal / mappings ++= universalDepMappings((Runtime / dependencyClasspath).value.filterNot { p => + p.get(AttributeKey[ModuleID]("moduleID")).exists { m => + m.organization == "org.scala-lang" || + m.organization.startsWith("com.fasterxml.jackson") + } +}) + +lazy val buildTarballsForDocker = taskKey[Unit]("Package consensus-client tarball and copy it to docker/target") buildTarballsForDocker := { IO.copyFile( (Universal / packageZipTarball).value, diff --git a/src/main/scala/units/client/contract/ContractFunction.scala b/src/main/scala/units/client/contract/ContractFunction.scala index 423f90c4..b982e1bf 100644 --- a/src/main/scala/units/client/contract/ContractFunction.scala +++ b/src/main/scala/units/client/contract/ContractFunction.scala @@ -8,11 +8,12 @@ import com.wavesplatform.lang.v1.compiler.Terms.{CONST_BYTESTR, CONST_LONG, CONS import units.{BlockHash, ClientError, Job} import units.util.HexBytesConverter.toHexNoPrefix import cats.syntax.either.* +import org.web3j.utils.Numeric.cleanHexPrefix abstract class ContractFunction(name: String, reference: BlockHash, extraArgs: Either[CommonError, List[EVALUATED]]) { def toFunctionCall(blockHash: BlockHash, transfersRootHash: Digest, lastClToElTransferIndex: Long): Job[FUNCTION_CALL] = (for { - hash <- CONST_STRING(blockHash) - ref <- CONST_STRING(reference) + hash <- CONST_STRING(cleanHexPrefix(blockHash)) + ref <- CONST_STRING(cleanHexPrefix(reference)) trh <- CONST_STRING(toHexNoPrefix(transfersRootHash)) xtra <- extraArgs } yield FUNCTION_CALL(