diff --git a/alethzero/Debugger.cpp b/alethzero/Debugger.cpp
index 93d6b1f6a..371630456 100644
--- a/alethzero/Debugger.cpp
+++ b/alethzero/Debugger.cpp
@@ -67,7 +67,8 @@ void Debugger::populate(dev::eth::Executive& _executive, dev::eth::Transaction c
bool DebugSession::populate(dev::eth::Executive& _executive, dev::eth::Transaction const& _transaction)
{
try {
- if (_executive.setup(_transaction))
+ _executive.initialize(_transaction);
+ if (_executive.execute())
return false;
}
catch (...)
diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index 712318442..1784fbf96 100644
--- a/alethzero/MainWin.cpp
+++ b/alethzero/MainWin.cpp
@@ -1122,7 +1122,7 @@ void Main::refreshBlockChain()
blocks.insert(bc.numberHash(b));
}
else if (f.toLongLong() <= bc.number())
- blocks.insert(bc.numberHash(u256(f.toLongLong())));
+ blocks.insert(bc.numberHash((unsigned)f.toLongLong()));
else if (f.size() == 40)
{
Address h(f.toStdString());
@@ -1385,7 +1385,7 @@ void Main::on_transactionQueue_currentItemChanged()
if (!!receipt.bloom())
s << "
Log Bloom: " << receipt.bloom() << "
";
else
- s << "Log Bloom: Uneventful
";
+ s << "Log Bloom: Uneventful
";
auto r = receipt.rlp();
s << "Receipt: " << toString(RLP(r)) << "
";
s << "Receipt-Hex: " Span(Mono) << toHex(receipt.rlp()) << "
";
@@ -1484,7 +1484,7 @@ void Main::on_blocks_currentItemChanged()
if (!!info.logBloom)
s << "Log Bloom: " << info.logBloom << "
";
else
- s << "Log Bloom: Uneventful
";
+ s << "Log Bloom: Uneventful
";
s << "Transactions: " << block[1].itemCount() << " @" << info.transactionsRoot << "" << "
";
s << "Uncles: " << block[2].itemCount() << " @" << info.sha3Uncles << "" << "
";
for (auto u: block[2])
diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp
index 534f18a69..6f52548c7 100644
--- a/alethzero/Transact.cpp
+++ b/alethzero/Transact.cpp
@@ -316,7 +316,7 @@ void Transact::rejigData()
return;
}
else
- gasNeeded = min((qint64)ethereum()->gasLimitRemaining(), (qint64)((b - value()) / gasPrice()));
+ gasNeeded = (qint64)min(ethereum()->gasLimitRemaining(), ((b - value()) / gasPrice()));
// Dry-run execution to determine gas requirement and any execution errors
Address to;
@@ -326,7 +326,7 @@ void Transact::rejigData()
else
{
to = m_context->fromString(ui->destination->currentText());
- er = ethereum()->call(s, value(), to, m_data, ethereum()->gasLimitRemaining(), gasPrice());
+ er = ethereum()->call(s, value(), to, m_data, gasNeeded, gasPrice());
}
gasNeeded = (qint64)(er.gasUsed + er.gasRefunded);
htmlInfo = QString("INFO Gas required: %1 total = %2 base, %3 exec [%4 refunded later]
").arg(gasNeeded).arg(baseGas).arg(gasNeeded - baseGas).arg((qint64)er.gasRefunded) + htmlInfo;
diff --git a/eth/main.cpp b/eth/main.cpp
index 206a6df57..2a065cc8c 100644
--- a/eth/main.cpp
+++ b/eth/main.cpp
@@ -835,11 +835,8 @@ int main(int argc, char** argv)
Executive e(state, c->blockChain(), 0);
Transaction t = state.pending()[index];
state = state.fromPending(index);
- bytes r = t.rlp();
try
{
- e.setup(&r);
-
OnOpFunc oof;
if (format == "pretty")
oof = [&](uint64_t steps, Instruction instr, bigint newMemSize, bigint gasCost, dev::eth::VM* vvm, dev::eth::ExtVMFace const* vextVM)
@@ -872,7 +869,9 @@ int main(int argc, char** argv)
f << toHex(dev::toCompactBigEndian(i.first, 1)) << " " << toHex(dev::toCompactBigEndian(i.second, 1)) << endl;
f << ext->myAddress << " " << hex << toHex(dev::toCompactBigEndian(vm->curPC(), 1)) << " " << hex << toHex(dev::toCompactBigEndian((int)(byte)instr, 1)) << " " << hex << toHex(dev::toCompactBigEndian((uint64_t)vm->gas(), 1)) << endl;
};
- e.go(oof);
+ e.initialize(t);
+ if (!e.execute())
+ e.go(oof);
e.finalize();
}
catch(Exception const& _e)
diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp
index f80680f38..688a0c326 100644
--- a/libethereum/BlockChain.cpp
+++ b/libethereum/BlockChain.cpp
@@ -63,7 +63,7 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, BlockChain const& _bc)
return _out;
}
-ldb::Slice dev::eth::toSlice(h256 _h, unsigned _sub)
+ldb::Slice dev::eth::toSlice(h256 const& _h, unsigned _sub)
{
#if ALL_COMPILERS_ARE_CPP11_COMPLIANT
static thread_local h256 h = _h ^ sha3(h256(u256(_sub)));
@@ -184,6 +184,19 @@ inline string toString(h256s const& _bs)
return out.str();
}
+LastHashes BlockChain::lastHashes(unsigned _n) const
+{
+ Guard l(x_lastLastHashes);
+ if (m_lastLastHashesNumber != _n || m_lastLastHashes.empty())
+ {
+ m_lastLastHashes.resize(256);
+ for (unsigned i = 0; i < 256; ++i)
+ m_lastLastHashes[i] = _n >= i ? numberHash(_n - i) : h256();
+ m_lastLastHashesNumber = _n;
+ }
+ return m_lastLastHashes;
+}
+
h256s BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max)
{
_bq.tick(*this);
@@ -412,6 +425,9 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db)
WriteGuard l(x_lastBlockHash);
m_lastBlockHash = newHash;
}
+
+ noteCanonChanged();
+
m_extrasDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&newHash, 32));
clog(BlockChainNote) << " Imported and best" << td << ". Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << toString(ret);
StructuredLogger::chainNewHead(
@@ -428,7 +444,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db)
return ret;
}
-h256s BlockChain::treeRoute(h256 _from, h256 _to, h256* o_common, bool _pre, bool _post) const
+h256s BlockChain::treeRoute(h256 const& _from, h256 const& _to, h256* o_common, bool _pre, bool _post) const
{
// cdebug << "treeRoute" << _from.abridged() << "..." << _to.abridged();
if (!_from || !_to)
@@ -438,38 +454,40 @@ h256s BlockChain::treeRoute(h256 _from, h256 _to, h256* o_common, bool _pre, boo
unsigned fn = details(_from).number;
unsigned tn = details(_to).number;
// cdebug << "treeRoute" << fn << "..." << tn;
+ h256 from = _from;
while (fn > tn)
{
if (_pre)
- ret.push_back(_from);
- _from = details(_from).parent;
+ ret.push_back(from);
+ from = details(from).parent;
fn--;
// cdebug << "from:" << fn << _from.abridged();
}
+ h256 to = _to;
while (fn < tn)
{
if (_post)
- back.push_back(_to);
- _to = details(_to).parent;
+ back.push_back(to);
+ to = details(to).parent;
tn--;
// cdebug << "to:" << tn << _to.abridged();
}
- while (_from != _to)
+ while (from != to)
{
- assert(_from);
- assert(_to);
- _from = details(_from).parent;
- _to = details(_to).parent;
+ assert(from);
+ assert(to);
+ from = details(from).parent;
+ to = details(to).parent;
if (_pre)
- ret.push_back(_from);
+ ret.push_back(from);
if (_post)
- back.push_back(_to);
+ back.push_back(to);
fn--;
tn--;
// cdebug << "from:" << fn << _from.abridged() << "; to:" << tn << _to.abridged();
}
if (o_common)
- *o_common = _from;
+ *o_common = from;
ret.reserve(ret.size() + back.size());
for (auto it = back.cbegin(); it != back.cend(); ++it)
ret.push_back(*it);
@@ -677,7 +695,7 @@ vector BlockChain::withBlockBloom(LogBloom const& _b, unsigned _earlie
return ret;
}
-h256Set BlockChain::allUnclesFrom(h256 _parent) const
+h256Set BlockChain::allUnclesFrom(h256 const& _parent) const
{
// Get all uncles cited given a parent (i.e. featured as uncles/main in parent, parent + 1, ... parent + 5).
h256Set ret;
@@ -692,7 +710,7 @@ h256Set BlockChain::allUnclesFrom(h256 _parent) const
return ret;
}
-bool BlockChain::isKnown(h256 _hash) const
+bool BlockChain::isKnown(h256 const& _hash) const
{
if (_hash == m_genesisHash)
return true;
@@ -706,7 +724,7 @@ bool BlockChain::isKnown(h256 _hash) const
return !!d.size();
}
-bytes BlockChain::block(h256 _hash) const
+bytes BlockChain::block(h256 const& _hash) const
{
if (_hash == m_genesisHash)
return m_genesisBlock;
diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h
index 235a39267..03c0fdcfd 100644
--- a/libethereum/BlockChain.h
+++ b/libethereum/BlockChain.h
@@ -30,9 +30,10 @@
#include
#include
#include
+#include
#include
#include
-#include
+#include
#include "BlockDetails.h"
#include "Account.h"
#include "Transaction.h"
@@ -61,7 +62,7 @@ struct BlockChainNote: public LogChannel { static const char* name() { return "=
// TODO: Move all this Genesis stuff into Genesis.h/.cpp
std::map const& genesisState();
-ldb::Slice toSlice(h256 _h, unsigned _sub = 0);
+ldb::Slice toSlice(h256 const& _h, unsigned _sub = 0);
using BlocksHash = std::map;
using TransactionHashes = h256s;
@@ -105,37 +106,42 @@ public:
h256s import(bytes const& _block, OverlayDB const& _stateDB);
/// Returns true if the given block is known (though not necessarily a part of the canon chain).
- bool isKnown(h256 _hash) const;
+ bool isKnown(h256 const& _hash) const;
/// Get the familial details concerning a block (or the most recent mined if none given). Thread-safe.
- BlockInfo info(h256 _hash) const { return BlockInfo(block(_hash)); }
+ BlockInfo info(h256 const& _hash) const { return BlockInfo(block(_hash)); }
BlockInfo info() const { return BlockInfo(block()); }
/// Get a block (RLP format) for the given hash (or the most recent mined if none given). Thread-safe.
- bytes block(h256 _hash) const;
+ bytes block(h256 const& _hash) const;
bytes block() const { return block(currentHash()); }
/// Get the familial details concerning a block (or the most recent mined if none given). Thread-safe.
- BlockDetails details(h256 _hash) const { return queryExtras(_hash, m_details, x_details, NullBlockDetails); }
+ BlockDetails details(h256 const& _hash) const { return queryExtras(_hash, m_details, x_details, NullBlockDetails); }
BlockDetails details() const { return details(currentHash()); }
/// Get the transactions' log blooms of a block (or the most recent mined if none given). Thread-safe.
- BlockLogBlooms logBlooms(h256 _hash) const { return queryExtras(_hash, m_logBlooms, x_logBlooms, NullBlockLogBlooms); }
+ BlockLogBlooms logBlooms(h256 const& _hash) const { return queryExtras(_hash, m_logBlooms, x_logBlooms, NullBlockLogBlooms); }
BlockLogBlooms logBlooms() const { return logBlooms(currentHash()); }
/// Get the transactions' receipts of a block (or the most recent mined if none given). Thread-safe.
- BlockReceipts receipts(h256 _hash) const { return queryExtras(_hash, m_receipts, x_receipts, NullBlockReceipts); }
+ BlockReceipts receipts(h256 const& _hash) const { return queryExtras(_hash, m_receipts, x_receipts, NullBlockReceipts); }
BlockReceipts receipts() const { return receipts(currentHash()); }
/// Get a list of transaction hashes for a given block. Thread-safe.
- TransactionHashes transactionHashes(h256 _hash) const { auto b = block(_hash); RLP rlp(b); h256s ret; for (auto t: rlp[1]) ret.push_back(sha3(t.data())); return ret; }
+ TransactionHashes transactionHashes(h256 const& _hash) const { auto b = block(_hash); RLP rlp(b); h256s ret; for (auto t: rlp[1]) ret.push_back(sha3(t.data())); return ret; }
TransactionHashes transactionHashes() const { return transactionHashes(currentHash()); }
/// Get a list of uncle hashes for a given block. Thread-safe.
- UncleHashes uncleHashes(h256 _hash) const { auto b = block(_hash); RLP rlp(b); h256s ret; for (auto t: rlp[2]) ret.push_back(sha3(t.data())); return ret; }
+ UncleHashes uncleHashes(h256 const& _hash) const { auto b = block(_hash); RLP rlp(b); h256s ret; for (auto t: rlp[2]) ret.push_back(sha3(t.data())); return ret; }
UncleHashes uncleHashes() const { return uncleHashes(currentHash()); }
- h256 numberHash(u256 _index) const { if (!_index) return genesisHash(); return queryExtras(h256(_index), m_blockHashes, x_blockHashes, NullBlockHash).value; }
+ /// Get the hash for a given block's number.
+ h256 numberHash(unsigned _i) const { if (!_i) return genesisHash(); return queryExtras(h256(u256(_i)), m_blockHashes, x_blockHashes, NullBlockHash).value; }
+
+ /// Get the last N hashes for a given block. (N is determined by the LastHashes type.)
+ LastHashes lastHashes() const { return lastHashes(number()); }
+ LastHashes lastHashes(unsigned _i) const;
/** Get the block blooms for a number of blocks. Thread-safe.
* @returns the object pertaining to the blocks:
@@ -158,15 +164,15 @@ public:
std::vector withBlockBloom(LogBloom const& _b, unsigned _earliest, unsigned _latest, unsigned _topLevel, unsigned _index) const;
/// Get a transaction from its hash. Thread-safe.
- bytes transaction(h256 _transactionHash) const { TransactionAddress ta = queryExtras(_transactionHash, m_transactionAddresses, x_transactionAddresses, NullTransactionAddress); if (!ta) return bytes(); return transaction(ta.blockHash, ta.index); }
- std::pair transactionLocation(h256 _transactionHash) const { TransactionAddress ta = queryExtras(_transactionHash, m_transactionAddresses, x_transactionAddresses, NullTransactionAddress); if (!ta) return std::pair(h256(), 0); return std::make_pair(ta.blockHash, ta.index); }
+ bytes transaction(h256 const& _transactionHash) const { TransactionAddress ta = queryExtras(_transactionHash, m_transactionAddresses, x_transactionAddresses, NullTransactionAddress); if (!ta) return bytes(); return transaction(ta.blockHash, ta.index); }
+ std::pair transactionLocation(h256 const& _transactionHash) const { TransactionAddress ta = queryExtras(_transactionHash, m_transactionAddresses, x_transactionAddresses, NullTransactionAddress); if (!ta) return std::pair(h256(), 0); return std::make_pair(ta.blockHash, ta.index); }
/// Get a block's transaction (RLP format) for the given block hash (or the most recent mined if none given) & index. Thread-safe.
- bytes transaction(h256 _blockHash, unsigned _i) const { bytes b = block(_blockHash); return RLP(b)[1][_i].data().toBytes(); }
+ bytes transaction(h256 const& _blockHash, unsigned _i) const { bytes b = block(_blockHash); return RLP(b)[1][_i].data().toBytes(); }
bytes transaction(unsigned _i) const { return transaction(currentHash(), _i); }
/// Get a number for the given hash (or the most recent mined if none given). Thread-safe.
- unsigned number(h256 _hash) const { return details(_hash).number; }
+ unsigned number(h256 const& _hash) const { return details(_hash).number; }
unsigned number() const { return number(currentHash()); }
/// Get a given block (RLP format). Thread-safe.
@@ -178,7 +184,7 @@ public:
/// Get all blocks not allowed as uncles given a parent (i.e. featured as uncles/main in parent, parent + 1, ... parent + 5).
/// @returns set including the header-hash of every parent (including @a _parent) up to and including generation +5
/// togther with all their quoted uncles.
- h256Set allUnclesFrom(h256 _parent) const;
+ h256Set allUnclesFrom(h256 const& _parent) const;
/** @returns the hash of all blocks between @a _from and @a _to, all blocks are ordered first by a number of
* blocks that are parent-to-child, then two sibling blocks, then a number of blocks that are child-to-parent.
@@ -194,7 +200,7 @@ public:
* treeRoute(1b, 2a) == { 1b, 1a, 2a }; // *o_common == g
* @endcode
*/
- h256s treeRoute(h256 _from, h256 _to, h256* o_common = nullptr, bool _pre = true, bool _post = true) const;
+ h256s treeRoute(h256 const& _from, h256 const& _to, h256* o_common = nullptr, bool _pre = true, bool _post = true) const;
struct Statistics
{
@@ -219,7 +225,7 @@ private:
void open(std::string _path, bool _killExisting = false);
void close();
- template T queryExtras(h256 _h, std::map& _m, boost::shared_mutex& _x, T const& _n) const
+ template T queryExtras(h256 const& _h, std::map& _m, boost::shared_mutex& _x, T const& _n) const
{
{
ReadGuard l(_x);
@@ -268,6 +274,11 @@ private:
void noteUsed(h256 const& _h, unsigned _extra = (unsigned)-1) const;
std::chrono::system_clock::time_point m_lastCollection;
+ void noteCanonChanged() const { Guard l(x_lastLastHashes); m_lastLastHashes.clear(); }
+ mutable Mutex x_lastLastHashes;
+ mutable LastHashes m_lastLastHashes;
+ mutable unsigned m_lastLastHashesNumber = (unsigned)-1;
+
void updateStats() const;
mutable Statistics m_lastStats;
diff --git a/libethereum/Client.h b/libethereum/Client.h
index 5fb30b8f0..1091bba58 100644
--- a/libethereum/Client.h
+++ b/libethereum/Client.h
@@ -110,7 +110,7 @@ public:
private:
u256 m_weiPerRef;
u256 m_refsPerBlock;
- u256 m_gasPerBlock = 1000000;
+ u256 m_gasPerBlock = 3141592;
std::array m_octiles;
};
diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp
index df30595b6..b45b9cf27 100644
--- a/libethereum/ClientBase.cpp
+++ b/libethereum/ClientBase.cpp
@@ -73,7 +73,7 @@ ExecutionResult ClientBase::call(Secret _secret, u256 _value, Address _dest, byt
State temp = asOf(_blockNumber);
u256 n = temp.transactionsFrom(toAddress(_secret));
Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret);
- ret = temp.execute(bc(), t.rlp(), Permanence::Reverted);
+ ret = temp.execute(bc().lastHashes(), t, Permanence::Reverted);
}
catch (...)
{
@@ -92,7 +92,7 @@ ExecutionResult ClientBase::create(Secret _secret, u256 _value, bytes const& _da
// cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret));
Transaction t(_value, _gasPrice, _gas, _data, n, _secret);
- ret = temp.execute(bc(), t.rlp(), Permanence::Reverted);
+ ret = temp.execute(bc().lastHashes(), t, Permanence::Reverted);
}
catch (...)
{
diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp
index 7dfc51b47..5bc42540f 100644
--- a/libethereum/EthereumHost.cpp
+++ b/libethereum/EthereumHost.cpp
@@ -178,7 +178,7 @@ void EthereumHost::maintainTransactions()
for (auto const& i: m_tq.transactions())
if (ep->m_requireTransactions || (!m_transactionsSent.count(i.first) && !ep->m_knownTransactions.count(i.first)))
{
- b += i.second;
+ b += i.second.rlp();
++n;
m_transactionsSent.insert(i.first);
}
diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp
index c574fa650..dfd526bef 100644
--- a/libethereum/Executive.cpp
+++ b/libethereum/Executive.cpp
@@ -35,7 +35,7 @@ using namespace dev::eth;
Executive::Executive(State& _s, BlockChain const& _bc, unsigned _level):
m_s(_s),
- m_lastHashes(_s.getLastHashes(_bc, (unsigned)_s.info().number - 1)),
+ m_lastHashes(_bc.lastHashes((unsigned)_s.info().number - 1)),
m_depth(_level)
{}
@@ -55,12 +55,33 @@ void Executive::accrueSubState(SubState& _parentContext)
_parentContext += m_ext->sub;
}
-bool Executive::setup(bytesConstRef _rlp)
+void Executive::initialize(Transaction const& _transaction)
{
- // Entry point for a user-executed transaction.
+ m_t = _transaction;
+
+ // Avoid transactions that would take us beyond the block gas limit.
+ u256 startGasUsed = m_s.gasUsed();
+ if (startGasUsed + (bigint)m_t.gas() > m_s.m_currentBlock.gasLimit)
+ {
+ clog(StateDetail) << "Too much gas used in this block: Require <" << (m_s.m_currentBlock.gasLimit - startGasUsed) << " Got" << m_t.gas();
+ m_excepted = TransactionException::BlockGasLimitReached;
+ BOOST_THROW_EXCEPTION(BlockGasLimitReached() << RequirementError((bigint)(m_s.m_currentBlock.gasLimit - startGasUsed), (bigint)m_t.gas()));
+ }
+
+ // Check gas cost is enough.
+ m_gasRequired = Interface::txGas(m_t.data());
+ if (m_t.gas() < m_gasRequired)
+ {
+ clog(StateDetail) << "Not enough gas to pay for the transaction: Require >" << m_gasRequired << " Got" << m_t.gas();
+ m_excepted = TransactionException::OutOfGas;
+ BOOST_THROW_EXCEPTION(OutOfGas() << RequirementError((bigint)m_gasRequired, (bigint)m_t.gas()));
+ }
+
+ // Avoid invalid transactions.
+ u256 nonceReq;
try
{
- m_t = Transaction(_rlp, CheckSignature::Sender);
+ nonceReq = m_s.transactionsFrom(m_t.sender());
}
catch (...)
{
@@ -68,15 +89,6 @@ bool Executive::setup(bytesConstRef _rlp)
m_excepted = TransactionException::InvalidSignature;
throw;
}
- return setup();
-}
-
-bool Executive::setup()
-{
- // Entry point for a user-executed transaction.
-
- // Avoid invalid transactions.
- auto nonceReq = m_s.transactionsFrom(m_t.sender());
if (m_t.nonce() != nonceReq)
{
clog(StateDetail) << "Invalid Nonce: Require" << nonceReq << " Got" << m_t.nonce();
@@ -84,46 +96,32 @@ bool Executive::setup()
BOOST_THROW_EXCEPTION(InvalidNonce() << RequirementError((bigint)nonceReq, (bigint)m_t.nonce()));
}
- // Check gas cost is enough.
- auto gasRequired = Interface::txGas(m_t.data());
-
- if (m_t.gas() < gasRequired)
- {
- clog(StateDetail) << "Not enough gas to pay for the transaction: Require >" << gasRequired << " Got" << m_t.gas();
- m_excepted = TransactionException::OutOfGas;
- BOOST_THROW_EXCEPTION(OutOfGas() << RequirementError((bigint)gasRequired, (bigint)m_t.gas()));
- }
-
- bigint gasCost = (bigint)m_t.gas() * m_t.gasPrice();
- bigint totalCost = m_t.value() + gasCost;
-
// Avoid unaffordable transactions.
- if (m_s.balance(m_t.sender()) < totalCost)
+ m_gasCost = (bigint)m_t.gas() * m_t.gasPrice();
+ m_totalCost = m_t.value() + m_gasCost;
+ if (m_s.balance(m_t.sender()) < m_totalCost)
{
- clog(StateDetail) << "Not enough cash: Require >" << totalCost << " Got" << m_s.balance(m_t.sender());
+ clog(StateDetail) << "Not enough cash: Require >" << m_totalCost << " Got" << m_s.balance(m_t.sender());
m_excepted = TransactionException::NotEnoughCash;
- BOOST_THROW_EXCEPTION(NotEnoughCash() << RequirementError(totalCost, (bigint)m_s.balance(m_t.sender())));
+ BOOST_THROW_EXCEPTION(NotEnoughCash() << RequirementError(m_totalCost, (bigint)m_s.balance(m_t.sender())));
}
+}
- u256 startGasUsed = m_s.gasUsed();
- if (startGasUsed + (bigint)m_t.gas() > m_s.m_currentBlock.gasLimit)
- {
- clog(StateDetail) << "Too much gas used in this block: Require <" << (m_s.m_currentBlock.gasLimit - startGasUsed) << " Got" << m_t.gas();
- m_excepted = TransactionException::BlockGasLimitReached;
- BOOST_THROW_EXCEPTION(BlockGasLimitReached() << RequirementError((bigint)(m_s.m_currentBlock.gasLimit - startGasUsed), (bigint)m_t.gas()));
- }
+bool Executive::execute()
+{
+ // Entry point for a user-executed transaction.
// Increment associated nonce for sender.
m_s.noteSending(m_t.sender());
// Pay...
- clog(StateDetail) << "Paying" << formatBalance(u256(gasCost)) << "from sender for gas (" << m_t.gas() << "gas at" << formatBalance(m_t.gasPrice()) << ")";
- m_s.subBalance(m_t.sender(), gasCost);
+ clog(StateDetail) << "Paying" << formatBalance(u256(m_gasCost)) << "from sender for gas (" << m_t.gas() << "gas at" << formatBalance(m_t.gasPrice()) << ")";
+ m_s.subBalance(m_t.sender(), m_gasCost);
if (m_t.isCreation())
- return create(m_t.sender(), m_t.value(), m_t.gasPrice(), m_t.gas() - (u256)gasRequired, &m_t.data(), m_t.sender());
+ return create(m_t.sender(), m_t.value(), m_t.gasPrice(), m_t.gas() - (u256)m_gasRequired, &m_t.data(), m_t.sender());
else
- return call(m_t.receiveAddress(), m_t.receiveAddress(), m_t.sender(), m_t.value(), m_t.gasPrice(), bytesConstRef(&m_t.data()), m_t.gas() - (u256)gasRequired, m_t.sender());
+ return call(m_t.receiveAddress(), m_t.receiveAddress(), m_t.sender(), m_t.value(), m_t.gasPrice(), bytesConstRef(&m_t.data()), m_t.gas() - (u256)m_gasRequired, m_t.sender());
}
bool Executive::call(Address _receiveAddress, Address _codeAddress, Address _senderAddress, u256 _value, u256 _gasPrice, bytesConstRef _data, u256 _gas, Address _originAddress)
diff --git a/libethereum/Executive.h b/libethereum/Executive.h
index eb0c27ad2..3445ad407 100644
--- a/libethereum/Executive.h
+++ b/libethereum/Executive.h
@@ -41,10 +41,21 @@ struct VMTraceChannel: public LogChannel { static const char* name() { return "E
* @brief Message-call/contract-creation executor; useful for executing transactions.
*
* Two ways of using this class - either as a transaction executive or a CALL/CREATE executive.
- * In the first use, after construction, begin with setup() and end with finalize(). Call go()
- * after setup() only if it returns false.
+ *
+ * In the first use, after construction, begin with initialize(), then execute() and end with finalize(). Call go()
+ * after execute() only if it returns false.
+ *
* In the second use, after construction, begin with call() or create() and end with
* accrueSubState(). Call go() after call()/create() only if it returns false.
+ *
+ * Example:
+ * @code
+ * Executive e(state, blockchain, 0);
+ * e.initialize(transaction);
+ * if (!e.execute())
+ * e.go();
+ * e.finalize();
+ * @endcode
*/
class Executive
{
@@ -59,17 +70,17 @@ public:
Executive(Executive const&) = delete;
void operator=(Executive) = delete;
- /// Set up the executive for evaluating a transaction. You must call finalize() following this.
- /// @returns true iff go() must be called (and thus a VM execution in required).
- bool setup(bytesConstRef _transaction);
- /// Set up the executive for evaluating a transaction. You must call finalize() following this.
- /// @returns true iff go() must be called (and thus a VM execution in required).
- bool setup(Transaction const& _transaction) { m_t = _transaction; return setup(); }
- /// Finalise a transaction previously set up with setup().
- /// @warning Only valid after setup(), and possibly go().
+ /// Initializes the executive for evaluating a transaction. You must call finalize() at some point following this.
+ void initialize(bytesConstRef _transaction) { initialize(Transaction(_transaction, CheckSignature::None)); }
+ void initialize(Transaction const& _transaction);
+ /// Finalise a transaction previously set up with initialize().
+ /// @warning Only valid after initialize() and execute(), and possibly go().
void finalize();
- /// @returns the transaction from setup().
- /// @warning Only valid after setup().
+ /// Begins execution of a transaction. You must call finalize() following this.
+ /// @returns true if the transaction is done, false if go() must be called.
+ bool execute();
+ /// @returns the transaction from initialize().
+ /// @warning Only valid after initialize().
Transaction const& t() const { return m_t; }
/// @returns the log entries created by this operation.
/// @warning Only valid after finalise().
@@ -107,8 +118,6 @@ public:
ExecutionResult executionResult() const;
private:
- bool setup();
-
State& m_s; ///< The state to which this operation/transaction is applied.
LastHashes m_lastHashes;
std::shared_ptr m_ext; ///< The VM externality object for the VM execution or null if no VM is required.
@@ -125,6 +134,10 @@ private:
Transaction m_t; ///< The original transaction. Set by setup().
LogEntries m_logs; ///< The log entries created by this transaction. Set by finalize().
+
+ bigint m_gasRequired;
+ bigint m_gasCost;
+ bigint m_totalCost;
};
}
diff --git a/libethereum/Interface.h b/libethereum/Interface.h
index 47fdb7250..529ddc093 100644
--- a/libethereum/Interface.h
+++ b/libethereum/Interface.h
@@ -71,11 +71,13 @@ public:
virtual void flushTransactions() = 0;
/// Makes the given call. Nothing is recorded into the state.
- virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = 0) = 0;
+ virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) = 0;
+ ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo) { return call(_secret, _value, _dest, _data, _gas, _gasPrice, m_default); }
/// Does the given creation. Nothing is recorded into the state.
/// @returns the pair of the Address of the created contract together with its code.
- virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = 0) = 0;
+ virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) = 0;
+ ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo) { return create(_secret, _value, _data, _gas, _gasPrice, m_default); }
// [STATE-QUERY API]
diff --git a/libethereum/State.cpp b/libethereum/State.cpp
index af3a4a223..9817e2bad 100644
--- a/libethereum/State.cpp
+++ b/libethereum/State.cpp
@@ -388,8 +388,7 @@ bool State::cull(TransactionQueue& _tq) const
{
try
{
- Transaction t(i.second, CheckSignature::Sender);
- if (t.nonce() <= transactionsFrom(t.sender()))
+ if (i.second.nonce() <= transactionsFrom(i.second.sender()))
{
_tq.drop(i.first);
ret = true;
@@ -411,7 +410,7 @@ TransactionReceipts State::sync(BlockChain const& _bc, TransactionQueue& _tq, Ga
TransactionReceipts ret;
auto ts = _tq.transactions();
- auto lh = getLastHashes(_bc, _bc.number());
+ LastHashes lh;
for (int goodTxs = 1; goodTxs;)
{
@@ -421,12 +420,11 @@ TransactionReceipts State::sync(BlockChain const& _bc, TransactionQueue& _tq, Ga
{
try
{
- if (Transaction(i.second, CheckSignature::Range).gasPrice() >= _gp.ask(*this))
+ if (i.second.gasPrice() >= _gp.ask(*this))
{
- Transaction t(i.second, CheckSignature::Sender);
- // don't have it yet! Execute it now.
- uncommitToMine();
// boost::timer t;
+ if (lh.empty())
+ lh = _bc.lastHashes();
execute(lh, i.second);
ret.push_back(m_receipts.back());
_tq.noteGood(i);
@@ -434,6 +432,7 @@ TransactionReceipts State::sync(BlockChain const& _bc, TransactionQueue& _tq, Ga
// cnote << "TX took:" << t.elapsed() * 1000;
}
}
+#if ETH_DEBUG
catch (InvalidNonce const& in)
{
bigint const* req = boost::get_error_info(in);
@@ -449,13 +448,19 @@ TransactionReceipts State::sync(BlockChain const& _bc, TransactionQueue& _tq, Ga
else
_tq.setFuture(i);
}
+ catch (BlockGasLimitReached const& e)
+ {
+ _tq.setFuture(i);
+ }
+#endif
catch (Exception const& _e)
{
// Something else went wrong - drop it.
_tq.drop(i.first);
if (o_transactionQueueChanged)
*o_transactionQueueChanged = true;
- cwarn << "Sync went wrong\n" << diagnostic_information(_e);
+ cnote << "Dropping invalid transaction:";
+ cnote << diagnostic_information(_e);
}
catch (std::exception const&)
{
@@ -463,6 +468,7 @@ TransactionReceipts State::sync(BlockChain const& _bc, TransactionQueue& _tq, Ga
_tq.drop(i.first);
if (o_transactionQueueChanged)
*o_transactionQueueChanged = true;
+ cnote << "Transaction caused low-level exception :(";
}
}
}
@@ -498,7 +504,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
GenericTrieDB receiptsTrie(&rm);
receiptsTrie.init();
- LastHashes lh = getLastHashes(_bc, (unsigned)m_previousBlock.number);
+ LastHashes lh = _bc.lastHashes((unsigned)m_previousBlock.number);
RLP rlp(_block);
// All ok with the block generally. Play back the transactions now...
@@ -509,7 +515,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
k << i;
transactionsTrie.insert(&k.out(), tr.data());
- execute(lh, tr.data());
+ execute(lh, Transaction(tr.data(), CheckSignature::Sender));
RLPStream receiptrlp;
m_receipts.back().streamRLP(receiptrlp);
@@ -1040,56 +1046,34 @@ bool State::isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const
return true;
}
-LastHashes State::getLastHashes(BlockChain const& _bc, unsigned _n) const
-{
- LastHashes ret;
- ret.resize(256);
- if (eth::c_protocolVersion > 49)
- {
- ret[0] = _bc.numberHash(_n);
- for (unsigned i = 1; i < 256; ++i)
- ret[i] = ret[i - 1] ? _bc.details(ret[i - 1]).parent : h256();
- }
- return ret;
-}
-
-ExecutionResult State::execute(BlockChain const& _bc, bytes const& _rlp, Permanence _p)
-{
- return execute(getLastHashes(_bc, _bc.number()), &_rlp, _p);
-}
-
-ExecutionResult State::execute(BlockChain const& _bc, bytesConstRef _rlp, Permanence _p)
+ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Permanence _p)
{
- return execute(getLastHashes(_bc, _bc.number()), _rlp, _p);
-}
-
-// TODO: maintain node overlay revisions for stateroots -> each commit gives a stateroot + OverlayDB; allow overlay copying for rewind operations.
-ExecutionResult State::execute(LastHashes const& _lh, bytesConstRef _rlp, Permanence _p)
-{
-#ifndef ETH_RELEASE
- commit(); // get an updated hash
-#endif
-
+#if ETH_PARANOIA
paranoia("start of execution.", true);
-
State old(*this);
-#if ETH_PARANOIA
auto h = rootHash();
#endif
+ // Create and initialize the executive. This will throw fairly cheaply and quickly if the
+ // transaction is bad in any way.
Executive e(*this, _lh, 0);
- e.setup(_rlp);
+ e.initialize(_t);
- u256 startGasUsed = gasUsed();
+ // Uncommitting is a non-trivial operation - only do it once we've verified as much of the
+ // transaction as possible.
+ uncommitToMine();
+ // OK - transaction looks valid - execute.
+ u256 startGasUsed = gasUsed();
#if ETH_PARANOIA
ctrace << "Executing" << e.t() << "on" << h;
ctrace << toHex(e.t().rlp());
#endif
+ if (!e.execute())
#if ETH_VMTRACE
- e.go(e.simpleTrace());
+ e.go(e.simpleTrace());
#else
- e.go();
+ e.go();
#endif
e.finalize();
diff --git a/libethereum/State.h b/libethereum/State.h
index ee88f443e..5ed76cc27 100644
--- a/libethereum/State.h
+++ b/libethereum/State.h
@@ -188,15 +188,9 @@ public:
/// Like sync but only operate on _tq, killing the invalid/old ones.
bool cull(TransactionQueue& _tq) const;
- /// Returns the last few block hashes of the current chain.
- LastHashes getLastHashes(BlockChain const& _bc, unsigned _n) const;
-
/// Execute a given transaction.
/// This will append @a _t to the transaction list and change the state accordingly.
- ExecutionResult execute(BlockChain const& _bc, bytes const& _rlp, Permanence _p = Permanence::Committed);
- ExecutionResult execute(BlockChain const& _bc, bytesConstRef _rlp, Permanence _p = Permanence::Committed);
- ExecutionResult execute(LastHashes const& _lh, bytes const& _rlp, Permanence _p = Permanence::Committed) { return execute(_lh, &_rlp, _p); }
- ExecutionResult execute(LastHashes const& _lh, bytesConstRef _rlp, Permanence _p = Permanence::Committed);
+ ExecutionResult execute(LastHashes const& _lh, Transaction const& _t, Permanence _p = Permanence::Committed);
/// Get the remaining gas limit in this block.
u256 gasLimitRemaining() const { return m_currentBlock.gasLimit - gasUsed(); }
diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp
index 5701fc4a5..803d320ee 100644
--- a/libethereum/TransactionQueue.cpp
+++ b/libethereum/TransactionQueue.cpp
@@ -46,7 +46,7 @@ bool TransactionQueue::import(bytesConstRef _transactionRLP)
UpgradeGuard ul(l);
// If valid, append to blocks.
- m_current[h] = _transactionRLP.toBytes();
+ m_current[h] = t;
m_known.insert(h);
}
catch (Exception const& _e)
@@ -63,20 +63,20 @@ bool TransactionQueue::import(bytesConstRef _transactionRLP)
return true;
}
-void TransactionQueue::setFuture(std::pair const& _t)
+void TransactionQueue::setFuture(std::pair const& _t)
{
WriteGuard l(m_lock);
if (m_current.count(_t.first))
{
m_current.erase(_t.first);
- m_unknown.insert(make_pair(Transaction(_t.second, CheckSignature::Sender).sender(), _t));
+ m_unknown.insert(make_pair(_t.second.sender(), _t));
}
}
-void TransactionQueue::noteGood(std::pair const& _t)
+void TransactionQueue::noteGood(std::pair const& _t)
{
WriteGuard l(m_lock);
- auto r = m_unknown.equal_range(Transaction(_t.second, CheckSignature::Sender).sender());
+ auto r = m_unknown.equal_range(_t.second.sender());
for (auto it = r.first; it != r.second; ++it)
m_current.insert(it->second);
m_unknown.erase(r.first, r.second);
diff --git a/libethereum/TransactionQueue.h b/libethereum/TransactionQueue.h
index b58944e4f..b104b98ca 100644
--- a/libethereum/TransactionQueue.h
+++ b/libethereum/TransactionQueue.h
@@ -25,6 +25,7 @@
#include
#include "libethcore/Common.h"
#include
+#include "Transaction.h"
namespace dev
{
@@ -46,19 +47,19 @@ public:
void drop(h256 _txHash);
- std::map transactions() const { ReadGuard l(m_lock); return m_current; }
+ std::map transactions() const { ReadGuard l(m_lock); return m_current; }
std::pair items() const { ReadGuard l(m_lock); return std::make_pair(m_current.size(), m_unknown.size()); }
- void setFuture(std::pair const& _t);
- void noteGood(std::pair const& _t);
+ void setFuture(std::pair const& _t);
+ void noteGood(std::pair const& _t);
void clear() { WriteGuard l(m_lock); m_known.clear(); m_current.clear(); m_unknown.clear(); }
private:
mutable boost::shared_mutex m_lock; ///< General lock.
std::set m_known; ///< Hashes of transactions in both sets.
- std::map m_current; ///< Map of SHA3(tx) to tx.
- std::multimap> m_unknown; ///< For transactions that have a future nonce; we map their sender address to the tx stuff, and insert once the sender has a valid TX.
+ std::map m_current; ///< Map of SHA3(tx) to tx.
+ std::multimap> m_unknown; ///< For transactions that have a future nonce; we map their sender address to the tx stuff, and insert once the sender has a valid TX.
};
}
diff --git a/libp2p/Network.cpp b/libp2p/Network.cpp
index 61028d458..5db2d8219 100644
--- a/libp2p/Network.cpp
+++ b/libp2p/Network.cpp
@@ -165,7 +165,7 @@ int Network::tcp4Listen(bi::tcp::acceptor& _acceptor, NetworkPreferences const&
return retport;
}
-bi::tcp::endpoint Network::traverseNAT(std::set const& _ifAddresses, unsigned short _listenPort, bi::address& o_upnpifaddr)
+bi::tcp::endpoint Network::traverseNAT(std::set const& _ifAddresses, unsigned short _listenPort, bi::address& o_upnpInterfaceAddr)
{
asserts(_listenPort != 0);
@@ -177,26 +177,26 @@ bi::tcp::endpoint Network::traverseNAT(std::set const& _ifAddresses
// let m_upnp continue as null - we handle it properly.
catch (...) {}
- bi::tcp::endpoint upnpep;
+ bi::tcp::endpoint upnpEP;
if (upnp && upnp->isValid())
{
- bi::address paddr;
+ bi::address pAddr;
int extPort = 0;
for (auto const& addr: _ifAddresses)
if (addr.is_v4() && isPrivateAddress(addr) && (extPort = upnp->addRedirect(addr.to_string().c_str(), _listenPort)))
{
- paddr = addr;
+ pAddr = addr;
break;
}
- auto eip = upnp->externalIP();
- bi::address eipaddr(bi::address::from_string(eip));
- if (extPort && eip != string("0.0.0.0") && !isPrivateAddress(eipaddr))
+ auto eIP = upnp->externalIP();
+ bi::address eIPAddr(bi::address::from_string(eIP));
+ if (extPort && eIP != string("0.0.0.0") && !isPrivateAddress(eIPAddr))
{
clog(NetNote) << "Punched through NAT and mapped local port" << _listenPort << "onto external port" << extPort << ".";
- clog(NetNote) << "External addr:" << eip;
- o_upnpifaddr = paddr;
- upnpep = bi::tcp::endpoint(eipaddr, (unsigned short)extPort);
+ clog(NetNote) << "External addr:" << eIP;
+ o_upnpInterfaceAddr = pAddr;
+ upnpEP = bi::tcp::endpoint(eIPAddr, (unsigned short)extPort);
}
else
clog(NetWarn) << "Couldn't punch through NAT (or no NAT in place).";
@@ -205,7 +205,7 @@ bi::tcp::endpoint Network::traverseNAT(std::set const& _ifAddresses
delete upnp;
}
- return upnpep;
+ return upnpEP;
}
bi::tcp::endpoint Network::resolveHost(string const& _addr)
diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp
index 19d946d01..7729c0ffe 100644
--- a/mix/MixClient.cpp
+++ b/mix/MixClient.cpp
@@ -112,7 +112,8 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c
State execState = _state;
Executive execution(execState, lastHashes, 0);
- execution.setup(&rlp);
+ execution.initialize(&rlp);
+ execution.execute();
std::vector machineStates;
std::vector levels;
std::vector codes;
@@ -184,7 +185,7 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c
// execute on a state
if (!_call)
{
- _state.execute(lastHashes, rlp);
+ _state.execute(lastHashes, _t);
if (_t.isCreation() && _state.code(d.contractAddress).empty())
BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Not enough gas for contract deployment"));
// collect watches
diff --git a/test/blockchain.cpp b/test/blockchain.cpp
index 50ca22c54..988859fe5 100644
--- a/test/blockchain.cpp
+++ b/test/blockchain.cpp
@@ -182,18 +182,17 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
Transactions txList;
for (auto const& txi: txs.transactions())
{
- Transaction tx(txi.second, CheckSignature::Sender);
- txList.push_back(tx);
+ txList.push_back(txi.second);
mObject txObject;
- txObject["nonce"] = toString(tx.nonce());
- txObject["data"] = "0x" + toHex(tx.data());
- txObject["gasLimit"] = toString(tx.gas());
- txObject["gasPrice"] = toString(tx.gasPrice());
- txObject["r"] = "0x" + toString(tx.signature().r);
- txObject["s"] = "0x" + toString(tx.signature().s);
- txObject["v"] = to_string(tx.signature().v + 27);
- txObject["to"] = tx.isCreation() ? "" : toString(tx.receiveAddress());
- txObject["value"] = toString(tx.value());
+ txObject["nonce"] = toString(txi.second.nonce());
+ txObject["data"] = "0x" + toHex(txi.second.data());
+ txObject["gasLimit"] = toString(txi.second.gas());
+ txObject["gasPrice"] = toString(txi.second.gasPrice());
+ txObject["r"] = "0x" + toString(txi.second.signature().r);
+ txObject["s"] = "0x" + toString(txi.second.signature().s);
+ txObject["v"] = to_string(txi.second.signature().v + 27);
+ txObject["to"] = txi.second.isCreation() ? "" : toString(txi.second.receiveAddress());
+ txObject["value"] = toString(txi.second.value());
txArray.push_back(txObject);
}
diff --git a/test/checkRandomStateTest.cpp b/test/checkRandomStateTest.cpp
index a4d390b16..49aca852f 100644
--- a/test/checkRandomStateTest.cpp
+++ b/test/checkRandomStateTest.cpp
@@ -83,12 +83,11 @@ bool doStateTest(mValue& _v)
ImportTest importer(o, false);
eth::State theState = importer.m_statePre;
- bytes tx = importer.m_transaction.rlp();
bytes output;
try
{
- output = theState.execute(lastHashes(importer.m_environment.currentBlock.number), tx).output;
+ output = theState.execute(lastHashes(importer.m_environment.currentBlock.number), importer.m_transaction).output;
}
catch (Exception const& _e)
{
diff --git a/test/createRandomStateTest.cpp b/test/createRandomStateTest.cpp
index f422d1717..5758598b9 100644
--- a/test/createRandomStateTest.cpp
+++ b/test/createRandomStateTest.cpp
@@ -183,12 +183,11 @@ void doStateTests(json_spirit::mValue& _v)
test::ImportTest importer(o, true);
eth::State theState = importer.m_statePre;
- bytes tx = importer.m_transaction.rlp();
bytes output;
try
{
- output = theState.execute(test::lastHashes(importer.m_environment.currentBlock.number), tx).output;
+ output = theState.execute(test::lastHashes(importer.m_environment.currentBlock.number), importer.m_transaction).output;
}
catch (Exception const& _e)
{
diff --git a/test/solidityExecutionFramework.h b/test/solidityExecutionFramework.h
index 86062a90b..2451aa381 100644
--- a/test/solidityExecutionFramework.h
+++ b/test/solidityExecutionFramework.h
@@ -142,7 +142,8 @@ protected:
try
{
// this will throw since the transaction is invalid, but it should nevertheless store the transaction
- executive.setup(&transactionRLP);
+ executive.initialize(&transactionRLP);
+ executive.execute();
}
catch (...) {}
if (_isCreation)
diff --git a/test/state.cpp b/test/state.cpp
index 4ab59f7a1..7c586ec7d 100644
--- a/test/state.cpp
+++ b/test/state.cpp
@@ -57,13 +57,12 @@ void doStateTests(json_spirit::mValue& v, bool _fillin)
ImportTest importer(o, _fillin);
State theState = importer.m_statePre;
- bytes tx = importer.m_transaction.rlp();
bytes output;
try
{
Listener::ExecTimeGuard guard{i.first};
- output = theState.execute(lastHashes(importer.m_environment.currentBlock.number), tx).output;
+ output = theState.execute(lastHashes(importer.m_environment.currentBlock.number), importer.m_transaction).output;
}
catch (Exception const& _e)
{
diff --git a/test/stateOriginal.cpp b/test/stateOriginal.cpp
index 5b7b0415e..384d85344 100644
--- a/test/stateOriginal.cpp
+++ b/test/stateOriginal.cpp
@@ -79,13 +79,9 @@ BOOST_AUTO_TEST_CASE(Complex)
cout << s;
// Inject a transaction to transfer funds from miner to me.
- bytes tx;
- {
- Transaction t(1000, 10000, 10000, me.address(), bytes(), s.transactionsFrom(myMiner.address()), myMiner.secret());
- assert(t.sender() == myMiner.address());
- tx = t.rlp();
- }
- s.execute(bc, tx);
+ Transaction t(1000, 10000, 10000, me.address(), bytes(), s.transactionsFrom(myMiner.address()), myMiner.secret());
+ assert(t.sender() == myMiner.address());
+ s.execute(bc.lastHashes(), t);
cout << s;