From 38b39ecf43b574caf4df6428ce64ba1027752e7a Mon Sep 17 00:00:00 2001 From: Satya Date: Thu, 30 Mar 2023 14:03:28 +0800 Subject: [PATCH] Fix (#229): Change key sort comparator to compare unsign bytes and related tests --- .../common/cbor/custom/CustomMapEncoder.java | 25 +------- .../transaction/spec/AuxiliaryDataTest.java | 13 +++- .../transaction/spec/MapPlutusDataTest.java | 59 +++++++++++++++++++ .../client/transaction/spec/UpdateTest.java | 4 +- .../JsonNoSchemaToMetadataConverterTest.java | 12 +++- 5 files changed, 84 insertions(+), 29 deletions(-) diff --git a/common/src/main/java/com/bloxbean/cardano/client/common/cbor/custom/CustomMapEncoder.java b/common/src/main/java/com/bloxbean/cardano/client/common/cbor/custom/CustomMapEncoder.java index 77f07564..3b0fb54a 100644 --- a/common/src/main/java/com/bloxbean/cardano/client/common/cbor/custom/CustomMapEncoder.java +++ b/common/src/main/java/com/bloxbean/cardano/client/common/cbor/custom/CustomMapEncoder.java @@ -10,8 +10,8 @@ import java.io.ByteArrayOutputStream; import java.io.OutputStream; +import java.util.Arrays; import java.util.Collection; -import java.util.Comparator; import java.util.TreeMap; /** @@ -76,28 +76,7 @@ private void encodeCanonical(Map map) throws CborException { * lexical order sorts earlier. */ - TreeMap sortedMap = new TreeMap<>(new Comparator() { - - @Override - public int compare(byte[] o1, byte[] o2) { - if (o1.length < o2.length) { - return -1; - } - if (o1.length > o2.length) { - return 1; - } - for (int i = 0; i < o1.length; i++) { - if (o1[i] < o2[i]) { - return -1; - } - if (o1[i] > o2[i]) { - return 1; - } - } - return 0; - } - - }); + TreeMap sortedMap = new TreeMap<>(Arrays::compareUnsigned); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); CborEncoder e = new CustomCborEncoder(byteArrayOutputStream); diff --git a/core/src/test/java/com/bloxbean/cardano/client/transaction/spec/AuxiliaryDataTest.java b/core/src/test/java/com/bloxbean/cardano/client/transaction/spec/AuxiliaryDataTest.java index dbb086f8..cbec844b 100644 --- a/core/src/test/java/com/bloxbean/cardano/client/transaction/spec/AuxiliaryDataTest.java +++ b/core/src/test/java/com/bloxbean/cardano/client/transaction/spec/AuxiliaryDataTest.java @@ -2,6 +2,7 @@ import co.nstant.in.cbor.CborException; import co.nstant.in.cbor.model.*; +import com.bloxbean.cardano.client.common.cbor.CborSerializationUtil; import com.bloxbean.cardano.client.exception.CborDeserializationException; import com.bloxbean.cardano.client.exception.CborSerializationException; import com.bloxbean.cardano.client.metadata.Metadata; @@ -10,7 +11,6 @@ import com.bloxbean.cardano.client.metadata.cbor.CBORMetadataMap; import com.bloxbean.cardano.client.metadata.helper.JsonNoSchemaToMetadataConverter; import com.bloxbean.cardano.client.transaction.spec.script.ScriptPubkey; -import com.bloxbean.cardano.client.transaction.util.CborSerializationUtil; import com.bloxbean.cardano.client.util.HexUtil; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -20,6 +20,7 @@ import java.io.IOException; import java.math.BigInteger; import java.util.Arrays; +import java.util.Collection; import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; @@ -28,7 +29,7 @@ public class AuxiliaryDataTest { String dataFile = "json-metadata.json"; @Test - public void getAuxiliaryDataHash_whenMetadataIsSet() throws IOException { + public void getAuxiliaryDataHash_checkKeysOrder_whenMetadataIsSet() throws Exception { JsonNode json = loadJsonMetadata("json-4"); Metadata metadata = JsonNoSchemaToMetadataConverter.jsonToCborMetadata(json.toString()); @@ -38,8 +39,14 @@ public void getAuxiliaryDataHash_whenMetadataIsSet() throws IOException { byte[] auxHashBytes = auxiliaryData.getAuxiliaryDataHash(); String auxHash = HexUtil.encodeHexString(auxHashBytes); + String serializedHex = HexUtil.encodeHexString(CborSerializationUtil.serialize(auxiliaryData.serialize())); - assertThat(auxHash).isEqualTo("17df7ed927194d072174f36ac34e09f92e8a63f4131bef66d8cd186b95b6bfe8"); + Map metadataMap = (Map)CborSerializationUtil.deserialize(HexUtil.decodeHexString(serializedHex)); + Collection metadataLabels = metadataMap.getKeys(); + + assertThat(metadataLabels).containsExactly(new UnsignedInteger(945845007538436815L), new UnsignedInteger(1302243434517352162L), new UnsignedInteger(1351859328329939190L), + new UnsignedInteger(7274669146951118819L), new UnsignedInteger(7505166164059511819L), new UnsignedInteger(new BigInteger("17802948329108123211"))); + assertThat(auxHash).isEqualTo("47a7d2a804b63b12818b1fc4bf710a966d20aa25105f315f92af673dfec435db"); } @Test diff --git a/core/src/test/java/com/bloxbean/cardano/client/transaction/spec/MapPlutusDataTest.java b/core/src/test/java/com/bloxbean/cardano/client/transaction/spec/MapPlutusDataTest.java index cac0f677..295ca0b6 100644 --- a/core/src/test/java/com/bloxbean/cardano/client/transaction/spec/MapPlutusDataTest.java +++ b/core/src/test/java/com/bloxbean/cardano/client/transaction/spec/MapPlutusDataTest.java @@ -1,7 +1,12 @@ package com.bloxbean.cardano.client.transaction.spec; +import co.nstant.in.cbor.model.*; +import com.bloxbean.cardano.client.common.cbor.CborSerializationUtil; +import com.bloxbean.cardano.client.util.HexUtil; import org.junit.jupiter.api.Test; +import java.util.Collection; + import static org.assertj.core.api.Assertions.assertThat; class MapPlutusDataTest { @@ -31,4 +36,58 @@ void testNotEquals() { assertThat(mapPlutusData).isNotEqualTo(mapPlutusData2); } + + @Test + void testLexicographicOrderForKeyInMap_whenIntKeys() throws Exception { + MapPlutusData mapPlutusData = new MapPlutusData(); + mapPlutusData.put(BigIntPlutusData.of(148218514), BytesPlutusData.of("value1")); + mapPlutusData.put(BigIntPlutusData.of(160376066), BytesPlutusData.of("value2")); + mapPlutusData.put(BigIntPlutusData.of(158897178), BytesPlutusData.of("value3")); + + String hex = mapPlutusData.serializeToHex(); + System.out.println(hex); + + //Deserialize and check the keys order + Map map = (Map)CborSerializationUtil.deserialize(HexUtil.decodeHexString(hex)); + Collection keys = map.getKeys(); + assertThat(keys).hasSize(3); + assertThat(keys).containsExactly(new UnsignedInteger(148218514), new UnsignedInteger(158897178), + new UnsignedInteger(160376066)); + } + + @Test + void testLexicographicOrderForKeyInMap_whenByteKeys() { + MapPlutusData mapPlutusData = new MapPlutusData(); + mapPlutusData.put(BytesPlutusData.of("148218514"), BytesPlutusData.of("value1")); + mapPlutusData.put(BytesPlutusData.of("160376066"), BytesPlutusData.of("value2")); + mapPlutusData.put(BytesPlutusData.of("158897178"), BytesPlutusData.of("value3")); + + String hex = mapPlutusData.serializeToHex(); + System.out.println(hex); + + //Deserialize and check the keys order + Map map = (Map)CborSerializationUtil.deserialize(HexUtil.decodeHexString(hex)); + Collection keys = map.getKeys(); + assertThat(keys).hasSize(3); + assertThat(keys).containsExactly(new ByteString("148218514".getBytes()), new ByteString("158897178".getBytes()), + new ByteString("160376066".getBytes())); + } + + @Test + void testLexicographicOrderForKeyInMap_whenNegativeKeys() { + MapPlutusData mapPlutusData = new MapPlutusData(); + mapPlutusData.put(BigIntPlutusData.of(148218514), BytesPlutusData.of("value1")); + mapPlutusData.put(BigIntPlutusData.of(-160376066), BytesPlutusData.of("value2")); + mapPlutusData.put(BigIntPlutusData.of(-158897178), BytesPlutusData.of("value3")); + + String hex = mapPlutusData.serializeToHex(); + System.out.println(hex); + + //Deserialize and check the keys order + Map map = (Map)CborSerializationUtil.deserialize(HexUtil.decodeHexString(hex)); + Collection keys = map.getKeys(); + assertThat(keys).hasSize(3); + assertThat(keys).containsExactly(new UnsignedInteger(148218514), new NegativeInteger(-158897178), new NegativeInteger(-160376066)); + } } + diff --git a/core/src/test/java/com/bloxbean/cardano/client/transaction/spec/UpdateTest.java b/core/src/test/java/com/bloxbean/cardano/client/transaction/spec/UpdateTest.java index 8188cd1f..1f28b6fc 100644 --- a/core/src/test/java/com/bloxbean/cardano/client/transaction/spec/UpdateTest.java +++ b/core/src/test/java/com/bloxbean/cardano/client/transaction/spec/UpdateTest.java @@ -12,8 +12,8 @@ class UpdateTest { @Test - void serDeser() throws Exception { - String cborHex = "82a7581cad5463153dc3d24b9ff133e46136028bdc1edbb897f5a7cf1b37950ca2021a0001400014821a00d59f801b00000002540be400581cb9547b8a57656539a8d9bc42c008e38d9c8bd9c8adbb1e73ad529497a2021a0001400014821a00d59f801b00000002540be400581cf7b341c14cd58fca4195a9b278cce1ef402dc0e06deb77e543cd1757a2021a0001400014821a00d59f801b00000002540be400581c162f94554ac8c225383a2248c245659eda870eaa82d0ef25fc7dcd82a2021a0001400014821a00d59f801b00000002540be400581c2075a095b3c844a29c24317a94a643ab8e22d54a3a3a72a420260af6a2021a0001400014821a00d59f801b00000002540be400581c268cfc0b89e910ead22e0ade91493d8212f53f3e2164b2e4bef0819ba2021a0001400014821a00d59f801b00000002540be400581c60baee25cbc90047e83fd01e1e57dc0b06d3d0cb150d0ab40bbfead1a2021a0001400014821a00d59f801b00000002540be40019013e"; + void testUpdate_serDeser() throws Exception { + String cborHex = "82a7581c162f94554ac8c225383a2248c245659eda870eaa82d0ef25fc7dcd82a2021a0001400014821a00d59f801b00000002540be400581c2075a095b3c844a29c24317a94a643ab8e22d54a3a3a72a420260af6a2021a0001400014821a00d59f801b00000002540be400581c268cfc0b89e910ead22e0ade91493d8212f53f3e2164b2e4bef0819ba2021a0001400014821a00d59f801b00000002540be400581c60baee25cbc90047e83fd01e1e57dc0b06d3d0cb150d0ab40bbfead1a2021a0001400014821a00d59f801b00000002540be400581cad5463153dc3d24b9ff133e46136028bdc1edbb897f5a7cf1b37950ca2021a0001400014821a00d59f801b00000002540be400581cb9547b8a57656539a8d9bc42c008e38d9c8bd9c8adbb1e73ad529497a2021a0001400014821a00d59f801b00000002540be400581cf7b341c14cd58fca4195a9b278cce1ef402dc0e06deb77e543cd1757a2021a0001400014821a00d59f801b00000002540be40019013e"; Update update = Update.deserialize(CborSerializationUtil.deserialize(HexUtil.decodeHexString(cborHex))); byte[] serBytes = CborSerializationUtil.serialize(update.serialize()); diff --git a/metadata/src/test/java/com/bloxbean/cardano/client/metadata/helper/JsonNoSchemaToMetadataConverterTest.java b/metadata/src/test/java/com/bloxbean/cardano/client/metadata/helper/JsonNoSchemaToMetadataConverterTest.java index 3c0b0747..e0ce96ff 100644 --- a/metadata/src/test/java/com/bloxbean/cardano/client/metadata/helper/JsonNoSchemaToMetadataConverterTest.java +++ b/metadata/src/test/java/com/bloxbean/cardano/client/metadata/helper/JsonNoSchemaToMetadataConverterTest.java @@ -1,6 +1,9 @@ package com.bloxbean.cardano.client.metadata.helper; +import co.nstant.in.cbor.model.DataItem; +import co.nstant.in.cbor.model.UnsignedInteger; import com.bloxbean.cardano.client.metadata.Metadata; +import com.bloxbean.cardano.client.metadata.cbor.CBORMetadata; import com.bloxbean.cardano.client.util.HexUtil; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -8,7 +11,10 @@ import org.junit.jupiter.api.Test; import java.io.IOException; +import java.math.BigInteger; +import java.util.Collection; +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -26,7 +32,11 @@ void testParseJSONMetadata() throws IOException { byte[] serializedBytes = metadata.serialize(); String hex = HexUtil.encodeHexString(serializedBytes); - String expected = "a61bf710c72e671fae4ba01b0d205105e6e7bacf504ebc4ea3b43bb0cc76bb326f17a30d8f1b12c2c4e58b6778f6a26430783065463bdefda922656830783134666638643bb6597a178e6a18971b12127f810d7dcee28264554a42333be153691687de9f671b64f4d10bda83efe33bcd995b2806a1d9971b6827b4dcb50c5c0b71726365486c5578586c576d5a4a63785964"; + Collection keys = CBORMetadata.deserialize(serializedBytes).getData().getKeys(); + + assertThat(keys).containsExactly(new UnsignedInteger(945845007538436815L), new UnsignedInteger(1302243434517352162L), new UnsignedInteger(1351859328329939190L), + new UnsignedInteger(7274669146951118819L), new UnsignedInteger(7505166164059511819L), new UnsignedInteger(new BigInteger("17802948329108123211"))); + String expected = "a61b0d205105e6e7bacf504ebc4ea3b43bb0cc76bb326f17a30d8f1b12127f810d7dcee28264554a42333be153691687de9f671b12c2c4e58b6778f6a26430783065463bdefda922656830783134666638643bb6597a178e6a18971b64f4d10bda83efe33bcd995b2806a1d9971b6827b4dcb50c5c0b71726365486c5578586c576d5a4a637859641bf710c72e671fae4ba0"; assertEquals(expected, hex); }