Fix bug in toInt() and refactor RLPList to extend ArrayList
This commit is contained in:
parent
7eaf9f0dba
commit
260aae5881
|
@ -111,7 +111,7 @@ public class Block {
|
|||
|
||||
this.hash = HashUtil.sha3(rawData.getRLPData());
|
||||
|
||||
List params = ((RLPList) rawData.getElement(0)).getList();
|
||||
RLPList params = (RLPList) rawData.get(0);
|
||||
|
||||
this.parentHash = ((RLPItem) params.get(0)).getData();
|
||||
this.unclesHash = ((RLPItem) params.get(1)).getData();
|
||||
|
@ -136,13 +136,13 @@ public class Block {
|
|||
this.nonce = ((RLPItem) params.get(12)).getData();
|
||||
|
||||
// parse transactions
|
||||
List<RLPElement> transactions = ((RLPList) rawData.getElement(1)).getList();
|
||||
RLPList transactions = (RLPList) rawData.get(1);
|
||||
for (RLPElement rlpTx : transactions){
|
||||
Transaction tx = new Transaction((RLPList)rlpTx);
|
||||
this.transactionsList.add(tx);
|
||||
}
|
||||
// parse uncles
|
||||
List<RLPElement> uncleBlocks = ((RLPList) rawData.getElement(2)).getList();
|
||||
RLPList uncleBlocks = (RLPList) rawData.get(2);
|
||||
for (RLPElement rawUncle : uncleBlocks){
|
||||
Block blockData = new Block((RLPList)rawUncle);
|
||||
this.uncleList.add(blockData);
|
||||
|
|
|
@ -71,23 +71,23 @@ public class Transaction {
|
|||
|
||||
public void rlpParse(){
|
||||
this.hash = HashUtil.sha3(rawData.getRLPData());
|
||||
this.nonce = ((RLPItem) rawData.getElement(0)).getData();
|
||||
this.value = ((RLPItem) rawData.getElement(1)).getData();
|
||||
this.receiveAddress = ((RLPItem) rawData.getElement(2)).getData();
|
||||
this.gasPrice = ((RLPItem) rawData.getElement(3)).getData();
|
||||
this.gasLimit = ((RLPItem) rawData.getElement(4)).getData();
|
||||
this.data = ((RLPItem) rawData.getElement(5)).getData();
|
||||
this.nonce = ((RLPItem) rawData.get(0)).getData();
|
||||
this.value = ((RLPItem) rawData.get(1)).getData();
|
||||
this.receiveAddress = ((RLPItem) rawData.get(2)).getData();
|
||||
this.gasPrice = ((RLPItem) rawData.get(3)).getData();
|
||||
this.gasLimit = ((RLPItem) rawData.get(4)).getData();
|
||||
this.data = ((RLPItem) rawData.get(5)).getData();
|
||||
|
||||
if (rawData.size() == 9){ // Simple transaction
|
||||
byte v = ((RLPItem) rawData.getElement(6)).getData()[0];
|
||||
byte[] r = ((RLPItem) rawData.getElement(7)).getData();
|
||||
byte[] s = ((RLPItem) rawData.getElement(8)).getData();
|
||||
byte v = ((RLPItem) rawData.get(6)).getData()[0];
|
||||
byte[] r = ((RLPItem) rawData.get(7)).getData();
|
||||
byte[] s = ((RLPItem) rawData.get(8)).getData();
|
||||
this.signature = ECDSASignature.fromComponents(r, s, v);
|
||||
} else if (rawData.size() == 10){ // Contract creation transaction
|
||||
this.init = ((RLPItem) rawData.getElement(6)).getData();
|
||||
byte v = ((RLPItem) rawData.getElement(7)).getData()[0];
|
||||
byte[] r = ((RLPItem) rawData.getElement(8)).getData();
|
||||
byte[] s = ((RLPItem) rawData.getElement(9)).getData();
|
||||
this.init = ((RLPItem) rawData.get(6)).getData();
|
||||
byte v = ((RLPItem) rawData.get(7)).getData()[0];
|
||||
byte[] r = ((RLPItem) rawData.get(8)).getData();
|
||||
byte[] s = ((RLPItem) rawData.get(9)).getData();
|
||||
this.signature = ECDSASignature.fromComponents(r, s, v);
|
||||
} else throw new RuntimeException("Wrong tx data element list size");
|
||||
this.parsed = true;
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.ethereum.net.message.NotInChainMessage;
|
|||
import org.ethereum.net.message.PeersMessage;
|
||||
import org.ethereum.net.message.StaticMessages;
|
||||
import org.ethereum.net.message.TransactionsMessage;
|
||||
import org.ethereum.util.ByteUtil;
|
||||
import org.ethereum.util.RLP;
|
||||
import org.ethereum.util.RLPList;
|
||||
import org.ethereum.util.Utils;
|
||||
|
@ -40,7 +41,7 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter {
|
|||
private final static byte[] MAGIC_PREFIX = {(byte)0x22, (byte)0x40, (byte)0x08, (byte)0x91};
|
||||
|
||||
private final static byte[] HELLO_MESSAGE = StaticMessages.HELLO_MESSAGE.getPayload();
|
||||
private final static byte[] HELLO_MESSAGE_LEN = calcPacketLength(HELLO_MESSAGE);
|
||||
private final static byte[] HELLO_MESSAGE_LEN = ByteUtil.calcPacketLength(HELLO_MESSAGE);
|
||||
|
||||
private long lastPongTime = 0;
|
||||
private boolean tearDown = false;
|
||||
|
@ -268,10 +269,9 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter {
|
|||
}
|
||||
|
||||
private void sendMsg(Message msg, ChannelHandlerContext ctx){
|
||||
|
||||
byte[] data = msg.getPayload();
|
||||
final ByteBuf buffer = ctx.alloc().buffer(data.length + 8);
|
||||
byte[] packetLen = calcPacketLength(data);
|
||||
byte[] packetLen = ByteUtil.calcPacketLength(data);
|
||||
|
||||
buffer.writeBytes(MAGIC_PREFIX);
|
||||
buffer.writeBytes(packetLen);
|
||||
|
@ -312,22 +312,8 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter {
|
|||
private void sendTx(ChannelHandlerContext ctx){
|
||||
byte[] TX_MSG =
|
||||
Hex.decode("2240089100000070F86E12F86B80881BC16D674EC8000094CD2A3D9F938E13CD947EC05ABC7FE734DF8DD8268609184E72A00064801BA0C52C114D4F5A3BA904A9B3036E5E118FE0DBB987FE3955DA20F2CD8F6C21AB9CA06BA4C2874299A55AD947DBC98A25EE895AABF6B625C26C435E84BFD70EDF2F69");
|
||||
|
||||
ByteBuf buffer = ctx.alloc().buffer(TX_MSG.length);
|
||||
buffer.writeBytes(TX_MSG);
|
||||
ctx.writeAndFlush(buffer);
|
||||
}
|
||||
|
||||
private static byte[] calcPacketLength(byte[] msg){
|
||||
|
||||
int msgLen = msg.length;
|
||||
|
||||
byte[] len = {
|
||||
(byte)((msgLen >> 24) & 0xFF),
|
||||
(byte)((msgLen >> 16) & 0xFF),
|
||||
(byte)((msgLen >> 8) & 0xFF),
|
||||
(byte)((msgLen ) & 0xFF)};
|
||||
return len;
|
||||
}
|
||||
|
||||
}
|
|
@ -26,14 +26,14 @@ public class BlocksMessage extends Message {
|
|||
|
||||
public void parseRLP() {
|
||||
|
||||
RLPList paramsList = (RLPList) rawData.getElement(0);
|
||||
RLPList paramsList = (RLPList) rawData.get(0);
|
||||
|
||||
if (Command.fromInt(((RLPItem) (paramsList).getElement(0)).getData()[0]) != BLOCKS) {
|
||||
if (Command.fromInt(((RLPItem) (paramsList).get(0)).getData()[0]) != BLOCKS) {
|
||||
throw new Error("BlocksMessage: parsing for mal data");
|
||||
}
|
||||
|
||||
for (int i = 1; i < paramsList.size(); ++i) {
|
||||
RLPList rlpData = ((RLPList) paramsList.getElement(i));
|
||||
RLPList rlpData = ((RLPList) paramsList.get(i));
|
||||
Block blockData = new Block(rlpData);
|
||||
this.blockDataList.add(blockData);
|
||||
}
|
||||
|
@ -46,8 +46,7 @@ public class BlocksMessage extends Message {
|
|||
}
|
||||
|
||||
public List<Block> getBlockDataList() {
|
||||
if (!parsed)
|
||||
parseRLP();
|
||||
if (!parsed) parseRLP();
|
||||
return blockDataList;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,13 +23,13 @@ public class DisconnectMessage extends Message {
|
|||
@Override
|
||||
public void parseRLP() {
|
||||
|
||||
RLPList paramsList = (RLPList) rawData.getElement(0);
|
||||
RLPList paramsList = (RLPList) rawData.get(0);
|
||||
|
||||
if (Command.fromInt(((RLPItem)(paramsList).getElement(0)).getData()[0]) != DISCONNECT){
|
||||
if (Command.fromInt(((RLPItem)(paramsList).get(0)).getData()[0]) != DISCONNECT){
|
||||
throw new Error("Disconnect: parsing for mal data");
|
||||
}
|
||||
|
||||
byte[] reasonB = ((RLPItem)paramsList.getElement(1)).getData();
|
||||
byte[] reasonB = ((RLPItem)paramsList.get(1)).getData();
|
||||
if (reasonB == null){
|
||||
this.reason = DISCONNECT_REQUESTED;
|
||||
} else {
|
||||
|
|
|
@ -28,19 +28,19 @@ public class GetChainMessage extends Message {
|
|||
@Override
|
||||
public void parseRLP() {
|
||||
|
||||
RLPList paramsList = (RLPList) rawData.getElement(0);
|
||||
RLPList paramsList = (RLPList) rawData.get(0);
|
||||
|
||||
if (Command.fromInt(((RLPItem)(paramsList).getElement(0)).getData()[0]) != GET_CHAIN){
|
||||
if (Command.fromInt(((RLPItem)(paramsList).get(0)).getData()[0]) != GET_CHAIN){
|
||||
throw new Error("GetChain: parsing for mal data");
|
||||
}
|
||||
|
||||
int size = paramsList.size();
|
||||
for (int i = 1; i < size - 1; ++i){
|
||||
blockHashList.add(((RLPItem) paramsList.getElement(i)).getData());
|
||||
blockHashList.add(((RLPItem) paramsList.get(i)).getData());
|
||||
}
|
||||
|
||||
// the last element is the num of requested blocks
|
||||
byte[] blockNumB = ((RLPItem)paramsList.getElement(size - 1)).getData();
|
||||
byte[] blockNumB = ((RLPItem)paramsList.get(size - 1)).getData();
|
||||
this.blockNum = new BigInteger(blockNumB);
|
||||
|
||||
this.parsed = true;
|
||||
|
|
|
@ -40,25 +40,25 @@ public class HelloMessage extends Message {
|
|||
@Override
|
||||
public void parseRLP() {
|
||||
|
||||
RLPList paramsList = (RLPList) rawData.getElement(0);
|
||||
RLPList paramsList = (RLPList) rawData.get(0);
|
||||
|
||||
// the message does no distinguish between the 0 and null so here I check command code for null
|
||||
// todo: find out if it can be 00
|
||||
if (((RLPItem)(paramsList).getElement(0)).getData() != null){
|
||||
if (((RLPItem)(paramsList).get(0)).getData() != null){
|
||||
throw new Error("HelloMessage: parsing for mal data");
|
||||
}
|
||||
|
||||
this.protocolVersion = ((RLPItem) paramsList.getElement(1)).getData()[0];
|
||||
this.protocolVersion = ((RLPItem) paramsList.get(1)).getData()[0];
|
||||
|
||||
byte[] networkIdBytes = ((RLPItem) paramsList.getElement(2)).getData();
|
||||
byte[] networkIdBytes = ((RLPItem) paramsList.get(2)).getData();
|
||||
this.networkId = networkIdBytes == null ? 0 : networkIdBytes[0] ;
|
||||
|
||||
this.clientId = new String(((RLPItem) paramsList.getElement(3)).getData());
|
||||
this.capabilities = ((RLPItem) paramsList.getElement(4)).getData()[0];
|
||||
this.clientId = new String(((RLPItem) paramsList.get(3)).getData());
|
||||
this.capabilities = ((RLPItem) paramsList.get(4)).getData()[0];
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(((RLPItem) paramsList.getElement(5)).getData());
|
||||
ByteBuffer bb = ByteBuffer.wrap(((RLPItem) paramsList.get(5)).getData());
|
||||
this.peerPort = bb.getShort();
|
||||
this.peerId = ((RLPItem) paramsList.getElement(6)).getData();
|
||||
this.peerId = ((RLPItem) paramsList.get(6)).getData();
|
||||
this.parsed = true;
|
||||
// todo: what to do when mal data ?
|
||||
}
|
||||
|
|
|
@ -23,12 +23,12 @@ public class NotInChainMessage extends Message {
|
|||
|
||||
@Override
|
||||
public void parseRLP() {
|
||||
RLPList paramsList = (RLPList) rawData.getElement(0);
|
||||
RLPList paramsList = (RLPList) rawData.get(0);
|
||||
|
||||
if (Command.fromInt(((RLPItem)(paramsList).getElement(0)).getData()[0] & 0xFF) != NOT_IN_CHAIN){
|
||||
if (Command.fromInt(((RLPItem)(paramsList).get(0)).getData()[0] & 0xFF) != NOT_IN_CHAIN){
|
||||
throw new Error("NotInChain Message: parsing for mal data");
|
||||
}
|
||||
hash = ((RLPItem)paramsList.getElement(1)).getData();
|
||||
hash = ((RLPItem)paramsList.get(1)).getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -31,17 +31,17 @@ public class PeersMessage extends Message {
|
|||
@Override
|
||||
public void parseRLP() {
|
||||
|
||||
RLPList paramsList = (RLPList) rawData.getElement(0);
|
||||
RLPList paramsList = (RLPList) rawData.get(0);
|
||||
|
||||
if (Command.fromInt(((RLPItem)(paramsList).getElement(0)).getData()[0] & 0xFF) != PEERS){
|
||||
if (Command.fromInt(((RLPItem)(paramsList).get(0)).getData()[0] & 0xFF) != PEERS){
|
||||
throw new Error("PeersMessage: parsing for mal data");
|
||||
}
|
||||
|
||||
for (int i = 1; i < paramsList.size(); ++i){
|
||||
|
||||
RLPList peerParams = (RLPList)paramsList.getElement(i);
|
||||
byte[] ip = ((RLPItem) peerParams.getElement(0)).getData();
|
||||
byte[] shortData = ((RLPItem) peerParams.getElement(1)).getData();
|
||||
RLPList peerParams = (RLPList)paramsList.get(i);
|
||||
byte[] ip = ((RLPItem) peerParams.get(0)).getData();
|
||||
byte[] shortData = ((RLPItem) peerParams.get(1)).getData();
|
||||
short peerPort = 0;
|
||||
if (shortData.length == 1)
|
||||
peerPort = shortData[0];
|
||||
|
@ -49,7 +49,7 @@ public class PeersMessage extends Message {
|
|||
ByteBuffer bb = ByteBuffer.wrap(shortData, 0, shortData.length);
|
||||
peerPort = bb.getShort();
|
||||
}
|
||||
byte[] peerId = ((RLPItem) peerParams.getElement(2)).getData();
|
||||
byte[] peerId = ((RLPItem) peerParams.get(2)).getData();
|
||||
PeerData peer = new PeerData(ip, peerPort, peerId);
|
||||
peers.add(peer);
|
||||
}
|
||||
|
|
|
@ -28,16 +28,16 @@ public class TransactionsMessage extends Message {
|
|||
|
||||
@Override
|
||||
public void parseRLP() {
|
||||
RLPList paramsList = (RLPList) rawData.getElement(0);
|
||||
RLPList paramsList = (RLPList) rawData.get(0);
|
||||
|
||||
if (Command.fromInt(((RLPItem)(paramsList).getElement(0)).getData()[0] & 0xFF) != TRANSACTIONS) {
|
||||
if (Command.fromInt(((RLPItem)(paramsList).get(0)).getData()[0] & 0xFF) != TRANSACTIONS) {
|
||||
throw new Error("TransactionMessage: parsing for mal data");
|
||||
}
|
||||
|
||||
transactions = new ArrayList<Transaction>();
|
||||
int size = paramsList.getList().size();
|
||||
int size = paramsList.size();
|
||||
for (int i = 1; i < size; ++i){
|
||||
RLPList rlpTxData = (RLPList) paramsList.getElement(i);
|
||||
RLPList rlpTxData = (RLPList) paramsList.get(i);
|
||||
Transaction tx = new Transaction(rlpTxData);
|
||||
transactions.add(tx);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package org.ethereum.util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
|
||||
|
@ -40,19 +38,34 @@ public class ByteUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* <p>Given a textual message, returns a byte buffer formatted as follows:</p>
|
||||
* Calculate packet length
|
||||
* @param msg
|
||||
* @return byte-array with 4 elements
|
||||
*/
|
||||
public static byte[] formatForSigning(byte[] message) {
|
||||
try {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
bos.write(encodeInt(message.length));
|
||||
bos.write(message);
|
||||
return bos.toByteArray();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e); // Cannot happen.
|
||||
}
|
||||
public static byte[] calcPacketLength(byte[] msg){
|
||||
int msgLen = msg.length;
|
||||
byte[] len = {
|
||||
(byte)((msgLen >> 24) & 0xFF),
|
||||
(byte)((msgLen >> 16) & 0xFF),
|
||||
(byte)((msgLen >> 8) & 0xFF),
|
||||
(byte)((msgLen ) & 0xFF)};
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast hex encoded value from byte[] to int
|
||||
*
|
||||
* Limited to Integer.MAX_VALUE: 2^32-1 (4 bytes)
|
||||
*
|
||||
* @param b array contains the values
|
||||
* @return unsigned positive int value.
|
||||
*/
|
||||
public static int byteArrayToInt(byte[] b) {
|
||||
if (b == null || b.length == 0)
|
||||
return 0;
|
||||
return new BigInteger(1, b).intValue();
|
||||
}
|
||||
|
||||
public static byte[] encodeInt(int value) {
|
||||
if (isLessThanUnsigned(value, 253)) {
|
||||
return new byte[]{(byte) value};
|
||||
|
|
|
@ -7,6 +7,7 @@ import java.util.Arrays;
|
|||
import java.util.Queue;
|
||||
|
||||
import static java.util.Arrays.copyOfRange;
|
||||
import static org.ethereum.util.ByteUtil.byteArrayToInt;
|
||||
import static org.spongycastle.util.Arrays.concatenate;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -556,7 +557,7 @@ public class RLP {
|
|||
fullTraverse(msgData, level + 1, pos + lengthOfLength + 1,
|
||||
pos + lengthOfLength + length + 1, levelToIndex,
|
||||
newLevelList);
|
||||
rlpList.addItem(newLevelList);
|
||||
rlpList.add(newLevelList);
|
||||
|
||||
pos += lengthOfLength + length + 1;
|
||||
continue;
|
||||
|
@ -576,7 +577,7 @@ public class RLP {
|
|||
if (length > 0)
|
||||
fullTraverse(msgData, level + 1, pos + 1, pos + length
|
||||
+ 1, levelToIndex, newLevelList);
|
||||
rlpList.addItem(newLevelList);
|
||||
rlpList.add(newLevelList);
|
||||
|
||||
pos += 1 + length;
|
||||
continue;
|
||||
|
@ -600,7 +601,7 @@ public class RLP {
|
|||
lengthOfLength + 1);
|
||||
|
||||
RLPItem rlpItem = new RLPItem(item);
|
||||
rlpList.addItem(rlpItem);
|
||||
rlpList.add(rlpItem);
|
||||
pos += lengthOfLength + length + 1;
|
||||
|
||||
continue;
|
||||
|
@ -619,7 +620,7 @@ public class RLP {
|
|||
System.arraycopy(msgData, pos, rlpPrefix, 0, 2);
|
||||
|
||||
RLPItem rlpItem = new RLPItem(item);
|
||||
rlpList.addItem(rlpItem);
|
||||
rlpList.add(rlpItem);
|
||||
pos += 1 + length;
|
||||
|
||||
continue;
|
||||
|
@ -628,7 +629,7 @@ public class RLP {
|
|||
if ((msgData[pos] & 0xFF) == OFFSET_SHORT_ITEM) {
|
||||
byte[] item = new byte[0];
|
||||
RLPItem rlpItem = new RLPItem(item);
|
||||
rlpList.addItem(rlpItem);
|
||||
rlpList.add(rlpItem);
|
||||
pos += 1;
|
||||
continue;
|
||||
}
|
||||
|
@ -638,7 +639,7 @@ public class RLP {
|
|||
byte[] item = { (byte) (msgData[pos] & 0xFF) };
|
||||
|
||||
RLPItem rlpItem = new RLPItem(item);
|
||||
rlpList.addItem(rlpItem);
|
||||
rlpList.add(rlpItem);
|
||||
pos += 1;
|
||||
continue;
|
||||
}
|
||||
|
@ -671,7 +672,7 @@ public class RLP {
|
|||
return new DecodeResult(pos+1+len, copyOfRange(data, pos+1, pos+1+len));
|
||||
} else if (prefix < OFFSET_SHORT_LIST) {
|
||||
int lenlen = prefix - OFFSET_LONG_ITEM + 1; // length of length the encoded bytes
|
||||
int lenbytes = toInt(copyOfRange(data, pos+1, pos+1+lenlen)); // length of encoded bytes
|
||||
int lenbytes = byteArrayToInt(copyOfRange(data, pos+1, pos+1+lenlen)); // length of encoded bytes
|
||||
return new DecodeResult(pos+1+lenlen+lenbytes, copyOfRange(data, pos+1+lenlen, pos+1+lenlen+lenbytes));
|
||||
} else if (prefix < OFFSET_LONG_LIST) {
|
||||
int len = prefix - OFFSET_SHORT_LIST; // length of the encoded list
|
||||
|
@ -679,7 +680,7 @@ public class RLP {
|
|||
return decodeList(data, pos, prevPos, len);
|
||||
} else if (prefix < 0xFF) {
|
||||
int lenlen = prefix - OFFSET_LONG_LIST + 1; // length of length the encoded list
|
||||
int lenlist = toInt(copyOfRange(data, pos+1, pos+1+lenlen)); // length of encoded bytes
|
||||
int lenlist = byteArrayToInt(copyOfRange(data, pos+1, pos+1+lenlen)); // length of encoded bytes
|
||||
pos = pos + lenlen + 1;
|
||||
int prevPos = lenlist;
|
||||
return decodeList(data, pos, prevPos, lenlist);
|
||||
|
@ -701,22 +702,7 @@ public class RLP {
|
|||
}
|
||||
return new DecodeResult(pos, slice.toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast hex encoded value from byte[] to int
|
||||
*
|
||||
* Limited to Integer.MAX_VALUE: 2^32-1
|
||||
*
|
||||
* @param b array contains the hex values
|
||||
* @return int value of all hex values together.
|
||||
*/
|
||||
public static int toInt(byte[] b) {
|
||||
if (b == null || b.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
return new BigInteger(b).intValue();
|
||||
}
|
||||
|
||||
|
||||
/* ******************************************************
|
||||
* ENCODING *
|
||||
* ******************************************************/
|
||||
|
@ -767,7 +753,6 @@ public class RLP {
|
|||
}
|
||||
|
||||
public static byte[] encodeByte(byte singleByte) {
|
||||
|
||||
if ((singleByte & 0xFF) == 0) {
|
||||
return new byte[] { (byte) OFFSET_SHORT_ITEM };
|
||||
} else if ((singleByte & 0xFF) < 0x7F) {
|
||||
|
@ -781,8 +766,9 @@ public class RLP {
|
|||
if (singleShort <= 0xFF)
|
||||
return encodeByte((byte) singleShort);
|
||||
else {
|
||||
return new byte[] { (byte) (OFFSET_SHORT_ITEM+2), (byte) (singleShort >> 8 & 0xFF),
|
||||
(byte) (singleShort >> 0 & 0xFF) };
|
||||
return new byte[] { (byte) (OFFSET_SHORT_ITEM + 2),
|
||||
(byte) (singleShort >> 8 & 0xFF),
|
||||
(byte) (singleShort >> 0 & 0xFF) };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,37 +1,15 @@
|
|||
package org.ethereum.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
* User: Roman Mandeleil
|
||||
* Created on: 21/04/14 16:26
|
||||
*/
|
||||
public class RLPList implements RLPElement {
|
||||
public class RLPList extends ArrayList<RLPElement> implements RLPElement {
|
||||
|
||||
byte[] rlpData;
|
||||
List<RLPElement> list;
|
||||
|
||||
public RLPList() {
|
||||
this.list = new ArrayList<RLPElement>();
|
||||
}
|
||||
|
||||
public void addItem(RLPElement element){
|
||||
list.add(element);
|
||||
}
|
||||
|
||||
public RLPElement getElement(int index){
|
||||
return list.get(index);
|
||||
}
|
||||
|
||||
public int size(){
|
||||
return list.size();
|
||||
}
|
||||
|
||||
public List<RLPElement> getList(){
|
||||
return list;
|
||||
}
|
||||
|
||||
public void setRLPData(byte[] rlpData){
|
||||
this.rlpData = rlpData;
|
||||
|
@ -49,7 +27,7 @@ public class RLPList implements RLPElement {
|
|||
|
||||
RLPList rlpList = (RLPList) element;
|
||||
System.out.print("[");
|
||||
for (RLPElement singleElement : rlpList.getList()) {
|
||||
for (RLPElement singleElement : rlpList) {
|
||||
recursivePrint(singleElement);
|
||||
}
|
||||
System.out.print("]");
|
||||
|
|
|
@ -128,7 +128,7 @@ public class BlockTest {
|
|||
public void testGenesisFromNew() {
|
||||
|
||||
System.out.println(CPP_PoC5_GENESIS_HEX_RLP_ENCODED);
|
||||
Object genesisItems = RLP.decode(CPP_PoC5_GENESIS_HEX_RLP_ENCODED.getBytes(), 0).getDecoded();
|
||||
Object genesisItems = RLP.decode(Hex.decode(CPP_PoC5_GENESIS_HEX_RLP_ENCODED), 0).getDecoded();
|
||||
// TODO: verify genesis items with expected values
|
||||
|
||||
/* From: https://ethereum.etherpad.mozilla.org/11
|
||||
|
|
|
@ -314,10 +314,31 @@ public class MessagesTest {
|
|||
@Test /* BlocksMessage parsing 1*/
|
||||
public void test_10(){
|
||||
|
||||
// BlockData [ hash=36a24b56c6104e5a5c0e70b0553f1a4d6109d065d718d7443a6a475ec8c83905 parentHash=372d8e5c6e32335fb86fa7a6ae1b35165745346e1c786eacd42df85f8da12b3d, unclesHash=1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347, coinbase=1a4d98707ba8dd3d36d16e8c165c272645695cea, stateHash=5e2d2cc0b42b38b5b18c9d65734f9877c035dd390b9c12c48624f2243668a268, txListHash=1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347, difficulty=02471a26, timestamp=1398260220, extraData=null, nonce=0000000000000000000000000000000000000000000000006f4cd02da011a235]
|
||||
String blocksRaw = "F8CC13F8C9F8C5A0372D8E5C6E32335FB86FA7A6AE1B35165745346E1C786EACD42DF85F8DA12B3DA01DCC4DE8DEC75D7AAB85B567B6CCD41AD312451B948A7413F0A142FD40D49347941A4D98707BA8DD3D36D16E8C165C272645695CEAA05E2D2CC0B42B38B5B18C9D65734F9877C035DD390B9C12C48624F2243668A268A01DCC4DE8DEC75D7AAB85B567B6CCD41AD312451B948A7413F0A142FD40D493478402471A26845357C1FC80A00000000000000000000000000000000000000000000000006F4CD02DA011A235C0C0";
|
||||
// BlockData [ hash=36a24b56c6104e5a5c0e70b0553f1a4d6109d065d718d7443a6a475ec8c83905 parentHash=372d8e5c6e32335fb86fa7a6ae1b35165745346e1c786eacd42df85f8da12b3d, unclesHash=1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347, coinbase=1a4d98707ba8dd3d36d16e8c165c272645695cea, stateHash=5e2d2cc0b42b38b5b18c9d65734f9877c035dd390b9c12c48624f2243668a268, txListHash=1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347, difficulty=02471a26, timestamp=1398260220, extraData=null, nonce=0000000000000000000000000000000000000000000000006f4cd02da011a235]
|
||||
// String blocksRaw = "F8CC13F8C9F8C5A0372D8E5C6E32335FB86FA7A6AE1B35165745346E1C786EACD42DF85F8DA12B3DA01DCC4DE8DEC75D7AAB85B567B6CCD41AD312451B948A7413F0A142FD40D49347941A4D98707BA8DD3D36D16E8C165C272645695CEAA05E2D2CC0B42B38B5B18C9D65734F9877C035DD390B9C12C48624F2243668A268A01DCC4DE8DEC75D7AAB85B567B6CCD41AD312451B948A7413F0A142FD40D493478402471A26845357C1FC80A00000000000000000000000000000000000000000000000006F4CD02DA011A235C0C0";
|
||||
|
||||
byte[] payload = Hex.decode(blocksRaw);
|
||||
/*
|
||||
parentHash: 00000000000000000000000000000000000000000000000000000000000000000
|
||||
unclesHash: 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347
|
||||
coinbase: 0000000000000000000000000000000000000000
|
||||
stateRoot: 2f4399b08efe68945c1cf90ffe85bbe3ce978959da753f9e649f034015b8817d
|
||||
txsTrieRoot: 00000000000000000000000000000000000000000000000000000000000000000
|
||||
difficulty: 400000
|
||||
number: <<empty string>>
|
||||
mixGasPrice: <<empty string>>
|
||||
gasLimit: 0f4240
|
||||
gasUsed: <<empty string>>
|
||||
timestamp: <<empty string>>
|
||||
extraData: <<empty string>>
|
||||
nonce: 04994f67dc55b09e814ab7ffc8df3686b4afb2bb53e60eae97ef043fe03fb829
|
||||
transaction: <<empty string>>
|
||||
uncles: <<empty string>>
|
||||
*/
|
||||
|
||||
// Genesis block
|
||||
String blocksRaw = "f8cbf8c7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a02f4399b08efe68945c1cf90ffe85bbe3ce978959da753f9e649f034015b8817da00000000000000000000000000000000000000000000000000000000000000000834000008080830f4240808080a004994f67dc55b09e814ab7ffc8df3686b4afb2bb53e60eae97ef043fe03fb829c0c0";
|
||||
|
||||
byte[] payload = Hex.decode(blocksRaw);
|
||||
RLPList rlpList = RLP.decode2(payload);
|
||||
|
||||
BlocksMessage blocksMessage = new BlocksMessage(rlpList);
|
||||
|
@ -328,31 +349,31 @@ public class MessagesTest {
|
|||
|
||||
Block block = list.get(0);
|
||||
|
||||
assertEquals("36A24B56C6104E5A5C0E70B0553F1A4D6109D065D718D7443A6A475EC8C83905",
|
||||
Utils.toHexString(block.getHash()).toUpperCase());
|
||||
assertEquals("69a7356a245f9dc5b865475ada5ee4e89b18f93c06503a9db3b3630e88e9fb4e",
|
||||
Utils.toHexString(block.getHash()));
|
||||
|
||||
assertEquals("372D8E5C6E32335FB86FA7A6AE1B35165745346E1C786EACD42DF85F8DA12B3D",
|
||||
Utils.toHexString(block.getParentHash()).toUpperCase());
|
||||
assertEquals("00000000000000000000000000000000000000000000000000000000000000000",
|
||||
Utils.toHexString(block.getParentHash()));
|
||||
|
||||
assertEquals("1DCC4DE8DEC75D7AAB85B567B6CCD41AD312451B948A7413F0A142FD40D49347",
|
||||
Utils.toHexString(block.getUnclesHash()).toUpperCase());
|
||||
assertEquals("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||
Utils.toHexString(block.getUnclesHash()));
|
||||
|
||||
assertEquals("1A4D98707BA8DD3D36D16E8C165C272645695CEA",
|
||||
Utils.toHexString(block.getCoinbase()).toUpperCase());
|
||||
assertEquals("0000000000000000000000000000000000000000",
|
||||
Utils.toHexString(block.getCoinbase()));
|
||||
|
||||
assertEquals("5E2D2CC0B42B38B5B18C9D65734F9877C035DD390B9C12C48624F2243668A268",
|
||||
Utils.toHexString(block.getStateRoot()).toUpperCase());
|
||||
assertEquals("2f4399b08efe68945c1cf90ffe85bbe3ce978959da753f9e649f034015b8817d",
|
||||
Utils.toHexString(block.getStateRoot()));
|
||||
|
||||
assertEquals("1DCC4DE8DEC75D7AAB85B567B6CCD41AD312451B948A7413F0A142FD40D49347",
|
||||
Utils.toHexString(block.getTxTrieRoot()).toUpperCase());
|
||||
assertEquals("00000000000000000000000000000000000000000000000000000000000000000",
|
||||
Utils.toHexString(block.getTxTrieRoot()));
|
||||
|
||||
assertEquals("02471A26", Utils.toHexString(block.getDifficulty()).toUpperCase());
|
||||
assertEquals(1398260220, block.getTimestamp());
|
||||
assertEquals("400000", Utils.toHexString(block.getDifficulty()));
|
||||
assertEquals(0, block.getTimestamp());
|
||||
|
||||
assertNull(block.getExtraData());
|
||||
|
||||
assertEquals("0000000000000000000000000000000000000000000000006F4CD02DA011A235",
|
||||
Utils.toHexString(block.getNonce()).toUpperCase());
|
||||
assertEquals("04994f67dc55b09e814ab7ffc8df3686b4afb2bb53e60eae97ef043fe03fb829",
|
||||
Utils.toHexString(block.getNonce()));
|
||||
}
|
||||
|
||||
@Test /* BlocksMessage really big message parsing */
|
||||
|
|
|
@ -14,7 +14,7 @@ import java.util.Arrays;
|
|||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
import static org.ethereum.util.RLP.toInt;
|
||||
import static org.ethereum.util.ByteUtil.byteArrayToInt;
|
||||
import static org.ethereum.util.RlpTestData.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
|
@ -366,7 +366,7 @@ public class RLPTest {
|
|||
assertEquals(expected, asHex(encoderesult));
|
||||
|
||||
byte[] decodeResult = (byte[]) RLP.decode(encoderesult, 0).getDecoded();
|
||||
int result = toInt(decodeResult);
|
||||
int result = byteArrayToInt(decodeResult);
|
||||
assertEquals(test, Integer.valueOf(result));
|
||||
}
|
||||
|
||||
|
@ -378,7 +378,7 @@ public class RLPTest {
|
|||
assertEquals(expected, asHex(encoderesult));
|
||||
|
||||
byte[] decodeResult = (byte[]) RLP.decode(encoderesult, 0).getDecoded();
|
||||
int result = toInt(decodeResult);
|
||||
int result = byteArrayToInt(decodeResult);
|
||||
assertEquals(test, Integer.valueOf(result));
|
||||
}
|
||||
|
||||
|
@ -390,7 +390,7 @@ public class RLPTest {
|
|||
assertEquals(expected, asHex(encoderesult));
|
||||
|
||||
byte[] decodeResult = (byte[]) RLP.decode(encoderesult, 0).getDecoded();
|
||||
int result = toInt(decodeResult);
|
||||
int result = byteArrayToInt(decodeResult);
|
||||
assertEquals(test, Integer.valueOf(result));
|
||||
|
||||
test = new Integer(1024);
|
||||
|
@ -399,7 +399,7 @@ public class RLPTest {
|
|||
assertEquals(expected, asHex(encoderesult));
|
||||
|
||||
decodeResult = (byte[]) RLP.decode(encoderesult, 0).getDecoded();
|
||||
result = toInt(decodeResult);
|
||||
result = byteArrayToInt(decodeResult);
|
||||
assertEquals(test, Integer.valueOf(result));
|
||||
}
|
||||
|
||||
|
@ -474,10 +474,10 @@ public class RLPTest {
|
|||
assertEquals(expected, asHex(encoderesult));
|
||||
|
||||
Object[] decodeResult = (Object[]) RLP.decode(encoderesult, 0).getDecoded();
|
||||
assertEquals(1, toInt( (byte[]) decodeResult[0] ));
|
||||
assertEquals(1, byteArrayToInt( (byte[]) decodeResult[0] ));
|
||||
assertEquals("cat", bytesToAscii( ((byte[]) ((Object[]) decodeResult[1])[0] )));
|
||||
assertEquals("dog", bytesToAscii( (byte[]) decodeResult[2]));
|
||||
assertEquals(2, toInt( ((byte[]) ((Object[]) decodeResult[3])[0] )));
|
||||
assertEquals(2, byteArrayToInt( ((byte[]) ((Object[]) decodeResult[3])[0] )));
|
||||
|
||||
test = new Object[] { new Object[] { "cat", "dog" }, new Object[] { 1, 2 }, new Object[] { } };
|
||||
expected = "cdc88363617483646f67c20102c0";
|
||||
|
@ -487,8 +487,8 @@ public class RLPTest {
|
|||
decodeResult = (Object[]) RLP.decode(encoderesult, 0).getDecoded();
|
||||
assertEquals("cat", bytesToAscii( ((byte[]) ((Object[]) decodeResult[0])[0] )));
|
||||
assertEquals("dog", bytesToAscii( ((byte[]) ((Object[]) decodeResult[0])[1] )));
|
||||
assertEquals(1, toInt( ((byte[]) ((Object[]) decodeResult[1])[0] )));
|
||||
assertEquals(2, toInt( ((byte[]) ((Object[]) decodeResult[1])[1] )));
|
||||
assertEquals(1, byteArrayToInt( ((byte[]) ((Object[]) decodeResult[1])[0] )));
|
||||
assertEquals(2, byteArrayToInt( ((byte[]) ((Object[]) decodeResult[1])[1] )));
|
||||
assertTrue( ( ((Object[]) decodeResult[2]).length == 0 ));
|
||||
}
|
||||
|
||||
|
@ -557,7 +557,7 @@ public class RLPTest {
|
|||
Object[] decodedList;
|
||||
|
||||
decodedByte = (byte[]) RLP.decode(fromHex(result01), pos).getDecoded();
|
||||
assertEquals(test01, toInt(decodedByte));
|
||||
assertEquals(test01, byteArrayToInt(decodedByte));
|
||||
|
||||
decodedData = (byte[]) RLP.decode(fromHex(result02), pos).getDecoded();
|
||||
assertEquals(test02, bytesToAscii(decodedData));
|
||||
|
@ -582,19 +582,19 @@ public class RLPTest {
|
|||
|
||||
// 1
|
||||
decodedData = (byte[]) RLP.decode(fromHex(result08), pos).getDecoded();
|
||||
assertEquals(test08, toInt(decodedData));
|
||||
assertEquals(test08, byteArrayToInt(decodedData));
|
||||
|
||||
// 10
|
||||
decodedData = (byte[]) RLP.decode(fromHex(result09), pos).getDecoded();
|
||||
assertEquals(test09, toInt(decodedData));
|
||||
assertEquals(test09, byteArrayToInt(decodedData));
|
||||
|
||||
// 100
|
||||
decodedData = (byte[]) RLP.decode(fromHex(result10), pos).getDecoded();
|
||||
assertEquals(test10, toInt(decodedData));
|
||||
assertEquals(test10, byteArrayToInt(decodedData));
|
||||
|
||||
// 1000
|
||||
decodedData = (byte[]) RLP.decode(fromHex(result11), pos).getDecoded();
|
||||
assertEquals(test11, toInt(decodedData));
|
||||
assertEquals(test11, byteArrayToInt(decodedData));
|
||||
|
||||
decodedData = (byte[]) RLP.decode(fromHex(result12), pos).getDecoded();
|
||||
assertTrue(test12.compareTo(new BigInteger(decodedData)) == 0);
|
||||
|
@ -678,4 +678,30 @@ public class RLPTest {
|
|||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void performanceDecode() {
|
||||
String blocksRaw = "f8cbf8c7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a02f4399b08efe68945c1cf90ffe85bbe3ce978959da753f9e649f034015b8817da00000000000000000000000000000000000000000000000000000000000000000834000008080830f4240808080a004994f67dc55b09e814ab7ffc8df3686b4afb2bb53e60eae97ef043fe03fb829c0c0";
|
||||
byte[] payload = Hex.decode(blocksRaw);
|
||||
|
||||
final int ITERATIONS = 10000000;
|
||||
RLPList list = null;
|
||||
DecodeResult result = null;
|
||||
|
||||
long start1 = System.currentTimeMillis();
|
||||
for (int i = 0; i < ITERATIONS; i++) {
|
||||
result = RLP.decode(payload, 0);
|
||||
}
|
||||
long end1 = System.currentTimeMillis();
|
||||
|
||||
long start2 = System.currentTimeMillis();
|
||||
for (int i = 0; i < ITERATIONS; i++) {
|
||||
list = RLP.decode2(payload);
|
||||
}
|
||||
long end2 = System.currentTimeMillis();
|
||||
|
||||
System.out.println(list + "" + result);
|
||||
System.out.println("Result RLP.decode(): " + (end1-start1) + "ms");
|
||||
System.out.println("Result RLP.decode2(): " + (end2-start2) + "ms");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue