Search in sources :

Example 1 with DatabaseType

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);
        }
    }
}
Also used : DatabaseType(org.aion.zero.impl.sync.DatabaseType) ByteArrayWrapper(org.aion.util.types.ByteArrayWrapper) ResponseTrieData(org.aion.zero.impl.sync.msg.ResponseTrieData) RequestTrieData(org.aion.zero.impl.sync.msg.RequestTrieData)

Example 2 with DatabaseType

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();
}
Also used : DatabaseType(org.aion.zero.impl.sync.DatabaseType) ArrayList(java.util.ArrayList)

Example 3 with DatabaseType

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);
        }
    }
}
Also used : ByteArrayWrapper(org.aion.util.types.ByteArrayWrapper) DatabaseType(org.aion.zero.impl.sync.DatabaseType) RLPElement(org.aion.rlp.RLPElement) RLPList(org.aion.rlp.RLPList)

Example 4 with DatabaseType

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);
        }
    }
}
Also used : DatabaseType(org.aion.zero.impl.sync.DatabaseType) BigInteger(java.math.BigInteger) RLPList(org.aion.rlp.RLPList)

Example 5 with DatabaseType

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();
}
Also used : ByteArrayWrapper(org.aion.util.types.ByteArrayWrapper) DatabaseType(org.aion.zero.impl.sync.DatabaseType) ArrayList(java.util.ArrayList)

Aggregations

DatabaseType (org.aion.zero.impl.sync.DatabaseType)6 ByteArrayWrapper (org.aion.util.types.ByteArrayWrapper)4 ArrayList (java.util.ArrayList)3 RLPList (org.aion.rlp.RLPList)2 BigInteger (java.math.BigInteger)1 RLPElement (org.aion.rlp.RLPElement)1 RequestTrieData (org.aion.zero.impl.sync.msg.RequestTrieData)1 ResponseTrieData (org.aion.zero.impl.sync.msg.ResponseTrieData)1