/* * Copyright (c) [2016] [ <ether.camp> ] * This file is part of the ethereumJ library. * * The ethereumJ library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The ethereumJ library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see <http://www.gnu.org/licenses/>. */ package org.ethereum.net.eth.message; import org.ethereum.net.eth.EthVersion; import java.util.HashMap; import java.util.Map; import static org.ethereum.net.eth.EthVersion.*; /** * A list of commands for the Ethereum network protocol. * <br> * The codes for these commands are the first byte in every packet. * * @see <a href="https://github.com/ethereum/wiki/wiki/Ethereum-Wire-Protocol"> * https://github.com/ethereum/wiki/wiki/Ethereum-Wire-Protocol</a> */ public enum EthMessageCodes { /* Ethereum protocol */ /** * {@code [0x00, [PROTOCOL_VERSION, NETWORK_ID, TD, BEST_HASH, GENESIS_HASH] } <br> * * Inform a peer of it's current ethereum state. This message should be * send after the initial handshake and prior to any ethereum related messages. */ STATUS(0x00), /** * PV 61 and lower <br> * {@code [+0x01, [hash_0: B_32, hash_1: B_32, ...] } <br> * * PV 62 and upper <br> * {@code [+0x01: P, [hash_0: B_32, number_0: P], [hash_1: B_32, number_1: P], ...] } <br> * * Specify one or more new blocks which have appeared on the network. * To be maximally helpful, nodes should inform peers of all blocks that they may not be aware of. * Including hashes that the sending peer could reasonably be considered to know * (due to the fact they were previously informed of because * that node has itself advertised knowledge of the hashes through NewBlockHashes) * is considered Bad Form, and may reduce the reputation of the sending node. * Including hashes that the sending node later refuses to honour with a proceeding * GetBlocks message is considered Bad Form, and may reduce the reputation of the sending node. * */ NEW_BLOCK_HASHES(0x01), /** * {@code [+0x02, [nonce, receiving_address, value, ...], ...] } <br> * * Specify (a) transaction(s) that the peer should make sure is included * on its transaction queue. The items in the list (following the first item 0x12) * are transactions in the format described in the main Ethereum specification. */ TRANSACTIONS(0x02), /** * {@code [+0x03: P, block: { P , B_32 }, maxHeaders: P, skip: P, reverse: P in { 0 , 1 } ] } <br> * * Replaces GetBlockHashes since PV 62. <br> * * Require peer to return a BlockHeaders message. * Reply must contain a number of block headers, * of rising number when reverse is 0, falling when 1, skip blocks apart, * beginning at block block (denoted by either number or hash) in the canonical chain, * and with at most maxHeaders items. */ GET_BLOCK_HEADERS(0x03), /** * {@code [+0x04, blockHeader_0, blockHeader_1, ...] } <br> * * Replaces BLOCK_HASHES since PV 62. <br> * * Reply to GetBlockHeaders. * The items in the list (following the message ID) are * block headers in the format described in the main Ethereum specification, * previously asked for in a GetBlockHeaders message. * This may validly contain no block headers * if no block headers were able to be returned for the GetBlockHeaders query. */ BLOCK_HEADERS(0x04), /** * {@code [+0x05, hash_0: B_32, hash_1: B_32, ...] } <br> * * Replaces GetBlocks since PV 62. <br> * * Require peer to return a BlockBodies message. * Specify the set of blocks that we're interested in with the hashes. */ GET_BLOCK_BODIES(0x05), /** * {@code [+0x06, [transactions_0, uncles_0] , ...] } <br> * * Replaces Blocks since PV 62. <br> * * Reply to GetBlockBodies. * The items in the list (following the message ID) are some of the blocks, minus the header, * in the format described in the main Ethereum specification, previously asked for in a GetBlockBodies message. * This may validly contain no block headers * if no block headers were able to be returned for the GetBlockHeaders query. */ BLOCK_BODIES(0x06), /** * {@code [+0x07 [blockHeader, transactionList, uncleList], totalDifficulty] } <br> * * Specify a single block that the peer should know about. The composite item * in the list (following the message ID) is a block in the format described * in the main Ethereum specification. */ NEW_BLOCK(0x07), /** * {@code [+0x0d, hash_0: B_32, hash_1: B_32, ...] } <br> * * Require peer to return a NodeData message. Hint that useful values in it * are those which correspond to given hashes. */ GET_NODE_DATA(0x0d), /** * {@code [+0x0e, value_0: B, value_1: B, ...] } <br> * * Provide a set of values which correspond to previously asked node data * hashes from GetNodeData. Does not need to contain all; best effort is * fine. If it contains none, then has no information for previous * GetNodeData hashes. */ NODE_DATA(0x0e), /** * {@code [+0x0f, hash_0: B_32, hash_1: B_32, ...] } <br> * * Require peer to return a Receipts message. Hint that useful values in it * are those which correspond to blocks of the given hashes. */ GET_RECEIPTS(0x0f), /** * {@code [+0x10, [receipt_0, receipt_1], ...] } <br> * * Provide a set of receipts which correspond to previously asked in GetReceipts. */ RECEIPTS(0x10); private int cmd; private static final Map<EthVersion, Map<Integer, EthMessageCodes>> intToTypeMap = new HashMap<>(); private static final Map<EthVersion, EthMessageCodes[]> versionToValuesMap = new HashMap<>(); static { versionToValuesMap.put(V62, new EthMessageCodes[]{ STATUS, NEW_BLOCK_HASHES, TRANSACTIONS, GET_BLOCK_HEADERS, BLOCK_HEADERS, GET_BLOCK_BODIES, BLOCK_BODIES, NEW_BLOCK }); versionToValuesMap.put(V63, new EthMessageCodes[]{ STATUS, NEW_BLOCK_HASHES, TRANSACTIONS, GET_BLOCK_HEADERS, BLOCK_HEADERS, GET_BLOCK_BODIES, BLOCK_BODIES, NEW_BLOCK, GET_NODE_DATA, NODE_DATA, GET_RECEIPTS, RECEIPTS }); for (EthVersion v : EthVersion.values()) { Map<Integer, EthMessageCodes> map = new HashMap<>(); intToTypeMap.put(v, map); for (EthMessageCodes code : values(v)) { map.put(code.cmd, code); } } } private EthMessageCodes(int cmd) { this.cmd = cmd; } public static EthMessageCodes[] values(EthVersion v) { return versionToValuesMap.get(v); } public static EthMessageCodes fromByte(byte i, EthVersion v) { Map<Integer, EthMessageCodes> map = intToTypeMap.get(v); return map.get((int) i); } public static boolean inRange(byte code, EthVersion v) { EthMessageCodes[] codes = values(v); return code >= codes[0].asByte() && code <= codes[codes.length - 1].asByte(); } public byte asByte() { return (byte) (cmd); } }