Skip to content

Commit

Permalink
Merge pull request #58 from bloxbean/fix_143
Browse files Browse the repository at this point in the history
fix: Handle ARRAY and MAP types in metadata map's key while converting to JSON
  • Loading branch information
satran004 committed Mar 12, 2024
2 parents 48910af + d0c26ce commit 3f7445e
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import com.bloxbean.cardano.client.exception.CborRuntimeException;
import com.bloxbean.cardano.client.metadata.Metadata;
import com.bloxbean.cardano.client.metadata.cbor.CBORMetadata;
import com.bloxbean.cardano.client.metadata.helper.MetadataToJsonNoSchemaConverter;
import com.bloxbean.cardano.client.transaction.spec.AuxiliaryData;
import com.bloxbean.cardano.yaci.core.model.AuxData;
import com.bloxbean.cardano.yaci.core.model.NativeScript;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package com.bloxbean.cardano.yaci.core.model.serializers;

import co.nstant.in.cbor.CborDecoder;
import co.nstant.in.cbor.CborException;
import co.nstant.in.cbor.model.*;
import com.bloxbean.cardano.client.exception.CborDeserializationException;
import com.bloxbean.cardano.client.metadata.exception.MetadataDeSerializationException;
import com.bloxbean.cardano.client.util.HexUtil;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;

import static co.nstant.in.cbor.model.MajorType.*;

//TODO -- Remove once it's fixed in CCL (https://github.com/cardano-foundation/cf-ledger-sync/issues/143)
class MetadataToJsonNoSchemaConverter {
private final static ObjectMapper objectMapper = new ObjectMapper();

/**
* Convert cbor metadata bytes to json string
* @param cborBytes
* @return
*/
public static String cborBytesToJson(byte[] cborBytes) {
try {
return cborHexToJson(HexUtil.encodeHexString(cborBytes));
} catch (Exception e) {
throw new MetadataDeSerializationException("Deserialization error", e);
}
}

/**
* Converts cbor metadata bytes in hex format to json string
* @param hex
* @return
*/
public static String cborHexToJson(String hex) {
try {
java.util.Map result = cborHexToJavaMap(hex);

return objectMapper.writeValueAsString(result);
} catch (Exception e) {
throw new MetadataDeSerializationException("Deserialization error", e);
}
}

private static java.util.Map cborHexToJavaMap(String hex) throws CborDeserializationException {
byte[] cborBytes = HexUtil.decodeHexString(hex);
List<DataItem> dataItemList = null;
try {
dataItemList = CborDecoder.decode(cborBytes);
} catch (CborException e) {
throw new CborDeserializationException("Cbor deserialization failed", e);
}

if(dataItemList != null && dataItemList.size() > 1)
throw new MetadataDeSerializationException("Multiple DataItems found at top level. Should be zero : " + dataItemList.size());

java.util.Map result = new HashMap();
DataItem dataItem = dataItemList.get(0);
if(dataItem instanceof Map) {
result = processMap((Map)dataItem);
} else {
throw new MetadataDeSerializationException("Top leve object should be a Map : " + dataItem.getMajorType().toString());
}
return result;
}

private static java.util.Map processMap(Map map) {
java.util.Map resultMap = new HashMap();
Collection<DataItem> keys = map.getKeys();
for(DataItem keyItem: keys) {
DataItem valueItem = map.get(keyItem);
Object key = processKey(keyItem);
Object value = processValue(valueItem);

resultMap.put(key, value);
}
return resultMap;
}

private static Object processKey(DataItem keyItem) {
if (UNSIGNED_INTEGER.equals(keyItem.getMajorType())){
return ((UnsignedInteger) keyItem).getValue();
} else if(NEGATIVE_INTEGER.equals(keyItem.getMajorType())) {
return ((NegativeInteger) keyItem).getValue();
} else if (BYTE_STRING.equals(keyItem.getMajorType())) {
byte[] bytes = ((ByteString) keyItem).getBytes();
return "0x" + HexUtil.encodeHexString(bytes);
} else if (UNICODE_STRING.equals(keyItem.getMajorType())) {
return ((UnicodeString) keyItem).getString();
} else if(MAP.equals(keyItem.getMajorType())){
return processMap((Map)keyItem);
} else if(ARRAY.equals(keyItem.getMajorType())) {
return processArray((Array)keyItem);
} else {
throw new MetadataDeSerializationException("Invalid key type : " + keyItem.getMajorType());
}
}

private static Object processValue(DataItem valueItem) {
if(UNSIGNED_INTEGER.equals(valueItem.getMajorType())){
return ((UnsignedInteger)valueItem).getValue();
} else if(NEGATIVE_INTEGER.equals(valueItem.getMajorType())) {
return ((NegativeInteger)valueItem).getValue();
} else if(BYTE_STRING.equals(valueItem.getMajorType())) {
byte[] bytes = ((ByteString)valueItem).getBytes();
return "0x" + HexUtil.encodeHexString(bytes);
} else if(UNICODE_STRING.equals(valueItem.getMajorType())) {
return ((UnicodeString)valueItem).getString();
} else if(MAP.equals(valueItem.getMajorType())){
return processMap((Map)valueItem);
} else if(ARRAY.equals(valueItem.getMajorType())) {
return processArray((Array)valueItem);
} else {
throw new MetadataDeSerializationException("Unsupported type : " + valueItem.getMajorType());
}
}

private static Object processArray(Array array) {
List<DataItem> dataItems = array.getDataItems();
List resultList = new ArrayList();
for(DataItem valueItem: dataItems) {
Object valueObj = processValue(valueItem);
resultList.add(valueObj);
}
return resultList;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,36 @@ public void blockFound(Block block) {
assertThat(amounts).hasSize(0);
}

@Test
public void fetchBlock_metadataWithArrayKey() throws InterruptedException {
VersionTable versionTable = N2NVersionTableConstant.v4AndAbove(protocolMagic);
BlockFetcher blockFetcher = new BlockFetcher(node, nodePort, versionTable);

CountDownLatch countDownLatch = new CountDownLatch(1);

StringBuilder sb = new StringBuilder();
blockFetcher.addBlockFetchListener(new BlockfetchAgentListener() {
@Override
public void blockFound(Block block) {
var metatdataJson = block.getAuxiliaryDataMap().get(2).getMetadataJson();
System.out.println(metatdataJson);
sb.append(metatdataJson);
countDownLatch.countDown();
}
});
blockFetcher.start();

Point from = new Point(54478325, "2cbc2a95ed9ab49b10d9016cc0201c19749c79ba28c9b55ff70860e65d67d077");
Point to = new Point(54478325, "2cbc2a95ed9ab49b10d9016cc0201c19749c79ba28c9b55ff70860e65d67d077");

blockFetcher.fetch(from, to);

countDownLatch.await(10, TimeUnit.SECONDS);
blockFetcher.shutdown();

assertThat(sb.toString()).isNotEqualTo("null");
}

/** Not able to fetch block 0
@Test
public void fetchGenesisBlockByron() throws InterruptedException {
Expand Down

0 comments on commit 3f7445e

Please sign in to comment.