Fix bug in toInt() and refactor RLPList to extend ArrayList

This commit is contained in:
nicksavers 2014-05-14 14:42:20 +02:00
parent 7eaf9f0dba
commit 260aae5881
16 changed files with 172 additions and 163 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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 {

View File

@ -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;

View File

@ -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 ?
}

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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};

View File

@ -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) };
}
}

View File

@ -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("]");

View File

@ -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

View File

@ -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 */

View File

@ -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");
}
}