From 50162cb2ef711067430a21df79e58452f93b5a16 Mon Sep 17 00:00:00 2001 From: alexandr Date: Sat, 28 Apr 2018 15:00:11 +0300 Subject: [PATCH 1/4] NODE 496: CreateAliasTransaction base trait --- .../com/wavesplatform/state/ExtractInfo.scala | 6 +- .../NarrowTransactionGenerator.scala | 8 +- .../database/LevelDBWriter.scala | 2 +- .../state/diffs/CommonValidation.scala | 40 ++++---- .../diffs/CreateAliasTransactionDiff.scala | 4 +- .../state/diffs/TransactionDiffer.scala | 2 +- .../com/wavesplatform/state/package.scala | 6 +- .../api/http/TransactionsApiRoute.scala | 56 +++++------ .../http/alias/SignedCreateAliasRequest.scala | 6 +- .../transaction/CreateAliasTransaction.scala | 65 ------------- .../CreateAliasTransactionV1.scala | 97 +++++++++++++++++++ .../transaction/TransactionFactory.scala | 4 +- .../transaction/TransactionParsers.scala | 2 +- .../smart/RealTransactionWrapper.scala | 4 +- .../com/wavesplatform/TransactionGen.scala | 4 +- .../wavesplatform/state/RollbackSpec.scala | 4 +- .../CreateAliasTransactionDiffTest.scala | 14 +-- .../AddressFromRecipientScenarioTest.scala | 6 +- .../CreateAliasTransactionSpecification.scala | 14 +-- .../FeeCalculatorSpecification.scala | 2 +- 20 files changed, 189 insertions(+), 157 deletions(-) delete mode 100644 src/main/scala/scorex/transaction/CreateAliasTransaction.scala create mode 100644 src/main/scala/scorex/transaction/CreateAliasTransactionV1.scala diff --git a/benchmark/src/main/scala/com/wavesplatform/state/ExtractInfo.scala b/benchmark/src/main/scala/com/wavesplatform/state/ExtractInfo.scala index ab8362f201a..2b3b253f661 100644 --- a/benchmark/src/main/scala/com/wavesplatform/state/ExtractInfo.scala +++ b/benchmark/src/main/scala/com/wavesplatform/state/ExtractInfo.scala @@ -14,7 +14,7 @@ import scodec.bits.{BitVector, ByteVector} import scorex.account.AddressScheme import scorex.block.Block import scorex.transaction.assets.IssueTransaction -import scorex.transaction.{Authorized, CreateAliasTransaction, DataTransaction, Transaction} +import scorex.transaction.{Authorized, CreateAliasTransactionV1, DataTransaction, Transaction} import scorex.utils.ScorexLogging import scala.collection.JavaConverters._ @@ -65,7 +65,7 @@ object ExtractInfo extends App with ScorexLogging { val aliasTxs = nonEmptyBlocks(benchSettings.aliasesFromHeight) .flatMap(_.transactionData) .collect { - case _: CreateAliasTransaction => true + case _: CreateAliasTransactionV1 => true } val restTxs = nonEmptyBlocks(benchSettings.restTxsFromHeight) @@ -81,7 +81,7 @@ object ExtractInfo extends App with ScorexLogging { } yield sender.toAddress.stringRepr write("accounts", benchSettings.accountsFile, takeUniq(1000, accounts)) - val aliasTxIds = aliasTxs.map(_.asInstanceOf[CreateAliasTransaction].alias.stringRepr) + val aliasTxIds = aliasTxs.map(_.asInstanceOf[CreateAliasTransactionV1].alias.stringRepr) write("aliases", benchSettings.aliasesFile, aliasTxIds.take(1000)) val restTxIds = restTxs.map(_.id().base58) diff --git a/generator/src/main/scala/com.wavesplatform.generator/NarrowTransactionGenerator.scala b/generator/src/main/scala/com.wavesplatform.generator/NarrowTransactionGenerator.scala index 036a14707a7..1d53d842b12 100644 --- a/generator/src/main/scala/com.wavesplatform.generator/NarrowTransactionGenerator.scala +++ b/generator/src/main/scala/com.wavesplatform.generator/NarrowTransactionGenerator.scala @@ -77,7 +77,7 @@ class NarrowTransactionGenerator(settings: Settings, val accounts: Seq[PrivateKe Seq.empty[IssueTransactionV1], Seq.empty[IssueTransactionV1], Seq.empty[LeaseTransactionV1], - Seq.empty[CreateAliasTransaction] + Seq.empty[CreateAliasTransactionV1] )) { case ((allTxsWithValid, validIssueTxs, reissuableIssueTxs, activeLeaseTransactions, aliases), _) => def moreThatStandartFee = 100000L + r.nextInt(100000) @@ -143,10 +143,10 @@ class NarrowTransactionGenerator(settings: Settings, val accounts: Seq[PrivateKe val sender = accounts.find(_.address == lease.sender.address).get logOption(LeaseCancelTransactionV1.create(sender, lease.id(), moreThatStandartFee * 3, ts)) }) - case CreateAliasTransaction => + case CreateAliasTransactionV1 => val sender = randomFrom(accounts).get val aliasString = NarrowTransactionGenerator.generateAlias() - logOption(CreateAliasTransaction.create(sender, Alias.buildWithCurrentNetworkByte(aliasString).right.get, 100000, ts)) + logOption(CreateAliasTransactionV1.create(sender, Alias.buildWithCurrentNetworkByte(aliasString).right.get, 100000, ts)) case MassTransferTransaction => val transferCount = r.nextInt(MassTransferTransaction.MaxTransferCount) val transfers = for (i <- 0 to transferCount) yield { @@ -210,7 +210,7 @@ class NarrowTransactionGenerator(settings: Settings, val accounts: Seq[PrivateKe case Some(tx: LeaseCancelTransaction) => activeLeaseTransactions.filter(_.id != tx.leaseId) case _ => activeLeaseTransactions }, tx match { - case Some(tx: CreateAliasTransaction) => aliases :+ tx + case Some(tx: CreateAliasTransactionV1) => aliases :+ tx case _ => aliases }) } diff --git a/src/main/scala/com/wavesplatform/database/LevelDBWriter.scala b/src/main/scala/com/wavesplatform/database/LevelDBWriter.scala index 890f2cfc3ba..cdc1e11d5b3 100644 --- a/src/main/scala/com/wavesplatform/database/LevelDBWriter.scala +++ b/src/main/scala/com/wavesplatform/database/LevelDBWriter.scala @@ -712,7 +712,7 @@ class LevelDBWriter(writableDB: DB, fs: FunctionalitySettings) extends Caches wi } } - case tx: CreateAliasTransaction => rw.delete(k.addressIdOfAlias(tx.alias)) + case tx: CreateAliasTransactionV1 => rw.delete(k.addressIdOfAlias(tx.alias)) case tx: ExchangeTransaction => rollbackOrderFill(rw, ByteStr(tx.buyOrder.id()), currentHeight) rollbackOrderFill(rw, ByteStr(tx.sellOrder.id()), currentHeight) diff --git a/src/main/scala/com/wavesplatform/state/diffs/CommonValidation.scala b/src/main/scala/com/wavesplatform/state/diffs/CommonValidation.scala index 7fa6432c714..5163370349f 100644 --- a/src/main/scala/com/wavesplatform/state/diffs/CommonValidation.scala +++ b/src/main/scala/com/wavesplatform/state/diffs/CommonValidation.scala @@ -93,26 +93,26 @@ object CommonValidation { ) tx match { - case _: BurnTransaction => Right(tx) - case _: PaymentTransaction => Right(tx) - case _: GenesisTransaction => Right(tx) - case _: TransferTransactionV1 => Right(tx) - case _: IssueTransactionV1 => Right(tx) - case _: ReissueTransactionV1 => Right(tx) - case _: ExchangeTransaction => Right(tx) - case _: LeaseTransactionV1 => Right(tx) - case _: LeaseCancelTransactionV1 => Right(tx) - case _: CreateAliasTransaction => Right(tx) - case _: MassTransferTransaction => activationBarrier(BlockchainFeatures.MassTransfer) - case _: DataTransaction => activationBarrier(BlockchainFeatures.DataTransaction) - case _: SetScriptTransaction => activationBarrier(BlockchainFeatures.SmartAccounts) - case _: TransferTransactionV2 => activationBarrier(BlockchainFeatures.SmartAccounts) - case _: IssueTransactionV2 => activationBarrier(BlockchainFeatures.SmartAccounts) - case _: ReissueTransactionV2 => activationBarrier(BlockchainFeatures.SmartAccounts) + case _: BurnTransaction => Right(tx) + case _: PaymentTransaction => Right(tx) + case _: GenesisTransaction => Right(tx) + case _: TransferTransactionV1 => Right(tx) + case _: IssueTransactionV1 => Right(tx) + case _: ReissueTransactionV1 => Right(tx) + case _: ExchangeTransaction => Right(tx) + case _: LeaseTransactionV1 => Right(tx) + case _: LeaseCancelTransactionV1 => Right(tx) + case _: CreateAliasTransactionV1 => Right(tx) + case _: MassTransferTransaction => activationBarrier(BlockchainFeatures.MassTransfer) + case _: DataTransaction => activationBarrier(BlockchainFeatures.DataTransaction) + case _: SetScriptTransaction => activationBarrier(BlockchainFeatures.SmartAccounts) + case _: TransferTransactionV2 => activationBarrier(BlockchainFeatures.SmartAccounts) + case _: IssueTransactionV2 => activationBarrier(BlockchainFeatures.SmartAccounts) + case _: ReissueTransactionV2 => activationBarrier(BlockchainFeatures.SmartAccounts) case _: LeaseTransactionV2 => activationBarrier(BlockchainFeatures.SmartAccounts) - case _: LeaseCancelTransactionV2 => activationBarrier(BlockchainFeatures.SmartAccounts) - case _: SponsorFeeTransaction => activationBarrier(BlockchainFeatures.FeeSponsorship) - case _ => Left(GenericError("Unknown transaction must be explicitly activated")) + case _: LeaseCancelTransactionV2 =>activationBarrier(BlockchainFeatures.SmartAccounts) + case _: SponsorFeeTransaction => activationBarrier(BlockchainFeatures.FeeSponsorship) + case _ => Left(GenericError("Unknown transaction must be explicitly activated")) } } @@ -145,7 +145,7 @@ object CommonValidation { case _: LeaseCancelTransactionV1 => Right(1) case _: LeaseCancelTransactionV2 => Right(1) case _: ExchangeTransaction => Right(3) - case _: CreateAliasTransaction => Right(1) + case _: CreateAliasTransactionV1 => Right(1) case tx: DataTransaction => Right(1 + (tx.bytes().length - 1) / 1024) case _: SetScriptTransaction => Right(1) case _: TransferTransactionV2 => Right(1) diff --git a/src/main/scala/com/wavesplatform/state/diffs/CreateAliasTransactionDiff.scala b/src/main/scala/com/wavesplatform/state/diffs/CreateAliasTransactionDiff.scala index 8b5eb2473ab..d5135146a09 100644 --- a/src/main/scala/com/wavesplatform/state/diffs/CreateAliasTransactionDiff.scala +++ b/src/main/scala/com/wavesplatform/state/diffs/CreateAliasTransactionDiff.scala @@ -1,12 +1,12 @@ package com.wavesplatform.state.diffs import com.wavesplatform.state.{Diff, LeaseBalance, Portfolio} -import scorex.transaction.{CreateAliasTransaction, ValidationError} +import scorex.transaction.{CreateAliasTransactionV1, ValidationError} import scala.util.Right object CreateAliasTransactionDiff { - def apply(height: Int)(tx: CreateAliasTransaction): Either[ValidationError, Diff] = { + def apply(height: Int)(tx: CreateAliasTransactionV1): Either[ValidationError, Diff] = { Right( Diff(height = height, tx = tx, diff --git a/src/main/scala/com/wavesplatform/state/diffs/TransactionDiffer.scala b/src/main/scala/com/wavesplatform/state/diffs/TransactionDiffer.scala index d572bbc7fa3..08353079a49 100644 --- a/src/main/scala/com/wavesplatform/state/diffs/TransactionDiffer.scala +++ b/src/main/scala/com/wavesplatform/state/diffs/TransactionDiffer.scala @@ -36,7 +36,7 @@ object TransactionDiffer { case ltx: LeaseTransaction => LeaseTransactionsDiff.lease(blockchain, currentBlockHeight)(ltx) case ltx: LeaseCancelTransaction => LeaseTransactionsDiff.leaseCancel(blockchain, settings, currentBlockTimestamp, currentBlockHeight)(ltx) case etx: ExchangeTransaction => ExchangeTransactionDiff(blockchain, currentBlockHeight)(etx) - case atx: CreateAliasTransaction => CreateAliasTransactionDiff(currentBlockHeight)(atx) + case atx: CreateAliasTransactionV1 => CreateAliasTransactionDiff(currentBlockHeight)(atx) case dtx: DataTransaction => DataTransactionDiff(blockchain, currentBlockHeight)(dtx) case sstx: SetScriptTransaction => SetScriptTransactionDiff(currentBlockHeight)(sstx) case stx: SponsorFeeTransaction => AssetTransactionsDiff.sponsor(blockchain, settings, currentBlockTimestamp, currentBlockHeight)(stx) diff --git a/src/main/scala/com/wavesplatform/state/package.scala b/src/main/scala/com/wavesplatform/state/package.scala index 93279920e1a..8bb95adc700 100644 --- a/src/main/scala/com/wavesplatform/state/package.scala +++ b/src/main/scala/com/wavesplatform/state/package.scala @@ -4,7 +4,7 @@ import scorex.account.{Address, AddressOrAlias, Alias} import scorex.block.Block import scorex.transaction.ValidationError.{AliasDoesNotExist, GenericError} import scorex.transaction.lease.{LeaseTransaction, LeaseTransactionV1} -import scorex.transaction.{AssetId, CreateAliasTransaction, Transaction, ValidationError} +import scorex.transaction.{AssetId, CreateAliasTransactionV1, Transaction, ValidationError} import scala.reflect.ClassTag import scala.util.{Left, Right, Try} @@ -72,8 +72,8 @@ package object state { def aliasesOfAddress(address: Address): Seq[Alias] = blockchain - .addressTransactions(address, Set(CreateAliasTransaction.typeId), Int.MaxValue, 0) - .collect { case (_, a: CreateAliasTransaction) => a.alias } + .addressTransactions(address, Set(CreateAliasTransactionV1.typeId), Int.MaxValue, 0) + .collect { case (_, a: CreateAliasTransactionV1) => a.alias } def activeLeases(address: Address): Seq[(Int, LeaseTransaction)] = blockchain diff --git a/src/main/scala/scorex/api/http/TransactionsApiRoute.scala b/src/main/scala/scorex/api/http/TransactionsApiRoute.scala index f809d33d1e5..289bb80d7a6 100644 --- a/src/main/scala/scorex/api/http/TransactionsApiRoute.scala +++ b/src/main/scala/scorex/api/http/TransactionsApiRoute.scala @@ -170,22 +170,22 @@ case class TransactionsApiRoute(settings: RestAPISettings, case None => Left(GenericError(s"Bad transaction type ($typeId) and version ($version)")) case Some(x) => x match { - case IssueTransactionV1 => TransactionFactory.issueAssetV1(jsv.as[IssueV1Request], wallet, time) - case IssueTransactionV2 => TransactionFactory.issueAssetV2(jsv.as[IssueV2Request], wallet, time) - case TransferTransactionV1 => TransactionFactory.transferAssetV1(jsv.as[TransferV1Request], wallet, time) - case TransferTransactionV2 => TransactionFactory.transferAssetV2(jsv.as[TransferV2Request], wallet, time) - case ReissueTransactionV1 => TransactionFactory.reissueAssetV1(jsv.as[ReissueV1Request], wallet, time) - case ReissueTransactionV2 => TransactionFactory.reissueAssetV2(jsv.as[ReissueV2Request], wallet, time) - case BurnTransaction => TransactionFactory.burnAsset(jsv.as[BurnRequest], wallet, time) - case MassTransferTransaction => TransactionFactory.massTransferAsset(jsv.as[MassTransferRequest], wallet, time) + case IssueTransactionV1 => TransactionFactory.issueAssetV1(jsv.as[IssueV1Request], wallet, time) + case IssueTransactionV2 => TransactionFactory.issueAssetV2(jsv.as[IssueV2Request], wallet, time) + case TransferTransactionV1 => TransactionFactory.transferAssetV1(jsv.as[TransferV1Request], wallet, time) + case TransferTransactionV2 => TransactionFactory.transferAssetV2(jsv.as[TransferV2Request], wallet, time) + case ReissueTransactionV1 => TransactionFactory.reissueAssetV1(jsv.as[ReissueV1Request], wallet, time) + case ReissueTransactionV2 => TransactionFactory.reissueAssetV2(jsv.as[ReissueV2Request], wallet, time) + case BurnTransaction => TransactionFactory.burnAsset(jsv.as[BurnRequest], wallet, time) + case MassTransferTransaction => TransactionFactory.massTransferAsset(jsv.as[MassTransferRequest], wallet, time) case LeaseTransactionV1 => TransactionFactory.leaseV1(jsv.as[LeaseV1Request], wallet, time) - case LeaseTransactionV2 => TransactionFactory.leaseV2(jsv.as[LeaseV2Request], wallet, time) - case LeaseCancelTransactionV1 => TransactionFactory.leaseCancelV1(jsv.as[LeaseCancelV1Request], wallet, time) + case LeaseTransactionV2 => TransactionFactory.leaseV2(jsv.as[LeaseV2Request], wallet, time) + case LeaseCancelTransactionV1 => TransactionFactory.leaseCancelV1(jsv.as[LeaseCancelV1Request], wallet, time) case LeaseCancelTransactionV2 => TransactionFactory.leaseCancelV2(jsv.as[LeaseCancelV2Request], wallet, time) - case CreateAliasTransaction => TransactionFactory.alias(jsv.as[CreateAliasRequest], wallet, time) - case DataTransaction => TransactionFactory.data(jsv.as[DataRequest], wallet, time) - case SetScriptTransaction => TransactionFactory.setScript(jsv.as[SetScriptRequest], wallet, time) - case SponsorFeeTransaction => TransactionFactory.sponsor(jsv.as[SponsorFeeRequest], wallet, time) + case CreateAliasTransactionV1 => TransactionFactory.alias(jsv.as[CreateAliasRequest], wallet, time) + case DataTransaction => TransactionFactory.data(jsv.as[DataRequest], wallet, time) + case SetScriptTransaction => TransactionFactory.setScript(jsv.as[SetScriptRequest], wallet, time) + case SponsorFeeTransaction => TransactionFactory.sponsor(jsv.as[SponsorFeeRequest], wallet, time) } } r match { @@ -216,22 +216,22 @@ case class TransactionsApiRoute(settings: RestAPISettings, case None => Left(GenericError(s"Bad transaction type ($typeId) and version ($version)")) case Some(x) => x match { - case IssueTransactionV1 => jsv.as[SignedIssueV1Request].toTx - case IssueTransactionV2 => jsv.as[SignedIssueV2Request].toTx - case TransferTransactionV1 => jsv.as[SignedTransferV1Request].toTx - case TransferTransactionV2 => jsv.as[SignedTransferV2Request].toTx - case MassTransferTransaction => jsv.as[SignedMassTransferRequest].toTx - case ReissueTransactionV1 => jsv.as[SignedReissueV1Request].toTx - case ReissueTransactionV2 => jsv.as[SignedReissueV2Request].toTx - case BurnTransaction => jsv.as[SignedBurnRequest].toTx + case IssueTransactionV1 => jsv.as[SignedIssueV1Request].toTx + case IssueTransactionV2 => jsv.as[SignedIssueV2Request].toTx + case TransferTransactionV1 => jsv.as[SignedTransferV1Request].toTx + case TransferTransactionV2 => jsv.as[SignedTransferV2Request].toTx + case MassTransferTransaction => jsv.as[SignedMassTransferRequest].toTx + case ReissueTransactionV1 => jsv.as[SignedReissueV1Request].toTx + case ReissueTransactionV2 => jsv.as[SignedReissueV2Request].toTx + case BurnTransaction => jsv.as[SignedBurnRequest].toTx case LeaseTransactionV1 => jsv.as[SignedLeaseV1Request].toTx - case LeaseTransactionV2 => jsv.as[SignedLeaseV2Request].toTx - case LeaseCancelTransactionV1 => jsv.as[SignedLeaseCancelV1Request].toTx + case LeaseTransactionV2 => jsv.as[SignedLeaseV2Request].toTx + case LeaseCancelTransactionV1 => jsv.as[SignedLeaseCancelV1Request].toTx case LeaseCancelTransactionV2 => jsv.as[SignedLeaseCancelV2Request].toTx - case CreateAliasTransaction => jsv.as[SignedCreateAliasRequest].toTx - case DataTransaction => jsv.as[SignedDataRequest].toTx - case SetScriptTransaction => jsv.as[SignedSetScriptRequest].toTx - case SponsorFeeTransaction => jsv.as[SignedSponsorFeeRequest].toTx + case CreateAliasTransactionV1 => jsv.as[SignedCreateAliasRequest].toTx + case DataTransaction => jsv.as[SignedDataRequest].toTx + case SetScriptTransaction => jsv.as[SignedSetScriptRequest].toTx + case SponsorFeeTransaction => jsv.as[SignedSponsorFeeRequest].toTx } } diff --git a/src/main/scala/scorex/api/http/alias/SignedCreateAliasRequest.scala b/src/main/scala/scorex/api/http/alias/SignedCreateAliasRequest.scala index e33125e76c1..05b04832ff3 100644 --- a/src/main/scala/scorex/api/http/alias/SignedCreateAliasRequest.scala +++ b/src/main/scala/scorex/api/http/alias/SignedCreateAliasRequest.scala @@ -5,7 +5,7 @@ import play.api.libs.json.{Format, Json} import scorex.account.{Alias, PublicKeyAccount} import scorex.api.http.BroadcastRequest import scorex.transaction.TransactionParsers.SignatureStringLength -import scorex.transaction.{CreateAliasTransaction, ValidationError} +import scorex.transaction.{CreateAliasTransactionV1, ValidationError} case class SignedCreateAliasRequest(@ApiModelProperty(value = "Base58 encoded sender public key", required = true) senderPublicKey: String, @@ -18,12 +18,12 @@ case class SignedCreateAliasRequest(@ApiModelProperty(value = "Base58 encoded se @ApiModelProperty(required = true) signature: String) extends BroadcastRequest { - def toTx: Either[ValidationError, CreateAliasTransaction] = + def toTx: Either[ValidationError, CreateAliasTransactionV1] = for { _sender <- PublicKeyAccount.fromBase58String(senderPublicKey) _signature <- parseBase58(signature, "invalid.signature", SignatureStringLength) _alias <- Alias.buildWithCurrentNetworkByte(alias) - _t <- CreateAliasTransaction.create(_sender, _alias, fee, timestamp, _signature) + _t <- CreateAliasTransactionV1.create(_sender, _alias, fee, timestamp, _signature) } yield _t } diff --git a/src/main/scala/scorex/transaction/CreateAliasTransaction.scala b/src/main/scala/scorex/transaction/CreateAliasTransaction.scala deleted file mode 100644 index 3c1c3c511d9..00000000000 --- a/src/main/scala/scorex/transaction/CreateAliasTransaction.scala +++ /dev/null @@ -1,65 +0,0 @@ -package scorex.transaction - -import com.google.common.primitives.{Bytes, Longs} -import com.wavesplatform.crypto -import com.wavesplatform.state.ByteStr -import monix.eval.Coeval -import play.api.libs.json.{JsObject, Json} -import scorex.account._ -import scorex.crypto.signatures.Curve25519.{KeyLength, SignatureLength} -import scorex.serialization.Deser - -import scala.util.{Failure, Success, Try} - -case class CreateAliasTransaction private (sender: PublicKeyAccount, alias: Alias, fee: Long, timestamp: Long, signature: ByteStr) - extends SignedTransaction { - - override val builder: TransactionParser = CreateAliasTransaction - override val id: Coeval[AssetId] = Coeval.evalOnce(ByteStr(crypto.fastHash(builder.typeId +: alias.bytes.arr))) - - override val bodyBytes: Coeval[Array[Byte]] = Coeval.evalOnce( - Bytes - .concat(Array(builder.typeId), sender.publicKey, Deser.serializeArray(alias.bytes.arr), Longs.toByteArray(fee), Longs.toByteArray(timestamp))) - - override val json: Coeval[JsObject] = Coeval.evalOnce( - jsonBase() ++ Json.obj( - "alias" -> alias.name, - "fee" -> fee, - "timestamp" -> timestamp - )) - - override val assetFee: (Option[AssetId], Long) = (None, fee) - override val bytes: Coeval[Array[Byte]] = Coeval.evalOnce(Bytes.concat(bodyBytes(), signature.arr)) - -} - -object CreateAliasTransaction extends TransactionParserFor[CreateAliasTransaction] with TransactionParser.HardcodedVersion1 { - - override val typeId: Byte = 10 - - override protected def parseTail(version: Byte, bytes: Array[Byte]): Try[TransactionT] = - Try { - val sender = PublicKeyAccount(bytes.slice(0, KeyLength)) - val (aliasBytes, aliasEnd) = Deser.parseArraySize(bytes, KeyLength) - (for { - alias <- Alias.fromBytes(aliasBytes) - fee = Longs.fromByteArray(bytes.slice(aliasEnd, aliasEnd + 8)) - timestamp = Longs.fromByteArray(bytes.slice(aliasEnd + 8, aliasEnd + 16)) - signature = ByteStr(bytes.slice(aliasEnd + 16, aliasEnd + 16 + SignatureLength)) - tx <- CreateAliasTransaction.create(sender, alias, fee, timestamp, signature) - } yield tx).fold(left => Failure(new Exception(left.toString)), right => Success(right)) - }.flatten - - def create(sender: PublicKeyAccount, alias: Alias, fee: Long, timestamp: Long, signature: ByteStr): Either[ValidationError, TransactionT] = - if (fee <= 0) { - Left(ValidationError.InsufficientFee()) - } else { - Right(CreateAliasTransaction(sender, alias, fee, timestamp, signature)) - } - - def create(sender: PrivateKeyAccount, alias: Alias, fee: Long, timestamp: Long): Either[ValidationError, TransactionT] = { - create(sender, alias, fee, timestamp, ByteStr.empty).right.map { unsigned => - unsigned.copy(signature = ByteStr(crypto.sign(sender, unsigned.bodyBytes()))) - } - } -} diff --git a/src/main/scala/scorex/transaction/CreateAliasTransactionV1.scala b/src/main/scala/scorex/transaction/CreateAliasTransactionV1.scala new file mode 100644 index 00000000000..30bdbc7011e --- /dev/null +++ b/src/main/scala/scorex/transaction/CreateAliasTransactionV1.scala @@ -0,0 +1,97 @@ +package scorex.transaction + +import com.google.common.primitives.{Bytes, Longs} +import com.wavesplatform.crypto +import com.wavesplatform.state.ByteStr +import monix.eval.Coeval +import play.api.libs.json.{JsObject, Json} +import scorex.account._ +import scorex.crypto.signatures.Curve25519.{KeyLength, SignatureLength} +import scorex.serialization.Deser +import scala.util.{Failure, Success, Try} + +trait CreateAliasTransaction extends ProvenTransaction { + def version: Byte + def alias: Alias + def fee: Long + def timestamp: Long + + override val assetFee: (Option[AssetId], Long) = (None, fee) + + override val json: Coeval[JsObject] = Coeval.evalOnce( + jsonBase() ++ Json.obj( + "version" -> version, + "alias" -> alias.name, + "fee" -> fee, + "timestamp" -> timestamp + )) + + val baseBytes: Coeval[Array[Byte]] = Coeval.evalOnce { + Bytes.concat( + sender.publicKey, + Deser.serializeArray(alias.bytes.arr), + Longs.toByteArray(fee), + Longs.toByteArray(timestamp) + ) + } +} + +object CreateAliasTransaction { + val typeId: Byte = 10 + + def parseBase(start: Int, bytes: Array[Byte]): Try[(PublicKeyAccount, Alias, Long, Long, Int)] = { + for { + sender <- Try(PublicKeyAccount(bytes.slice(start, start + KeyLength))) + (aliasBytes, aliasEnd) = Deser.parseArraySize(bytes, start + KeyLength) + alias <- Alias.fromBytes(aliasBytes).fold(err => Failure(new Exception(err.toString)), Success.apply) + fee <- Try(Longs.fromByteArray(bytes.slice(aliasEnd, aliasEnd + 8))) + timestamp <- Try(Longs.fromByteArray(bytes.slice(aliasEnd + 8, aliasEnd + 16))) + } yield (sender, alias, fee, timestamp, aliasEnd + 16) + } +} + +case class CreateAliasTransactionV1 private (sender: PublicKeyAccount, alias: Alias, fee: Long, timestamp: Long, signature: ByteStr) + extends CreateAliasTransaction + with SignedTransaction { + + override def version: Byte = 1 + override val builder: TransactionParser = CreateAliasTransactionV1 + + override val id: Coeval[AssetId] = + Coeval.evalOnce(ByteStr(crypto.fastHash(builder.typeId +: alias.bytes.arr))) + + override val bodyBytes: Coeval[Array[Byte]] = + baseBytes.map(base => Bytes.concat(Array(builder.typeId), base)) + + override val bytes: Coeval[Array[Byte]] = + bodyBytes.map(body => Bytes.concat(body, signature.arr)) +} + +object CreateAliasTransactionV1 extends TransactionParserFor[CreateAliasTransactionV1] with TransactionParser.HardcodedVersion1 { + + override val typeId: Byte = CreateAliasTransaction.typeId + + override protected def parseTail(version: Byte, bytes: Array[Byte]): Try[TransactionT] = + Try { + for { + (sender, alias, fee, timestamp, end) <- CreateAliasTransaction.parseBase(0, bytes) + signature = ByteStr(bytes.slice(end, end + SignatureLength)) + tx <- CreateAliasTransactionV1 + .create(sender, alias, fee, timestamp, signature) + .fold(left => Failure(new Exception(left.toString)), right => Success(right)) + } yield tx + }.flatten + + def create(sender: PublicKeyAccount, alias: Alias, fee: Long, timestamp: Long, signature: ByteStr): Either[ValidationError, TransactionT] = + if (fee <= 0) { + Left(ValidationError.InsufficientFee()) + } else { + Right(CreateAliasTransactionV1(sender, alias, fee, timestamp, signature)) + } + + def create(sender: PrivateKeyAccount, alias: Alias, fee: Long, timestamp: Long): Either[ValidationError, TransactionT] = { + create(sender, alias, fee, timestamp, ByteStr.empty).right.map { unsigned => + unsigned.copy(signature = ByteStr(crypto.sign(sender, unsigned.bodyBytes()))) + } + } +} diff --git a/src/main/scala/scorex/transaction/TransactionFactory.scala b/src/main/scala/scorex/transaction/TransactionFactory.scala index 2dde60075e0..104e5ace23f 100644 --- a/src/main/scala/scorex/transaction/TransactionFactory.scala +++ b/src/main/scala/scorex/transaction/TransactionFactory.scala @@ -157,12 +157,12 @@ object TransactionFactory { timestamp) } yield tx - def alias(request: CreateAliasRequest, wallet: Wallet, time: Time): Either[ValidationError, CreateAliasTransaction] = + def alias(request: CreateAliasRequest, wallet: Wallet, time: Time): Either[ValidationError, CreateAliasTransactionV1] = for { senderPrivateKey <- wallet.findWallet(request.sender) alias <- Alias.buildWithCurrentNetworkByte(request.alias) timestamp = request.timestamp.getOrElse(time.getTimestamp()) - tx <- CreateAliasTransaction.create(senderPrivateKey, alias, request.fee, timestamp) + tx <- CreateAliasTransactionV1.create(senderPrivateKey, alias, request.fee, timestamp) } yield tx def reissueAssetV1(request: ReissueV1Request, wallet: Wallet, time: Time): Either[ValidationError, ReissueTransactionV1] = diff --git a/src/main/scala/scorex/transaction/TransactionParsers.scala b/src/main/scala/scorex/transaction/TransactionParsers.scala index 8d90e64672d..e0a0be78d6d 100644 --- a/src/main/scala/scorex/transaction/TransactionParsers.scala +++ b/src/main/scala/scorex/transaction/TransactionParsers.scala @@ -27,7 +27,7 @@ object TransactionParsers { ExchangeTransaction, LeaseTransactionV1, LeaseCancelTransactionV1, - CreateAliasTransaction, + CreateAliasTransactionV1, MassTransferTransaction ).map { x => x.typeId -> x diff --git a/src/main/scala/scorex/transaction/smart/RealTransactionWrapper.scala b/src/main/scala/scorex/transaction/smart/RealTransactionWrapper.scala index a2b729b2ee4..87428d4bc03 100644 --- a/src/main/scala/scorex/transaction/smart/RealTransactionWrapper.scala +++ b/src/main/scala/scorex/transaction/smart/RealTransactionWrapper.scala @@ -58,7 +58,7 @@ case class RealTransactionWrapper(tx: Transaction) extends com.wavesplatform.lan case g: LeaseTransaction => Right(g.amount) case g: TransferTransaction => Right(g.amount) case g: ExchangeTransaction => Right(g.amount) - case _: CreateAliasTransaction => Left("Transaction doesn't contain amount") + case _: CreateAliasTransactionV1 => Left("Transaction doesn't contain amount") case _: SetScriptTransaction => Left("Transaction doesn't contain amount") case _: MassTransferTransaction => Left("Transaction doesn't contain amount") case _: LeaseCancelTransaction => Left("Transaction doesn't contain amount") @@ -71,7 +71,7 @@ case class RealTransactionWrapper(tx: Transaction) extends com.wavesplatform.lan override def timestamp: Long = tx.timestamp override def aliasText: Either[String, String] = tx match { - case g: CreateAliasTransaction => Right(g.alias.name) + case g: CreateAliasTransactionV1 => Right(g.alias.name) case _ => Left("Transaction doesn't contain alias text") } diff --git a/src/test/scala/com/wavesplatform/TransactionGen.scala b/src/test/scala/com/wavesplatform/TransactionGen.scala index 87b1177afa6..67deecae9f1 100644 --- a/src/test/scala/com/wavesplatform/TransactionGen.scala +++ b/src/test/scala/com/wavesplatform/TransactionGen.scala @@ -327,11 +327,11 @@ trait TransactionGenBase extends ScriptGen { val MinIssueFee = 100000000 - val createAliasGen: Gen[CreateAliasTransaction] = for { + val createAliasGen: Gen[CreateAliasTransactionV1] = for { timestamp: Long <- positiveLongGen sender: PrivateKeyAccount <- accountGen alias: Alias <- aliasGen - } yield CreateAliasTransaction.create(sender, alias, MinIssueFee, timestamp).right.get + } yield CreateAliasTransactionV1.create(sender, alias, MinIssueFee, timestamp).right.get val issueParamGen = for { sender: PrivateKeyAccount <- accountGen diff --git a/src/test/scala/com/wavesplatform/state/RollbackSpec.scala b/src/test/scala/com/wavesplatform/state/RollbackSpec.scala index 5aa90eb10aa..7382e847c6e 100644 --- a/src/test/scala/com/wavesplatform/state/RollbackSpec.scala +++ b/src/test/scala/com/wavesplatform/state/RollbackSpec.scala @@ -13,7 +13,7 @@ import scorex.transaction.assets.{IssueTransactionV1, ReissueTransactionV1} import scorex.transaction.lease.{LeaseCancelTransactionV1, LeaseTransactionV1} import scorex.transaction.smart.SetScriptTransaction import scorex.transaction.transfer._ -import scorex.transaction.{CreateAliasTransaction, DataTransaction, GenesisTransaction} +import scorex.transaction.{CreateAliasTransactionV1, DataTransaction, GenesisTransaction} class RollbackSpec extends FreeSpec with Matchers with WithState with TransactionGen with PropertyChecks with NoShrink { private val time = new TestTime @@ -187,7 +187,7 @@ class RollbackSpec extends FreeSpec with Matchers with WithState with Transactio TestBlock.create( nextTs, genesisBlockId, - Seq(CreateAliasTransaction.create(sender, alias, 1, nextTs).explicitGet()) + Seq(CreateAliasTransactionV1.create(sender, alias, 1, nextTs).explicitGet()) )) d.blockchainUpdater.resolveAlias(alias) should contain(sender.toAddress) diff --git a/src/test/scala/com/wavesplatform/state/diffs/CreateAliasTransactionDiffTest.scala b/src/test/scala/com/wavesplatform/state/diffs/CreateAliasTransactionDiffTest.scala index 1612e66ad4a..a3f92569bb0 100644 --- a/src/test/scala/com/wavesplatform/state/diffs/CreateAliasTransactionDiffTest.scala +++ b/src/test/scala/com/wavesplatform/state/diffs/CreateAliasTransactionDiffTest.scala @@ -9,12 +9,12 @@ import org.scalatest.{Matchers, PropSpec} import scorex.account.PrivateKeyAccount import scorex.lagonaki.mocks.TestBlock import scorex.transaction.assets.IssueTransaction -import scorex.transaction.{CreateAliasTransaction, GenesisTransaction} +import scorex.transaction.{CreateAliasTransactionV1, GenesisTransaction} class CreateAliasTransactionDiffTest extends PropSpec with PropertyChecks with Matchers with TransactionGen with NoShrink { val preconditionsAndAliasCreations - : Gen[(GenesisTransaction, CreateAliasTransaction, CreateAliasTransaction, CreateAliasTransaction, CreateAliasTransaction)] = for { + : Gen[(GenesisTransaction, CreateAliasTransactionV1, CreateAliasTransactionV1, CreateAliasTransactionV1, CreateAliasTransactionV1)] = for { master <- accountGen ts <- timestampGen genesis: GenesisTransaction = GenesisTransaction.create(master, ENOUGH_AMT, ts).right.get @@ -22,10 +22,10 @@ class CreateAliasTransactionDiffTest extends PropSpec with PropertyChecks with M alias2 <- aliasGen suchThat (_.name != alias.name) fee <- smallFeeGen other: PrivateKeyAccount <- accountGen - aliasTx = CreateAliasTransaction.create(master, alias, fee, ts).right.get - sameAliasTx = CreateAliasTransaction.create(master, alias, fee + 1, ts).right.get - sameAliasOtherSenderTx = CreateAliasTransaction.create(other, alias, fee + 2, ts).right.get - anotherAliasTx = CreateAliasTransaction.create(master, alias2, fee + 3, ts).right.get + aliasTx = CreateAliasTransactionV1.create(master, alias, fee, ts).right.get + sameAliasTx = CreateAliasTransactionV1.create(master, alias, fee + 1, ts).right.get + sameAliasOtherSenderTx = CreateAliasTransactionV1.create(other, alias, fee + 2, ts).right.get + anotherAliasTx = CreateAliasTransactionV1.create(master, alias2, fee + 3, ts).right.get } yield (genesis, aliasTx, sameAliasTx, sameAliasOtherSenderTx, anotherAliasTx) property("can create and resolve aliases preserving waves invariant") { @@ -73,7 +73,7 @@ class CreateAliasTransactionDiffTest extends PropSpec with PropertyChecks with M maybeFeeAsset <- Gen.oneOf(maybeAsset, maybeAsset2) alias <- aliasGen fee <- smallFeeGen - aliasTx = CreateAliasTransaction.create(aliasedRecipient, alias, fee, ts).right.get + aliasTx = CreateAliasTransactionV1.create(aliasedRecipient, alias, fee, ts).right.get transfer <- transferGeneratorP(master, alias, maybeAsset.map(_.id()), maybeFeeAsset.map(_.id())) lease <- leaseAndCancelGeneratorP(master, alias, master).map(_._1) } yield (gen, gen2, issue1, issue2, aliasTx, transfer, lease) diff --git a/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/AddressFromRecipientScenarioTest.scala b/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/AddressFromRecipientScenarioTest.scala index 3e210244f7f..95b3704135b 100644 --- a/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/AddressFromRecipientScenarioTest.scala +++ b/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/AddressFromRecipientScenarioTest.scala @@ -15,11 +15,11 @@ import scorex.account.{AddressOrAlias, AddressScheme, PrivateKeyAccount} import scorex.lagonaki.mocks.TestBlock import scorex.transaction.smart.BlockchainContext import scorex.transaction.transfer._ -import scorex.transaction.{CreateAliasTransaction, GenesisTransaction, Transaction} +import scorex.transaction.{CreateAliasTransactionV1, GenesisTransaction, Transaction} class AddressFromRecipientScenarioTest extends PropSpec with PropertyChecks with Matchers with TransactionGen with NoShrink { - val preconditionsAndAliasCreations: Gen[(Seq[GenesisTransaction], CreateAliasTransaction, TransferTransactionV1, TransferTransactionV1)] = for { + val preconditionsAndAliasCreations: Gen[(Seq[GenesisTransaction], CreateAliasTransactionV1, TransferTransactionV1, TransferTransactionV1)] = for { master <- accountGen ts <- timestampGen other: PrivateKeyAccount <- accountGen @@ -27,7 +27,7 @@ class AddressFromRecipientScenarioTest extends PropSpec with PropertyChecks with genesis2: GenesisTransaction = GenesisTransaction.create(other, ENOUGH_AMT, ts).right.get alias <- aliasGen fee <- smallFeeGen - aliasTx = CreateAliasTransaction.create(other, alias, fee, ts).right.get + aliasTx = CreateAliasTransactionV1.create(other, alias, fee, ts).right.get transferViaAddress <- transferGeneratorP(master, other, None, None) transferViaAlias <- transferGeneratorP(master, AddressOrAlias.fromBytes(alias.bytes.arr, 0).right.get._1, None, None) } yield (Seq(genesis1, genesis2), aliasTx, transferViaAddress, transferViaAlias) diff --git a/src/test/scala/scorex/transaction/CreateAliasTransactionSpecification.scala b/src/test/scala/scorex/transaction/CreateAliasTransactionSpecification.scala index 07ca4f45bfd..e419c4e120e 100644 --- a/src/test/scala/scorex/transaction/CreateAliasTransactionSpecification.scala +++ b/src/test/scala/scorex/transaction/CreateAliasTransactionSpecification.scala @@ -8,29 +8,29 @@ import scorex.account.{Alias, PrivateKeyAccount} class CreateAliasTransactionSpecification extends PropSpec with PropertyChecks with Matchers with TransactionGen { property("CreateAliasTransaction serialization roundtrip") { - forAll(createAliasGen) { tx: CreateAliasTransaction => - val recovered = CreateAliasTransaction.parseBytes(tx.bytes()).get + forAll(createAliasGen) { tx: CreateAliasTransactionV1 => + val recovered = CreateAliasTransactionV1.parseBytes(tx.bytes()).get assertTxs(recovered, tx) } } property("CreateAliasTransaction serialization from TypedTransaction") { - forAll(createAliasGen) { tx: CreateAliasTransaction => + forAll(createAliasGen) { tx: CreateAliasTransactionV1 => val recovered = TransactionParsers.parseBytes(tx.bytes()).get - assertTxs(recovered.asInstanceOf[CreateAliasTransaction], tx) + assertTxs(recovered.asInstanceOf[CreateAliasTransactionV1], tx) } } property("The same aliases from different senders have the same id") { forAll(accountGen, accountGen, aliasGen, timestampGen) { case (a1: PrivateKeyAccount, a2: PrivateKeyAccount, a: Alias, t: Long) => - val tx1 = CreateAliasTransaction.create(a1, a, MinIssueFee, t).right.get - val tx2 = CreateAliasTransaction.create(a2, a, MinIssueFee, t).right.get + val tx1 = CreateAliasTransactionV1.create(a1, a, MinIssueFee, t).right.get + val tx2 = CreateAliasTransactionV1.create(a2, a, MinIssueFee, t).right.get tx1.id() shouldBe tx2.id() } } - private def assertTxs(first: CreateAliasTransaction, second: CreateAliasTransaction): Unit = { + private def assertTxs(first: CreateAliasTransactionV1, second: CreateAliasTransactionV1): Unit = { first.sender.address shouldEqual second.sender.address first.timestamp shouldEqual second.timestamp first.fee shouldEqual second.fee diff --git a/src/test/scala/scorex/transaction/FeeCalculatorSpecification.scala b/src/test/scala/scorex/transaction/FeeCalculatorSpecification.scala index b7b3e7803b3..aa7102a29b7 100644 --- a/src/test/scala/scorex/transaction/FeeCalculatorSpecification.scala +++ b/src/test/scala/scorex/transaction/FeeCalculatorSpecification.scala @@ -138,7 +138,7 @@ class FeeCalculatorSpecification extends PropSpec with PropertyChecks with Match property("Create alias transaction") { val feeCalc = new FeeCalculator(mySettings, noScriptBlockchain) - forAll(createAliasGen) { tx: CreateAliasTransaction => + forAll(createAliasGen) { tx: CreateAliasTransactionV1 => feeCalc.enoughFee(tx) shouldBeRightIf (tx.fee >= 600000) } } From 39dff7a5e8c3ee9a51c0a8e36ba8fae49834c1b4 Mon Sep 17 00:00:00 2001 From: alexandr Date: Sat, 28 Apr 2018 16:23:29 +0300 Subject: [PATCH 2/4] NODE-496: Proof based CreateAliasTransaction and tests --- .../NarrowTransactionGenerator.scala | 4 +- .../wavesplatform/it/api/AsyncHttpApi.scala | 4 +- .../database/LevelDBWriter.scala | 2 +- .../state/diffs/CommonValidation.scala | 5 +- .../diffs/CreateAliasTransactionDiff.scala | 4 +- .../state/diffs/TransactionDiffer.scala | 2 +- .../com/wavesplatform/state/package.scala | 3 +- .../api/http/TransactionsApiRoute.scala | 8 ++- .../scorex/api/http/alias/AliasApiRoute.scala | 2 +- .../http/alias/AliasBroadcastApiRoute.scala | 5 +- .../api/http/alias/CreateAliasRequest.scala | 16 ----- .../api/http/alias/CreateAliasV1Request.scala | 16 +++++ .../api/http/alias/CreateAliasV2Request.scala | 18 +++++ .../http/alias/SignedCreateAliasRequest.scala | 32 --------- .../alias/SignedCreateAliasV1Request.scala | 32 +++++++++ .../alias/SignedCreateAliasV2Request.scala | 35 ++++++++++ .../transaction/CreateAliasTransaction.scala | 50 ++++++++++++++ .../CreateAliasTransactionV1.scala | 47 +------------ .../CreateAliasTransactionV2.scala | 69 +++++++++++++++++++ .../transaction/TransactionFactory.scala | 12 +++- .../transaction/TransactionParsers.scala | 1 + .../smart/RealTransactionWrapper.scala | 4 +- .../scala/com/wavesplatform/RequestGen.scala | 6 +- .../com/wavesplatform/TransactionGen.scala | 21 +++++- .../http/AliasBroadcastRouteSpec.scala | 4 +- .../CreateAliasTransactionDiffTest.scala | 25 ++++--- .../AddressFromRecipientScenarioTest.scala | 10 +-- .../CreateAliasTransactionSpecification.scala | 18 ++--- .../FeeCalculatorSpecification.scala | 2 +- .../api/http/alias/AliasRequestTests.scala | 10 +-- 30 files changed, 312 insertions(+), 155 deletions(-) delete mode 100644 src/main/scala/scorex/api/http/alias/CreateAliasRequest.scala create mode 100644 src/main/scala/scorex/api/http/alias/CreateAliasV1Request.scala create mode 100644 src/main/scala/scorex/api/http/alias/CreateAliasV2Request.scala delete mode 100644 src/main/scala/scorex/api/http/alias/SignedCreateAliasRequest.scala create mode 100644 src/main/scala/scorex/api/http/alias/SignedCreateAliasV1Request.scala create mode 100644 src/main/scala/scorex/api/http/alias/SignedCreateAliasV2Request.scala create mode 100644 src/main/scala/scorex/transaction/CreateAliasTransaction.scala create mode 100644 src/main/scala/scorex/transaction/CreateAliasTransactionV2.scala diff --git a/generator/src/main/scala/com.wavesplatform.generator/NarrowTransactionGenerator.scala b/generator/src/main/scala/com.wavesplatform.generator/NarrowTransactionGenerator.scala index 1d53d842b12..7b765a6b704 100644 --- a/generator/src/main/scala/com.wavesplatform.generator/NarrowTransactionGenerator.scala +++ b/generator/src/main/scala/com.wavesplatform.generator/NarrowTransactionGenerator.scala @@ -77,7 +77,7 @@ class NarrowTransactionGenerator(settings: Settings, val accounts: Seq[PrivateKe Seq.empty[IssueTransactionV1], Seq.empty[IssueTransactionV1], Seq.empty[LeaseTransactionV1], - Seq.empty[CreateAliasTransactionV1] + Seq.empty[CreateAliasTransaction] )) { case ((allTxsWithValid, validIssueTxs, reissuableIssueTxs, activeLeaseTransactions, aliases), _) => def moreThatStandartFee = 100000L + r.nextInt(100000) @@ -210,7 +210,7 @@ class NarrowTransactionGenerator(settings: Settings, val accounts: Seq[PrivateKe case Some(tx: LeaseCancelTransaction) => activeLeaseTransactions.filter(_.id != tx.leaseId) case _ => activeLeaseTransactions }, tx match { - case Some(tx: CreateAliasTransactionV1) => aliases :+ tx + case Some(tx: CreateAliasTransaction) => aliases :+ tx case _ => aliases }) } diff --git a/it/src/main/scala/com/wavesplatform/it/api/AsyncHttpApi.scala b/it/src/main/scala/com/wavesplatform/it/api/AsyncHttpApi.scala index 1d9e60333ac..1e7e93dd0a4 100644 --- a/it/src/main/scala/com/wavesplatform/it/api/AsyncHttpApi.scala +++ b/it/src/main/scala/com/wavesplatform/it/api/AsyncHttpApi.scala @@ -20,7 +20,7 @@ import org.scalatest.{Assertion, Assertions, Matchers} import play.api.libs.json.Json.{parse, stringify, toJson} import play.api.libs.json._ import scorex.api.http.PeersApiRoute.{ConnectReq, connectFormat} -import scorex.api.http.alias.CreateAliasRequest +import scorex.api.http.alias.CreateAliasV1Request import scorex.api.http.assets._ import scorex.api.http.leasing.{LeaseCancelV1Request, LeaseV1Request, SignedLeaseCancelV1Request, SignedLeaseV1Request} import scorex.api.http.{AddressApiRoute, ApiErrorResponse, DataRequest} @@ -355,7 +355,7 @@ object AsyncHttpApi extends Assertions { } def createAlias(targetAddress: String, alias: String, fee: Long): Future[Transaction] = - postJson("/alias/create", CreateAliasRequest(targetAddress, alias, fee)).as[Transaction] + postJson("/alias/create", CreateAliasV1Request(targetAddress, alias, fee)).as[Transaction] def aliasByAddress(targetAddress: String): Future[Seq[String]] = get(s"/alias/by-address/$targetAddress").as[Seq[String]] diff --git a/src/main/scala/com/wavesplatform/database/LevelDBWriter.scala b/src/main/scala/com/wavesplatform/database/LevelDBWriter.scala index cdc1e11d5b3..890f2cfc3ba 100644 --- a/src/main/scala/com/wavesplatform/database/LevelDBWriter.scala +++ b/src/main/scala/com/wavesplatform/database/LevelDBWriter.scala @@ -712,7 +712,7 @@ class LevelDBWriter(writableDB: DB, fs: FunctionalitySettings) extends Caches wi } } - case tx: CreateAliasTransactionV1 => rw.delete(k.addressIdOfAlias(tx.alias)) + case tx: CreateAliasTransaction => rw.delete(k.addressIdOfAlias(tx.alias)) case tx: ExchangeTransaction => rollbackOrderFill(rw, ByteStr(tx.buyOrder.id()), currentHeight) rollbackOrderFill(rw, ByteStr(tx.sellOrder.id()), currentHeight) diff --git a/src/main/scala/com/wavesplatform/state/diffs/CommonValidation.scala b/src/main/scala/com/wavesplatform/state/diffs/CommonValidation.scala index 5163370349f..4d16348451e 100644 --- a/src/main/scala/com/wavesplatform/state/diffs/CommonValidation.scala +++ b/src/main/scala/com/wavesplatform/state/diffs/CommonValidation.scala @@ -111,7 +111,8 @@ object CommonValidation { case _: ReissueTransactionV2 => activationBarrier(BlockchainFeatures.SmartAccounts) case _: LeaseTransactionV2 => activationBarrier(BlockchainFeatures.SmartAccounts) case _: LeaseCancelTransactionV2 =>activationBarrier(BlockchainFeatures.SmartAccounts) - case _: SponsorFeeTransaction => activationBarrier(BlockchainFeatures.FeeSponsorship) + case _: CreateAliasTransactionV2 => activationBarrier(BlockchainFeatures.SmartAccounts) + case _:SponsorFeeTransaction => activationBarrier(BlockchainFeatures.FeeSponsorship) case _ => Left(GenericError("Unknown transaction must be explicitly activated")) } } @@ -145,7 +146,7 @@ object CommonValidation { case _: LeaseCancelTransactionV1 => Right(1) case _: LeaseCancelTransactionV2 => Right(1) case _: ExchangeTransaction => Right(3) - case _: CreateAliasTransactionV1 => Right(1) + case _: CreateAliasTransactionV1 => Right(1) case tx: DataTransaction => Right(1 + (tx.bytes().length - 1) / 1024) case _: SetScriptTransaction => Right(1) case _: TransferTransactionV2 => Right(1) diff --git a/src/main/scala/com/wavesplatform/state/diffs/CreateAliasTransactionDiff.scala b/src/main/scala/com/wavesplatform/state/diffs/CreateAliasTransactionDiff.scala index d5135146a09..8b5eb2473ab 100644 --- a/src/main/scala/com/wavesplatform/state/diffs/CreateAliasTransactionDiff.scala +++ b/src/main/scala/com/wavesplatform/state/diffs/CreateAliasTransactionDiff.scala @@ -1,12 +1,12 @@ package com.wavesplatform.state.diffs import com.wavesplatform.state.{Diff, LeaseBalance, Portfolio} -import scorex.transaction.{CreateAliasTransactionV1, ValidationError} +import scorex.transaction.{CreateAliasTransaction, ValidationError} import scala.util.Right object CreateAliasTransactionDiff { - def apply(height: Int)(tx: CreateAliasTransactionV1): Either[ValidationError, Diff] = { + def apply(height: Int)(tx: CreateAliasTransaction): Either[ValidationError, Diff] = { Right( Diff(height = height, tx = tx, diff --git a/src/main/scala/com/wavesplatform/state/diffs/TransactionDiffer.scala b/src/main/scala/com/wavesplatform/state/diffs/TransactionDiffer.scala index 08353079a49..d572bbc7fa3 100644 --- a/src/main/scala/com/wavesplatform/state/diffs/TransactionDiffer.scala +++ b/src/main/scala/com/wavesplatform/state/diffs/TransactionDiffer.scala @@ -36,7 +36,7 @@ object TransactionDiffer { case ltx: LeaseTransaction => LeaseTransactionsDiff.lease(blockchain, currentBlockHeight)(ltx) case ltx: LeaseCancelTransaction => LeaseTransactionsDiff.leaseCancel(blockchain, settings, currentBlockTimestamp, currentBlockHeight)(ltx) case etx: ExchangeTransaction => ExchangeTransactionDiff(blockchain, currentBlockHeight)(etx) - case atx: CreateAliasTransactionV1 => CreateAliasTransactionDiff(currentBlockHeight)(atx) + case atx: CreateAliasTransaction => CreateAliasTransactionDiff(currentBlockHeight)(atx) case dtx: DataTransaction => DataTransactionDiff(blockchain, currentBlockHeight)(dtx) case sstx: SetScriptTransaction => SetScriptTransactionDiff(currentBlockHeight)(sstx) case stx: SponsorFeeTransaction => AssetTransactionsDiff.sponsor(blockchain, settings, currentBlockTimestamp, currentBlockHeight)(stx) diff --git a/src/main/scala/com/wavesplatform/state/package.scala b/src/main/scala/com/wavesplatform/state/package.scala index 8bb95adc700..4da42c8699a 100644 --- a/src/main/scala/com/wavesplatform/state/package.scala +++ b/src/main/scala/com/wavesplatform/state/package.scala @@ -3,6 +3,7 @@ package com.wavesplatform import scorex.account.{Address, AddressOrAlias, Alias} import scorex.block.Block import scorex.transaction.ValidationError.{AliasDoesNotExist, GenericError} +import scorex.transaction._ import scorex.transaction.lease.{LeaseTransaction, LeaseTransactionV1} import scorex.transaction.{AssetId, CreateAliasTransactionV1, Transaction, ValidationError} @@ -73,7 +74,7 @@ package object state { def aliasesOfAddress(address: Address): Seq[Alias] = blockchain .addressTransactions(address, Set(CreateAliasTransactionV1.typeId), Int.MaxValue, 0) - .collect { case (_, a: CreateAliasTransactionV1) => a.alias } + .collect { case (_, a: CreateAliasTransaction) => a.alias } def activeLeases(address: Address): Seq[(Int, LeaseTransaction)] = blockchain diff --git a/src/main/scala/scorex/api/http/TransactionsApiRoute.scala b/src/main/scala/scorex/api/http/TransactionsApiRoute.scala index 289bb80d7a6..d1b8f2745cb 100644 --- a/src/main/scala/scorex/api/http/TransactionsApiRoute.scala +++ b/src/main/scala/scorex/api/http/TransactionsApiRoute.scala @@ -14,7 +14,7 @@ import play.api.libs.json._ import scorex.BroadcastRoute import scorex.account.Address import scorex.api.http.DataRequest._ -import scorex.api.http.alias.{CreateAliasRequest, SignedCreateAliasRequest} +import scorex.api.http.alias.{CreateAliasV1Request, CreateAliasV2Request, SignedCreateAliasV1Request, SignedCreateAliasV2Request} import scorex.api.http.assets.SponsorFeeRequest._ import scorex.api.http.assets._ import scorex.api.http.leasing._ @@ -182,7 +182,8 @@ case class TransactionsApiRoute(settings: RestAPISettings, case LeaseTransactionV2 => TransactionFactory.leaseV2(jsv.as[LeaseV2Request], wallet, time) case LeaseCancelTransactionV1 => TransactionFactory.leaseCancelV1(jsv.as[LeaseCancelV1Request], wallet, time) case LeaseCancelTransactionV2 => TransactionFactory.leaseCancelV2(jsv.as[LeaseCancelV2Request], wallet, time) - case CreateAliasTransactionV1 => TransactionFactory.alias(jsv.as[CreateAliasRequest], wallet, time) + case CreateAliasTransactionV1 => TransactionFactory.aliasV1(jsv.as[CreateAliasV1Request], wallet, time) + case CreateAliasTransactionV2 => TransactionFactory.aliasV2(jsv.as[CreateAliasV2Request], wallet, time) case DataTransaction => TransactionFactory.data(jsv.as[DataRequest], wallet, time) case SetScriptTransaction => TransactionFactory.setScript(jsv.as[SetScriptRequest], wallet, time) case SponsorFeeTransaction => TransactionFactory.sponsor(jsv.as[SponsorFeeRequest], wallet, time) @@ -228,7 +229,8 @@ case class TransactionsApiRoute(settings: RestAPISettings, case LeaseTransactionV2 => jsv.as[SignedLeaseV2Request].toTx case LeaseCancelTransactionV1 => jsv.as[SignedLeaseCancelV1Request].toTx case LeaseCancelTransactionV2 => jsv.as[SignedLeaseCancelV2Request].toTx - case CreateAliasTransactionV1 => jsv.as[SignedCreateAliasRequest].toTx + case CreateAliasTransactionV1 => jsv.as[SignedCreateAliasV1Request].toTx + case CreateAliasTransactionV2 => jsv.as[SignedCreateAliasV2Request].toTx case DataTransaction => jsv.as[SignedDataRequest].toTx case SetScriptTransaction => jsv.as[SignedSetScriptRequest].toTx case SponsorFeeTransaction => jsv.as[SignedSponsorFeeRequest].toTx diff --git a/src/main/scala/scorex/api/http/alias/AliasApiRoute.scala b/src/main/scala/scorex/api/http/alias/AliasApiRoute.scala index 00e7dea9650..f4b97c50b60 100644 --- a/src/main/scala/scorex/api/http/alias/AliasApiRoute.scala +++ b/src/main/scala/scorex/api/http/alias/AliasApiRoute.scala @@ -39,7 +39,7 @@ case class AliasApiRoute(settings: RestAPISettings, wallet: Wallet, utx: UtxPool ) )) @ApiResponses(Array(new ApiResponse(code = 200, message = "Json with response or error"))) - def alias: Route = processRequest("create", (t: CreateAliasRequest) => doBroadcast(TransactionFactory.alias(t, wallet, time))) + def alias: Route = processRequest("create", (t: CreateAliasV1Request) => doBroadcast(TransactionFactory.aliasV1(t, wallet, time))) @Path("/by-alias/{alias}") @ApiOperation( value = "Account", diff --git a/src/main/scala/scorex/api/http/alias/AliasBroadcastApiRoute.scala b/src/main/scala/scorex/api/http/alias/AliasBroadcastApiRoute.scala index 5fb2ef05f1d..7274408d451 100644 --- a/src/main/scala/scorex/api/http/alias/AliasBroadcastApiRoute.scala +++ b/src/main/scala/scorex/api/http/alias/AliasBroadcastApiRoute.scala @@ -1,12 +1,11 @@ package scorex.api.http.alias -import javax.ws.rs.Path - import akka.http.scaladsl.server.Route import com.wavesplatform.settings.RestAPISettings import com.wavesplatform.utx.UtxPool import io.netty.channel.group.ChannelGroup import io.swagger.annotations._ +import javax.ws.rs.Path import scorex.BroadcastRoute import scorex.api.http._ @@ -33,7 +32,7 @@ case class AliasBroadcastApiRoute(settings: RestAPISettings, utx: UtxPool, allCh )) @ApiResponses(Array(new ApiResponse(code = 200, message = "Json with response or error"))) def signedCreate: Route = (path("create") & post) { - json[SignedCreateAliasRequest] { aliasReq => + json[SignedCreateAliasV1Request] { aliasReq => doBroadcast(aliasReq.toTx) } } diff --git a/src/main/scala/scorex/api/http/alias/CreateAliasRequest.scala b/src/main/scala/scorex/api/http/alias/CreateAliasRequest.scala deleted file mode 100644 index d24ba05675e..00000000000 --- a/src/main/scala/scorex/api/http/alias/CreateAliasRequest.scala +++ /dev/null @@ -1,16 +0,0 @@ -package scorex.api.http.alias - -import io.swagger.annotations.ApiModelProperty -import play.api.libs.json.{Format, Json} - -case class CreateAliasRequest(@ApiModelProperty(value = "Base58 encoded sender public key", required = true) - sender: String, - @ApiModelProperty(value = "Alias", required = true) - alias: String, - @ApiModelProperty(required = true) - fee: Long, - timestamp: Option[Long] = None) - -object CreateAliasRequest { - implicit val aliasRequestFormat: Format[CreateAliasRequest] = Json.format -} diff --git a/src/main/scala/scorex/api/http/alias/CreateAliasV1Request.scala b/src/main/scala/scorex/api/http/alias/CreateAliasV1Request.scala new file mode 100644 index 00000000000..6eb4c726f8b --- /dev/null +++ b/src/main/scala/scorex/api/http/alias/CreateAliasV1Request.scala @@ -0,0 +1,16 @@ +package scorex.api.http.alias + +import io.swagger.annotations.ApiModelProperty +import play.api.libs.json.{Format, Json} + +case class CreateAliasV1Request(@ApiModelProperty(value = "Base58 encoded sender public key", required = true) + sender: String, + @ApiModelProperty(value = "Alias", required = true) + alias: String, + @ApiModelProperty(required = true) + fee: Long, + timestamp: Option[Long] = None) + +object CreateAliasV1Request { + implicit val aliasV1RequestFormat: Format[CreateAliasV1Request] = Json.format +} diff --git a/src/main/scala/scorex/api/http/alias/CreateAliasV2Request.scala b/src/main/scala/scorex/api/http/alias/CreateAliasV2Request.scala new file mode 100644 index 00000000000..911ee72241d --- /dev/null +++ b/src/main/scala/scorex/api/http/alias/CreateAliasV2Request.scala @@ -0,0 +1,18 @@ +package scorex.api.http.alias + +import io.swagger.annotations.ApiModelProperty +import play.api.libs.json.{Format, Json} + +case class CreateAliasV2Request(@ApiModelProperty(required = true) + version: Byte, + @ApiModelProperty(value = "Base58 encoded sender public key", required = true) + sender: String, + @ApiModelProperty(value = "Alias", required = true) + alias: String, + @ApiModelProperty(required = true) + fee: Long, + timestamp: Option[Long] = None) + +object CreateAliasV2Request { + implicit val aliasV2RequestFormat: Format[CreateAliasV2Request] = Json.format +} diff --git a/src/main/scala/scorex/api/http/alias/SignedCreateAliasRequest.scala b/src/main/scala/scorex/api/http/alias/SignedCreateAliasRequest.scala deleted file mode 100644 index 05b04832ff3..00000000000 --- a/src/main/scala/scorex/api/http/alias/SignedCreateAliasRequest.scala +++ /dev/null @@ -1,32 +0,0 @@ -package scorex.api.http.alias - -import io.swagger.annotations.ApiModelProperty -import play.api.libs.json.{Format, Json} -import scorex.account.{Alias, PublicKeyAccount} -import scorex.api.http.BroadcastRequest -import scorex.transaction.TransactionParsers.SignatureStringLength -import scorex.transaction.{CreateAliasTransactionV1, ValidationError} - -case class SignedCreateAliasRequest(@ApiModelProperty(value = "Base58 encoded sender public key", required = true) - senderPublicKey: String, - @ApiModelProperty(required = true) - fee: Long, - @ApiModelProperty(value = "Alias", required = true) - alias: String, - @ApiModelProperty(required = true) - timestamp: Long, - @ApiModelProperty(required = true) - signature: String) - extends BroadcastRequest { - def toTx: Either[ValidationError, CreateAliasTransactionV1] = - for { - _sender <- PublicKeyAccount.fromBase58String(senderPublicKey) - _signature <- parseBase58(signature, "invalid.signature", SignatureStringLength) - _alias <- Alias.buildWithCurrentNetworkByte(alias) - _t <- CreateAliasTransactionV1.create(_sender, _alias, fee, timestamp, _signature) - } yield _t -} - -object SignedCreateAliasRequest { - implicit val broadcastAliasRequestReadsFormat: Format[SignedCreateAliasRequest] = Json.format -} diff --git a/src/main/scala/scorex/api/http/alias/SignedCreateAliasV1Request.scala b/src/main/scala/scorex/api/http/alias/SignedCreateAliasV1Request.scala new file mode 100644 index 00000000000..25ae1fde808 --- /dev/null +++ b/src/main/scala/scorex/api/http/alias/SignedCreateAliasV1Request.scala @@ -0,0 +1,32 @@ +package scorex.api.http.alias + +import io.swagger.annotations.ApiModelProperty +import play.api.libs.json.{Format, Json} +import scorex.account.{Alias, PublicKeyAccount} +import scorex.api.http.BroadcastRequest +import scorex.transaction.TransactionParsers.SignatureStringLength +import scorex.transaction.{CreateAliasTransactionV1, ValidationError} + +case class SignedCreateAliasV1Request(@ApiModelProperty(value = "Base58 encoded sender public key", required = true) + senderPublicKey: String, + @ApiModelProperty(required = true) + fee: Long, + @ApiModelProperty(value = "Alias", required = true) + alias: String, + @ApiModelProperty(required = true) + timestamp: Long, + @ApiModelProperty(required = true) + signature: String) + extends BroadcastRequest { + def toTx: Either[ValidationError, CreateAliasTransactionV1] = + for { + _sender <- PublicKeyAccount.fromBase58String(senderPublicKey) + _signature <- parseBase58(signature, "invalid.signature", SignatureStringLength) + _alias <- Alias.buildWithCurrentNetworkByte(alias) + _t <- CreateAliasTransactionV1.create(_sender, _alias, fee, timestamp, _signature) + } yield _t +} + +object SignedCreateAliasV1Request { + implicit val broadcastAliasV1RequestReadsFormat: Format[SignedCreateAliasV1Request] = Json.format +} diff --git a/src/main/scala/scorex/api/http/alias/SignedCreateAliasV2Request.scala b/src/main/scala/scorex/api/http/alias/SignedCreateAliasV2Request.scala new file mode 100644 index 00000000000..edd0c9c26bb --- /dev/null +++ b/src/main/scala/scorex/api/http/alias/SignedCreateAliasV2Request.scala @@ -0,0 +1,35 @@ +package scorex.api.http.alias + +import io.swagger.annotations.ApiModelProperty +import play.api.libs.json.{Format, Json} +import scorex.account.{Alias, PublicKeyAccount} +import scorex.api.http.BroadcastRequest +import scorex.transaction.{CreateAliasTransaction, CreateAliasTransactionV2, Proofs, ValidationError} +import cats.implicits._ + +case class SignedCreateAliasV2Request(@ApiModelProperty(required = true) + version: Byte, + @ApiModelProperty(value = "Base58 encoded sender public key", required = true) + senderPublicKey: String, + @ApiModelProperty(required = true) + fee: Long, + @ApiModelProperty(value = "Alias", required = true) + alias: String, + @ApiModelProperty(required = true) + timestamp: Long, + @ApiModelProperty(required = true) + proofs: List[String]) + extends BroadcastRequest { + def toTx: Either[ValidationError, CreateAliasTransaction] = + for { + _sender <- PublicKeyAccount.fromBase58String(senderPublicKey) + _proofBytes <- proofs.traverse(s => parseBase58(s, "invalid proof", Proofs.MaxProofStringSize)) + _proofs <- Proofs.create(_proofBytes) + _alias <- Alias.buildWithCurrentNetworkByte(alias) + _t <- CreateAliasTransactionV2.create(version, _sender, _alias, fee, timestamp, _proofs) + } yield _t +} + +object SignedCreateAliasV2Request { + implicit val broadcastAliasV2RequestReadsFormat: Format[SignedCreateAliasV2Request] = Json.format +} diff --git a/src/main/scala/scorex/transaction/CreateAliasTransaction.scala b/src/main/scala/scorex/transaction/CreateAliasTransaction.scala new file mode 100644 index 00000000000..f3d7a80e5b0 --- /dev/null +++ b/src/main/scala/scorex/transaction/CreateAliasTransaction.scala @@ -0,0 +1,50 @@ +package scorex.transaction + +import com.google.common.primitives.{Bytes, Longs} +import monix.eval.Coeval +import play.api.libs.json.{JsObject, Json} +import scorex.account.{Alias, PublicKeyAccount} +import scorex.crypto.signatures.Curve25519.KeyLength +import scorex.serialization.Deser + +import scala.util.{Failure, Success, Try} + +trait CreateAliasTransaction extends ProvenTransaction { + def version: Byte + def alias: Alias + def fee: Long + def timestamp: Long + + override val assetFee: (Option[AssetId], Long) = (None, fee) + + override val json: Coeval[JsObject] = Coeval.evalOnce( + jsonBase() ++ Json.obj( + "version" -> version, + "alias" -> alias.name, + "fee" -> fee, + "timestamp" -> timestamp + )) + + val baseBytes: Coeval[Array[Byte]] = Coeval.evalOnce { + Bytes.concat( + sender.publicKey, + Deser.serializeArray(alias.bytes.arr), + Longs.toByteArray(fee), + Longs.toByteArray(timestamp) + ) + } +} + +object CreateAliasTransaction { + val typeId: Byte = 10 + + def parseBase(start: Int, bytes: Array[Byte]): Try[(PublicKeyAccount, Alias, Long, Long, Int)] = { + for { + sender <- Try(PublicKeyAccount(bytes.slice(start, start + KeyLength))) + (aliasBytes, aliasEnd) = Deser.parseArraySize(bytes, start + KeyLength) + alias <- Alias.fromBytes(aliasBytes).fold(err => Failure(new Exception(err.toString)), Success.apply) + fee <- Try(Longs.fromByteArray(bytes.slice(aliasEnd, aliasEnd + 8))) + timestamp <- Try(Longs.fromByteArray(bytes.slice(aliasEnd + 8, aliasEnd + 16))) + } yield (sender, alias, fee, timestamp, aliasEnd + 16) + } +} diff --git a/src/main/scala/scorex/transaction/CreateAliasTransactionV1.scala b/src/main/scala/scorex/transaction/CreateAliasTransactionV1.scala index 30bdbc7011e..df324fc6845 100644 --- a/src/main/scala/scorex/transaction/CreateAliasTransactionV1.scala +++ b/src/main/scala/scorex/transaction/CreateAliasTransactionV1.scala @@ -1,54 +1,13 @@ package scorex.transaction -import com.google.common.primitives.{Bytes, Longs} +import com.google.common.primitives.Bytes import com.wavesplatform.crypto import com.wavesplatform.state.ByteStr import monix.eval.Coeval -import play.api.libs.json.{JsObject, Json} import scorex.account._ -import scorex.crypto.signatures.Curve25519.{KeyLength, SignatureLength} -import scorex.serialization.Deser -import scala.util.{Failure, Success, Try} - -trait CreateAliasTransaction extends ProvenTransaction { - def version: Byte - def alias: Alias - def fee: Long - def timestamp: Long - - override val assetFee: (Option[AssetId], Long) = (None, fee) +import scorex.crypto.signatures.Curve25519.SignatureLength - override val json: Coeval[JsObject] = Coeval.evalOnce( - jsonBase() ++ Json.obj( - "version" -> version, - "alias" -> alias.name, - "fee" -> fee, - "timestamp" -> timestamp - )) - - val baseBytes: Coeval[Array[Byte]] = Coeval.evalOnce { - Bytes.concat( - sender.publicKey, - Deser.serializeArray(alias.bytes.arr), - Longs.toByteArray(fee), - Longs.toByteArray(timestamp) - ) - } -} - -object CreateAliasTransaction { - val typeId: Byte = 10 - - def parseBase(start: Int, bytes: Array[Byte]): Try[(PublicKeyAccount, Alias, Long, Long, Int)] = { - for { - sender <- Try(PublicKeyAccount(bytes.slice(start, start + KeyLength))) - (aliasBytes, aliasEnd) = Deser.parseArraySize(bytes, start + KeyLength) - alias <- Alias.fromBytes(aliasBytes).fold(err => Failure(new Exception(err.toString)), Success.apply) - fee <- Try(Longs.fromByteArray(bytes.slice(aliasEnd, aliasEnd + 8))) - timestamp <- Try(Longs.fromByteArray(bytes.slice(aliasEnd + 8, aliasEnd + 16))) - } yield (sender, alias, fee, timestamp, aliasEnd + 16) - } -} +import scala.util.{Failure, Success, Try} case class CreateAliasTransactionV1 private (sender: PublicKeyAccount, alias: Alias, fee: Long, timestamp: Long, signature: ByteStr) extends CreateAliasTransaction diff --git a/src/main/scala/scorex/transaction/CreateAliasTransactionV2.scala b/src/main/scala/scorex/transaction/CreateAliasTransactionV2.scala new file mode 100644 index 00000000000..a9f5d92cb38 --- /dev/null +++ b/src/main/scala/scorex/transaction/CreateAliasTransactionV2.scala @@ -0,0 +1,69 @@ +package scorex.transaction + +import cats.implicits._ +import com.google.common.primitives.Bytes +import com.wavesplatform.crypto +import com.wavesplatform.state.ByteStr +import monix.eval.Coeval +import scorex.account.{Alias, PrivateKeyAccount, PublicKeyAccount} + +import scala.util.{Failure, Success, Try} + +final case class CreateAliasTransactionV2 private (version: Byte, sender: PublicKeyAccount, alias: Alias, fee: Long, timestamp: Long, proofs: Proofs) + extends CreateAliasTransaction { + + override val id: Coeval[AssetId] = + Coeval.evalOnce(ByteStr(crypto.fastHash(builder.typeId +: alias.bytes.arr))) + + override val bodyBytes: Coeval[Array[Byte]] = + baseBytes.map(base => Bytes.concat(Array(builder.typeId, version), base)) + + override def builder: TransactionParser = CreateAliasTransactionV2 + + override val bytes: Coeval[Array[Byte]] = + (bodyBytes, proofs.bytes) + .mapN { case (bb, pb) => Bytes.concat(Array(0: Byte), bb, pb) } +} + +object CreateAliasTransactionV2 extends TransactionParserFor[CreateAliasTransactionV2] with TransactionParser.MultipleVersions { + override val typeId: Byte = CreateAliasTransaction.typeId + + override def supportedVersions: Set[Byte] = Set(2) + + override protected def parseTail(version: Byte, bytes: Array[Byte]): Try[CreateAliasTransactionV2] = { + Try { + for { + (sender, alias, fee, timestamp, end) <- CreateAliasTransaction.parseBase(0, bytes) + result <- (for { + proofs <- Proofs.fromBytes(bytes.drop(end)) + tx <- CreateAliasTransactionV2.create(version, sender, alias, fee, timestamp, proofs) + } yield tx).fold(left => Failure(new Exception(left.toString)), right => Success(right)) + } yield result + }.flatten + } + + def create(version: Byte, + sender: PublicKeyAccount, + alias: Alias, + fee: Long, + timestamp: Long, + proofs: Proofs): Either[ValidationError, CreateAliasTransactionV2] = + if (fee <= 0) { + Left(ValidationError.InsufficientFee()) + } else if (!(supportedVersions contains version)) { + Left(ValidationError.UnsupportedVersion(version)) + } else { + Right(CreateAliasTransactionV2(version, sender, alias, fee, timestamp, proofs)) + } + + def selfSigned(sender: PrivateKeyAccount, + version: Byte, + alias: Alias, + fee: Long, + timestamp: Long): Either[ValidationError, CreateAliasTransactionV2] = { + for { + unsigned <- create(version, sender, alias, fee, timestamp, Proofs.empty) + proofs <- Proofs.create(Seq(ByteStr(crypto.sign(sender, unsigned.bodyBytes())))) + } yield unsigned.copy(proofs = proofs) + } +} diff --git a/src/main/scala/scorex/transaction/TransactionFactory.scala b/src/main/scala/scorex/transaction/TransactionFactory.scala index 104e5ace23f..d909a7038ae 100644 --- a/src/main/scala/scorex/transaction/TransactionFactory.scala +++ b/src/main/scala/scorex/transaction/TransactionFactory.scala @@ -4,7 +4,7 @@ import com.google.common.base.Charsets import com.wavesplatform.state.ByteStr import scorex.account._ import scorex.api.http.DataRequest -import scorex.api.http.alias.CreateAliasRequest +import scorex.api.http.alias.{CreateAliasV1Request, CreateAliasV2Request} import scorex.api.http.assets._ import scorex.api.http.leasing.{LeaseCancelV1Request, LeaseCancelV2Request, LeaseV1Request, LeaseV2Request} import scorex.crypto.encode.Base58 @@ -157,7 +157,7 @@ object TransactionFactory { timestamp) } yield tx - def alias(request: CreateAliasRequest, wallet: Wallet, time: Time): Either[ValidationError, CreateAliasTransactionV1] = + def aliasV1(request: CreateAliasV1Request, wallet: Wallet, time: Time): Either[ValidationError, CreateAliasTransactionV1] = for { senderPrivateKey <- wallet.findWallet(request.sender) alias <- Alias.buildWithCurrentNetworkByte(request.alias) @@ -165,6 +165,14 @@ object TransactionFactory { tx <- CreateAliasTransactionV1.create(senderPrivateKey, alias, request.fee, timestamp) } yield tx + def aliasV2(request: CreateAliasV2Request, wallet: Wallet, time: Time): Either[ValidationError, CreateAliasTransactionV2] = + for { + senderPrivateKey <- wallet.findWallet(request.sender) + alias <- Alias.buildWithCurrentNetworkByte(request.alias) + timestamp = request.timestamp.getOrElse(time.getTimestamp()) + tx <- CreateAliasTransactionV2.selfSigned(senderPrivateKey, request.version, alias, request.fee, timestamp) + } yield tx + def reissueAssetV1(request: ReissueV1Request, wallet: Wallet, time: Time): Either[ValidationError, ReissueTransactionV1] = for { pk <- wallet.findWallet(request.sender) diff --git a/src/main/scala/scorex/transaction/TransactionParsers.scala b/src/main/scala/scorex/transaction/TransactionParsers.scala index e0a0be78d6d..a18b64676b2 100644 --- a/src/main/scala/scorex/transaction/TransactionParsers.scala +++ b/src/main/scala/scorex/transaction/TransactionParsers.scala @@ -38,6 +38,7 @@ object TransactionParsers { TransferTransactionV2, SetScriptTransaction, IssueTransactionV2, + CreateAliasTransactionV2, ReissueTransactionV2, LeaseTransactionV2, LeaseCancelTransactionV2, diff --git a/src/main/scala/scorex/transaction/smart/RealTransactionWrapper.scala b/src/main/scala/scorex/transaction/smart/RealTransactionWrapper.scala index 87428d4bc03..a2b729b2ee4 100644 --- a/src/main/scala/scorex/transaction/smart/RealTransactionWrapper.scala +++ b/src/main/scala/scorex/transaction/smart/RealTransactionWrapper.scala @@ -58,7 +58,7 @@ case class RealTransactionWrapper(tx: Transaction) extends com.wavesplatform.lan case g: LeaseTransaction => Right(g.amount) case g: TransferTransaction => Right(g.amount) case g: ExchangeTransaction => Right(g.amount) - case _: CreateAliasTransactionV1 => Left("Transaction doesn't contain amount") + case _: CreateAliasTransaction => Left("Transaction doesn't contain amount") case _: SetScriptTransaction => Left("Transaction doesn't contain amount") case _: MassTransferTransaction => Left("Transaction doesn't contain amount") case _: LeaseCancelTransaction => Left("Transaction doesn't contain amount") @@ -71,7 +71,7 @@ case class RealTransactionWrapper(tx: Transaction) extends com.wavesplatform.lan override def timestamp: Long = tx.timestamp override def aliasText: Either[String, String] = tx match { - case g: CreateAliasTransactionV1 => Right(g.alias.name) + case g: CreateAliasTransaction => Right(g.alias.name) case _ => Left("Transaction doesn't contain alias text") } diff --git a/src/test/scala/com/wavesplatform/RequestGen.scala b/src/test/scala/com/wavesplatform/RequestGen.scala index 9cb5795fef8..a8d6c0a965f 100644 --- a/src/test/scala/com/wavesplatform/RequestGen.scala +++ b/src/test/scala/com/wavesplatform/RequestGen.scala @@ -4,7 +4,7 @@ import org.scalacheck.Gen.{alphaNumChar, choose, listOfN, oneOf} import org.scalacheck.{Arbitrary, Gen => G} import org.scalatest.Suite import scorex.account.Alias -import scorex.api.http.alias.SignedCreateAliasRequest +import scorex.api.http.alias.SignedCreateAliasV1Request import scorex.api.http.assets._ import scorex.api.http.leasing.{SignedLeaseCancelV1Request, SignedLeaseV1Request} import scorex.crypto.encode.Base58 @@ -111,11 +111,11 @@ trait RequestGen extends TransactionGen { _: Suite => _tr <- transferReq } yield SignedTransferV1Request(_tr.sender, _tr.assetId, _tr.recipient, _tr.amount, _tr.fee, _tr.feeAssetId, _timestamp, _tr.attachment, _signature) - val createAliasReq: G[SignedCreateAliasRequest] = for { + val createAliasReq: G[SignedCreateAliasV1Request] = for { _signature <- signatureGen _timestamp <- ntpTimestampGen _alias <- createAliasGen - } yield SignedCreateAliasRequest(_alias.sender.toString, _alias.fee, _alias.alias.name, _timestamp, _signature) + } yield SignedCreateAliasV1Request(_alias.sender.toString, _alias.fee, _alias.alias.name, _timestamp, _signature) val leaseReq: G[SignedLeaseV1Request] = for { _signature <- signatureGen diff --git a/src/test/scala/com/wavesplatform/TransactionGen.scala b/src/test/scala/com/wavesplatform/TransactionGen.scala index 67deecae9f1..fb1918a2202 100644 --- a/src/test/scala/com/wavesplatform/TransactionGen.scala +++ b/src/test/scala/com/wavesplatform/TransactionGen.scala @@ -327,11 +327,26 @@ trait TransactionGenBase extends ScriptGen { val MinIssueFee = 100000000 - val createAliasGen: Gen[CreateAliasTransactionV1] = for { + val createAliasGen: Gen[CreateAliasTransaction] = for { timestamp: Long <- positiveLongGen sender: PrivateKeyAccount <- accountGen alias: Alias <- aliasGen - } yield CreateAliasTransactionV1.create(sender, alias, MinIssueFee, timestamp).right.get + version <- Gen.oneOf(CreateAliasTransactionV2.supportedVersions.toSeq) + tx <- Gen.oneOf( + CreateAliasTransactionV1.create(sender, alias, MinIssueFee, timestamp).right.get, + CreateAliasTransactionV2.selfSigned(sender, version, alias, MinIssueFee, timestamp).right.get + ) + } yield tx + + def createAliasGen(sender: PrivateKeyAccount, alias: Alias, fee: Long, timestamp: Long): Gen[CreateAliasTransaction] = { + for { + version <- Gen.oneOf(CreateAliasTransactionV2.supportedVersions.toSeq) + tx <- Gen.oneOf( + CreateAliasTransactionV1.create(sender, alias, fee, timestamp).right.get, + CreateAliasTransactionV2.selfSigned(sender, version, alias, fee, timestamp).right.get + ) + } yield tx + } val issueParamGen = for { sender: PrivateKeyAccount <- accountGen @@ -519,7 +534,7 @@ trait TransactionGenBase extends ScriptGen { (is, ri, bu) <- issueReissueBurnGen.retryUntil { case (i, r, b) => i.isInstanceOf[IssueTransactionV1] && r.isInstanceOf[ReissueTransactionV1] } - ca <- createAliasGen + ca <- createAliasGen.retryUntil(_.version == 1).map(_.asInstanceOf[CreateAliasTransactionV1]) xt <- exchangeTransactionGen tx <- Gen.oneOf(tr, is.asInstanceOf[IssueTransactionV1], ri.asInstanceOf[ReissueTransactionV1], ca, bu, xt) } yield tx).label("random transaction") diff --git a/src/test/scala/com/wavesplatform/http/AliasBroadcastRouteSpec.scala b/src/test/scala/com/wavesplatform/http/AliasBroadcastRouteSpec.scala index 050ab13bb49..7c8a88f5ffe 100644 --- a/src/test/scala/com/wavesplatform/http/AliasBroadcastRouteSpec.scala +++ b/src/test/scala/com/wavesplatform/http/AliasBroadcastRouteSpec.scala @@ -29,7 +29,7 @@ class AliasBroadcastRouteSpec extends RouteSpec("/alias/broadcast/") with Reques def posting(url: String, v: JsValue): RouteTestResult = Post(routePath(url), v) ~> route "when state validation fails" in { - forAll(createAliasGen) { (t: Transaction) => + forAll(createAliasGen.retryUntil(_.version == 1)) { (t: Transaction) => posting("create", t.json()) should produce(StateCheckFailed(t, "foo")) } } @@ -39,7 +39,7 @@ class AliasBroadcastRouteSpec extends RouteSpec("/alias/broadcast/") with Reques val route = AliasBroadcastApiRoute(settings, utx, allChannels).route "create alias transaction" in forAll(createAliasReq) { req => - import scorex.api.http.alias.SignedCreateAliasRequest.broadcastAliasRequestReadsFormat + import scorex.api.http.alias.SignedCreateAliasV1Request.broadcastAliasV1RequestReadsFormat def posting(v: JsValue): RouteTestResult = Post(routePath("create"), v) ~> route diff --git a/src/test/scala/com/wavesplatform/state/diffs/CreateAliasTransactionDiffTest.scala b/src/test/scala/com/wavesplatform/state/diffs/CreateAliasTransactionDiffTest.scala index a3f92569bb0..23b3ad6fbeb 100644 --- a/src/test/scala/com/wavesplatform/state/diffs/CreateAliasTransactionDiffTest.scala +++ b/src/test/scala/com/wavesplatform/state/diffs/CreateAliasTransactionDiffTest.scala @@ -1,6 +1,7 @@ package com.wavesplatform.state.diffs import cats._ +import com.wavesplatform.features.BlockchainFeatures import com.wavesplatform.state._ import com.wavesplatform.{NoShrink, TransactionGen} import org.scalacheck.Gen @@ -8,13 +9,19 @@ import org.scalatest.prop.PropertyChecks import org.scalatest.{Matchers, PropSpec} import scorex.account.PrivateKeyAccount import scorex.lagonaki.mocks.TestBlock +import scorex.settings.TestFunctionalitySettings import scorex.transaction.assets.IssueTransaction -import scorex.transaction.{CreateAliasTransactionV1, GenesisTransaction} +import scorex.transaction.{CreateAliasTransaction, CreateAliasTransactionV1, GenesisTransaction} class CreateAliasTransactionDiffTest extends PropSpec with PropertyChecks with Matchers with TransactionGen with NoShrink { + val fs = + TestFunctionalitySettings.Enabled.copy( + preActivatedFeatures = Map(BlockchainFeatures.SmartAccounts.id -> 0) + ) + val preconditionsAndAliasCreations - : Gen[(GenesisTransaction, CreateAliasTransactionV1, CreateAliasTransactionV1, CreateAliasTransactionV1, CreateAliasTransactionV1)] = for { + : Gen[(GenesisTransaction, CreateAliasTransaction, CreateAliasTransaction, CreateAliasTransaction, CreateAliasTransaction)] = for { master <- accountGen ts <- timestampGen genesis: GenesisTransaction = GenesisTransaction.create(master, ENOUGH_AMT, ts).right.get @@ -22,16 +29,16 @@ class CreateAliasTransactionDiffTest extends PropSpec with PropertyChecks with M alias2 <- aliasGen suchThat (_.name != alias.name) fee <- smallFeeGen other: PrivateKeyAccount <- accountGen - aliasTx = CreateAliasTransactionV1.create(master, alias, fee, ts).right.get - sameAliasTx = CreateAliasTransactionV1.create(master, alias, fee + 1, ts).right.get - sameAliasOtherSenderTx = CreateAliasTransactionV1.create(other, alias, fee + 2, ts).right.get - anotherAliasTx = CreateAliasTransactionV1.create(master, alias2, fee + 3, ts).right.get + aliasTx <- createAliasGen(master, alias, fee, ts) + sameAliasTx <- createAliasGen(master, alias, fee + 1, ts) + sameAliasOtherSenderTx <- createAliasGen(other, alias, fee + 2, ts) + anotherAliasTx <- createAliasGen(master, alias2, fee + 3, ts) } yield (genesis, aliasTx, sameAliasTx, sameAliasOtherSenderTx, anotherAliasTx) property("can create and resolve aliases preserving waves invariant") { forAll(preconditionsAndAliasCreations) { case (gen, aliasTx, _, _, anotherAliasTx) => - assertDiffAndState(Seq(TestBlock.create(Seq(gen, aliasTx))), TestBlock.create(Seq(anotherAliasTx))) { + assertDiffAndState(Seq(TestBlock.create(Seq(gen, aliasTx))), TestBlock.create(Seq(anotherAliasTx)), fs) { case (blockDiff, newState) => val totalPortfolioDiff = Monoid.combineAll(blockDiff.portfolios.values) totalPortfolioDiff.balance shouldBe 0 @@ -50,11 +57,11 @@ class CreateAliasTransactionDiffTest extends PropSpec with PropertyChecks with M property("cannot recreate existing alias") { forAll(preconditionsAndAliasCreations) { case (gen, aliasTx, sameAliasTx, sameAliasOtherSenderTx, _) => - assertDiffEi(Seq(TestBlock.create(Seq(gen, aliasTx))), TestBlock.create(Seq(sameAliasTx))) { blockDiffEi => + assertDiffEi(Seq(TestBlock.create(Seq(gen, aliasTx))), TestBlock.create(Seq(sameAliasTx)), fs) { blockDiffEi => blockDiffEi should produce("AlreadyInTheState") } - assertDiffEi(Seq(TestBlock.create(Seq(gen, aliasTx))), TestBlock.create(Seq(sameAliasOtherSenderTx))) { blockDiffEi => + assertDiffEi(Seq(TestBlock.create(Seq(gen, aliasTx))), TestBlock.create(Seq(sameAliasOtherSenderTx)), fs) { blockDiffEi => blockDiffEi should produce("AlreadyInTheState") } } diff --git a/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/AddressFromRecipientScenarioTest.scala b/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/AddressFromRecipientScenarioTest.scala index 95b3704135b..a643cc74e30 100644 --- a/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/AddressFromRecipientScenarioTest.scala +++ b/src/test/scala/com/wavesplatform/state/diffs/smart/scenarios/AddressFromRecipientScenarioTest.scala @@ -15,19 +15,19 @@ import scorex.account.{AddressOrAlias, AddressScheme, PrivateKeyAccount} import scorex.lagonaki.mocks.TestBlock import scorex.transaction.smart.BlockchainContext import scorex.transaction.transfer._ -import scorex.transaction.{CreateAliasTransactionV1, GenesisTransaction, Transaction} +import scorex.transaction.{CreateAliasTransaction, GenesisTransaction, Transaction} class AddressFromRecipientScenarioTest extends PropSpec with PropertyChecks with Matchers with TransactionGen with NoShrink { - val preconditionsAndAliasCreations: Gen[(Seq[GenesisTransaction], CreateAliasTransactionV1, TransferTransactionV1, TransferTransactionV1)] = for { + val preconditionsAndAliasCreations: Gen[(Seq[GenesisTransaction], CreateAliasTransaction, TransferTransactionV1, TransferTransactionV1)] = for { master <- accountGen ts <- timestampGen other: PrivateKeyAccount <- accountGen genesis1: GenesisTransaction = GenesisTransaction.create(master, ENOUGH_AMT, ts).right.get genesis2: GenesisTransaction = GenesisTransaction.create(other, ENOUGH_AMT, ts).right.get - alias <- aliasGen - fee <- smallFeeGen - aliasTx = CreateAliasTransactionV1.create(other, alias, fee, ts).right.get + alias <- aliasGen + fee <- smallFeeGen + aliasTx <- createAliasGen(other, alias, fee, ts) transferViaAddress <- transferGeneratorP(master, other, None, None) transferViaAlias <- transferGeneratorP(master, AddressOrAlias.fromBytes(alias.bytes.arr, 0).right.get._1, None, None) } yield (Seq(genesis1, genesis2), aliasTx, transferViaAddress, transferViaAlias) diff --git a/src/test/scala/scorex/transaction/CreateAliasTransactionSpecification.scala b/src/test/scala/scorex/transaction/CreateAliasTransactionSpecification.scala index e419c4e120e..55546fff811 100644 --- a/src/test/scala/scorex/transaction/CreateAliasTransactionSpecification.scala +++ b/src/test/scala/scorex/transaction/CreateAliasTransactionSpecification.scala @@ -8,16 +8,16 @@ import scorex.account.{Alias, PrivateKeyAccount} class CreateAliasTransactionSpecification extends PropSpec with PropertyChecks with Matchers with TransactionGen { property("CreateAliasTransaction serialization roundtrip") { - forAll(createAliasGen) { tx: CreateAliasTransactionV1 => - val recovered = CreateAliasTransactionV1.parseBytes(tx.bytes()).get - assertTxs(recovered, tx) + forAll(createAliasGen) { tx: CreateAliasTransaction => + val recovered = tx.builder.parseBytes(tx.bytes()).get + recovered shouldEqual tx } } property("CreateAliasTransaction serialization from TypedTransaction") { - forAll(createAliasGen) { tx: CreateAliasTransactionV1 => + forAll(createAliasGen) { tx: CreateAliasTransaction => val recovered = TransactionParsers.parseBytes(tx.bytes()).get - assertTxs(recovered.asInstanceOf[CreateAliasTransactionV1], tx) + recovered shouldEqual tx } } @@ -29,12 +29,4 @@ class CreateAliasTransactionSpecification extends PropSpec with PropertyChecks w tx1.id() shouldBe tx2.id() } } - - private def assertTxs(first: CreateAliasTransactionV1, second: CreateAliasTransactionV1): Unit = { - first.sender.address shouldEqual second.sender.address - first.timestamp shouldEqual second.timestamp - first.fee shouldEqual second.fee - first.alias.bytes shouldEqual second.alias.bytes - first.bytes() shouldEqual second.bytes() - } } diff --git a/src/test/scala/scorex/transaction/FeeCalculatorSpecification.scala b/src/test/scala/scorex/transaction/FeeCalculatorSpecification.scala index aa7102a29b7..b7b3e7803b3 100644 --- a/src/test/scala/scorex/transaction/FeeCalculatorSpecification.scala +++ b/src/test/scala/scorex/transaction/FeeCalculatorSpecification.scala @@ -138,7 +138,7 @@ class FeeCalculatorSpecification extends PropSpec with PropertyChecks with Match property("Create alias transaction") { val feeCalc = new FeeCalculator(mySettings, noScriptBlockchain) - forAll(createAliasGen) { tx: CreateAliasTransactionV1 => + forAll(createAliasGen) { tx: CreateAliasTransaction => feeCalc.enoughFee(tx) shouldBeRightIf (tx.fee >= 600000) } } diff --git a/src/test/scala/scorex/transaction/api/http/alias/AliasRequestTests.scala b/src/test/scala/scorex/transaction/api/http/alias/AliasRequestTests.scala index 12bb8b99aa6..0cfb7165772 100644 --- a/src/test/scala/scorex/transaction/api/http/alias/AliasRequestTests.scala +++ b/src/test/scala/scorex/transaction/api/http/alias/AliasRequestTests.scala @@ -2,7 +2,7 @@ package scorex.transaction.api.http.alias import org.scalatest.{FunSuite, Matchers} import play.api.libs.json.Json -import scorex.api.http.alias.{CreateAliasRequest, SignedCreateAliasRequest} +import scorex.api.http.alias.{CreateAliasV1Request, SignedCreateAliasV1Request} class AliasRequestTests extends FunSuite with Matchers { test("CreateAliasRequest") { @@ -15,9 +15,9 @@ class AliasRequestTests extends FunSuite with Matchers { } """ - val req = Json.parse(json).validate[CreateAliasRequest].get + val req = Json.parse(json).validate[CreateAliasV1Request].get - req shouldBe CreateAliasRequest("3Myss6gmMckKYtka3cKCM563TBJofnxvfD7", "ALIAS", 10000000) + req shouldBe CreateAliasV1Request("3Myss6gmMckKYtka3cKCM563TBJofnxvfD7", "ALIAS", 10000000) } test("SignedCreateAliasRequest") { @@ -32,9 +32,9 @@ class AliasRequestTests extends FunSuite with Matchers { } """ - val req = Json.parse(json).validate[SignedCreateAliasRequest].get + val req = Json.parse(json).validate[SignedCreateAliasV1Request].get - req shouldBe SignedCreateAliasRequest( + req shouldBe SignedCreateAliasV1Request( "CRxqEuxhdZBEHX42MU4FfyJxuHmbDBTaHMhM3Uki7pLw", 100000, "ALIAS", From 1961cb800d9c9b5b6aea0d53f97b22a1a8ef8b77 Mon Sep 17 00:00:00 2001 From: alexandr Date: Sat, 28 Apr 2018 16:39:17 +0300 Subject: [PATCH 3/4] NODE 496: Resolve conflicts --- .../state/diffs/CommonValidation.scala | 38 ++++++------- .../api/http/TransactionsApiRoute.scala | 56 +++++++++---------- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/main/scala/com/wavesplatform/state/diffs/CommonValidation.scala b/src/main/scala/com/wavesplatform/state/diffs/CommonValidation.scala index 4d16348451e..0004a27925e 100644 --- a/src/main/scala/com/wavesplatform/state/diffs/CommonValidation.scala +++ b/src/main/scala/com/wavesplatform/state/diffs/CommonValidation.scala @@ -93,27 +93,27 @@ object CommonValidation { ) tx match { - case _: BurnTransaction => Right(tx) - case _: PaymentTransaction => Right(tx) - case _: GenesisTransaction => Right(tx) - case _: TransferTransactionV1 => Right(tx) - case _: IssueTransactionV1 => Right(tx) - case _: ReissueTransactionV1 => Right(tx) - case _: ExchangeTransaction => Right(tx) - case _: LeaseTransactionV1 => Right(tx) - case _: LeaseCancelTransactionV1 => Right(tx) - case _: CreateAliasTransactionV1 => Right(tx) - case _: MassTransferTransaction => activationBarrier(BlockchainFeatures.MassTransfer) - case _: DataTransaction => activationBarrier(BlockchainFeatures.DataTransaction) - case _: SetScriptTransaction => activationBarrier(BlockchainFeatures.SmartAccounts) - case _: TransferTransactionV2 => activationBarrier(BlockchainFeatures.SmartAccounts) - case _: IssueTransactionV2 => activationBarrier(BlockchainFeatures.SmartAccounts) - case _: ReissueTransactionV2 => activationBarrier(BlockchainFeatures.SmartAccounts) + case _: BurnTransaction => Right(tx) + case _: PaymentTransaction => Right(tx) + case _: GenesisTransaction => Right(tx) + case _: TransferTransactionV1 => Right(tx) + case _: IssueTransactionV1 => Right(tx) + case _: ReissueTransactionV1 => Right(tx) + case _: ExchangeTransaction => Right(tx) + case _: LeaseTransactionV1 => Right(tx) + case _: LeaseCancelTransactionV1 => Right(tx) + case _: CreateAliasTransactionV1 => Right(tx) + case _: MassTransferTransaction => activationBarrier(BlockchainFeatures.MassTransfer) + case _: DataTransaction => activationBarrier(BlockchainFeatures.DataTransaction) + case _: SetScriptTransaction => activationBarrier(BlockchainFeatures.SmartAccounts) + case _: TransferTransactionV2 => activationBarrier(BlockchainFeatures.SmartAccounts) + case _: IssueTransactionV2 => activationBarrier(BlockchainFeatures.SmartAccounts) + case _: ReissueTransactionV2 => activationBarrier(BlockchainFeatures.SmartAccounts) case _: LeaseTransactionV2 => activationBarrier(BlockchainFeatures.SmartAccounts) - case _: LeaseCancelTransactionV2 =>activationBarrier(BlockchainFeatures.SmartAccounts) + case _: LeaseCancelTransactionV2 => activationBarrier(BlockchainFeatures.SmartAccounts) case _: CreateAliasTransactionV2 => activationBarrier(BlockchainFeatures.SmartAccounts) - case _:SponsorFeeTransaction => activationBarrier(BlockchainFeatures.FeeSponsorship) - case _ => Left(GenericError("Unknown transaction must be explicitly activated")) + case _: SponsorFeeTransaction => activationBarrier(BlockchainFeatures.FeeSponsorship) + case _ => Left(GenericError("Unknown transaction must be explicitly activated")) } } diff --git a/src/main/scala/scorex/api/http/TransactionsApiRoute.scala b/src/main/scala/scorex/api/http/TransactionsApiRoute.scala index d1b8f2745cb..92257846195 100644 --- a/src/main/scala/scorex/api/http/TransactionsApiRoute.scala +++ b/src/main/scala/scorex/api/http/TransactionsApiRoute.scala @@ -170,23 +170,23 @@ case class TransactionsApiRoute(settings: RestAPISettings, case None => Left(GenericError(s"Bad transaction type ($typeId) and version ($version)")) case Some(x) => x match { - case IssueTransactionV1 => TransactionFactory.issueAssetV1(jsv.as[IssueV1Request], wallet, time) - case IssueTransactionV2 => TransactionFactory.issueAssetV2(jsv.as[IssueV2Request], wallet, time) - case TransferTransactionV1 => TransactionFactory.transferAssetV1(jsv.as[TransferV1Request], wallet, time) - case TransferTransactionV2 => TransactionFactory.transferAssetV2(jsv.as[TransferV2Request], wallet, time) - case ReissueTransactionV1 => TransactionFactory.reissueAssetV1(jsv.as[ReissueV1Request], wallet, time) - case ReissueTransactionV2 => TransactionFactory.reissueAssetV2(jsv.as[ReissueV2Request], wallet, time) - case BurnTransaction => TransactionFactory.burnAsset(jsv.as[BurnRequest], wallet, time) - case MassTransferTransaction => TransactionFactory.massTransferAsset(jsv.as[MassTransferRequest], wallet, time) + case IssueTransactionV1 => TransactionFactory.issueAssetV1(jsv.as[IssueV1Request], wallet, time) + case IssueTransactionV2 => TransactionFactory.issueAssetV2(jsv.as[IssueV2Request], wallet, time) + case TransferTransactionV1 => TransactionFactory.transferAssetV1(jsv.as[TransferV1Request], wallet, time) + case TransferTransactionV2 => TransactionFactory.transferAssetV2(jsv.as[TransferV2Request], wallet, time) + case ReissueTransactionV1 => TransactionFactory.reissueAssetV1(jsv.as[ReissueV1Request], wallet, time) + case ReissueTransactionV2 => TransactionFactory.reissueAssetV2(jsv.as[ReissueV2Request], wallet, time) + case BurnTransaction => TransactionFactory.burnAsset(jsv.as[BurnRequest], wallet, time) + case MassTransferTransaction => TransactionFactory.massTransferAsset(jsv.as[MassTransferRequest], wallet, time) case LeaseTransactionV1 => TransactionFactory.leaseV1(jsv.as[LeaseV1Request], wallet, time) - case LeaseTransactionV2 => TransactionFactory.leaseV2(jsv.as[LeaseV2Request], wallet, time) - case LeaseCancelTransactionV1 => TransactionFactory.leaseCancelV1(jsv.as[LeaseCancelV1Request], wallet, time) + case LeaseTransactionV2 => TransactionFactory.leaseV2(jsv.as[LeaseV2Request], wallet, time) + case LeaseCancelTransactionV1 => TransactionFactory.leaseCancelV1(jsv.as[LeaseCancelV1Request], wallet, time) case LeaseCancelTransactionV2 => TransactionFactory.leaseCancelV2(jsv.as[LeaseCancelV2Request], wallet, time) - case CreateAliasTransactionV1 => TransactionFactory.aliasV1(jsv.as[CreateAliasV1Request], wallet, time) + case CreateAliasTransactionV1 => TransactionFactory.aliasV1(jsv.as[CreateAliasV1Request], wallet, time) case CreateAliasTransactionV2 => TransactionFactory.aliasV2(jsv.as[CreateAliasV2Request], wallet, time) - case DataTransaction => TransactionFactory.data(jsv.as[DataRequest], wallet, time) - case SetScriptTransaction => TransactionFactory.setScript(jsv.as[SetScriptRequest], wallet, time) - case SponsorFeeTransaction => TransactionFactory.sponsor(jsv.as[SponsorFeeRequest], wallet, time) + case DataTransaction => TransactionFactory.data(jsv.as[DataRequest], wallet, time) + case SetScriptTransaction => TransactionFactory.setScript(jsv.as[SetScriptRequest], wallet, time) + case SponsorFeeTransaction => TransactionFactory.sponsor(jsv.as[SponsorFeeRequest], wallet, time) } } r match { @@ -217,23 +217,23 @@ case class TransactionsApiRoute(settings: RestAPISettings, case None => Left(GenericError(s"Bad transaction type ($typeId) and version ($version)")) case Some(x) => x match { - case IssueTransactionV1 => jsv.as[SignedIssueV1Request].toTx - case IssueTransactionV2 => jsv.as[SignedIssueV2Request].toTx - case TransferTransactionV1 => jsv.as[SignedTransferV1Request].toTx - case TransferTransactionV2 => jsv.as[SignedTransferV2Request].toTx - case MassTransferTransaction => jsv.as[SignedMassTransferRequest].toTx - case ReissueTransactionV1 => jsv.as[SignedReissueV1Request].toTx - case ReissueTransactionV2 => jsv.as[SignedReissueV2Request].toTx - case BurnTransaction => jsv.as[SignedBurnRequest].toTx + case IssueTransactionV1 => jsv.as[SignedIssueV1Request].toTx + case IssueTransactionV2 => jsv.as[SignedIssueV2Request].toTx + case TransferTransactionV1 => jsv.as[SignedTransferV1Request].toTx + case TransferTransactionV2 => jsv.as[SignedTransferV2Request].toTx + case MassTransferTransaction => jsv.as[SignedMassTransferRequest].toTx + case ReissueTransactionV1 => jsv.as[SignedReissueV1Request].toTx + case ReissueTransactionV2 => jsv.as[SignedReissueV2Request].toTx + case BurnTransaction => jsv.as[SignedBurnRequest].toTx case LeaseTransactionV1 => jsv.as[SignedLeaseV1Request].toTx - case LeaseTransactionV2 => jsv.as[SignedLeaseV2Request].toTx - case LeaseCancelTransactionV1 => jsv.as[SignedLeaseCancelV1Request].toTx + case LeaseTransactionV2 => jsv.as[SignedLeaseV2Request].toTx + case LeaseCancelTransactionV1 => jsv.as[SignedLeaseCancelV1Request].toTx case LeaseCancelTransactionV2 => jsv.as[SignedLeaseCancelV2Request].toTx - case CreateAliasTransactionV1 => jsv.as[SignedCreateAliasV1Request].toTx + case CreateAliasTransactionV1 => jsv.as[SignedCreateAliasV1Request].toTx case CreateAliasTransactionV2 => jsv.as[SignedCreateAliasV2Request].toTx - case DataTransaction => jsv.as[SignedDataRequest].toTx - case SetScriptTransaction => jsv.as[SignedSetScriptRequest].toTx - case SponsorFeeTransaction => jsv.as[SignedSponsorFeeRequest].toTx + case DataTransaction => jsv.as[SignedDataRequest].toTx + case SetScriptTransaction => jsv.as[SignedSetScriptRequest].toTx + case SponsorFeeTransaction => jsv.as[SignedSponsorFeeRequest].toTx } } From 49f1f320fa37bf9a34f2b36bdebc663517e232d5 Mon Sep 17 00:00:00 2001 From: alexandr Date: Sat, 28 Apr 2018 16:52:06 +0300 Subject: [PATCH 4/4] NODE-496 Simplified common validation matching --- .../state/diffs/CommonValidation.scala | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/main/scala/com/wavesplatform/state/diffs/CommonValidation.scala b/src/main/scala/com/wavesplatform/state/diffs/CommonValidation.scala index 9baa1c79420..06b1cc4862a 100644 --- a/src/main/scala/com/wavesplatform/state/diffs/CommonValidation.scala +++ b/src/main/scala/com/wavesplatform/state/diffs/CommonValidation.scala @@ -10,7 +10,7 @@ import scorex.transaction.ValidationError._ import scorex.transaction._ import scorex.transaction.assets._ import scorex.transaction.assets.exchange.ExchangeTransaction -import scorex.transaction.lease.{LeaseCancelTransactionV1, LeaseCancelTransactionV2, LeaseTransactionV1, LeaseTransactionV2} +import scorex.transaction.lease._ import scorex.transaction.smart.SetScriptTransaction import scorex.transaction.transfer._ @@ -136,21 +136,17 @@ object CommonValidation { def feeInUnits: Either[ValidationError, Int] = tx match { case _: GenesisTransaction => Right(0) case _: PaymentTransaction => Right(1) - case _: IssueTransactionV1 => Right(1000) - case _: IssueTransactionV2 => Right(1000) + case _: IssueTransaction => Right(1000) case _: ReissueTransaction => Right(1000) case _: BurnTransaction => Right(1) - case _: TransferTransactionV1 => Right(1) + case _: TransferTransaction => Right(1) case tx: MassTransferTransaction => Right(1 + (tx.transfers.size + 1) / 2) - case _: LeaseTransactionV1 => Right(1) - case _: LeaseTransactionV2 => Right(1) - case _: LeaseCancelTransactionV1 => Right(1) - case _: LeaseCancelTransactionV2 => Right(1) + case _: LeaseTransaction => Right(1) + case _: LeaseCancelTransaction => Right(1) case _: ExchangeTransaction => Right(3) - case _: CreateAliasTransactionV1 => Right(1) + case _: CreateAliasTransaction => Right(1) case tx: DataTransaction => Right(1 + (tx.bytes().length - 1) / 1024) case _: SetScriptTransaction => Right(1) - case _: TransferTransactionV2 => Right(1) case _: SponsorFeeTransaction => Right(1000) case _ => Left(UnsupportedTransactionType) }