use of org.aion.zero.impl.sync.msg.ResponseTrieData in project aion by aionnetwork.
the class RequestTrieDataHandler method receive.
@Override
public void receive(int peerId, String displayId, final byte[] message) {
if (message == null || message.length == 0) {
this.log.debug("<req-trie empty message from peer={}>", displayId);
return;
}
RequestTrieData request = RequestTrieData.decode(message);
if (request != null) {
DatabaseType dbType = request.getDbType();
ByteArrayWrapper key = ByteArrayWrapper.wrap(request.getNodeKey());
int limit = request.getLimit();
if (log.isDebugEnabled()) {
this.log.debug("<req-trie from-db={} key={} peer={}>", dbType, key, displayId);
}
byte[] value = null;
try {
// retrieve from blockchain depending on db type
value = chain.getTrieNode(key.toBytes(), dbType);
} catch (Exception e) {
this.log.error("<req-trie value retrieval failed>", e);
}
if (value != null) {
ResponseTrieData response;
if (limit == 1) {
// generate response without referenced nodes
response = new ResponseTrieData(key, value, dbType);
} else {
// check for internal limit on the request
if (limit == 0) {
limit = TRIE_DATA_REQUEST_MAXIMUM_BATCH_SIZE;
} else {
// the first value counts towards the limit
limit = Math.min(limit - 1, TRIE_DATA_REQUEST_MAXIMUM_BATCH_SIZE);
}
Map<ByteArrayWrapper, byte[]> referencedNodes = Collections.emptyMap();
try {
// determine if the node can be expanded
referencedNodes = chain.getReferencedTrieNodes(value, limit, dbType);
} catch (Exception e) {
this.log.error("<req-trie reference retrieval failed>", e);
}
// generate response with referenced nodes
response = new ResponseTrieData(key, value, referencedNodes, dbType);
}
// reply to request
this.p2p.send(peerId, displayId, response);
}
} else {
this.log.error("<req-trie decode-error msg-bytes={} peer={}>", message.length, displayId);
if (log.isTraceEnabled()) {
this.log.trace("<req-trie decode-error for msg={} peer={}>", Arrays.toString(message), displayId);
}
}
}
use of org.aion.zero.impl.sync.msg.ResponseTrieData in project aion by aionnetwork.
the class ResponseTrieDataHandlerTest method testReceive_correctMessage.
@Test
public void testReceive_correctMessage() {
Logger log = mock(Logger.class);
when(log.isDebugEnabled()).thenReturn(true);
BlockingQueue<TrieNodeWrapper> receivedQueue = new LinkedBlockingQueue<>();
ResponseTrieDataHandler handler = new ResponseTrieDataHandler(log, receivedQueue);
// receive correct message
byte[] encoding = RLP.encodeList(RLP.encodeElement(nodeKey), RLP.encodeElement(leafValue), RLP.encodeList(new byte[0]), RLP.encodeString(STATE.toString()));
handler.receive(peerId, displayId, encoding);
ResponseTrieData response = ResponseTrieData.decode(encoding);
verify(log, times(1)).debug("<res-trie response={} peer={}>", response, displayId);
TrieNodeWrapper node = new TrieNodeWrapper(peerId, displayId, response);
assertThat(receivedQueue).containsExactly(node);
}
use of org.aion.zero.impl.sync.msg.ResponseTrieData in project aion by aionnetwork.
the class TrieNodeWrapperTest method testConstructor.
@Test
public void testConstructor() {
byte[] encoding = RLP.encodeList(RLP.encodeElement(nodeKey), RLP.encodeElement(leafValue), RLP.encodeList(new byte[0]), RLP.encodeString(STATE.toString()));
ResponseTrieData response = ResponseTrieData.decode(encoding);
TrieNodeWrapper node = new TrieNodeWrapper(peerId, displayId, response);
assertThat(node.getPeerId()).isEqualTo(peerId);
assertThat(node.getDisplayId()).isEqualTo(displayId);
assertThat(node.getNodeKey()).isEqualTo(response.getNodeKey());
assertThat(node.getNodeValue()).isEqualTo(response.getNodeValue());
assertThat(node.getReferencedNodes()).isEqualTo(response.getReferencedNodes());
assertThat(node.getDbType()).isEqualTo(response.getDbType());
}
use of org.aion.zero.impl.sync.msg.ResponseTrieData in project aion by aionnetwork.
the class RequestTrieDataHandlerTest method testReceive_correctMessage_limitTwo.
@Test
public void testReceive_correctMessage_limitTwo() {
Logger log = mock(Logger.class);
when(log.isDebugEnabled()).thenReturn(true);
IAionBlockchain chain = mock(AionBlockchainImpl.class);
when(chain.getTrieNode(nodeKey, STATE)).thenReturn(leafValue);
when(chain.getReferencedTrieNodes(leafValue, 1, STATE)).thenReturn(singleReference);
IP2pMgr p2p = mock(P2pMgr.class);
RequestTrieDataHandler handler = new RequestTrieDataHandler(log, chain, p2p);
// receive correct message
byte[] encoding = RLP.encodeList(RLP.encodeElement(nodeKey), RLP.encodeString(STATE.toString()), RLP.encodeInt(2));
handler.receive(peerId, displayId, encoding);
verify(log, times(1)).debug("<req-trie from-db={} key={} peer={}>", STATE, wrappedNodeKey, displayId);
verify(chain, times(1)).getTrieNode(nodeKey, STATE);
verify(chain, times(1)).getReferencedTrieNodes(leafValue, 1, STATE);
ResponseTrieData expectedResponse = new ResponseTrieData(wrappedNodeKey, leafValue, singleReference, STATE);
verify(p2p, times(1)).send(peerId, displayId, expectedResponse);
}
use of org.aion.zero.impl.sync.msg.ResponseTrieData in project aion by aionnetwork.
the class RequestTrieDataHandlerTest method testReceive_correctMessage_limitOne.
@Test
public void testReceive_correctMessage_limitOne() {
Logger log = mock(Logger.class);
when(log.isDebugEnabled()).thenReturn(true);
IAionBlockchain chain = mock(AionBlockchainImpl.class);
when(chain.getTrieNode(nodeKey, STATE)).thenReturn(leafValue);
IP2pMgr p2p = mock(P2pMgr.class);
RequestTrieDataHandler handler = new RequestTrieDataHandler(log, chain, p2p);
// receive correct message
byte[] encoding = RLP.encodeList(RLP.encodeElement(nodeKey), RLP.encodeString(STATE.toString()), RLP.encodeInt(1));
handler.receive(peerId, displayId, encoding);
verify(log, times(1)).debug("<req-trie from-db={} key={} peer={}>", STATE, wrappedNodeKey, displayId);
verify(chain, times(1)).getTrieNode(nodeKey, STATE);
ResponseTrieData expectedResponse = new ResponseTrieData(wrappedNodeKey, leafValue, STATE);
verify(p2p, times(1)).send(peerId, displayId, expectedResponse);
}
Aggregations