Fix Transaction RLP encoding

This commit is contained in:
nicksavers 2014-05-20 23:43:35 +02:00
parent c1bc0ffafd
commit 91db5c8b22
8 changed files with 158 additions and 164 deletions

View File

@ -65,24 +65,24 @@ public class Transaction {
private ECDSASignature signature; private ECDSASignature signature;
/* Tx in encoded form */ /* Tx in encoded form */
private byte[] rlpEncodedSigned;
private byte[] rlpEncoded; private byte[] rlpEncoded;
private byte[] unsignedRLPEncoded;
/* Indicates if this transaction has been parsed /* Indicates if this transaction has been parsed
* from the rlp-encoded data */ * from the rlp-encoded data */
private boolean parsed = false; private boolean parsed = false;
public Transaction(byte[] rawData) { public Transaction(byte[] rawData) {
this.rlpEncoded = rawData; this.rlpEncodedSigned = rawData;
parsed = false; parsed = false;
} }
public Transaction(byte[] nonce, byte[] value, byte[] recieveAddress, byte[] gasPrice, byte[] gas, byte[] data) { public Transaction(byte[] nonce, byte[] gasPrice, byte[] gas, byte[] recieveAddress, byte[] value, byte[] data) {
this.nonce = nonce; this.nonce = nonce;
this.value = value;
this.receiveAddress = recieveAddress;
this.gasPrice = gasPrice; this.gasPrice = gasPrice;
this.gasLimit = gas; this.gasLimit = gas;
if(recieveAddress == null) { this.receiveAddress = recieveAddress;
this.value = value;
if(recieveAddress == null || receiveAddress.length == 0) {
this.init = data; this.init = data;
} else { } else {
this.data = data; this.data = data;
@ -92,10 +92,10 @@ public class Transaction {
public void rlpParse(){ public void rlpParse(){
RLPList decodedTxList = RLP.decode2(rlpEncoded); RLPList decodedTxList = RLP.decode2(rlpEncodedSigned);
RLPList transaction = (RLPList) decodedTxList.get(0); RLPList transaction = (RLPList) decodedTxList.get(0);
this.hash = HashUtil.sha3(rlpEncoded); this.hash = HashUtil.sha3(rlpEncodedSigned);
this.nonce = ((RLPItem) transaction.get(0)).getRLPData(); this.nonce = ((RLPItem) transaction.get(0)).getRLPData();
this.gasPrice = ((RLPItem) transaction.get(1)).getRLPData(); this.gasPrice = ((RLPItem) transaction.get(1)).getRLPData();
@ -126,7 +126,7 @@ public class Transaction {
public byte[] getHash() { public byte[] getHash() {
if (!parsed) rlpParse(); if (!parsed) rlpParse();
byte[] plainMsg = this.getRlpUnsigned(); byte[] plainMsg = this.getEncoded();
return HashUtil.sha3(plainMsg); return HashUtil.sha3(plainMsg);
} }
@ -221,9 +221,9 @@ public class Transaction {
* For signature games you have to keep also * For signature games you have to keep also
* rlp of the transaction without any signature data * rlp of the transaction without any signature data
*/ */
public byte[] getRlpUnsigned(){ public byte[] getEncoded(){
if (unsignedRLPEncoded != null) return unsignedRLPEncoded; if (rlpEncoded != null) return rlpEncoded;
byte[] nonce = RLP.encodeElement(this.nonce); byte[] nonce = RLP.encodeElement(this.nonce);
byte[] gasPrice = RLP.encodeElement(this.gasPrice); byte[] gasPrice = RLP.encodeElement(this.gasPrice);
@ -234,19 +234,19 @@ public class Transaction {
if(Arrays.equals(this.receiveAddress, new byte[0])) { if(Arrays.equals(this.receiveAddress, new byte[0])) {
byte[] init = RLP.encodeElement(this.init); byte[] init = RLP.encodeElement(this.init);
this.unsignedRLPEncoded = RLP.encodeList(nonce, gasPrice, gasLimit, value, receiveAddress, this.rlpEncoded = RLP.encodeList(nonce, gasPrice, gasLimit, receiveAddress, value,
data, init); data, init);
} else { } else {
this.unsignedRLPEncoded = RLP.encodeList(nonce, gasPrice, gasLimit, value, receiveAddress, this.rlpEncoded = RLP.encodeList(nonce, gasPrice, gasLimit, receiveAddress, value,
data); data);
} }
return unsignedRLPEncoded; return rlpEncoded;
} }
public byte[] getEncoded() { public byte[] getEncodedSigned() {
if(rlpEncoded != null) return rlpEncoded; if(rlpEncodedSigned != null) return rlpEncodedSigned;
byte[] nonce = RLP.encodeElement(this.nonce); byte[] nonce = RLP.encodeElement(this.nonce);
byte[] gasPrice = RLP.encodeElement(this.gasPrice); byte[] gasPrice = RLP.encodeElement(this.gasPrice);
@ -255,18 +255,18 @@ public class Transaction {
byte[] value = RLP.encodeElement(this.value); byte[] value = RLP.encodeElement(this.value);
byte[] data = RLP.encodeElement(this.data); byte[] data = RLP.encodeElement(this.data);
byte[] v = RLP.encodeByte( signature.v ); byte[] v = RLP.encodeByte( signature.v );
byte[] r = RLP.encodeElement(BigIntegers.asUnsignedByteArray(signature.r)); byte[] r = RLP.encodeElement(BigIntegers.asUnsignedByteArray(signature.r));
byte[] s = RLP.encodeElement(BigIntegers.asUnsignedByteArray(signature.s)); byte[] s = RLP.encodeElement(BigIntegers.asUnsignedByteArray(signature.s));
if(Arrays.equals(this.receiveAddress, new byte[0])) { if(Arrays.equals(this.receiveAddress, new byte[0])) {
byte[] init = RLP.encodeElement(this.init); byte[] init = RLP.encodeElement(this.init);
this.rlpEncoded = RLP.encodeList(nonce, gasPrice, gasLimit, value, receiveAddress, this.rlpEncodedSigned = RLP.encodeList(nonce, gasPrice, gasLimit, receiveAddress, value,
data, init, v, r, s); data, init, v, r, s);
} else { } else {
this.rlpEncoded = RLP.encodeList(nonce, gasPrice, gasLimit, value, receiveAddress, this.rlpEncodedSigned = RLP.encodeList(nonce, gasPrice, gasLimit, receiveAddress, value,
data, v, r, s); data, v, r, s);
} }
return rlpEncoded; return rlpEncodedSigned;
} }
} }

View File

@ -95,7 +95,7 @@ public class ClientPeer {
*/ */
public void sendTransaction(Transaction transaction){ public void sendTransaction(Transaction transaction){
transaction.getEncoded(); transaction.getEncodedSigned();
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);

View File

@ -32,7 +32,7 @@ public class TransactionsMessage extends Message {
for (Transaction tx : transactionList){ for (Transaction tx : transactionList){
byte[] txPayload = tx.getEncoded(); byte[] txPayload = tx.getEncodedSigned();
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(); elements[i + 1] = transactionList.get(i).getEncodedSigned();
} }
payload = RLP.encodeList(elements); payload = RLP.encodeList(elements);

View File

@ -17,6 +17,17 @@ import org.spongycastle.util.encoders.Hex;
public class Utils { public class Utils {
private static SecureRandom random = new SecureRandom(); private static SecureRandom random = new SecureRandom();
public static byte[] asUnsignedByteArray(BigInteger bigInteger) {
byte[] array = bigInteger.toByteArray();
if (array[0] == 0) {
byte[] tmp = new byte[array.length - 1];
System.arraycopy(array, 1, tmp, 0, tmp.length);
array = tmp;
}
return array;
}
public static byte[] hexStringToByteArr(String hexString){ public static byte[] hexStringToByteArr(String hexString){

View File

@ -2,68 +2,157 @@ package org.ethereum.core;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import org.ethereum.crypto.ECKey;
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 {
private static String RLP_ENCODED_TX = "f88b8085e8d4a510008227109413978aee95f38490e9769c39b2773ed763d9cd5f872386f26fc10000a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4701ca00502e84be138ca397e49f96e8c82e5a99afc09e0ea4582cc109ea221eeb479efa078f18d645b39ec44778c12ffc4b0"; private static String RLP_ENCODED_TX = "e88085e8d4a510008227109413978aee95f38490e9769c39b2773ed763d9cd5f872386f26fc1000080";
private static String RLP_ENCODED_TX2 = "f8ccf8a6808609184e72a0008227109491a10664d0cd489085a7a018beb5245d4f2272f180b840000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011ca0c2604bd6eeca76afce4e7775d87960e3d4ed3b69235a3f94d6f1497c9831b50ca0664124a6b323350dd57a650434dc6bf8ddf37cd1a2686fee377e512aa12f1214a0c84f20b2df6abd635babd7af64cd76756cd4e39c0ccb87eaaaad609f21d1fe51820334";
private static String HASH_RAW_TX = ""; private static String HASH_RAW_TX = "";
private static String HASH_SIGNED_TX = ""; private static String HASH_SIGNED_TX = "";
@Test /* sign transaction https://tools.ietf.org/html/rfc6979 */
public void test1() throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException, IOException {
//python taken exact data
String txRLPRawData = "a9e880872386f26fc1000085e8d4a510008203e89413978aee95f38490e9769c39b2773ed763d9cd5f80";
// String txRLPRawData = "f82804881bc16d674ec8000094cd2a3d9f938e13cd947ec05abc7fe734df8dd8268609184e72a0006480";
byte[] cowPrivKey = Hex.decode("c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4");
ECKey key = ECKey.fromPrivate(cowPrivKey);
byte[] data = Hex.decode(txRLPRawData);
// step 1: serialize + RLP encode
// step 2: hash = sha3(step1)
byte[] txHash = HashUtil.sha3(data);
String signature = key.doSign(txHash).toBase64();
System.out.println(signature);
}
@Test /* achieve public key of the sender */
public void test2() throws Exception {
// cat --> 79B08AD8787060333663D19704909EE7B1903E58
// cow --> CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826
BigInteger value = new BigInteger("1000000000000000000000000");
byte[] privKey = HashUtil.sha3("cat".getBytes());
Address receiveAddress = new Address(privKey);
byte[] senderPrivKey = HashUtil.sha3("cow".getBytes());
byte[] gasPrice= Hex.decode("09184e72a000");
byte[] gas = Hex.decode("4255");
Transaction tx = new Transaction(null, value.toByteArray(),
receiveAddress.getAddress(), gasPrice, gas, null);
tx.sign(senderPrivKey);
System.out.println("v\t\t\t: " + Hex.toHexString(new byte[] { tx.getSignature().v }));
System.out.println("r\t\t\t: " + Hex.toHexString(BigIntegers.asUnsignedByteArray(tx.getSignature().r)));
System.out.println("s\t\t\t: " + Hex.toHexString(BigIntegers.asUnsignedByteArray(tx.getSignature().s)));
System.out.println("RLP encoded tx\t\t: " + Hex.toHexString( tx.getEncodedSigned() ));
// retrieve the signer/sender of the transaction
ECKey key = ECKey.signatureToKey(tx.getHash(), tx.getSignature().toBase64());
System.out.println("Tx unsigned RLP\t\t: " + Hex.toHexString( tx.getEncoded()));
System.out.println("Tx signed RLP\t\t: " + Hex.toHexString( tx.getEncodedSigned() ));
System.out.println("Signature public key\t: " + Hex.toHexString(key.getPubKey()));
System.out.println("Sender is\t\t: " + Hex.toHexString(key.getAddress()));
Assert.assertEquals("cd2a3d9f938e13cd947ec05abc7fe734df8dd826",
Hex.toHexString(key.getAddress()));
}
@Test /* encode transaction */
public void test3() throws Exception {
BigInteger value = new BigInteger("1000000000000000000000000");
byte[] privKey = HashUtil.sha3("cat".getBytes());
Address receiveAddress = new Address(privKey);
byte[] gasPrice= Hex.decode("09184e72a000");
byte[] gas = Hex.decode("4255");
Transaction tx = new Transaction(null, value.toByteArray(),
receiveAddress.getAddress(), gasPrice, gas, null);
tx.sign(privKey);
byte[] payload = tx.getEncodedSigned();
System.out.println(Hex.toHexString( payload ));
}
@Test @Test
public void testTransactionFromRLP() { public void testTransactionFromRLP() {
// from RLP encoding // from RLP encoding
byte[] encodedTxBytes = Hex.decode(RLP_ENCODED_TX2); byte[] encodedTxBytes = Hex.decode(RLP_ENCODED_TX);
Transaction tx = new Transaction(encodedTxBytes); Transaction tx = new Transaction(encodedTxBytes);
assertNull(Hex.toHexString(tx.getNonce())); assertNull(Hex.toHexString(tx.getNonce()));
assertNull(Hex.toHexString(tx.getValue())); assertNull(Hex.toHexString(tx.getValue()));
assertEquals(RLP_ENCODED_TX2, Hex.toHexString(tx.getReceiveAddress())); assertEquals(RLP_ENCODED_TX, Hex.toHexString(tx.getReceiveAddress()));
assertEquals(RLP_ENCODED_TX2, Hex.toHexString(tx.getGasPrice())); assertEquals(RLP_ENCODED_TX, Hex.toHexString(tx.getGasPrice()));
assertEquals(RLP_ENCODED_TX2, Hex.toHexString(tx.getGasLimit())); assertEquals(RLP_ENCODED_TX, Hex.toHexString(tx.getGasLimit()));
assertEquals(RLP_ENCODED_TX2, Hex.toHexString(tx.getData())); assertEquals(RLP_ENCODED_TX, Hex.toHexString(tx.getData()));
assertEquals(RLP_ENCODED_TX2, Hex.toHexString(tx.getInit())); assertEquals(RLP_ENCODED_TX, Hex.toHexString(tx.getInit()));
assertEquals(28, tx.getSignature().v); assertEquals(28, tx.getSignature().v);
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())); assertEquals(RLP_ENCODED_TX, Hex.toHexString(tx.getEncodedSigned()));
} }
@Test @Test
public void testTransactionFromNew() throws Exception { public void testTransactionFromNew() throws Exception {
byte[] privKeyBytes = Hex.decode("3ecb44df2159c26e0f995712d4f39b6f6e499b40749b1cf1246c37f9516cb6a4"); byte[] privKeyBytes = Hex.decode("c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4");
// nonce=0, gasprice=10 ** 12, startgas=10000, to=, value=10 ** 16, data='').sign(k) String RLP_TX_UNSIGNED = "eb8085e8d4a510008227109413978aee95f38490e9769c39b2773ed763d9cd5f872386f26fc1000080";
// byte[] nonce = BigInteger.ZERO.toByteArray(); String RLP_TX_SIGNED = "f86b8085e8d4a510008227109413978aee95f38490e9769c39b2773ed763d9cd5f872386f26fc10000801ba0eab47c1a49bf2fe5d40e01d313900e19ca485867d462fe06e139e3a536c6d4f4a014a569d327dcda4b29f74f93c0e9729d2f49ad726e703f9cd90dbb0fbf6649f1";
// byte[] value = Denomination.ETHER.getDenomination().toByteArray();
// byte[] recieveAddress = Hex.decode("8a40bfaa73256b60764c1bf40675a99083efb075"); byte[] nonce = BigIntegers.asUnsignedByteArray(BigInteger.ZERO);
// byte[] gasPrice = Denomination.SZABO.getDenomination().toByteArray(); byte[] gasPrice = Hex.decode("e8d4a51000"); // 1000000000000
// byte[] gas = new BigInteger("10000").toByteArray(); byte[] gas = Hex.decode("2710"); // 10000
// byte[] data = new byte[0]; byte[] recieveAddress = Hex.decode("13978aee95f38490e9769c39b2773ed763d9cd5f");
byte[] value = Hex.decode("2386f26fc10000"); //10000000000000000"
byte[] data = new byte[0];
Transaction tx = new Transaction(nonce, gasPrice, gas, recieveAddress, value, data);
byte[] nonce = null;
byte[] value = null; // Testing unsigned
byte[] recieveAddress = Hex.decode("91a10664d0cd489085a7a018beb5245d4f2272f1"); String encodedUnsigned = Hex.toHexString(tx.getEncoded());
byte[] gasPrice = Hex.decode("09184e72a000");
byte[] gas = Hex.decode("2710");
byte[] data = Hex.decode("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001");
Transaction tx = new Transaction(nonce, value, recieveAddress, gasPrice, gas, data);
byte[] encoded = tx.getEncoded();
String test = Hex.toHexString(encoded);
System.out.println(RLP_ENCODED_TX2); System.out.println(RLP_TX_UNSIGNED);
System.out.println(test); System.out.println(encodedUnsigned);
assertEquals(RLP_ENCODED_TX2, test); assertEquals(RLP_TX_UNSIGNED, encodedUnsigned);
assertEquals(HASH_RAW_TX, Hex.toHexString(tx.getHash())); assertEquals(HASH_RAW_TX, Hex.toHexString(tx.getHash()));
// Testing signed
tx.sign(privKeyBytes); tx.sign(privKeyBytes);
String encodedSigned = Hex.toHexString(tx.getEncodedSigned());
System.out.println(RLP_TX_SIGNED);
System.out.println(encodedSigned);
assertEquals(RLP_TX_SIGNED, encodedSigned);
assertEquals(HASH_RAW_TX, Hex.toHexString(tx.getHash())); assertEquals(HASH_RAW_TX, Hex.toHexString(tx.getHash()));
} }
} }

View File

@ -538,7 +538,7 @@ public class MessagesTest {
receiveAddress.getAddress(), gasPrice, gas, null); receiveAddress.getAddress(), gasPrice, gas, null);
tx.sign(privKey); tx.sign(privKey);
tx.getEncoded(); tx.getEncodedSigned();
List<Transaction> txList = new ArrayList<Transaction>(); List<Transaction> txList = new ArrayList<Transaction>();
txList.add(tx); txList.add(tx);
@ -548,11 +548,7 @@ public class MessagesTest {
//todo: add assertion to the test whenever you know what should be the result //todo: add assertion to the test whenever you know what should be the result
System.out.println(Hex.toHexString( transactionsMessage.getPayload() )); System.out.println(Hex.toHexString( transactionsMessage.getPayload() ));
// !!! [ 15:51:24 | eth ] Ignoring invalid transaction: Invalid transaction format: Bad field 1 (8b00d3c21bcecceda1000000) // !!! [ 15:51:24 | eth ] Ignoring invalid transaction: Invalid transaction format: Bad field 1 (8b00d3c21bcecceda1000000)
} }
} }

View File

@ -1,102 +0,0 @@
package org.ethereum.transaction;
import java.io.IOException;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import org.ethereum.core.Address;
import org.ethereum.core.Transaction;
import org.ethereum.crypto.ECKey;
import org.ethereum.crypto.HashUtil;
import org.junit.Assert;
import org.junit.Test;
import org.spongycastle.util.BigIntegers;
import org.spongycastle.util.encoders.Hex;
public class TransactionTest {
@Test /* sign transaction https://tools.ietf.org/html/rfc6979 */
public void test1() throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException, IOException {
//python taken exact data
String txRLPRawData = "a9e880872386f26fc1000085e8d4a510008203e89413978aee95f38490e9769c39b2773ed763d9cd5f80";
// String txRLPRawData = "f82804881bc16d674ec8000094cd2a3d9f938e13cd947ec05abc7fe734df8dd8268609184e72a0006480";
byte[] cowPrivKey = Hex.decode("c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4");
ECKey key = ECKey.fromPrivate(cowPrivKey);
byte[] data = Hex.decode(txRLPRawData);
// step 1: serialize + RLP encode
// step 2: hash = sha3(step1)
byte[] txHash = HashUtil.sha3(data);
String signature = key.doSign(txHash).toBase64();
System.out.println(signature);
}
@Test /* achieve public key of the sender */
public void test2() throws Exception {
// cat --> 79B08AD8787060333663D19704909EE7B1903E58
// cow --> CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826
BigInteger value = new BigInteger("1000000000000000000000000");
byte[] privKey = HashUtil.sha3("cat".getBytes());
Address receiveAddress = new Address(privKey);
byte[] senderPrivKey = HashUtil.sha3("cow".getBytes());
byte[] gasPrice= Hex.decode("09184e72a000");
byte[] gas = Hex.decode("4255");
Transaction tx = new Transaction(null, value.toByteArray(),
receiveAddress.getAddress(), gasPrice, gas, null);
tx.sign(senderPrivKey);
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("Sender is\t\t: " + Hex.toHexString(key.getAddress()));
Assert.assertEquals("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826",
Hex.toHexString(key.getAddress()).toUpperCase());
}
@Test /* encode transaction */
public void test3() throws Exception {
BigInteger value = new BigInteger("1000000000000000000000000");
byte[] privKey = HashUtil.sha3("cat".getBytes());
Address receiveAddress = new Address(privKey);
byte[] gasPrice= Hex.decode("09184e72a000");
byte[] gas = Hex.decode("4255");
Transaction tx = new Transaction(null, value.toByteArray(),
receiveAddress.getAddress(), gasPrice, gas, null);
tx.sign(privKey);
byte[] payload = tx.getEncoded();
System.out.println(Hex.toHexString( payload ));
}
}

View File

@ -237,7 +237,7 @@ public class RLPTest {
public void testEncodeElementNull(){ public void testEncodeElementNull(){
byte[] actuals = RLP.encodeElement(null); byte[] actuals = RLP.encodeElement(null);
assertArrayEquals(new byte[] { (byte) 0x00 }, actuals); assertArrayEquals(new byte[] { (byte) 0x80 }, actuals);
} }
@Test /** found bug encode list affects element value, @Test /** found bug encode list affects element value,