Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.bloxbean.cardano.yaci.core.exception;

public class BlockParseRuntimeException extends RuntimeException {
private Long blockNumber;
private byte[] blockCbor;

public BlockParseRuntimeException(Long blockNumber, byte[] blockCbor, Exception e) {
super(e);
this.blockNumber = blockNumber;
this.blockCbor = blockCbor;
}

public BlockParseRuntimeException(Long blockNumber, byte[] blockCbor, String msg, Exception e) {
super(msg, e);
this.blockNumber = blockNumber;
this.blockCbor = blockCbor;
}

public Long getBlockNumber() {
return blockNumber;
}

public byte[] getBlockCbor() {
return blockCbor;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import co.nstant.in.cbor.model.UnsignedInteger;
import com.bloxbean.cardano.yaci.core.common.EraUtil;
import com.bloxbean.cardano.yaci.core.common.GenesisConfig;
import com.bloxbean.cardano.yaci.core.exception.BlockParseRuntimeException;
import com.bloxbean.cardano.yaci.core.model.Block;
import com.bloxbean.cardano.yaci.core.model.BlockHeader;
import com.bloxbean.cardano.yaci.core.model.Era;
Expand Down Expand Up @@ -138,16 +139,19 @@ private void onReceiveBlocks(MsgBlock message) {
errorBlks++;
log.error("Error in parsing", e);

Long blockNumber = null;
//Catch exception to avoid exception propagation
try {
Array headerArray = (Array) ((Array) array.getDataItems().get(1)).getDataItems().get(0);
BlockHeader blockHeader = BlockHeaderSerializer.INSTANCE.getBlockHeaderFromHeaderArray(headerArray);
log.error("BlockHeader >> Block No: " + blockHeader.getHeaderBody().getBlockNumber() + ", Slot: " + blockHeader.getHeaderBody().getSlot());
blockNumber = blockHeader.getHeaderBody().getBlockNumber();
} catch (Exception e1) {
log.error("Error in parsing block header", e1);
}

getAgentListeners().stream().forEach(blockfetchAgentListener -> blockfetchAgentListener.onParsingError(e));
var blockParseException = new BlockParseRuntimeException(blockNumber, body, e);
getAgentListeners().stream().forEach(blockfetchAgentListener -> blockfetchAgentListener.onParsingError(blockParseException));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.bloxbean.cardano.yaci.core.protocol.blockfetch;

import com.bloxbean.cardano.yaci.core.exception.BlockParseRuntimeException;
import com.bloxbean.cardano.yaci.core.model.Block;
import com.bloxbean.cardano.yaci.core.model.byron.ByronEbBlock;
import com.bloxbean.cardano.yaci.core.model.byron.ByronMainBlock;
Expand Down Expand Up @@ -35,7 +36,7 @@ default void byronEbBlockFound(ByronEbBlock byronEbBlock) {

}

default void onParsingError(Exception e) {
default void onParsingError(BlockParseRuntimeException e) {

}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.bloxbean.cardano.yaci.core.protocol.blockfetch;

import co.nstant.in.cbor.model.Array;
import co.nstant.in.cbor.model.UnsignedInteger;
import com.bloxbean.cardano.yaci.core.exception.BlockParseRuntimeException;
import com.bloxbean.cardano.yaci.core.protocol.blockfetch.messages.MsgBlock;
import com.bloxbean.cardano.yaci.core.util.CborSerializationUtil;
import com.bloxbean.cardano.yaci.core.util.HexUtil;
import org.junit.jupiter.api.Test;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.times;

public class BlockfetchAgentTest {

@Test
void testParseErrorHandling() {
BlockfetchAgent blockfetchAgent = new BlockfetchAgent();
BlockfetchAgentListener mockListener = mock(BlockfetchAgentListener.class);
blockfetchAgent.addListener(mockListener);

//Block cbor with unparsable data
String cborHex = "820785828a1a00325c341a04e93d335820616ba2c1b29f32f69408f024aa43577ea0db22a37d023667028f46c6bf6a9bd25820e9e9e0eac579ac6c36f23f183373e6259ba4e01bb4312c648987640e1dcf22ff5820cf68024875af973ef111b33d896a4072814215cd4454bfcf8d08440be55ec81c825840fc00bbd0f5c509684691cd33d3d084d82f63a2d09ce9f45ae219446c7e13fcb487958bfcbe5bd28fca52aa18462f1c4c7c043f4f416182c756749887ce5a18b95850caed967b60ad049456260fa42c4e5af06401be312b38af21f7437abaa6f0ad88503a68bc505e83633c39473121ce8aa4463589ca1077f8d372b4e3f9de2f3724fda5201de45f1e17e070709fc62d3805190374582070a576367e8132e4e5a3c2ab0e647494fb80a3168b207c401c558d721f81069d8458203e5bc618a0d992bc8fba5276e51dd5d1ca2837a3799a6b10b0c1c560c90f28070a19023f58409c80a80b63829376aa475f284033b30fc52e23d4a5a6c3062f82018ec69b58c15c2b549b9250b2e546bb83ef7049e5b228c0b676de89e00296d48aee95af5302820a025901c07a7c704ff4bade83915c094d4c18a93e05c6e14c32bc4a50a76648f1c779b4646a7fcf8e3b5cd8a4ae1270f988d9049bfea8b42d6e30890c65fb4af7a5a92c07a817e9247c4d30fc9f7072238cb9ceee6bcd4065d71285f5e14b47dc1f8ead1981365f853844000a4c3b881b14505f4634355d5960b8b86db52f797e910af8a3f5c9f5caa1acc20e8c6532d21f7973da52b0b46b7bc880198e36b144d177876eeac0b217b0e62fc62641a7280a00e96538f28be88644aa137004e3ec75e8a9904fb4c8424fa3bcd7941dc6b3d13efa53b507484c4bfc7895f576e35944182aaac2ed645994a0d05a7b1c9a953279e99144ebc0295d2c2b656378f8d61f043e866cbfd33fe4f36021f3f718136516e28ecb9981cba008601b7d75084dde0ba6df854a860d3cac659def796ad63440a644ab4e46db9c650f6f4161f85c0696aada2edb2466af971213fc607dc72c20fc95cd1efa9a8fac19308f40b0a27608ca23ac4a9215704901eda739c3c2f66f1cdbc5ea2a204ad9154e9fa1c139aaa6152d734e4a521a7c7813614666ecbadad77aed3f1e67d2272c44e56534bc17521b6406ee4c359ec698e7006b91ffb896ad5ce2e9a21d0c6450499d71cc1da73c0cc681a800d9010281825820deee1236f2468a916e525d952996944621a762d921e2ac9e518fb42166e63d7101018282583900ff76e52a2bbd75feedecd082d9e87a4b3c2232a048898570c24b747871bc22b9a36f8b31472a273fd7ae610ccaabf15117b92bc97497b7e4821a001e8480a1581c23b62b4570c332e3b1809370805286f14824437ed661e09fd1037619a1495061796c4b6f796e310182583900b08760eb6576fcd70e653e61a26a8a0b5180e403175e328db577c9600416e08ece7a5d20ea5c141163223ad8aa86ce604f1b82e96d891bae1a050ab9ce021a00034cd5031a04e940a90758206baaa832cd21bc539f0643f3e6257a4e21ce1a548d1e9b18be17516d712d6ffe081a04e93cc109a1581c23b62b4570c332e3b1809370805286f14824437ed661e09fd1037619a1495061796c4b6f796e31010ed9010281581c6d66c78fb7803aca916c571ea3180f470a830919abf354fbada766b781a200d9010282825820cb05a31a8c6a27c96c9b777d332a43d75c8a0154c560492f814d9375d8dd1bcf584045bfd6b0e9e370cfae5ab005e5844bfed36c91e6262dbd0d78fd25a219a6f65534dcece75fd954dfcde86f9fe933bed75488d42a28286bf0579a32de7e75980a82582043f21b577a7c12ed60d99d981f3af0822ead911970836a56b31426caec3c16c558401858abe89432588bc6518a4f8cc7f758f7b4cf6999ca340cf2f7fda67b63735694a42e1d5d5dad7871b54e3d6cedc758ef2b1061135aeb6312341e02554a5d0f01d901028182019f8200581c6d66c78fb7803aca916c571ea3180f470a830919abf354fbada766b782051a04f87c6effa100d90103a100a11902d1a178383463303937313566346539316462393262323234376635653561636462306138663037656161376334303230376264383234626564336632a172353036313739364334423646373936453331a8646e616d656b5061796c4b6f796e20233165696d61676582784061646166733a2f2f6132373034303239663331316665356566366239303463643233363536306534626438643666306633353430316162316331356464333130683366336166653066696d656469615479706569696d6167652f706e676a6261636b67726f756e6466526f636b657264626f64796442617365676c696e65617274644261736568636c6f7468696e67645079726f6465796573645a65737480";
byte[] cborBytes = HexUtil.decodeHexString(cborHex);

Array di = (Array) CborSerializationUtil.deserializeOne(cborBytes);

var diList = di.getDataItems();
//Add a random number to witnesset to create invalid cbor
((Array)((Array)diList.get(1)).getDataItems().get(2)).getDataItems().add(new UnsignedInteger(8999));

//Updated cbor bytes after modification
cborBytes = CborSerializationUtil.serialize(di);

// Create a mocked MsgBlock with corrupted data
MsgBlock corruptedMsgBlock = mock(MsgBlock.class);
when(corruptedMsgBlock.getBytes()).thenReturn(cborBytes);

// Act
blockfetchAgent.processResponse(corruptedMsgBlock);

verify(mockListener, times(1)).onParsingError(any(BlockParseRuntimeException.class));
}
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
group = com.bloxbean.cardano
artifactId = yaci
version = 0.4.0-beta3
version = 0.4.0-beta4
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.bloxbean.cardano.yaci.helper;

import com.bloxbean.cardano.yaci.core.common.Constants;
import com.bloxbean.cardano.yaci.core.exception.BlockParseRuntimeException;
import com.bloxbean.cardano.yaci.core.model.Block;
import com.bloxbean.cardano.yaci.core.model.Era;
import com.bloxbean.cardano.yaci.core.protocol.chainsync.messages.Point;
import com.bloxbean.cardano.yaci.core.protocol.chainsync.messages.Tip;
import com.bloxbean.cardano.yaci.core.util.HexUtil;
import com.bloxbean.cardano.yaci.helper.listener.BlockChainDataListener;
import com.bloxbean.cardano.yaci.helper.model.Transaction;
import org.junit.jupiter.api.Disabled;
Expand Down Expand Up @@ -136,4 +138,31 @@ public void intersactFound(Tip tip, Point point) {
countDownLatch.await(60, TimeUnit.SECONDS);
assertThat(success.get()).isTrue();
}

@Test
void syncFromPoint_continueOnParseError() throws InterruptedException {
BlockSync blockSync = new BlockSync(Constants.PREVIEW_PUBLIC_RELAY_ADDR, Constants.PREPROD_PUBLIC_RELAY_PORT,
Constants.PREVIEW_PROTOCOL_MAGIC, Constants.WELL_KNOWN_PREVIEW_POINT);

AtomicLong blockNo = new AtomicLong();
CountDownLatch countDownLatch = new CountDownLatch(10);
blockSync.startSync(new Point(82394373, "49033a53f777ce932be005539b01ef4d7e3b49ee4ae2f315342a182f3281384a"),
new BlockChainDataListener() {
@Override
public void onBlock(Era era, Block block, List<Transaction> transactions) {
System.out.println(block.getHeader().getHeaderBody().getBlockNumber());
blockNo.set(block.getHeader().getHeaderBody().getBlockNumber());
countDownLatch.countDown();
}

@Override
public void onParsingError(BlockParseRuntimeException e) {
System.out.println("ERROR BLock: " + e.getBlockNumber());
System.out.println("CBOR: " + HexUtil.encodeHexString(e.getBlockCbor()));
}
});

countDownLatch.await(60, TimeUnit.SECONDS);
assertThat(blockNo.get()).isGreaterThan(3300404 + 5);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.bloxbean.cardano.yaci.helper;

import com.bloxbean.cardano.yaci.core.common.Constants;
import com.bloxbean.cardano.yaci.core.exception.BlockParseRuntimeException;
import com.bloxbean.cardano.yaci.core.model.Block;
import com.bloxbean.cardano.yaci.core.model.BlockHeader;
import com.bloxbean.cardano.yaci.core.model.byron.ByronBlockHead;
Expand Down Expand Up @@ -194,6 +195,11 @@ public void byronBlockFound(ByronMainBlock byronBlock) {
public void byronEbBlockFound(ByronEbBlock byronEbBlock) {
chainSyncAgent.sendNextMessage();
}

@Override
public void onParsingError(BlockParseRuntimeException e) {
chainSyncAgent.sendNextMessage();
}
});

keepAliveAgent.addListener(response -> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.bloxbean.cardano.yaci.helper.listener;

import com.bloxbean.cardano.yaci.core.exception.BlockParseRuntimeException;
import com.bloxbean.cardano.yaci.core.model.Block;
import com.bloxbean.cardano.yaci.core.model.Era;
import com.bloxbean.cardano.yaci.core.model.byron.ByronEbBlock;
Expand Down Expand Up @@ -43,5 +44,5 @@ default void intersactNotFound(Tip tip) {}

default void onDisconnect() {}

default void onParsingError(Exception e) {}
default void onParsingError(BlockParseRuntimeException e) {}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.bloxbean.cardano.yaci.helper.listener;

import com.bloxbean.cardano.yaci.core.exception.BlockParseRuntimeException;
import com.bloxbean.cardano.yaci.core.model.*;
import com.bloxbean.cardano.yaci.core.model.byron.ByronEbBlock;
import com.bloxbean.cardano.yaci.core.model.byron.ByronMainBlock;
Expand Down Expand Up @@ -133,7 +134,7 @@ public void onDisconnect() {
}

@Override
public void onParsingError(Exception e) {
public void onParsingError(BlockParseRuntimeException e) {
blockChainDataListener.onParsingError(e);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,28 @@ public void blockFound(Block block) {
System.out.println(blocks.get(0));
assertThat(blocks.get(0).getHeader().getHeaderBody().getBlockNumber()).isGreaterThan(287480);
}

@Test
void testChainSync_continueOnParseError() throws InterruptedException {
N2NChainSyncFetcher chainSyncFetcher = new N2NChainSyncFetcher(Constants.PREVIEW_PUBLIC_RELAY_ADDR,
Constants.PREVIEW_PUBLIC_RELAY_PORT,
new Point(82394373, "49033a53f777ce932be005539b01ef4d7e3b49ee4ae2f315342a182f3281384a"),
Constants.PREVIEW_PROTOCOL_MAGIC, false);

List<Block> blocks = new ArrayList<>();
CountDownLatch countDownLatch = new CountDownLatch(10);
chainSyncFetcher.addBlockFetchListener(new BlockfetchAgentListener() {
@Override
public void blockFound(Block block) {
blocks.add(block);
countDownLatch.countDown();
}
});
chainSyncFetcher.start();
countDownLatch.await(60, TimeUnit.SECONDS);
chainSyncFetcher.shutdown();

System.out.println(blocks.get(0));
assertThat(blocks).hasSizeGreaterThan(8);
}
}