use of org.aion.zero.impl.sync.DatabaseType 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.DatabaseType in project aion by aionnetwork.
the class RequestTrieDataTest method correctParameters.
/**
* Parameters for testing:
*
* <ul>
* <li>{@link #testDecode_correct(byte[], DatabaseType, int)}
* <li>{@link #testEncode_correct(byte[], DatabaseType, int)}
* <li>{@link #testEncodeDecode(byte[], DatabaseType, int)}
* </ul>
*/
@SuppressWarnings("unused")
private Object correctParameters() {
List<Object> parameters = new ArrayList<>();
byte[][] keyOptions = new byte[][] { nodeKey, altNodeKey, zeroNodeKey };
DatabaseType[] dbOptions = new DatabaseType[] { STATE, STORAGE, DETAILS };
int[] limitOptions = new int[] { 0, 1, 10, Integer.MAX_VALUE };
// network and directory
String[] net_values = new String[] { "mainnet", "invalid" };
for (byte[] key : keyOptions) {
for (DatabaseType db : dbOptions) {
for (int limit : limitOptions) {
parameters.add(new Object[] { key, db, limit });
}
}
}
return parameters.toArray();
}
use of org.aion.zero.impl.sync.DatabaseType in project aion by aionnetwork.
the class ResponseTrieData method decode.
/**
* Decodes a message into a trie node response.
*
* @param message a {@code byte} array representing a response to a trie node request.
* @return the decoded trie node response
* @implNote The decoder must return {@code null} if any of the component values are {@code
* null} or invalid.
*/
public static ResponseTrieData decode(final byte[] message) {
if (message == null || message.length == 0) {
return null;
} else {
RLPList list = RLP.decode2(message);
if (list.get(0) instanceof RLPList) {
list = (RLPList) list.get(0);
} else {
return null;
}
if (list.size() != TRIE_DATA_RESPONSE_COMPONENTS) {
return null;
} else {
// decode the key
byte[] hash = list.get(0).getRLPData();
if (hash.length != HASH_SIZE) {
return null;
}
// decode the value
byte[] value = list.get(1).getRLPData();
if (value.length == 0) {
return null;
}
// decode the referenced nodes
RLPElement referenced = list.get(2);
if (!(referenced instanceof RLPList)) {
return null;
}
Map<ByteArrayWrapper, byte[]> nodes = decodeReferencedNodes((RLPList) referenced);
if (nodes == null) {
return null;
}
// decode the db type
byte[] type = list.get(3).getRLPData();
DatabaseType dbType;
try {
dbType = DatabaseType.valueOf(new String(type));
} catch (IllegalArgumentException e) {
return null;
}
return new ResponseTrieData(ByteArrayWrapper.wrap(hash), value, nodes, dbType);
}
}
}
use of org.aion.zero.impl.sync.DatabaseType in project aion by aionnetwork.
the class RequestTrieData method decode.
/**
* Decodes a message into a trie node request.
*
* @param message a {@code byte} array representing a request for a trie node.
* @return the decoded trie node request if valid or {@code null} when the decoding encounters
* invalid input
* @implNote Ensures that the components are not {@code null}.
*/
public static RequestTrieData decode(final byte[] message) {
if (message == null || message.length == 0) {
return null;
} else {
RLPList list = RLP.decode2(message);
if (list.get(0) instanceof RLPList) {
list = (RLPList) list.get(0);
} else {
return null;
}
if (list.size() != TRIE_DATA_REQUEST_COMPONENTS) {
return null;
} else {
// decode the key
byte[] hash = list.get(0).getRLPData();
if (hash.length != HASH_SIZE) {
return null;
}
// decode the db type
byte[] type = list.get(1).getRLPData();
DatabaseType dbType;
try {
dbType = DatabaseType.valueOf(new String(type));
} catch (IllegalArgumentException e) {
return null;
}
// decode the limit
int depth = new BigInteger(1, list.get(2).getRLPData()).intValue();
return new RequestTrieData(hash, dbType, depth);
}
}
}
use of org.aion.zero.impl.sync.DatabaseType in project aion by aionnetwork.
the class ResponseTrieDataTest method correctParameters.
/**
* Parameters for testing:
*
* <ul>
* <li>{@link #testDecode_correct(ByteArrayWrapper, byte[], Map, DatabaseType)}
* <li>{@link #testEncode_4Parameters_correct(ByteArrayWrapper, byte[], Map, DatabaseType)}
* <li>{@link #testEncodeDecode(ByteArrayWrapper, byte[], Map, DatabaseType)}
* </ul>
*/
@SuppressWarnings("unused")
private Object correctParameters() {
List<Object> parameters = new ArrayList<>();
ByteArrayWrapper[] keyOptions = new ByteArrayWrapper[] { wrappedNodeKey, wrappedAltNodeKey, wrappedZeroNodeKey };
byte[][] valueOptions = new byte[][] { leafValue, branchValue, extensionValue };
Object[] refOptions = new Object[] { emptyReferences, singleReference, multipleReferences };
DatabaseType[] dbOptions = new DatabaseType[] { STATE, STORAGE, DETAILS };
// network and directory
String[] net_values = new String[] { "mainnet", "invalid" };
for (ByteArrayWrapper key : keyOptions) {
for (byte[] value : valueOptions) {
for (Object refs : refOptions) {
for (DatabaseType db : dbOptions) {
parameters.add(new Object[] { key, value, refs, db });
}
}
}
}
return parameters.toArray();
}
Aggregations