Transactions, RLP, and more cool stuff...
This commit is contained in:
parent
4c1d3e79eb
commit
cf82f9b459
|
@ -7,6 +7,12 @@
|
||||||
<version>0.1-SNAPSHOT</version>
|
<version>0.1-SNAPSHOT</version>
|
||||||
<name>EthereumJ</name>
|
<name>EthereumJ</name>
|
||||||
<url>http://www.ethereumj.org</url>
|
<url>http://www.ethereumj.org</url>
|
||||||
|
|
||||||
|
<!-- * To deploy all the classes and dependencies to one jar,
|
||||||
|
* that's one option to pack stand alone.
|
||||||
|
mvn clean package dependency:copy-dependencies
|
||||||
|
-->
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<!-- Third-party dependencies -->
|
<!-- Third-party dependencies -->
|
||||||
|
@ -114,6 +120,20 @@
|
||||||
<target>1.7</target>
|
<target>1.7</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<mainClass>org.ethereum.gui.ToolBar</mainClass>
|
||||||
|
</manifest>
|
||||||
|
</archive>
|
||||||
|
<descriptorRefs>
|
||||||
|
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||||
|
</descriptorRefs>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
|
@ -1,7 +1,6 @@
|
||||||
package org.ethereum.core;
|
package org.ethereum.core;
|
||||||
|
|
||||||
import org.ethereum.crypto.ECKey;
|
import org.ethereum.crypto.ECKey;
|
||||||
import org.ethereum.crypto.HashUtil;
|
|
||||||
import org.ethereum.util.Utils;
|
import org.ethereum.util.Utils;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
|
@ -16,34 +15,34 @@ import java.util.Arrays;
|
||||||
public class Address {
|
public class Address {
|
||||||
|
|
||||||
byte[] privKey;
|
byte[] privKey;
|
||||||
byte[] pubKey;
|
byte[] address;
|
||||||
|
|
||||||
public Address(){
|
public Address(){
|
||||||
privKey = new BigInteger(130, Utils.getRandom()).toString(32).getBytes();
|
privKey = new BigInteger(130, Utils.getRandom()).toString(32).getBytes();
|
||||||
this.pubKey = ECKey.fromPrivate(privKey).getAddress();
|
this.address = ECKey.fromPrivate(privKey).getAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Address(byte[] privKey) {
|
public Address(byte[] privKey) {
|
||||||
this.privKey = privKey;
|
this.privKey = privKey;
|
||||||
this.pubKey = ECKey.fromPrivate(privKey).getAddress();
|
this.address = ECKey.fromPrivate(privKey).getAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Address(byte[] privKey, byte[] pubKey) {
|
public Address(byte[] privKey, byte[] address) {
|
||||||
this.privKey = privKey;
|
this.privKey = privKey;
|
||||||
this.pubKey = pubKey;
|
this.address = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getPrivKey() {
|
public byte[] getPrivKey() {
|
||||||
return privKey;
|
return privKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getPubKey() {
|
public byte[] getAddress() {
|
||||||
return pubKey;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return Hex.toHexString(pubKey);
|
return Hex.toHexString(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -53,13 +52,13 @@ public class Address {
|
||||||
|
|
||||||
Address address = (Address) o;
|
Address address = (Address) o;
|
||||||
|
|
||||||
if (!Arrays.equals(pubKey, address.pubKey)) return false;
|
if (!Arrays.equals(this.address, address.address)) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Arrays.hashCode(pubKey);
|
return Arrays.hashCode(address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import org.ethereum.util.RLP;
|
||||||
import org.ethereum.util.RLPItem;
|
import org.ethereum.util.RLPItem;
|
||||||
import org.ethereum.util.RLPList;
|
import org.ethereum.util.RLPList;
|
||||||
import org.ethereum.util.Utils;
|
import org.ethereum.util.Utils;
|
||||||
|
import org.spongycastle.util.BigIntegers;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
import edu.emory.mathcs.backport.java.util.Arrays;
|
import edu.emory.mathcs.backport.java.util.Arrays;
|
||||||
|
@ -24,6 +25,8 @@ import edu.emory.mathcs.backport.java.util.Arrays;
|
||||||
public class Transaction {
|
public class Transaction {
|
||||||
|
|
||||||
private byte[] rlpEncoded;
|
private byte[] rlpEncoded;
|
||||||
|
private byte[] unsignedRLPEncoded;
|
||||||
|
|
||||||
private boolean parsed = false;
|
private boolean parsed = false;
|
||||||
|
|
||||||
/* creation contract tx
|
/* creation contract tx
|
||||||
|
@ -129,8 +132,11 @@ public class Transaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getHash() {
|
public byte[] getHash() {
|
||||||
|
|
||||||
if (!parsed) rlpParse();
|
if (!parsed) rlpParse();
|
||||||
return HashUtil.sha3(this.getEncoded(false));
|
byte[] plainMsg = this.getRlpUnsigned();
|
||||||
|
|
||||||
|
return HashUtil.sha3(plainMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getNonce() {
|
public byte[] getNonce() {
|
||||||
|
@ -218,71 +224,77 @@ public class Transaction {
|
||||||
", signatureS=" + Utils.toHexString(signature.s.toByteArray()) +
|
", signatureS=" + Utils.toHexString(signature.s.toByteArray()) +
|
||||||
']';
|
']';
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getEncoded(boolean signed) {
|
|
||||||
if(rlpEncoded == null) {
|
|
||||||
|
|
||||||
// TODO: Alternative clean way to encode, using RLP.encode() after it's optimized
|
/**
|
||||||
// return new Object[] { nonce, value, receiveAddress, gasPrice,
|
* For signature games you have to keep also
|
||||||
// gasLimit, data, init, signature };
|
* rlp of the transaction without any signature data
|
||||||
|
*/
|
||||||
|
public byte[] getRlpUnsigned(){
|
||||||
|
|
||||||
/* Temporary order for an RLP encoded transaction in cpp client */
|
if (unsignedRLPEncoded != null) return unsignedRLPEncoded;
|
||||||
byte[] nonce = RLP.encodeElement(this.nonce);
|
|
||||||
byte[] gasPrice = RLP.encodeElement(this.gasPrice);
|
|
||||||
byte[] gasLimit = RLP.encodeElement(this.gasLimit);
|
|
||||||
byte[] receiveAddress = RLP.encodeElement(this.receiveAddress);
|
|
||||||
byte[] value = RLP.encodeElement(this.value);
|
|
||||||
byte[] data = RLP.encodeElement(this.data);
|
|
||||||
|
|
||||||
byte[] v = null;
|
byte[] nonce = RLP.encodeElement(this.nonce);
|
||||||
byte[] r = null;
|
byte[] gasPrice = RLP.encodeElement(this.gasPrice);
|
||||||
byte[] s = null;
|
byte[] gasLimit = RLP.encodeElement(this.gasLimit);
|
||||||
|
byte[] receiveAddress = RLP.encodeElement(this.receiveAddress);
|
||||||
|
byte[] value = RLP.encodeElement(this.value);
|
||||||
|
byte[] data = RLP.encodeElement(this.data);
|
||||||
|
|
||||||
if(signed && signature != null) {
|
if(Arrays.equals(this.receiveAddress, new byte[0])) {
|
||||||
// byte[] signature = RLP.encodeElement(this.signature);
|
byte[] init = RLP.encodeElement(this.init);
|
||||||
|
this.unsignedRLPEncoded = RLP.encodeList(nonce, gasPrice, gasLimit, value, receiveAddress,
|
||||||
|
data, init);
|
||||||
|
} else {
|
||||||
|
this.unsignedRLPEncoded = RLP.encodeList(nonce, gasPrice, gasLimit, value, receiveAddress,
|
||||||
|
data);
|
||||||
|
}
|
||||||
|
|
||||||
v = RLP.encodeByte( signature.v );
|
return unsignedRLPEncoded;
|
||||||
r = RLP.encodeElement(signature.r.toByteArray());
|
}
|
||||||
s = RLP.encodeElement(signature.s.toByteArray());
|
|
||||||
|
|
||||||
if(Arrays.equals(this.receiveAddress, new byte[0])) {
|
public byte[] getEncoded() {
|
||||||
byte[] init = RLP.encodeElement(this.init);
|
|
||||||
this.rlpEncoded = RLP.encodeList(nonce, gasPrice, gasLimit, value, receiveAddress,
|
|
||||||
data, init, v, r, s);
|
|
||||||
} else {
|
|
||||||
this.rlpEncoded = RLP.encodeList(nonce, gasPrice, gasLimit, value, receiveAddress,
|
|
||||||
data, v, r, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
if(rlpEncoded != null) return rlpEncoded;
|
||||||
|
|
||||||
byte[] result;
|
/* Temporary order for an RLP encoded transaction in cpp client */
|
||||||
|
byte[] nonce = RLP.encodeElement(this.nonce);
|
||||||
|
byte[] gasPrice = RLP.encodeElement(this.gasPrice);
|
||||||
|
byte[] gasLimit = RLP.encodeElement(this.gasLimit);
|
||||||
|
byte[] receiveAddress = RLP.encodeElement(this.receiveAddress);
|
||||||
|
byte[] value = RLP.encodeElement(this.value);
|
||||||
|
byte[] data = RLP.encodeElement(this.data);
|
||||||
|
|
||||||
if(Arrays.equals(this.receiveAddress, new byte[0])) {
|
byte[] v = null;
|
||||||
byte[] init = RLP.encodeElement(this.init);
|
byte[] r = null;
|
||||||
result = RLP.encodeList(nonce, gasPrice, gasLimit, value, receiveAddress,
|
byte[] s = null;
|
||||||
data, init);
|
|
||||||
} else {
|
|
||||||
result = RLP.encodeList(nonce, gasPrice, gasLimit, value, receiveAddress,
|
|
||||||
data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Order of the Yellow Paper / eth-go & pyethereum clients
|
v = RLP.encodeByte( signature.v );
|
||||||
byte[] nonce = RLP.encodeElement(this.nonce);
|
r = RLP.encodeElement(BigIntegers.asUnsignedByteArray(signature.r));
|
||||||
byte[] value = RLP.encodeElement(this.value);
|
s = RLP.encodeElement(BigIntegers.asUnsignedByteArray(signature.s));
|
||||||
byte[] receiveAddress = RLP.encodeElement(this.receiveAddress);
|
|
||||||
byte[] gasPrice = RLP.encodeElement(this.gasPrice);
|
if(Arrays.equals(this.receiveAddress, new byte[0])) {
|
||||||
byte[] gasLimit = RLP.encodeElement(this.gasLimit);
|
byte[] init = RLP.encodeElement(this.init);
|
||||||
byte[] data = RLP.encodeElement(this.data);
|
this.rlpEncoded = RLP.encodeList(nonce, gasPrice, gasLimit, value, receiveAddress,
|
||||||
byte[] init = RLP.encodeElement(this.init);
|
data, init, v, r, s);
|
||||||
*/
|
} else {
|
||||||
|
this.rlpEncoded = RLP.encodeList(nonce, gasPrice, gasLimit, value, receiveAddress,
|
||||||
|
data, v, r, s);
|
||||||
}
|
}
|
||||||
return rlpEncoded;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Order of the Yellow Paper / eth-go & pyethereum clients
|
||||||
|
byte[] nonce = RLP.encodeElement(this.nonce);
|
||||||
|
byte[] value = RLP.encodeElement(this.value);
|
||||||
|
byte[] receiveAddress = RLP.encodeElement(this.receiveAddress);
|
||||||
|
byte[] gasPrice = RLP.encodeElement(this.gasPrice);
|
||||||
|
byte[] gasLimit = RLP.encodeElement(this.gasLimit);
|
||||||
|
byte[] data = RLP.encodeElement(this.data);
|
||||||
|
byte[] init = RLP.encodeElement(this.init);
|
||||||
|
*/
|
||||||
|
|
||||||
|
return rlpEncoded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
import javax.xml.transform.Transformer;
|
import javax.xml.transform.Transformer;
|
||||||
import javax.xml.transform.TransformerConfigurationException;
|
|
||||||
import javax.xml.transform.TransformerException;
|
import javax.xml.transform.TransformerException;
|
||||||
import javax.xml.transform.TransformerFactory;
|
import javax.xml.transform.TransformerFactory;
|
||||||
import javax.xml.transform.dom.DOMSource;
|
import javax.xml.transform.dom.DOMSource;
|
||||||
|
@ -197,7 +196,7 @@ public class Wallet {
|
||||||
raw.setAttributeNode(id);
|
raw.setAttributeNode(id);
|
||||||
|
|
||||||
Element addressE = doc.createElement("address");
|
Element addressE = doc.createElement("address");
|
||||||
addressE.setTextContent(Hex.toHexString(address.getPubKey()));
|
addressE.setTextContent(Hex.toHexString(address.getAddress()));
|
||||||
|
|
||||||
Attr nonce = doc.createAttribute("nonce");
|
Attr nonce = doc.createAttribute("nonce");
|
||||||
nonce.setValue("0");
|
nonce.setValue("0");
|
||||||
|
|
|
@ -69,11 +69,11 @@ public class ConnectionConsoleWindow extends JFrame implements PeerListener{
|
||||||
Thread t = new Thread() {
|
Thread t = new Thread() {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
// new ClientPeer(thisConsole).connect("82.217.72.169", 30303);
|
// new ClientPeer(thisConsole).connect("54.201.28.117", 30303); // peer discovery
|
||||||
// new ClientPeer(thisConsole).connect("54.201.28.117", 30303);
|
|
||||||
// new ClientPeer(thisConsole).connect("82.217.72.169", 30303); // Nick
|
// new ClientPeer(thisConsole).connect("82.217.72.169", 30303); // Nick
|
||||||
|
|
||||||
new ClientPeer(thisConsole).connect("54.204.10.41", 30303);
|
// new ClientPeer(thisConsole).connect("54.204.10.41", 30303);
|
||||||
|
new ClientPeer(thisConsole).connect("54.211.14.10", 30303);
|
||||||
// new ClientPeer(thisConsole).connect("192.168.1.102", 30303);
|
// new ClientPeer(thisConsole).connect("192.168.1.102", 30303);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,18 +5,14 @@ import org.ethereum.core.Transaction;
|
||||||
import org.ethereum.crypto.HashUtil;
|
import org.ethereum.crypto.HashUtil;
|
||||||
import org.ethereum.manager.MainData;
|
import org.ethereum.manager.MainData;
|
||||||
import org.ethereum.net.client.ClientPeer;
|
import org.ethereum.net.client.ClientPeer;
|
||||||
import org.ethereum.net.message.TransactionsMessage;
|
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.KeyEvent;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.text.DefaultEditorKit;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* www.ethereumJ.com
|
* www.ethereumJ.com
|
||||||
|
@ -75,7 +71,7 @@ class PayOutDialog extends JDialog {
|
||||||
byte[] gas = Hex.decode("4255");
|
byte[] gas = Hex.decode("4255");
|
||||||
|
|
||||||
Transaction tx = new Transaction(null, value.toByteArray(),
|
Transaction tx = new Transaction(null, value.toByteArray(),
|
||||||
receiveAddress.getPubKey(), gasPrice, gas, null);
|
receiveAddress.getAddress(), gasPrice, gas, null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
tx.sign(senderPrivKey);
|
tx.sign(senderPrivKey);
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class WalletAddressPanel extends JPanel{
|
||||||
addressField.setBorder(border);
|
addressField.setBorder(border);
|
||||||
addressField.setEnabled(true);
|
addressField.setEnabled(true);
|
||||||
addressField.setEditable(false);
|
addressField.setEditable(false);
|
||||||
addressField.setText(Hex.toHexString(address.getPubKey()).toUpperCase());
|
addressField.setText(Hex.toHexString(address.getAddress()).toUpperCase());
|
||||||
addressField.setForeground(new Color(143, 170, 220));
|
addressField.setForeground(new Color(143, 170, 220));
|
||||||
addressField.setFont(new Font("Monospaced", 0, 12));
|
addressField.setFont(new Font("Monospaced", 0, 12));
|
||||||
addressField.setPreferredSize(new Dimension(300, 35));
|
addressField.setPreferredSize(new Dimension(300, 35));
|
||||||
|
|
|
@ -57,8 +57,7 @@ public class MainData {
|
||||||
// if it is the first block to add
|
// if it is the first block to add
|
||||||
// check that the parent is the genesis
|
// check that the parent is the genesis
|
||||||
if (blockChainDB.isEmpty() &&
|
if (blockChainDB.isEmpty() &&
|
||||||
!"69a7356a245f9dc5b865475ada5ee4e89b18f93c06503a9db3b3630e88e9fb4e".
|
!Arrays.equals(StaticMessages.GENESSIS_HASH, firstBlockToAdd.getParentHash())){
|
||||||
equals(Hex.toHexString(firstBlockToAdd.getParentHash()))){
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,7 @@ public class ClientPeer {
|
||||||
*/
|
*/
|
||||||
public void sendTransaction(Transaction transaction){
|
public void sendTransaction(Transaction transaction){
|
||||||
|
|
||||||
transaction.getEncoded(true);
|
transaction.getEncoded();
|
||||||
java.util.List<Transaction> txList = new ArrayList<Transaction>();
|
java.util.List<Transaction> txList = new ArrayList<Transaction>();
|
||||||
txList.add(transaction);
|
txList.add(transaction);
|
||||||
TransactionsMessage transactionsMessage = new TransactionsMessage(txList);
|
TransactionsMessage transactionsMessage = new TransactionsMessage(txList);
|
||||||
|
|
|
@ -50,14 +50,14 @@ public class StaticMessages {
|
||||||
|
|
||||||
public static final byte[] GET_CHAIN = Hex.decode("2240089100000027F82514A069A7356A245F9DC5B865475ADA5EE4E89B18F93C06503A9DB3B3630E88E9FB4E820100");
|
public static final byte[] GET_CHAIN = Hex.decode("2240089100000027F82514A069A7356A245F9DC5B865475ADA5EE4E89B18F93C06503A9DB3B3630E88E9FB4E820100");
|
||||||
|
|
||||||
public static final byte[] GENESSIS_HASH = Hex.decode("69a7356a245f9dc5b865475ada5ee4e89b18f93c06503a9db3b3630e88e9fb4e");
|
public static final byte[] GENESSIS_HASH = Hex.decode("f5232afe32aba6b366f8aa86a6939437c5e13d1fd71a0f51e77735d3456eb1a6");
|
||||||
public static final byte[] MAGIC_PACKET = Hex.decode("22400891");
|
public static final byte[] MAGIC_PACKET = Hex.decode("22400891");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
|
||||||
byte[] peerIdBytes = HashUtil.randomPeerId();
|
byte[] peerIdBytes = HashUtil.randomPeerId();
|
||||||
|
|
||||||
HELLO_MESSAGE = new HelloMessage((byte)0x0F, (byte)0x00, "EthereumJ [v0.0.1] pure java [by Roman Mandeleil]",
|
HELLO_MESSAGE = new HelloMessage((byte)0x10, (byte)0x00, "EthereumJ [v0.5.1] pure java by RomanJ",
|
||||||
(byte)0b00000111, (short)30303, peerIdBytes);
|
(byte)0b00000111, (short)30303, peerIdBytes);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class TransactionsMessage extends Message {
|
||||||
|
|
||||||
for (Transaction tx : transactionList){
|
for (Transaction tx : transactionList){
|
||||||
|
|
||||||
byte[] txPayload = tx.getEncoded(true);
|
byte[] txPayload = tx.getEncoded();
|
||||||
try {
|
try {
|
||||||
baos.write(txPayload);
|
baos.write(txPayload);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -43,7 +43,7 @@ public class TransactionsMessage extends Message {
|
||||||
byte[][] elements = new byte[transactionList.size() + 1][];
|
byte[][] elements = new byte[transactionList.size() + 1][];
|
||||||
elements[0] = new byte[]{Command.TRANSACTIONS.asByte()};
|
elements[0] = new byte[]{Command.TRANSACTIONS.asByte()};
|
||||||
for (int i = 0; i < transactionList.size(); ++i){
|
for (int i = 0; i < transactionList.size(); ++i){
|
||||||
elements[i + 1] = transactionList.get(i).getEncoded(true);
|
elements[i + 1] = transactionList.get(i).getEncoded();
|
||||||
}
|
}
|
||||||
|
|
||||||
payload = RLP.encodeList(elements);
|
payload = RLP.encodeList(elements);
|
||||||
|
|
|
@ -98,7 +98,7 @@ public class RLP {
|
||||||
* followed by the concatenation of the RLP encodings of the items. The
|
* followed by the concatenation of the RLP encodings of the items. The
|
||||||
* range of the first byte is thus [0xf8, 0xff].
|
* range of the first byte is thus [0xf8, 0xff].
|
||||||
*/
|
*/
|
||||||
private static int OFFSET_LONG_LIST = 0xf8;
|
private static int OFFSET_LONG_LIST = 0xf7;
|
||||||
|
|
||||||
|
|
||||||
/* ******************************************************
|
/* ******************************************************
|
||||||
|
|
|
@ -31,7 +31,7 @@ public class TransactionTest {
|
||||||
assertEquals("c2604bd6eeca76afce4e7775d87960e3d4ed3b69235a3f94d6f1497c9831b50c", tx.getSignature().r);
|
assertEquals("c2604bd6eeca76afce4e7775d87960e3d4ed3b69235a3f94d6f1497c9831b50c", tx.getSignature().r);
|
||||||
assertEquals("664124a6b323350dd57a650434dc6bf8ddf37cd1a2686fee377e512aa12f1214", tx.getSignature().s);
|
assertEquals("664124a6b323350dd57a650434dc6bf8ddf37cd1a2686fee377e512aa12f1214", tx.getSignature().s);
|
||||||
|
|
||||||
assertEquals(RLP_ENCODED_TX2, Hex.toHexString(tx.getEncoded(false)));
|
assertEquals(RLP_ENCODED_TX2, Hex.toHexString(tx.getEncoded()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -55,7 +55,7 @@ public class TransactionTest {
|
||||||
byte[] data = Hex.decode("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001");
|
byte[] data = Hex.decode("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001");
|
||||||
|
|
||||||
Transaction tx = new Transaction(nonce, value, recieveAddress, gasPrice, gas, data);
|
Transaction tx = new Transaction(nonce, value, recieveAddress, gasPrice, gas, data);
|
||||||
byte[] encoded = tx.getEncoded(false);
|
byte[] encoded = tx.getEncoded();
|
||||||
String test = Hex.toHexString(encoded);
|
String test = Hex.toHexString(encoded);
|
||||||
|
|
||||||
System.out.println(RLP_ENCODED_TX2);
|
System.out.println(RLP_ENCODED_TX2);
|
||||||
|
|
|
@ -7,7 +7,6 @@ import java.net.UnknownHostException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import junit.framework.Assert;
|
|
||||||
import org.ethereum.core.Address;
|
import org.ethereum.core.Address;
|
||||||
import org.ethereum.core.Block;
|
import org.ethereum.core.Block;
|
||||||
import org.ethereum.core.Transaction;
|
import org.ethereum.core.Transaction;
|
||||||
|
@ -536,10 +535,10 @@ public class MessagesTest {
|
||||||
byte[] gas = Hex.decode("4255");
|
byte[] gas = Hex.decode("4255");
|
||||||
|
|
||||||
Transaction tx = new Transaction(null, value.toByteArray(),
|
Transaction tx = new Transaction(null, value.toByteArray(),
|
||||||
receiveAddress.getPubKey(), gasPrice, gas, null);
|
receiveAddress.getAddress(), gasPrice, gas, null);
|
||||||
|
|
||||||
tx.sign(privKey);
|
tx.sign(privKey);
|
||||||
tx.getEncoded(true);
|
tx.getEncoded();
|
||||||
|
|
||||||
List<Transaction> txList = new ArrayList<Transaction>();
|
List<Transaction> txList = new ArrayList<Transaction>();
|
||||||
txList.add(tx);
|
txList.add(tx);
|
||||||
|
|
|
@ -5,13 +5,14 @@ import java.math.BigInteger;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.NoSuchProviderException;
|
import java.security.NoSuchProviderException;
|
||||||
import java.security.SignatureException;
|
|
||||||
|
|
||||||
import org.ethereum.core.Address;
|
import org.ethereum.core.Address;
|
||||||
import org.ethereum.core.Transaction;
|
import org.ethereum.core.Transaction;
|
||||||
import org.ethereum.crypto.ECKey;
|
import org.ethereum.crypto.ECKey;
|
||||||
import org.ethereum.crypto.HashUtil;
|
import org.ethereum.crypto.HashUtil;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.spongycastle.util.BigIntegers;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
public class TransactionTest {
|
public class TransactionTest {
|
||||||
|
@ -53,16 +54,28 @@ public class TransactionTest {
|
||||||
byte[] gas = Hex.decode("4255");
|
byte[] gas = Hex.decode("4255");
|
||||||
|
|
||||||
Transaction tx = new Transaction(null, value.toByteArray(),
|
Transaction tx = new Transaction(null, value.toByteArray(),
|
||||||
receiveAddress.getPubKey(), gasPrice, gas, null);
|
receiveAddress.getAddress(), gasPrice, gas, null);
|
||||||
|
|
||||||
tx.sign(senderPrivKey);
|
tx.sign(senderPrivKey);
|
||||||
|
|
||||||
System.out.println(tx.toString());
|
|
||||||
|
|
||||||
ECKey key = ECKey.signatureToKey(HashUtil.sha3(tx.getEncoded(true)), tx.getSignature().toBase64());
|
|
||||||
|
System.out.println("r: " + Hex.toHexString(tx.getSignature().r.toByteArray()));
|
||||||
|
System.out.println("s: " + Hex.toHexString(tx.getSignature().s.toByteArray()));
|
||||||
|
|
||||||
|
System.out.println(Hex.toHexString( tx.getEncoded() ));
|
||||||
|
|
||||||
|
// retrieve the signer/sender of the transaction
|
||||||
|
ECKey key = ECKey.signatureToKey(tx.getHash(), tx.getSignature().toBase64());
|
||||||
|
|
||||||
|
System.out.println("Tx unsigned RLP: " + Hex.toHexString( tx.getRlpUnsigned() ));
|
||||||
|
System.out.println("Tx signed RLP: " + Hex.toHexString( tx.getEncoded() ));
|
||||||
|
|
||||||
System.out.println("Signature public key\t: " + Hex.toHexString(key.getPubKey()));
|
System.out.println("Signature public key\t: " + Hex.toHexString(key.getPubKey()));
|
||||||
System.out.println("Sender is\t\t: " + Hex.toHexString(key.getAddress()));
|
System.out.println("Sender is\t\t: " + Hex.toHexString(key.getAddress()));
|
||||||
|
|
||||||
|
Assert.assertEquals("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826",
|
||||||
|
Hex.toHexString(key.getAddress()).toUpperCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,10 +91,10 @@ public class TransactionTest {
|
||||||
byte[] gas = Hex.decode("4255");
|
byte[] gas = Hex.decode("4255");
|
||||||
|
|
||||||
Transaction tx = new Transaction(null, value.toByteArray(),
|
Transaction tx = new Transaction(null, value.toByteArray(),
|
||||||
receiveAddress.getPubKey(), gasPrice, gas, null);
|
receiveAddress.getAddress(), gasPrice, gas, null);
|
||||||
|
|
||||||
tx.sign(privKey);
|
tx.sign(privKey);
|
||||||
byte[] payload = tx.getEncoded(true);
|
byte[] payload = tx.getEncoded();
|
||||||
|
|
||||||
System.out.println(Hex.toHexString( payload ));
|
System.out.println(Hex.toHexString( payload ));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue