From b97b79c37ddbc270c8feedc3f3ccc4565bec28f0 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 27 May 2014 12:56:28 +0200 Subject: [PATCH] VM trace. --- CMakeLists.txt | 20 +++++++++++--- alethzero/Main.ui | 53 +++++++++++++++++++++++++----------- alethzero/MainWin.cpp | 5 ++-- alethzero/MainWin.h | 2 +- eth/eth.js | 16 +++++------ include.lll | 21 ++++++++++++--- libethereum/Executive.cpp | 57 +++++++++++++++++++++++++++++++++++++++ libethereum/State.cpp | 2 +- 8 files changed, 142 insertions(+), 34 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a219c65aa..307ff33eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,9 +7,9 @@ cmake_policy(SET CMP0015 NEW) # Default HEADLESS to 0. set(HEADLESS CACHE BOOL 0) -if ("x${HEADLESS}" STREQUAL "x") - set(HEADLESS 0) -endif () +#if ("x${HEADLESS}" STREQUAL "x") +# set(HEADLESS 0) +#endif () if ("x${PARANOIA}" STREQUAL "x") if ("x${CMAKE_BUILD_TYPE}" STREQUAL "xDebug") @@ -23,6 +23,18 @@ if (PARANOIA) add_definitions(-DETH_PARANOIA) endif () +if ("x${VMTRACE}" STREQUAL "x") + if ("x${CMAKE_BUILD_TYPE}" STREQUAL "xDebug") + set(VMTRACE 1) + else () + set(VMTRACE 0) + endif () +endif () + +if (VMTRACE) + add_definitions(-DETH_VMTRACE) +endif () + # Default TARGET_PLATFORM to "linux". set(TARGET_PLATFORM CACHE STRING "linux") if ("x${TARGET_PLATFORM}" STREQUAL "x") @@ -276,6 +288,6 @@ endif () enable_testing() add_test(NAME alltests WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/test COMMAND testeth) -unset(HEADLESS CACHE) +#unset(HEADLESS CACHE) #unset(TARGET_PLATFORM CACHE) diff --git a/alethzero/Main.ui b/alethzero/Main.ui index 5886554e3..de7f8e428 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -317,7 +317,10 @@ 8 - + + + 2 + 0 @@ -347,20 +350,40 @@ - - - 10 - - - 1 - - - Qt::Vertical - - - QSlider::TicksBothSides - - + + + + + 20 + + + 1 + + + Qt::Vertical + + + QSlider::TicksBothSides + + + + + + + + 20 + 0 + + + + 20 + + + Qt::AlignCenter + + + + diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index e32e7c335..4bf20b561 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -212,7 +212,7 @@ Main::Main(QWidget *parent) : ui->configDock->close(); - on_verbosity_sliderMoved(); + on_verbosity_valueChanged(); initUnits(ui->gasPriceUnits); initUnits(ui->valueUnits); ui->valueUnits->setCurrentIndex(6); @@ -995,9 +995,10 @@ void Main::on_connect_triggered() } } -void Main::on_verbosity_sliderMoved() +void Main::on_verbosity_valueChanged() { g_logVerbosity = ui->verbosity->value(); + ui->verbosityLabel->setText(QString::number(g_logVerbosity)); } void Main::on_mine_triggered() diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 9ce134bf1..057859de3 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -49,7 +49,7 @@ private slots: void on_send_clicked(); void on_create_triggered(); void on_net_triggered(); - void on_verbosity_sliderMoved(); + void on_verbosity_valueChanged(); void on_ourAccounts_doubleClicked(); void ourAccountsRowsMoved(); void on_accounts_doubleClicked(); diff --git a/eth/eth.js b/eth/eth.js index 2ea9b836c..02c6f4b8a 100644 --- a/eth/eth.js +++ b/eth/eth.js @@ -77,15 +77,15 @@ window.eth = (function ethScope() { }; if (m == "create" || m == "transact") ret[m] = function() { return reqAsync(m, getParams(arguments), arguments[s.order.length]) } - else - { - ret[am] = function() { return reqAsync(m, getParams(arguments), arguments[s.order.length]) } - if (s.params) - ret[m] = function() { return reqSync(m, getParams(arguments)) } + else + { + ret[am] = function() { return reqAsync(m, getParams(arguments), arguments[s.order.length]) } + if (s.params) + ret[m] = function() { return reqSync(m, getParams(arguments)) } else - Object.defineProperty(ret, m, { - get: function() { return reqSync(m, {}); }, - set: function(v) {} + Object.defineProperty(ret, m, { + get: function() { return reqSync(m, {}); }, + set: function(v) {} }) } })(spec[si]); diff --git a/include.lll b/include.lll index ea196b123..857def4d4 100644 --- a/include.lll +++ b/include.lll @@ -1,7 +1,22 @@ { (def 'gav 0x8a40bfaa73256b60764c1bf40675a99083efb075) + +(def 'alloc (len) (asm msize 0 1 len msize add sub mstore8)) + (def 'send (to value) (call (- (gas) 21) to value 0 0 0 0)) -(def 'makevar (name pos) { (def name (sload pos)) (def name (v) (sstore pos v)) } ) -(def 'varcount 0) -(def 'var (name) { (makevar name varcount) (def 'varcount (+ varcount 1)) } ) +(def 'send (gaslimit to value) (call gaslimit to value 0 0 0 0)) +(def 'msg (gaslimit to value data datasize outsize) { [32]:outsize [0]:(alloc @32) (call gaslimit to value data datasize @0 @32) @0 }) +(def 'msg (gaslimit to value data datasize) { (call gaslimit to value data datasize 0 32) @0 }) +(def 'msg (gaslimit to value data) { [0] data (msg gaslimit to value 0 32) }) +(def 'create (to value code) { [0]:(msize) (create to value @0 (lll code @0) }) + +(def 'sha3 (val) { [0]:val (sha3 0 32) }) +(def 'return (val) { [0]:val (return 0 32) }) + +(def 'makesvar (name pos) { (def name (sload pos)) (def name (v) (sstore pos v)) } ) +(def 'svarcount 0) +(def 'svar (name) { (makesvar name svarcount) (def 'svarcount (+ svarcount 1)) } ) +(def 'makevar (name pos) { (def name (mload pos)) (def name (v) (mstore pos v)) } ) +(def 'varcount 128) ;; Allow 4 x 32 byte slots for us to use. +(def 'var (name) { (makevar name varcount) (def 'varcount (+ varcount 32)) } ) } diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index cd29941b0..49af0eaaa 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -120,6 +120,39 @@ void Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g m_ext = new ExtVM(m_s, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init); } +struct VMTraceChannel: public LogChannel { static const char* name() { return "EVM"; } static const int verbosity = 11; }; + +string memDump(bytes const& _b, unsigned _w = 8, bool _html = false) +{ + stringstream ret; + if (_html) + ret << "
";
+	for (unsigned i = 0; i < _b.size(); i += _w)
+	{
+		ret << hex << setw(4) << setfill('0') << i << " ";
+		for (unsigned j = i; j < i + _w; ++j)
+			if (j < _b.size())
+				if (_b[j] >= 32 && _b[j] < 128)
+					if ((char)_b[j] == '<' && _html)
+						ret << "<";
+					else if ((char)_b[j] == '&' && _html)
+						ret << "&";
+					else
+						ret << (char)_b[j];
+				else
+					ret << '?';
+			else
+				ret << ' ';
+		ret << " ";
+		for (unsigned j = i; j < i + _w && j < _b.size(); ++j)
+			ret << setfill('0') << setw(2) << hex << (unsigned)_b[j] << " ";
+		ret << "\n";
+	}
+	if (_html)
+		ret << "
"; + return ret.str(); +} + bool Executive::go(uint64_t _steps) { if (m_vm) @@ -127,7 +160,31 @@ bool Executive::go(uint64_t _steps) bool revert = false; try { +#if ETH_VMTRACE + for (uint64_t s = 0;; ++s) + { + ostringstream o; + o << endl << " STACK" << endl; + for (auto i: vm().stack()) + o << (h256)i << endl; + o << " MEMORY" << endl << memDump(vm().memory()); + o << " STORAGE" << endl; + for (auto const& i: state().storage(ext().myAddress)) + o << showbase << hex << i.first << ": " << i.second << endl; + eth::LogOutputStream(true) << o.str(); + eth::LogOutputStream(false) << dec << " | #" << s << " | " << hex << setw(4) << setfill('0') << vm().curPC() << " : " << c_instructionInfo.at((Instruction)ext().getCode(vm().curPC())).name << " | " << dec << vm().gas() << " ]"; + if (s >= _steps) + break; + try + { + m_out = m_vm->go(*m_ext, 1); + break; + } + catch (StepsDone const&) {} + } +#else m_out = m_vm->go(*m_ext, _steps); +#endif m_endGas = m_vm->gas(); } catch (StepsDone const&) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index fa70dde24..a3314ccee 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -267,7 +267,7 @@ bool State::sync(BlockChain const& _bc, h256 _block) { auto b = _bc.block(_block); bi.populate(b); - bi.verifyInternals(_bc.block(_block)); +// bi.verifyInternals(_bc.block(_block)); // Unneeded - we already verify on import into the blockchain. } catch (...) {