use of org.aion.zero.impl.sync.msg.RequestBlocks in project aion by aionnetwork.
the class RequestBlocksHandler method receive.
@Override
public void receive(int peerId, String displayId, final byte[] message) {
if (message == null || message.length == 0) {
this.log.debug("<request-blocks empty message from peer={}>", displayId);
return;
}
RequestBlocks request = RequestBlocks.decode(message);
if (request != null) {
if (request.isNumber()) {
// process block requests by number
long start = request.getStartHeight();
int count = Math.min(request.getCount(), V1Constants.BLOCKS_REQUEST_MAXIMUM_BATCH_SIZE);
boolean descending = request.isDescending();
if (log.isDebugEnabled()) {
this.log.debug("<request-blocks from-block={} count={} order={}>", start, count, descending ? "DESC" : "ASC");
}
List<Block> blockList = null;
try {
// retrieve blocks from block store depending on requested order
if (descending) {
blockList = chain.getBlocksByRange(start, start - count + 1);
} else {
blockList = chain.getBlocksByRange(start, start + count - 1);
}
} catch (Exception e) {
this.log.error("<request-blocks value retrieval failed>", e);
}
if (blockList != null) {
// generate response with retrieved blocks
// TODO: check the message size and ensure that it fits predefined limits
ResponseBlocks response = new ResponseBlocks(blockList);
// reply to request
this.p2p.send(peerId, displayId, response);
}
} else {
// process block requests by hash
byte[] startHash = request.getStartHash();
int count = Math.min(request.getCount(), V1Constants.BLOCKS_REQUEST_MAXIMUM_BATCH_SIZE);
boolean descending = request.isDescending();
if (log.isDebugEnabled()) {
this.log.debug("<request-blocks from-block={} count={} order={}>", Hex.toHexString(startHash), count, descending ? "DESC" : "ASC");
}
// check if block exists
Block block = chain.getBlockByHash(startHash);
if (block != null) {
long start = block.getNumber();
List<Block> blockList = null;
try {
// retrieve blocks from block store depending on requested order
if (descending) {
blockList = chain.getBlocksByRange(start, start - count + 1);
} else {
blockList = chain.getBlocksByRange(start, start + count - 1);
}
} catch (Exception e) {
this.log.error("<request-blocks value retrieval failed>", e);
}
if (blockList != null && blockList.contains(block)) {
// generate response with retrieved blocks
// TODO: check the message size and ensure that it fits predefined limits
ResponseBlocks response = new ResponseBlocks(blockList);
// reply to request
this.p2p.send(peerId, displayId, response);
} else {
// retrieving multiple blocks failed
// or the requested block was on a side chain
// generate response with single block
ResponseBlocks response = new ResponseBlocks(List.of(block));
// reply to request
this.p2p.send(peerId, displayId, response);
}
}
}
} else {
this.log.error("<request-blocks decode-error msg-bytes={} peer={}>", message.length, displayId);
if (log.isTraceEnabled()) {
this.log.trace("<request-blocks decode-error for msg={} peer={}>", Arrays.toString(message), displayId);
}
}
}
use of org.aion.zero.impl.sync.msg.RequestBlocks in project aion by aionnetwork.
the class RequestBlocksHandlerTest method testReceive_correctMessage_ascending_withHash.
@Test
public void testReceive_correctMessage_ascending_withHash() {
Block first = consecutiveBlocks.get(0);
byte[] hash = first.getHash();
Block last = consecutiveBlocks.get(3);
Logger log = mock(Logger.class);
when(log.isDebugEnabled()).thenReturn(true);
IAionBlockchain chain = mock(AionBlockchainImpl.class);
when(chain.getBlockByHash(hash)).thenReturn(first);
when(chain.getBlocksByRange(first.getNumber(), last.getNumber())).thenReturn(consecutiveBlocks);
IP2pMgr p2p = mock(P2pMgr.class);
RequestBlocksHandler handler = new RequestBlocksHandler(log, chain, p2p);
// receive correct message
RequestBlocks request = new RequestBlocks(hash, 4, false);
handler.receive(peerId, displayId, request.encode());
verify(log, times(1)).debug("<request-blocks from-block={} count={} order={}>", Hex.toHexString(hash), 4, "ASC");
verify(chain, times(1)).getBlockByHash(hash);
verify(chain, times(1)).getBlocksByRange(first.getNumber(), last.getNumber());
ResponseBlocks expectedResponse = new ResponseBlocks(consecutiveBlocks);
verify(p2p, times(1)).send(peerId, displayId, expectedResponse);
}
use of org.aion.zero.impl.sync.msg.RequestBlocks in project aion by aionnetwork.
the class RequestBlocksHandlerTest method testReceive_correctMessage_descending_withHeight.
@Test
public void testReceive_correctMessage_descending_withHeight() {
Block first = consecutiveBlocks.get(3);
Block last = consecutiveBlocks.get(0);
// reverse the list order
LinkedList<Block> reverse = new LinkedList<>();
for (Block b : consecutiveBlocks) {
reverse.addFirst(b);
}
Logger log = mock(Logger.class);
when(log.isDebugEnabled()).thenReturn(true);
IAionBlockchain chain = mock(AionBlockchainImpl.class);
when(chain.getBlocksByRange(first.getNumber(), last.getNumber())).thenReturn(reverse);
IP2pMgr p2p = mock(P2pMgr.class);
RequestBlocksHandler handler = new RequestBlocksHandler(log, chain, p2p);
// receive correct message
RequestBlocks request = new RequestBlocks(first.getNumber(), 4, true);
handler.receive(peerId, displayId, request.encode());
verify(log, times(1)).debug("<request-blocks from-block={} count={} order={}>", first.getNumber(), 4, "DESC");
verify(chain, times(1)).getBlocksByRange(first.getNumber(), last.getNumber());
ResponseBlocks expectedResponse = new ResponseBlocks(reverse);
verify(p2p, times(1)).send(peerId, displayId, expectedResponse);
}
use of org.aion.zero.impl.sync.msg.RequestBlocks in project aion by aionnetwork.
the class RequestBlocksHandlerTest method testReceive_correctMessage_withHashOnSideChain.
@Test
public void testReceive_correctMessage_withHashOnSideChain() {
Block first = consecutiveBlocks.get(0);
byte[] hash = first.getHash();
Block last = consecutiveBlocks.get(3);
Logger log = mock(Logger.class);
when(log.isDebugEnabled()).thenReturn(true);
IAionBlockchain chain = mock(AionBlockchainImpl.class);
when(chain.getBlockByHash(hash)).thenReturn(first);
when(chain.getBlocksByRange(first.getNumber(), last.getNumber())).thenReturn(List.of(last));
IP2pMgr p2p = mock(P2pMgr.class);
RequestBlocksHandler handler = new RequestBlocksHandler(log, chain, p2p);
// receive correct message
RequestBlocks request = new RequestBlocks(hash, 4, false);
handler.receive(peerId, displayId, request.encode());
verify(log, times(1)).debug("<request-blocks from-block={} count={} order={}>", Hex.toHexString(hash), 4, "ASC");
verify(chain, times(1)).getBlockByHash(hash);
verify(chain, times(1)).getBlocksByRange(first.getNumber(), last.getNumber());
ResponseBlocks expectedResponse = new ResponseBlocks(List.of(first));
verify(p2p, times(1)).send(peerId, displayId, expectedResponse);
}
use of org.aion.zero.impl.sync.msg.RequestBlocks in project aion by aionnetwork.
the class RequestBlocksHandlerTest method testReceive_correctMessage_ascending_withHeight.
@Test
public void testReceive_correctMessage_ascending_withHeight() {
Block first = consecutiveBlocks.get(0);
Block last = consecutiveBlocks.get(3);
Logger log = mock(Logger.class);
when(log.isDebugEnabled()).thenReturn(true);
IAionBlockchain chain = mock(AionBlockchainImpl.class);
when(chain.getBlocksByRange(first.getNumber(), last.getNumber())).thenReturn(consecutiveBlocks);
IP2pMgr p2p = mock(P2pMgr.class);
RequestBlocksHandler handler = new RequestBlocksHandler(log, chain, p2p);
// receive correct message
RequestBlocks request = new RequestBlocks(first.getNumber(), 4, false);
handler.receive(peerId, displayId, request.encode());
verify(log, times(1)).debug("<request-blocks from-block={} count={} order={}>", first.getNumber(), 4, "ASC");
verify(chain, times(1)).getBlocksByRange(first.getNumber(), last.getNumber());
ResponseBlocks expectedResponse = new ResponseBlocks(consecutiveBlocks);
verify(p2p, times(1)).send(peerId, displayId, expectedResponse);
}
Aggregations