diff --git a/build.sbt b/build.sbt index 1f693e6134..5ea963c03d 100644 --- a/build.sbt +++ b/build.sbt @@ -86,8 +86,7 @@ lazy val `node-tests` = project lazy val `grpc-server` = project.dependsOn(node % "compile;runtime->provided", `node-testkit`, `node-tests` % "test->test") -// TODO: [scala3] enable -// lazy val `ride-runner` = project.dependsOn(node, `grpc-server`, `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`, `lang-testkit` % "test->test", `node-testkit`) lazy val `node-generator` = project.dependsOn(node, `node-testkit`, `node-testkit`) @@ -144,7 +143,7 @@ lazy val `waves-node` = (project in file(".")) `node-tests`, `node-generator`, benchmark, - // `ride-runner` // TODO: [scala3] enable + `ride-runner` ) inScope(Global)( @@ -199,7 +198,7 @@ inScope(Global)( lazy val packageAll = taskKey[Unit]("Package all artifacts") packageAll := { (node / assembly).value - // (`ride-runner` / assembly).value // TODO: [scala3] enable + (`ride-runner` / assembly).value buildDebPackages.value buildTarballsForDocker.value } @@ -216,14 +215,13 @@ buildTarballsForDocker := { ) } -// TODO: [scala3] enable -// lazy val buildRIDERunnerForDocker = taskKey[Unit]("Package RIDE Runner tarball and copy it to docker/target") -// buildRIDERunnerForDocker := { -// IO.copyFile( -// (`ride-runner` / Universal / packageZipTarball).value, -// (`ride-runner` / baseDirectory).value / "docker" / "target" / s"${(`ride-runner` / name).value}.tgz" -// ) -// } +lazy val buildRIDERunnerForDocker = taskKey[Unit]("Package RIDE Runner tarball and copy it to docker/target") +buildRIDERunnerForDocker := { + IO.copyFile( + (`ride-runner` / Universal / packageZipTarball).value, + (`ride-runner` / baseDirectory).value / "docker" / "target" / s"${(`ride-runner` / name).value}.tgz" + ) +} lazy val checkPRRaw = taskKey[Unit]("Build a project and run unit tests") checkPRRaw := Def @@ -240,7 +238,7 @@ checkPRRaw := Def (`node-it` / Test / compile).value (benchmark / Test / compile).value (`node-generator` / Compile / compile).value - // (`ride-runner` / Test / compile).value // TODO: [scala3] enable + (`ride-runner` / Test / test).value } ) .value 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 7fafb43231..8d28529bf5 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 @@ -18,6 +18,7 @@ import com.wavesplatform.lang.v1.traits.Environment import com.wavesplatform.lang.* import monix.eval.Coeval +import java.io.{PrintWriter, StringWriter} import scala.annotation.tailrec import scala.collection.mutable.ListBuffer @@ -128,7 +129,9 @@ class EvaluatorV2( case null => e.toString case msg => msg } - Coeval(Left((CommonError(s"""An error during run ${function.ev}: ${e.getClass} $error"""), 0))) + val sw = new StringWriter() + e.printStackTrace(new PrintWriter(sw)) + Coeval(Left((CommonError(s"""An error during run ${function.ev}: ${e.getClass} $error ${sw.toString}"""), 0))) } ) _ <- update(result) diff --git a/node/src/main/scala/com/wavesplatform/settings/BlockchainSettings.scala b/node/src/main/scala/com/wavesplatform/settings/BlockchainSettings.scala index b8690d5879..eb6297932a 100644 --- a/node/src/main/scala/com/wavesplatform/settings/BlockchainSettings.scala +++ b/node/src/main/scala/com/wavesplatform/settings/BlockchainSettings.scala @@ -336,7 +336,7 @@ object BlockchainSettings { def fromRootConfig(config: Config): BlockchainSettings = ConfigSource.fromConfig(config).at("waves.blockchain").loadOrThrow[BlockchainSettings] - implicit val configReader: ConfigReader[BlockchainSettings] = ConfigReader.fromCursor(cur => + given ConfigReader[BlockchainSettings] = ConfigReader.fromCursor(cur => for { objCur <- cur.asObjectCursor blockchainTypeString <- objCur.atKey("type").flatMap(_.asString).map(_.toUpperCase) diff --git a/ride-runner/src/main/scala/com/wavesplatform/api/RideMulticastHttpApi.scala b/ride-runner/src/main/scala/com/wavesplatform/api/RideMulticastHttpApi.scala index 6852c5be48..74c66af7fc 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/api/RideMulticastHttpApi.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/api/RideMulticastHttpApi.scala @@ -6,6 +6,7 @@ import com.wavesplatform.api.RideMulticastHttpApi.{AskResult, AskServerResponse, import com.wavesplatform.utils.ScorexLogging import monix.eval.Task import play.api.libs.json.{JsObject, Json} +import pureconfig.ConfigReader import sttp.client3.* import scala.concurrent.duration.{Duration, DurationLong, FiniteDuration} @@ -38,7 +39,7 @@ class RideMulticastHttpApi(settings: Settings, httpBackend: SttpBackend[Identity } object RideMulticastHttpApi { - case class Settings(rideRunnerApiBaseUri: String, nodeApiBaseUri: String) + case class Settings(rideRunnerApiBaseUri: String, nodeApiBaseUri: String) derives ConfigReader case class AskResult(rideRunner: AskServerResponse, node: AskServerResponse) { def timeDiff: FiniteDuration = (node.time - rideRunner.time).toCoarsest diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/blockchain/ImmutableBlockchain.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/blockchain/ImmutableBlockchain.scala index 97e471c07b..e4c5c6a98d 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/blockchain/ImmutableBlockchain.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/blockchain/ImmutableBlockchain.scala @@ -87,12 +87,7 @@ class ImmutableBlockchain(override val settings: BlockchainSettings, input: Ride // Ride: blockInfoByHeight, lastBlock override def blockHeader(height: Int): Option[SignedBlockHeader] = - // Dirty, but we have a clear error instead of "None.get" - blockHeaders - .get(height) - .tap { r => - if (r.isEmpty) throw new RuntimeException(s"blockHeader($height): can't find a block header, please specify or check your script") - } + blockHeaders.get(height) // Ride: blockInfoByHeight override def hitSource(height: Int): Option[ByteStr] = input.blocks.get(height).flatMap(_.VRF) @@ -197,7 +192,7 @@ class ImmutableBlockchain(override val settings: BlockchainSettings, input: Ride override def wavesBalances(addresses: Seq[Address]): Map[Address, Long] = ??? - override def effectiveBalanceBanHeights(address: Address): Seq[Int] = ??? + override def effectiveBalanceBanHeights(address: Address): Seq[Int] = Seq.empty override def lastStateHash(refId: Option[BlockId]): BlockId = ??? diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/blockchain/LazyBlockchain.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/blockchain/LazyBlockchain.scala index 3275187dca..ba0ccab860 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/blockchain/LazyBlockchain.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/blockchain/LazyBlockchain.scala @@ -281,19 +281,19 @@ class LazyBlockchain[TagT] private ( affected } - private def updateCacheIfExists[CacheKeyT <: MemCacheKey](key: CacheKeyT)(v: RemoteData[CacheKeyT#ValueT]): AffectedTags[TagT] = { + private def updateCacheIfExists[V, K <: MemCacheKey[V]](key: K)(v: RemoteData[V]): AffectedTags[TagT] = { getAffectedTags(key).tap { tags => if (tags.isEmpty) memCache.updateIfExists(key, v) // Not yet removed from memCache, but already removed from tags else memCache.set(key, v) } } - private def removeCache[CacheKeyT <: MemCacheKey](key: CacheKeyT): AffectedTags[TagT] = { + private def removeCache[K <: MemCacheKey[?]](key: K): AffectedTags[TagT] = { memCache.remove(key) getAffectedTags(key) } - private def getAffectedTags(key: MemCacheKey): AffectedTags[TagT] = allTags.get(key).getOrElse(AffectedTags.empty) + private def getAffectedTags(key: MemCacheKey[?]): AffectedTags[TagT] = allTags.get(key).getOrElse(AffectedTags.empty) private def append(atHeight: Height, evt: BlockchainUpdated.Append)(implicit ctx: ReadWrite): AffectedTags[TagT] = { val (initialAffectedTags, txs, timer) = evt.body match { diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/CacheKeyTags.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/CacheKeyTags.scala index 9ed1c1a820..8b11169b66 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/CacheKeyTags.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/CacheKeyTags.scala @@ -12,20 +12,20 @@ class CacheKeyTags[TagT] { // not exist - we don't known this key // exist, but empty - we known this key, but doesn't remember why // exist and non-empty - we know, why do we need this key (but there are probably more tags) - private val allTags = new ConcurrentHashMap[MemCacheKey, Tags]() + private val allTags = new ConcurrentHashMap[MemCacheKey[?], Tags]() - def get(key: MemCacheKey): Option[Tags] = Option(allTags.get(key)) + def get(key: MemCacheKey[?]): Option[Tags] = Option(allTags.get(key)) - def addDependent(key: MemCacheKey, tag: TagT): Unit = allTags.compute(key, (_, origTags) => Option(origTags).getOrElse(Set.empty) + tag) + def addDependent(key: MemCacheKey[?], tag: TagT): Unit = allTags.compute(key, (_, origTags) => Option(origTags).getOrElse(Set.empty) + tag) def removeTags(xs: collection.Set[TagT]): Unit = { - allTags.replaceAll { (_: MemCacheKey, orig: Tags) => + allTags.replaceAll { (_: MemCacheKey[?], orig: Tags) => if (orig.size >= xs.size) orig -- xs else orig.diff(xs) } // Use removeIf to remove empty keys in JRE 17 - val emptyKeys = allTags.reduceEntries[Seq[MemCacheKey]]( + val emptyKeys = allTags.reduceEntries[Seq[MemCacheKey[?]]]( 4, // parallelismThreshold entry => if (entry.getValue.isEmpty) Seq(entry.getKey) else Seq.empty, _ ++ _ diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/mem/MemBlockchainDataCache.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/mem/MemBlockchainDataCache.scala index 1e4a57dc66..9017c4b306 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/mem/MemBlockchainDataCache.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/mem/MemBlockchainDataCache.scala @@ -5,36 +5,35 @@ import com.typesafe.config.ConfigMemorySize import com.wavesplatform.ride.runner.caches.RemoteData import com.wavesplatform.ride.runner.caches.mem.MemBlockchainDataCache.Settings import com.wavesplatform.ride.runner.stats.KamonCaffeineStats +import org.github.jamm.MemoryMeter import pureconfig.ConfigReader class MemBlockchainDataCache(settings: Settings) { + private val mmeter = MemoryMeter.builder().build() private val backend = Caffeine .newBuilder() .softValues() .maximumWeight(settings.size.toBytes) .recordStats(() => new KamonCaffeineStats("Common")) - .weigher { (key: MemCacheKey, value: RemoteData[Any]) => - val v = value.mayBeValue.map(_.asInstanceOf[key.ValueT]) - key.keyWeight + v.fold(0) { v => - MemCacheWeights.OfCachedRemoteDataOverhead + key.valueWeight(v) - } + .weigher { (key: MemCacheKey[?], value: RemoteData[Any]) => + (mmeter.measure(key) + mmeter.measure(value)).toInt } - .build[MemCacheKey, RemoteData[Any]]() + .build[MemCacheKey[?], RemoteData[Any]]() - def get[T <: MemCacheKey](key: T): RemoteData[T#ValueT] = - Option(backend.getIfPresent(key)).getOrElse(RemoteData.Unknown).asInstanceOf[RemoteData[T#ValueT]] + def get[V, K <: MemCacheKey[V]](key: K): RemoteData[V] = + Option(backend.getIfPresent(key)).getOrElse(RemoteData.Unknown).asInstanceOf[RemoteData[V]] - def getOrLoad[T <: MemCacheKey](key: T)(load: T => RemoteData[T#ValueT]): RemoteData[T#ValueT] = - backend.get(key, _ => load(key)).asInstanceOf[RemoteData[T#ValueT]] + def getOrLoad[V, K <: MemCacheKey[V]](key: K)(load: K => RemoteData[V]): RemoteData[V] = + backend.get(key, _ => load(key)).asInstanceOf[RemoteData[V]] - def set[T <: MemCacheKey, V](key: T, value: RemoteData[V])(implicit ev: V =:= T#ValueT): Unit = backend.put(key, value) + def set[V, K <: MemCacheKey[V]](key: K, value: RemoteData[V]): Unit = backend.put(key, value) - def updateIfExists[T <: MemCacheKey, V](key: T, newValue: RemoteData[V])(implicit ev: V =:= T#ValueT): Unit = + def updateIfExists[V, K <: MemCacheKey[V]](key: K, newValue: RemoteData[V]): Unit = Option(backend.policy().getEntryIfPresentQuietly(key)).foreach { _ => backend.put(key, newValue) } - def remove[T <: MemCacheKey](key: T): Unit = backend.invalidate(key) + def remove[K <: MemCacheKey[?]](key: K): Unit = backend.invalidate(key) } object MemBlockchainDataCache { diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/mem/MemCacheKey.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/mem/MemCacheKey.scala index b181f81b6e..6101281f84 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/mem/MemCacheKey.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/caches/mem/MemCacheKey.scala @@ -4,77 +4,36 @@ import com.google.protobuf.ByteString import com.wavesplatform.account.{Address, Alias} import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.EitherExt2 +import com.wavesplatform.common.utils.EitherExt2.explicitGet import com.wavesplatform.events.protobuf.StateUpdate -import com.wavesplatform.protobuf.{ByteStringExt, transaction as pb} import com.wavesplatform.protobuf.transaction.PBAmounts.toAssetAndAmount import com.wavesplatform.protobuf.transaction.PBTransactions.{toVanillaDataEntry, toVanillaScript} import com.wavesplatform.protobuf.transaction.{CreateAliasTransactionData, Transaction} +import com.wavesplatform.protobuf.{ByteStringExt, transaction as pb} import com.wavesplatform.ride.runner.caches.{WeighedAccountScriptInfo, WeighedAssetDescription} import com.wavesplatform.state.{AssetDescription, AssetScriptInfo, DataEntry, Height, LeaseBalance, TransactionId} import com.wavesplatform.transaction.Asset.IssuedAsset import com.wavesplatform.utils.StringBytes import com.wavesplatform.{account, state, transaction} -import com.wavesplatform.common.utils.EitherExt2.explicitGet -sealed trait MemCacheKey extends Product with Serializable { - type ValueT - def keyWeight: Int - def valueWeight(value: ValueT): Int -} +sealed trait MemCacheKey[ValueT] object MemCacheKey { - case class AccountData(address: Address, dataKey: String) extends MemCacheKey { - override type ValueT = DataEntry[?] - // 24 = 12 (header) + 4 (ref) + 4 (ref) + 4 (align) - override def keyWeight: Int = 24 + MemCacheWeights.OfAddress + MemCacheWeights.ofAsciiString(dataKey) - override def valueWeight(value: DataEntry[?]): Int = MemCacheWeights.ofDataEntry(value) - } + case class AccountData(address: Address, dataKey: String) extends MemCacheKey[DataEntry[?]] - case class Transaction(id: TransactionId) extends MemCacheKey { - override type ValueT = state.Height - override def keyWeight: Int = 16 + MemCacheWeights.OfTransactionId // 16 = 12 (header) + 4 (ref) + id - override def valueWeight(value: Height): Int = 16 // 12 (header) + 4 (int value) - } + case class Transaction(id: TransactionId) extends MemCacheKey[state.Height] - case object Height extends MemCacheKey { - override type ValueT = state.Height - override def keyWeight: Int = 0 - override def valueWeight(value: Height): Int = 16 // 12 (header) + 4 (int value) - } + case object Height extends MemCacheKey[state.Height] - case class Alias(alias: account.Alias) extends MemCacheKey { - override type ValueT = Address - override def keyWeight: Int = 16 + MemCacheWeights.ofAlias(alias) // 16 = 12 (header) + 4 (ref) + alias - override def valueWeight(value: Address): Int = MemCacheWeights.OfAddress - } + case class Alias(alias: account.Alias) extends MemCacheKey[Address] - case class Asset(asset: IssuedAsset) extends MemCacheKey { - override type ValueT = WeighedAssetDescription - override def keyWeight: Int = MemCacheWeights.OfIssuedAsset - override def valueWeight(value: WeighedAssetDescription): Int = MemCacheWeights.ofWeighedAssetDescription(value) - } + case class Asset(asset: IssuedAsset) extends MemCacheKey[WeighedAssetDescription] - case class AccountBalance(address: Address, asset: transaction.Asset) extends MemCacheKey { - override type ValueT = Long - // 24 = 12 (header) + 4*2 (ref: address, asset) + 4 (align) - override def keyWeight: Int = 24 + MemCacheWeights.OfAddress + MemCacheWeights.ofAsset(asset) - override def valueWeight(value: Long): Int = 8 - } + case class AccountBalance(address: Address, asset: transaction.Asset) extends MemCacheKey[Long] - case class AccountLeaseBalance(address: Address) extends MemCacheKey { - override type ValueT = LeaseBalance - // 16 = 12 (header) + 4 (ref) - override def keyWeight: Int = 16 + MemCacheWeights.OfAddress - override def valueWeight(value: LeaseBalance): Int = MemCacheWeights.OfLeaseBalance - } + case class AccountLeaseBalance(address: Address) extends MemCacheKey[LeaseBalance] - case class AccountScript(address: Address) extends MemCacheKey { - override type ValueT = WeighedAccountScriptInfo - // 16 = 12 (header) + 4 (ref) - override def keyWeight: Int = 16 + MemCacheWeights.OfAddress - // 24 = 12 (header) + 4 (size) + 4 (ref: scriptInfo) + 4 (align) - override def valueWeight(value: WeighedAccountScriptInfo): Int = 24 + value.scriptInfoWeight - } + case class AccountScript(address: Address) extends MemCacheKey[WeighedAccountScriptInfo] } class GrpcCacheKeyConverters(chainId: Byte) { @@ -83,10 +42,10 @@ class GrpcCacheKeyConverters(chainId: Byte) { MemCacheKey.AccountData(update.address.toAddress(chainId), dataKey) } - def accountDataValueBefore(update: StateUpdate.DataEntryUpdate): Option[MemCacheKey.AccountData#ValueT] = + def accountDataValueBefore(update: StateUpdate.DataEntryUpdate): Option[DataEntry[?]] = update.dataEntryBefore.map(accountDataValue) - def accountDataValueAfter(update: StateUpdate.DataEntryUpdate): Option[MemCacheKey.AccountData#ValueT] = update.dataEntry.map(accountDataValue) - def accountDataValue(dataEntry: pb.DataEntry): MemCacheKey.AccountData#ValueT = toVanillaDataEntry(dataEntry) + def accountDataValueAfter(update: StateUpdate.DataEntryUpdate): Option[DataEntry[?]] = update.dataEntry.map(accountDataValue) + def accountDataValue(dataEntry: pb.DataEntry): DataEntry[?] = toVanillaDataEntry(dataEntry) def transactionIdKey(id: ByteString): MemCacheKey.Transaction = MemCacheKey.Transaction(TransactionId(ByteStr(id.toByteArray))) 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 be6d6eecc6..1bef100ff4 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 @@ -63,7 +63,10 @@ trait ReadOnly { } def getRemoteDataOpt[T](key: Key[Option[T]]): RemoteData[T] = RemoteData(getOpt(key)) - + + def readFromDb[K, V](k: K, kvHistoryPair: KvHistoryPair[K, V], maxHeight: Height)(implicit @unused ev: V =:!= Option[?]): RemoteData[V] = + readFromDbRaw(k, kvHistoryPair, maxHeight).fold(RemoteData.unknown[V])(RemoteData.Cached(_)) + def readFromDb[K, V](k: K, kvHistoryPair: KvHistoryPair[K, Option[V]], maxHeight: Height): RemoteData[V] = readFromDbRaw(k, kvHistoryPair, maxHeight).fold(RemoteData.unknown[V])(RemoteData.loaded) 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 ce793611cb..a177e5bdd9 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 @@ -37,7 +37,7 @@ trait ReadWrite extends ReadOnly { k: K, kvHistoryPair: KvHistoryPair[K, V], fromHeight: Height - ): RemoteData[V] = + )(implicit @unused ev: V =:!= Option[?]): RemoteData[V] = RemoteData.cachedOrUnknown(removeFromAndGetLatestExistedBase(k, kvHistoryPair, fromHeight)) def removeFromAndGetLatestExisted[K, V](k: K, kvHistoryPair: KvHistoryPair[K, Option[V]], fromHeight: Height): RemoteData[V] = diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/RideDbAccess.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/RideDbAccess.scala index a826ff0081..295d72f931 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/RideDbAccess.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/RideDbAccess.scala @@ -7,19 +7,19 @@ import org.rocksdb.* import scala.util.Using trait RideDbAccess { - def batchedReadOnly[T](f: ReadOnly => T): T - def batchedReadWrite[T](f: ReadWrite => T): T + def batchedReadOnly[T](f: ReadOnly => T)(implicit ev: T <:!< Task[?]): T + def batchedReadWrite[T](f: ReadWrite => T)(implicit ev: T <:!< Task[?]): T def directReadOnly[T](f: ReadOnly => T): T def directReadWrite[T](f: ReadWrite => T): T } object RideDbAccess { def fromRocksDb(db: RocksDB): RideDbAccess = new RideDbAccess with ScorexLogging { - override def batchedReadOnly[T](f: ReadOnly => T): T = withReadOptions { ro => + override def batchedReadOnly[T](f: ReadOnly => T)(implicit ev: T <:!< Task[?]): T = withReadOptions { ro => f(new BatchedReadOnly(db, ro)) } - override def batchedReadWrite[T](f: ReadWrite => T): T = withReadOptions { ro => + override def batchedReadWrite[T](f: ReadWrite => T)(implicit ev: T <:!< Task[?]): T = withReadOptions { ro => Using.resource(mkWriteOptions()) { wo => Using.resource(SynchronizedWriteBatch()) { wb => val r = f(new BatchedReadWrite(db, ro, wb)) diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/package.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/package.scala index bbfd825528..0df85238f2 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/package.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/db/package.scala @@ -2,7 +2,13 @@ package com.wavesplatform.ride.runner import com.wavesplatform.state.Height +import scala.annotation.targetName +import scala.util.NotGiven + package object db { type Heights = Vector[Height] val EmptyHeights: Heights = Vector.empty + + type =:!=[A, B] = NotGiven[A =:= B] + type <:!<[A, B] = NotGiven[A <:< B] } diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/entrypoints/WavesRideRunnerCompareService.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/entrypoints/WavesRideRunnerCompareService.scala index 908ca9ab85..5744fff978 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/entrypoints/WavesRideRunnerCompareService.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/entrypoints/WavesRideRunnerCompareService.scala @@ -2,9 +2,13 @@ package com.wavesplatform.ride.runner.entrypoints import akka.actor.ActorSystem import akka.http.scaladsl.Http +import cats.syntax.traverse.* +import com.typesafe.config.{Config, ConfigRenderOptions} import com.wavesplatform.account.Address import com.wavesplatform.api.RideMulticastHttpApi import com.wavesplatform.api.http.CompositeHttpService +import com.wavesplatform.common.utils.EitherExt2.explicitGet +import com.wavesplatform.ride.runner.entrypoints.settings.RideRunnerGlobalSettings import com.wavesplatform.ride.runner.http.{HttpServiceStatus, ServiceApiRoute} import com.wavesplatform.ride.runner.stats.RideRunnerStats import com.wavesplatform.utils.ScorexLogging @@ -15,12 +19,16 @@ import monix.eval.Task import monix.execution.{ExecutionModel, Scheduler} import monix.reactive.Observable import play.api.libs.json.{JsObject, Json} +import pureconfig.ConfigReader +import pureconfig.error.ThrowableFailure import sttp.client3.HttpURLConnectionBackend import java.io.File import java.util.concurrent.{LinkedBlockingQueue, RejectedExecutionException, ThreadPoolExecutor, TimeUnit} import scala.concurrent.Await import scala.concurrent.duration.{Duration, DurationInt, FiniteDuration} +import scala.util.Try +import scala.util.control.NonFatal object WavesRideRunnerCompareService extends ScorexLogging { case class Settings( @@ -29,10 +37,24 @@ object WavesRideRunnerCompareService extends ScorexLogging { maxChecks: Option[Long], rideApi: RideMulticastHttpApi.Settings, testRequests: List[(Address, JsObject)] + ) derives ConfigReader + + given ConfigReader[JsObject] = ConfigReader.fromFunction { v => + try Right(Json.parse(v.render(ConfigRenderOptions.concise())).as[JsObject]) + catch { case NonFatal(e) => ConfigReader.Result.fail(ThrowableFailure(e, Some(v.origin()))) } + } + given ConfigReader[Address] = ConfigReader.fromStringTry(str => Try(Address.fromString(str).explicitGet())) + given ConfigReader[(Address, JsObject)] = ConfigReader.fromCursor(cur => + for { + l <- cur.asList + addr <- ConfigReader[Address].from(l(0)) + jso <- ConfigReader[JsObject].from(l(1)) + } yield (addr, jso) ) def main(args: Array[String]): Unit = { - val (globalConfig, settings) = AppInitializer.init(checkDb = false, externalConfig = args.headOption.map(new File(_).getAbsoluteFile)) + val (globalConfig: Config, settings: RideRunnerGlobalSettings) = + AppInitializer.init(checkDb = false, externalConfig = args.headOption.map(new File(_).getAbsoluteFile)) if (settings.rideCompareService.testRequests.isEmpty) throw new IllegalArgumentException("Specify waves.compare.test-requests in config") log.info("Starting...") diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/entrypoints/WavesRideRunnerWithBlockchainService.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/entrypoints/WavesRideRunnerWithBlockchainService.scala index 04e633c50e..f187f0c0e7 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/entrypoints/WavesRideRunnerWithBlockchainService.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/entrypoints/WavesRideRunnerWithBlockchainService.scala @@ -2,13 +2,15 @@ package com.wavesplatform.ride.runner.entrypoints import akka.actor.ActorSystem import akka.http.scaladsl.Http +import com.typesafe.config.Config import com.wavesplatform.api.http.CompositeHttpService import com.wavesplatform.api.{DefaultBlockchainApi, GrpcChannelSettings, GrpcConnector} import com.wavesplatform.ride.runner.blockchain.LazyBlockchain import com.wavesplatform.ride.runner.caches.CacheKeyTags import com.wavesplatform.ride.runner.caches.disk.DefaultDiskCaches import com.wavesplatform.ride.runner.caches.mem.MemBlockchainDataCache -import com.wavesplatform.ride.runner.db.RideRocksDb +import com.wavesplatform.ride.runner.db.{<:!<, =:!=, RideRocksDb} +import com.wavesplatform.ride.runner.entrypoints.settings.RideRunnerGlobalSettings import com.wavesplatform.ride.runner.http.{EvaluateApiRoute, HttpServiceStatus, ServiceApiRoute} import com.wavesplatform.ride.runner.requests.{DefaultRequestService, RideScriptRunRequest, SynchronizedJobScheduler} import com.wavesplatform.ride.runner.stats.RideRunnerStats @@ -30,7 +32,7 @@ import scala.concurrent.duration.{Duration, DurationInt} object WavesRideRunnerWithBlockchainService extends ScorexLogging { def main(args: Array[String]): Unit = { - val (globalConfig, settings) = AppInitializer.init(externalConfig = args.headOption.map(new File(_).getAbsoluteFile)) + val (globalConfig: Config, settings: RideRunnerGlobalSettings) = AppInitializer.init(externalConfig = args.headOption.map(new File(_).getAbsoluteFile)) log.info("Starting...") // It has to be before other code: https://github.com/kamon-io/Kamon/issues/601#issuecomment-748995094 diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/entrypoints/settings/RideRunnerGlobalSettings.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/entrypoints/settings/RideRunnerGlobalSettings.scala index 4d07d79158..115f8db614 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/entrypoints/settings/RideRunnerGlobalSettings.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/entrypoints/settings/RideRunnerGlobalSettings.scala @@ -7,6 +7,7 @@ import com.wavesplatform.ride.runner.caches.mem.MemBlockchainDataCache import com.wavesplatform.ride.runner.entrypoints.{Heights, WavesRideRunnerCompareService} import com.wavesplatform.ride.runner.requests.DefaultRequestService import com.wavesplatform.settings.* +import com.wavesplatform.settings.BlockchainSettings.given import com.wavesplatform.ride.runner.input.PureconfigImplicits.* import pureconfig.* diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerAccount.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerAccount.scala index e7ed70e2cf..e09f5e4476 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerAccount.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerAccount.scala @@ -1,8 +1,11 @@ package com.wavesplatform.ride.runner.input import com.wavesplatform.account.Alias +import com.wavesplatform.ride.runner.input.RideRunnerInputParser.given import com.wavesplatform.transaction.Asset.IssuedAsset import com.wavesplatform.transaction.{Asset, TxNonNegativeAmount} +import pureconfig.error.UserValidationFailed +import pureconfig.{CollectionReaders, ConfigConvert, ConfigReader} /** @param data * Some(Map.empty) means the data was here @@ -15,6 +18,6 @@ case class RideRunnerAccount( data: Option[Map[String, RideRunnerDataEntry]] = None, aliases: List[Alias] = Nil, scriptInfo: Option[RideRunnerScriptInfo] = None -) { +) derives ConfigReader { def balance(mayBeAssetId: Asset): Option[Long] = mayBeAssetId.fold(regularBalance)(assetBalances.get).map(_.value) } diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerAsset.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerAsset.scala index cd18a98e35..7de23320b7 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerAsset.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerAsset.scala @@ -3,6 +3,8 @@ package com.wavesplatform.ride.runner.input import com.wavesplatform.account.PublicKey import com.wavesplatform.account.PublicKeys.EmptyPublicKey import com.wavesplatform.lang.script.Script +import com.wavesplatform.ride.runner.input.RideRunnerInputParser.given +import pureconfig.ConfigReader import java.nio.charset.StandardCharsets @@ -15,7 +17,7 @@ case class RideRunnerAsset( quantity: Long = 9007199254740991L, // In JS: MAX_SAFE_INTEGER script: Option[Script] = None, minSponsoredAssetFee: Long = 0L -) +) derives ConfigReader object RideRunnerAsset { val DefaultName = StringOrBytesAsByteArray("name".getBytes(StandardCharsets.UTF_8)) diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerBlock.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerBlock.scala index 0289549581..53e4eaa2f8 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerBlock.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerBlock.scala @@ -3,6 +3,8 @@ package com.wavesplatform.ride.runner.input import com.wavesplatform.account.PublicKey import com.wavesplatform.account.PublicKeys.EmptyPublicKey import com.wavesplatform.common.state.ByteStr +import com.wavesplatform.ride.runner.input.RideRunnerInputParser.given +import pureconfig.ConfigReader case class RideRunnerBlock( timestamp: Long = System.currentTimeMillis(), @@ -11,4 +13,4 @@ case class RideRunnerBlock( generatorPublicKey: PublicKey = EmptyPublicKey, VRF: Option[ByteStr] = None, blockReward: Long = 600_000_000L // 6 WAVES -) +) derives ConfigReader diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerBlockchainState.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerBlockchainState.scala index a818141106..25a86fafec 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerBlockchainState.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerBlockchainState.scala @@ -3,8 +3,12 @@ package com.wavesplatform.ride.runner.input import com.wavesplatform.account.Address import com.wavesplatform.common.state.ByteStr import com.wavesplatform.features.BlockchainFeatures +import com.wavesplatform.ride.runner.input.RideRunnerInputParser.given import com.wavesplatform.transaction.Asset.IssuedAsset -import pureconfig.ConfigReader +import pureconfig.ConfigReader.Result +import pureconfig.generic.ProductHint +import pureconfig.{ConfigCursor, ConfigReader, ReadsMissingKeys} +import pureconfig.generic.semiauto.deriveReader case class RideRunnerBlockchainState( height: Int = 3296626, @@ -13,4 +17,9 @@ case class RideRunnerBlockchainState( assets: Map[IssuedAsset, RideRunnerAsset] = Map.empty, blocks: Map[Int, RideRunnerBlock] = Map.empty, transactions: Map[ByteStr, RideRunnerTransaction] = Map.empty -) derives ConfigReader +) + +object RideRunnerBlockchainState { + // required for default args to work properly: https://github.com/pureconfig/pureconfig/issues/1673 + given ConfigReader[RideRunnerBlockchainState] = deriveReader[RideRunnerBlockchainState] +} diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerInput.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerInput.scala index 029890bca6..fd9b0ecc25 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerInput.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerInput.scala @@ -3,6 +3,7 @@ package com.wavesplatform.ride.runner.input import com.wavesplatform.account.{Address, DefaultAddressScheme} import play.api.libs.json.JsObject + case class RideRunnerInput( address: Address, request: JsObject, diff --git a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerLeaseBalance.scala b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerLeaseBalance.scala index ef4aecf951..0eebe032aa 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerLeaseBalance.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/ride/runner/input/RideRunnerLeaseBalance.scala @@ -1,7 +1,10 @@ package com.wavesplatform.ride.runner.input +import com.wavesplatform.ride.runner.input.RideRunnerInputParser.given import com.wavesplatform.transaction.TxNonNegativeAmount import pureconfig.ConfigReader -case class RideRunnerLeaseBalance(in: TxNonNegativeAmount = TxNonNegativeAmount.unsafeFrom(0), out: TxNonNegativeAmount = TxNonNegativeAmount.unsafeFrom(0)) - derives ConfigReader +case class RideRunnerLeaseBalance( + in: TxNonNegativeAmount = TxNonNegativeAmount.unsafeFrom(0), + out: TxNonNegativeAmount = TxNonNegativeAmount.unsafeFrom(0) +) derives ConfigReader diff --git a/ride-runner/src/test/scala/com/wavesplatform/ride/DiffXInstances.scala b/ride-runner/src/test/scala/com/wavesplatform/ride/DiffXInstances.scala index dc145192aa..610df816ed 100644 --- a/ride-runner/src/test/scala/com/wavesplatform/ride/DiffXInstances.scala +++ b/ride-runner/src/test/scala/com/wavesplatform/ride/DiffXInstances.scala @@ -1,15 +1,40 @@ package com.wavesplatform.ride import com.softwaremill.diffx.Diff +import com.softwaremill.diffx.generic.AutoDerivation import com.softwaremill.diffx.generic.auto.* -import com.wavesplatform.account.PublicKey +import com.wavesplatform.account.{Address, AddressOrAlias, Alias, PublicKey} import com.wavesplatform.common.state.ByteStr import com.wavesplatform.lang.script.Script -import com.wavesplatform.ride.runner.input.StringOrBytesAsByteArray +import com.wavesplatform.ride.runner.input.* +import com.wavesplatform.state.LeaseBalance +import com.wavesplatform.transaction.Asset.IssuedAsset +import com.wavesplatform.transaction.assets.exchange.AssetPair +import com.wavesplatform.transaction.{Asset, TxNonNegativeAmount} +import play.api.libs.json.{JsObject, JsValue} trait DiffXInstances { - implicit val diffForByteStr: Diff[ByteStr] = Diff.summon[String].contramap(_.toString) - implicit val diffForStringOrBytesAsByteArray: Diff[StringOrBytesAsByteArray] = diffForByteStr.contramap(ByteStr(_)) - implicit val diffForScript: Diff[Script] = diffForByteStr.contramap(_.bytes()) - implicit val diffForPublicKey: Diff[PublicKey] = diffForByteStr.contramap(x => x) + given Diff[ByteStr] = Diff[String].contramap(_.toString) + given Diff[StringOrBytesAsByteArray] = Diff[ByteStr].contramap(ByteStr(_)) + given Diff[Script] = Diff[ByteStr].contramap(_.bytes()) + given Diff[PublicKey] = Diff[ByteStr].contramap(x => x) + given Diff[JsValue] = Diff.derived[JsValue] + given Diff[JsObject] = Diff.derived[JsObject] + given Diff[Address] = Diff[ByteStr].contramap(a => ByteStr(a.bytes)) + given Diff[TxNonNegativeAmount] = Diff[Long].contramap(_.value) + given Diff[Asset.IssuedAsset] = Diff[String].contramap(AssetPair.assetIdStr) + given Diff[Asset] = Diff[String].contramap(AssetPair.assetIdStr) + given Diff[RideRunnerLeaseBalance] = Diff.derived[RideRunnerLeaseBalance] + given Diff[RideRunnerDataEntry] = Diff.derived[RideRunnerDataEntry] + given Diff[Alias] = Diff[String].contramap(_.toString) + given Diff[AddressOrAlias] = Diff[String].contramap(_.toString) + given Diff[RideRunnerScriptInfo] = Diff.derived[RideRunnerScriptInfo] + given Diff[RideRunnerAccount] = Diff.derived[RideRunnerAccount] + given Diff[RideRunnerAsset] = Diff.derived[RideRunnerAsset] + given Diff[RideRunnerBlock] = Diff.derived[RideRunnerBlock] + given Diff[RideRunnerTransaction] = Diff.derived[RideRunnerTransaction] + given Diff[RideRunnerBlockchainState] = Diff.derived[RideRunnerBlockchainState] + given Diff[RideRunnerPostProcessingMethod] = Diff.derived[RideRunnerPostProcessingMethod] + given Diff[RideRunnerTest] = Diff.derived[RideRunnerTest] + given Diff[RideRunnerInput] = Diff.derived[RideRunnerInput] } diff --git a/ride-runner/src/test/scala/com/wavesplatform/ride/runner/ExpectedHeightCallsTestSuite.scala b/ride-runner/src/test/scala/com/wavesplatform/ride/runner/ExpectedHeightCallsTestSuite.scala index 761d7a323d..8b59051806 100644 --- a/ride-runner/src/test/scala/com/wavesplatform/ride/runner/ExpectedHeightCallsTestSuite.scala +++ b/ride-runner/src/test/scala/com/wavesplatform/ride/runner/ExpectedHeightCallsTestSuite.scala @@ -120,11 +120,11 @@ class ExpectedHeightCallsTestSuite extends BaseTestSuite with HasTestAccounts { height = DefaultHeight, accounts = Map( aliceAddr -> RideRunnerAccount( - regularBalance = Some(TxNonNegativeAmount(10_000_000)) + regularBalance = Some(TxNonNegativeAmount.unsafeFrom(10_000_000)) ), bobAddr -> RideRunnerAccount( data = Some(Map.empty), - regularBalance = Some(TxNonNegativeAmount(10_300_000)) + regularBalance = Some(TxNonNegativeAmount.unsafeFrom(10_300_000)) ) ), blocks = Map( 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 7987a85028..5588543ebc 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 @@ -154,7 +154,7 @@ class RequestServiceTestSuite extends BaseTestSuite with HasGrpc with HasBasicGr } } - private case class TestDependencies( + case class TestDependencies( requestServiceSettings: DefaultRequestService.Settings, requests: RequestService, processor: Processor, diff --git a/ride-runner/src/test/scala/com/wavesplatform/ride/runner/TestScript.scala b/ride-runner/src/test/scala/com/wavesplatform/ride/runner/TestScript.scala index e2ab1479f0..1963dbd551 100644 --- a/ride-runner/src/test/scala/com/wavesplatform/ride/runner/TestScript.scala +++ b/ride-runner/src/test/scala/com/wavesplatform/ride/runner/TestScript.scala @@ -4,6 +4,7 @@ import com.wavesplatform.common.utils.{Base64, EitherExt2} import com.wavesplatform.lang.API import com.wavesplatform.lang.script.Script import com.wavesplatform.lang.v1.estimator.v3.ScriptEstimatorV3 +import com.wavesplatform.common.utils.EitherExt2.explicitGet object TestScript { def scriptFrom(src: String): Script = diff --git a/ride-runner/src/test/scala/com/wavesplatform/ride/runner/blockchain/LazyBlockchainTestSuite.scala b/ride-runner/src/test/scala/com/wavesplatform/ride/runner/blockchain/LazyBlockchainTestSuite.scala index e0984519c9..e811e01669 100644 --- a/ride-runner/src/test/scala/com/wavesplatform/ride/runner/blockchain/LazyBlockchainTestSuite.scala +++ b/ride-runner/src/test/scala/com/wavesplatform/ride/runner/blockchain/LazyBlockchainTestSuite.scala @@ -7,6 +7,7 @@ import com.wavesplatform.account.PublicKeys.EmptyPublicKey import com.wavesplatform.api.{HasGrpc, TestBlockchainApi} import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.EitherExt2 +import com.wavesplatform.common.utils.EitherExt2.explicitGet import com.wavesplatform.events.protobuf.BlockchainUpdated.Append.Body import com.wavesplatform.events.protobuf.{BlockchainUpdated, StateUpdate} import com.wavesplatform.history.DefaultBlockchainSettings @@ -19,10 +20,10 @@ import com.wavesplatform.ride.runner.caches.* import com.wavesplatform.ride.runner.caches.disk.DefaultDiskCaches import com.wavesplatform.ride.runner.caches.mem.{MemBlockchainDataCache, MemCacheKey} import com.wavesplatform.ride.runner.db.HasTestDb -import com.wavesplatform.state.{AccountScriptInfo, AssetDescription, Height, IntegerDataEntry, LeaseBalance, TransactionId} +import com.wavesplatform.state.{AccountScriptInfo, AssetDescription, DataEntry, Height, IntegerDataEntry, LeaseBalance, TransactionId} import com.wavesplatform.transaction.{Asset, AssetIdLength} import com.wavesplatform.utils.StringBytes -import com.wavesplatform.{BaseTestSuite, HasTestAccounts} +import com.wavesplatform.{BaseTestSuite, HasTestAccounts, state} class LazyBlockchainTestSuite extends BaseTestSuite with HasTestDb with HasGrpc with HasTestAccounts { "LazyBlockchain" - { @@ -488,7 +489,7 @@ class LazyBlockchainTestSuite extends BaseTestSuite with HasTestDb with HasGrpc private lazy val heightKey = MemCacheKey.Height private lazy val accountScriptKey = MemCacheKey.AccountScript(aliceAddr) - private lazy val allDependencies: Map[MemCacheKey, Tag] = Map( + private lazy val allDependencies: Map[MemCacheKey[?], Tag] = Map( MemCacheKey.AccountData(aliceAddr, "x") -> 1, MemCacheKey.Transaction(transactionId) -> 2, heightKey -> 3, @@ -503,7 +504,7 @@ class LazyBlockchainTestSuite extends BaseTestSuite with HasTestDb with HasGrpc private type Tag = Int private abstract class Test { - val dependencies: Map[MemCacheKey, Tag] = Map.empty + val dependencies: Map[MemCacheKey[?], Tag] = Map.empty val preEvents: Seq[BlockchainUpdated] = Seq.empty val trackAffectedEvents: Seq[BlockchainUpdated] = Seq.empty @@ -533,7 +534,7 @@ class LazyBlockchainTestSuite extends BaseTestSuite with HasTestDb with HasGrpc } private class Access(val blockchain: LazyBlockchain[Tag], memCache: MemBlockchainDataCache, val affectedTags: AffectedTags[Tag]) { - def get[T <: MemCacheKey](key: T): RemoteData[T#ValueT] = memCache.get(key) + def get[V, T <: MemCacheKey[V]](key: T): RemoteData[V] = memCache.get(key) def noTagsAffected(): this.type = withClue("affected tags (noTagsAreAffected)") { affectedTags shouldBe empty @@ -542,7 +543,7 @@ class LazyBlockchainTestSuite extends BaseTestSuite with HasTestDb with HasGrpc def allTagsAffected(): this.type = allTagsAffectedExcept() - def allTagsAffectedExcept(keys: MemCacheKey*): this.type = { + def allTagsAffectedExcept(keys: MemCacheKey[?]*): this.type = { val expected = allTags -- keys.map(allDependencies.apply) val sortedDiff = (expected -- affectedTags).toList.sorted withClue(s"affected tags, diff={${sortedDiff.mkString(", ")}}") { @@ -572,7 +573,7 @@ class LazyBlockchainTestSuite extends BaseTestSuite with HasTestDb with HasGrpc aliceLeaseBalance = RemoteData.Cached(LeaseBalance(4L, 3L)), aliceAccountScript = RemoteData.Cached( WeighedAccountScriptInfo( - scriptInfoWeight = 480, + scriptInfoWeight = 528, accountScriptInfo = AccountScriptInfo( publicKey = alice.publicKey, script = accountScript.script, @@ -584,13 +585,13 @@ class LazyBlockchainTestSuite extends BaseTestSuite with HasTestDb with HasGrpc ) def dataIs( - aliceAccountData: RemoteData[MemCacheKey.AccountData#ValueT] = RemoteData.Unknown, - transaction: RemoteData[MemCacheKey.Transaction#ValueT] = RemoteData.Unknown, - assetInfo: RemoteData[MemCacheKey.Asset#ValueT] = RemoteData.Unknown, - aliceWavesBalance: RemoteData[MemCacheKey.AccountBalance#ValueT] = RemoteData.Unknown, - bobAssetBalance: RemoteData[MemCacheKey.AccountBalance#ValueT] = RemoteData.Unknown, - aliceLeaseBalance: RemoteData[MemCacheKey.AccountLeaseBalance#ValueT] = RemoteData.Unknown, - aliceAccountScript: RemoteData[MemCacheKey.AccountScript#ValueT] = RemoteData.Unknown + aliceAccountData: RemoteData[DataEntry[?]] = RemoteData.Unknown, + transaction: RemoteData[state.Height] = RemoteData.Unknown, + assetInfo: RemoteData[WeighedAssetDescription] = RemoteData.Unknown, + aliceWavesBalance: RemoteData[Long] = RemoteData.Unknown, + bobAssetBalance: RemoteData[Long] = RemoteData.Unknown, + aliceLeaseBalance: RemoteData[LeaseBalance] = RemoteData.Unknown, + aliceAccountScript: RemoteData[WeighedAccountScriptInfo] = RemoteData.Unknown ): this.type = { withClue("account data") { get(MemCacheKey.AccountData(aliceAddr, "x")) shouldBe aliceAccountData diff --git a/ride-runner/src/test/scala/com/wavesplatform/ride/runner/caches/disk/AccountScriptDiskCacheTestSuite.scala b/ride-runner/src/test/scala/com/wavesplatform/ride/runner/caches/disk/AccountScriptDiskCacheTestSuite.scala index 7fefd8640e..3d789ba388 100644 --- a/ride-runner/src/test/scala/com/wavesplatform/ride/runner/caches/disk/AccountScriptDiskCacheTestSuite.scala +++ b/ride-runner/src/test/scala/com/wavesplatform/ride/runner/caches/disk/AccountScriptDiskCacheTestSuite.scala @@ -7,6 +7,7 @@ import com.wavesplatform.lang.script.Script import com.wavesplatform.ride.runner.caches.WeighedAccountScriptInfo import com.wavesplatform.ride.runner.db.{Heights, ReadOnly, ReadWrite} import com.wavesplatform.state.AccountScriptInfo +import com.wavesplatform.common.utils.EitherExt2.explicitGet class AccountScriptDiskCacheTestSuite extends DiskCacheWithHistoryTestSuite[Address, WeighedAccountScriptInfo] { private val defaultAddressId = AddressId(0L) // There is only one addressId 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 360a8b2f56..1aea285473 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,7 +10,6 @@ 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/ride-runner/src/test/scala/com/wavesplatform/ride/runner/input/RideRunnerInputParserTestSuite.scala b/ride-runner/src/test/scala/com/wavesplatform/ride/runner/input/RideRunnerInputParserTestSuite.scala index 8ebd68a41f..0f420e99b7 100644 --- a/ride-runner/src/test/scala/com/wavesplatform/ride/runner/input/RideRunnerInputParserTestSuite.scala +++ b/ride-runner/src/test/scala/com/wavesplatform/ride/runner/input/RideRunnerInputParserTestSuite.scala @@ -17,6 +17,7 @@ import org.scalatest.prop.TableDrivenPropertyChecks import com.wavesplatform.ride.runner.input.PureconfigImplicits.* import play.api.libs.json.* import pureconfig.* +import com.wavesplatform.common.utils.EitherExt2.explicitGet import java.nio.charset.StandardCharsets import scala.reflect.ClassTag @@ -146,12 +147,12 @@ let x = getIntegerValue(alice, "x") "Integer" in { List( - Byte.MinValue, - Byte.MaxValue, - Short.MinValue, - Short.MaxValue, - Int.MinValue, - Int.MaxValue, + Byte.MinValue.toLong, + Byte.MaxValue.toLong, + Short.MinValue.toLong, + Short.MaxValue.toLong, + Int.MinValue.toLong, + Int.MaxValue.toLong, Long.MinValue, Long.MaxValue ).foreach { x => parse("integer", x.toString) shouldBe IntegerRideRunnerDataEntry(x) } @@ -269,9 +270,9 @@ let x = getIntegerValue(alice, "x") regularBalance = TxNonNegativeAmount.unsafeFrom(500001).some ), aliceAddr -> RideRunnerAccount( - assetBalances = Map(btc -> TxNonNegativeAmount(1)), + assetBalances = Map(btc -> TxNonNegativeAmount.unsafeFrom(1)), regularBalance = TxNonNegativeAmount.unsafeFrom(500100).some, - leasing = RideRunnerLeaseBalance(in = TxNonNegativeAmount(10), out = TxNonNegativeAmount(100)).some, + leasing = RideRunnerLeaseBalance(in = TxNonNegativeAmount.unsafeFrom(10), out = TxNonNegativeAmount.unsafeFrom(100)).some, generatingBalance = TxNonNegativeAmount.unsafeFrom(100_000_000_000L).some, data = Map( "a" -> IntegerRideRunnerDataEntry(11), @@ -373,8 +374,8 @@ func bar () = { } } - private def parseQuotedStringAs[T: ConfigReader: ClassTag](s: String): T = + private def parseQuotedStringAs[T: {ConfigReader, ClassTag}](s: String): T = ConfigSource.fromConfig(ConfigFactory.parseString(s"""x = \"\"\"$s\"\"\"""")).at("x").loadOrThrow[T] - private def parseAs[T: ConfigReader: ClassTag](rawContent: String): T = + private def parseAs[T: {ConfigReader, ClassTag}](rawContent: String): T = ConfigSource.fromConfig(ConfigFactory.parseString(s"""x = $rawContent""")).at("x").loadOrThrow[T] }