From 815296b7a59f9fa081701e10efa41554a6f95394 Mon Sep 17 00:00:00 2001 From: Ivan Mashonskii Date: Fri, 20 May 2022 14:09:38 +0300 Subject: [PATCH] NODE-2471 Fix EIP712Domain (#3708) --- .../assets/exchange/EthOrders.scala | 10 +- .../assets/exchange/EthOrderSpec.scala | 208 +++++++++--------- .../exchange/OrderJsonSpecification.scala | 36 +-- 3 files changed, 133 insertions(+), 121 deletions(-) diff --git a/node/src/main/scala/com/wavesplatform/transaction/assets/exchange/EthOrders.scala b/node/src/main/scala/com/wavesplatform/transaction/assets/exchange/EthOrders.scala index e291b281eb5..f31feaee553 100644 --- a/node/src/main/scala/com/wavesplatform/transaction/assets/exchange/EthOrders.scala +++ b/node/src/main/scala/com/wavesplatform/transaction/assets/exchange/EthOrders.scala @@ -8,7 +8,6 @@ import com.wavesplatform.account.{AddressScheme, PublicKey} import com.wavesplatform.common.state.ByteStr import com.wavesplatform.transaction.Asset import com.wavesplatform.transaction.Asset.{IssuedAsset, Waves} -import org.bouncycastle.util.encoders.Hex import org.web3j.crypto.Sign.SignatureData import org.web3j.crypto.{ECDSASignature, ECKeyPair, Sign, StructuredDataEncoder} import play.api.libs.json.{JsObject, Json} @@ -116,10 +115,6 @@ object EthOrders extends App { | { | "name": "chainId", | "type": "uint256" - | }, - | { - | "name": "verifyingContract", - | "type": "address" | } | ], | "Order": [ @@ -175,10 +170,9 @@ object EthOrders extends App { | }, | "primaryType": "Order", | "domain": { - | "name": "Waves Exchange", + | "name": "Waves Order", | "version": "1", - | "chainId": ${AddressScheme.current.chainId}, - | "verifyingContract": "0x${Hex.toHexString(Array.fill[Byte](20)(AddressScheme.current.chainId))}" + | "chainId": ${AddressScheme.current.chainId} | }, | "message": {} |} diff --git a/node/src/test/scala/com/wavesplatform/transaction/assets/exchange/EthOrderSpec.scala b/node/src/test/scala/com/wavesplatform/transaction/assets/exchange/EthOrderSpec.scala index ab27d415418..2d3ff59496e 100644 --- a/node/src/test/scala/com/wavesplatform/transaction/assets/exchange/EthOrderSpec.scala +++ b/node/src/test/scala/com/wavesplatform/transaction/assets/exchange/EthOrderSpec.scala @@ -26,8 +26,10 @@ class EthOrderSpec "ETH signed order" should "recover signer public key correctly" in { val testOrder = Order( Order.V4, - OrderAuthentication(TestEthOrdersPublicKey), - TestEthOrdersPublicKey, + EthSignature( + "0xfe56e1cbd6945f1e17ce9f9eb21172dd7810bcc74651dd7d3eaeca5d9ae0409113e5236075841af8195cb4dba3947ae9b99dbd560fd0c43afe89cc0b648690321c" + ), + PublicKey(EthStubBytes32), AssetPair(IssuedAsset(ByteStr(EthStubBytes32)), IssuedAsset(ByteStr(EthStubBytes32))), OrderType.BUY, TxExchangeAmount.unsafeFrom(1), @@ -38,12 +40,7 @@ class EthOrderSpec IssuedAsset(ByteStr(EthStubBytes32)) ) - val signature = - EthEncoding.toBytes( - "0xdac6583ff5596ab9583b3d52ad3242a17fe4a2c7f7e937f3e75544e16012521706c5ee2aaa9faefce03c6566b8c1f8c8a6a98b4760e71ed24ae22f0a12f52b441c" - ) - - val result = EthOrders.recoverEthSignerKey(testOrder, signature) + val result = EthOrders.recoverEthSignerKey(testOrder, testOrder.eip712Signature.get.arr) result shouldBe TestEthOrdersPublicKey result.toAddress shouldBe TestEthOrdersPublicKey.toAddress } @@ -102,19 +99,21 @@ class EthOrderSpec sh.issueAsset(ByteStr(EthStubBytes32)) } - val buyOrder = Order.selfSigned( - Order.V3, - TxHelpers.defaultSigner, - TxHelpers.matcher.publicKey, - AssetPair(IssuedAsset(ByteStr(EthStubBytes32)), Waves), - OrderType.BUY, - 1, - 100L, - 1, - 123, - 100000, - Waves - ).explicitGet() + val buyOrder = Order + .selfSigned( + Order.V3, + TxHelpers.defaultSigner, + TxHelpers.matcher.publicKey, + AssetPair(IssuedAsset(ByteStr(EthStubBytes32)), Waves), + OrderType.BUY, + 1, + 100L, + 1, + 123, + 100000, + Waves + ) + .explicitGet() val differ = TransactionDiffer(Some(1L), 100L)(blockchain, _) val transaction = TxHelpers.exchange(buyOrder, ethSellOrder, price = 100, version = TxVersion.V3, timestamp = 100) @@ -143,7 +142,8 @@ class EthOrderSpec 123, 100000, Waves - ).explicitGet() + ) + .explicitGet() .withProofs(TxHelpers.signature("2Bi5YFCeAUvQqWFJYUTzaDUfAdoHmQ4RC6nviBwvQgUYJLKrsa4T5eESGr5Er261kdeyNgHVJUGai8mALtLLWDoQ")) val sellOrder = ethSellOrder.copy(orderAuthentication = @@ -155,71 +155,81 @@ class EthOrderSpec StubHelpers(blockchain).creditBalance(sellOrder.senderAddress, *) val transaction = TxHelpers - .exchange(buyOrder, sellOrder, price = 100, buyMatcherFee = buyOrder.matcherFee.value, sellMatcherFee = sellOrder.matcherFee.value, version = TxVersion.V3, timestamp = 100) + .exchange( + buyOrder, + sellOrder, + price = 100, + buyMatcherFee = buyOrder.matcherFee.value, + sellMatcherFee = sellOrder.matcherFee.value, + version = TxVersion.V3, + timestamp = 100 + ) .copy(proofs = TxHelpers.signature("4WrABDgkk9JraBLNQK4LTq7LWqVLgLzAEv8fr1rjr4ovca7224EBzLrEgcHdtHscGpQbLsk39ttQfqHMVLr9tXcB")) - transaction.json() should matchJson("""{ - | "type": 7, - | "id": "GtWWteMgnVYeAq4BSbqw9aFM3K17zHrYsij14VtJiVdL", - | "fee": 1000000, - | "feeAssetId": null, - | "timestamp": 100, - | "version": 3, - | "chainId": 84, - | "sender": "3MtGzgmNa5fMjGCcPi5nqMTdtZkfojyWHL9", - | "senderPublicKey": "9BUoYQYq7K38mkk61q8aMH9kD9fKSVL1Fib7FbH6nUkQ", - | "proofs": [ - | "4WrABDgkk9JraBLNQK4LTq7LWqVLgLzAEv8fr1rjr4ovca7224EBzLrEgcHdtHscGpQbLsk39ttQfqHMVLr9tXcB" - | ], - | "order1": { - | "version": 3, - | "id": "75YqwVQbiQmLMQBE61W1aLcsaAUnWbzM5Udh9Z4mXUBf", - | "sender": "3MtGzgmNa5fMjGCcPi5nqMTdtZkfojyWHL9", - | "senderPublicKey": "9BUoYQYq7K38mkk61q8aMH9kD9fKSVL1Fib7FbH6nUkQ", - | "matcherPublicKey": "9BUoYQYq7K38mkk61q8aMH9kD9fKSVL1Fib7FbH6nUkQ", - | "assetPair": { - | "amountAsset": "5fQPsn8hoaVddFG26cWQ5QFdqxWtUPNaZ9zH2E6LYzFn", - | "priceAsset": null - | }, - | "orderType": "buy", - | "amount": 1, - | "price": 100, - | "timestamp": 1, - | "expiration": 123, - | "matcherFee": 100000, - | "signature": "2Bi5YFCeAUvQqWFJYUTzaDUfAdoHmQ4RC6nviBwvQgUYJLKrsa4T5eESGr5Er261kdeyNgHVJUGai8mALtLLWDoQ", - | "proofs": [ - | "2Bi5YFCeAUvQqWFJYUTzaDUfAdoHmQ4RC6nviBwvQgUYJLKrsa4T5eESGr5Er261kdeyNgHVJUGai8mALtLLWDoQ" - | ], - | "matcherFeeAssetId": null - | }, - | "order2": { - | "version": 4, - | "id": "6tXL591oH3mnwgFcbxqQnqHBF1oQ1Cc6hdLuBU6FB6UG", - | "sender": "3MvELtsVTCQWjjzVVWLVHDaSDNGxoviwjng", - | "senderPublicKey": "CHzosnszumJmrh9Yd86Dgf6THq2adzK3RuRmwAWBoU5KdsGJjQmPERHjFLB2eHkDNVnq17cYPk3RZaSiLRkcU96", - | "matcherPublicKey": "9BUoYQYq7K38mkk61q8aMH9kD9fKSVL1Fib7FbH6nUkQ", - | "assetPair": { - | "amountAsset": "5fQPsn8hoaVddFG26cWQ5QFdqxWtUPNaZ9zH2E6LYzFn", - | "priceAsset": null - | }, - | "orderType": "sell", - | "amount": 1, - | "price": 100, - | "timestamp": 1, - | "expiration": 123, - | "matcherFee": 100000, - | "signature": "", - | "proofs": [], - | "matcherFeeAssetId": null, - | "eip712Signature": "0x6c4385dd5f6f1200b4d0630c9076104f34c801c16a211e505facfd743ba242db4429b966ffa8d2a9aff9037dafda78cfc8f7c5ef1c94493f5954bc7ebdb649281b", - | "priceMode": null - | }, - | "amount": 1, - | "price": 100, - | "buyMatcherFee": 100000, - | "sellMatcherFee": 100000 - |}""".stripMargin) + transaction.json() should matchJson( + """{ + | "type": 7, + | "id": "GtWWteMgnVYeAq4BSbqw9aFM3K17zHrYsij14VtJiVdL", + | "fee": 1000000, + | "feeAssetId": null, + | "timestamp": 100, + | "version": 3, + | "chainId": 84, + | "sender": "3MtGzgmNa5fMjGCcPi5nqMTdtZkfojyWHL9", + | "senderPublicKey": "9BUoYQYq7K38mkk61q8aMH9kD9fKSVL1Fib7FbH6nUkQ", + | "proofs": [ + | "4WrABDgkk9JraBLNQK4LTq7LWqVLgLzAEv8fr1rjr4ovca7224EBzLrEgcHdtHscGpQbLsk39ttQfqHMVLr9tXcB" + | ], + | "order1": { + | "version": 3, + | "id": "75YqwVQbiQmLMQBE61W1aLcsaAUnWbzM5Udh9Z4mXUBf", + | "sender": "3MtGzgmNa5fMjGCcPi5nqMTdtZkfojyWHL9", + | "senderPublicKey": "9BUoYQYq7K38mkk61q8aMH9kD9fKSVL1Fib7FbH6nUkQ", + | "matcherPublicKey": "9BUoYQYq7K38mkk61q8aMH9kD9fKSVL1Fib7FbH6nUkQ", + | "assetPair": { + | "amountAsset": "5fQPsn8hoaVddFG26cWQ5QFdqxWtUPNaZ9zH2E6LYzFn", + | "priceAsset": null + | }, + | "orderType": "buy", + | "amount": 1, + | "price": 100, + | "timestamp": 1, + | "expiration": 123, + | "matcherFee": 100000, + | "signature": "2Bi5YFCeAUvQqWFJYUTzaDUfAdoHmQ4RC6nviBwvQgUYJLKrsa4T5eESGr5Er261kdeyNgHVJUGai8mALtLLWDoQ", + | "proofs": [ + | "2Bi5YFCeAUvQqWFJYUTzaDUfAdoHmQ4RC6nviBwvQgUYJLKrsa4T5eESGr5Er261kdeyNgHVJUGai8mALtLLWDoQ" + | ], + | "matcherFeeAssetId": null + | }, + | "order2": { + | "version": 4, + | "id": "6tXL591oH3mnwgFcbxqQnqHBF1oQ1Cc6hdLuBU6FB6UG", + | "sender": "3Mvrr424JENHdP4wrSFyNWBVEuQTHBDxMVi", + | "senderPublicKey": "4nZcsfxa3mtAg8D2iR8J139CTVm7Y2aTEd3B8J6p45tX6v8sjCT9JGAWnHGa8ZxenQyaSAVu3FPsry1RnXucpcqE", + | "matcherPublicKey": "9BUoYQYq7K38mkk61q8aMH9kD9fKSVL1Fib7FbH6nUkQ", + | "assetPair": { + | "amountAsset": "5fQPsn8hoaVddFG26cWQ5QFdqxWtUPNaZ9zH2E6LYzFn", + | "priceAsset": null + | }, + | "orderType": "sell", + | "amount": 1, + | "price": 100, + | "timestamp": 1, + | "expiration": 123, + | "matcherFee": 100000, + | "signature": "", + | "proofs": [], + | "matcherFeeAssetId": null, + | "eip712Signature": "0x6c4385dd5f6f1200b4d0630c9076104f34c801c16a211e505facfd743ba242db4429b966ffa8d2a9aff9037dafda78cfc8f7c5ef1c94493f5954bc7ebdb649281b", + | "priceMode": null + | }, + | "amount": 1, + | "price": 100, + | "buyMatcherFee": 100000, + | "sellMatcherFee": 100000 + |}""".stripMargin + ) } it should "not work in exchange transaction with changed signature" in { @@ -262,19 +272,21 @@ class EthOrderSpec sh.issueAsset(ByteStr(EthStubBytes32), Some(script)) } - val buyOrder = Order.selfSigned( - Order.V3, - TxHelpers.defaultSigner, - TxHelpers.matcher.publicKey, - AssetPair(IssuedAsset(ByteStr(EthStubBytes32)), Waves), - OrderType.BUY, - 1, - 100L, - 1, - 123, - 100000, - Waves - ).explicitGet() + val buyOrder = Order + .selfSigned( + Order.V3, + TxHelpers.defaultSigner, + TxHelpers.matcher.publicKey, + AssetPair(IssuedAsset(ByteStr(EthStubBytes32)), Waves), + OrderType.BUY, + 1, + 100L, + 1, + 123, + 100000, + Waves + ) + .explicitGet() val differ = TransactionDiffer(Some(1L), 100L)(blockchain, _) val transaction = TxHelpers.exchange(buyOrder, ethSellOrder, price = 100, version = TxVersion.V3, timestamp = 100) diff --git a/node/src/test/scala/com/wavesplatform/transaction/assets/exchange/OrderJsonSpecification.scala b/node/src/test/scala/com/wavesplatform/transaction/assets/exchange/OrderJsonSpecification.scala index ceff11c6dfb..ace18185481 100644 --- a/node/src/test/scala/com/wavesplatform/transaction/assets/exchange/OrderJsonSpecification.scala +++ b/node/src/test/scala/com/wavesplatform/transaction/assets/exchange/OrderJsonSpecification.scala @@ -123,7 +123,6 @@ class OrderJsonSpecification extends PropSpec with JsonMatchers with EthHelpers o.matcherFeeAssetId shouldBe IssuedAsset(ByteStr.decodeBase58("29ot86P3HoUZXH1FCoyvff7aeZ3Kt7GqPwBWXncjRF2b").get) } - val jsonOV4WithEthSig = Json.parse(s""" { "version": 4, @@ -149,7 +148,9 @@ class OrderJsonSpecification extends PropSpec with JsonMatchers with EthHelpers case JsSuccess(o, _) => o.id().toString shouldBe "FU8kLN9rRXCYjUDVUg914L3rdKNbgqpcfPmzXV7kLSJZ" o.withProofs(Proofs.empty).id() shouldNot be(o.id()) - o.senderPublicKey shouldBe PublicKey(ByteStr.decodeBase58("4aEWkjMryfRtekGnQwwCYQg5gaoC41cgWxYXTaLfYCrt41T4A3kXnQnt6hR5d2DHaWsHfFYXvswbbumZ3s8irEWN").get) + o.senderPublicKey shouldBe PublicKey( + ByteStr.decodeBase58("4LySXRvAsKTfhvabypvFUwYT3cvUFyZBhzFhq9UUDfzDmM4wDEmu3m5xPSD7iZrm7Zg4mmUXAkEQmodGgrdCAic7").get + ) o.matcherPublicKey shouldBe PublicKey(Base58.tryDecodeWithLimit("DZUxn4pC7QdYrRqacmaAJghatvnn1Kh1mkE2scZoLuGJ").get) o.assetPair.amountAsset shouldBe IssuedAsset(ByteStr.decodeBase58("29ot86P3HoUZXH1FCoyvff7aeZ3Kt7GqPwBWXncjRF2b").get) o.assetPair.priceAsset shouldBe IssuedAsset(ByteStr.decodeBase58("GEtBMkg419zhDiYRXKwn2uPcabyXKqUqj4w3Gcs1dq44").get) @@ -160,7 +161,13 @@ class OrderJsonSpecification extends PropSpec with JsonMatchers with EthHelpers o.expiration shouldBe 5 o.signature shouldBe ByteStr.empty o.matcherFeeAssetId shouldBe IssuedAsset(ByteStr.decodeBase58("29ot86P3HoUZXH1FCoyvff7aeZ3Kt7GqPwBWXncjRF2b").get) - o.eip712Signature shouldBe Some(ByteStr(EthEncoding.toBytes("0x40dd06c9f80215612a0397948a10dd82d6a58dda8a256544971e236a95a395ad6b87e75fb58789ece4f2ff7ed380849d120faefce135b6f7ddec9e11df169f971b"))) + o.eip712Signature shouldBe Some( + ByteStr( + EthEncoding.toBytes( + "0x40dd06c9f80215612a0397948a10dd82d6a58dda8a256544971e236a95a395ad6b87e75fb58789ece4f2ff7ed380849d120faefce135b6f7ddec9e11df169f971b" + ) + ) + ) } } @@ -187,7 +194,7 @@ class OrderJsonSpecification extends PropSpec with JsonMatchers with EthHelpers } } - val base58Str = "DZUxn4pC7QdYrRqacmaAJghatvnn1Kh1mkE2scZoLuGJ" + val base58Str = "DZUxn4pC7QdYrRqacmaAJghatvnn1Kh1mkE2scZoLuGJ" val json: JsValue = Json.parse(s""" { "sender": "$base58Str", @@ -253,18 +260,17 @@ class OrderJsonSpecification extends PropSpec with JsonMatchers with EthHelpers x -> mkJson(x) } - jsons.foreach { - case (priceAssetStr, rawJson) => - withClue(priceAssetStr) { - Json.parse(rawJson).validate[Order] match { - case e: JsError => - fail("Error: " + JsError.toJson(e).toString()) - case s: JsSuccess[Order] => - val o = s.get - o.assetPair.amountAsset shouldBe Waves - o.assetPair.priceAsset shouldBe Waves - } + jsons.foreach { case (priceAssetStr, rawJson) => + withClue(priceAssetStr) { + Json.parse(rawJson).validate[Order] match { + case e: JsError => + fail("Error: " + JsError.toJson(e).toString()) + case s: JsSuccess[Order] => + val o = s.get + o.assetPair.amountAsset shouldBe Waves + o.assetPair.priceAsset shouldBe Waves } + } } } }