Skip to content

Commit

Permalink
NODE-2295: /debug/validate should take the priority pool into account…
Browse files Browse the repository at this point in the history
… (REST API) (#3384)
  • Loading branch information
Karasiq authored Mar 19, 2021
1 parent 4a19921 commit dd7d1db
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 41 deletions.
23 changes: 12 additions & 11 deletions node/src/main/scala/com/wavesplatform/Application.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import java.security.Security
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicBoolean

import scala.concurrent.{Await, Future}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.util.{Failure, Success, Try}

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.Http.ServerBinding
Expand All @@ -22,7 +27,7 @@ import com.wavesplatform.api.http.leasing.LeaseApiRoute
import com.wavesplatform.common.state.ByteStr
import com.wavesplatform.consensus.PoSSelector
import com.wavesplatform.consensus.nxt.api.http.NxtConsensusApiRoute
import com.wavesplatform.database.{DBExt, Keys, openDB}
import com.wavesplatform.database.{openDB, DBExt, Keys}
import com.wavesplatform.events.{BlockchainUpdateTriggers, UtxEvent}
import com.wavesplatform.extensions.{Context, Extension}
import com.wavesplatform.features.EstimatorProvider._
Expand All @@ -33,12 +38,12 @@ import com.wavesplatform.metrics.Metrics
import com.wavesplatform.mining.{Miner, MinerDebugInfo, MinerImpl}
import com.wavesplatform.network._
import com.wavesplatform.settings.WavesSettings
import com.wavesplatform.state.appender.{BlockAppender, ExtensionAppender, MicroblockAppender}
import com.wavesplatform.state.{Blockchain, BlockchainUpdaterImpl, Diff, Height}
import com.wavesplatform.transaction.smart.script.trace.TracedResult
import com.wavesplatform.state.appender.{BlockAppender, ExtensionAppender, MicroblockAppender}
import com.wavesplatform.transaction.{Asset, DiscardedBlocks, Transaction}
import com.wavesplatform.utils.Schedulers._
import com.wavesplatform.transaction.smart.script.trace.TracedResult
import com.wavesplatform.utils._
import com.wavesplatform.utils.Schedulers._
import com.wavesplatform.utx.{UtxPool, UtxPoolImpl}
import com.wavesplatform.wallet.Wallet
import io.netty.channel.Channel
Expand All @@ -55,11 +60,6 @@ import org.influxdb.dto.Point
import org.iq80.leveldb.DB
import org.slf4j.LoggerFactory

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
import scala.util.{Failure, Success, Try}

class Application(val actorSystem: ActorSystem, val settings: WavesSettings, configRoot: ConfigObject, time: NTP) extends ScorexLogging {
app =>

Expand Down Expand Up @@ -351,7 +351,8 @@ class Application(val actorSystem: ActorSystem, val settings: WavesSettings, con
scoreStatsReporter,
configRoot,
loadBalanceHistory,
levelDB.loadStateHash
levelDB.loadStateHash,
() => utxStorage.priorityPool.compositeBlockchain
),
AssetsApiRoute(
settings.restAPISettings,
Expand Down Expand Up @@ -541,8 +542,8 @@ object Application extends ScorexLogging {
Metrics.start(settings.metrics, time)

def dumpMinerConfig(): Unit = {
import settings.synchronizationSettings.microBlockSynchronizer
import settings.{minerSettings => miner}
import settings.synchronizationSettings.microBlockSynchronizer

Metrics.write(
Point
Expand Down
28 changes: 15 additions & 13 deletions node/src/main/scala/com/wavesplatform/api/http/DebugApiRoute.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ package com.wavesplatform.api.http
import java.net.{InetAddress, InetSocketAddress, URI}
import java.util.concurrent.ConcurrentMap

import scala.concurrent.{ExecutionContext, Future}
import scala.concurrent.duration._
import scala.util.{Failure, Success}
import scala.util.control.NonFatal

import akka.http.scaladsl.common.{EntityStreamingSupport, JsonEntityStreamingSupport}
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.headers.Accept
Expand All @@ -12,32 +17,27 @@ import cats.implicits._
import cats.kernel.Monoid
import com.typesafe.config.{ConfigObject, ConfigRenderOptions}
import com.wavesplatform.account.Address
import com.wavesplatform.api.common.CommonTransactionsApi.TransactionMeta
import com.wavesplatform.api.common.{CommonAccountsApi, CommonAssetsApi, CommonTransactionsApi}
import com.wavesplatform.api.common.CommonTransactionsApi.TransactionMeta
import com.wavesplatform.api.http.TransactionsApiRoute.TransactionJsonSerializer
import com.wavesplatform.common.state.ByteStr
import com.wavesplatform.lang.ValidationError
import com.wavesplatform.mining.{Miner, MinerDebugInfo}
import com.wavesplatform.network.{PeerDatabase, PeerInfo, _}
import com.wavesplatform.settings.{RestAPISettings, WavesSettings}
import com.wavesplatform.state.diffs.TransactionDiffer
import com.wavesplatform.state.{Blockchain, LeaseBalance, NG, Portfolio, StateHash}
import com.wavesplatform.transaction.TxValidationError.{GenericError, InvalidRequestSignature}
import com.wavesplatform.state.diffs.TransactionDiffer
import com.wavesplatform.transaction._
import com.wavesplatform.transaction.TxValidationError.{GenericError, InvalidRequestSignature}
import com.wavesplatform.transaction.smart.script.trace.TracedResult
import com.wavesplatform.utils.{ScorexLogging, Time}
import com.wavesplatform.utx.UtxPool
import com.wavesplatform.wallet.Wallet
import io.netty.channel.Channel
import monix.eval.{Coeval, Task}
import monix.execution.Scheduler
import play.api.libs.json.Json.JsValueWrapper
import play.api.libs.json._

import scala.concurrent.duration._
import scala.concurrent.{ExecutionContext, Future}
import scala.util.control.NonFatal
import scala.util.{Failure, Success}
import play.api.libs.json.Json.JsValueWrapper

case class DebugApiRoute(
ws: WavesSettings,
Expand All @@ -58,7 +58,8 @@ case class DebugApiRoute(
scoreReporter: Coeval[RxScoreObserver.Stats],
configRoot: ConfigObject,
loadBalanceHistory: Address => Seq[(Int, Long)],
loadStateHash: Int => Option[StateHash]
loadStateHash: Int => Option[StateHash],
priorityPoolBlockchain: () => Blockchain
) extends ApiRoute
with AuthRoute
with ScorexLogging {
Expand Down Expand Up @@ -224,13 +225,14 @@ case class DebugApiRoute(

def validate: Route =
path("validate")(jsonPost[JsObject] { jsv =>
val startTime = System.nanoTime()

val blockchain = priorityPoolBlockchain()
val startTime = System.nanoTime()

val parsedTransaction = TransactionFactory.fromSignedRequest(jsv)

val tracedDiff = for {
tx <- TracedResult(parsedTransaction)
diff <- TransactionDiffer(blockchain.lastBlockTimestamp, time.correctedTime())(blockchain, tx)
diff <- TransactionDiffer.forceValidate(blockchain.lastBlockTimestamp, time.correctedTime())(blockchain, tx)
} yield (tx, diff)

val error = tracedDiff.resultE match {
Expand Down
4 changes: 2 additions & 2 deletions node/src/test/scala/com/wavesplatform/history/Domain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ package com.wavesplatform.history
import cats.syntax.option._
import com.wavesplatform.account.Address
import com.wavesplatform.api.common.{AddressPortfolio, AddressTransactions}
import com.wavesplatform.block.Block.BlockId
import com.wavesplatform.block.{Block, MicroBlock}
import com.wavesplatform.block.Block.BlockId
import com.wavesplatform.common.state.ByteStr
import com.wavesplatform.common.utils.EitherExt2
import com.wavesplatform.database.{DBExt, LevelDBWriter}
import com.wavesplatform.lang.ValidationError
import com.wavesplatform.state._
import com.wavesplatform.transaction.Asset.IssuedAsset
import com.wavesplatform.transaction.{BlockchainUpdater, _}
import com.wavesplatform.transaction.Asset.IssuedAsset
import org.iq80.leveldb.DB

case class Domain(db: DB, blockchainUpdater: BlockchainUpdaterImpl, levelDBWriter: LevelDBWriter) {
Expand Down
54 changes: 39 additions & 15 deletions node/src/test/scala/com/wavesplatform/http/DebugApiRouteSpec.scala
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
package com.wavesplatform.http

import scala.util.Random

import akka.http.scaladsl.model.{ContentTypes, HttpEntity, StatusCodes}
import com.wavesplatform.{BlockchainStubHelpers, NTPTime, TestValues, TestWallet}
import com.wavesplatform.api.http.ApiError.ApiKeyNotValid
import com.wavesplatform.api.http.DebugApiRoute
import com.wavesplatform.block.SignedBlockHeader
import com.wavesplatform.common.state.ByteStr
import com.wavesplatform.common.utils._
import com.wavesplatform.db.WithDomain
import com.wavesplatform.features.BlockchainFeatures
import com.wavesplatform.it.util._
import com.wavesplatform.lagonaki.mocks.TestBlock
import com.wavesplatform.lang.v1.estimator.v3.ScriptEstimatorV3
import com.wavesplatform.lang.v1.traits.domain.Issue
import com.wavesplatform.network.PeerDatabase
import com.wavesplatform.settings.WavesSettings
import com.wavesplatform.state.StateHash.SectionId
import com.wavesplatform.state.{AccountScriptInfo, AssetDescription, AssetScriptInfo, Blockchain, Height, NG, StateHash}
import com.wavesplatform.state.StateHash.SectionId
import com.wavesplatform.transaction.TxHelpers
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.{BlockchainStubHelpers, NTPTime, TestValues, TestWallet}
import com.wavesplatform.transaction.transfer.TransferTransaction
import monix.eval.Task
import org.scalamock.scalatest.PathMockFactory
import play.api.libs.json.{JsArray, JsObject, JsValue, Json}

import scala.util.Random
import play.api.libs.json.{JsArray, JsObject, Json, JsValue}

//noinspection ScalaStyle
class DebugApiRouteSpec
Expand All @@ -33,7 +36,8 @@ class DebugApiRouteSpec
with TestWallet
with NTPTime
with PathMockFactory
with BlockchainStubHelpers {
with BlockchainStubHelpers
with WithDomain {

val wavesSettings = WavesSettings.default()
val configObject = wavesSettings.config.root()
Expand Down Expand Up @@ -68,7 +72,8 @@ class DebugApiRouteSpec
_ => Seq.empty, {
case 2 => Some(testStateHash)
case _ => None
}
},
() => blockchain
)
import debugApiRoute._

Expand All @@ -94,14 +99,34 @@ class DebugApiRouteSpec
}

routePath("/validate") - {
def routeWithBlockchain(blockchain: Blockchain with NG) =
debugApiRoute.copy(blockchain = blockchain, priorityPoolBlockchain = () => blockchain).route


def validatePost(tx: TransferTransaction) =
Post(routePath("/validate"), HttpEntity(ContentTypes.`application/json`, tx.json().toString()))

"takes the priority pool into account" in withDomain(domainSettingsWithFeatures(BlockchainFeatures.NG)) { d =>
d.appendBlock(TxHelpers.genesis(TxHelpers.defaultAddress))
d.appendBlock(TxHelpers.transfer(to = TxHelpers.secondAddress, amount = 1.waves + TestValues.fee))

val route = debugApiRoute.copy(priorityPoolBlockchain = () => d.blockchain).route
val tx = TxHelpers.transfer(TxHelpers.secondSigner, TestValues.address, 1.waves)
validatePost(tx) ~> route ~> check {
val json = Json.parse(responseAs[String])
(json \ "valid").as[Boolean] shouldBe true
(json \ "validationTime").as[Int] shouldBe 1000 +- 1000
}
}

"valid tx" in {
val blockchain = createBlockchainStub()
(blockchain.balance _).when(TxHelpers.defaultSigner.publicKey.toAddress, *).returns(Long.MaxValue)

val route = debugApiRoute.copy(blockchain = blockchain).route
val route = routeWithBlockchain(blockchain)

val tx = TxHelpers.transfer(TxHelpers.defaultSigner, TestValues.address, 1.waves)
Post(routePath("/validate"), HttpEntity(ContentTypes.`application/json`, tx.json().toString())) ~> route ~> check {
validatePost(tx) ~> route ~> check {
val json = Json.parse(responseAs[String])
(json \ "valid").as[Boolean] shouldBe true
(json \ "validationTime").as[Int] shouldBe 1000 +- 1000
Expand All @@ -112,10 +137,10 @@ class DebugApiRouteSpec
val blockchain = createBlockchainStub()
(blockchain.balance _).when(TxHelpers.defaultSigner.publicKey.toAddress, *).returns(0)

val route = debugApiRoute.copy(blockchain = blockchain).route
val route = routeWithBlockchain(blockchain)

val tx = TxHelpers.transfer(TxHelpers.defaultSigner, TestValues.address, Long.MaxValue)
Post(routePath("/validate"), HttpEntity(ContentTypes.`application/json`, tx.json().toString())) ~> route ~> check {
validatePost(tx) ~> route ~> check {
val json = Json.parse(responseAs[String])
(json \ "valid").as[Boolean] shouldBe false
(json \ "validationTime").as[Int] shouldBe 1000 +- 1000
Expand Down Expand Up @@ -150,7 +175,7 @@ class DebugApiRouteSpec
)
}

val route = debugApiRoute.copy(blockchain = blockchain).route
val route = routeWithBlockchain(blockchain)
val tx = TxHelpers.exchange(TxHelpers.order(OrderType.BUY, TestValues.asset), TxHelpers.order(OrderType.SELL, TestValues.asset))
jsonPost(routePath("/validate"), tx.json()) ~> route ~> check {
val json = Json.parse(responseAs[String])
Expand Down Expand Up @@ -249,8 +274,7 @@ class DebugApiRouteSpec
(blockchain.hasAccountScript _).when(*).returns(true)
}

val route = debugApiRoute.copy(blockchain = blockchain).route

val route = routeWithBlockchain(blockchain)
def testFunction(name: String, result: InvokeScriptTransaction => String) = withClue(s"function $name") {
val tx = TxHelpers.invoke(TxHelpers.defaultAddress, name, fee = 102500000)

Expand Down Expand Up @@ -518,7 +542,7 @@ class DebugApiRouteSpec
)
)
}
val route = debugApiRoute.copy(blockchain = blockchain).route
val route = routeWithBlockchain(blockchain)
val tx = TxHelpers.transfer(TxHelpers.defaultSigner, TxHelpers.defaultAddress, 1, TestValues.asset)

jsonPost(routePath("/validate"), tx.json()) ~> route ~> check {
Expand Down

0 comments on commit dd7d1db

Please sign in to comment.