From b672ff83e45e03b99029dd3bfeb2a324c9e9b549 Mon Sep 17 00:00:00 2001 From: Sergey Nazarov Date: Mon, 20 Nov 2023 13:28:45 +0400 Subject: [PATCH] wip --- .../scala/com/wavesplatform/Application.scala | 1 - .../api/common/CommonAccountsApi.scala | 4 +- .../api/http/TransactionJsonSerializer.scala | 4 +- .../api/http/assets/AssetsApiRoute.scala | 2 - .../com/wavesplatform/database/Keys.scala | 2 +- .../database/RocksDBWriter.scala | 35 ++---- .../com/wavesplatform/database/package.scala | 112 ++++++++---------- .../wavesplatform/protobuf/PBSnapshots.scala | 26 ++-- .../state/BlockchainUpdaterImpl.scala | 43 ++++--- .../wavesplatform/state/LeaseSnapshot.scala | 30 ----- .../state/NewTransactionInfo.scala | 9 +- .../wavesplatform/state/StateSnapshot.scala | 24 +--- .../state/TxStateSnapshotHashBuilder.scala | 2 +- .../state/diffs/DiffsCommon.scala | 21 ++-- .../state/diffs/LeaseTransactionsDiff.scala | 2 +- .../diffs/invoke/InvokeDiffsCommon.scala | 10 +- .../state/patch/CancelAllLeases.scala | 7 +- .../patch/CancelLeasesToDisabledAliases.scala | 22 ++-- .../state/reader/LeaseDetails.scala | 5 +- .../state/reader/SnapshotBlockchain.scala | 12 +- .../validation/impl/LeaseTxValidator.scala | 8 +- .../api/http/CustomJsonMarshallerSpec.scala | 98 +++++---------- .../consensus/FPPoSSelectorTest.scala | 2 +- .../wavesplatform/db/ScriptCacheTest.scala | 2 +- .../wavesplatform/history/SnapshotOps.scala | 4 +- .../wavesplatform/http/AssetsRouteSpec.scala | 5 +- .../http/DebugApiRouteSpec.scala | 4 +- .../wavesplatform/http/LeaseRouteSpec.scala | 105 ++++++---------- .../http/TransactionsRouteSpec.scala | 20 ++-- .../wavesplatform/mining/BlockV5Test.scala | 2 +- .../mining/BlockWithMaxBaseTargetTest.scala | 2 +- .../wavesplatform/state/RollbackSpec.scala | 12 +- .../diffs/ci/sync/SyncInvokeLeaseTest.scala | 4 +- .../snapshot/StateSnapshotProtoTest.scala | 9 +- .../snapshot/StateSnapshotStorageTest.scala | 12 +- .../database/rocksdb/package.scala | 2 +- 36 files changed, 245 insertions(+), 419 deletions(-) delete mode 100644 node/src/main/scala/com/wavesplatform/state/LeaseSnapshot.scala diff --git a/node/src/main/scala/com/wavesplatform/Application.scala b/node/src/main/scala/com/wavesplatform/Application.scala index 1f2bfbb1c0f..74625fabfb1 100644 --- a/node/src/main/scala/com/wavesplatform/Application.scala +++ b/node/src/main/scala/com/wavesplatform/Application.scala @@ -441,7 +441,6 @@ class Application(val actorSystem: ActorSystem, val settings: WavesSettings, con settings.restAPISettings, serverRequestTimeout, wallet, - transactionPublisher, blockchainUpdater, () => blockchainUpdater.snapshotBlockchain, time, 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 0e7bc89ddcc..9570d4d38a3 100644 --- a/node/src/main/scala/com/wavesplatform/api/common/CommonAccountsApi.scala +++ b/node/src/main/scala/com/wavesplatform/api/common/CommonAccountsApi.scala @@ -188,8 +188,8 @@ object CommonAccountsApi { leaseId, ld.sourceId, ld.sender.toAddress, - blockchain.resolveAlias(ld.recipient).orElse(resolveDisabledAlias(leaseId)).explicitGet(), - ld.amount, + blockchain.resolveAlias(ld.recipientAddress).orElse(resolveDisabledAlias(leaseId)).explicitGet(), + ld.amount.value, ld.height, ld.status match { case Status.Active => LeaseInfo.Status.Active 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 b67c81bf8b7..366d7db0479 100644 --- a/node/src/main/scala/com/wavesplatform/api/http/TransactionJsonSerializer.scala +++ b/node/src/main/scala/com/wavesplatform/api/http/TransactionJsonSerializer.scala @@ -448,7 +448,7 @@ final case class TransactionJsonSerializer(blockchain: Blockchain, commonApi: Co ): LeaseRef = { val detailsOpt = blockchain.leaseDetails(leaseId) val txMetaOpt = detailsOpt.flatMap(d => blockchain.transactionMeta(d.sourceId)) - val recipientOpt = recipientParamOpt.orElse(detailsOpt.map(_.recipient)) + val recipientOpt = recipientParamOpt.orElse(detailsOpt.map(_.recipientAddress)) val resolvedRecipientOpt = recipientOpt.flatMap(r => blockchain.resolveAlias(r).toOption) val statusOpt = detailsOpt.map(_.status) @@ -464,7 +464,7 @@ final case class TransactionJsonSerializer(blockchain: Blockchain, commonApi: Co detailsOpt.map(_.sourceId), detailsOpt.map(_.sender.toAddress), resolvedRecipientOpt, - amountOpt orElse detailsOpt.map(_.amount), + amountOpt orElse detailsOpt.map(_.amount.value), txMetaOpt.map(_.height), status, statusDataOpt.flatMap(_._1), 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 e8bfbc82b05..f7c447ad04a 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 @@ -27,7 +27,6 @@ import com.wavesplatform.api.http.assets.AssetsApiRoute.{ } import com.wavesplatform.common.state.ByteStr import com.wavesplatform.lang.ValidationError -import com.wavesplatform.network.TransactionPublisher import com.wavesplatform.settings.RestAPISettings import com.wavesplatform.state.{AssetDescription, AssetScriptInfo, Blockchain, TxMeta} import com.wavesplatform.transaction.Asset.IssuedAsset @@ -51,7 +50,6 @@ case class AssetsApiRoute( settings: RestAPISettings, serverRequestTimeout: FiniteDuration, wallet: Wallet, - transactionPublisher: TransactionPublisher, blockchain: Blockchain, compositeBlockchain: () => Blockchain, time: Time, diff --git a/node/src/main/scala/com/wavesplatform/database/Keys.scala b/node/src/main/scala/com/wavesplatform/database/Keys.scala index 47fc85f3e83..8fbb1b70834 100644 --- a/node/src/main/scala/com/wavesplatform/database/Keys.scala +++ b/node/src/main/scala/com/wavesplatform/database/Keys.scala @@ -99,7 +99,7 @@ object Keys { Key(LeaseBalance, addressId.toByteArray, readLeaseBalance, writeLeaseBalance) def leaseDetailsHistory(leaseId: ByteStr): Key[Seq[Int]] = historyKey(LeaseDetailsHistory, leaseId.arr) - def leaseDetails(leaseId: ByteStr)(height: Int): Key[Option[Either[Boolean, LeaseDetails]]] = + def leaseDetails(leaseId: ByteStr)(height: Int): Key[Option[LeaseDetails]] = Key.opt(LeaseDetailsTag, Ints.toByteArray(height) ++ leaseId.arr, readLeaseDetails, writeLeaseDetails) def filledVolumeAndFeeAt(orderId: ByteStr, height: Height): Key[VolumeAndFeeNode] = diff --git a/node/src/main/scala/com/wavesplatform/database/RocksDBWriter.scala b/node/src/main/scala/com/wavesplatform/database/RocksDBWriter.scala index 4da53d6a2ab..3bdde73ae90 100644 --- a/node/src/main/scala/com/wavesplatform/database/RocksDBWriter.scala +++ b/node/src/main/scala/com/wavesplatform/database/RocksDBWriter.scala @@ -484,15 +484,8 @@ class RocksDBWriter( expiredKeys ++= updateHistory(rw, Keys.assetDetailsHistory(asset), threshold, Keys.assetDetails(asset)) } - val txLeases = for { - (_, txInfo) <- snapshot.transactions - (id, lease) <- txInfo.snapshot.leaseStates - } yield (Some(txInfo.transaction), id, lease) - val txLeaseIdSet = txLeases.map(_._2).toSet - val allLeases = txLeases ++ snapshot.leaseStates.collect { case (id, lease) if !txLeaseIdSet.contains(id) => (None, id, lease) } - allLeases.foreach { case (txOpt, id, lease) => - val details = lease.toDetails(this, txOpt, leaseDetails(id)) - rw.put(Keys.leaseDetails(id)(height), Some(Right(details))) + for ((id, details) <- snapshot.leaseStates) { + rw.put(Keys.leaseDetails(id)(height), Some(details)) expiredKeys ++= updateHistory(rw, Keys.leaseDetailsHistory(id), threshold, Keys.leaseDetails(id)) } @@ -523,7 +516,10 @@ class RocksDBWriter( val txId = TransactionId(id) val size = rw.put(Keys.transactionAt(Height(height), num, rdb.txHandle), Some((meta, tx))) - rw.put(Keys.transactionStateSnapshotAt(Height(height), num, rdb.txSnapshotHandle), Some(PBSnapshots.toProtobuf(txInfo.snapshot, txInfo.status))) + rw.put( + Keys.transactionStateSnapshotAt(Height(height), num, rdb.txSnapshotHandle), + Some(PBSnapshots.toProtobuf(txInfo.snapshot, txInfo.status)) + ) rw.put(Keys.transactionMetaById(txId, rdb.txMetaHandle), Some(TransactionMeta(height, num, tx.tpe.id, meta.status.protobuf, 0, size))) targetBf.put(id.arr) @@ -953,23 +949,8 @@ class RocksDBWriter( override def leaseDetails(leaseId: ByteStr): Option[LeaseDetails] = readOnly { db => for { - h <- db.get(Keys.leaseDetailsHistory(leaseId)).headOption - detailsOrFlag <- db.get(Keys.leaseDetails(leaseId)(h)) - details <- detailsOrFlag.fold( - isActive => - transactionInfo(leaseId, db).collect { case (txm, lt: LeaseTransaction) => - LeaseDetails( - lt.sender, - lt.recipient, - lt.amount.value, - if (isActive) LeaseDetails.Status.Active - else LeaseDetails.Status.Cancelled(h, None), - leaseId, - txm.height - ) - }, - Some(_) - ) + h <- db.get(Keys.leaseDetailsHistory(leaseId)).headOption + details <- db.get(Keys.leaseDetails(leaseId)(h)) } yield details } diff --git a/node/src/main/scala/com/wavesplatform/database/package.scala b/node/src/main/scala/com/wavesplatform/database/package.scala index a450c64d056..46c5192e045 100644 --- a/node/src/main/scala/com/wavesplatform/database/package.scala +++ b/node/src/main/scala/com/wavesplatform/database/package.scala @@ -24,8 +24,16 @@ import com.wavesplatform.state.* import com.wavesplatform.state.StateHash.SectionId import com.wavesplatform.state.reader.LeaseDetails import com.wavesplatform.transaction.Asset.IssuedAsset -import com.wavesplatform.transaction.lease.LeaseTransaction -import com.wavesplatform.transaction.{EthereumTransaction, GenesisTransaction, PBSince, PaymentTransaction, Transaction, TransactionParsers, TxValidationError} +import com.wavesplatform.transaction.{ + EthereumTransaction, + GenesisTransaction, + PBSince, + PaymentTransaction, + Transaction, + TransactionParsers, + TxPositiveAmount, + TxValidationError +} import com.wavesplatform.utils.* import monix.eval.Task import monix.reactive.Observable @@ -135,47 +143,39 @@ package object database { 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.recipient)), - ld.amount, - ByteString.copyFrom(ld.sourceId.arr), - ld.height, - ld.status match { - case LeaseDetails.Status.Active => pb.LeaseDetails.Status.Active(com.google.protobuf.empty.Empty()) - case LeaseDetails.Status.Cancelled(height, cancelTxId) => - pb.LeaseDetails.Status - .Cancelled(pb.LeaseDetails.Cancelled(height, cancelTxId.fold(ByteString.EMPTY)(id => ByteString.copyFrom(id.arr)))) - case LeaseDetails.Status.Expired(height) => pb.LeaseDetails.Status.Expired(pb.LeaseDetails.Expired(height)) - } - ).toByteArray - ) + def writeLeaseDetails(ld: LeaseDetails): Array[Byte] = + 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.Status.Active(com.google.protobuf.empty.Empty()) + case LeaseDetails.Status.Cancelled(height, cancelTxId) => + pb.LeaseDetails.Status + .Cancelled(pb.LeaseDetails.Cancelled(height, cancelTxId.fold(ByteString.EMPTY)(id => ByteString.copyFrom(id.arr)))) + case LeaseDetails.Status.Expired(height) => pb.LeaseDetails.Status.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( - d.senderPublicKey.toPublicKey, - PBRecipients.toAddressOrAlias(d.recipient.get, AddressScheme.current.chainId).explicitGet(), - d.amount, - d.status match { - case pb.LeaseDetails.Status.Active(_) => LeaseDetails.Status.Active - case pb.LeaseDetails.Status.Expired(pb.LeaseDetails.Expired(height, _)) => LeaseDetails.Status.Expired(height) - case pb.LeaseDetails.Status.Cancelled(pb.LeaseDetails.Cancelled(height, transactionId, _)) => - LeaseDetails.Status.Cancelled(height, Some(transactionId.toByteStr).filter(!_.isEmpty)) - case pb.LeaseDetails.Status.Empty => ??? - }, - d.sourceId.toByteStr, - d.height - ) - ) - } + def readLeaseDetails(data: Array[Byte]): LeaseDetails = { + val d = pb.LeaseDetails.parseFrom(data) + LeaseDetails( + d.senderPublicKey.toPublicKey, + PBRecipients.toAddress(d.recipient.get, AddressScheme.current.chainId).explicitGet(), + TxPositiveAmount.unsafeFrom(d.amount), + d.status match { + case pb.LeaseDetails.Status.Active(_) => LeaseDetails.Status.Active + case pb.LeaseDetails.Status.Expired(pb.LeaseDetails.Expired(height, _)) => LeaseDetails.Status.Expired(height) + case pb.LeaseDetails.Status.Cancelled(pb.LeaseDetails.Cancelled(height, transactionId, _)) => + LeaseDetails.Status.Cancelled(height, Some(transactionId.toByteStr).filter(!_.isEmpty)) + case pb.LeaseDetails.Status.Empty => ??? + }, + d.sourceId.toByteStr, + d.height + ) + } 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)))) @@ -247,17 +247,6 @@ package object database { ).toByteArray } - def readAssetStaticInfo(bb: Array[Byte]): AssetStaticInfo = { - val sai = pb.StaticAssetInfo.parseFrom(bb) - AssetStaticInfo( - sai.id.toByteStr, - TransactionId(sai.sourceId.toByteStr), - PublicKey(sai.issuerPublicKey.toByteArray), - sai.decimals, - sai.isNft - ) - } - def writeBlockMeta(data: pb.BlockMeta): Array[Byte] = data.toByteArray def readBlockMeta(bs: Array[Byte]): pb.BlockMeta = pb.BlockMeta.parseFrom(bs) @@ -700,16 +689,13 @@ package object database { Height(pbStaticInfo.height) ) - def loadActiveLeases(rdb: RDB, fromHeight: Int, toHeight: Int): Seq[LeaseTransaction] = rdb.db.withResource { r => + def loadActiveLeases(rdb: RDB, fromHeight: Int, toHeight: Int): Map[ByteStr, LeaseDetails] = rdb.db.withResource { r => (for { - id <- loadLeaseIds(r, fromHeight, toHeight, includeCancelled = false) - details <- fromHistory(r, Keys.leaseDetailsHistory(id), Keys.leaseDetails(id)) - if details.exists(_.fold(identity, _.isActive)) - tm <- r.get(Keys.transactionMetaById(TransactionId(id), rdb.txMetaHandle)) - tx <- r.get(Keys.transactionAt(Height(tm.height), TxNum(tm.num.toShort), rdb.txHandle)) - } yield tx).collect { - case (ltm, lt: LeaseTransaction) if ltm.status == TxMeta.Status.Succeeded => lt - }.toSeq + id <- loadLeaseIds(r, fromHeight, toHeight, includeCancelled = false) + maybeNewDetails <- fromHistory(r, Keys.leaseDetailsHistory(id), Keys.leaseDetails(id)) + newDetails <- maybeNewDetails + if newDetails.isActive + } yield (id, newDetails)).toMap } def loadLeaseIds(resource: DBResource, fromHeight: Int, toHeight: Int, includeCancelled: Boolean): Set[ByteStr] = { @@ -726,7 +712,7 @@ package object database { iterator.seek(KeyTags.LeaseDetails.prefixBytes ++ Ints.toByteArray(fromHeight)) while (iterator.isValid && keyInRange()) { val leaseId = ByteStr(iterator.key().drop(6)) - if (includeCancelled || readLeaseDetails(iterator.value()).fold(identity, _.isActive)) + if (includeCancelled || readLeaseDetails(iterator.value()).isActive) leaseIds += leaseId else leaseIds -= leaseId diff --git a/node/src/main/scala/com/wavesplatform/protobuf/PBSnapshots.scala b/node/src/main/scala/com/wavesplatform/protobuf/PBSnapshots.scala index 3002c822010..0406763116f 100644 --- a/node/src/main/scala/com/wavesplatform/protobuf/PBSnapshots.scala +++ b/node/src/main/scala/com/wavesplatform/protobuf/PBSnapshots.scala @@ -4,7 +4,6 @@ import com.google.protobuf.ByteString import com.wavesplatform.account.{Address, Alias, PublicKey} import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.EitherExt2 -import com.wavesplatform.crypto.KeyLength import com.wavesplatform.lang.script.ScriptReader import com.wavesplatform.protobuf.snapshot.TransactionStateSnapshot import com.wavesplatform.protobuf.snapshot.TransactionStateSnapshot.AssetStatic @@ -12,8 +11,8 @@ import com.wavesplatform.protobuf.transaction.{PBAmounts, PBTransactions} import com.wavesplatform.state.* import com.wavesplatform.state.reader.LeaseDetails import com.wavesplatform.state.reader.LeaseDetails.Status -import com.wavesplatform.transaction.Asset import com.wavesplatform.transaction.Asset.IssuedAsset +import com.wavesplatform.transaction.{Asset, TxPositiveAmount} import scala.collection.immutable.VectorMap @@ -46,10 +45,10 @@ object PBSnapshots { orderFills.map { case (orderId, VolumeAndFee(volume, fee)) => S.OrderFill(orderId.toByteString, volume, fee) }.toSeq, - leaseStates.map { case (leaseId, LeaseSnapshot(sender, recipient, amount, status)) => - val pbStatus = status match { + leaseStates.map { case (leaseId, ld) => + val pbStatus = ld.status match { case Status.Active => - S.LeaseState.Status.Active(S.LeaseState.Active(amount, sender.toByteString, recipient.asInstanceOf[Address].toByteString)) + S.LeaseState.Status.Active(S.LeaseState.Active(ld.amount.value, ld.sender.toByteString, ld.recipientAddress.toByteString)) case _: Status.Cancelled | _: Status.Expired => S.LeaseState.Status.Cancelled(S.LeaseState.Cancelled()) } @@ -116,23 +115,20 @@ object PBSnapshots { .map(s => s.assetId.toIssuedAssetId -> SponsorshipValue(s.minFee)) .toMap - val leaseStates: Map[ByteStr, LeaseSnapshot] = + val leaseStates: Map[ByteStr, LeaseDetails] = pbSnapshot.leaseStates.map { ls => ls.status match { case TransactionStateSnapshot.LeaseState.Status.Active(value) => - ls.leaseId.toByteStr -> LeaseSnapshot( + ls.leaseId.toByteStr -> LeaseDetails( value.sender.toPublicKey, value.recipient.toAddress(), - value.amount, - LeaseDetails.Status.Active + TxPositiveAmount.unsafeFrom(value.amount), + LeaseDetails.Status.Active, + txId, + height ) case _: TransactionStateSnapshot.LeaseState.Status.Cancelled | TransactionStateSnapshot.LeaseState.Status.Empty => - ls.leaseId.toByteStr -> LeaseSnapshot( - PublicKey(ByteStr.fill(KeyLength)(0)), - Address(Array.fill(Address.HashLength)(0)), - 0, - LeaseDetails.Status.Cancelled(0, None) - ) + ls.leaseId.toByteStr -> ??? } }.toMap diff --git a/node/src/main/scala/com/wavesplatform/state/BlockchainUpdaterImpl.scala b/node/src/main/scala/com/wavesplatform/state/BlockchainUpdaterImpl.scala index 99d193f72b9..4aa2255a67a 100644 --- a/node/src/main/scala/com/wavesplatform/state/BlockchainUpdaterImpl.scala +++ b/node/src/main/scala/com/wavesplatform/state/BlockchainUpdaterImpl.scala @@ -22,7 +22,6 @@ import com.wavesplatform.state.reader.{LeaseDetails, SnapshotBlockchain} import com.wavesplatform.transaction.* import com.wavesplatform.transaction.Asset.{IssuedAsset, Waves} import com.wavesplatform.transaction.TxValidationError.{BlockAppendError, GenericError, MicroBlockAppendError} -import com.wavesplatform.transaction.lease.* import com.wavesplatform.transaction.transfer.TransferTransactionLike import com.wavesplatform.utils.{ScorexLogging, Time, UnsupportedFeature, forceStopApplication} import kamon.Kamon @@ -37,7 +36,7 @@ class BlockchainUpdaterImpl( wavesSettings: WavesSettings, time: Time, blockchainUpdateTriggers: BlockchainUpdateTriggers, - collectActiveLeases: (Int, Int) => Seq[LeaseTransaction], + collectActiveLeases: (Int, Int) => Map[ByteStr, LeaseDetails], miner: Miner = _ => () ) extends Blockchain with BlockchainUpdater @@ -55,7 +54,7 @@ class BlockchainUpdaterImpl( private val lock = new ReentrantReadWriteLock(true) private def writeLock[B](f: => B): B = inLock(lock.writeLock(), f) - def readLock[B](f: => B): B = inLock(lock.readLock(), f) + private def readLock[B](f: => B): B = inLock(lock.readLock(), f) private lazy val maxBlockReadinessAge = wavesSettings.minerSettings.intervalAfterLastBlockThenGenerationIsAllowed.toMillis @@ -419,7 +418,7 @@ class BlockchainUpdaterImpl( ) } - private def collectLeasesToCancel(newHeight: Int): Seq[LeaseTransaction] = + private def collectLeasesToCancel(newHeight: Int): Map[ByteStr, LeaseDetails] = if (rocksdb.isFeatureActivated(BlockchainFeatures.LeaseExpiration, newHeight)) { val toHeight = newHeight - rocksdb.settings.functionalitySettings.leaseExpiration val fromHeight = rocksdb.featureActivationHeight(BlockchainFeatures.LeaseExpiration.id) match { @@ -431,24 +430,22 @@ class BlockchainUpdaterImpl( toHeight } collectActiveLeases(fromHeight, toHeight) - } else Seq.empty - - private def cancelLeases(leaseTransactions: Seq[LeaseTransaction], height: Int): Map[ByteStr, StateSnapshot] = { - val snapshotsById = - for { - lt <- leaseTransactions - recipient <- rocksdb.resolveAlias(lt.recipient).toSeq - portfolios = Map( - lt.sender.toAddress -> Portfolio(0, LeaseBalance(0, -lt.amount.value)), - recipient -> Portfolio(0, LeaseBalance(-lt.amount.value, 0)) - ) - leaseStates = Map( - lt.id() -> LeaseSnapshot(lt.sender, lt.recipient, lt.amount.value, LeaseDetails.Status.Expired(height)) - ) - snapshot = StateSnapshot.build(rocksdb, portfolios, leaseStates = leaseStates).explicitGet() - } yield lt.id() -> snapshot - snapshotsById.toMap - } + } else Map.empty + + private def cancelLeases(leaseTransactions: Map[ByteStr, LeaseDetails], height: Int): Map[ByteStr, StateSnapshot] = + for { + (id, lt) <- leaseTransactions + ltMeta <- transactionMeta(id).toSeq + recipient <- rocksdb.resolveAlias(lt.recipientAddress).toSeq + portfolios = Map( + lt.sender.toAddress -> Portfolio(0, LeaseBalance(0, -lt.amount.value)), + recipient -> Portfolio(0, LeaseBalance(-lt.amount.value, 0)) + ) + leaseStates = Map( + id -> LeaseDetails(lt.sender, lt.recipientAddress, lt.amount, LeaseDetails.Status.Expired(height), id, ltMeta.height) + ) + snapshot = StateSnapshot.build(rocksdb, portfolios, leaseStates = leaseStates).explicitGet() + } yield id -> snapshot override def removeAfter(blockId: ByteStr): Either[ValidationError, DiscardedBlocks] = writeLock { log.info(s"Trying rollback blockchain to $blockId") @@ -821,7 +818,7 @@ object BlockchainUpdaterImpl { private def displayFeatures(s: Set[Short]): String = s"FEATURE${if (s.size > 1) "S" else ""} ${s.mkString(", ")} ${if (s.size > 1) "have been" else "has been"}" - def areVersionsOfSameBlock(b1: Block, b2: Block): Boolean = + private def areVersionsOfSameBlock(b1: Block, b2: Block): Boolean = b1.header.generator == b2.header.generator && b1.header.baseTarget == b2.header.baseTarget && b1.header.reference == b2.header.reference && diff --git a/node/src/main/scala/com/wavesplatform/state/LeaseSnapshot.scala b/node/src/main/scala/com/wavesplatform/state/LeaseSnapshot.scala deleted file mode 100644 index e49fa4a09d4..00000000000 --- a/node/src/main/scala/com/wavesplatform/state/LeaseSnapshot.scala +++ /dev/null @@ -1,30 +0,0 @@ -package com.wavesplatform.state -import com.wavesplatform.account.{AddressOrAlias, PublicKey} -import com.wavesplatform.common.state.ByteStr -import com.wavesplatform.state.reader.LeaseDetails -import com.wavesplatform.transaction.Transaction -import com.wavesplatform.transaction.lease.LeaseCancelTransaction - -import scala.util.Try - -case class LeaseSnapshot(sender: PublicKey, recipient: AddressOrAlias, amount: Long, status: LeaseDetails.Status) { - val isActive: Boolean = status == LeaseDetails.Status.Active - - def toDetails(blockchain: Blockchain, txOpt: Option[Transaction], innerDetails: => Option[LeaseDetails]): LeaseDetails = { - def height(id: ByteStr) = blockchain.transactionMeta(id).map(_.height).getOrElse(blockchain.height) - val (sourceId, sourceHeight) = txOpt match { - case Some(c: LeaseCancelTransaction) => (c.leaseId, height(c.leaseId)) - case Some(i) if isActive => (i.id(), blockchain.height) // produced by lease or invoke (including eth) - case Some(i) if !isActive && innerDetails.isEmpty => (i.id(), blockchain.height) // produced and cancelled by the same invoke - case _ => - def id = innerDetails.get.sourceId // cancelled by invoke and produced by other transaction from the state - Try((id, height(id))).getOrElse((ByteStr.empty, 0)) - } - LeaseDetails(sender, recipient, amount, status, sourceId, sourceHeight) - } -} - -object LeaseSnapshot { - def fromDetails(details: LeaseDetails): LeaseSnapshot = - LeaseSnapshot(details.sender, details.recipient, details.amount, details.status) -} diff --git a/node/src/main/scala/com/wavesplatform/state/NewTransactionInfo.scala b/node/src/main/scala/com/wavesplatform/state/NewTransactionInfo.scala index fb8668ecab5..9945f45b9e9 100644 --- a/node/src/main/scala/com/wavesplatform/state/NewTransactionInfo.scala +++ b/node/src/main/scala/com/wavesplatform/state/NewTransactionInfo.scala @@ -68,10 +68,7 @@ object NewTransactionInfo { case t: LeaseCancelTransaction => Set(t.sender.toAddress) ++ blockchain .leaseDetails(t.leaseId) - .flatMap(_.recipient match { - case alias: Alias => blockchain.resolveAlias(alias).toOption - case address: Address => Some(address) - }) + .map(_.recipientAddress) .toSet case t: LeaseTransaction => Set(t.sender.toAddress) ++ (t.recipient match { @@ -79,12 +76,12 @@ object NewTransactionInfo { case address: Address => Set(address) }) case t: MassTransferTransaction => - Set(t.sender.toAddress) ++ (t.transfers.flatMap { + Set(t.sender.toAddress) ++ t.transfers.flatMap { _.address match { case alias: Alias => blockchain.resolveAlias(alias).toOption.toSet case address: Address => Set(address) } - }) + } case t: ReissueTransaction => Set(t.sender.toAddress) case t: SetAssetScriptTransaction => Set(t.sender.toAddress) case t: SetScriptTransaction => Set(t.sender.toAddress) diff --git a/node/src/main/scala/com/wavesplatform/state/StateSnapshot.scala b/node/src/main/scala/com/wavesplatform/state/StateSnapshot.scala index 7cb0a8ab492..46aaba292b2 100644 --- a/node/src/main/scala/com/wavesplatform/state/StateSnapshot.scala +++ b/node/src/main/scala/com/wavesplatform/state/StateSnapshot.scala @@ -1,13 +1,13 @@ package com.wavesplatform.state + import cats.data.Ior import cats.implicits.{catsSyntaxEitherId, catsSyntaxSemigroup, toBifunctorOps, toTraverseOps} import cats.kernel.Monoid import com.wavesplatform.account.{Address, Alias, PublicKey} import com.wavesplatform.common.state.ByteStr -import com.wavesplatform.common.utils.EitherExt2 import com.wavesplatform.database.protobuf.EthereumTransactionMeta import com.wavesplatform.lang.ValidationError -import com.wavesplatform.state.reader.SnapshotBlockchain +import com.wavesplatform.state.reader.{LeaseDetails, SnapshotBlockchain} import com.wavesplatform.transaction.Asset.{IssuedAsset, Waves} import com.wavesplatform.transaction.TxValidationError.GenericError import com.wavesplatform.transaction.{Asset, Transaction} @@ -23,7 +23,7 @@ case class StateSnapshot( assetNamesAndDescriptions: Map[IssuedAsset, AssetInfo] = Map(), assetScripts: Map[IssuedAsset, AssetScriptInfo] = Map(), sponsorships: Map[IssuedAsset, SponsorshipValue] = Map(), - leaseStates: Map[ByteStr, LeaseSnapshot] = Map(), + leaseStates: Map[ByteStr, LeaseDetails] = Map(), aliases: Map[Alias, Address] = Map(), orderFills: Map[ByteStr, VolumeAndFee] = Map(), accountScripts: Map[PublicKey, Option[AccountScriptInfo]] = Map(), @@ -79,7 +79,7 @@ object StateSnapshot { updatedAssets: Map[IssuedAsset, Ior[AssetInfo, AssetVolumeInfo]] = Map(), assetScripts: Map[IssuedAsset, AssetScriptInfo] = Map(), sponsorships: Map[IssuedAsset, Sponsorship] = Map(), - leaseStates: Map[ByteStr, LeaseSnapshot] = Map(), + leaseStates: Map[ByteStr, LeaseDetails] = Map(), aliases: Map[Alias, Address] = Map(), accountData: Map[Address, Map[String, DataEntry[?]]] = Map(), accountScripts: Map[PublicKey, Option[AccountScriptInfo]] = Map(), @@ -102,7 +102,7 @@ object StateSnapshot { assetNamesAndDescriptions(issuedAssets, updatedAssets), assetScripts, sponsorships.collect { case (asset, value: SponsorshipValue) => (asset, value) }, - resolvedLeaseStates(blockchain, leaseStates, aliases), + leaseStates, aliases, of, accountScripts, @@ -197,20 +197,6 @@ object StateSnapshot { issued ++ updated } - private def resolvedLeaseStates( - blockchain: Blockchain, - leaseStates: Map[ByteStr, LeaseSnapshot], - aliases: Map[Alias, Address] - ): Map[ByteStr, LeaseSnapshot] = - leaseStates.view - .mapValues(details => - details.copy(recipient = details.recipient match { - case address: Address => address - case alias: Alias => aliases.getOrElse(alias, blockchain.resolveAlias(alias).explicitGet()) - }) - ) - .toMap - private def orderFills(volumeAndFees: Map[ByteStr, VolumeAndFee], blockchain: Blockchain): Either[String, Map[ByteStr, VolumeAndFee]] = volumeAndFees.toSeq .traverse { case (orderId, value) => diff --git a/node/src/main/scala/com/wavesplatform/state/TxStateSnapshotHashBuilder.scala b/node/src/main/scala/com/wavesplatform/state/TxStateSnapshotHashBuilder.scala index 5c3d9caf5ed..de6a81a4d45 100644 --- a/node/src/main/scala/com/wavesplatform/state/TxStateSnapshotHashBuilder.scala +++ b/node/src/main/scala/com/wavesplatform/state/TxStateSnapshotHashBuilder.scala @@ -69,7 +69,7 @@ object TxStateSnapshotHashBuilder { snapshot.leaseStates.foreach { case (leaseId, details) => changedKeys += leaseId.arr ++ booleanToBytes(details.isActive) if (details.isActive) { - changedKeys += leaseId.arr ++ details.sender.arr ++ details.recipient.bytes ++ Longs.toByteArray(details.amount) + changedKeys += leaseId.arr ++ details.sender.arr ++ details.recipientAddress.bytes ++ Longs.toByteArray(details.amount.value) } } diff --git a/node/src/main/scala/com/wavesplatform/state/diffs/DiffsCommon.scala b/node/src/main/scala/com/wavesplatform/state/diffs/DiffsCommon.scala index 5c83e03e367..08e9810871e 100644 --- a/node/src/main/scala/com/wavesplatform/state/diffs/DiffsCommon.scala +++ b/node/src/main/scala/com/wavesplatform/state/diffs/DiffsCommon.scala @@ -16,8 +16,9 @@ import com.wavesplatform.lang.v1.estimator.v2.ScriptEstimatorV2 import com.wavesplatform.lang.v1.estimator.{ScriptEstimator, ScriptEstimatorV1} import com.wavesplatform.lang.v1.traits.domain.* import com.wavesplatform.state.reader.LeaseDetails -import com.wavesplatform.state.{AssetVolumeInfo, Blockchain, LeaseBalance, LeaseSnapshot, Portfolio, SponsorshipValue, StateSnapshot} +import com.wavesplatform.state.{AssetVolumeInfo, Blockchain, LeaseBalance, Portfolio, SponsorshipValue, StateSnapshot} import com.wavesplatform.transaction.Asset.{IssuedAsset, Waves} +import com.wavesplatform.transaction.TxPositiveAmount import com.wavesplatform.transaction.TxValidationError.GenericError object DiffsCommon { @@ -134,7 +135,7 @@ object DiffsCommon { def processLease( blockchain: Blockchain, - amount: Long, + amount: TxPositiveAmount, sender: PublicKey, recipient: AddressOrAlias, fee: Long, @@ -156,17 +157,17 @@ object DiffsCommon { ) leaseBalance = blockchain.leaseBalance(senderAddress) senderBalance = blockchain.balance(senderAddress, Waves) - requiredBalance = if (blockchain.isFeatureActivated(BlockchainFeatures.SynchronousCalls)) amount + fee else amount + requiredBalance = if (blockchain.isFeatureActivated(BlockchainFeatures.SynchronousCalls)) amount.value + fee else amount.value _ <- Either.cond( senderBalance - leaseBalance.out >= requiredBalance, (), GenericError(s"Cannot lease more than own: Balance: $senderBalance, already leased: ${leaseBalance.out}") ) portfolioDiff = Map( - senderAddress -> Portfolio(-fee, LeaseBalance(0, amount)), - recipientAddress -> Portfolio(0, LeaseBalance(amount, 0)) + senderAddress -> Portfolio(-fee, LeaseBalance(0, amount.value)), + recipientAddress -> Portfolio(0, LeaseBalance(amount.value, 0)) ) - details = LeaseSnapshot(sender, recipient, amount, LeaseDetails.Status.Active) + details = LeaseDetails(sender, recipientAddress, amount, LeaseDetails.Status.Active, txId, blockchain.height) snapshot <- StateSnapshot.build( blockchain, portfolios = portfolioDiff, @@ -186,7 +187,7 @@ object DiffsCommon { val allowedTs = blockchain.settings.functionalitySettings.allowMultipleLeaseCancelTransactionUntilTimestamp for { lease <- blockchain.leaseDetails(leaseId).toRight(GenericError(s"Lease with id=$leaseId not found")) - recipient <- blockchain.resolveAlias(lease.recipient) + recipient <- blockchain.resolveAlias(lease.recipientAddress) _ <- Either.cond( lease.isActive || time <= allowedTs, (), @@ -200,14 +201,14 @@ object DiffsCommon { s"time=$time > allowMultipleLeaseCancelTransactionUntilTimestamp=$allowedTs" ) ) - senderPortfolio = Map[Address, Portfolio](sender.toAddress -> Portfolio(-fee, LeaseBalance(0, -lease.amount))) - recipientPortfolio = Map(recipient -> Portfolio(0, LeaseBalance(-lease.amount, 0))) + senderPortfolio = Map[Address, Portfolio](sender.toAddress -> Portfolio(-fee, LeaseBalance(0, -lease.amount.value))) + recipientPortfolio = Map(recipient -> Portfolio(0, LeaseBalance(-lease.amount.value, 0))) actionInfo = lease.copy(status = LeaseDetails.Status.Cancelled(blockchain.height, Some(cancelTxId))) portfolios <- Portfolio.combine(senderPortfolio, recipientPortfolio).leftMap(GenericError(_)) snapshot <- StateSnapshot.build( blockchain, portfolios = portfolios, - leaseStates = Map(leaseId -> LeaseSnapshot.fromDetails(actionInfo)) + leaseStates = Map(leaseId -> actionInfo) ) } yield snapshot } diff --git a/node/src/main/scala/com/wavesplatform/state/diffs/LeaseTransactionsDiff.scala b/node/src/main/scala/com/wavesplatform/state/diffs/LeaseTransactionsDiff.scala index cedecbd0a51..f6ad69f6faa 100644 --- a/node/src/main/scala/com/wavesplatform/state/diffs/LeaseTransactionsDiff.scala +++ b/node/src/main/scala/com/wavesplatform/state/diffs/LeaseTransactionsDiff.scala @@ -7,7 +7,7 @@ import com.wavesplatform.transaction.lease.* object LeaseTransactionsDiff { def lease(blockchain: Blockchain)(tx: LeaseTransaction): Either[ValidationError, StateSnapshot] = DiffsCommon - .processLease(blockchain, tx.amount.value, tx.sender, tx.recipient, tx.fee.value, tx.id(), tx.id()) + .processLease(blockchain, tx.amount, tx.sender, tx.recipient, tx.fee.value, tx.id(), tx.id()) def leaseCancel(blockchain: Blockchain, time: Long)(tx: LeaseCancelTransaction): Either[ValidationError, StateSnapshot] = DiffsCommon diff --git a/node/src/main/scala/com/wavesplatform/state/diffs/invoke/InvokeDiffsCommon.scala b/node/src/main/scala/com/wavesplatform/state/diffs/invoke/InvokeDiffsCommon.scala index e154bb12c44..b7be52f79af 100644 --- a/node/src/main/scala/com/wavesplatform/state/diffs/invoke/InvokeDiffsCommon.scala +++ b/node/src/main/scala/com/wavesplatform/state/diffs/invoke/InvokeDiffsCommon.scala @@ -464,8 +464,8 @@ object InvokeDiffsCommon { if (remainingLimit < Int.MaxValue) remainingLimit - currentSnapshot.scriptsComplexity.toInt else remainingLimit - val blockchain = SnapshotBlockchain(sblockchain, currentSnapshot) - val actionSender = Recipient.Address(ByteStr(dAppAddress.bytes)) + val blockchain = SnapshotBlockchain(sblockchain, currentSnapshot) + val actionSender = Recipient.Address(ByteStr(dAppAddress.bytes)) def applyTransfer(transfer: AssetTransfer, pk: PublicKey): TracedResult[ValidationError, StateSnapshot] = { val AssetTransfer(addressRepr, recipient, amount, asset) = transfer @@ -628,10 +628,10 @@ object InvokeDiffsCommon { def applyLease(l: Lease): TracedResult[ValidationError, StateSnapshot] = for { - _ <- TracedResult(LeaseTxValidator.validateAmount(l.amount)) - recipient <- TracedResult(AddressOrAlias.fromRide(l.recipient)) + validAmount <- TracedResult(LeaseTxValidator.validateAmount(l.amount)) + recipient <- TracedResult(AddressOrAlias.fromRide(l.recipient)) leaseId = Lease.calculateId(l, tx.txId) - diff <- DiffsCommon.processLease(blockchain, l.amount, pk, recipient, fee = 0, leaseId, tx.txId) + diff <- DiffsCommon.processLease(blockchain, validAmount, pk, recipient, fee = 0, leaseId, tx.txId) } yield diff def applyLeaseCancel(l: LeaseCancel): TracedResult[ValidationError, StateSnapshot] = diff --git a/node/src/main/scala/com/wavesplatform/state/patch/CancelAllLeases.scala b/node/src/main/scala/com/wavesplatform/state/patch/CancelAllLeases.scala index 15c83699c37..a0bd2bbfd9b 100644 --- a/node/src/main/scala/com/wavesplatform/state/patch/CancelAllLeases.scala +++ b/node/src/main/scala/com/wavesplatform/state/patch/CancelAllLeases.scala @@ -5,7 +5,8 @@ import com.wavesplatform.account.{Address, PublicKey} import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.* import com.wavesplatform.state.reader.LeaseDetails -import com.wavesplatform.state.{Blockchain, LeaseBalance, LeaseSnapshot, StateSnapshot} +import com.wavesplatform.state.{Blockchain, LeaseBalance, StateSnapshot} +import com.wavesplatform.transaction.TxPositiveAmount import play.api.libs.json.{Json, OFormat} case object CancelAllLeases extends PatchAtHeight('W' -> 462000, 'T' -> 51500) { @@ -13,11 +14,11 @@ case object CancelAllLeases extends PatchAtHeight('W' -> 462000, 'T' -> 51500) { private[patch] case class CancelledLeases(balances: Map[Address, LeaseBalance], cancelledLeases: Seq[LeaseData]) { private[this] val height: Int = patchHeight.getOrElse(0) - val leaseStates: Map[ByteStr, LeaseSnapshot] = cancelledLeases.map { data => + val leaseStates: Map[ByteStr, LeaseDetails] = cancelledLeases.map { data => val sender = PublicKey(ByteStr.decodeBase58(data.senderPublicKey).get) val recipient = Address.fromString(data.recipient).explicitGet() val id = ByteStr.decodeBase58(data.id).get - (id, LeaseSnapshot(sender, recipient, data.amount, status = LeaseDetails.Status.Expired(height))) + (id, LeaseDetails(sender, recipient, TxPositiveAmount.unsafeFrom(data.amount), status = LeaseDetails.Status.Expired(height), id, height)) }.toMap } diff --git a/node/src/main/scala/com/wavesplatform/state/patch/CancelLeasesToDisabledAliases.scala b/node/src/main/scala/com/wavesplatform/state/patch/CancelLeasesToDisabledAliases.scala index e1e343e4bf7..df704603b8a 100644 --- a/node/src/main/scala/com/wavesplatform/state/patch/CancelLeasesToDisabledAliases.scala +++ b/node/src/main/scala/com/wavesplatform/state/patch/CancelLeasesToDisabledAliases.scala @@ -1,12 +1,13 @@ package com.wavesplatform.state.patch import cats.implicits.{catsSyntaxAlternativeSeparate, catsSyntaxSemigroup, toFoldableOps} -import com.wavesplatform.account.{Address, Alias, PublicKey} +import com.wavesplatform.account.{Address, PublicKey} import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.{Base58, EitherExt2} import com.wavesplatform.features.BlockchainFeatures import com.wavesplatform.state.reader.LeaseDetails -import com.wavesplatform.state.{Blockchain, LeaseBalance, LeaseSnapshot, Portfolio, StateSnapshot} +import com.wavesplatform.state.{Blockchain, LeaseBalance, Portfolio, StateSnapshot} +import com.wavesplatform.transaction.TxPositiveAmount import play.api.libs.json.{Json, Reads} case object CancelLeasesToDisabledAliases extends PatchOnFeature(BlockchainFeatures.SynchronousCalls, Set('W')) { @@ -19,19 +20,20 @@ case object CancelLeasesToDisabledAliases extends PatchOnFeature(BlockchainFeatu height: Int ) - def patchData: Map[ByteStr, (LeaseSnapshot, Address)] = { + def patchData: Map[ByteStr, (LeaseDetails, Address)] = { implicit val cancelDetailsReads: Reads[CancelDetails] = Json.reads readPatchData[Seq[CancelDetails]]().map { cancelDetails => val leaseId = ByteStr(Base58.decode(cancelDetails.id)) val sender = PublicKey(Base58.decode(cancelDetails.senderPublicKey)) - val recipientAlias = Alias.fromString(cancelDetails.recipientAlias).explicitGet() val recipientAddress = Address.fromString(cancelDetails.recipientAddress).explicitGet() - leaseId -> (LeaseSnapshot( + leaseId -> (LeaseDetails( sender, - recipientAlias, - cancelDetails.amount, - LeaseDetails.Status.Expired(0) + recipientAddress, + TxPositiveAmount.unsafeFrom(cancelDetails.amount), + LeaseDetails.Status.Expired(0), + leaseId, + cancelDetails.height ) -> recipientAddress) }.toMap } @@ -42,8 +44,8 @@ case object CancelLeasesToDisabledAliases extends PatchOnFeature(BlockchainFeatu ( Portfolio .combine( - Map(ld.sender.toAddress -> Portfolio(lease = LeaseBalance(0, -ld.amount))), - Map(recipientAddress -> Portfolio(lease = LeaseBalance(-ld.amount, 0))) + Map(ld.sender.toAddress -> Portfolio(lease = LeaseBalance(0, -ld.amount.value))), + Map(recipientAddress -> Portfolio(lease = LeaseBalance(-ld.amount.value, 0))) ) .explicitGet(), StateSnapshot( diff --git a/node/src/main/scala/com/wavesplatform/state/reader/LeaseDetails.scala b/node/src/main/scala/com/wavesplatform/state/reader/LeaseDetails.scala index 66cd1ea363e..b693f69e631 100644 --- a/node/src/main/scala/com/wavesplatform/state/reader/LeaseDetails.scala +++ b/node/src/main/scala/com/wavesplatform/state/reader/LeaseDetails.scala @@ -1,7 +1,8 @@ package com.wavesplatform.state.reader -import com.wavesplatform.account.{AddressOrAlias, PublicKey} +import com.wavesplatform.account.{Address, PublicKey} import com.wavesplatform.common.state.ByteStr +import com.wavesplatform.transaction.TxPositiveAmount object LeaseDetails { sealed trait Status @@ -26,6 +27,6 @@ object LeaseDetails { } } -case class LeaseDetails(sender: PublicKey, recipient: AddressOrAlias, amount: Long, status: LeaseDetails.Status, sourceId: ByteStr, height: Int) { +case class LeaseDetails(sender: PublicKey, recipientAddress: Address, amount: TxPositiveAmount, status: LeaseDetails.Status, sourceId: ByteStr, height: Int) { def isActive: Boolean = status == LeaseDetails.Status.Active } diff --git a/node/src/main/scala/com/wavesplatform/state/reader/SnapshotBlockchain.scala b/node/src/main/scala/com/wavesplatform/state/reader/SnapshotBlockchain.scala index c757ff5140d..f131329b5c1 100644 --- a/node/src/main/scala/com/wavesplatform/state/reader/SnapshotBlockchain.scala +++ b/node/src/main/scala/com/wavesplatform/state/reader/SnapshotBlockchain.scala @@ -83,18 +83,10 @@ case class SnapshotBlockchain( override def assetDescription(asset: IssuedAsset): Option[AssetDescription] = SnapshotBlockchain.assetDescription(asset, snapshot, height, inner) - override def leaseDetails(leaseId: ByteStr): Option[LeaseDetails] = { - lazy val innerDetails = inner.leaseDetails(leaseId) - val txOpt = - snapshot.transactions - .collectFirst { - case (_, txInfo) if txInfo.snapshot.leaseStates.contains(leaseId) => txInfo.transaction - } + override def leaseDetails(leaseId: ByteStr): Option[LeaseDetails] = snapshot.leaseStates .get(leaseId) - .map(_.toDetails(this, txOpt, innerDetails)) - .orElse(innerDetails) - } + .orElse(inner.leaseDetails(leaseId)) override def transferById(id: ByteStr): Option[(Int, TransferTransactionLike)] = snapshot.transactions diff --git a/node/src/main/scala/com/wavesplatform/transaction/validation/impl/LeaseTxValidator.scala b/node/src/main/scala/com/wavesplatform/transaction/validation/impl/LeaseTxValidator.scala index 7c21869f2a3..c1f5548f4f8 100644 --- a/node/src/main/scala/com/wavesplatform/transaction/validation/impl/LeaseTxValidator.scala +++ b/node/src/main/scala/com/wavesplatform/transaction/validation/impl/LeaseTxValidator.scala @@ -4,11 +4,11 @@ import cats.data.ValidatedNel import com.wavesplatform.lang.ValidationError import com.wavesplatform.transaction.lease.LeaseTransaction import com.wavesplatform.transaction.validation.TxValidator -import com.wavesplatform.transaction.TxValidationError +import com.wavesplatform.transaction.{TxPositiveAmount, TxValidationError} object LeaseTxValidator extends TxValidator[LeaseTransaction] { override def validate(tx: LeaseTransaction): ValidatedNel[ValidationError, LeaseTransaction] = { - import tx._ + import tx.* V.seq(tx)( V.noOverflow(amount.value, fee.value), V.cond(sender.toAddress != recipient, TxValidationError.ToSelf), @@ -16,6 +16,6 @@ object LeaseTxValidator extends TxValidator[LeaseTransaction] { ) } - def validateAmount(amount: Long) = - Either.cond(amount > 0, (), TxValidationError.NonPositiveAmount(amount, "waves")) + def validateAmount(amount: Long): Either[ValidationError, TxPositiveAmount] = + TxPositiveAmount.from(amount).left.map[ValidationError](_ => TxValidationError.NonPositiveAmount(amount, "waves")) } diff --git a/node/src/test/scala/com/wavesplatform/api/http/CustomJsonMarshallerSpec.scala b/node/src/test/scala/com/wavesplatform/api/http/CustomJsonMarshallerSpec.scala index 9f1a6b67ed2..a8a48c170f8 100644 --- a/node/src/test/scala/com/wavesplatform/api/http/CustomJsonMarshallerSpec.scala +++ b/node/src/test/scala/com/wavesplatform/api/http/CustomJsonMarshallerSpec.scala @@ -5,24 +5,14 @@ import akka.http.scaladsl.model.MediaTypes.`application/json` import akka.http.scaladsl.model.headers.Accept import akka.http.scaladsl.server.Route import akka.http.scaladsl.testkit.ScalatestRouteTest -import com.wavesplatform.api.common.{CommonAccountsApi, CommonAssetsApi, CommonTransactionsApi, TransactionMeta} import com.wavesplatform.api.http.assets.AssetsApiRoute -import com.wavesplatform.common.state.ByteStr -import com.wavesplatform.features.BlockchainFeatures -import com.wavesplatform.history.DefaultBlockchainSettings -import com.wavesplatform.http.{ApiErrorMatchers, RestAPISettingsHelper} -import com.wavesplatform.network.TransactionPublisher -import com.wavesplatform.state.TxMeta.Status -import com.wavesplatform.state.reader.{LeaseDetails, SnapshotBlockchain} -import com.wavesplatform.state.{Blockchain, Height} -import com.wavesplatform.test.PropSpec -import com.wavesplatform.transaction.Asset -import com.wavesplatform.transaction.Asset.IssuedAsset +import com.wavesplatform.db.WithState.AddrWithBalance +import com.wavesplatform.http.{ApiErrorMatchers, DummyTransactionPublisher, RestAPISettingsHelper} +import com.wavesplatform.settings.WavesSettings +import com.wavesplatform.test.* +import com.wavesplatform.transaction.TxHelpers import com.wavesplatform.utils.SharedSchedulerMixin -import com.wavesplatform.utx.UtxPool -import com.wavesplatform.{NTPTime, TestWallet} import org.scalactic.source.Position -import org.scalamock.scalatest.PathMockFactory import play.api.libs.json.* import scala.concurrent.duration.DurationInt @@ -31,24 +21,17 @@ import scala.reflect.ClassTag class CustomJsonMarshallerSpec extends PropSpec with RestAPISettingsHelper - with PathMockFactory - with TestWallet - with NTPTime with ScalatestRouteTest with ApiErrorMatchers with ApiMarshallers - with SharedSchedulerMixin { - private val blockchain = mock[Blockchain] - private val utx = mock[UtxPool] - private val publisher = mock[TransactionPublisher] - private val transactionsApi = mock[CommonTransactionsApi] - private val accountsApi = mock[CommonAccountsApi] - private val assetsApi = mock[CommonAssetsApi] + with SharedDomain + with SharedSchedulerMixin { private val numberFormat = Accept(`application/json`.withParams(Map("large-significand-format" -> "string"))) + private val richAccount = TxHelpers.signer(55) - (() => blockchain.activatedFeatures).expects().returning(BlockchainFeatures.implemented.map(_ -> 0).toMap).anyNumberOfTimes() - (() => blockchain.settings).expects().returning(DefaultBlockchainSettings).anyNumberOfTimes() + override def genesisBalances: Seq[AddrWithBalance] = Seq(AddrWithBalance(richAccount.toAddress, 50000.waves)) + override def settings: WavesSettings = DomainPresets.BlockRewardDistribution private def ensureFieldsAre[A: ClassTag](v: JsObject, fields: String*)(implicit pos: Position): Unit = for (f <- fields) (v \ f).get shouldBe a[A] @@ -66,47 +49,32 @@ class CustomJsonMarshallerSpec private val transactionsRoute = TransactionsApiRoute( restAPISettings, - transactionsApi, - testWallet, - blockchain, - mock[() => SnapshotBlockchain], - () => utx.size, - publisher, + domain.transactionsApi, + domain.wallet, + domain.blockchain, + () => domain.blockchain, + () => domain.utxPool.size, + DummyTransactionPublisher.accepting, ntpTime, new RouteTimeout(60.seconds)(sharedScheduler) ).route property("/transactions/info/{id}") { - forAll(leaseGen) { lt => - val height: Height = Height(1) - (transactionsApi.transactionById _).expects(lt.id()).returning(Some(TransactionMeta.Default(height, lt, Status.Succeeded, 0L))).twice() - (blockchain.leaseDetails _) - .expects(lt.id()) - .returning(Some(LeaseDetails(lt.sender, lt.recipient, lt.amount.value, LeaseDetails.Status.Active, lt.id(), 1))) - .twice() - checkRoute(Get(s"/transactions/info/${lt.id()}"), transactionsRoute, "amount") - } + // todo: add other transaction types + val leaseTx = TxHelpers.lease(sender = richAccount, TxHelpers.address(80), 25.waves) + domain.appendBlock(leaseTx) + checkRoute(Get(s"/transactions/info/${leaseTx.id()}"), transactionsRoute, "amount") } property("/transactions/calculateFee") { - (() => blockchain.height).expects().returning(1000).anyNumberOfTimes() - (blockchain.assetScript _).expects(*).returning(None).anyNumberOfTimes() - - forAll(transferV2Gen) { tx => - (transactionsApi.calculateFee _).expects(*).returning(Right((Asset.Waves, 1, 1))).twice() - checkRoute(Post("/transactions/calculateFee", tx.json()), transactionsRoute, "feeAmount") - } + val tx = TxHelpers.transfer(richAccount, TxHelpers.address(81), 5.waves) + checkRoute(Post("/transactions/calculateFee", tx.json()), transactionsRoute, "feeAmount") } - private val rewardRoute = RewardApiRoute(blockchain).route + private val rewardRoute = RewardApiRoute(domain.blockchain).route property("/blockchain/rewards") { - (() => blockchain.height).expects().returning(1000).anyNumberOfTimes() - (blockchain.blockReward _).expects(*).returning(Some(1000)).twice() - (blockchain.wavesAmount _).expects(*).returning(BigInt(10000000)).twice() - (blockchain.blockRewardVotes _).expects(1000).returning(Seq(100L)).twice() - - checkRoute(Get("/blockchain/rewards/1000"), rewardRoute, "totalWavesAmount", "currentReward", "minIncrement") + checkRoute(Get("/blockchain/rewards/2"), rewardRoute, "totalWavesAmount", "currentReward", "minIncrement") } property("/debug/stateWaves") { @@ -116,13 +84,12 @@ class CustomJsonMarshallerSpec private val assetsRoute = AssetsApiRoute( restAPISettings, 60.seconds, - testWallet, - publisher, - blockchain, - mock[() => SnapshotBlockchain], + domain.wallet, + domain.blockchain, + () => domain.blockchain, ntpTime, - accountsApi, - assetsApi, + domain.accountsApi, + domain.assetsApi, 1000, new RouteTimeout(60.seconds)(sharedScheduler) ).route @@ -132,9 +99,8 @@ class CustomJsonMarshallerSpec } property("/assets/balance/{address}/{assetId}") { - forAll(accountGen, bytes32gen.map(b => IssuedAsset(ByteStr(b)))) { case (keyPair, assetId) => - (blockchain.balance _).expects(keyPair.toAddress, assetId).returning(1000L).twice() - checkRoute(Get(s"/assets/balance/${keyPair.publicKey.toAddress}/${assetId.id}"), assetsRoute, "balance") - } + val issue = TxHelpers.issue(richAccount, 100000_00, 2.toByte) + domain.appendBlock(issue) + checkRoute(Get(s"/assets/balance/${richAccount.toAddress}/${issue.id()}"), assetsRoute, "balance") } } diff --git a/node/src/test/scala/com/wavesplatform/consensus/FPPoSSelectorTest.scala b/node/src/test/scala/com/wavesplatform/consensus/FPPoSSelectorTest.scala index 3b536e78fa6..0a4d082422c 100644 --- a/node/src/test/scala/com/wavesplatform/consensus/FPPoSSelectorTest.scala +++ b/node/src/test/scala/com/wavesplatform/consensus/FPPoSSelectorTest.scala @@ -282,7 +282,7 @@ class FPPoSSelectorTest extends FreeSpec with WithNewDBForEachTest with DBCacheS val settings0 = WavesSettings.fromRootConfig(loadConfig(ConfigFactory.load())) val settings = settings0.copy(featuresSettings = settings0.featuresSettings.copy(autoShutdownOnUnsupportedFeature = false)) val bcu = - new BlockchainUpdaterImpl(defaultWriter, settings, ntpTime, ignoreBlockchainUpdateTriggers, (_, _) => Seq.empty) + new BlockchainUpdaterImpl(defaultWriter, settings, ntpTime, ignoreBlockchainUpdateTriggers, (_, _) => Map.empty) val pos = PoSSelector(bcu, settings.synchronizationSettings.maxBaseTarget) try { val (accounts, blocks) = gen(ntpTime).sample.get diff --git a/node/src/test/scala/com/wavesplatform/db/ScriptCacheTest.scala b/node/src/test/scala/com/wavesplatform/db/ScriptCacheTest.scala index f37a7bfa9a7..e1d08d1d7ab 100644 --- a/node/src/test/scala/com/wavesplatform/db/ScriptCacheTest.scala +++ b/node/src/test/scala/com/wavesplatform/db/ScriptCacheTest.scala @@ -138,7 +138,7 @@ class ScriptCacheTest extends FreeSpec with WithNewDBForEachTest { TestFunctionalitySettings.Stub ) val bcu = - new BlockchainUpdaterImpl(defaultWriter, settings, ntpTime, ignoreBlockchainUpdateTriggers, (_, _) => Seq.empty) + new BlockchainUpdaterImpl(defaultWriter, settings, ntpTime, ignoreBlockchainUpdateTriggers, (_, _) => Map.empty) try { val (accounts, blocks) = gen(ntpTime).sample.get diff --git a/node/src/test/scala/com/wavesplatform/history/SnapshotOps.scala b/node/src/test/scala/com/wavesplatform/history/SnapshotOps.scala index aed67685d60..bff0bb1dc61 100644 --- a/node/src/test/scala/com/wavesplatform/history/SnapshotOps.scala +++ b/node/src/test/scala/com/wavesplatform/history/SnapshotOps.scala @@ -21,7 +21,7 @@ object SnapshotOps { updatedAssets, s.aliases, orderFills(blockchain), - s.leaseStates.map(l => (l._1, LeaseDetails(l._2.sender, l._2.recipient, l._2.amount, l._2.status, ByteStr.empty, 0))), + s.leaseStates.map(l => (l._1, LeaseDetails(l._2.sender, l._2.recipientAddress, l._2.amount, l._2.status, ByteStr.empty, 0))), s.accountScripts, s.assetScripts.view.mapValues(Some(_)).toMap, s.accountData, @@ -96,7 +96,7 @@ object SnapshotOps { diff.updatedAssets, diff.assetScripts.collect { case (asset, Some(info)) => (asset, info) }, diff.sponsorship, - diff.leaseState.map(l => (l._1, LeaseSnapshot(l._2.sender, l._2.recipient, l._2.amount, l._2.status))), + diff.leaseState.map(l => (l._1, ???)), diff.aliases, diff.accountData, diff.scripts, diff --git a/node/src/test/scala/com/wavesplatform/http/AssetsRouteSpec.scala b/node/src/test/scala/com/wavesplatform/http/AssetsRouteSpec.scala index 6484726d1e4..24fc7c4e5c2 100644 --- a/node/src/test/scala/com/wavesplatform/http/AssetsRouteSpec.scala +++ b/node/src/test/scala/com/wavesplatform/http/AssetsRouteSpec.scala @@ -25,11 +25,11 @@ import com.wavesplatform.state.{AssetDescription, AssetScriptInfo, BinaryDataEnt import com.wavesplatform.test.* import com.wavesplatform.test.DomainPresets.* import com.wavesplatform.transaction.Asset.IssuedAsset +import com.wavesplatform.transaction.EthTxGenerator.Arg import com.wavesplatform.transaction.TxHelpers.* import com.wavesplatform.transaction.assets.IssueTransaction import com.wavesplatform.transaction.smart.SetScriptTransaction import com.wavesplatform.transaction.transfer.MassTransferTransaction -import com.wavesplatform.transaction.EthTxGenerator.Arg import com.wavesplatform.transaction.{AssetIdLength, EthTxGenerator, GenesisTransaction, Transaction, TxHelpers, TxNonNegativeAmount, TxVersion} import com.wavesplatform.utils.SharedSchedulerMixin import org.scalatest.concurrent.Eventually @@ -59,7 +59,6 @@ class AssetsRouteSpec restAPISettings, 60.seconds, testWallet, - DummyTransactionPublisher.accepting, d.blockchain, () => d.blockchain.snapshotBlockchain, TestTime(), @@ -287,7 +286,7 @@ class AssetsRouteSpec checkDetails(route, issues(i), issues(i).id().toString, assetDesc.copy(sequenceInBlock = i)) } - d.appendBlock((7 to 10).map(issues): _*) + d.appendBlock((7 to 10).map(issues) *) (1 to 6).foreach { i => checkDetails(route, issues(i), issues(i).id().toString, assetDesc.copy(sequenceInBlock = i)) } diff --git a/node/src/test/scala/com/wavesplatform/http/DebugApiRouteSpec.scala b/node/src/test/scala/com/wavesplatform/http/DebugApiRouteSpec.scala index 29089460466..9ba3b469ed8 100644 --- a/node/src/test/scala/com/wavesplatform/http/DebugApiRouteSpec.scala +++ b/node/src/test/scala/com/wavesplatform/http/DebugApiRouteSpec.scala @@ -38,7 +38,7 @@ import com.wavesplatform.transaction.assets.exchange.OrderType import com.wavesplatform.transaction.smart.InvokeScriptTransaction import com.wavesplatform.transaction.smart.InvokeScriptTransaction.Payment import com.wavesplatform.transaction.smart.script.ScriptCompiler -import com.wavesplatform.transaction.{ERC20Address, Transaction, TxHelpers, TxVersion} +import com.wavesplatform.transaction.{ERC20Address, Transaction, TxHelpers, TxPositiveAmount, TxVersion} import com.wavesplatform.utils.SharedSchedulerMixin import com.wavesplatform.wallet.Wallet import monix.eval.Task @@ -1690,7 +1690,7 @@ class DebugApiRouteSpec (blockchain.leaseDetails _) .when(canceledLeaseId) - .returns(Some(LeaseDetails(dAppPk, TxHelpers.defaultAddress, leaseCancelAmount, LeaseDetails.Status.Active, invoke.id(), 1))) + .returns(Some(LeaseDetails(dAppPk, TxHelpers.defaultAddress, TxPositiveAmount.unsafeFrom(leaseCancelAmount), LeaseDetails.Status.Active, invoke.id(), 1))) .anyNumberOfTimes() (blockchain.leaseDetails _) diff --git a/node/src/test/scala/com/wavesplatform/http/LeaseRouteSpec.scala b/node/src/test/scala/com/wavesplatform/http/LeaseRouteSpec.scala index d58f5337c4d..82e5aca2e01 100644 --- a/node/src/test/scala/com/wavesplatform/http/LeaseRouteSpec.scala +++ b/node/src/test/scala/com/wavesplatform/http/LeaseRouteSpec.scala @@ -2,69 +2,55 @@ package com.wavesplatform.http import akka.http.scaladsl.model.{ContentTypes, FormData, HttpEntity} import akka.http.scaladsl.server.Route +import com.wavesplatform.NTPTime import com.wavesplatform.account.{Address, AddressOrAlias, KeyPair} -import com.wavesplatform.api.common.{CommonAccountsApi, LeaseInfo} +import com.wavesplatform.api.common.CommonAccountsApi import com.wavesplatform.api.http.RouteTimeout import com.wavesplatform.api.http.leasing.LeaseApiRoute import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.EitherExt2 -import com.wavesplatform.db.WithDomain import com.wavesplatform.db.WithState.AddrWithBalance import com.wavesplatform.history.Domain import com.wavesplatform.lang.directives.values.{V5, V6} import com.wavesplatform.lang.v1.FunctionHeader import com.wavesplatform.lang.v1.compiler.Terms.{CONST_BYTESTR, CONST_LONG, FUNCTION_CALL} import com.wavesplatform.lang.v1.compiler.TestCompiler -import com.wavesplatform.network.TransactionPublisher import com.wavesplatform.settings.WavesSettings import com.wavesplatform.state.TxMeta.Status import com.wavesplatform.state.diffs.ENOUGH_AMT import com.wavesplatform.state.reader.LeaseDetails -import com.wavesplatform.state.{BinaryDataEntry, Blockchain, Height, TxMeta} +import com.wavesplatform.state.{BinaryDataEntry, Blockchain} import com.wavesplatform.test.* import com.wavesplatform.test.DomainPresets.* +import com.wavesplatform.transaction.EthTxGenerator.Arg import com.wavesplatform.transaction.TxHelpers.{defaultSigner, secondSigner, signer} import com.wavesplatform.transaction.lease.{LeaseCancelTransaction, LeaseTransaction} import com.wavesplatform.transaction.smart.SetScriptTransaction import com.wavesplatform.transaction.smart.script.trace.TracedResult import com.wavesplatform.transaction.utils.EthConverters.* -import com.wavesplatform.transaction.EthTxGenerator.Arg import com.wavesplatform.transaction.utils.Signed -import com.wavesplatform.transaction.{Asset, Authorized, EthTxGenerator, Transaction, TxHelpers, TxVersion} -import com.wavesplatform.utils.{SharedSchedulerMixin, SystemTime} -import com.wavesplatform.wallet.Wallet -import com.wavesplatform.{NTPTime, TestWallet, TransactionGen} +import com.wavesplatform.transaction.{Asset, Authorized, EthTxGenerator, Transaction, TxHelpers, TxPositiveAmount, TxVersion} +import com.wavesplatform.utils.SharedSchedulerMixin import org.scalacheck.Gen -import org.scalamock.scalatest.PathMockFactory import play.api.libs.json.{JsArray, JsObject, Json} import scala.concurrent.Future import scala.concurrent.duration.* -class LeaseRouteSpec - extends RouteSpec("/leasing") - with TransactionGen - with RestAPISettingsHelper - with NTPTime - with WithDomain - with TestWallet - with PathMockFactory - with SharedSchedulerMixin { +class LeaseRouteSpec extends RouteSpec("/leasing") with RestAPISettingsHelper with NTPTime with SharedDomain with SharedSchedulerMixin { private def route(domain: Domain) = LeaseApiRoute( restAPISettings, - testWallet, + domain.wallet, domain.blockchain, (_, _) => Future.successful(TracedResult(Right(true))), ntpTime, CommonAccountsApi(() => domain.blockchainUpdater.snapshotBlockchain, domain.rdb, domain.blockchain), new RouteTimeout(60.seconds)(sharedScheduler) - ) + ).route private def withRoute(balances: Seq[AddrWithBalance], settings: WavesSettings = mostRecent)(f: (Domain, Route) => Unit): Unit = - withDomain(settings = settings, balances = balances) { d => - f(d, route(d).route) - } + f(domain, route(domain)) private def setScriptTransaction(sender: KeyPair) = SetScriptTransaction @@ -133,7 +119,8 @@ class LeaseRouteSpec } } - private def toDetails(lt: LeaseTransaction) = LeaseDetails(lt.sender, lt.recipient, lt.amount.value, LeaseDetails.Status.Active, lt.id(), 1) + private def toDetails(lt: LeaseTransaction, blockchain: Blockchain) = + LeaseDetails(lt.sender, blockchain.resolveAlias(lt.recipient).explicitGet(), lt.amount, LeaseDetails.Status.Active, lt.id(), 1) private def leaseGen(sender: KeyPair, maxAmount: Long, timestamp: Long): Gen[LeaseTransaction] = for { @@ -150,7 +137,7 @@ class LeaseRouteSpec "created and cancelled by Lease/LeaseCancel transactions" in forAll(leaseTx) { leaseTransaction => withRoute(Seq(AddrWithBalance(sender.toAddress))) { (d, r) => d.appendBlock(leaseTransaction) - val expectedDetails = Seq(leaseTransaction.id() -> toDetails(leaseTransaction)) + val expectedDetails = Seq(leaseTransaction.id() -> toDetails(leaseTransaction, d.blockchain)) d.liquidAndSolidAssert { () => checkActiveLeasesFor(leaseTransaction.sender.toAddress, r, expectedDetails) checkActiveLeasesFor(leaseTransaction.recipient, r, expectedDetails) @@ -168,7 +155,7 @@ class LeaseRouteSpec "created by LeaseTransaction and canceled by InvokeScriptTransaction" in forAll(leaseTx) { leaseTransaction => withRoute(Seq(AddrWithBalance(sender.toAddress))) { (d, r) => d.appendBlock(leaseTransaction) - val expectedDetails = Seq(leaseTransaction.id() -> toDetails(leaseTransaction)) + val expectedDetails = Seq(leaseTransaction.id() -> toDetails(leaseTransaction, d.blockchain)) d.liquidAndSolidAssert { () => checkActiveLeasesFor(leaseTransaction.sender.toAddress, r, expectedDetails) @@ -225,7 +212,8 @@ class LeaseRouteSpec i.value } .get - val expectedDetails = Seq(leaseId -> LeaseDetails(setScript.sender, recipient, 10_000.waves, LeaseDetails.Status.Active, invoke.id(), 1)) + val expectedDetails = + Seq(leaseId -> LeaseDetails(setScript.sender, recipient, TxPositiveAmount(10_000_00000000L), LeaseDetails.Status.Active, invoke.id(), 1)) d.liquidAndSolidAssert { () => checkActiveLeasesFor(sender.toAddress, r, expectedDetails) @@ -254,7 +242,8 @@ class LeaseRouteSpec i.value } .get - val expectedDetails = Seq(leaseId -> LeaseDetails(setScript.sender, recipient, 10_000.waves, LeaseDetails.Status.Active, invoke.id(), 1)) + val expectedDetails = + Seq(leaseId -> LeaseDetails(setScript.sender, recipient, TxPositiveAmount(10_000_00000000L), LeaseDetails.Status.Active, invoke.id(), 1)) d.liquidAndSolidAssert { () => checkActiveLeasesFor(sender.toAddress, r, expectedDetails) @@ -300,7 +289,8 @@ class LeaseRouteSpec i.value } .get - val expectedDetails = Seq(leaseId -> LeaseDetails(sender.publicKey, recipient, 10_000.waves, LeaseDetails.Status.Active, invoke.id(), 1)) + val expectedDetails = + Seq(leaseId -> LeaseDetails(sender.publicKey, recipient, TxPositiveAmount(10_000_00000000L), LeaseDetails.Status.Active, invoke.id(), 1)) d.liquidAndSolidAssert { () => checkActiveLeasesFor(sender.toAddress, r, expectedDetails) @@ -337,7 +327,8 @@ class LeaseRouteSpec i.value } .get - val expectedDetails = Seq(leaseId -> LeaseDetails(dApp.publicKey, recipient, 10_000.waves, LeaseDetails.Status.Active, invoke.id(), 1)) + val expectedDetails = + Seq(leaseId -> LeaseDetails(dApp.publicKey, recipient, TxPositiveAmount(10_000_00000000L), LeaseDetails.Status.Active, invoke.id(), 1)) d.liquidAndSolidAssert { () => checkActiveLeasesFor(dApp.toAddress, r, expectedDetails) @@ -418,7 +409,8 @@ class LeaseRouteSpec } .get - val expectedDetails = Seq(leaseId -> LeaseDetails(target.publicKey, recipient, 10_000.waves, LeaseDetails.Status.Active, ist.id(), 1)) + val expectedDetails = + Seq(leaseId -> LeaseDetails(target.publicKey, recipient, TxPositiveAmount(10_000_00000000L), LeaseDetails.Status.Active, ist.id(), 1)) d.liquidAndSolidAssert { () => checkActiveLeasesFor(target.toAddress, r, expectedDetails) @@ -486,7 +478,7 @@ class LeaseRouteSpec getLeaseId(dApp1.toAddress) -> LeaseDetails( dApp1.publicKey, leaseRecipient1.toAddress, - leaseAmount1, + TxPositiveAmount.unsafeFrom(leaseAmount1), LeaseDetails.Status.Active, invokeTx.id(), 3 @@ -496,7 +488,7 @@ class LeaseRouteSpec getLeaseId(dApp2.toAddress) -> LeaseDetails( dApp2.publicKey, leaseRecipient2.toAddress, - leaseAmount2, + TxPositiveAmount.unsafeFrom(leaseAmount2), LeaseDetails.Status.Active, invokeTx.id(), 3 @@ -515,42 +507,13 @@ class LeaseRouteSpec } routePath("/info") in { - val blockchain = stub[Blockchain] - val commonApi = stub[CommonAccountsApi] - - val route = LeaseApiRoute( - restAPISettings, - stub[Wallet], - blockchain, - stub[TransactionPublisher], - SystemTime, - commonApi, - new RouteTimeout(60.seconds)(sharedScheduler) - ).route val lease = TxHelpers.lease() val leaseCancel = TxHelpers.leaseCancel(lease.id()) - (blockchain.transactionInfo _).when(lease.id()).returning(Some(TxMeta(Height(1), Status.Succeeded, 0L) -> lease)) - (commonApi.leaseInfo _) - .when(lease.id()) - .returning( - Some( - LeaseInfo( - lease.id(), - lease.id(), - lease.sender.toAddress, - lease.recipient.asInstanceOf[Address], - lease.amount.value, - 1, - LeaseInfo.Status.Canceled, - Some(2), - Some(leaseCancel.id()) - ) - ) - ) - (commonApi.leaseInfo _).when(*).returning(None) + domain.appendBlock(lease) + domain.appendBlock(leaseCancel) - Get(routePath(s"/info/${lease.id()}")) ~> route ~> check { + Get(routePath(s"/info/${lease.id()}")) ~> route(domain) ~> check { val response = responseAs[JsObject] response should matchJson(s"""{ | "id" : "${lease.id()}", @@ -588,7 +551,7 @@ class LeaseRouteSpec | "cancelTransactionId" : "${leaseCancel.id()}" |}]""".stripMargin) - Get(routePath(s"/info?id=${lease.id()}&id=${lease.id()}")) ~> route ~> check { + Get(routePath(s"/info?id=${lease.id()}&id=${lease.id()}")) ~> route(domain) ~> check { val response = responseAs[JsArray] response should matchJson(leasesListJson) } @@ -596,7 +559,7 @@ class LeaseRouteSpec Post( routePath(s"/info"), HttpEntity(ContentTypes.`application/json`, Json.obj("ids" -> Seq(lease.id().toString, lease.id().toString)).toString()) - ) ~> route ~> check { + ) ~> route(domain) ~> check { val response = responseAs[JsArray] response should matchJson(leasesListJson) } @@ -607,7 +570,7 @@ class LeaseRouteSpec ContentTypes.`application/json`, Json.obj("ids" -> (0 to restAPISettings.transactionsByAddressLimit).map(_ => lease.id().toString)).toString() ) - ) ~> route ~> check { + ) ~> route(domain) ~> check { val response = responseAs[JsObject] response should matchJson("""{ | "error" : 10, @@ -618,12 +581,12 @@ class LeaseRouteSpec Post( routePath(s"/info"), FormData("id" -> lease.id().toString, "id" -> lease.id().toString) - ) ~> route ~> check { + ) ~> route(domain) ~> check { val response = responseAs[JsArray] response should matchJson(leasesListJson) } - Get(routePath(s"/info?id=nonvalid&id=${leaseCancel.id()}")) ~> route ~> check { + Get(routePath(s"/info?id=nonvalid&id=${leaseCancel.id()}")) ~> route(domain) ~> check { val response = responseAs[JsObject] response should matchJson(s""" |{ diff --git a/node/src/test/scala/com/wavesplatform/http/TransactionsRouteSpec.scala b/node/src/test/scala/com/wavesplatform/http/TransactionsRouteSpec.scala index ad6aca80e59..272e983604b 100644 --- a/node/src/test/scala/com/wavesplatform/http/TransactionsRouteSpec.scala +++ b/node/src/test/scala/com/wavesplatform/http/TransactionsRouteSpec.scala @@ -37,7 +37,7 @@ import com.wavesplatform.transaction.smart.script.trace.{AccountVerifierTrace, T import com.wavesplatform.transaction.smart.{InvokeScriptTransaction, SetScriptTransaction} import com.wavesplatform.transaction.transfer.TransferTransaction import com.wavesplatform.transaction.utils.Signed -import com.wavesplatform.transaction.{Asset, AssetIdLength, CreateAliasTransaction, EthTxGenerator, TxHelpers, TxVersion} +import com.wavesplatform.transaction.{Asset, AssetIdLength, CreateAliasTransaction, EthTxGenerator, TxHelpers, TxPositiveAmount, TxVersion} import com.wavesplatform.utils.{EthEncoding, EthHelpers, SharedSchedulerMixin} import com.wavesplatform.{BlockGen, BlockchainStubHelpers, TestValues, TestWallet} import monix.reactive.Observable @@ -302,11 +302,11 @@ class TransactionsRouteSpec (blockchain.leaseDetails _) .expects(leaseId1) - .returning(Some(LeaseDetails(TestValues.keyPair.publicKey, TestValues.address, 123, LeaseDetails.Status.Active, leaseId1, 1))) + .returning(Some(LeaseDetails(TestValues.keyPair.publicKey, TestValues.address, TxPositiveAmount(123), LeaseDetails.Status.Active, leaseId1, 1))) .anyNumberOfTimes() (blockchain.leaseDetails _) .expects(leaseId2) - .returning(Some(LeaseDetails(TestValues.keyPair.publicKey, TestValues.address, 123, LeaseDetails.Status.Active, leaseId2, 1))) + .returning(Some(LeaseDetails(TestValues.keyPair.publicKey, TestValues.address, TxPositiveAmount(123), LeaseDetails.Status.Active, leaseId2, 1))) .anyNumberOfTimes() (blockchain.leaseDetails _) .expects(leaseCancelId) @@ -315,7 +315,7 @@ class TransactionsRouteSpec LeaseDetails( TestValues.keyPair.publicKey, TestValues.address, - 123, + TxPositiveAmount(123), LeaseDetails.Status.Cancelled(2, Some(leaseCancelId)), leaseCancelId, 1 @@ -553,7 +553,7 @@ class TransactionsRouteSpec .when(lease.id()) .returns( Some( - LeaseDetails(lease.sender, lease.recipient, lease.amount.value, LeaseDetails.Status.Cancelled(2, Some(leaseCancel.id())), lease.id(), 1) + LeaseDetails(lease.sender, ???, lease.amount, LeaseDetails.Status.Cancelled(2, Some(leaseCancel.id())), lease.id(), 1) ) ) @@ -689,11 +689,11 @@ class TransactionsRouteSpec (blockchain.leaseDetails _) .expects(leaseId1) - .returning(Some(LeaseDetails(TestValues.keyPair.publicKey, TestValues.address, 123, LeaseDetails.Status.Active, leaseId1, 1))) + .returning(Some(LeaseDetails(TestValues.keyPair.publicKey, TestValues.address, TxPositiveAmount(123), LeaseDetails.Status.Active, leaseId1, 1))) .anyNumberOfTimes() (blockchain.leaseDetails _) .expects(leaseId2) - .returning(Some(LeaseDetails(TestValues.keyPair.publicKey, TestValues.address, 123, LeaseDetails.Status.Active, leaseId2, 1))) + .returning(Some(LeaseDetails(TestValues.keyPair.publicKey, TestValues.address, TxPositiveAmount(123), LeaseDetails.Status.Active, leaseId2, 1))) .anyNumberOfTimes() (blockchain.leaseDetails _) .expects(leaseCancelId) @@ -702,7 +702,7 @@ class TransactionsRouteSpec LeaseDetails( TestValues.keyPair.publicKey, TestValues.address, - 123, + TxPositiveAmount(123), LeaseDetails.Status.Cancelled(2, Some(leaseCancelId)), leaseCancelId, 1 @@ -712,7 +712,7 @@ class TransactionsRouteSpec .anyNumberOfTimes() (blockchain.leaseDetails _) .expects(nestedLeaseId) - .returning(Some(LeaseDetails(TestValues.keyPair.publicKey, TestValues.address, 123, LeaseDetails.Status.Active, nestedLeaseId, 1))) + .returning(Some(LeaseDetails(TestValues.keyPair.publicKey, TestValues.address, TxPositiveAmount(123), LeaseDetails.Status.Active, nestedLeaseId, 1))) .anyNumberOfTimes() (blockchain.leaseDetails _) .expects(nestedLeaseCancelId) @@ -721,7 +721,7 @@ class TransactionsRouteSpec LeaseDetails( TestValues.keyPair.publicKey, TestValues.address, - 123, + TxPositiveAmount(123), LeaseDetails.Status.Cancelled(2, Some(nestedLeaseCancelId)), nestedLeaseCancelId, 1 diff --git a/node/src/test/scala/com/wavesplatform/mining/BlockV5Test.scala b/node/src/test/scala/com/wavesplatform/mining/BlockV5Test.scala index 21cb7bc5394..12625590359 100644 --- a/node/src/test/scala/com/wavesplatform/mining/BlockV5Test.scala +++ b/node/src/test/scala/com/wavesplatform/mining/BlockV5Test.scala @@ -454,7 +454,7 @@ class BlockV5Test extends FlatSpec with WithDomain with OptionValues with Either ): Unit = { withRocksDBWriter(settings.blockchainSettings) { blockchain => val bcu: BlockchainUpdaterImpl = - new BlockchainUpdaterImpl(blockchain, settings, time, ignoreBlockchainUpdateTriggers, (_, _) => Seq.empty) { + new BlockchainUpdaterImpl(blockchain, settings, time, ignoreBlockchainUpdateTriggers, (_, _) => Map.empty) { override def activatedFeatures: Map[Short, Int] = super.activatedFeatures -- disabledFeatures.get() } try f(bcu) diff --git a/node/src/test/scala/com/wavesplatform/mining/BlockWithMaxBaseTargetTest.scala b/node/src/test/scala/com/wavesplatform/mining/BlockWithMaxBaseTargetTest.scala index 1137945f7b1..7d3e52e4a89 100644 --- a/node/src/test/scala/com/wavesplatform/mining/BlockWithMaxBaseTargetTest.scala +++ b/node/src/test/scala/com/wavesplatform/mining/BlockWithMaxBaseTargetTest.scala @@ -130,7 +130,7 @@ class BlockWithMaxBaseTargetTest extends FreeSpec with WithNewDBForEachTest with ) val bcu = - new BlockchainUpdaterImpl(defaultWriter, settings, ntpTime, ignoreBlockchainUpdateTriggers, (_, _) => Seq.empty) + new BlockchainUpdaterImpl(defaultWriter, settings, ntpTime, ignoreBlockchainUpdateTriggers, (_, _) => Map.empty) val pos = PoSSelector(bcu, settings.synchronizationSettings.maxBaseTarget) val utxPoolStub = new UtxPoolImpl(ntpTime, bcu, settings0.utxSettings, settings.maxTxErrorLogSize, settings0.minerSettings.enable) diff --git a/node/src/test/scala/com/wavesplatform/state/RollbackSpec.scala b/node/src/test/scala/com/wavesplatform/state/RollbackSpec.scala index 1a7deaec2e7..9391bb3301c 100644 --- a/node/src/test/scala/com/wavesplatform/state/RollbackSpec.scala +++ b/node/src/test/scala/com/wavesplatform/state/RollbackSpec.scala @@ -25,7 +25,7 @@ import com.wavesplatform.transaction.TxValidationError.AliasDoesNotExist import com.wavesplatform.transaction.lease.LeaseTransaction import com.wavesplatform.transaction.smart.{InvokeTransaction, SetScriptTransaction} import com.wavesplatform.transaction.transfer.* -import com.wavesplatform.transaction.{Transaction, TxHelpers, TxNonNegativeAmount, TxVersion} +import com.wavesplatform.transaction.{Transaction, TxHelpers, TxNonNegativeAmount, TxPositiveAmount, TxVersion} import org.scalatest.{Assertion, Assertions} class RollbackSpec extends FreeSpec with WithDomain { @@ -181,7 +181,7 @@ class RollbackSpec extends FreeSpec with WithDomain { d.blockchainUpdater.height shouldBe 2 val blockWithLeaseId = d.lastBlockId d.blockchainUpdater.leaseDetails(lt.id()) should contain( - LeaseDetails(sender.publicKey, recipient.toAddress, leaseAmount, LeaseDetails.Status.Active, lt.id(), 2) + LeaseDetails(sender.publicKey, recipient.toAddress, lt.amount, LeaseDetails.Status.Active, lt.id(), 2) ) d.blockchainUpdater.leaseBalance(sender.toAddress).out shouldEqual leaseAmount d.blockchainUpdater.leaseBalance(recipient.toAddress).in shouldEqual leaseAmount @@ -200,7 +200,7 @@ class RollbackSpec extends FreeSpec with WithDomain { LeaseDetails( sender.publicKey, recipient.toAddress, - leaseAmount, + lt.amount, LeaseDetails.Status.Cancelled(d.blockchain.height, Some(leaseCancel.id())), lt.id(), 2 @@ -211,7 +211,7 @@ class RollbackSpec extends FreeSpec with WithDomain { d.rollbackTo(blockWithLeaseId) d.blockchainUpdater.leaseDetails(lt.id()) should contain( - LeaseDetails(sender.publicKey, recipient.toAddress, leaseAmount, LeaseDetails.Status.Active, lt.id(), 2) + LeaseDetails(sender.publicKey, recipient.toAddress, lt.amount, LeaseDetails.Status.Active, lt.id(), 2) ) d.blockchainUpdater.leaseBalance(sender.toAddress).out shouldEqual leaseAmount d.blockchainUpdater.leaseBalance(recipient.toAddress).in shouldEqual leaseAmount @@ -694,7 +694,7 @@ class RollbackSpec extends FreeSpec with WithDomain { val (leaseAmount, leaseFc) = leaseFunctionCall(leaseRecipientAddress.toAddress) def leaseDetails(invokeId: ByteStr) = - Some(LeaseDetails(checkPk, leaseRecipientAddress.toAddress, leaseAmount, LeaseDetails.Status.Active, invokeId, 3)) + Some(LeaseDetails(checkPk, leaseRecipientAddress.toAddress, TxPositiveAmount.unsafeFrom(leaseAmount), LeaseDetails.Status.Active, invokeId, 3)) // liquid block rollback val invokeId1 = append(d.lastBlockId, leaseFc) @@ -760,7 +760,7 @@ class RollbackSpec extends FreeSpec with WithDomain { LeaseDetails( checkPk, leaseRecipientAddress, - leaseAmount, + TxPositiveAmount.unsafeFrom(leaseAmount), if (cancelId.isEmpty) LeaseDetails.Status.Active else LeaseDetails.Status.Cancelled(cancelHeight, Some(cancelId)), sourceId, diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeLeaseTest.scala b/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeLeaseTest.scala index f5a2165bf29..be423e2bddd 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeLeaseTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/diffs/ci/sync/SyncInvokeLeaseTest.scala @@ -44,11 +44,11 @@ class SyncInvokeLeaseTest extends PropSpec with WithDomain { d.appendAndAssertSucceed(invoke(dApp1Address)) val lease1 = d.liquidDiff.leaseState.head._2 lease1.status shouldBe a[Cancelled] - lease1.recipient shouldBe dApp2Address + lease1.recipientAddress shouldBe dApp2Address lease1.amount shouldBe 1 val lease2 = d.liquidDiff.leaseState.last._2 lease2.status shouldBe Active - lease2.recipient shouldBe dApp2Address + lease2.recipientAddress shouldBe dApp2Address lease2.amount shouldBe 555 } } diff --git a/node/src/test/scala/com/wavesplatform/state/snapshot/StateSnapshotProtoTest.scala b/node/src/test/scala/com/wavesplatform/state/snapshot/StateSnapshotProtoTest.scala index 0cb4d8a6593..bf5f7df21e7 100644 --- a/node/src/test/scala/com/wavesplatform/state/snapshot/StateSnapshotProtoTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/snapshot/StateSnapshotProtoTest.scala @@ -60,13 +60,8 @@ class StateSnapshotProtoTest extends PropSpec { IssuedAsset(ByteStr.fromBytes(2, 2, 2)) -> SponsorshipValue(0) ), Map( - ByteStr.fromBytes(4, 5, 6) -> LeaseSnapshot(defaultSigner.publicKey, secondAddress, 123, Status.Active), - ByteStr.fromBytes(7, 8, 9) -> LeaseSnapshot( - PublicKey(ByteStr.fill(KeyLength)(0)), - Address(Array.fill(Address.HashLength)(0)), - 0, - Status.Cancelled(0, None) - ) + ByteStr.fromBytes(4, 5, 6) -> ???, + ByteStr.fromBytes(7, 8, 9) -> ??? ), Map( Alias.create("alias").explicitGet() -> defaultAddress, diff --git a/node/src/test/scala/com/wavesplatform/state/snapshot/StateSnapshotStorageTest.scala b/node/src/test/scala/com/wavesplatform/state/snapshot/StateSnapshotStorageTest.scala index 8d3c115a9d8..44ecd523fd6 100644 --- a/node/src/test/scala/com/wavesplatform/state/snapshot/StateSnapshotStorageTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/snapshot/StateSnapshotStorageTest.scala @@ -15,6 +15,7 @@ import com.wavesplatform.state.* import com.wavesplatform.state.TxMeta.Status.{Failed, Succeeded} import com.wavesplatform.state.diffs.BlockDiffer.CurrentBlockFeePart import com.wavesplatform.state.diffs.ENOUGH_AMT +import com.wavesplatform.state.reader.LeaseDetails import com.wavesplatform.state.reader.LeaseDetails.Status.{Active, Cancelled} import com.wavesplatform.test.DomainPresets.* import com.wavesplatform.test.{NumericExt, PropSpec} @@ -174,7 +175,7 @@ class StateSnapshotStorageTest extends PropSpec with WithDomain { recipient -> LeaseBalance(leaseTx.amount.value, 0) ), leaseStates = Map( - leaseTx.id() -> LeaseSnapshot(sender.publicKey, recipient, leaseTx.amount.value, Active) + leaseTx.id() -> ??? ) ) ) @@ -192,12 +193,7 @@ class StateSnapshotStorageTest extends PropSpec with WithDomain { recipient -> LeaseBalance(0, 0) ), leaseStates = Map( - leaseTx.id() -> LeaseSnapshot( - PublicKey(ByteStr.fill(KeyLength)(0)), - Address(Array.fill(Address.HashLength)(0)), - 0, - Cancelled(0, None) - ) + leaseTx.id() -> ??? ) ) ) @@ -330,7 +326,7 @@ class StateSnapshotStorageTest extends PropSpec with WithDomain { dAppAssetId -> AssetInfo("name", "description", Height(height)) ), leaseStates = Map( - leaseId -> LeaseSnapshot(dAppPk, senderAddress, 123, Active) + leaseId -> ??? ), accountData = Map( dAppPk.toAddress -> Map("key" -> StringDataEntry("key", "abc")) 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 index 815cd6bce93..2367f392b08 100644 --- a/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/package.scala +++ b/ride-runner/src/main/scala/com/wavesplatform/database/rocksdb/package.scala @@ -131,7 +131,7 @@ package object rocksdb { ld => pb.LeaseDetails( ByteString.copyFrom(ld.sender.arr), - Some(PBRecipients.create(ld.recipient)), + Some(PBRecipients.create(ld.recipientAddress)), ld.amount, ByteString.copyFrom(ld.sourceId.arr), ld.height,