/* * Copyright (c) [2016] [ <ether.camp> ] * This file is part of the ethereumJ library. * * The ethereumJ library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The ethereumJ library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see <http://www.gnu.org/licenses/>. */ package org.ethereum.core; import org.ethereum.config.SystemProperties; import org.ethereum.config.blockchain.HomesteadConfig; import org.ethereum.config.net.MainNetConfig; import org.ethereum.core.genesis.GenesisLoader; import org.ethereum.crypto.ECKey; import org.ethereum.crypto.ECKey.MissingPrivateKeyException; import org.ethereum.crypto.HashUtil; import org.ethereum.db.BlockStoreDummy; import org.ethereum.jsontestsuite.suite.StateTestSuite; import org.ethereum.jsontestsuite.suite.runners.StateTestRunner; import org.ethereum.solidity.compiler.CompilationResult; import org.ethereum.solidity.compiler.SolidityCompiler; import org.ethereum.util.ByteUtil; import org.ethereum.vm.LogInfo; import org.ethereum.vm.program.ProgramResult; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import org.spongycastle.util.BigIntegers; import org.spongycastle.util.encoders.Hex; import java.io.IOException; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.ethereum.solidity.SolidityType.*; 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 = keccak(step1) byte[] txHash = HashUtil.sha3(data); String signature = key.doSign(txHash).toBase64(); System.out.println(signature); } @Ignore @Test /* achieve public key of the sender */ public void test2() throws Exception { // cat --> 79b08ad8787060333663d19704909ee7b1903e58 // cow --> cd2a3d9f938e13cd947ec05abc7fe734df8dd826 BigInteger value = new BigInteger("1000000000000000000000"); byte[] privKey = HashUtil.sha3("cat".getBytes()); ECKey ecKey = ECKey.fromPrivate(privKey); byte[] senderPrivKey = HashUtil.sha3("cow".getBytes()); byte[] gasPrice = Hex.decode("09184e72a000"); byte[] gas = Hex.decode("4255"); // Tn (nonce); Tp(pgas); Tg(gaslimi); Tt(value); Tv(value); Ti(sender); Tw; Tr; Ts Transaction tx = new Transaction(null, gasPrice, gas, ecKey.getAddress(), value.toByteArray(), null); tx.sign(ECKey.fromPrivate(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.getEncoded())); // retrieve the signer/sender of the transaction ECKey key = ECKey.signatureToKey(tx.getHash(), tx.getSignature()); System.out.println("Tx unsigned RLP\t\t: " + Hex.toHexString(tx.getEncodedRaw())); System.out.println("Tx signed RLP\t\t: " + 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())); assertEquals("cd2a3d9f938e13cd947ec05abc7fe734df8dd826", Hex.toHexString(key.getAddress())); System.out.println(tx.toString()); } @Ignore @Test /* achieve public key of the sender nonce: 01 */ public void test3() throws Exception { // cat --> 79b08ad8787060333663d19704909ee7b1903e58 // cow --> cd2a3d9f938e13cd947ec05abc7fe734df8dd826 ECKey ecKey = ECKey.fromPrivate(HashUtil.sha3("cat".getBytes())); byte[] senderPrivKey = HashUtil.sha3("cow".getBytes()); byte[] nonce = {0x01}; byte[] gasPrice = Hex.decode("09184e72a000"); byte[] gasLimit = Hex.decode("4255"); BigInteger value = new BigInteger("1000000000000000000000000"); Transaction tx = new Transaction(nonce, gasPrice, gasLimit, ecKey.getAddress(), value.toByteArray(), null); tx.sign(ECKey.fromPrivate(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.getEncoded())); // retrieve the signer/sender of the transaction ECKey key = ECKey.signatureToKey(tx.getHash(), tx.getSignature()); System.out.println("Tx unsigned RLP\t\t: " + Hex.toHexString(tx.getEncodedRaw())); System.out.println("Tx signed RLP\t\t: " + 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())); assertEquals("cd2a3d9f938e13cd947ec05abc7fe734df8dd826", Hex.toHexString(key.getAddress())); } // Testdata from: https://github.com/ethereum/tests/blob/master/txtest.json String RLP_ENCODED_RAW_TX = "e88085e8d4a510008227109413978aee95f38490e9769c39b2773ed763d9cd5f872386f26fc1000080"; String RLP_ENCODED_UNSIGNED_TX = "eb8085e8d4a510008227109413978aee95f38490e9769c39b2773ed763d9cd5f872386f26fc1000080808080"; String HASH_TX = "328ea6d24659dec48adea1aced9a136e5ebdf40258db30d1b1d97ed2b74be34e"; String RLP_ENCODED_SIGNED_TX = "f86b8085e8d4a510008227109413978aee95f38490e9769c39b2773ed763d9cd5f872386f26fc10000801ba0eab47c1a49bf2fe5d40e01d313900e19ca485867d462fe06e139e3a536c6d4f4a014a569d327dcda4b29f74f93c0e9729d2f49ad726e703f9cd90dbb0fbf6649f1"; String KEY = "c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4"; byte[] testNonce = Hex.decode(""); byte[] testGasPrice = BigIntegers.asUnsignedByteArray(BigInteger.valueOf(1000000000000L)); byte[] testGasLimit = BigIntegers.asUnsignedByteArray(BigInteger.valueOf(10000)); byte[] testReceiveAddress = Hex.decode("13978aee95f38490e9769c39b2773ed763d9cd5f"); byte[] testValue = BigIntegers.asUnsignedByteArray(BigInteger.valueOf(10000000000000000L)); byte[] testData = Hex.decode(""); byte[] testInit = Hex.decode(""); @Ignore @Test public void testTransactionFromSignedRLP() throws Exception { Transaction txSigned = new Transaction(Hex.decode(RLP_ENCODED_SIGNED_TX)); assertEquals(HASH_TX, Hex.toHexString(txSigned.getHash())); assertEquals(RLP_ENCODED_SIGNED_TX, Hex.toHexString(txSigned.getEncoded())); assertEquals(BigInteger.ZERO, new BigInteger(1, txSigned.getNonce())); assertEquals(new BigInteger(1, testGasPrice), new BigInteger(1, txSigned.getGasPrice())); assertEquals(new BigInteger(1, testGasLimit), new BigInteger(1, txSigned.getGasLimit())); assertEquals(Hex.toHexString(testReceiveAddress), Hex.toHexString(txSigned.getReceiveAddress())); assertEquals(new BigInteger(1, testValue), new BigInteger(1, txSigned.getValue())); assertNull(txSigned.getData()); assertEquals(27, txSigned.getSignature().v); assertEquals("eab47c1a49bf2fe5d40e01d313900e19ca485867d462fe06e139e3a536c6d4f4", Hex.toHexString(BigIntegers.asUnsignedByteArray(txSigned.getSignature().r))); assertEquals("14a569d327dcda4b29f74f93c0e9729d2f49ad726e703f9cd90dbb0fbf6649f1", Hex.toHexString(BigIntegers.asUnsignedByteArray(txSigned.getSignature().s))); } @Ignore @Test public void testTransactionFromUnsignedRLP() throws Exception { Transaction txUnsigned = new Transaction(Hex.decode(RLP_ENCODED_UNSIGNED_TX)); assertEquals(HASH_TX, Hex.toHexString(txUnsigned.getHash())); assertEquals(RLP_ENCODED_UNSIGNED_TX, Hex.toHexString(txUnsigned.getEncoded())); txUnsigned.sign(ECKey.fromPrivate(Hex.decode(KEY))); assertEquals(RLP_ENCODED_SIGNED_TX, Hex.toHexString(txUnsigned.getEncoded())); assertEquals(BigInteger.ZERO, new BigInteger(1, txUnsigned.getNonce())); assertEquals(new BigInteger(1, testGasPrice), new BigInteger(1, txUnsigned.getGasPrice())); assertEquals(new BigInteger(1, testGasLimit), new BigInteger(1, txUnsigned.getGasLimit())); assertEquals(Hex.toHexString(testReceiveAddress), Hex.toHexString(txUnsigned.getReceiveAddress())); assertEquals(new BigInteger(1, testValue), new BigInteger(1, txUnsigned.getValue())); assertNull(txUnsigned.getData()); assertEquals(27, txUnsigned.getSignature().v); assertEquals("eab47c1a49bf2fe5d40e01d313900e19ca485867d462fe06e139e3a536c6d4f4", Hex.toHexString(BigIntegers.asUnsignedByteArray(txUnsigned.getSignature().r))); assertEquals("14a569d327dcda4b29f74f93c0e9729d2f49ad726e703f9cd90dbb0fbf6649f1", Hex.toHexString(BigIntegers.asUnsignedByteArray(txUnsigned.getSignature().s))); } @Ignore @Test public void testTransactionFromNew1() throws MissingPrivateKeyException { Transaction txNew = new Transaction(testNonce, testGasPrice, testGasLimit, testReceiveAddress, testValue, testData); assertEquals("", Hex.toHexString(txNew.getNonce())); assertEquals(new BigInteger(1, testGasPrice), new BigInteger(1, txNew.getGasPrice())); assertEquals(new BigInteger(1, testGasLimit), new BigInteger(1, txNew.getGasLimit())); assertEquals(Hex.toHexString(testReceiveAddress), Hex.toHexString(txNew.getReceiveAddress())); assertEquals(new BigInteger(1, testValue), new BigInteger(1, txNew.getValue())); assertEquals("", Hex.toHexString(txNew.getData())); assertNull(txNew.getSignature()); assertEquals(RLP_ENCODED_RAW_TX, Hex.toHexString(txNew.getEncodedRaw())); assertEquals(HASH_TX, Hex.toHexString(txNew.getHash())); assertEquals(RLP_ENCODED_UNSIGNED_TX, Hex.toHexString(txNew.getEncoded())); txNew.sign(ECKey.fromPrivate(Hex.decode(KEY))); assertEquals(RLP_ENCODED_SIGNED_TX, Hex.toHexString(txNew.getEncoded())); assertEquals(27, txNew.getSignature().v); assertEquals("eab47c1a49bf2fe5d40e01d313900e19ca485867d462fe06e139e3a536c6d4f4", Hex.toHexString(BigIntegers.asUnsignedByteArray(txNew.getSignature().r))); assertEquals("14a569d327dcda4b29f74f93c0e9729d2f49ad726e703f9cd90dbb0fbf6649f1", Hex.toHexString(BigIntegers.asUnsignedByteArray(txNew.getSignature().s))); } @Ignore @Test public void testTransactionFromNew2() throws MissingPrivateKeyException { byte[] privKeyBytes = Hex.decode("c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4"); String RLP_TX_UNSIGNED = "eb8085e8d4a510008227109413978aee95f38490e9769c39b2773ed763d9cd5f872386f26fc1000080808080"; String RLP_TX_SIGNED = "f86b8085e8d4a510008227109413978aee95f38490e9769c39b2773ed763d9cd5f872386f26fc10000801ba0eab47c1a49bf2fe5d40e01d313900e19ca485867d462fe06e139e3a536c6d4f4a014a569d327dcda4b29f74f93c0e9729d2f49ad726e703f9cd90dbb0fbf6649f1"; String HASH_TX_UNSIGNED = "328ea6d24659dec48adea1aced9a136e5ebdf40258db30d1b1d97ed2b74be34e"; byte[] nonce = BigIntegers.asUnsignedByteArray(BigInteger.ZERO); byte[] gasPrice = Hex.decode("e8d4a51000"); // 1000000000000 byte[] gas = Hex.decode("2710"); // 10000 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); // Testing unsigned String encodedUnsigned = Hex.toHexString(tx.getEncoded()); assertEquals(RLP_TX_UNSIGNED, encodedUnsigned); assertEquals(HASH_TX_UNSIGNED, Hex.toHexString(tx.getHash())); // Testing signed tx.sign(ECKey.fromPrivate(privKeyBytes)); String encodedSigned = Hex.toHexString(tx.getEncoded()); assertEquals(RLP_TX_SIGNED, encodedSigned); assertEquals(HASH_TX_UNSIGNED, Hex.toHexString(tx.getHash())); } @Test public void testTransactionCreateContract() { // String rlp = // "f89f808609184e72a0008203e8808203e8b84b4560005444602054600f60056002600a02010b0d630000001d596002602054630000003b5860066000530860056006600202010a0d6300000036596004604054630000003b5860056060541ca0ddc901d83110ea50bc40803f42083afea1bbd420548f6392a679af8e24b21345a06620b3b512bea5f0a272703e8d6933177c23afc79516fd0ca4a204aa6e34c7e9"; byte[] senderPrivKey = HashUtil.sha3("cow".getBytes()); byte[] nonce = BigIntegers.asUnsignedByteArray(BigInteger.ZERO); byte[] gasPrice = Hex.decode("09184e72a000"); // 10000000000000 byte[] gas = Hex.decode("03e8"); // 1000 byte[] recieveAddress = null; byte[] endowment = Hex.decode("03e8"); //10000000000000000" byte[] init = Hex.decode ("4560005444602054600f60056002600a02010b0d630000001d596002602054630000003b5860066000530860056006600202010a0d6300000036596004604054630000003b586005606054"); Transaction tx1 = new Transaction(nonce, gasPrice, gas, recieveAddress, endowment, init); tx1.sign(ECKey.fromPrivate(senderPrivKey)); byte[] payload = tx1.getEncoded(); System.out.println(Hex.toHexString(payload)); Transaction tx2 = new Transaction(payload); // tx2.getSender(); String plainTx1 = Hex.toHexString(tx1.getEncodedRaw()); String plainTx2 = Hex.toHexString(tx2.getEncodedRaw()); // Transaction tx = new Transaction(Hex.decode(rlp)); System.out.println("tx1.hash: " + Hex.toHexString(tx1.getHash())); System.out.println("tx2.hash: " + Hex.toHexString(tx2.getHash())); System.out.println(); System.out.println("plainTx1: " + plainTx1); System.out.println("plainTx2: " + plainTx2); System.out.println(Hex.toHexString(tx2.getSender())); } @Ignore @Test public void encodeReceiptTest() { String data = "f90244a0f5ff3fbd159773816a7c707a9b8cb6bb778b934a8f6466c7830ed970498f4b688301e848b902000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dbda94cd2a3d9f938e13cd947ec05abc7fe734df8dd826c083a1a1a1"; byte[] stateRoot = Hex.decode("f5ff3fbd159773816a7c707a9b8cb6bb778b934a8f6466c7830ed970498f4b68"); byte[] gasUsed = Hex.decode("01E848"); Bloom bloom = new Bloom(Hex.decode("0000000000000000800000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")); LogInfo logInfo1 = new LogInfo( Hex.decode("cd2a3d9f938e13cd947ec05abc7fe734df8dd826"), null, Hex.decode("a1a1a1") ); List<LogInfo> logs = new ArrayList<>(); logs.add(logInfo1); // TODO calculate cumulative gas TransactionReceipt receipt = new TransactionReceipt(stateRoot, gasUsed, bloom, logs); assertEquals(data, Hex.toHexString(receipt.getEncoded())); } @Test public void constantCallConflictTest() throws Exception { /* 0x095e7baea6a6c7c4c2dfeb977efac326af552d87 contract is the following Solidity code: contract Test { uint a = 256; function set(uint s) { a = s; } function get() returns (uint) { return a; } } */ String json = "{ " + " 'test1' : { " + " 'env' : { " + " 'currentCoinbase' : '2adc25665018aa1fe0e6bc666dac8fc2697ff9ba', " + " 'currentDifficulty' : '0x0100', " + " 'currentGasLimit' : '0x0f4240', " + " 'currentNumber' : '0x00', " + " 'currentTimestamp' : '0x01', " + " 'previousHash' : '5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6' " + " }, " + " 'logs' : [ " + " ], " + " 'out' : '0x', " + " 'post' : { " + " '095e7baea6a6c7c4c2dfeb977efac326af552d87' : { " + " 'balance' : '0x0de0b6b3a76586a0', " + " 'code' : '0x606060405260e060020a600035046360fe47b1811460245780636d4ce63c14602e575b005b6004356000556022565b6000546060908152602090f3', " + " 'nonce' : '0x00', " + " 'storage' : { " + " '0x00' : '0x0400' " + " } " + " }, " + " '2adc25665018aa1fe0e6bc666dac8fc2697ff9ba' : { " + " 'balance' : '0x67c3', " + " 'code' : '0x', " + " 'nonce' : '0x00', " + " 'storage' : { " + " } " + " }, " + " 'a94f5374fce5edbc8e2a8697c15331677e6ebf0b' : { " + " 'balance' : '0x0DE0B6B3A762119D', " + " 'code' : '0x', " + " 'nonce' : '0x01', " + " 'storage' : { " + " } " + " } " + " }, " + " 'postStateRoot' : '17454a767e5f04461256f3812ffca930443c04a47d05ce3f38940c4a14b8c479', " + " 'pre' : { " + " '095e7baea6a6c7c4c2dfeb977efac326af552d87' : { " + " 'balance' : '0x0de0b6b3a7640000', " + " 'code' : '0x606060405260e060020a600035046360fe47b1811460245780636d4ce63c14602e575b005b6004356000556022565b6000546060908152602090f3', " + " 'nonce' : '0x00', " + " 'storage' : { " + " '0x00' : '0x02' " + " } " + " }, " + " 'a94f5374fce5edbc8e2a8697c15331677e6ebf0b' : { " + " 'balance' : '0x0de0b6b3a7640000', " + " 'code' : '0x', " + " 'nonce' : '0x00', " + " 'storage' : { " + " } " + " } " + " }, " + " 'transaction' : { " + " 'data' : '0x60fe47b10000000000000000000000000000000000000000000000000000000000000400', " + " 'gasLimit' : '0x061a80', " + " 'gasPrice' : '0x01', " + " 'nonce' : '0x00', " + " 'secretKey' : '45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8', " + " 'to' : '095e7baea6a6c7c4c2dfeb977efac326af552d87', " + " 'value' : '0x0186a0' " + " } " + " } " + "}"; StateTestSuite stateTestSuite = new StateTestSuite(json.replaceAll("'", "\"")); List<String> res = new StateTestRunner(stateTestSuite.getTestCases().get("test1")) { @Override protected ProgramResult executeTransaction(Transaction tx) { // first emulating the constant call (Ethereum.callConstantFunction) // to ensure it doesn't affect the final state { Repository track = repository.startTracking(); Transaction txConst = CallTransaction.createCallTransaction(0, 0, 100000000000000L, "095e7baea6a6c7c4c2dfeb977efac326af552d87", 0, CallTransaction.Function.fromSignature("get")); txConst.sign(ECKey.fromPrivate(new byte[32])); Block bestBlock = block; TransactionExecutor executor = new TransactionExecutor (txConst, bestBlock.getCoinbase(), track, new BlockStoreDummy(), invokeFactory, bestBlock) .setLocalCall(true); executor.init(); executor.execute(); executor.go(); executor.finalization(); track.rollback(); System.out.println("Return value: " + new IntType("uint").decode(executor.getResult().getHReturn())); } // now executing the JSON test transaction return super.executeTransaction(tx); } }.runImpl(); if (!res.isEmpty()) throw new RuntimeException("Test failed: " + res); } @Test public void homesteadContractCreationTest() throws Exception { // Checks Homestead updates (1) & (3) from // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.mediawiki /* trying to create a contract with the following Solidity code: contract Test { uint a = 256; function set(uint s) { a = s; } function get() returns (uint) { return a; } } */ int iBitLowGas = 0x015f84; // [actual gas required] - 1 String aBitLowGas = "0x0" + Integer.toHexString(iBitLowGas); String senderPostBalance = "0x0" + Long.toHexString(1000000000000000000L - iBitLowGas); String json = "{ " + " 'test1' : { " + " 'env' : { " + " 'currentCoinbase' : '2adc25665018aa1fe0e6bc666dac8fc2697ff9ba', " + " 'currentDifficulty' : '0x0100', " + " 'currentGasLimit' : '0x0f4240', " + " 'currentNumber' : '0x01', " + " 'currentTimestamp' : '0x01', " + " 'previousHash' : '5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6' " + " }, " + " 'logs' : [ " + " ], " + " 'out' : '0x', " + " 'post' : { " + " '2adc25665018aa1fe0e6bc666dac8fc2697ff9ba' : { " + " 'balance' : '" + aBitLowGas + "', " + " 'code' : '0x', " + " 'nonce' : '0x00', " + " 'storage' : { " + " } " + " }," + " 'a94f5374fce5edbc8e2a8697c15331677e6ebf0b' : { " + " 'balance' : '" + senderPostBalance + "', " + " 'code' : '0x', " + " 'nonce' : '0x01', " + " 'storage' : { " + " } " + " } " + " }, " + " 'postStateRoot' : '17454a767e5f04461256f3812ffca930443c04a47d05ce3f38940c4a14b8c479', " + " 'pre' : { " + " 'a94f5374fce5edbc8e2a8697c15331677e6ebf0b' : { " + " 'balance' : '0x0de0b6b3a7640000', " + " 'code' : '0x', " + " 'nonce' : '0x00', " + " 'storage' : { " + " } " + " } " + " }, " + " 'transaction' : { " + " 'data' : '0x6060604052610100600060005055603b8060196000396000f3606060405260e060020a600035046360fe47b1811460245780636d4ce63c14602e575b005b6004356000556022565b6000546060908152602090f3', " + " 'gasLimit' : '" + aBitLowGas + "', " + " 'gasPrice' : '0x01', " + " 'nonce' : '0x00', " + " 'secretKey' : '45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8', " + " 'to' : '', " + " 'value' : '0x0' " + " } " + " } " + "}"; StateTestSuite stateTestSuite = new StateTestSuite(json.replaceAll("'", "\"")); System.out.println(json.replaceAll("'", "\"")); try { SystemProperties.getDefault().setBlockchainConfig(new HomesteadConfig()); List<String> res = new StateTestRunner(stateTestSuite.getTestCases().get("test1")).runImpl(); if (!res.isEmpty()) throw new RuntimeException("Test failed: " + res); } finally { SystemProperties.getDefault().setBlockchainConfig(MainNetConfig.INSTANCE); } } @Test public void multiSuicideTest() throws IOException, InterruptedException { String contract = "pragma solidity ^0.4.3;" + "contract PsychoKiller {" + " function () payable {}" + " function homicide() {" + " suicide(msg.sender);" + " }" + " function multipleHomocide() {" + " PsychoKiller k = this;" + " k.homicide();" + " k.homicide();" + " k.homicide();" + " k.homicide();" + " }" + "}"; SolidityCompiler.Result res = SolidityCompiler.compile( contract.getBytes(), true, SolidityCompiler.Options.ABI, SolidityCompiler.Options.BIN); System.out.println(res.errors); CompilationResult cres = CompilationResult.parse(res.output); BlockchainImpl blockchain = ImportLightTest.createBlockchain(GenesisLoader.loadGenesis( getClass().getResourceAsStream("/genesis/genesis-light.json"))); ECKey sender = ECKey.fromPrivate(Hex.decode("3ec771c31cac8c0dba77a69e503765701d3c2bb62435888d4ffa38fed60c445c")).compress(); System.out.println("address: " + Hex.toHexString(sender.getAddress())); if (cres.contracts.get("PsychoKiller") != null) { Transaction tx = createTx(blockchain, sender, new byte[0], Hex.decode(cres.contracts.get("PsychoKiller").bin)); executeTransaction(blockchain, tx); byte[] contractAddress = tx.getContractAddress(); CallTransaction.Contract contract1 = new CallTransaction.Contract(cres.contracts.get("PsychoKiller").abi); byte[] callData = contract1.getByName("multipleHomocide").encode(); Transaction tx1 = createTx(blockchain, sender, contractAddress, callData, 0l); ProgramResult programResult = executeTransaction(blockchain, tx1).getResult(); // suicide of a single account should be counted only once Assert.assertEquals(24000, programResult.getFutureRefund()); } else { Assert.fail(); } } @Test public void receiptErrorTest() throws Exception { BlockchainImpl blockchain = ImportLightTest.createBlockchain(GenesisLoader.loadGenesis( getClass().getResourceAsStream("/genesis/genesis-light.json"))); ECKey sender = ECKey.fromPrivate(Hex.decode("3ec771c31cac8c0dba77a69e503765701d3c2bb62435888d4ffa38fed60c445c")); { // Receipt RLP backward compatibility TransactionReceipt receipt = new TransactionReceipt(Hex.decode("f9010c80825208b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c082520880")); Assert.assertTrue(receipt.isValid()); Assert.assertTrue(receipt.isSuccessful()); } { Transaction tx = createTx(blockchain, sender, new byte[32], new byte[0], 100); TransactionReceipt receipt = executeTransaction(blockchain, tx).getReceipt(); System.out.println(Hex.toHexString(receipt.getEncoded())); receipt = new TransactionReceipt(receipt.getEncoded()); Assert.assertTrue(receipt.isValid()); Assert.assertTrue(receipt.isSuccessful()); } { Transaction tx = createTx(blockchain, new ECKey(), new byte[32], new byte[0], 100); TransactionReceipt receipt = executeTransaction(blockchain, tx).getReceipt(); receipt = new TransactionReceipt(receipt.getEncoded()); Assert.assertFalse(receipt.isValid()); Assert.assertFalse(receipt.isSuccessful()); Assert.assertTrue(receipt.getError().contains("Not enough")); } { Transaction tx = new Transaction( ByteUtil.intToBytesNoLeadZeroes(100500), ByteUtil.longToBytesNoLeadZeroes(1), ByteUtil.longToBytesNoLeadZeroes(3_000_000), new byte[0], ByteUtil.longToBytesNoLeadZeroes(0), new byte[0]); tx.sign(sender); TransactionReceipt receipt = executeTransaction(blockchain, tx).getReceipt(); receipt = new TransactionReceipt(receipt.getEncoded()); Assert.assertFalse(receipt.isValid()); Assert.assertFalse(receipt.isSuccessful()); Assert.assertTrue(receipt.getError().contains("nonce")); } { String contract = "contract GasConsumer {" + " function GasConsumer() {" + " int i = 0;" + " while(true) sha3(i++);" + " }" + "}"; SolidityCompiler.Result res = SolidityCompiler.compile( contract.getBytes(), true, SolidityCompiler.Options.ABI, SolidityCompiler.Options.BIN); System.out.println(res.errors); CompilationResult cres = CompilationResult.parse(res.output); Transaction tx = createTx(blockchain, sender, new byte[0], Hex.decode(cres.contracts.get("GasConsumer").bin), 0); TransactionReceipt receipt = executeTransaction(blockchain, tx).getReceipt(); receipt = new TransactionReceipt(receipt.getEncoded()); Assert.assertTrue(receipt.isValid()); Assert.assertFalse(receipt.isSuccessful()); Assert.assertTrue(receipt.getError().contains("Not enough gas")); } } protected Transaction createTx(BlockchainImpl blockchain, ECKey sender, byte[] receiveAddress, byte[] data) { return createTx(blockchain, sender, receiveAddress, data, 0); } protected Transaction createTx(BlockchainImpl blockchain, ECKey sender, byte[] receiveAddress, byte[] data, long value) { BigInteger nonce = blockchain.getRepository().getNonce(sender.getAddress()); Transaction tx = new Transaction( ByteUtil.bigIntegerToBytes(nonce), ByteUtil.longToBytesNoLeadZeroes(0), ByteUtil.longToBytesNoLeadZeroes(3_000_000), receiveAddress, ByteUtil.longToBytesNoLeadZeroes(value), data); tx.sign(sender); return tx; } public TransactionExecutor executeTransaction(BlockchainImpl blockchain, Transaction tx) { Repository track = blockchain.getRepository().startTracking(); TransactionExecutor executor = new TransactionExecutor(tx, new byte[32], blockchain.getRepository(), blockchain.getBlockStore(), blockchain.getProgramInvokeFactory(), blockchain.getBestBlock()); executor.init(); executor.execute(); executor.go(); executor.finalization(); track.commit(); return executor; } @Test public void afterEIP158Test() throws Exception { int chainId = 1; String rlpUnsigned = "ec098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a764000080018080"; String unsignedHash = "daf5a779ae972f972197303d7b574746c7ef83eadac0f2791ad23db92e4c8e53"; String privateKey = "4646464646464646464646464646464646464646464646464646464646464646"; BigInteger signatureR = new BigInteger("18515461264373351373200002665853028612451056578545711640558177340181847433846"); BigInteger signatureS = new BigInteger("46948507304638947509940763649030358759909902576025900602547168820602576006531"); String signedTxRlp = "f86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83"; Transaction tx = Transaction.create( "3535353535353535353535353535353535353535", new BigInteger("1000000000000000000"), new BigInteger("9"), new BigInteger("20000000000"), new BigInteger("21000"), chainId ); // Checking RLP of unsigned transaction and its hash assert Arrays.equals(Hex.decode(rlpUnsigned), tx.getEncoded()); assert Arrays.equals(Hex.decode(unsignedHash), tx.getHash()); ECKey ecKey = ECKey.fromPrivate(Hex.decode(privateKey)); tx.sign(ecKey); // Checking modified signature assert tx.getSignature().r.equals(signatureR); assert tx.getSignature().s.equals(signatureS); // Checking that we get correct TX in the end assert Arrays.equals(Hex.decode(signedTxRlp), tx.getEncoded()); // Check that we could correctly extract tx from new RLP Transaction txSigned = new Transaction(Hex.decode(signedTxRlp)); assert txSigned.getChainId() == chainId; } @Test public void etcChainIdTest() { Transaction tx = new Transaction(Hex.decode("f871830617428504a817c80083015f90940123286bd94beecd40905321f5c3202c7628d685880ecab7b2bae2c27080819ea021355678b1aa704f6ad4706fb8647f5125beadd1d84c6f9cf37dda1b62f24b1aa06b4a64fd29bb6e54a2c5107e8be42ac039a8ffb631e16e7bcbd15cdfc0015ee2")); Integer chainId = tx.getChainId(); assert 61 == chainId; } @Test public void longChainIdTest() { Transaction tx = new Transaction(Hex.decode("f8ae82477b8504a817c80083015f9094977ddf44438d540892d1b8618fea65395399971680b844eceb6e3e57696e6454757262696e655f30310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007827e19a025f55532f5cebec362f3f750a3b9c47ab76322622eb3a26ad24c80f9c388c15ba02dcc7ebcfb6ad6ae09f56a29d710cc4115e960a83b98405cf98f7177c14d8a51")); Integer chainId = tx.getChainId(); assert 16123 == chainId; Transaction tx1 = Transaction.create( "3535353535353535353535353535353535353535", new BigInteger("1000000000000000000"), new BigInteger("9"), new BigInteger("20000000000"), new BigInteger("21000"), 333333 ); ECKey key = new ECKey(); tx1.sign(key); Transaction tx2 = new Transaction(tx1.getEncoded()); assert 333333 == tx2.getChainId(); assert Arrays.equals(tx2.getSender(), key.getAddress()); } }