diff --git a/grpc-server/src/main/scala/com/wavesplatform/api/grpc/TransactionsApiGrpcImpl.scala b/grpc-server/src/main/scala/com/wavesplatform/api/grpc/TransactionsApiGrpcImpl.scala index 7848170398..e8f6640622 100644 --- a/grpc-server/src/main/scala/com/wavesplatform/api/grpc/TransactionsApiGrpcImpl.scala +++ b/grpc-server/src/main/scala/com/wavesplatform/api/grpc/TransactionsApiGrpcImpl.scala @@ -1,6 +1,5 @@ package com.wavesplatform.api.grpc -import scala.concurrent.Future import com.wavesplatform.account.AddressScheme import com.wavesplatform.api.common.{CommonTransactionsApi, TransactionMeta} import com.wavesplatform.api.grpc.TransactionsApiGrpcImpl.applicationStatusFromTxStatus @@ -8,13 +7,15 @@ import com.wavesplatform.protobuf.* import com.wavesplatform.protobuf.transaction.* import com.wavesplatform.protobuf.utils.PBImplicitConversions.PBRecipientImplicitConversionOps import com.wavesplatform.state.{Blockchain, TxMeta, InvokeScriptResult as VISR} -import com.wavesplatform.transaction.{Authorized, EthereumTransaction} import com.wavesplatform.transaction.TxValidationError.GenericError -import io.grpc.{Status, StatusRuntimeException} +import com.wavesplatform.transaction.{Authorized, EthereumTransaction} import io.grpc.stub.StreamObserver +import io.grpc.{Status, StatusRuntimeException} import monix.execution.Scheduler import monix.reactive.Observable +import scala.concurrent.Future + class TransactionsApiGrpcImpl(blockchain: Blockchain, commonApi: CommonTransactionsApi)(implicit sc: Scheduler) extends TransactionsApiGrpc.TransactionsApi { @@ -64,6 +65,20 @@ class TransactionsApiGrpcImpl(blockchain: Blockchain, commonApi: CommonTransacti ) } + override def getTransactionSnapshots( + request: TransactionSnapshotsRequest, + responseObserver: StreamObserver[TransactionSnapshotResponse] + ): Unit = + responseObserver.interceptErrors { + val snapshots = + for { + id <- request.transactionIds + (snapshot, status) <- blockchain.transactionSnapshot(id.toByteStr) + pbSnapshot = PBSnapshots.toProtobuf(snapshot, status) + } yield TransactionSnapshotResponse(id, Some(pbSnapshot)) + responseObserver.completeWith(Observable.fromIterable(snapshots)) + } + override def getUnconfirmed(request: TransactionsRequest, responseObserver: StreamObserver[TransactionResponse]): Unit = responseObserver.interceptErrors { val unconfirmedTransactions = if (!request.sender.isEmpty) { diff --git a/node/src/main/scala/com/wavesplatform/api/http/TransactionsApiRoute.scala b/node/src/main/scala/com/wavesplatform/api/http/TransactionsApiRoute.scala index 83d468b0a3..b2a7bc53c0 100644 --- a/node/src/main/scala/com/wavesplatform/api/http/TransactionsApiRoute.scala +++ b/node/src/main/scala/com/wavesplatform/api/http/TransactionsApiRoute.scala @@ -88,7 +88,7 @@ case class TransactionsApiRoute( blockchain .transactionSnapshot(id) .toRight(TransactionDoesNotExist) - .map(StateSnapshotJson.fromSnapshot) + .map { case (snapshot, _) => StateSnapshotJson.fromSnapshot(snapshot) } val single = (get & path(TransactionId))(id => complete(readSnapshot(id))) val multiple = (pathEndOrSingleSlash & anyParam("id", limit = settings.transactionSnapshotsLimit))(rawIds => complete( diff --git a/node/src/main/scala/com/wavesplatform/database/RocksDBWriter.scala b/node/src/main/scala/com/wavesplatform/database/RocksDBWriter.scala index b102348f73..2647ab2c4b 100644 --- a/node/src/main/scala/com/wavesplatform/database/RocksDBWriter.scala +++ b/node/src/main/scala/com/wavesplatform/database/RocksDBWriter.scala @@ -21,6 +21,7 @@ import com.wavesplatform.protobuf.snapshot.TransactionStatus as PBStatus import com.wavesplatform.protobuf.{ByteStrExt, ByteStringExt, PBSnapshots} import com.wavesplatform.settings.{BlockchainSettings, DBSettings} import com.wavesplatform.state.* +import com.wavesplatform.state.TxMeta.Status import com.wavesplatform.transaction.* import com.wavesplatform.transaction.Asset.{IssuedAsset, Waves} import com.wavesplatform.transaction.EthereumTransaction.Transfer @@ -970,11 +971,11 @@ class RocksDBWriter( } } - override def transactionSnapshot(id: ByteStr): Option[StateSnapshot] = readOnly { db => + override def transactionSnapshot(id: ByteStr): Option[(StateSnapshot, Status)] = readOnly { db => for { meta <- db.get(Keys.transactionMetaById(TransactionId(id), rdb.txMetaHandle)) snapshot <- db.get(Keys.transactionStateSnapshotAt(Height(meta.height), TxNum(meta.num.toShort), rdb.txSnapshotHandle)) - } yield PBSnapshots.fromProtobuf(snapshot, id, meta.height)._1 + } yield PBSnapshots.fromProtobuf(snapshot, id, meta.height) } override def resolveAlias(alias: Alias): Either[ValidationError, Address] = diff --git a/node/src/main/scala/com/wavesplatform/state/Blockchain.scala b/node/src/main/scala/com/wavesplatform/state/Blockchain.scala index 0be7ce335a..3e7471e6fc 100644 --- a/node/src/main/scala/com/wavesplatform/state/Blockchain.scala +++ b/node/src/main/scala/com/wavesplatform/state/Blockchain.scala @@ -12,6 +12,7 @@ import com.wavesplatform.lang.script.ContractScript import com.wavesplatform.lang.v1.ContractLimits import com.wavesplatform.lang.v1.traits.domain.Issue import com.wavesplatform.settings.BlockchainSettings +import com.wavesplatform.state.TxMeta.Status import com.wavesplatform.transaction.Asset.{IssuedAsset, Waves} import com.wavesplatform.transaction.TxValidationError.AliasDoesNotExist import com.wavesplatform.transaction.assets.IssueTransaction @@ -46,7 +47,7 @@ trait Blockchain { def transactionInfo(id: ByteStr): Option[(TxMeta, Transaction)] def transactionInfos(ids: Seq[ByteStr]): Seq[Option[(TxMeta, Transaction)]] def transactionMeta(id: ByteStr): Option[TxMeta] - def transactionSnapshot(id: ByteStr): Option[StateSnapshot] + def transactionSnapshot(id: ByteStr): Option[(StateSnapshot, Status)] def containsTransaction(tx: Transaction): Boolean diff --git a/node/src/main/scala/com/wavesplatform/state/BlockchainUpdaterImpl.scala b/node/src/main/scala/com/wavesplatform/state/BlockchainUpdaterImpl.scala index a91ce4e00d..26e694c766 100644 --- a/node/src/main/scala/com/wavesplatform/state/BlockchainUpdaterImpl.scala +++ b/node/src/main/scala/com/wavesplatform/state/BlockchainUpdaterImpl.scala @@ -17,6 +17,7 @@ import com.wavesplatform.metrics.{TxsInBlockchainStats, *} import com.wavesplatform.mining.{Miner, MiningConstraint, MiningConstraints} import com.wavesplatform.settings.{BlockchainSettings, WavesSettings} import com.wavesplatform.state.BlockchainUpdaterImpl.BlockApplyResult.{Applied, Ignored} +import com.wavesplatform.state.TxMeta.Status import com.wavesplatform.state.diffs.BlockDiffer import com.wavesplatform.transaction.* import com.wavesplatform.transaction.Asset.{IssuedAsset, Waves} @@ -753,7 +754,7 @@ class BlockchainUpdaterImpl( snapshotBlockchain.transactionMeta(id) } - override def transactionSnapshot(id: ByteStr): Option[StateSnapshot] = readLock { + override def transactionSnapshot(id: ByteStr): Option[(StateSnapshot, Status)] = readLock { snapshotBlockchain.transactionSnapshot(id) } diff --git a/node/src/main/scala/com/wavesplatform/state/SnapshotBlockchain.scala b/node/src/main/scala/com/wavesplatform/state/SnapshotBlockchain.scala index de252e9050..e4abac8296 100644 --- a/node/src/main/scala/com/wavesplatform/state/SnapshotBlockchain.scala +++ b/node/src/main/scala/com/wavesplatform/state/SnapshotBlockchain.scala @@ -8,6 +8,7 @@ import com.wavesplatform.common.state.ByteStr import com.wavesplatform.features.BlockchainFeatures.RideV6 import com.wavesplatform.lang.ValidationError import com.wavesplatform.settings.BlockchainSettings +import com.wavesplatform.state.TxMeta.Status import com.wavesplatform.transaction.Asset.{IssuedAsset, Waves} import com.wavesplatform.transaction.TxValidationError.{AliasDoesNotExist, AliasIsDisabled} import com.wavesplatform.transaction.transfer.{TransferTransaction, TransferTransactionLike} @@ -119,10 +120,10 @@ case class SnapshotBlockchain( .map(t => TxMeta(Height(this.height), t.status, t.spentComplexity)) .orElse(inner.transactionMeta(id)) - override def transactionSnapshot(id: ByteStr): Option[StateSnapshot] = + override def transactionSnapshot(id: ByteStr): Option[(StateSnapshot, Status)] = snapshot.transactions .get(id) - .map(_.snapshot) + .map(tx => (tx.snapshot, tx.status)) .orElse(inner.transactionSnapshot(id)) override def height: Int = inner.height + blockMeta.fold(0)(_ => 1) diff --git a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/MatcherBlockchainTest.scala b/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/MatcherBlockchainTest.scala index d5093121f4..6b28ca7876 100644 --- a/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/MatcherBlockchainTest.scala +++ b/node/src/test/scala/com/wavesplatform/state/diffs/smart/predef/MatcherBlockchainTest.scala @@ -13,6 +13,7 @@ import com.wavesplatform.lang.v1.compiler.TestCompiler import com.wavesplatform.lang.v1.traits.domain.Recipient import com.wavesplatform.settings.BlockchainSettings import com.wavesplatform.state.* +import com.wavesplatform.state.TxMeta.Status import com.wavesplatform.test.PropSpec import com.wavesplatform.transaction.Asset.Waves import com.wavesplatform.transaction.smart.script.ScriptRunner @@ -41,7 +42,7 @@ class MatcherBlockchainTest extends PropSpec with MockFactory with WithDomain { override def transactionInfo(id: ByteStr): Option[(TxMeta, Transaction)] = ??? override def transactionInfos(ids: Seq[BlockId]): Seq[Option[(TxMeta, Transaction)]] = ??? override def transactionMeta(id: ByteStr): Option[TxMeta] = ??? - override def transactionSnapshot(id: ByteStr): Option[StateSnapshot] = ??? + override def transactionSnapshot(id: ByteStr): Option[(StateSnapshot, Status)] = ??? override def containsTransaction(tx: Transaction): Boolean = ??? override def assetDescription(id: Asset.IssuedAsset): Option[AssetDescription] = ??? override def resolveAlias(a: Alias): Either[ValidationError, Address] = ??? diff --git a/node/src/test/scala/com/wavesplatform/utils/EmptyBlockchain.scala b/node/src/test/scala/com/wavesplatform/utils/EmptyBlockchain.scala index 1530549fde..ecddcb139a 100644 --- a/node/src/test/scala/com/wavesplatform/utils/EmptyBlockchain.scala +++ b/node/src/test/scala/com/wavesplatform/utils/EmptyBlockchain.scala @@ -7,6 +7,7 @@ import com.wavesplatform.common.state.ByteStr import com.wavesplatform.lang.ValidationError import com.wavesplatform.settings.BlockchainSettings import com.wavesplatform.state.* +import com.wavesplatform.state.TxMeta.Status import com.wavesplatform.transaction.Asset.{IssuedAsset, Waves} import com.wavesplatform.transaction.TxValidationError.GenericError import com.wavesplatform.transaction.transfer.TransferTransactionLike @@ -49,7 +50,7 @@ trait EmptyBlockchain extends Blockchain { override def transactionMeta(id: ByteStr): Option[TxMeta] = None - override def transactionSnapshot(id: ByteStr): Option[StateSnapshot] = None + override def transactionSnapshot(id: ByteStr): Option[(StateSnapshot, Status)] = None override def containsTransaction(tx: Transaction): Boolean = false diff --git a/project/Dependencies.scala b/project/Dependencies.scala index ac3e5a07c8..478b87aa7d 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -6,7 +6,7 @@ import scalapb.compiler.Version.scalapbVersion object Dependencies { // Node protobuf schemas private[this] val protoSchemasLib = - "com.wavesplatform" % "protobuf-schemas" % "1.5.1" classifier "protobuf-src" intransitive () + "com.wavesplatform" % "protobuf-schemas" % "1.5.2-86-SNAPSHOT" classifier "protobuf-src" intransitive () private def akkaModule(module: String) = "com.typesafe.akka" %% s"akka-$module" % "2.6.21"