/*
* 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.db;
import org.ethereum.config.SystemProperties;
import org.ethereum.config.blockchain.FrontierConfig;
import org.ethereum.config.net.MainNetConfig;
import org.ethereum.core.Block;
import org.ethereum.core.Transaction;
import org.ethereum.core.TransactionInfo;
import org.ethereum.datasource.inmem.HashMapDB;
import org.ethereum.util.blockchain.SolidityContract;
import org.ethereum.util.blockchain.StandaloneBlockchain;
import org.ethereum.vm.DataWord;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import java.math.BigInteger;
import java.util.Arrays;
/**
* Created by Anton Nashatyrev on 08.04.2016.
*/
public class TransactionStoreTest {
@AfterClass
public static void cleanup() {
SystemProperties.resetToDefault();
}
@Test
public void simpleTest() {
String contractSrc =
"contract Adder {" +
" function add(int a, int b) returns (int) {return a + b;}" +
"}";
HashMapDB<byte[]> txDb = new HashMapDB<>();
StandaloneBlockchain bc = new StandaloneBlockchain();
bc.getBlockchain().withTransactionStore(new TransactionStore(txDb));
SolidityContract contract = bc.submitNewContract(contractSrc);
bc.createBlock();
contract.callFunction("add", 555, 222);
Block b2 = bc.createBlock();
contract.callFunction("add", 333, 333);
Block b3 = bc.createBlock();
Transaction tx1 = b2.getTransactionsList().get(0);
TransactionInfo tx1Info = bc.getBlockchain().getTransactionInfo(tx1.getHash());
byte[] executionResult = tx1Info.getReceipt().getExecutionResult();
Assert.assertArrayEquals(new DataWord(777).getData(), executionResult);
System.out.println(txDb.keys().size());
bc.getBlockchain().flush();
System.out.println(txDb.keys().size());
TransactionStore txStore = new TransactionStore(txDb);
TransactionInfo tx1Info_ = txStore.get(tx1.getHash()).get(0);
executionResult = tx1Info_.getReceipt().getExecutionResult();
Assert.assertArrayEquals(new DataWord(777).getData(), executionResult);
TransactionInfo highIndex = new TransactionInfo(tx1Info.getReceipt(), tx1Info.getBlockHash(), 255);
TransactionInfo highIndexCopy = new TransactionInfo(highIndex.getEncoded());
Assert.assertArrayEquals(highIndex.getBlockHash(), highIndexCopy.getBlockHash());
Assert.assertEquals(highIndex.getIndex(), highIndexCopy.getIndex());
}
@Test
public void forkTest() {
// check that TransactionInfo is always returned from the main chain for
// transaction which included into blocks from different forks
String contractSrc =
"contract Adder {" +
" int public lastResult;" +
" function add(int a, int b) returns (int) {lastResult = a + b; return lastResult; }" +
"}";
HashMapDB txDb = new HashMapDB();
StandaloneBlockchain bc = new StandaloneBlockchain();
TransactionStore transactionStore = new TransactionStore(txDb);
bc.getBlockchain().withTransactionStore(transactionStore);
SolidityContract contract = bc.submitNewContract(contractSrc);
Block b1 = bc.createBlock();
contract.callFunction("add", 555, 222);
Block b2 = bc.createBlock();
Transaction tx1 = b2.getTransactionsList().get(0);
TransactionInfo txInfo = bc.getBlockchain().getTransactionInfo(tx1.getHash());
Assert.assertTrue(Arrays.equals(txInfo.getBlockHash(), b2.getHash()));
Block b2_ = bc.createForkBlock(b1);
contract.callFunction("add", 555, 222); // tx with the same hash as before
Block b3_ = bc.createForkBlock(b2_);
TransactionInfo txInfo_ = bc.getBlockchain().getTransactionInfo(tx1.getHash());
Assert.assertTrue(Arrays.equals(txInfo_.getBlockHash(), b3_.getHash()));
Block b3 = bc.createForkBlock(b2);
Block b4 = bc.createForkBlock(b3);
txInfo = bc.getBlockchain().getTransactionInfo(tx1.getHash());
Assert.assertTrue(Arrays.equals(txInfo.getBlockHash(), b2.getHash()));
}
@Test
public void backwardCompatibleDbTest() {
// check that we can read previously saved entries (saved with legacy code)
HashMapDB txDb = new HashMapDB();
TransactionStore transactionStore = new TransactionStore(txDb);
StandaloneBlockchain bc = new StandaloneBlockchain();
bc.getBlockchain().withTransactionStore(transactionStore);
bc.sendEther(new byte[20], BigInteger.valueOf(1000));
Block b1 = bc.createBlock();
Transaction tx = b1.getTransactionsList().get(0);
TransactionInfo info = transactionStore.get(tx.getHash()).get(0);
HashMapDB<byte[]> txDb1 = new HashMapDB<>();
txDb1.put(tx.getHash(), info.getEncoded()); // legacy serialization
TransactionStore transactionStore1 = new TransactionStore(txDb1);
TransactionInfo info1 = transactionStore1.get(tx.getHash()).get(0);
Assert.assertArrayEquals(info1.getReceipt().getPostTxState(), info.getReceipt().getPostTxState());
}
}