Skip to content

Commit

Permalink
NODE-2476 Check asset id field size (#3716)
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-mashonskiy authored Jul 7, 2023
1 parent 51616ba commit 961e643
Show file tree
Hide file tree
Showing 21 changed files with 176 additions and 118 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ object ByteStr {

def fromLong(longValue: Long): ByteStr = {
val buf = new Array[Byte](8)
var b = longValue
var b = longValue

for (i <- (buf.length - 1) to 0 by -1) {
buf(i) = b.toByte
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import com.typesafe.config.{Config, ConfigFactory}
import com.wavesplatform.common.state.ByteStr
import com.wavesplatform.common.utils.EitherExt2
import com.wavesplatform.it.NodeConfigs
import com.wavesplatform.it.api.SyncHttpApi._
import com.wavesplatform.it.sync._
import com.wavesplatform.it.api.SyncHttpApi.*
import com.wavesplatform.it.sync.*
import com.wavesplatform.it.transactions.BaseTransactionSuite
import com.wavesplatform.lang.v1.estimator.v2.ScriptEstimatorV2
import com.wavesplatform.test._
import com.wavesplatform.transaction.Asset
import com.wavesplatform.test.*
import com.wavesplatform.transaction.{Asset, AssetIdLength}
import com.wavesplatform.transaction.smart.script.ScriptCompiler
import org.scalatest.CancelAfterFailure

import scala.concurrent.duration._
import scala.concurrent.duration.*

class Ride4DAppsActivationTestSuite extends BaseTransactionSuite with CancelAfterFailure {
private val estimator = ScriptEstimatorV2
Expand Down Expand Up @@ -113,7 +113,7 @@ class Ride4DAppsActivationTestSuite extends BaseTransactionSuite with CancelAfte
test("can't set script with user function to asset before Ride4DApps activation") {
assertBadRequestAndMessage(
sender.setAssetScript(
Asset.IssuedAsset(ByteStr("Test".getBytes("UTF-8"))).id.toString,
Asset.IssuedAsset(ByteStr.fill(AssetIdLength)(1)).id.toString,
smartAcc,
issueFee,
Some(scriptV2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.typesafe.config.Config

import scala.util.{Random, Try}
import com.wavesplatform.account.{AddressScheme, KeyPair}
import com.wavesplatform.api.http.ApiError.WrongJson
import com.wavesplatform.features.BlockchainFeatures.RideV6
import com.wavesplatform.it.NodeConfigs
import com.wavesplatform.it.NodeConfigs.Default
Expand Down Expand Up @@ -120,7 +121,7 @@ class AliasTransactionSuite extends BaseTransactionSuite with TableDrivenPropert
("aliasName", "message"),
("", "Alias '' length should be between 4 and 30"),
("abc", "Alias 'abc' length should be between 4 and 30"),
(null, "failed to parse json message"),
(null, WrongJson.WrongJsonDataMessage),
("morethen_thirtycharactersinline", "Alias 'morethen_thirtycharactersinline' length should be between 4 and 30"),
("~!|#$%^&*()_+=\";:/?><|\\][{}", "Alias should contain only following characters: -.0123456789@_abcdefghijklmnopqrstuvwxyz"),
("multilnetest\ntest", "Alias should contain only following characters: -.0123456789@_abcdefghijklmnopqrstuvwxyz"),
Expand All @@ -143,7 +144,7 @@ class AliasTransactionSuite extends BaseTransactionSuite with TableDrivenPropert

val aliasFee = createAlias(thirdKeyPair, thirdAddressAlias)
val aliasFull = fullAliasByAddress(thirdAddress, thirdAddressAlias)
//lease maximum value, to pass next thirdAddress
// lease maximum value, to pass next thirdAddress
val leasingAmount = balance1 - minFee - 0.5.waves

val leasingTx = sender.lease(firstKeyPair, aliasFull, leasingAmount, minFee).id
Expand All @@ -154,7 +155,7 @@ class AliasTransactionSuite extends BaseTransactionSuite with TableDrivenPropert

}

//previous test should not be commented to run this one
// previous test should not be commented to run this one
test("Not able to create alias when insufficient funds") {
for (v <- aliasTxSupportedVersions) {
val balance = miner.accountBalances(firstAddress)._1
Expand All @@ -177,7 +178,15 @@ class AliasTransactionSuite extends BaseTransactionSuite with TableDrivenPropert
)

val kp = KeyPair(Longs.toByteArray(Random.nextLong()))
val cat = CreateAliasTransaction(3.toByte, notMiner.publicKey, "abc12345", TxPositiveAmount.unsafeFrom(0.005.waves), System.currentTimeMillis(), Proofs.empty, AddressScheme.current.chainId)
val cat = CreateAliasTransaction(
3.toByte,
notMiner.publicKey,
"abc12345",
TxPositiveAmount.unsafeFrom(0.005.waves),
System.currentTimeMillis(),
Proofs.empty,
AddressScheme.current.chainId
)
val signedCreateAlias = cat.copy(
proofs = cat.signWith(notMiner.keyPair.privateKey).proofs.proofs ++ cat.signWith(kp.privateKey).proofs.proofs
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@ package com.wavesplatform.it.sync.transactions
import com.google.common.primitives.Ints
import com.typesafe.config.Config
import com.wavesplatform.account.{AddressScheme, KeyPair}
import com.wavesplatform.api.http.ApiError.{CustomValidationError, TooBigArrayAllocation}
import com.wavesplatform.api.http.ApiError.{CustomValidationError, TooBigArrayAllocation, WrongJson}
import com.wavesplatform.common.state.ByteStr
import com.wavesplatform.common.utils.{Base58, EitherExt2}
import com.wavesplatform.it.NodeConfigs
import com.wavesplatform.it.api.SyncHttpApi._
import com.wavesplatform.it.api.SyncHttpApi.*
import com.wavesplatform.it.api.{TransactionInfo, UnexpectedStatusCodeException}
import com.wavesplatform.it.sync.{calcDataFee, minFee, _}
import com.wavesplatform.it.sync.{calcDataFee, minFee, *}
import com.wavesplatform.it.transactions.BaseTransactionSuite
import com.wavesplatform.test._
import com.wavesplatform.test.*
import com.wavesplatform.lang.v1.estimator.ScriptEstimatorV1
import com.wavesplatform.state.{BinaryDataEntry, BooleanDataEntry, DataEntry, EmptyDataEntry, IntegerDataEntry, StringDataEntry}
import com.wavesplatform.transaction.smart.script.ScriptCompiler
import com.wavesplatform.transaction.{DataTransaction, Proofs, TxVersion}
import org.scalatest.{Assertion, Assertions, EitherValues}
import play.api.libs.json._
import play.api.libs.json.*

import scala.concurrent.duration._
import scala.concurrent.duration.*
import scala.util.{Failure, Random, Try}

class DataTransactionSuite extends BaseTransactionSuite with EitherValues {
Expand Down Expand Up @@ -53,10 +53,10 @@ class DataTransactionSuite extends BaseTransactionSuite with EitherValues {
ScriptCompiler
.compile(
"""{-# STDLIB_VERSION 2 #-}
|{-# CONTENT_TYPE EXPRESSION #-}
|{-# SCRIPT_TYPE ACCOUNT #-}
|
|true""".stripMargin,
|{-# CONTENT_TYPE EXPRESSION #-}
|{-# SCRIPT_TYPE ACCOUNT #-}
|
|true""".stripMargin,
ScriptEstimatorV1
)
.explicitGet()
Expand Down Expand Up @@ -127,7 +127,7 @@ class DataTransactionSuite extends BaseTransactionSuite with EitherValues {
CustomValidationError("Duplicated keys found")
)

//able to "remove" nonexistent key (account state won't be changed, but transaction should be succesfully broadcasted)
// able to "remove" nonexistent key (account state won't be changed, but transaction should be succesfully broadcasted)
sender.broadcastData(
sender.keyPair,
List(EmptyDataEntry("nonexistentkey")),
Expand Down Expand Up @@ -224,15 +224,15 @@ class DataTransactionSuite extends BaseTransactionSuite with EitherValues {
}

test("max transaction size") {
//Max size of transaction V1
// Max size of transaction V1
val maxKeySizeV1 = 100
val key = "\u6fae" * (maxKeySizeV1 - 1)
val data = List.tabulate(26)(n => BinaryDataEntry(key + n.toChar, ByteStr(Array.fill(5599)(n.toByte))))
val fee = calcDataFee(data, TxVersion.V1)
val txId = sender.putData(firstKeyPair, data, fee, version = TxVersion.V1).id
nodes.waitForTransaction(txId)

//Max size of transaction V2
// Max size of transaction V2
val maxKeySizeV2 = 400
val key2 = "u" * (maxKeySizeV2 - 1)
val data2 = List.tabulate(5)(n => BinaryDataEntry(key2 + n.toChar, ByteStr(Array.fill(Short.MaxValue)(n.toByte))))
Expand Down Expand Up @@ -312,9 +312,9 @@ class DataTransactionSuite extends BaseTransactionSuite with EitherValues {
val keys = Seq("int", "bool", "int", "blob", "?&$#^123\\/.a:;'\"\r\n\t\u0000|%è&", "str", "inexisted_key", tooBigKey)
val values = Seq[Any](-127, false, -127, ByteStr(Array[Byte](127.toByte, 0, 1, 1)), "specïal", "BBBB")

val list = sender.getDataList(secondAddress, keys *).map(_.value)
val jsonList = sender.getDataListJson(secondAddress, keys *).map(_.value)
val postList = sender.getDataListPost(secondAddress, keys *).map(_.value)
val list = sender.getDataList(secondAddress, keys*).map(_.value)
val jsonList = sender.getDataListJson(secondAddress, keys*).map(_.value)
val postList = sender.getDataListPost(secondAddress, keys*).map(_.value)

list shouldBe values
jsonList shouldBe list
Expand Down Expand Up @@ -411,7 +411,7 @@ class DataTransactionSuite extends BaseTransactionSuite with EitherValues {
def id(obj: JsObject): String = obj.value("id").as[String]

val noProof = request - "proofs"
assertBadRequestAndResponse(sender.postJson("/transactions/broadcast", noProof), "failed to parse json message.*proofs.*missing")
assertBadRequestAndResponse(sender.postJson("/transactions/broadcast", noProof), s"${WrongJson.WrongJsonDataMessage}.*proofs.*missing")
nodes.foreach(_.ensureTxDoesntExist(id(noProof)))

val badProof = request ++ Json.obj("proofs" -> Seq(Base58.encode(Array.fill(64)(Random.nextInt().toByte))))
Expand Down Expand Up @@ -479,16 +479,15 @@ class DataTransactionSuite extends BaseTransactionSuite with EitherValues {

test("try to make address with 1000 DataEntries") {
for (v <- dataTxSupportedVersions) {
val dataSet = 0 until 200 flatMap (
i =>
List(
IntegerDataEntry(s"int$i", 1000 + i),
BooleanDataEntry(s"bool$i", false),
BinaryDataEntry(s"blob$i", ByteStr(Array[Byte](127.toByte, 0, 1, 1))),
StringDataEntry(s"str$i", s"hi there! + $i"),
IntegerDataEntry(s"integer$i", 1000 - i)
)
val dataSet = 0 until 200 flatMap (i =>
List(
IntegerDataEntry(s"int$i", 1000 + i),
BooleanDataEntry(s"bool$i", false),
BinaryDataEntry(s"blob$i", ByteStr(Array[Byte](127.toByte, 0, 1, 1))),
StringDataEntry(s"str$i", s"hi there! + $i"),
IntegerDataEntry(s"integer$i", 1000 - i)
)
)

val txIds = dataSet.grouped(100).map(_.toList).map(data => sender.putData(fourthKeyPair, data, calcDataFee(data, v), version = v).id)
txIds foreach nodes.waitForTransaction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.wavesplatform.it.sync.transactions

import com.google.protobuf.ByteString
import com.wavesplatform.account.{Address, AddressScheme, Alias}
import com.wavesplatform.api.http.ApiError.WrongJson
import com.wavesplatform.api.http.requests.{MassTransferRequest, SignedMassTransferRequest}
import com.wavesplatform.common.state.ByteStr
import com.wavesplatform.common.utils.EitherExt2
Expand Down Expand Up @@ -262,7 +263,7 @@ class MassTransferTransactionSuite extends BaseTransactionSuite {
def id(obj: JsObject) = obj.value("id").as[String]

val noProof = signedMassTransfer - "proofs"
assertBadRequestAndResponse(sender.postJson("/transactions/broadcast", noProof), "failed to parse json message.*proofs.*missing")
assertBadRequestAndResponse(sender.postJson("/transactions/broadcast", noProof), s"${WrongJson.WrongJsonDataMessage}.*proofs.*missing")
nodes.foreach(_.ensureTxDoesntExist(id(noProof)))

val badProof = signedMassTransfer ++ Json.obj("proofs" -> Seq(fakeSignature.toString))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@ class SetAssetScriptTransactionSuite extends BaseTransactionSuite {
)
assertApiError(
broadcastSetAssetScriptJson(assetWOScript, firstKeyPair, setAssetScriptFee, version = v),
AssertiveApiError(WrongJson.Id, "failed to parse json message", matchMessage = true)
AssertiveApiError(WrongJson.Id, WrongJson.WrongJsonDataMessage, matchMessage = true)
)
assertApiError(
broadcastSetAssetScriptJson(assetWOScript, firstKeyPair, setAssetScriptFee, Some(""), version = v),
AssertiveApiError(WrongJson.Id, "failed to parse json message", matchMessage = true)
AssertiveApiError(WrongJson.Id, WrongJson.WrongJsonDataMessage, matchMessage = true)
)
miner.assertBalances(firstAddress, balance, eff)
}
Expand Down Expand Up @@ -158,7 +158,7 @@ class SetAssetScriptTransactionSuite extends BaseTransactionSuite {
}
assertApiError(broadcastSetAssetScriptJson(assetWAnotherOwner, secondKeyPair, setAssetScriptFee, Some(""), version = v)) { error =>
error.id shouldBe WrongJson.Id
error.message shouldBe "failed to parse json message"
error.message shouldBe WrongJson.WrongJsonDataMessage
}
}
}
Expand All @@ -180,10 +180,10 @@ class SetAssetScriptTransactionSuite extends BaseTransactionSuite {
test("sender's waves balance is decreased by fee") {
val script2 = ScriptCompiler(
s"""
|match tx {
| case _: SetAssetScriptTransaction => true
| case _ => false
|}
|match tx {
| case _: SetAssetScriptTransaction => true
| case _ => false
|}
""".stripMargin,
isAssetScript = true,
estimator
Expand Down Expand Up @@ -253,7 +253,7 @@ class SetAssetScriptTransactionSuite extends BaseTransactionSuite {
),
(
sastx(assetId = IssuedAsset(ByteStr.decodeBase58("9ekQuYn92natMnMq8KqeGK3Nn7cpKd3BvPEGgD6fFyyz9ekQuYn92natMnMq8").get)),
AssertiveApiError(WrongJson.Id, "failed to parse json", StatusCodes.BadRequest, true)
AssertiveApiError(WrongJson.Id, WrongJson.WrongJsonDataMessage, StatusCodes.BadRequest, true)
),
(
sastx(assetId = IssuedAsset(ByteStr.decodeBase58("9ekQuYn92natMnMq8KqeGK3Nn7cpKd3BvPEGgD6fFyyz").get)),
Expand Down Expand Up @@ -290,7 +290,7 @@ class SetAssetScriptTransactionSuite extends BaseTransactionSuite {

val noProof = request - "proofs"
assertApiError(sender.postJson("/transactions/broadcast", noProof)) { error =>
error.message should include regex "failed to parse json message"
error.message should include regex WrongJson.WrongJsonDataMessage

val validationErrors = (error.json \ "validationErrors" \ "obj.proofs").as[JsArray].value.flatMap(json => (json \ "msg").as[List[String]])
validationErrors should contain("error.path.missing")
Expand All @@ -313,10 +313,10 @@ class SetAssetScriptTransactionSuite extends BaseTransactionSuite {
test("try to update script to null") {
for (v <- setAssetScrTxSupportedVersions) {
assertApiError(broadcastSetAssetScriptJson(assetWScript, firstKeyPair, setAssetScriptFee, version = v)) { error =>
error.message should include regex "failed to parse json message"
error.message should include regex WrongJson.WrongJsonDataMessage
}
assertApiError(broadcastSetAssetScriptJson(assetWScript, firstKeyPair, setAssetScriptFee, Some(""), version = v)) { error =>
error.message should include regex "failed to parse json message"
error.message should include regex WrongJson.WrongJsonDataMessage
}
}
}
Expand Down Expand Up @@ -401,7 +401,7 @@ class SetAssetScriptTransactionSuite extends BaseTransactionSuite {

nodes.waitForHeightAriseAndTxPresent(tx)

//try to change unchangeable script
// try to change unchangeable script
val nonIssuerUnsignedTx2 = SetAssetScriptTransaction(
version = v,
accountA.publicKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.wavesplatform.it.sync.transactions

import com.typesafe.config.Config
import com.wavesplatform.account.{AddressScheme, PublicKey}
import com.wavesplatform.api.http.ApiError.WrongJson
import com.wavesplatform.api.http.requests.TransferRequest
import com.wavesplatform.common.state.ByteStr
import com.wavesplatform.common.utils.{Base58, EitherExt2}
Expand Down Expand Up @@ -59,9 +60,9 @@ class SignAndBroadcastApiSuite extends BaseTransactionSuite with NTPTime with Be
for (v <- supportedVersions) {
val json = Json.obj("type" -> CreateAliasTransaction.typeId, "sender" -> firstAddress, "alias" -> "alias", "fee" -> 100000)
val js = if (Option(v).isDefined) json ++ Json.obj("version" -> v) else json
assertSignBadJson(js - "type", "failed to parse json message")
assertSignBadJson(js - "type", WrongJson.WrongJsonDataMessage)
assertSignBadJson(js + ("type" -> JsNumber(-100)), "Bad transaction type")
assertSignBadJson(js - "alias", "failed to parse json message")
assertSignBadJson(js - "alias", WrongJson.WrongJsonDataMessage)
}

val obsoleteTx =
Expand All @@ -78,7 +79,7 @@ class SignAndBroadcastApiSuite extends BaseTransactionSuite with NTPTime with Be
"fee" -> 100000,
"attachment" -> "W" * 524291
)
assertSignBadJson(bigBaseTx, "failed to parse json message")
assertSignBadJson(bigBaseTx, WrongJson.WrongJsonDataMessage)
}

test("/transaction/calculateFee should handle coding size limit") {
Expand All @@ -92,7 +93,7 @@ class SignAndBroadcastApiSuite extends BaseTransactionSuite with NTPTime with Be
"amount" -> 1,
"assetId" -> "W" * 524291
)
assertBadRequestAndMessage(sender.calculateFee(json).feeAmount, "failed to parse json message")
assertBadRequestAndMessage(sender.calculateFee(json).feeAmount, WrongJson.WrongJsonDataMessage)
}
}

Expand Down Expand Up @@ -137,10 +138,10 @@ class SignAndBroadcastApiSuite extends BaseTransactionSuite with NTPTime with Be
assertBroadcastBadJson(jsonV2, "Proof doesn't validate")

for (j <- List(jsonV1, jsonV2)) {
assertBroadcastBadJson(j - "type", "failed to parse json message")
assertBroadcastBadJson(j - "type", WrongJson.WrongJsonDataMessage)
assertBroadcastBadJson(j - "type" + ("type" -> Json.toJson(88)), "Bad transaction type")
assertBroadcastBadJson(j - "chainId" + ("chainId" -> Json.toJson(123)), "Wrong chain-id")
assertBroadcastBadJson(j - "alias", "failed to parse json message")
assertBroadcastBadJson(j - "alias", WrongJson.WrongJsonDataMessage)
}
}

Expand Down
10 changes: 6 additions & 4 deletions node/src/main/scala/com/wavesplatform/api/http/ApiError.scala
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,12 @@ object ApiError {

final case class WrongJson(
cause: Option[Throwable] = None,
errors: scala.collection.Seq[(JsPath, scala.collection.Seq[JsonValidationError])] = Seq.empty
errors: scala.collection.Seq[(JsPath, scala.collection.Seq[JsonValidationError])] = Seq.empty,
msg: Option[String] = None
) extends ApiError {
override val id = WrongJson.Id
override val code = StatusCodes.BadRequest
override val message: String = WrongJson.Message
override val message: String = msg.getOrElse(WrongJson.WrongJsonMessage)
override lazy val json: JsObject = Json.obj(
"error" -> id,
"message" -> message,
Expand All @@ -90,8 +91,9 @@ object ApiError {
)
}
case object WrongJson {
val Id = 1
val Message = "failed to parse json message"
val Id = 1
val WrongJsonMessage = "failed to parse json message"
val WrongJsonDataMessage = "json data validation error, see validationErrors for details"
}

// API Auth
Expand Down
Loading

0 comments on commit 961e643

Please sign in to comment.