diff --git a/ethereumj-core/src/main/java/org/ethereum/crypto/ECKey.java b/ethereumj-core/src/main/java/org/ethereum/crypto/ECKey.java index d42d1bdf..5a8b6f7d 100644 --- a/ethereumj-core/src/main/java/org/ethereum/crypto/ECKey.java +++ b/ethereumj-core/src/main/java/org/ethereum/crypto/ECKey.java @@ -27,7 +27,6 @@ import java.util.Arrays; import javax.annotation.Nullable; -import org.ethereum.util.ByteUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.asn1.sec.SECNamedCurves; @@ -294,9 +293,15 @@ public class ECKey implements Serializable { this.s = s; } - public static ECDSASignature fromComponents(byte[] r, byte[] s) { + private static ECDSASignature fromComponents(byte[] r, byte[] s) { return new ECDSASignature(new BigInteger(r), new BigInteger(s)); } + + public static ECDSASignature fromComponents(byte[] r, byte[] s, byte v) { + ECDSASignature signature = fromComponents(r, s); + signature.v = v; + return signature; + } /** * Will automatically adjust the S component to be less than or equal to half the curve order, if necessary. diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/MainData.java b/ethereumj-core/src/main/java/org/ethereum/manager/MainData.java index d897ad13..fd573583 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/MainData.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/MainData.java @@ -3,9 +3,9 @@ package org.ethereum.manager; import com.maxmind.geoip.Location; import org.ethereum.geodb.IpGeoDB; -import org.ethereum.net.vo.BlockData; +import org.ethereum.net.vo.Block; import org.ethereum.net.vo.PeerData; -import org.ethereum.net.vo.TransactionData; +import org.ethereum.net.vo.Transaction; import java.util.*; @@ -30,6 +30,6 @@ public class MainData { } } - public void addBlocks(List blocks) {} - public void addTransactions(List transactions) {} + public void addBlocks(List blocks) {} + public void addTransactions(List transactions) {} } diff --git a/ethereumj-core/src/main/java/org/ethereum/net/ReasonCode.java b/ethereumj-core/src/main/java/org/ethereum/net/ReasonCode.java new file mode 100644 index 00000000..24f1e34e --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/net/ReasonCode.java @@ -0,0 +1,42 @@ +package org.ethereum.net; + +import java.util.HashMap; +import java.util.Map; + +public enum ReasonCode { + + REASON_DISCONNECT_REQUESTED(0x00), + REASON_TCP_ERROR(0x01), + REASON_BAD_PROTOCOL(0x02), + REASON_USELESS_PEER(0x03), + REASON_TOO_MANY_PEERS(0x04), + REASON_ALREADY_CONNECTED(0x05), + REASON_WRONG_GENESIS(0x06), + REASON_INCOMPATIBLE_PROTOCOL(0x07), + REASON_PEER_QUITING(0x08), + UNKNOWN(0xFF); + + private int reason; + + private static final Map intToTypeMap = new HashMap(); + static { + for (ReasonCode type : ReasonCode.values()) { + intToTypeMap.put(type.reason, type); + } + } + + private ReasonCode(int reason) { + this.reason = reason; + } + + public static ReasonCode fromInt(int i) { + ReasonCode type = intToTypeMap.get(Integer.valueOf(i)); + if (type == null) + return ReasonCode.UNKNOWN; + return type; + } + + public byte asByte() { + return (byte) reason; + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/net/client/EthereumProtocolHandler.java b/ethereumj-core/src/main/java/org/ethereum/net/client/EthereumProtocolHandler.java index 2847f1d9..f8095d90 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/client/EthereumProtocolHandler.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/client/EthereumProtocolHandler.java @@ -1,6 +1,6 @@ package org.ethereum.net.client; -import static org.ethereum.net.Command.BLOCKS; +import static org.ethereum.net.Command.*; import static org.ethereum.net.Command.DISCONNECT; import static org.ethereum.net.Command.GET_CHAIN; import static org.ethereum.net.Command.GET_PEERS; @@ -24,7 +24,6 @@ import java.util.TimerTask; import org.ethereum.gui.PeerListener; import org.ethereum.manager.MainData; import org.ethereum.net.Command; -import org.ethereum.net.RLP; import org.ethereum.net.message.BlocksMessage; import org.ethereum.net.message.DisconnectMessage; import org.ethereum.net.message.GetChainMessage; @@ -34,8 +33,9 @@ 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.net.rlp.RLP; import org.ethereum.net.rlp.RLPList; -import org.ethereum.net.vo.BlockData; +import org.ethereum.net.vo.Block; import org.ethereum.util.Utils; import org.spongycastle.util.encoders.Hex; @@ -55,16 +55,6 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { private long lastPongTime = 0; private boolean tearDown = false; - // hello data - private boolean handShaked = false; - private byte protocolVersion; - private byte networkId; - - private String clientId; - private byte capabilities; - private short peerPort; - private byte[] peerId; - private PeerListener peerListener; public EthereumProtocolHandler() { } @@ -75,7 +65,6 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(final ChannelHandlerContext ctx) { - // TODO: send hello // TODO: send ping schedule another ping // TODO: ByteBuf vs Stream vs new byte ??? @@ -96,12 +85,10 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { long currTime = System.currentTimeMillis(); if (currTime - lastPongTime > 30000){ - System.out.println("No ping answer for [30 sec]"); throw new Error("No ping return for 30 [sec]"); // TODO: shutdown the handler } - System.out.println("[Send: PING]"); if (peerListener != null) peerListener.console("[Send: PING]"); sendPing(ctx); @@ -111,7 +98,6 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { timer.scheduleAtFixedRate(new TimerTask() { public void run() { - System.out.println("[Send: GET_PEERS]"); sendGetPeers(ctx); } @@ -120,7 +106,6 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { timer.scheduleAtFixedRate(new TimerTask() { public void run() { - System.out.println("[Send: GET_TRANSACTIONS]"); sendGetTransactions(ctx); } @@ -129,7 +114,6 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { timer.schedule(new TimerTask() { public void run() { - System.out.println("[Send: GET_CHAIN]"); sendGetChain(ctx); } @@ -156,26 +140,16 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { byte command = RLP.getCommandCode(payload); // got HELLO if (Command.fromInt(command) == HELLO) { - System.out.println("[Recv: HELLO]" ); RLPList rlpList = new RLPList(); RLP.parseObjects(payload, rlpList); HelloMessage helloMessage = new HelloMessage(rlpList); - this.protocolVersion = helloMessage.getProtocolVersion(); - this.networkId = helloMessage.getNetworkId(); - this.clientId = helloMessage.getClientId(); - this.capabilities = helloMessage.getCapabilities(); - this.peerPort = helloMessage.getPeerPort(); - this.peerId = helloMessage.getPeerId(); - System.out.println(helloMessage.toString()); if (peerListener != null) peerListener.console(helloMessage.toString()); } - // got DISCONNECT if (Command.fromInt(command) == DISCONNECT) { - System.out.println("[Recv: DISCONNECT]"); if (peerListener != null) peerListener.console("[Recv: DISCONNECT]"); @@ -186,21 +160,18 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { System.out.println(disconnectMessage); if (peerListener != null) peerListener.console(disconnectMessage.toString()); } - // got PING send pong if (Command.fromInt(command) == PING) { System.out.println("[Recv: PING]"); if (peerListener != null) peerListener.console("[Recv: PING]"); sendPong(ctx); } - // got PONG mark it if (Command.fromInt(command) == PONG) { System.out.println("[Recv: PONG]" ); if (peerListener != null) peerListener.console("[Recv: PONG]"); this.lastPongTime = System.currentTimeMillis(); } - // got GETPEERS send peers if (Command.fromInt(command) == GET_PEERS) { System.out.println("[Recv: GETPEERS]" ); @@ -223,10 +194,8 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { buffer.writeBytes(answerBytes); ctx.writeAndFlush(buffer); } - // got PEERS if (Command.fromInt(command) == PEERS) { - System.out.println("[Recv: PEERS]"); if (peerListener != null) peerListener.console("[Recv: PEERS]"); @@ -239,10 +208,8 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { System.out.println(peersMessage); if (peerListener != null) peerListener.console(peersMessage.toString()); } - // got TRANSACTIONS if (Command.fromInt(command) == TRANSACTIONS) { - System.out.println("Recv: TRANSACTIONS]"); if (peerListener != null) peerListener.console("Recv: TRANSACTIONS]"); @@ -254,9 +221,7 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { // todo: if you got transactions send it to your peers System.out.println(transactionsMessage); if (peerListener != null) peerListener.console(transactionsMessage.toString()); - } - // got BLOCKS if (Command.fromInt(command) == BLOCKS) { System.out.println("[Recv: BLOCKS]"); @@ -266,13 +231,12 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { RLP.parseObjects(payload, rlpList); BlocksMessage blocksMessage = new BlocksMessage(rlpList); - List blockList = blocksMessage.getBlockDataList(); + List blockList = blocksMessage.getBlockDataList(); MainData.instance.addBlocks(blockList); System.out.println(blocksMessage); if (peerListener != null) peerListener.console(blocksMessage.toString()); } - // got GETCHAIN if (Command.fromInt(command) == GET_CHAIN) { System.out.println("[Recv: GET_CHAIN]"); @@ -285,7 +249,6 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { System.out.println(getChainMessage); if (peerListener != null) peerListener.console(getChainMessage.toString()); } - // got NOTINCHAIN if (Command.fromInt(command) == NOT_IN_CHAIN) { System.out.println("[Recv: NOT_IN_CHAIN]"); @@ -298,15 +261,12 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { System.out.println(notInChainMessage); if (peerListener != null) peerListener.console(notInChainMessage.toString()); } - // got GETTRANSACTIONS if (Command.fromInt(command) == GET_TRANSACTIONS) { System.out.println("[Recv: GET_TRANSACTIONS]"); if (peerListener != null) peerListener.console("[Recv: GET_TRANSACTIONS]"); - // todo: send the queue of the transactions } - } @Override @@ -337,7 +297,6 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { ctx.writeAndFlush(buffer); } - private void sendPing(ChannelHandlerContext ctx){ ByteBuf buffer = ctx.alloc().buffer(StaticMessages.PING.length); buffer.writeBytes(StaticMessages.PING); diff --git a/ethereumj-core/src/main/java/org/ethereum/net/message/BlocksMessage.java b/ethereumj-core/src/main/java/org/ethereum/net/message/BlocksMessage.java index 33cd3a4d..eaa48756 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/message/BlocksMessage.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/message/BlocksMessage.java @@ -8,8 +8,8 @@ import static org.ethereum.net.Command.BLOCKS; import org.ethereum.net.Command; import org.ethereum.net.rlp.RLPItem; import org.ethereum.net.rlp.RLPList; -import org.ethereum.net.vo.BlockData; -import org.ethereum.net.vo.TransactionData; +import org.ethereum.net.vo.Block; +import org.ethereum.net.vo.Transaction; /** * www.ethereumJ.com @@ -18,7 +18,7 @@ import org.ethereum.net.vo.TransactionData; */ public class BlocksMessage extends Message { - private List blockDataList = new ArrayList(); + private List blockDataList = new ArrayList(); public BlocksMessage(RLPList rawData) { super(rawData); @@ -34,7 +34,7 @@ public class BlocksMessage extends Message { for (int i = 1; i < paramsList.size(); ++i){ RLPList rlpData = ((RLPList)paramsList.getElement(i)); - BlockData blockData = new BlockData(rlpData); + Block blockData = new Block(rlpData); this.blockDataList.add(blockData); } parsed = true; @@ -45,7 +45,7 @@ public class BlocksMessage extends Message { return null; } - public List getBlockDataList() { + public List getBlockDataList() { if (!parsed) parseRLP(); return blockDataList; } @@ -53,11 +53,11 @@ public class BlocksMessage extends Message { public String toString() { StringBuffer sb = new StringBuffer(); - for (BlockData blockData : this.getBlockDataList()){ + for (Block blockData : this.getBlockDataList()){ sb.append(" ").append( blockData.toString() ).append("\n"); - List transactions = blockData.getTransactionsList(); - for (TransactionData transactionData : transactions){ + List transactions = blockData.getTransactionsList(); + for (Transaction transactionData : transactions){ sb.append("[").append(transactionData).append("]\n"); } } diff --git a/ethereumj-core/src/main/java/org/ethereum/net/message/HelloMessage.java b/ethereumj-core/src/main/java/org/ethereum/net/message/HelloMessage.java index ef026bfc..713dc72a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/message/HelloMessage.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/message/HelloMessage.java @@ -1,8 +1,10 @@ package org.ethereum.net.message; import org.spongycastle.util.encoders.Hex; + import static org.ethereum.net.Command.HELLO; -import org.ethereum.net.RLP; + +import org.ethereum.net.rlp.RLP; import org.ethereum.net.rlp.RLPItem; import org.ethereum.net.rlp.RLPList; diff --git a/ethereumj-core/src/main/java/org/ethereum/net/message/TransactionsMessage.java b/ethereumj-core/src/main/java/org/ethereum/net/message/TransactionsMessage.java index 1e1cd6c6..cb991896 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/message/TransactionsMessage.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/message/TransactionsMessage.java @@ -4,7 +4,7 @@ import static org.ethereum.net.Command.TRANSACTIONS; import org.ethereum.net.Command; import org.ethereum.net.rlp.RLPItem; import org.ethereum.net.rlp.RLPList; -import org.ethereum.net.vo.TransactionData; +import org.ethereum.net.vo.Transaction; import java.util.ArrayList; import java.util.List; @@ -16,7 +16,7 @@ import java.util.List; */ public class TransactionsMessage extends Message { - private List transactions = new ArrayList(); + private List transactions = new ArrayList(); public TransactionsMessage() { } @@ -33,17 +33,17 @@ public class TransactionsMessage extends Message { throw new Error("TransactionMessage: parsing for mal data"); } - transactions = new ArrayList(); + transactions = new ArrayList(); int size = paramsList.getList().size(); for (int i = 1; i < size; ++i){ RLPList rlpTxData = (RLPList) paramsList.getElement(i); - TransactionData tx = new TransactionData(rlpTxData); + Transaction tx = new Transaction(rlpTxData); transactions.add(tx); } parsed = true; } - public List getTransactions() { + public List getTransactions() { if (!parsed) parseRLP(); return transactions; } @@ -56,7 +56,7 @@ public class TransactionsMessage extends Message { public String toString(){ if(!parsed) parseRLP(); StringBuffer sb = new StringBuffer(); - for (TransactionData transactionData : transactions){ + for (Transaction transactionData : transactions){ sb.append(" ").append(transactionData).append("\n"); } return "Transactions Message [\n" + sb.toString() + " ]"; diff --git a/ethereumj-core/src/main/java/org/ethereum/net/RLP.java b/ethereumj-core/src/main/java/org/ethereum/net/rlp/RLP.java similarity index 99% rename from ethereumj-core/src/main/java/org/ethereum/net/RLP.java rename to ethereumj-core/src/main/java/org/ethereum/net/rlp/RLP.java index bec70ebe..9a9e9db8 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/RLP.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/rlp/RLP.java @@ -1,4 +1,4 @@ -package org.ethereum.net; +package org.ethereum.net.rlp; import java.io.UnsupportedEncodingException; import java.math.BigInteger; @@ -8,9 +8,6 @@ import java.util.Arrays; import java.util.List; import java.util.Queue; -import org.ethereum.net.rlp.RLPItem; -import org.ethereum.net.rlp.RLPList; - public class RLP { public static byte decodeOneByteItem(byte[] data, int index) { diff --git a/ethereumj-core/src/main/java/org/ethereum/net/vo/BlockData.java b/ethereumj-core/src/main/java/org/ethereum/net/vo/Block.java similarity index 85% rename from ethereumj-core/src/main/java/org/ethereum/net/vo/BlockData.java rename to ethereumj-core/src/main/java/org/ethereum/net/vo/Block.java index a91ad7e6..8dbbf558 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/vo/BlockData.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/vo/Block.java @@ -7,7 +7,6 @@ import org.ethereum.net.rlp.RLPList; import org.ethereum.util.Utils; import java.math.BigInteger; -import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; @@ -16,10 +15,10 @@ import java.util.List; * User: Roman Mandeleil * Created on: 13/04/14 19:34 */ -public class BlockData { +public class Block { - RLPList rawData; - boolean parsed = false; + private RLPList rawData; + private boolean parsed = false; private byte[] hash; private byte[] parentHash; @@ -33,15 +32,15 @@ public class BlockData { private byte[] extraData; private byte[] nonce; - List transactionsList = new ArrayList(); - List uncleList = new ArrayList(); + private List transactionsList = new ArrayList(); + private List uncleList = new ArrayList(); - public BlockData(RLPList rawData) { + public Block(RLPList rawData) { this.rawData = rawData; this.parsed = false; } - public BlockData(byte[] parentHash, byte[] unclesHash, byte[] coinbase, byte[] stateHash, byte[] txListHash, byte[] difficulty, long timestamp, byte[] extraData, byte[] nonce, List transactionsList, List uncleList) { + public Block(byte[] parentHash, byte[] unclesHash, byte[] coinbase, byte[] stateHash, byte[] txListHash, byte[] difficulty, long timestamp, byte[] extraData, byte[] nonce, List transactionsList, List uncleList) { this.parentHash = parentHash; this.unclesHash = unclesHash; this.coinbase = coinbase; @@ -54,11 +53,10 @@ public class BlockData { this.transactionsList = transactionsList; this.uncleList = uncleList; this.parsed = true; - } // [parent_hash, uncles_hash, coinbase, state_root, tx_list_hash, difficulty, timestamp, extradata, nonce] - private void parseRLP(){ + private void parseRLP() { this.hash = HashUtil.sha3(rawData.getRLPData()); @@ -76,29 +74,24 @@ public class BlockData { this.extraData = ((RLPItem) params.get(7)).getData(); this.nonce = ((RLPItem) params.get(8)).getData(); - // parse transactions List transactions = ((RLPList) rawData.getElement(1)).getList(); for (RLPElement rlpTx : transactions){ - - TransactionData tx = new TransactionData((RLPList)rlpTx); + Transaction tx = new Transaction((RLPList)rlpTx); this.transactionsList.add(tx); } // parse uncles List uncleBlocks = ((RLPList) rawData.getElement(2)).getList(); for (RLPElement rawUncle : uncleBlocks){ - - BlockData blockData = new BlockData((RLPList)rawUncle); + Block blockData = new Block((RLPList)rawUncle); this.uncleList.add(blockData); } - this.parsed = true; } public byte[] getHash(){ - if (!parsed) parseRLP(); return hash; } @@ -148,12 +141,12 @@ public class BlockData { return nonce; } - public List getTransactionsList() { + public List getTransactionsList() { if (!parsed) parseRLP(); return transactionsList; } - public List getUncleList() { + public List getUncleList() { if (!parsed) parseRLP(); return uncleList; } diff --git a/ethereumj-core/src/main/java/org/ethereum/net/vo/PeerData.java b/ethereumj-core/src/main/java/org/ethereum/net/vo/PeerData.java index d98a81ca..0ba50f85 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/vo/PeerData.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/vo/PeerData.java @@ -77,7 +77,6 @@ public class PeerData { this.lastCheckTime = lastCheckTime; } - @Override public String toString() { return "Peer: [ ip=" + getInetAddress()+ ", port=" + getPort() + ", peerId=" + Hex.toHexString( getPeerId() ) + "]"; diff --git a/ethereumj-core/src/main/java/org/ethereum/net/vo/Transaction.java b/ethereumj-core/src/main/java/org/ethereum/net/vo/Transaction.java new file mode 100644 index 00000000..20d6899d --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/net/vo/Transaction.java @@ -0,0 +1,161 @@ +package org.ethereum.net.vo; + +import org.ethereum.crypto.ECKey.ECDSASignature; +import org.ethereum.crypto.ECKey; +import org.ethereum.crypto.HashUtil; +import org.ethereum.net.rlp.RLPItem; +import org.ethereum.net.rlp.RLPList; +import org.ethereum.util.Utils; + +/** + * www.ethereumJ.com + * User: Roman Mandeleil + * Created on: 21/04/14 09:19 + */ +public class Transaction { + + private RLPList rawData; + private boolean parsed = false; + +// creation contract tx or simple send tx +// [ nonce, value, receiveAddress, gasPrice, gasDeposit, data, signatureV, signatureR, signatureS ] +// or +// [ nonce, endowment, 0, gasPrice, gasDeposit (for init), body, init, signatureV, signatureR, signatureS ] + + private byte[] hash; + private byte[] nonce; + private byte[] value; + + // In creation transaction the receive address is - 0 + private byte[] receiveAddress; + private byte[] gasPrice; + private byte[] gas; + + // Contract creation [data] will hold the contract + // for other transaction [data] can hold data + private byte[] data; + private byte[] init; + + // Signature + private ECDSASignature signature; + + public Transaction(RLPList rawData) { + this.rawData = rawData; + parsed = false; + } + + public Transaction(byte[] nonce, byte[] value, byte[] recieveAddress, byte[] gasPrice, byte[] gas, byte[] data, byte v, byte[] r, byte[] s) { + this.nonce = nonce; + this.value = value; + this.receiveAddress = recieveAddress; + this.gasPrice = gasPrice; + this.gas = gas; + this.data = data; + this.signature = ECDSASignature.fromComponents(r, s, v); + parsed = true; + } + + 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.gas = ((RLPItem) rawData.getElement(4)).getData(); + this.data = ((RLPItem) rawData.getElement(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(); + 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.signature = ECDSASignature.fromComponents(r, s, v); + } else + throw new Error("Wrong tx data element list size"); + + this.parsed = true; + } + + + public RLPList getRawData() { + return rawData; + } + + public boolean isParsed() { + return parsed; + } + + public byte[] getHash() { + if (!parsed) rlpParse(); + return hash; + } + + public byte[] getNonce() { + if (!parsed) rlpParse(); + return nonce; + } + + public byte[] getValue() { + if (!parsed) rlpParse(); + return value; + } + + public byte[] getReceiveAddress() { + if (!parsed) rlpParse(); + return receiveAddress; + } + + public byte[] getGasPrice() { + if (!parsed) rlpParse(); + return gasPrice; + } + + public byte[] getGas() { + if (!parsed) rlpParse(); + return gas; + } + + public byte[] getData() { + if (!parsed) rlpParse(); + return data; + } + + public byte[] getInit() { + if (!parsed) rlpParse(); + return init; + } + + public ECDSASignature getSignature() { + if (!parsed) rlpParse(); + return signature; + } + + public boolean isContract() { + return this.receiveAddress.length == 0; + } + + @Override + public String toString() { + if (!parsed) rlpParse(); + return "TransactionData [" + " hash=" + Utils.toHexString(hash) + + " nonce=" + Utils.toHexString(nonce) + + ", value=" + Utils.toHexString(value) + + ", receiveAddress=" + Utils.toHexString(receiveAddress) + + ", gasPrice=" + Utils.toHexString(gasPrice) + + ", gas=" + Utils.toHexString(gas) + + ", data=" + Utils.toHexString(data) + + ", init=" + Utils.toHexString(init) + + ", signatureV=" + signature.v + + ", signatureR=" + Utils.toHexString(signature.r.toByteArray()) + + ", signatureS=" + Utils.toHexString(signature.s.toByteArray()) + + ']'; + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/net/vo/TransactionData.java b/ethereumj-core/src/main/java/org/ethereum/net/vo/TransactionData.java deleted file mode 100644 index e910f884..00000000 --- a/ethereumj-core/src/main/java/org/ethereum/net/vo/TransactionData.java +++ /dev/null @@ -1,188 +0,0 @@ -package org.ethereum.net.vo; - -import org.ethereum.crypto.HashUtil; -import org.ethereum.net.rlp.RLPItem; -import org.ethereum.net.rlp.RLPList; -import org.ethereum.util.Utils; - -/** - * www.ethereumJ.com - * User: Roman Mandeleil - * Created on: 21/04/14 09:19 - */ -public class TransactionData { - - RLPList rawData; - boolean parsed = false; - - -// creation contract tx or simple send tx -// [ nonce, value, receiveAddress, gasPrice, gasDeposit, data, signatureV, signatureR, signatureS ] -// or -// [ nonce, endowment, 0, gasPrice, gasDeposit (for init), body, init, signatureV, signatureR, signatureS ] - - byte[] hash; - byte[] nonce; - byte[] value; - - // In creation transaction the receive address is - 0 - byte[] receiveAddress; - byte[] gasPrice; - byte[] gas; - - // Contract creation [data] will hold the contract - // for other transaction [data] can hold data - byte[] data; - byte[] init; - - - // Signature - byte signatureV; - byte[] signatureR; - byte[] signatureS; - - - public TransactionData(RLPList rawData) { - this.rawData = rawData; - parsed = false; - } - - public TransactionData(byte[] nonce, byte[] value, byte[] recieveAddress, byte[] gasPrice, byte[] gas, byte[] data, byte signatureV, byte[] signatureR, byte[] signatureS) { - this.nonce = nonce; - this.value = value; - this.receiveAddress = recieveAddress; - this.gasPrice = gasPrice; - this.gas = gas; - this.data = data; - this.signatureV = signatureV; - this.signatureR = signatureR; - this.signatureS = signatureS; - parsed = true; - } - - - public void rlpParse(){ - - if (rawData.size() == 9){ // Simple transaction - - 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.gas = ((RLPItem) rawData.getElement(4)).getData(); - this.data = ((RLPItem) rawData.getElement(5)).getData(); - this.signatureV = ((RLPItem) rawData.getElement(6)).getData()[0]; - this.signatureR = ((RLPItem) rawData.getElement(7)).getData(); - this.signatureS = ((RLPItem) rawData.getElement(8)).getData(); - - } else if (rawData.size() == 10){ // Contract creation transaction - - 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.gas = ((RLPItem) rawData.getElement(4)).getData(); - this.data = ((RLPItem) rawData.getElement(5)).getData(); - this.init = ((RLPItem) rawData.getElement(6)).getData(); - this.signatureV = ((RLPItem) rawData.getElement(7)).getData()[0]; - this.signatureR = ((RLPItem) rawData.getElement(8)).getData(); - this.signatureS = ((RLPItem) rawData.getElement(9)).getData(); - - } else throw new Error("Wrong tx data element list size"); - - this.parsed = true; - } - - - public RLPList getRawData() { - return rawData; - } - - public boolean isParsed() { - return parsed; - } - - public byte[] getHash() { - if (!parsed) rlpParse(); - return hash; - } - - public byte[] getNonce() { - - if (!parsed) rlpParse(); - return nonce; - } - - public byte[] getValue() { - - if (!parsed) rlpParse(); - return value; - } - - public byte[] getReceiveAddress() { - - if (!parsed) rlpParse(); - return receiveAddress; - } - - public byte[] getGasPrice() { - - if (!parsed) rlpParse(); - return gasPrice; - } - - public byte[] getGas() { - - if (!parsed) rlpParse(); - return gas; - } - - public byte[] getData() { - - if (!parsed) rlpParse(); - return data; - } - - public byte[] getInit() { - - if (!parsed) rlpParse(); - return init; - } - - public byte getSignatureV() { - - if (!parsed) rlpParse(); - return signatureV; - } - - public byte[] getSignatureR() { - - if (!parsed) rlpParse(); - return signatureR; - } - - public byte[] getSignatureS() { - - if (!parsed) rlpParse(); - return signatureS; - } - - @Override - public String toString() { - if (!parsed) rlpParse(); - return "TransactionData [" + " hash=" + Utils.toHexString(hash) + - " nonce=" + Utils.toHexString(nonce) + - ", value=" + Utils.toHexString(value) + - ", receiveAddress=" + Utils.toHexString(receiveAddress) + - ", gasPrice=" + Utils.toHexString(gasPrice) + - ", gas=" + Utils.toHexString(gas) + - ", data=" + Utils.toHexString(data) + - ", init=" + Utils.toHexString(init) + - ", signatureV=" + signatureV + - ", signatureR=" + Utils.toHexString(signatureR) + - ", signatureS=" + Utils.toHexString(signatureS) + - ']'; - } -} diff --git a/ethereumj-core/src/test/java/org/ethereum/block/BlockTest.java b/ethereumj-core/src/test/java/org/ethereum/block/BlockTest.java index 8ab86f09..e08c5fb6 100644 --- a/ethereumj-core/src/test/java/org/ethereum/block/BlockTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/block/BlockTest.java @@ -2,9 +2,9 @@ package org.ethereum.block; import org.spongycastle.util.encoders.Hex; import org.ethereum.crypto.HashUtil; -import org.ethereum.net.RLP; +import org.ethereum.net.rlp.RLP; import org.ethereum.net.rlp.RLPList; -import org.ethereum.net.vo.BlockData; +import org.ethereum.net.vo.Block; import org.junit.Test; import java.io.IOException; @@ -131,7 +131,7 @@ public class BlockTest { RLPList rlpList = new RLPList(); RLP.parseObjects(payload, rlpList); - BlockData blockData = new BlockData(rlpList); + Block blockData = new Block(rlpList); RLPList.recursivePrint(rlpList); } } diff --git a/ethereumj-core/src/test/java/org/ethereum/crypto/ECKeyTest.java b/ethereumj-core/src/test/java/org/ethereum/crypto/ECKeyTest.java index 70f8f660..a978f25a 100644 --- a/ethereumj-core/src/test/java/org/ethereum/crypto/ECKeyTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/crypto/ECKeyTest.java @@ -117,8 +117,7 @@ public class ECKeyTest { ECKey key = ECKey.fromPublicOnly(pubKey); BigInteger r = new BigInteger("28157690258821599598544026901946453245423343069728565040002908283498585537001"); BigInteger s = new BigInteger("30212485197630673222315826773656074299979444367665131281281249560925428307087"); - ECDSASignature sig = ECDSASignature.fromComponents(r.toByteArray(), s.toByteArray()); - sig.v = 28; + ECDSASignature sig = ECDSASignature.fromComponents(r.toByteArray(), s.toByteArray(), (byte) 28); key.verify(HashUtil.sha3(exampleMessage.getBytes()), sig); } @@ -126,8 +125,7 @@ public class ECKeyTest { public void testVerifySignature2() { BigInteger r = new BigInteger("c52c114d4f5a3ba904a9b3036e5e118fe0dbb987fe3955da20f2cd8f6c21ab9c", 16); BigInteger s = new BigInteger("6ba4c2874299a55ad947dbc98a25ee895aabf6b625c26c435e84bfd70edf2f69", 16); - ECDSASignature sig = ECDSASignature.fromComponents(r.toByteArray(), s.toByteArray()); - sig.v = 0x1b; + ECDSASignature sig = ECDSASignature.fromComponents(r.toByteArray(), s.toByteArray(), (byte) 0x1b); byte[] rawtx = Hex.decode("f82804881bc16d674ec8000094cd2a3d9f938e13cd947ec05abc7fe734df8dd8268609184e72a0006480"); try { ECKey key = ECKey.signatureToKey(HashUtil.sha3(rawtx), sig.toBase64()); diff --git a/ethereumj-core/src/test/java/org/ethereum/net/MessagesTest.java b/ethereumj-core/src/test/java/org/ethereum/net/MessagesTest.java index 42ea4b5b..9dbf20ac 100644 --- a/ethereumj-core/src/test/java/org/ethereum/net/MessagesTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/net/MessagesTest.java @@ -12,10 +12,11 @@ import org.ethereum.net.message.HelloMessage; import org.ethereum.net.message.NotInChainMessage; import org.ethereum.net.message.PeersMessage; import org.ethereum.net.message.TransactionsMessage; +import org.ethereum.net.rlp.RLP; import org.ethereum.net.rlp.RLPList; -import org.ethereum.net.vo.BlockData; +import org.ethereum.net.vo.Block; import org.ethereum.net.vo.PeerData; -import org.ethereum.net.vo.TransactionData; +import org.ethereum.net.vo.Transaction; import org.ethereum.util.Utils; import org.junit.Test; import org.spongycastle.util.encoders.Hex; @@ -91,7 +92,7 @@ public class MessagesTest { System.out.println(disconnectMessage); assertEquals(disconnectMessage.getReason(), - DisconnectMessage.REASON_DISCONNECT_REQUESTED); + DisconnectMessage.REASON_DISCONNECT_REQUESTED); } @Test /* DisconnectMessage 2 */ @@ -106,10 +107,9 @@ public class MessagesTest { System.out.println(disconnectMessage); assertEquals(disconnectMessage.getReason(), - DisconnectMessage.REASON_TCP_ERROR); + DisconnectMessage.REASON_TCP_ERROR); } - /* PEERS */ @Test /* PeersMessage 1*/ @@ -131,7 +131,6 @@ public class MessagesTest { assertEquals(30303, peerData.getPort()); assertEquals("82A8A5831D3B4FB76CF130CDC8A2B162A85D005D82A1DCC9B73239035EADE6347EDE2FFC86571ABE348EA38699CE886AA3D425FE58182C433434AB4CFD7B5B88", Utils.toHexString( peerData.getPeerId() ).toUpperCase()); - } @Test /* PeersMessage 2 */ @@ -160,7 +159,6 @@ public class MessagesTest { assertEquals(30303, peerData.getPort()); assertEquals("F6155F1A60143B7D9D5D1A440D7D52FE6809F69E0C6F1E0024457E0D71DD88ADE3B13AAA940C89AC0610952B48BD832C42E343A13E61FFDB06010CFFC345E053", Utils.toHexString( peerData.getPeerId() ).toUpperCase()); - } @Test /* Peers msg parsing performance*/ @@ -199,7 +197,7 @@ public class MessagesTest { assertEquals(1, transactionsMessage.getTransactions().size()); - TransactionData tx = + Transaction tx = transactionsMessage.getTransactions().get(0); assertEquals("558A3797E0DD3FBFAF761F1ADD6749C7D5DB313FDAC5CBA59F40E28AF7BBACD1", @@ -227,16 +225,15 @@ public class MessagesTest { Utils.toHexString( tx.getInit() ).toUpperCase()); assertEquals("1B", - Utils.toHexString( new byte[] {tx.getSignatureV()} ).toUpperCase()); + Utils.toHexString( new byte[] {tx.getSignature().v} ).toUpperCase()); assertEquals("5E3868194605F1647593B842725818CCFA6A38651A728715133A8E97CDCFAC54", - Utils.toHexString( tx.getSignatureR() ).toUpperCase()); + Utils.toHexString( tx.getSignature().r.toByteArray() ).toUpperCase()); assertEquals("0FF91628D04B215EBCCFD5F4FC34CC1B45DF32F6B4609FBB0DE42E8522264467", - Utils.toHexString( tx.getSignatureS() ).toUpperCase()); + Utils.toHexString( tx.getSignature().s.toByteArray() ).toUpperCase()); } - @Test /* Transactions message 2 */ public void test_9(){ @@ -251,7 +248,7 @@ public class MessagesTest { assertEquals(3, transactionsMessage.getTransactions().size()); - TransactionData tx = + Transaction tx = transactionsMessage.getTransactions().get(0); assertEquals("4B7D9670A92BF120D5B43400543B69304A14D767CF836A7F6ABFF4EDDE092895", @@ -279,14 +276,13 @@ public class MessagesTest { Utils.toHexString( tx.getInit() ).toUpperCase()); assertEquals("1C", - Utils.toHexString( new byte[] {tx.getSignatureV()} ).toUpperCase()); + Utils.toHexString( new byte[] {tx.getSignature().v} ).toUpperCase()); assertEquals("7F6EB94576346488C6253197BDE6A7E59DDC36F2773672C849402AA9C402C3C4", - Utils.toHexString( tx.getSignatureR() ).toUpperCase()); + Utils.toHexString( tx.getSignature().r.toByteArray() ).toUpperCase()); assertEquals("6D254E662BF7450DD8D835160CBB053463FED0B53F2CDD7F3EA8731919C8E8CC", - Utils.toHexString( tx.getSignatureS() ).toUpperCase()); - + Utils.toHexString( tx.getSignature().s.toByteArray() ).toUpperCase()); tx = transactionsMessage.getTransactions().get(2); @@ -315,17 +311,16 @@ public class MessagesTest { Utils.toHexString( tx.getInit() ).toUpperCase()); assertEquals("1B", - Utils.toHexString( new byte[] {tx.getSignatureV()} ).toUpperCase()); + Utils.toHexString( new byte[] {tx.getSignature().v} ).toUpperCase()); assertEquals("D05887574456C6DE8F7A0D172342C2CBDD4CF7AFE15D9DBB8B75B748BA6791C9", - Utils.toHexString( tx.getSignatureR() ).toUpperCase()); + Utils.toHexString( tx.getSignature().r.toByteArray() ).toUpperCase()); assertEquals("1E87172A861F6C37B5A9E3A5D0D7393152A7FBE41530E5BB8AC8F35433E5931B", - Utils.toHexString(tx.getSignatureS()).toUpperCase()); + Utils.toHexString( tx.getSignature().s.toByteArray() ).toUpperCase()); } - /* BLOCKS */ @Test /* BlocksMessage parsing 1*/ @@ -339,12 +334,12 @@ public class MessagesTest { RLP.parseObjects(payload, rlpList); BlocksMessage blocksMessage = new BlocksMessage(rlpList); - List list = blocksMessage.getBlockDataList(); + List list = blocksMessage.getBlockDataList(); System.out.println(blocksMessage); assertEquals(1, list.size()); - BlockData block = list.get(0); + Block block = list.get(0); assertEquals("36A24B56C6104E5A5C0E70B0553F1A4D6109D065D718D7443A6A475EC8C83905", Utils.toHexString(block.getHash()).toUpperCase()); @@ -373,7 +368,6 @@ public class MessagesTest { Utils.toHexString(block.getNonce()).toUpperCase()); } - @Test /* BlocksMessage really big message parsing */ public void test11(){ @@ -384,13 +378,12 @@ public class MessagesTest { RLP.parseObjects(payload, rlpList); BlocksMessage blocksMessage = new BlocksMessage(rlpList); - List list = blocksMessage.getBlockDataList(); + List list = blocksMessage.getBlockDataList(); System.out.println(blocksMessage); - assertEquals(32, list.size()); - BlockData block = list.get(31); + Block block = list.get(31); assertEquals("518916DFB79C390BD7BFF75712174512C2F96BEC42A3F573355507AD1588CE0C", Utils.toHexString(block.getHash()).toUpperCase()); @@ -419,11 +412,8 @@ public class MessagesTest { Utils.toHexString(block.getNonce()).toUpperCase()); System.out.println(blocksMessage); - } - - /* GET_CHAIN */ @Test /* GET_CHAIN message parsing*/ @@ -449,12 +439,8 @@ public class MessagesTest { assertEquals("03AF21F3939C29C231200B1F790F16421A8923254CBF2A90455B9B8F28BE4562", Utils.toHexString( getChainMessage.getBlockHashList().get(25) ).toUpperCase()); - - - } - /* NOT_IN_CHAIN */ @Test /* NotInChainMessage parsing 1 */ @@ -472,7 +458,5 @@ public class MessagesTest { assertEquals("E5E441F0877116011CCDECE2501A50B40C40418377037E16D0282B2B5E347138", Utils.toHexString(notInChainMessage.getHash()).toUpperCase()); } - - } diff --git a/ethereumj-core/src/test/java/org/ethereum/net/RLPTest.java b/ethereumj-core/src/test/java/org/ethereum/net/RLPTest.java index 1e48f6fa..8b67814d 100644 --- a/ethereumj-core/src/test/java/org/ethereum/net/RLPTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/net/RLPTest.java @@ -2,6 +2,7 @@ package org.ethereum.net; import org.spongycastle.util.encoders.Hex; import org.ethereum.crypto.HashUtil; +import org.ethereum.net.rlp.RLP; import org.ethereum.net.rlp.RLPList; import org.ethereum.util.Utils; import org.junit.Test;