From 4af9a6cac4babc31df1939466c674a5a0fd698a5 Mon Sep 17 00:00:00 2001 From: Alexis Hernandez Date: Sat, 30 Mar 2019 11:52:41 -0700 Subject: [PATCH] server: Remove TPoS contract logic from the ScriptPubKey model --- .../models/persisted/Transaction.scala | 11 +++- .../explorer/models/rpc/ScriptPubKey.scala | 28 ++------- .../xsn/explorer/services/BlockService.scala | 8 +-- .../explorer/services/logic/BlockLogic.scala | 19 +++---- .../models/rpc/ScriptPubKeySpec.scala | 57 ------------------- ...4214827f930a69802c1c43d1fb2ff7b7075b2d1701 | 2 +- ...207a7ef6115fa1dd33f7156b006fafc6bb85a79eb8 | 2 +- 7 files changed, 27 insertions(+), 100 deletions(-) delete mode 100644 server/test/com/xsn/explorer/models/rpc/ScriptPubKeySpec.scala diff --git a/server/app/com/xsn/explorer/models/persisted/Transaction.scala b/server/app/com/xsn/explorer/models/persisted/Transaction.scala index c32dcb9..55d95be 100644 --- a/server/app/com/xsn/explorer/models/persisted/Transaction.scala +++ b/server/app/com/xsn/explorer/models/persisted/Transaction.scala @@ -63,12 +63,19 @@ object Transaction { } val outputs = tx.vout.flatMap { vout => - val tposAddresses = vout.scriptPubKey.flatMap(_.getTPoSAddresses) + val contract = vout.scriptPubKey.flatMap(_.getTPoSContractDetails) val scriptMaybe = vout.scriptPubKey.map(_.hex) for { address <- vout.address script <- scriptMaybe - } yield Transaction.Output(tx.id, vout.n, vout.value, address, script, tposAddresses.map(_._1), tposAddresses.map(_._2)) + } yield Transaction.Output( + tx.id, + vout.n, + vout.value, + address, + script, + tposOwnerAddress = contract.map(_.owner), + tposMerchantAddress = contract.map(_.merchant)) } val transaction = Transaction( diff --git a/server/app/com/xsn/explorer/models/rpc/ScriptPubKey.scala b/server/app/com/xsn/explorer/models/rpc/ScriptPubKey.scala index 5c1d6ad..65a3845 100644 --- a/server/app/com/xsn/explorer/models/rpc/ScriptPubKey.scala +++ b/server/app/com/xsn/explorer/models/rpc/ScriptPubKey.scala @@ -1,5 +1,6 @@ package com.xsn.explorer.models.rpc +import com.xsn.explorer.models.TPoSContract import com.xsn.explorer.models.values.{Address, HexString} import play.api.libs.functional.syntax._ import play.api.libs.json.{Reads, __} @@ -11,31 +12,10 @@ case class ScriptPubKey( addresses: List[Address]) { /** - * Parse addresses from a TPoS contract transaction. - * - * @return (owner address, merchant address) + * Get TPoS contract details if available */ - def getTPoSAddresses: Option[(Address, Address)] = { - /** - * expected: - * - "asm": "OP_RETURN 5869337351664d51737932437a4d5a54726e4b573648464770315671465468644c77 58794a4338786e664672484e634d696e68366778755052595939484361593944416f 99" - * - * new format: - *- "asm": "OP_RETURN 586a55587938507a55464d78534c37594135767866574a587365746b354d5638676f 58794a4338786e664672484e634d696e68366778755052595939484361593944416f 99 1f60a6a385a4e5163ffef65dd873f17452bb0d9f89da701ffcc5a0f72287273c0571485c29123fef880d2d8169cfdb884bf95a18a0b36461517acda390ce4cf441" - */ - Option(asm) - .map(_ split " ") - .filter(_.size >= 4) // relax size check - .map(_.toList) - .flatMap { - case op :: owner :: merchant :: _ if op == "OP_RETURN" => - for { - ownerAddress <- Address.fromHex(owner) - merchantAddress <- Address.fromHex(merchant) - } yield (ownerAddress, merchantAddress) - - case _ => None - } + def getTPoSContractDetails: Option[TPoSContract.Details] = { + TPoSContract.Details.fromOutputScriptASM(asm) } } diff --git a/server/app/com/xsn/explorer/services/BlockService.scala b/server/app/com/xsn/explorer/services/BlockService.scala index 9ed80dd..6812651 100644 --- a/server/app/com/xsn/explorer/services/BlockService.scala +++ b/server/app/com/xsn/explorer/services/BlockService.scala @@ -255,14 +255,12 @@ class BlockService @Inject() ( .getTransaction(tposTxId) .toFutureOr - addresses <- blockLogic - .getTPoSAddresses(tposTx) + contract <- blockLogic + .getTPoSContractDetails(tposTx) .toFutureOr - (ownerAddress, merchantAddress) = addresses - rewards <- blockLogic - .getTPoSRewards(coinstakeTx, ownerAddress, merchantAddress, coinstakeInput) + .getTPoSRewards(coinstakeTx, contract, coinstakeInput) .toFutureOr } yield rewards diff --git a/server/app/com/xsn/explorer/services/logic/BlockLogic.scala b/server/app/com/xsn/explorer/services/logic/BlockLogic.scala index 41a626d..1289c60 100644 --- a/server/app/com/xsn/explorer/services/logic/BlockLogic.scala +++ b/server/app/com/xsn/explorer/services/logic/BlockLogic.scala @@ -45,11 +45,11 @@ class BlockLogic { Or.from(maybe, One(BlockNotFoundError)) } - def getTPoSAddresses(tposContract: Transaction[_]): ApplicationResult[(Address, Address)] = { + def getTPoSContractDetails(tposContract: Transaction[_]): ApplicationResult[TPoSContract.Details] = { val maybe = tposContract .vout .flatMap(_.scriptPubKey) - .flatMap(_.getTPoSAddresses) + .flatMap(_.getTPoSContractDetails) .headOption Or.from(maybe, One(BlockNotFoundError)) @@ -107,8 +107,7 @@ class BlockLogic { def getTPoSRewards( coinstakeTx: Transaction[_], - owner: Address, - merchant: Address, + contract: TPoSContract.Details, coinstakeInput: BigDecimal): ApplicationResult[TPoSBlockRewards] = { /** @@ -123,22 +122,22 @@ class BlockLogic { val coinstakeVOUT = coinstakeTx.vout val ownerValue = coinstakeVOUT - .filter(_.address contains owner) + .filter(_.address contains contract.owner) .map(_.value) .sum val ownerReward = BlockReward( - owner, + contract.owner, (ownerValue - coinstakeInput) max 0) // merchant - val merchantValue = coinstakeVOUT.filter(_.address contains merchant).map(_.value).sum - val merchantReward = BlockReward(merchant, merchantValue) + val merchantValue = coinstakeVOUT.filter(_.address contains contract.merchant).map(_.value).sum + val merchantReward = BlockReward(contract.merchant, merchantValue) // master node val masternodeRewardOUT = coinstakeVOUT.filterNot { out => - out.address.contains(owner) || - out.address.contains(merchant) + out.address.contains(contract.owner) || + out.address.contains(contract.merchant) } val masternodeAddressMaybe = masternodeRewardOUT.flatMap(_.address).headOption val masternodeRewardMaybe = masternodeAddressMaybe.map { masternodeAddress => diff --git a/server/test/com/xsn/explorer/models/rpc/ScriptPubKeySpec.scala b/server/test/com/xsn/explorer/models/rpc/ScriptPubKeySpec.scala deleted file mode 100644 index 35cf6d9..0000000 --- a/server/test/com/xsn/explorer/models/rpc/ScriptPubKeySpec.scala +++ /dev/null @@ -1,57 +0,0 @@ -package com.xsn.explorer.models.rpc - -import com.xsn.explorer.models.values.{HexString, _} -import org.scalatest.{MustMatchers, OptionValues, WordSpec} - -class ScriptPubKeySpec extends WordSpec with MustMatchers with OptionValues { - - private val dummyScript = HexString.from("00").get - - "getTPoSAddresses" should { - - "parse the addresses" in { - val script = ScriptPubKey("nulldata", "OP_RETURN 5869337351664d51737932437a4d5a54726e4b573648464770315671465468644c77 58794a4338786e664672484e634d696e68366778755052595939484361593944416f 99", dummyScript, List.empty) - val expected = ( - Address.from("Xi3sQfMQsy2CzMZTrnKW6HFGp1VqFThdLw").get, - Address.from("XyJC8xnfFrHNcMinh6gxuPRYY9HCaY9DAo").get) - - val result = script.getTPoSAddresses - result.value mustEqual expected - } - - "support more than 4 values if we have the addresses" in { - val script = ScriptPubKey("nulldata", "OP_RETURN 586a55587938507a55464d78534c37594135767866574a587365746b354d5638676f 58794a4338786e664672484e634d696e68366778755052595939484361593944416f 99 1f60a6a385a4e5163ffef65dd873f17452bb0d9f89da701ffcc5a0f72287273c0571485c29123fef880d2d8169cfdb884bf95a18a0b36461517acda390ce4cf441", dummyScript, List.empty) - - val result = script.getTPoSAddresses - result.nonEmpty mustEqual true - } - - "fail if OP_RETURN is not present" in { - val script = ScriptPubKey("nulldata", "OP_RTURN 5869337351664d51737932437a4d5a54726e4b573648464770315671465468644c77 58794a4338786e664672484e634d696e68366778755052595939484361593944416f 99", dummyScript, List.empty) - - val result = script.getTPoSAddresses - result.isEmpty mustEqual true - } - - "fail if the comission is missing" in { - val script = ScriptPubKey("nulldata", "OP_RETURN 5869337351664d51737932437a4d5a54726e4b573648464770315671465468644c77 58794a4338786e664672484e634d696e68366778755052595939484361593944416f ", dummyScript, List.empty) - - val result = script.getTPoSAddresses - result.isEmpty mustEqual true - } - - "fail if the owner address is malformed" in { - val script = ScriptPubKey("nulldata", "OP_RETURN 586933735164d51737932437a4d5a54726e4b573648464770315671465468644c77 58794a4338786e664672484e634d696e68366778755052595939484361593944416f 99", dummyScript, List.empty) - - val result = script.getTPoSAddresses - result.isEmpty mustEqual true - } - - "fail if the merchant address is malformed" in { - val script = ScriptPubKey("nulldata", "OP_RETURN 5869337351664d51737932437a4d5a54726e4b573648464770315671465468644c77 58794a4338786664672484e634d696e68366778755052595939484361593944416f 99", dummyScript, List.empty) - - val result = script.getTPoSAddresses - result.isEmpty mustEqual true - } - } -} diff --git a/server/test/resources/transactions/7f2b5f25b0ae24a417633e4214827f930a69802c1c43d1fb2ff7b7075b2d1701 b/server/test/resources/transactions/7f2b5f25b0ae24a417633e4214827f930a69802c1c43d1fb2ff7b7075b2d1701 index 61bd1b7..888b22e 100644 --- a/server/test/resources/transactions/7f2b5f25b0ae24a417633e4214827f930a69802c1c43d1fb2ff7b7075b2d1701 +++ b/server/test/resources/transactions/7f2b5f25b0ae24a417633e4214827f930a69802c1c43d1fb2ff7b7075b2d1701 @@ -24,7 +24,7 @@ "valueSat": 0, "n": 0, "scriptPubKey": { - "asm": "OP_RETURN 5869337351664d51737932437a4d5a54726e4b573648464770315671465468644c77 58794a4338786e664672484e634d696e68366778755052595939484361593944416f 99", + "asm": "OP_RETURN 5869337351664d51737932437a4d5a54726e4b573648464770315671465468644c77 58794a4338786e664672484e634d696e68366778755052595939484361593944416f 99 ffaabbcc", "hex": "6a225869337351664d51737932437a4d5a54726e4b573648464770315671465468644c772258794a4338786e664672484e634d696e68366778755052595939484361593944416f0163", "type": "nulldata" } diff --git a/server/test/resources/transactions/99c51e4fe89466faa734d6207a7ef6115fa1dd33f7156b006fafc6bb85a79eb8 b/server/test/resources/transactions/99c51e4fe89466faa734d6207a7ef6115fa1dd33f7156b006fafc6bb85a79eb8 index afc3e5d..8689e18 100644 --- a/server/test/resources/transactions/99c51e4fe89466faa734d6207a7ef6115fa1dd33f7156b006fafc6bb85a79eb8 +++ b/server/test/resources/transactions/99c51e4fe89466faa734d6207a7ef6115fa1dd33f7156b006fafc6bb85a79eb8 @@ -24,7 +24,7 @@ "valueSat": 0, "n": 0, "scriptPubKey": { - "asm": "OP_RETURN 587535556b67524c385952716f57367545573853784d4c446b4a77626a4656666765 5862474670737568763641483367703364783565517241657850356b455368396259 99", + "asm": "OP_RETURN 587535556b67524c385952716f57367545573853784d4c446b4a77626a4656666765 5862474670737568763641483367703364783565517241657850356b455368396259 99 ffaabbcc", "hex": "6a22587535556b67524c385952716f57367545573853784d4c446b4a77626a4656666765225862474670737568763641483367703364783565517241657850356b4553683962590163", "type": "nulldata" }