/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see .
*/
/** @file Transaction.h
* @author Gav Wood
* @date 2014
*/
#pragma once
#include
#include
#include
#include
#include
namespace dev
{
namespace eth
{
enum class TransactionException
{
None = 0,
Unknown,
BadRLP,
InvalidFormat,
OutOfGasIntrinsic, ///< Too little gas to pay for the base transaction cost.
InvalidSignature,
InvalidNonce,
NotEnoughCash,
OutOfGasBase, ///< Too little gas to pay for the base transaction cost.
BlockGasLimitReached,
BadInstruction,
BadJumpDestination,
OutOfGas, ///< Ran out of gas executing code of the transaction.
OutOfStack, ///< Ran out of stack executing code of the transaction.
StackUnderflow
};
enum class CodeDeposit
{
None = 0,
Failed,
Success
};
struct VMException;
TransactionException toTransactionException(Exception const& _e);
std::ostream& operator<<(std::ostream& _out, TransactionException const& _er);
/// Description of the result of executing a transaction.
struct ExecutionResult
{
u256 gasUsed = 0;
TransactionException excepted = TransactionException::Unknown;
Address newAddress;
bytes output;
CodeDeposit codeDeposit = CodeDeposit::None; ///< Failed if an attempted deposit failed due to lack of gas.
u256 gasRefunded = 0;
unsigned depositSize = 0; ///< Amount of code of the creation's attempted deposit.
u256 gasForDeposit; ///< Amount of gas remaining for the code deposit phase.
};
std::ostream& operator<<(std::ostream& _out, ExecutionResult const& _er);
/// Encodes a transaction, ready to be exported to or freshly imported from RLP.
class Transaction: public TransactionBase
{
public:
/// Constructs a null transaction.
Transaction() {}
/// Constructs from a transaction skeleton & optional secret.
Transaction(TransactionSkeleton const& _ts, Secret const& _s = Secret()): TransactionBase(_ts, _s) {}
/// Constructs a signed message-call transaction.
Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, Address const& _dest, bytes const& _data, u256 const& _nonce, Secret const& _secret):
TransactionBase(_value, _gasPrice, _gas, _dest, _data, _nonce, _secret)
{}
/// Constructs a signed contract-creation transaction.
Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, bytes const& _data, u256 const& _nonce, Secret const& _secret):
TransactionBase(_value, _gasPrice, _gas, _data, _nonce, _secret)
{}
/// Constructs an unsigned message-call transaction.
Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, Address const& _dest, bytes const& _data, u256 const& _nonce = UndefinedU256):
TransactionBase(_value, _gasPrice, _gas, _dest, _data, _nonce)
{}
/// Constructs an unsigned contract-creation transaction.
Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, bytes const& _data, u256 const& _nonce = UndefinedU256):
TransactionBase(_value, _gasPrice, _gas, _data, _nonce)
{}
/// Constructs a transaction from the given RLP.
explicit Transaction(bytesConstRef _rlp, CheckTransaction _checkSig);
/// Constructs a transaction from the given RLP.
explicit Transaction(bytes const& _rlp, CheckTransaction _checkSig): Transaction(&_rlp, _checkSig) {}
/// @returns true if the transaction contains enough gas for the basic payment.
bool checkPayment() const { return m_gas >= gasRequired(); }
/// @returns the gas required to run this transaction.
bigint gasRequired() const;
/// Get the fee associated for a transaction with the given data.
template static bigint gasRequired(T const& _data, u256 _gas = 0) { bigint ret = c_txGas + _gas; for (auto i: _data) ret += i ? c_txDataNonZeroGas : c_txDataZeroGas; return ret; }
private:
mutable bigint m_gasRequired = 0; ///< Memoised amount required for the transaction to run.
};
/// Nice name for vector of Transaction.
using Transactions = std::vector;
class LocalisedTransaction: public Transaction
{
public:
LocalisedTransaction(
Transaction const& _t,
h256 const& _blockHash,
unsigned _transactionIndex,
BlockNumber _blockNumber = 0
):
Transaction(_t),
m_blockHash(_blockHash),
m_transactionIndex(_transactionIndex),
m_blockNumber(_blockNumber)
{}
h256 const& blockHash() const { return m_blockHash; }
unsigned transactionIndex() const { return m_transactionIndex; }
BlockNumber blockNumber() const { return m_blockNumber; }
private:
h256 m_blockHash;
unsigned m_transactionIndex;
BlockNumber m_blockNumber;
};
}
}