/*
* 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.jsontestsuite.suite.runners;
import org.ethereum.config.BlockchainConfig;
import org.ethereum.config.SystemProperties;
import org.ethereum.core.Transaction;
import org.ethereum.jsontestsuite.suite.TransactionTestCase;
import org.ethereum.jsontestsuite.suite.Utils;
import org.ethereum.jsontestsuite.suite.builder.TransactionBuilder;
import org.ethereum.jsontestsuite.suite.validators.TransactionValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
public class TransactionTestRunner {
private static Logger logger = LoggerFactory.getLogger("TCK-Test");
public static List<String> run(TransactionTestCase transactionTestCase2) {
return new TransactionTestRunner(transactionTestCase2).runImpl();
}
protected TransactionTestCase transactionTestCase;
protected Transaction transaction = null;
protected Transaction expectedTransaction;
protected long blockNumber;
protected BlockchainConfig blockchainConfig;
public TransactionTestRunner(TransactionTestCase transactionTestCase) {
this.transactionTestCase = transactionTestCase;
}
public List<String> runImpl() {
blockNumber = transactionTestCase.getBlocknumber() == null ? 0 : Utils.parseLong(transactionTestCase.getBlocknumber());
logger.info("Block number: {}", blockNumber);
this.blockchainConfig = SystemProperties.getDefault().getBlockchainConfig().getConfigForBlock(blockNumber);
try {
byte[] rlp = Utils.parseData(transactionTestCase.getRlp());
transaction = new Transaction(rlp);
transaction.verify();
} catch (Exception e) {
transaction = null;
}
if (transaction == null || transaction.getEncoded().length < 10000) {
logger.info("Transaction: {}", transaction);
} else {
logger.info("Transaction data skipped because it's too big", transaction);
}
expectedTransaction = transactionTestCase.getTransaction() == null ? null : TransactionBuilder.build(transactionTestCase.getTransaction());
if (expectedTransaction == null || expectedTransaction.getEncoded().length < 10000) {
logger.info("Expected transaction: {}", expectedTransaction);
} else {
logger.info("Expected transaction data skipped because it's too big", transaction);
}
// Not enough GAS
if (transaction != null) {
long basicTxCost = blockchainConfig.getTransactionCost(transaction);
if (new BigInteger(1, transaction.getGasLimit()).compareTo(BigInteger.valueOf(basicTxCost)) < 0) {
transaction = null;
}
}
// Transaction signature verification
String acceptFail = null;
boolean shouldAccept = transaction != null && blockchainConfig.acceptTransactionSignature(transaction);
if (!shouldAccept) transaction = null;
if (shouldAccept != (expectedTransaction != null)) {
acceptFail = "Transaction shouldn't be accepted";
}
String wrongSender = null;
String wrongHash = null;
if (transaction != null && expectedTransaction != null) {
// Verifying sender
if (!Hex.toHexString(transaction.getSender()).equals(transactionTestCase.getSender()))
wrongSender = "Sender is incorrect in parsed transaction";
// Verifying hash
// NOTE: "hash" is not required field in test case
if (transactionTestCase.getHash() != null &&
!Hex.toHexString(transaction.getHash()).equals(transactionTestCase.getHash()))
wrongHash = "Hash is incorrect in parsed transaction";
}
logger.info("--------- POST Validation---------");
List<String> results = new ArrayList<>();
ArrayList<String> outputSummary =
TransactionValidator.valid(transaction, expectedTransaction);
results.addAll(outputSummary);
if (acceptFail != null) results.add(acceptFail);
if (wrongSender != null) results.add(wrongSender);
if (wrongHash != null) results.add(wrongHash);
for (String result : results) {
logger.error(result);
}
logger.info("\n\n");
return results;
}
}