From 31f1c73a188d649760d0075bd008bcb082e56e1c Mon Sep 17 00:00:00 2001 From: winsvega Date: Fri, 19 Dec 2014 01:57:21 +0300 Subject: [PATCH 01/18] Cteate Contract From Contract Init Code Test --- test/stInitCodeTestFiller.json | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/test/stInitCodeTestFiller.json b/test/stInitCodeTestFiller.json index 76d8f7957..1ac0a11ad 100644 --- a/test/stInitCodeTestFiller.json +++ b/test/stInitCodeTestFiller.json @@ -276,20 +276,19 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87": { "balance": "10000", "nonce": 0, - "code": "{[[ 2 ]](ADDRESS)(CODECOPY 0 0 32)(CREATE 0 0 32)}", + "code": "{(MSTORE 0 0x601080600c6000396000f20060003554156009570060203560003555) [[ 0 ]] (CREATE 23 4 28)}", "storage": {} - }, + }, - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "100000", - "code" : "", - "nonce" : "0", - "storage" : { - } - } + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance" : "100000", + "code" : "", + "nonce" : "0", + "storage" : {} + } }, "transaction" : - { + { "data" : "0x00", "gasLimit" : "10000", "gasPrice" : "1", From ae66da681c1196d4cefed4273bf065dff006a355 Mon Sep 17 00:00:00 2001 From: winsvega Date: Sat, 20 Dec 2014 19:12:52 +0300 Subject: [PATCH 02/18] Contract Creation Init Codes --- test/stInitCodeTestFiller.json | 188 ++++++++++++++++++++++++++++++--- 1 file changed, 175 insertions(+), 13 deletions(-) diff --git a/test/stInitCodeTestFiller.json b/test/stInitCodeTestFiller.json index 1ac0a11ad..55f5567af 100644 --- a/test/stInitCodeTestFiller.json +++ b/test/stInitCodeTestFiller.json @@ -262,11 +262,11 @@ } }, - "CallTheContractToCreateContractWithInitCode" : { + "CallContractToCreateContractWhichWouldCreateContractInInitCode" : { "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", "currentDifficulty" : "45678256", - "currentGasLimit" : "1000000", + "currentGasLimit" : "100000000", "currentNumber" : "0", "currentTimestamp" : 1, "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" @@ -274,28 +274,190 @@ "pre" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87": { - "balance": "10000", + "balance": "1", "nonce": 0, - "code": "{(MSTORE 0 0x601080600c6000396000f20060003554156009570060203560003555) [[ 0 ]] (CREATE 23 4 28)}", + "comment": "{[[0]] 12 (CREATE 0 64 32)}", + "code": "{(MSTORE 0 0x600c600055602060406000f0)(CREATE 0 20 12)}", "storage": {} - }, + }, - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance" : "100000", - "code" : "", - "nonce" : "0", - "storage" : {} - } + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000000", + "code" : "", + "nonce" : "0", + "storage" : { + } + } }, "transaction" : + { + "data" : "0x00", + "gasLimit" : "20000000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "0" + } + }, + + "CallContractToCreateContractWhichWouldCreateContractIfCalled" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "100000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87": { + "balance": "1000", + "nonce": 0, + "comment": "(CREATE 0 64 32)", + "comment": "{[[0]] 12 (MSTORE 32 0x602060406000f0)(RETURN 57 7)}", + "code": "{(MSTORE 0 0x600c60005566602060406000f060205260076039f3)[[0]](CREATE 1 11 21)(CALL 500 (SLOAD 0) 1 0 0 0 0)}", + "storage": {} + }, + + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000000", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { "data" : "0x00", - "gasLimit" : "10000", + "gasLimit" : "20000000", "gasPrice" : "1", "nonce" : "0", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", - "value" : "1" + "value" : "0" + } + }, + + "CallContractToCreateContractOOG" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "100000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "095e7baea6a6c7c4c2dfeb977efac326af552d87": { + "balance": "0", + "nonce": 0, + "comment": "(CREATE 0 64 32)", + "comment": "{[[0]] 12 (MSTORE 32 0x602060406000f0)(RETURN 57 7)}", + "code": "{(MSTORE 0 0x600c60005566602060406000f060205260076039f3)[[0]](CREATE 1 11 21)(CALL 0 (SLOAD 0) 0 0 0 0 0)}", + "storage": {} + }, + + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000000", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "0x00", + "gasLimit" : "20000000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "0" + } + }, + + "CallContractToCreateContractAndCallItOOG" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "100000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "095e7baea6a6c7c4c2dfeb977efac326af552d87": { + "balance": "1000", + "nonce": 0, + "comment": "(CREATE 0 64 32)", + "comment": "{[[0]] 12 (MSTORE 32 0x602060406000f0)(RETURN 57 7)}", + "code": "{(MSTORE 0 0x600c60005566602060406000f060205260076039f3)[[0]](CREATE 1 11 21)(CALL 0 (SLOAD 0) 1 0 0 0 0)}", + "storage": {} + }, + + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000000", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "0x00", + "gasLimit" : "20000000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "0" + } + }, + + "CallContractToCreateContractNoCash" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "100000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "095e7baea6a6c7c4c2dfeb977efac326af552d87": { + "balance": "1000", + "nonce": 0, + "comment": "(CREATE 0 64 32)", + "comment": "{[[0]] 12 (MSTORE 32 0x602060406000f0)(RETURN 57 7)}", + "code": "{(MSTORE 0 0x600c60005566602060406000f060205260076039f3)[[0]](CREATE 1001 11 21)}", + "storage": {} + }, + + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000000", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "0x00", + "gasLimit" : "20000000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "0" } } } From 1174c7168dc08be1b574807b499fcc4502f7c135 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 22 Dec 2014 17:24:06 +0100 Subject: [PATCH 03/18] Update evmjit --- evmjit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evmjit b/evmjit index 1b490244b..66d5a2b5c 160000 --- a/evmjit +++ b/evmjit @@ -1 +1 @@ -Subproject commit 1b490244bf4864b96448d56a7cd20f3d5b0a0b9b +Subproject commit 66d5a2b5cdf1361dcf0205b191dd12be090ed224 From fd61f9f45280b71b0e272e71587ddd39dfdc7f8d Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 22 Dec 2014 17:24:38 +0100 Subject: [PATCH 04/18] git ignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index c18d5a01d..6fde7ca22 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,5 @@ profile DerivedData project.pbxproj + +evmjit From 2aa1933b1b9ac7b94231da291a2d8d010bb6a6fc Mon Sep 17 00:00:00 2001 From: wanderer Date: Mon, 22 Dec 2014 23:58:04 -0500 Subject: [PATCH 05/18] added stackUnder Flow test --- test/stInitCodeTestFiller.json | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/stInitCodeTestFiller.json b/test/stInitCodeTestFiller.json index 76d8f7957..52f674098 100644 --- a/test/stInitCodeTestFiller.json +++ b/test/stInitCodeTestFiller.json @@ -92,6 +92,36 @@ "value" : "1" } }, + "StackUnderFlowContractCreation" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "0x6000f1", + "gasLimit" : "1000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "", + "value" : "0" + } + }, "TransactionSuicideInitCode" : { "env" : { From 74b085efea90dbce18a7320ff05cda0de0bd99d5 Mon Sep 17 00:00:00 2001 From: Joris Bontje Date: Tue, 23 Dec 2014 15:03:57 +0100 Subject: [PATCH 06/18] use Ethereum PPA for cryptopp and jsonrpc dependencies --- docker/Dockerfile | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index c183f03b9..9c76549cb 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -7,6 +7,7 @@ RUN apt-get upgrade -y # Ethereum dependencies RUN apt-get install -qy build-essential g++-4.8 git cmake libboost-all-dev libcurl4-openssl-dev wget RUN apt-get install -qy automake unzip libgmp-dev libtool libleveldb-dev yasm libminiupnpc-dev libreadline-dev scons +RUN apt-get install -qy libjsoncpp-dev libargtable2-dev # NCurses based GUI (not optional though for a succesful compilation, see https://github.com/ethereum/cpp-ethereum/issues/452 ) RUN apt-get install -qy libncurses5-dev @@ -14,15 +15,11 @@ RUN apt-get install -qy libncurses5-dev # Qt-based GUI # RUN apt-get install -qy qtbase5-dev qt5-default qtdeclarative5-dev libqt5webkit5-dev -# Cryptopp -RUN git clone --depth=1 https://github.com/mmoss/cryptopp.git -RUN cd cryptopp && scons --shared --prefix=/usr - -# JSONRPC (version 0.2.1, see https://github.com/ethereum/cpp-ethereum/issues/453 ) -RUN apt-get install -qy libjsoncpp-dev libargtable2-dev -RUN git clone --depth=1 --branch=0.2.1 https://github.com/cinemast/libjson-rpc-cpp.git -RUN mkdir -p libjson-rpc-cpp/build -RUN cd libjson-rpc-cpp/build && cmake .. && make && make install +# Ethereum PPA +RUN apt-get install -qy software-properties-common +RUN add-apt-repository ppa:ethereum/ethereum +RUN apt-get update +RUN apt-get install -qy libcryptopp-dev libjson-rpc-cpp-dev # Build Ethereum (HEADLESS) RUN git clone --depth=1 https://github.com/ethereum/cpp-ethereum From c1d8aa7551792405c856c1814b13ad244c4861f3 Mon Sep 17 00:00:00 2001 From: winsvega Date: Tue, 23 Dec 2014 23:38:44 +0300 Subject: [PATCH 07/18] comments in json --- test/stInitCodeTestFiller.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/stInitCodeTestFiller.json b/test/stInitCodeTestFiller.json index 55f5567af..501b1ff21 100644 --- a/test/stInitCodeTestFiller.json +++ b/test/stInitCodeTestFiller.json @@ -276,7 +276,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87": { "balance": "1", "nonce": 0, - "comment": "{[[0]] 12 (CREATE 0 64 32)}", + "//": "{[[0]] 12 (CREATE 0 64 32)}", "code": "{(MSTORE 0 0x600c600055602060406000f0)(CREATE 0 20 12)}", "storage": {} }, @@ -315,8 +315,8 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87": { "balance": "1000", "nonce": 0, - "comment": "(CREATE 0 64 32)", - "comment": "{[[0]] 12 (MSTORE 32 0x602060406000f0)(RETURN 57 7)}", + "//": "(CREATE 0 64 32)", + "//": "{[[0]] 12 (MSTORE 32 0x602060406000f0)(RETURN 57 7)}", "code": "{(MSTORE 0 0x600c60005566602060406000f060205260076039f3)[[0]](CREATE 1 11 21)(CALL 500 (SLOAD 0) 1 0 0 0 0)}", "storage": {} }, @@ -355,8 +355,8 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87": { "balance": "0", "nonce": 0, - "comment": "(CREATE 0 64 32)", - "comment": "{[[0]] 12 (MSTORE 32 0x602060406000f0)(RETURN 57 7)}", + "//": "(CREATE 0 64 32)", + "//": "{[[0]] 12 (MSTORE 32 0x602060406000f0)(RETURN 57 7)}", "code": "{(MSTORE 0 0x600c60005566602060406000f060205260076039f3)[[0]](CREATE 1 11 21)(CALL 0 (SLOAD 0) 0 0 0 0 0)}", "storage": {} }, @@ -395,8 +395,8 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87": { "balance": "1000", "nonce": 0, - "comment": "(CREATE 0 64 32)", - "comment": "{[[0]] 12 (MSTORE 32 0x602060406000f0)(RETURN 57 7)}", + "//": "(CREATE 0 64 32)", + "//": "{[[0]] 12 (MSTORE 32 0x602060406000f0)(RETURN 57 7)}", "code": "{(MSTORE 0 0x600c60005566602060406000f060205260076039f3)[[0]](CREATE 1 11 21)(CALL 0 (SLOAD 0) 1 0 0 0 0)}", "storage": {} }, @@ -435,8 +435,8 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87": { "balance": "1000", "nonce": 0, - "comment": "(CREATE 0 64 32)", - "comment": "{[[0]] 12 (MSTORE 32 0x602060406000f0)(RETURN 57 7)}", + "//": "(CREATE 0 64 32)", + "//": "{[[0]] 12 (MSTORE 32 0x602060406000f0)(RETURN 57 7)}", "code": "{(MSTORE 0 0x600c60005566602060406000f060205260076039f3)[[0]](CREATE 1001 11 21)}", "storage": {} }, From ac583f503fd06a280edab8a913b4aba8825a9ab5 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 24 Dec 2014 11:36:08 +0100 Subject: [PATCH 08/18] Implemented 256-long history for PREVHASH, though still optional. --- alethzero/MainWin.cpp | 4 +-- eth/main.cpp | 2 +- exp/main.cpp | 4 +-- libethereum/Client.cpp | 4 +-- libethereum/Executive.cpp | 11 +++++-- libethereum/Executive.h | 6 +++- libethereum/ExtVM.cpp | 4 +-- libethereum/ExtVM.h | 4 +-- libethereum/State.cpp | 48 +++++++++++++++++++------------ libethereum/State.h | 14 +++++---- libevm/ExtVMFace.cpp | 3 +- libevm/ExtVMFace.h | 10 +++++-- libevm/VM.h | 12 ++++++-- libp2p/Session.cpp | 2 +- mix/AssemblyDebuggerModel.cpp | 2 +- test/solidityExecutionFramework.h | 2 +- test/state.cpp | 2 +- test/stateOriginal.cpp | 2 +- test/vm.cpp | 2 +- 19 files changed, 88 insertions(+), 50 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index e25db4137..9cc651e4a 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1350,7 +1350,7 @@ void Main::on_debugCurrent_triggered() { unsigned txi = item->data(Qt::UserRole + 1).toInt(); m_executiveState = ethereum()->state(txi + 1, h); - m_currentExecution = unique_ptr(new Executive(m_executiveState, 0)); + m_currentExecution = unique_ptr(new Executive(m_executiveState, ethereum()->blockChain(), 0)); Transaction t = m_executiveState.pending()[txi]; m_executiveState = m_executiveState.fromPending(txi); auto r = t.rlp(); @@ -1803,7 +1803,7 @@ void Main::on_debug_clicked() { Secret s = i.secret(); m_executiveState = ethereum()->postState(); - m_currentExecution = unique_ptr(new Executive(m_executiveState, 0)); + m_currentExecution = unique_ptr(new Executive(m_executiveState, ethereum()->blockChain(), 0)); Transaction t = isCreation() ? Transaction(value(), gasPrice(), ui->gas->value(), m_data, m_executiveState.transactionsFrom(dev::toAddress(s)), s) : Transaction(value(), gasPrice(), ui->gas->value(), fromString(ui->destination->currentText()), m_data, m_executiveState.transactionsFrom(dev::toAddress(s)), s); diff --git a/eth/main.cpp b/eth/main.cpp index 1520e86c4..1d139faa7 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -619,7 +619,7 @@ int main(int argc, char** argv) dev::eth::State state =c->state(index + 1,c->blockChain().numberHash(block)); if (index < state.pending().size()) { - Executive e(state, 0); + Executive e(state, c->blockChain(), 0); Transaction t = state.pending()[index]; state = state.fromPending(index); bytes r = t.rlp(); diff --git a/exp/main.cpp b/exp/main.cpp index 27707decb..e714f29da 100644 --- a/exp/main.cpp +++ b/exp/main.cpp @@ -21,13 +21,13 @@ */ #include #include +#include #include #include #include #include #include #include -#include #include #include #include @@ -91,7 +91,7 @@ int main() Transaction t(0, 10000, 10000, c, bytes(), 0, u.secret()); cnote << "Transaction: " << t; cnote << s.balance(c); - s.execute(t.rlp()); + s.execute(LastHashes(), t.rlp()); cnote << "State after transaction: " << s; cnote << before.diff(s); } diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index e3346754b..02ef2d3be 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -343,7 +343,7 @@ bytes Client::call(Secret _secret, u256 _value, Address _dest, bytes const& _dat n = temp.transactionsFrom(toAddress(_secret)); } Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); - u256 gasUsed = temp.execute(t.rlp(), &out, false); + u256 gasUsed = temp.execute(m_bc, t.rlp(), &out, false); (void)gasUsed; // TODO: do something with gasused which it returns. } catch (...) @@ -442,7 +442,7 @@ void Client::doWork() // returns h256s as blooms, once for each transaction. cwork << "postSTATE <== TQ"; - h512s newPendingBlooms = m_postMine.sync(m_tq); + h512s newPendingBlooms = m_postMine.sync(m_bc, m_tq); if (newPendingBlooms.size()) { for (auto i: newPendingBlooms) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index d16cf794c..3bc6ea93e 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -29,12 +29,19 @@ #include "State.h" #include "ExtVM.h" #include "Precompiled.h" +#include "BlockChain.h" using namespace std; using namespace dev; using namespace dev::eth; #define ETH_VMTRACE 1 +Executive::Executive(State& _s, BlockChain const& _bc, unsigned _level): + m_s(_s), + m_lastHashes(_s.getLastHashes(_bc)), + m_depth(_level) +{} + u256 Executive::gasUsed() const { return m_t.gas() - m_endGas; @@ -123,7 +130,7 @@ bool Executive::call(Address _receiveAddress, Address _codeAddress, Address _sen { m_vm = VMFactory::create(_gas); bytes const& c = m_s.code(_codeAddress); - m_ext = make_shared(m_s, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c, m_depth); + m_ext = make_shared(m_s, m_lastHashes, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c, m_depth); } else m_endGas = _gas; @@ -143,7 +150,7 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g // Execute _init. m_vm = VMFactory::create(_gas); - m_ext = make_shared(m_s, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init, m_depth); + m_ext = make_shared(m_s, m_lastHashes, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init, m_depth); return _init.empty(); } diff --git a/libethereum/Executive.h b/libethereum/Executive.h index 8ccccddf8..0b154b4b5 100644 --- a/libethereum/Executive.h +++ b/libethereum/Executive.h @@ -34,6 +34,7 @@ namespace eth { class State; +class BlockChain; class ExtVM; struct Manifest; @@ -52,7 +53,9 @@ class Executive { public: /// Basic constructor. - Executive(State& _s, unsigned _level): m_s(_s), m_depth(_level) {} + Executive(State& _s, LastHashes const& _lh, unsigned _level): m_s(_s), m_lastHashes(_lh), m_depth(_level) {} + /// Basic constructor. + Executive(State& _s, BlockChain const& _bc, unsigned _level); /// Basic destructor. ~Executive() = default; @@ -102,6 +105,7 @@ public: private: 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. std::unique_ptr m_vm; ///< The VM object or null if no VM is required. bytes m_precompiledOut; ///< Used for the output when there is no VM for a contract (i.e. precompiled). diff --git a/libethereum/ExtVM.cpp b/libethereum/ExtVM.cpp index a005a030b..a8eba5a50 100644 --- a/libethereum/ExtVM.cpp +++ b/libethereum/ExtVM.cpp @@ -28,7 +28,7 @@ using namespace dev::eth; bool ExtVM::call(Address _receiveAddress, u256 _txValue, bytesConstRef _txData, u256& io_gas, bytesRef _out, OnOpFunc const& _onOp, Address _myAddressOverride, Address _codeAddressOverride) { - Executive e(m_s, depth + 1); + Executive e(m_s, lastHashes, depth + 1); if (!e.call(_receiveAddress, _codeAddressOverride ? _codeAddressOverride : _receiveAddress, _myAddressOverride ? _myAddressOverride : myAddress, _txValue, gasPrice, _txData, io_gas, origin)) { e.go(_onOp); @@ -45,7 +45,7 @@ h160 ExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc // Increment associated nonce for sender. m_s.noteSending(myAddress); - Executive e(m_s, depth + 1); + Executive e(m_s, lastHashes, depth + 1); if (!e.create(myAddress, _endowment, gasPrice, io_gas, _code, origin)) { e.go(_onOp); diff --git a/libethereum/ExtVM.h b/libethereum/ExtVM.h index cfe40874f..30cbf1a5a 100644 --- a/libethereum/ExtVM.h +++ b/libethereum/ExtVM.h @@ -39,8 +39,8 @@ class ExtVM: public ExtVMFace { public: /// Full constructor. - ExtVM(State& _s, Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytesConstRef _code, unsigned _depth = 0): - ExtVMFace(_myAddress, _caller, _origin, _value, _gasPrice, _data, _code.toBytes(), _s.m_previousBlock, _s.m_currentBlock, _depth), m_s(_s), m_origCache(_s.m_cache) + ExtVM(State& _s, LastHashes const& _lh, Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytesConstRef _code, unsigned _depth = 0): + ExtVMFace(_myAddress, _caller, _origin, _value, _gasPrice, _data, _code.toBytes(), _s.m_previousBlock, _s.m_currentBlock, _lh, _depth), m_s(_s), m_origCache(_s.m_cache) { m_s.ensureCached(_myAddress, true, true); } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index e02b06bcd..e5d31d863 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -114,7 +114,7 @@ State::State(OverlayDB const& _db, BlockChain const& _bc, h256 _h): m_ourAddress = bi.coinbaseAddress; sync(_bc, bi.parentHash, bip); - enact(&b); + enact(&b, _bc); } State::State(State const& _s): @@ -319,7 +319,7 @@ bool State::sync(BlockChain const& _bc, h256 _block, BlockInfo const& _bi) for (auto it = chain.rbegin(); it != chain.rend(); ++it) { auto b = _bc.block(*it); - enact(&b); + enact(&b, _bc); cleanup(true); } } @@ -348,7 +348,7 @@ u256 State::enactOn(bytesConstRef _block, BlockInfo const& _bi, BlockChain const sync(_bc, _bi.parentHash); resetCurrent(); m_previousBlock = biParent; - return enact(_block, &_bc); + return enact(_block, _bc); } map State::addresses() const @@ -412,12 +412,14 @@ bool State::cull(TransactionQueue& _tq) const return ret; } -h512s State::sync(TransactionQueue& _tq, bool* o_transactionQueueChanged) +h512s State::sync(BlockChain const& _bc, TransactionQueue& _tq, bool* o_transactionQueueChanged) { // TRANSACTIONS h512s ret; auto ts = _tq.transactions(); + auto lh = getLastHashes(_bc); + for (int goodTxs = 1; goodTxs;) { goodTxs = 0; @@ -429,7 +431,7 @@ h512s State::sync(TransactionQueue& _tq, bool* o_transactionQueueChanged) { uncommitToMine(); // boost::timer t; - execute(i.second); + execute(lh, i.second); ret.push_back(m_receipts.back().bloom()); _tq.noteGood(i); ++goodTxs; @@ -467,7 +469,7 @@ h512s State::sync(TransactionQueue& _tq, bool* o_transactionQueueChanged) return ret; } -u256 State::enact(bytesConstRef _block, BlockChain const* _bc, bool _checkNonce) +u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce) { // m_currentBlock is assumed to be prepopulated and reset. @@ -496,6 +498,8 @@ u256 State::enact(bytesConstRef _block, BlockChain const* _bc, bool _checkNonce) GenericTrieDB receiptsTrie(&rm); receiptsTrie.init(); + LastHashes lh = getLastHashes(_bc); + // All ok with the block generally. Play back the transactions now... unsigned i = 0; for (auto const& tr: RLP(_block)[1]) @@ -507,7 +511,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const* _bc, bool _checkNonce) // cnote << m_state.root() << m_state; // cnote << *this; - execute(tr.data()); + execute(lh, tr.data()); RLPStream receiptrlp; m_receipts.back().streamRLP(receiptrlp); @@ -551,7 +555,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const* _bc, bool _checkNonce) // Check uncles & apply their rewards to state. set nonces = { m_currentBlock.nonce }; Addresses rewarded; - set knownUncles = _bc ? _bc->allUnclesFrom(m_currentBlock.parentHash) : set(); + set knownUncles = _bc.allUnclesFrom(m_currentBlock.parentHash); for (auto const& i: RLP(_block)[2]) { if (knownUncles.count(sha3(i.data()))) @@ -560,13 +564,11 @@ u256 State::enact(bytesConstRef _block, BlockChain const* _bc, bool _checkNonce) BlockInfo uncle = BlockInfo::fromHeader(i.data()); if (nonces.count(uncle.nonce)) BOOST_THROW_EXCEPTION(DuplicateUncleNonce()); - if (_bc) - { - BlockInfo uncleParent(_bc->block(uncle.parentHash)); - if ((bigint)uncleParent.number < (bigint)m_currentBlock.number - 6) - BOOST_THROW_EXCEPTION(UncleTooOld()); - uncle.verifyParent(uncleParent); - } + + BlockInfo uncleParent(_bc.block(uncle.parentHash)); + if ((bigint)uncleParent.number < (bigint)m_currentBlock.number - 6) + BOOST_THROW_EXCEPTION(UncleTooOld()); + uncle.verifyParent(uncleParent); nonces.insert(uncle.nonce); tdIncrease += uncle.difficulty; @@ -648,7 +650,7 @@ bool State::amIJustParanoid(BlockChain const& _bc) cnote << "PARANOIA root:" << s.rootHash(); // s.m_currentBlock.populate(&block.out(), false); // s.m_currentBlock.verifyInternals(&block.out()); - s.enact(&block.out(), &_bc, false); // don't check nonce for this since we haven't mined it yet. + s.enact(&block.out(), _bc, false); // don't check nonce for this since we haven't mined it yet. s.cleanup(false); return true; } @@ -993,9 +995,17 @@ bool State::isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const return true; } -// TODO: maintain node overlay revisions for stateroots -> each commit gives a stateroot + OverlayDB; allow overlay copying for rewind operations. +LastHashes State::getLastHashes(BlockChain const& _bc) const +{ + LastHashes ret; + unsigned n = (unsigned)m_previousBlock.number; + for (unsigned i = 0; i < 256; ++i) + ret[i] = _bc.numberHash(n - i); + return ret; +} -u256 State::execute(bytesConstRef _rlp, bytes* o_output, bool _commit) +// TODO: maintain node overlay revisions for stateroots -> each commit gives a stateroot + OverlayDB; allow overlay copying for rewind operations. +u256 State::execute(LastHashes const& _lh, bytesConstRef _rlp, bytes* o_output, bool _commit) { #ifndef ETH_RELEASE commit(); // get an updated hash @@ -1008,7 +1018,7 @@ u256 State::execute(bytesConstRef _rlp, bytes* o_output, bool _commit) auto h = rootHash(); #endif - Executive e(*this, 0); + Executive e(*this, _lh, 0); e.setup(_rlp); u256 startGasUsed = gasUsed(); diff --git a/libethereum/State.h b/libethereum/State.h index 763a67451..0473893c4 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -143,14 +143,18 @@ public: /// @returns a list of bloom filters one for each transaction placed from the queue into the state. /// @a o_transactionQueueChanged boolean pointer, the value of which will be set to true if the transaction queue /// changed and the pointer is non-null - h512s sync(TransactionQueue& _tq, bool* o_transactionQueueChanged = nullptr); + h512s sync(BlockChain const& _bc, TransactionQueue& _tq, bool* o_transactionQueueChanged = nullptr); /// Like sync but only operate on _tq, killing the invalid/old ones. bool cull(TransactionQueue& _tq) const; + LastHashes getLastHashes(BlockChain const& _bc) const; + /// Execute a given transaction. /// This will append @a _t to the transaction list and change the state accordingly. - u256 execute(bytes const& _rlp, bytes* o_output = nullptr, bool _commit = true) { return execute(&_rlp, o_output, _commit); } - u256 execute(bytesConstRef _rlp, bytes* o_output = nullptr, bool _commit = true); + u256 execute(BlockChain const& _bc, bytes const& _rlp, bytes* o_output = nullptr, bool _commit = true) { return execute(getLastHashes(_bc), &_rlp, o_output, _commit); } + u256 execute(BlockChain const& _bc, bytesConstRef _rlp, bytes* o_output = nullptr, bool _commit = true) { return execute(getLastHashes(_bc), _rlp, o_output, _commit); } + u256 execute(LastHashes const& _lh, bytes const& _rlp, bytes* o_output = nullptr, bool _commit = true) { return execute(_lh, &_rlp, o_output, _commit); } + u256 execute(LastHashes const& _lh, bytesConstRef _rlp, bytes* o_output = nullptr, bool _commit = true); /// Get the remaining gas limit in this block. u256 gasLimitRemaining() const { return m_currentBlock.gasLimit - gasUsed(); } @@ -268,9 +272,9 @@ private: /// Retrieve all information about a given address into a cache. void ensureCached(std::map& _cache, Address _a, bool _requireCode, bool _forceCreate) const; - /// Execute the given block, assuming it corresponds to m_currentBlock. If _bc is passed, it will be used to check the uncles. + /// Execute the given block, assuming it corresponds to m_currentBlock. /// Throws on failure. - u256 enact(bytesConstRef _block, BlockChain const* _bc = nullptr, bool _checkNonce = true); + u256 enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce = true); /// Finalise the block, applying the earned rewards. void applyRewards(Addresses const& _uncleAddresses); diff --git a/libevm/ExtVMFace.cpp b/libevm/ExtVMFace.cpp index 8a08a290c..ebef1fdb0 100644 --- a/libevm/ExtVMFace.cpp +++ b/libevm/ExtVMFace.cpp @@ -25,7 +25,7 @@ using namespace std; using namespace dev; using namespace dev::eth; -ExtVMFace::ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytes const& _code, BlockInfo const& _previousBlock, BlockInfo const& _currentBlock, unsigned _depth): +ExtVMFace::ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytes const& _code, BlockInfo const& _previousBlock, BlockInfo const& _currentBlock, LastHashes const& _lh, unsigned _depth): myAddress(_myAddress), caller(_caller), origin(_origin), @@ -33,6 +33,7 @@ ExtVMFace::ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 gasPrice(_gasPrice), data(_data), code(_code), + lastHashes(_lh), previousBlock(_previousBlock), currentBlock(_currentBlock), depth(_depth) diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 84dee4272..2c5e9400c 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -93,6 +93,8 @@ struct SubState class ExtVMFace; class VM; +using LastHashes = std::array; + using OnOpFunc = std::function; /** @@ -105,7 +107,7 @@ public: ExtVMFace() = default; /// Full constructor. - ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytes const& _code, BlockInfo const& _previousBlock, BlockInfo const& _currentBlock, unsigned _depth); + ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytes const& _code, BlockInfo const& _previousBlock, BlockInfo const& _currentBlock, LastHashes const& _lh, unsigned _depth); virtual ~ExtVMFace() = default; @@ -145,6 +147,9 @@ public: /// Revert any changes made (by any of the other calls). virtual void revert() {} + /// Hash of a block if within the last 256 blocks, or h256() otherwise. + h256 prevhash(u256 _number) { return _number < currentBlock.number && _number > (std::max(257, currentBlock.number) - 257) ? lastHashes[(unsigned)(currentBlock.number - 1 - _number)] : h256(); } // TODO: CHECK!!! + /// Get the code at the given location in code ROM. byte getCode(u256 _n) const { return _n < code.size() ? code[(size_t)_n] : 0; } @@ -155,7 +160,8 @@ public: u256 gasPrice; ///< Price of gas (that we already paid). bytesConstRef data; ///< Current input data. bytes code; ///< Current code that is executing. - BlockInfo previousBlock; ///< The previous block's information. + LastHashes lastHashes; ///< Most recent 256 blocks' hashes. + BlockInfo previousBlock; ///< The previous block's information. TODO: PoC-8: REMOVE BlockInfo currentBlock; ///< The current block's information. SubState sub; ///< Sub-band VM state (suicides, refund counter, logs). unsigned depth = 0; ///< Depth of the present call. diff --git a/libevm/VM.h b/libevm/VM.h index 1f3fc17d5..64353e2db 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -198,7 +198,6 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st require(1); runGas = c_balanceGas; break; - case Instruction::LOG0: case Instruction::LOG1: case Instruction::LOG2: @@ -240,6 +239,11 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st break; } + case Instruction::PREVHASH: + if (c_protocolVersion > 49) + require(1); + break; + case Instruction::PC: case Instruction::MSIZE: case Instruction::GAS: @@ -251,7 +255,6 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st case Instruction::CALLDATASIZE: case Instruction::CODESIZE: case Instruction::GASPRICE: - case Instruction::PREVHASH: case Instruction::COINBASE: case Instruction::TIMESTAMP: case Instruction::NUMBER: @@ -581,7 +584,10 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st m_stack.push_back(_ext.gasPrice); break; case Instruction::PREVHASH: - m_stack.push_back(_ext.previousBlock.hash); + if (c_protocolVersion > 49) + m_stack.back() = (u256)_ext.prevhash(m_stack.back()); + else + m_stack.push_back(_ext.previousBlock.hash); break; case Instruction::COINBASE: m_stack.push_back((u160)_ext.currentBlock.coinbaseAddress); diff --git a/libp2p/Session.cpp b/libp2p/Session.cpp index cb0a60a92..bf08cfe00 100644 --- a/libp2p/Session.cpp +++ b/libp2p/Session.cpp @@ -195,7 +195,7 @@ bool Session::interpret(RLP const& _r) // "'operator<<' should be declared prior to the call site or in an associated namespace of one of its arguments" stringstream capslog; for (auto cap: caps) - capslog << "(" << hex << cap.first << "," << hex << cap.second << ")"; + capslog << "(" << cap.first << "," << dec << cap.second << ")"; clogS(NetMessageSummary) << "Hello: " << clientVersion << "V[" << m_protocolVersion << "]" << id.abridged() << showbase << capslog.str() << dec << listenPort; diff --git a/mix/AssemblyDebuggerModel.cpp b/mix/AssemblyDebuggerModel.cpp index 1e07760e1..17abf5700 100644 --- a/mix/AssemblyDebuggerModel.cpp +++ b/mix/AssemblyDebuggerModel.cpp @@ -38,7 +38,7 @@ AssemblyDebuggerModel::AssemblyDebuggerModel(): m_baseState(Address(), m_overlayDB, BaseState::Empty) { m_baseState.addBalance(m_userAccount.address(), 10000000 * ether); - m_currentExecution = std::unique_ptr(new Executive(m_executiveState, 0)); + m_currentExecution = std::unique_ptr(new Executive(m_executiveState, LastHashes(), 0)); } DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(dev::bytesConstRef _rawTransaction) diff --git a/test/solidityExecutionFramework.h b/test/solidityExecutionFramework.h index 91ee7ad6a..9f25b3725 100644 --- a/test/solidityExecutionFramework.h +++ b/test/solidityExecutionFramework.h @@ -117,7 +117,7 @@ private: void sendMessage(bytes const& _data, bool _isCreation, u256 const& _value = 0) { m_state.addBalance(m_sender, _value); // just in case - eth::Executive executive(m_state, 0); + eth::Executive executive(m_state, eth::LastHashes(), 0); eth::Transaction t = _isCreation ? eth::Transaction(_value, m_gasPrice, m_gas, _data, 0, KeyPair::create().sec()) : eth::Transaction(_value, m_gasPrice, m_gas, m_contractAddress, _data, 0, KeyPair::create().sec()); bytes transactionRLP = t.rlp(); diff --git a/test/state.cpp b/test/state.cpp index b1ad8d44e..133468226 100644 --- a/test/state.cpp +++ b/test/state.cpp @@ -62,7 +62,7 @@ void doStateTests(json_spirit::mValue& v, bool _fillin) try { - theState.execute(tx, &output); + theState.execute(LastHashes(), tx, &output); } catch (Exception const& _e) { diff --git a/test/stateOriginal.cpp b/test/stateOriginal.cpp index 8344894f4..a49c55061 100644 --- a/test/stateOriginal.cpp +++ b/test/stateOriginal.cpp @@ -69,7 +69,7 @@ int stateTest() assert(t.sender() == myMiner.address()); tx = t.rlp(); } - s.execute(tx); + s.execute(bc, tx); cout << s; diff --git a/test/vm.cpp b/test/vm.cpp index 920f0582c..18bf57977 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -33,7 +33,7 @@ using namespace dev::eth; using namespace dev::test; FakeExtVM::FakeExtVM(eth::BlockInfo const& _previousBlock, eth::BlockInfo const& _currentBlock, unsigned _depth): /// TODO: XXX: remove the default argument & fix. - ExtVMFace(Address(), Address(), Address(), 0, 1, bytesConstRef(), bytes(), _previousBlock, _currentBlock, _depth) {} + ExtVMFace(Address(), Address(), Address(), 0, 1, bytesConstRef(), bytes(), _previousBlock, _currentBlock, LastHashes(), _depth) {} h160 FakeExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _init, OnOpFunc const&) { From d8323bbd09e3eec0a94e3ac8f1f56d2f6fd4ba34 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 25 Dec 2014 10:34:11 +0000 Subject: [PATCH 09/18] Simple ABI in/out and new Solidity-based Config/NameReg integration. --- alethzero/MainWin.cpp | 25 ++++++ libdevcore/Common.h | 3 + libdevcore/CommonData.cpp | 180 ++------------------------------------ libdevcore/CommonData.h | 3 + libdevcore/vector_ref.h | 2 +- libethereum/Client.cpp | 26 ++++++ libethereum/Client.h | 33 +++++++ libethereum/State.cpp | 9 +- 8 files changed, 102 insertions(+), 179 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 9cc651e4a..324868022 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -106,6 +106,8 @@ static QString contentsOfQResource(std::string const& res) } Address c_config = Address("661005d2720d855f1d9976f88bb10c1a3398c77f"); +Address c_newConfig = Address("d5f9d8d94886e70b06e474c3fb14fd43e2f23970"); +Address c_nameReg = Address("ddd1cea741d548f90d86fb87a3ae6492e18c03a1"); Main::Main(QWidget *parent) : QMainWindow(parent), @@ -450,6 +452,29 @@ static Public stringToPublic(QString const& _a) QString Main::pretty(dev::Address _a) const { + static std::map s_memos; + + if (!s_memos.count(_a)) + { + static Address s_newNameReg; + + if (!s_newNameReg) + s_newNameReg = abiOut
(ethereum()->call(c_newConfig, abiIn(1, (u256)1))); + + if (s_newNameReg) + { + QString s = QString::fromStdString(toString(abiOut(ethereum()->call(s_newNameReg, abiIn(2, _a))))); + if (s.size()) + { + s_memos[_a] = s; + return s; + } + } + } + else + if (s_memos[_a].size()) + return s_memos[_a]; + h256 n; if (h160 nameReg = (u160)ethereum()->stateAt(c_config, 0)) diff --git a/libdevcore/Common.h b/libdevcore/Common.h index 198119f24..11bee7aa5 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -74,6 +74,9 @@ using StringMap = std::map; using u256Map = std::map; using HexMap = std::map; +// Fixed-length string types. +using string32 = std::array; + // Null/Invalid values for convenience. static const u256 Invalid256 = ~(u256)0; static const bytes NullBytes; diff --git a/libdevcore/CommonData.cpp b/libdevcore/CommonData.cpp index fc3910cfe..b3abe4300 100644 --- a/libdevcore/CommonData.cpp +++ b/libdevcore/CommonData.cpp @@ -123,180 +123,10 @@ bytes dev::asNibbles(std::string const& _s) return ret; } -#if 0 - -/* Following code is copyright 2012-2014 Luke Dashjr - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the standard MIT license. See COPYING for more details. - */ - -#include -#include -#include -#include - -static const int8_t b58digits_map[] = { - -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1, - -1, 9,10,11,12,13,14,15, 16,-1,17,18,19,20,21,-1, - 22,23,24,25,26,27,28,29, 30,31,32,-1,-1,-1,-1,-1, - -1,33,34,35,36,37,38,39, 40,41,42,43,-1,44,45,46, - 47,48,49,50,51,52,53,54, 55,56,57,-1,-1,-1,-1,-1, -}; - -bool b58tobin(void *bin, size_t *binszp, const char *b58, size_t b58sz) -{ - size_t binsz = *binszp; - const unsigned char *b58u = (void*)b58; - unsigned char *binu = bin; - size_t outisz = (binsz + 3) / 4; - uint32_t outi[outisz]; - uint64_t t; - uint32_t c; - size_t i, j; - uint8_t bytesleft = binsz % 4; - uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0; - unsigned zerocount = 0; - - if (!b58sz) - b58sz = strlen(b58); - - memset(outi, 0, outisz * sizeof(*outi)); - - // Leading zeros, just count - for (i = 0; i < b58sz && !b58digits_map[b58u[i]]; ++i) - ++zerocount; - - for ( ; i < b58sz; ++i) - { - if (b58u[i] & 0x80) - // High-bit set on invalid digit - return false; - if (b58digits_map[b58u[i]] == -1) - // Invalid base58 digit - return false; - c = (unsigned)b58digits_map[b58u[i]]; - for (j = outisz; j--; ) - { - t = ((uint64_t)outi[j]) * 58 + c; - c = (t & 0x3f00000000) >> 32; - outi[j] = t & 0xffffffff; - } - if (c) - // Output number too big (carry to the next int32) - return false; - if (outi[0] & zeromask) - // Output number too big (last int32 filled too far) - return false; - } - - j = 0; - switch (bytesleft) { - case 3: - *(binu++) = (outi[0] & 0xff0000) >> 16; - case 2: - *(binu++) = (outi[0] & 0xff00) >> 8; - case 1: - *(binu++) = (outi[0] & 0xff); - ++j; - default: - break; - } - - for (; j < outisz; ++j) - { - *(binu++) = (outi[j] >> 0x18) & 0xff; - *(binu++) = (outi[j] >> 0x10) & 0xff; - *(binu++) = (outi[j] >> 8) & 0xff; - *(binu++) = (outi[j] >> 0) & 0xff; - } - - // Count canonical base58 byte count - binu = bin; - for (i = 0; i < binsz; ++i) - { - if (binu[i]) - break; - --*binszp; - } - *binszp += zerocount; - - return true; -} - -static -bool my_dblsha256(void *hash, const void *data, size_t datasz) +std::string dev::toString(string32 const& _s) { - uint8_t buf[0x20]; - return b58_sha256_impl(buf, data, datasz) && b58_sha256_impl(hash, buf, sizeof(buf)); -} - -int b58check(const void *bin, size_t binsz, const char *base58str, size_t b58sz) -{ - unsigned char buf[32]; - const uint8_t *binc = bin; - unsigned i; - if (binsz < 4) - return -4; - if (!my_dblsha256(buf, bin, binsz - 4)) - return -2; - if (memcmp(&binc[binsz - 4], buf, 4)) - return -1; - - // Check number of zeros is correct AFTER verifying checksum (to avoid possibility of accessing base58str beyond the end) - for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i) - {} // Just finding the end of zeros, nothing to do in loop - if (binc[i] == '\0' || base58str[i] == '1') - return -3; - - return binc[0]; -} - -static const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; - -bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz) -{ - const uint8_t *bin = data; - int carry; - size_t i, j, high, zcount = 0; - size_t size; - - while (zcount < binsz && !bin[zcount]) - ++zcount; - - size = (binsz - zcount) * 138 / 100 + 1; - uint8_t buf[size]; - memset(buf, 0, size); - - for (i = zcount, high = size - 1; i < binsz; ++i, high = j) - { - for (carry = bin[i], j = size - 1; (j > high) || carry; --j) - { - carry += 256 * buf[j]; - buf[j] = carry % 58; - carry /= 58; - } - } - - for (j = 0; j < size && !buf[j]; ++j); - - if (*b58sz <= zcount + size - j) - { - *b58sz = zcount + size - j + 1; - return false; - } - - if (zcount) - memset(b58, '1', zcount); - for (i = zcount; j < size; ++i, ++j) - b58[i] = b58digits_ordered[buf[j]]; - b58[i] = '\0'; - *b58sz = i + 1; - - return true; + std::string ret; + for (unsigned i = 0; i < 32 && _s[i]; ++i) + ret.push_back(_s[i]); + return ret; } - -#endif diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h index 87d2f5e28..6fab67452 100644 --- a/libdevcore/CommonData.h +++ b/libdevcore/CommonData.h @@ -236,4 +236,7 @@ inline std::set<_T> operator+(std::set<_T> const& _a, std::set<_T> const& _b) return ret += _b; } +/// Make normal string from fixed-length string. +std::string toString(string32 const& _s); + } diff --git a/libdevcore/vector_ref.h b/libdevcore/vector_ref.h index db46d62f6..714c53b8c 100644 --- a/libdevcore/vector_ref.h +++ b/libdevcore/vector_ref.h @@ -40,7 +40,7 @@ public: vector_ref<_T> cropped(size_t _begin, size_t _count = ~size_t(0)) const { if (m_data && _begin + std::max(size_t(0), _count) <= m_count) return vector_ref<_T>(m_data + _begin, _count == ~size_t(0) ? m_count - _begin : _count); else return vector_ref<_T>(); } void retarget(_T const* _d, size_t _s) { m_data = _d; m_count = _s; } void retarget(std::vector<_T> const& _t) { m_data = _t.data(); m_count = _t.size(); } - void copyTo(vector_ref::type> _t) const { memcpy(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T)); } + void copyTo(vector_ref::type> _t) const { memcpy(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T)); memset(_t.data() + m_count, 0, std::max(_t.size(), m_count) - m_count); } _T* begin() { return m_data; } _T* end() { return m_data + m_count; } diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 02ef2d3be..c7ed4500c 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -353,6 +353,32 @@ bytes Client::call(Secret _secret, u256 _value, Address _dest, bytes const& _dat return out; } +bytes Client::call(Address _dest, bytes const& _data, u256 _gas, u256 _value, u256 _gasPrice) +{ + bytes out; + try + { + u256 n; + State temp; + KeyPair k = KeyPair::create(); + // cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret)); + { + ReadGuard l(x_stateDB); + temp = m_postMine; + temp.addBalance(k.address(), _gas * _gasPrice + _value); + n = temp.transactionsFrom(k.address()); + } + Transaction t(_value, _gasPrice, _gas, _dest, _data, n, k.secret()); + u256 gasUsed = temp.execute(m_bc, t.rlp(), &out, false); + (void)gasUsed; // TODO: do something with gasused which it returns. + } + catch (...) + { + // TODO: Some sort of notification of failure. + } + return out; +} + Address Client::transact(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) { startWorking(); diff --git a/libethereum/Client.h b/libethereum/Client.h index e8c460093..a68a3ecd8 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include #include @@ -105,6 +107,34 @@ struct WorkChannel: public LogChannel { static const char* name() { return "-W-" #define cworkin dev::LogOutputStream() #define cworkout dev::LogOutputStream() +template struct ABISerialiser {}; +template struct ABISerialiser> { static bytes serialise(FixedHash const& _t) { return _t.asBytes(); } }; +template <> struct ABISerialiser { static bytes serialise(u256 const& _t) { return h256(_t).asBytes(); } }; +template <> struct ABISerialiser { static bytes serialise(u160 const& _t) { return h160(_t).asBytes(); } }; + +inline bytes abiInAux() { return {}; } +template bytes abiInAux(T const& _t, U const& ... _u) +{ + return ABISerialiser::serialise(_t) + abiInAux(_u ...); +} + +template bytes abiIn(byte _id, T const& ... _t) +{ + return bytes(1, _id) + abiInAux(_t ...); +} + +template struct ABIDeserialiser {}; +template struct ABIDeserialiser> { static FixedHash deserialise(bytesConstRef& io_t) { FixedHash ret(io_t.cropped(0, N).toBytes()); io_t = io_t.cropped(N); return ret; } }; +template <> struct ABIDeserialiser { static u256 deserialise(bytesConstRef& io_t) { u256 ret = fromBigEndian(io_t.cropped(0, 32)); io_t = io_t.cropped(32); return ret; } }; +template <> struct ABIDeserialiser { static u256 deserialise(bytesConstRef& io_t) { u160 ret = fromBigEndian(io_t.cropped(0, 20)); io_t = io_t.cropped(20); return ret; } }; +template <> struct ABIDeserialiser { static string32 deserialise(bytesConstRef& io_t) { string32 ret; io_t.cropped(0, 32).copyTo(vector_ref(ret.data(), 32)); io_t = io_t.cropped(32); return ret; } }; + +template T abiOut(bytes const& _data) +{ + bytesConstRef o(&_data); + return ABIDeserialiser::deserialise(o); +} + /** * @brief Main API hub for interfacing with Ethereum. */ @@ -135,6 +165,9 @@ public: /// Makes the given call. Nothing is recorded into the state. virtual bytes call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo); + /// Makes the given call. Nothing is recorded into the state. This cheats by creating a null address and endowing it with a lot of ETH. + virtual bytes call(Address _dest, bytes const& _data = bytes(), u256 _gas = 125000, u256 _value = 0, u256 _gasPrice = 1 * ether); + // Informational stuff // [NEW API] diff --git a/libethereum/State.cpp b/libethereum/State.cpp index e5d31d863..ecdf2dab3 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -998,9 +998,12 @@ bool State::isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const LastHashes State::getLastHashes(BlockChain const& _bc) const { LastHashes ret; - unsigned n = (unsigned)m_previousBlock.number; - for (unsigned i = 0; i < 256; ++i) - ret[i] = _bc.numberHash(n - i); + if (c_protocolVersion > 49) + { + unsigned n = (unsigned)m_previousBlock.number; + for (unsigned i = 0; i < 256; ++i) + ret[i] = _bc.numberHash(n - i); + } return ret; } From 15afb23e5ad044bd4a5c1a60c7380ab4a574ca41 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 25 Dec 2014 11:36:55 +0000 Subject: [PATCH 10/18] More integration with SolNameReg --- alethzero/MainWin.cpp | 57 +++++++++++++++++++++++++++++++------------ libethereum/Client.h | 1 + 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 324868022..dbcd0f493 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -450,25 +450,23 @@ static Public stringToPublic(QString const& _a) return Public(); } +static Address g_newNameReg; + QString Main::pretty(dev::Address _a) const { static std::map s_memos; if (!s_memos.count(_a)) { - static Address s_newNameReg; - - if (!s_newNameReg) - s_newNameReg = abiOut
(ethereum()->call(c_newConfig, abiIn(1, (u256)1))); + if (!g_newNameReg) + g_newNameReg = abiOut
(ethereum()->call(c_newConfig, abiIn(1, (u256)1))); - if (s_newNameReg) + if (g_newNameReg) { - QString s = QString::fromStdString(toString(abiOut(ethereum()->call(s_newNameReg, abiIn(2, _a))))); + QString s = QString::fromStdString(toString(abiOut(ethereum()->call(g_newNameReg, abiIn(2, _a))))); + s_memos[_a] = s; if (s.size()) - { - s_memos[_a] = s; return s; - } } } else @@ -494,19 +492,47 @@ QString Main::render(dev::Address _a) const return QString::fromStdString(_a.abridged()); } -Address Main::fromString(QString const& _a) const +string32 fromString(std::string const& _s) +{ + string32 ret; + for (unsigned i = 0; i < 32 && i <= _s.size(); ++i) + ret[i] = i < _s.size() ? _s[i] : 0; + return ret; +} + +Address Main::fromString(QString const& _n) const { - if (_a == "(Create Contract)") + if (_n == "(Create Contract)") return Address(); - string sn = _a.toStdString(); + static std::map s_memos; + + if (!s_memos.count(_n)) + { + if (!g_newNameReg) + g_newNameReg = abiOut
(ethereum()->call(c_newConfig, abiIn(1, (u256)1))); + + if (g_newNameReg) + { + Address a = abiOut
(ethereum()->call(g_newNameReg, abiIn(0, ::fromString(_n.toStdString())))); + s_memos[_n] = a; + if (a) + return a; + } + } + else + if (s_memos[_n]) + return s_memos[_n]; + + string sn = _n.toStdString(); if (sn.size() > 32) sn.resize(32); h256 n; memcpy(n.data(), sn.data(), sn.size()); memset(n.data() + sn.size(), 0, 32 - sn.size()); - if (_a.size()) + if (_n.size()) { + if (h160 nameReg = (u160)ethereum()->stateAt(c_config, 0)) if (h256 a = ethereum()->stateAt(nameReg, n)) return right160(a); @@ -514,8 +540,9 @@ Address Main::fromString(QString const& _a) const if (h256 a = ethereum()->stateAt(m_nameReg, n)) return right160(a); } - if (_a.size() == 40) - return Address(fromHex(_a.toStdString())); + + if (_n.size() == 40) + return Address(fromHex(_n.toStdString())); else return Address(); } diff --git a/libethereum/Client.h b/libethereum/Client.h index a68a3ecd8..06c504355 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -111,6 +111,7 @@ template struct ABISerialiser {}; template struct ABISerialiser> { static bytes serialise(FixedHash const& _t) { return _t.asBytes(); } }; template <> struct ABISerialiser { static bytes serialise(u256 const& _t) { return h256(_t).asBytes(); } }; template <> struct ABISerialiser { static bytes serialise(u160 const& _t) { return h160(_t).asBytes(); } }; +template <> struct ABISerialiser { static bytes serialise(string32 const& _t) { return bytesConstRef((byte const*)_t.data(), 32).toBytes(); } }; inline bytes abiInAux() { return {}; } template bytes abiInAux(T const& _t, U const& ... _u) From 0a46ee464b5c1e6b4d1e942c694d1dd6b068c350 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 25 Dec 2014 11:45:10 +0000 Subject: [PATCH 11/18] Speed up basic calls. --- libethereum/Client.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index c7ed4500c..edad31c6d 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -27,6 +27,7 @@ #include #include #include "Defaults.h" +#include "Executive.h" #include "EthereumHost.h" using namespace std; using namespace dev; @@ -355,28 +356,24 @@ bytes Client::call(Secret _secret, u256 _value, Address _dest, bytes const& _dat bytes Client::call(Address _dest, bytes const& _data, u256 _gas, u256 _value, u256 _gasPrice) { - bytes out; try { - u256 n; State temp; - KeyPair k = KeyPair::create(); - // cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret)); +// cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret)); { ReadGuard l(x_stateDB); temp = m_postMine; - temp.addBalance(k.address(), _gas * _gasPrice + _value); - n = temp.transactionsFrom(k.address()); } - Transaction t(_value, _gasPrice, _gas, _dest, _data, n, k.secret()); - u256 gasUsed = temp.execute(m_bc, t.rlp(), &out, false); - (void)gasUsed; // TODO: do something with gasused which it returns. + Executive e(temp, LastHashes(), 0); + e.call(_dest, _dest, Address(), _value, _gasPrice, &_data, _gas, Address()); + e.go(); + return e.out().toBytes(); } catch (...) { // TODO: Some sort of notification of failure. } - return out; + return bytes(); } Address Client::transact(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) From cc75d1bb5c8e95a715b72290bab2dee3b76c0b4e Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 27 Dec 2014 18:09:01 +0000 Subject: [PATCH 12/18] Receipts debugging. --- eth/main.cpp | 12 ++++++++++++ libethereum/Client.cpp | 8 +++++--- libethereum/Client.h | 2 +- libethereum/State.cpp | 30 ++++++++++++++---------------- libethereum/TransactionReceipt.cpp | 16 ++++++++++++++++ libethereum/TransactionReceipt.h | 3 +++ 6 files changed, 51 insertions(+), 20 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index 1d139faa7..d55766cfd 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -89,6 +89,7 @@ void interactiveHelp() << " importConfig Import the config (.RLP) from the path provided." < Dumps a contract to /.evm." << endl << " dumptrace Dumps a transaction trace" << endl << "to . should be one of pretty, standard, standard+." << endl + << " dumpreceipt Dumps a transation receipt." << endl << " exit Exits the application." << endl; } @@ -606,6 +607,17 @@ int main(int argc, char** argv) else cwarn << "Require parameters: contract ENDOWMENT GASPRICE GAS CODEHEX"; } + else if (c && cmd == "dumpreceipt") + { + unsigned block; + unsigned index; + iss >> block >> index; + dev::eth::TransactionReceipt r = c->blockChain().receipts(c->blockChain().numberHash(block)).receipts[index]; + auto rb = r.rlp(); + cout << "RLP: " << RLP(rb) << endl; + cout << "Hex: " << toHex(rb) << endl; + cout << r << endl; + } else if (c && cmd == "dumptrace") { unsigned block; diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index edad31c6d..d8967c084 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -365,9 +365,11 @@ bytes Client::call(Address _dest, bytes const& _data, u256 _gas, u256 _value, u2 temp = m_postMine; } Executive e(temp, LastHashes(), 0); - e.call(_dest, _dest, Address(), _value, _gasPrice, &_data, _gas, Address()); - e.go(); - return e.out().toBytes(); + if (!e.call(_dest, _dest, Address(), _value, _gasPrice, &_data, _gas, Address())) + { + e.go(); + return e.out().toBytes(); + } } catch (...) { diff --git a/libethereum/Client.h b/libethereum/Client.h index 06c504355..bf6d902b7 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -125,7 +125,7 @@ template bytes abiIn(byte _id, T const& ... _t) } template struct ABIDeserialiser {}; -template struct ABIDeserialiser> { static FixedHash deserialise(bytesConstRef& io_t) { FixedHash ret(io_t.cropped(0, N).toBytes()); io_t = io_t.cropped(N); return ret; } }; +template struct ABIDeserialiser> { static FixedHash deserialise(bytesConstRef& io_t) { FixedHash ret; io_t.cropped(0, N).copyTo(ret.ref()); return ret; } }; template <> struct ABIDeserialiser { static u256 deserialise(bytesConstRef& io_t) { u256 ret = fromBigEndian(io_t.cropped(0, 32)); io_t = io_t.cropped(32); return ret; } }; template <> struct ABIDeserialiser { static u256 deserialise(bytesConstRef& io_t) { u160 ret = fromBigEndian(io_t.cropped(0, 20)); io_t = io_t.cropped(20); return ret; } }; template <> struct ABIDeserialiser { static string32 deserialise(bytesConstRef& io_t) { string32 ret; io_t.cropped(0, 32).copyTo(vector_ref(ret.data(), 32)); io_t = io_t.cropped(32); return ret; } }; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index ecdf2dab3..ec9e2d31f 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -508,26 +508,11 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce) k << i; transactionsTrie.insert(&k.out(), tr.data()); - -// cnote << m_state.root() << m_state; -// cnote << *this; execute(lh, tr.data()); RLPStream receiptrlp; m_receipts.back().streamRLP(receiptrlp); receiptsTrie.insert(&k.out(), &receiptrlp.out()); -/* - if (tr[1].toHash() != m_state.root()) - { - // Invalid state root - cnote << m_state.root() << "\n" << m_state; - cnote << *this; - cnote << "INVALID: " << tr[1].toHash(); - BOOST_THROW_EXCEPTION(InvalidTransactionStateRoot()); - } - if (tr[2].toInt() != gasUsed()) - BOOST_THROW_EXCEPTION(InvalidTransactionGasUsed()); -*/ ++i; } @@ -539,7 +524,20 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce) if (receiptsTrie.root() != m_currentBlock.receiptsRoot) { - cwarn << "Bad receipts state root!"; + cwarn << "Bad receipts state root."; + cwarn << "Block:" << toHex(_block); + cwarn << "Block RLP:" << RLP(_block); + cwarn << "Want: " << receiptsTrie.root() << ", got: " << m_currentBlock.receiptsRoot; + for (unsigned j = 0; j < i; ++j) + { + RLPStream k; + k << j; + auto b = asBytes(receiptsTrie.at(&k.out())); + cwarn << j << ": "; + cwarn << "RLP: " << RLP(b); + cwarn << "Hex: " << toHex(b); + cwarn << TransactionReceipt(&b); + } BOOST_THROW_EXCEPTION(InvalidReceiptsStateRoot()); } diff --git a/libethereum/TransactionReceipt.cpp b/libethereum/TransactionReceipt.cpp index 0fb104490..868b00558 100644 --- a/libethereum/TransactionReceipt.cpp +++ b/libethereum/TransactionReceipt.cpp @@ -49,3 +49,19 @@ void TransactionReceipt::streamRLP(RLPStream& _s) const for (LogEntry const& l: m_log) l.streamRLP(_s); } + +std::ostream& dev::operator<<(std::ostream& _out, TransactionReceipt const& _r) +{ + _out << "Root: " << _r.stateRoot() << std::endl; + _out << "Gas used: " << _r.gasUsed() << std::endl; + _out << "Logs: " << _r.log().size() << " entries:" << std::endl; + for (LogEntry const& i: _r.log()) + { + _out << "Address " << i.address << ". Topics:" << std::endl; + for (auto const& j: i.topics) + _out << " " << j << std::endl; + _out << " Data: " << toHex(i.data) << std::endl; + } + _out << "Bloom: " << _r.bloom() << std::endl; + return _out; +} diff --git a/libethereum/TransactionReceipt.h b/libethereum/TransactionReceipt.h index 23995c75a..ebf591995 100644 --- a/libethereum/TransactionReceipt.h +++ b/libethereum/TransactionReceipt.h @@ -58,4 +58,7 @@ private: using TransactionReceipts = std::vector; } + +std::ostream& operator<<(std::ostream& _out, eth::TransactionReceipt const& _r); + } From 5b9b7543fad226a56aa9885cd2cef788bece7dfb Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 27 Dec 2014 20:27:25 +0000 Subject: [PATCH 13/18] Fix for copyTo bug. --- libdevcore/vector_ref.h | 3 ++- libethereum/Client.h | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libdevcore/vector_ref.h b/libdevcore/vector_ref.h index 714c53b8c..2771c739a 100644 --- a/libdevcore/vector_ref.h +++ b/libdevcore/vector_ref.h @@ -40,7 +40,8 @@ public: vector_ref<_T> cropped(size_t _begin, size_t _count = ~size_t(0)) const { if (m_data && _begin + std::max(size_t(0), _count) <= m_count) return vector_ref<_T>(m_data + _begin, _count == ~size_t(0) ? m_count - _begin : _count); else return vector_ref<_T>(); } void retarget(_T const* _d, size_t _s) { m_data = _d; m_count = _s; } void retarget(std::vector<_T> const& _t) { m_data = _t.data(); m_count = _t.size(); } - void copyTo(vector_ref::type> _t) const { memcpy(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T)); memset(_t.data() + m_count, 0, std::max(_t.size(), m_count) - m_count); } + void copyTo(vector_ref::type> _t) const { memcpy(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T)); } + void populate(vector_ref::type> _t) const { copyTo(_t); memset(_t.data() + m_count, 0, std::max(_t.size(), m_count) - m_count); } _T* begin() { return m_data; } _T* end() { return m_data + m_count; } diff --git a/libethereum/Client.h b/libethereum/Client.h index bf6d902b7..6a3d7ec22 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -125,10 +125,10 @@ template bytes abiIn(byte _id, T const& ... _t) } template struct ABIDeserialiser {}; -template struct ABIDeserialiser> { static FixedHash deserialise(bytesConstRef& io_t) { FixedHash ret; io_t.cropped(0, N).copyTo(ret.ref()); return ret; } }; +template struct ABIDeserialiser> { static FixedHash deserialise(bytesConstRef& io_t) { FixedHash ret; io_t.cropped(0, N).populate(ret.ref()); return ret; } }; template <> struct ABIDeserialiser { static u256 deserialise(bytesConstRef& io_t) { u256 ret = fromBigEndian(io_t.cropped(0, 32)); io_t = io_t.cropped(32); return ret; } }; template <> struct ABIDeserialiser { static u256 deserialise(bytesConstRef& io_t) { u160 ret = fromBigEndian(io_t.cropped(0, 20)); io_t = io_t.cropped(20); return ret; } }; -template <> struct ABIDeserialiser { static string32 deserialise(bytesConstRef& io_t) { string32 ret; io_t.cropped(0, 32).copyTo(vector_ref(ret.data(), 32)); io_t = io_t.cropped(32); return ret; } }; +template <> struct ABIDeserialiser { static string32 deserialise(bytesConstRef& io_t) { string32 ret; io_t.cropped(0, 32).populate(vector_ref(ret.data(), 32)); io_t = io_t.cropped(32); return ret; } }; template T abiOut(bytes const& _data) { From a6cd367483c7cac867949a6ba518949a98eacf44 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 27 Dec 2014 21:09:24 +0000 Subject: [PATCH 14/18] Fix for overuse of stack. --- libethereum/State.cpp | 3 ++- libevm/ExtVMFace.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index ec9e2d31f..a351b3da5 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -996,11 +996,12 @@ bool State::isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const LastHashes State::getLastHashes(BlockChain const& _bc) const { LastHashes ret; + ret.resize(256); if (c_protocolVersion > 49) { unsigned n = (unsigned)m_previousBlock.number; for (unsigned i = 0; i < 256; ++i) - ret[i] = _bc.numberHash(n - i); + ret[i] = _bc.numberHash(std::max(n, i) - i); } return ret; } diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 2c5e9400c..a4ec80ed8 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -93,7 +93,7 @@ struct SubState class ExtVMFace; class VM; -using LastHashes = std::array; +using LastHashes = std::vector; using OnOpFunc = std::function; From 92f43a7a35dc637f996a5750b3720a6def318503 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 27 Dec 2014 21:40:58 +0000 Subject: [PATCH 15/18] Fix allowed uncles. --- libethereum/State.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index a351b3da5..dfd65c713 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -564,7 +564,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce) BOOST_THROW_EXCEPTION(DuplicateUncleNonce()); BlockInfo uncleParent(_bc.block(uncle.parentHash)); - if ((bigint)uncleParent.number < (bigint)m_currentBlock.number - 6) + if ((bigint)uncleParent.number < (bigint)m_currentBlock.number - 7) BOOST_THROW_EXCEPTION(UncleTooOld()); uncle.verifyParent(uncleParent); From 4bea66340304eeedb733c90917b2e937e03d2daa Mon Sep 17 00:00:00 2001 From: winsvega Date: Sun, 28 Dec 2014 16:48:27 +0300 Subject: [PATCH 16/18] Transaction Tests --- test/stTransactionTestFiller.json | 137 +++++++++++++++++++++++++++++- 1 file changed, 136 insertions(+), 1 deletion(-) diff --git a/test/stTransactionTestFiller.json b/test/stTransactionTestFiller.json index 260e7953f..09c323cf5 100644 --- a/test/stTransactionTestFiller.json +++ b/test/stTransactionTestFiller.json @@ -187,5 +187,140 @@ "to" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b", "value" : "502" } - } + }, + + "ContractStoreClearsSuccess" : { + "env" : { + "currentCoinbase" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "currentDifficulty" : "45678256", + "currentGasLimit" : "10000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "7000", + "code" : "", + "nonce" : "0", + "storage" : { + } + }, + + "d2571607e241ecf590ed94b12d87c94babe36db6" : { + "balance" : "0", + "code" : "{(SSTORE 0 0)(SSTORE 1 0)(SSTORE 2 0)(SSTORE 3 0)(SSTORE 4 0)(SSTORE 5 0)(SSTORE 6 0)(SSTORE 7 0)(SSTORE 8 0)(SSTORE 9 0)}", + "nonce" : "0", + "storage" : { + "0x" : "0x0c", + "0x01" : "0x0c", + "0x02" : "0x0c", + "0x03" : "0x0c", + "0x04" : "0x0c", + "0x05" : "0x0c", + "0x06" : "0x0c", + "0x07" : "0x0c", + "0x08" : "0x0c", + "0x09" : "0x0c" + } + } + + }, + "transaction" : + { + "data" : "", + "gasLimit" : "600", + "gasPrice" : "1", + "nonce" : "", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "d2571607e241ecf590ed94b12d87c94babe36db6", + "value" : "10" + } + }, + + "ContractStoreClearsOOG" : { + "env" : { + "currentCoinbase" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "currentDifficulty" : "45678256", + "currentGasLimit" : "10000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "7000", + "code" : "", + "nonce" : "0", + "storage" : { + } + }, + + "d2571607e241ecf590ed94b12d87c94babe36db6" : { + "balance" : "0", + "code" : "{(SSTORE 0 0)(SSTORE 1 0)(SSTORE 2 0)(SSTORE 3 0)(SSTORE 4 0)(SSTORE 5 0)(SSTORE 6 0)(SSTORE 7 0)(SSTORE 8 0)(SSTORE 9 12)}", + "nonce" : "0", + "storage" : { + "0x" : "0x0c", + "0x01" : "0x0c", + "0x02" : "0x0c", + "0x03" : "0x0c", + "0x04" : "0x0c", + "0x05" : "0x0c", + "0x06" : "0x0c", + "0x07" : "0x0c", + "0x08" : "0x0c", + "0x09" : "0x0c" + } + } + + }, + "transaction" : + { + "data" : "", + "gasLimit" : "600", + "gasPrice" : "1", + "nonce" : "", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "d2571607e241ecf590ed94b12d87c94babe36db6", + "value" : "10" + } + }, + + "TransactionTooManyRlpElements" : { + "env" : { + "currentCoinbase" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "currentDifficulty" : "45678256", + "currentGasLimit" : "10000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000", + "code" : "", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "data" : "", + "gasLimit" : "600", + "gasLimit" : "1600", + "gasPrice" : "1", + "gasPrice" : "12", + "nonce" : "", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d9", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "d2571607e241ecf590ed94b12d87c94babe36db6", + "value" : "10" + } + }, + } From 33c04f975d65ae306e21830e67d8763986e65bb6 Mon Sep 17 00:00:00 2001 From: wanderer Date: Mon, 29 Dec 2014 10:02:06 -0500 Subject: [PATCH 17/18] added balance tests --- test/stSystemOperationsTestFiller.json | 102 +++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/test/stSystemOperationsTestFiller.json b/test/stSystemOperationsTestFiller.json index 9fc8db773..34ab5078a 100644 --- a/test/stSystemOperationsTestFiller.json +++ b/test/stSystemOperationsTestFiller.json @@ -1410,5 +1410,107 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } + }, + + "callValue": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[0]] (CALLVALUE) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "currentAccountBalance": { + "env": { + "previousHash": "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber": "0", + "currentGasLimit": "10000000", + "currentDifficulty": "256", + "currentTimestamp": 1, + "currentCoinbase": "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre": { + "095e7baea6a6c7c4c2dfeb977efac326af552d87": { + "balance": "1000000000000000000", + "nonce": 0, + "code": "{ [[0]] (balance (address)) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "1000000000000000000", + "nonce": 0, + "code": "", + "storage": {} + } + }, + "transaction": { + "nonce": "0", + "gasPrice": "1", + "gasLimit": "10000000", + "to": "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value": "100000", + "secretKey": "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data": "" + } + }, + + "callerAccountBalance": { + "env": { + "previousHash": "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber": "0", + "currentGasLimit": "10000000", + "currentDifficulty": "256", + "currentTimestamp": 1, + "currentCoinbase": "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre": { + "095e7baea6a6c7c4c2dfeb977efac326af552d87": { + "balance": "1000000000000000000", + "nonce": 0, + "code": "{ [[0]] (balance (caller)) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "1000000000000000000", + "nonce": 0, + "code": "", + "storage": {} + } + }, + "transaction": { + "nonce": "0", + "gasPrice": "1", + "gasLimit": "10000000", + "to": "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value": "100000", + "secretKey": "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data": "" } + } } From 25a744c13d26f44f57a6346fc8e2b0a298fc876b Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 2 Jan 2015 15:10:53 +0000 Subject: [PATCH 18/18] JUMPDESTs must be explicit. --- libevm/VM.h | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/libevm/VM.h b/libevm/VM.h index 64353e2db..47efbfcba 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -83,29 +83,9 @@ inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _st auto memNeed = [](dev::u256 _offset, dev::u256 _size) { return _size ? (bigint)_offset + _size : (bigint)0; }; if (m_jumpDests.empty()) - { - std::set implicit; for (unsigned i = 0; i < _ext.code.size(); ++i) if (_ext.code[i] == (byte)Instruction::JUMPDEST) m_jumpDests.insert(i); - else if (_ext.code[i] >= (byte)Instruction::PUSH1 && _ext.code[i] <= (byte)Instruction::PUSH32) - { - int in = _ext.code[i] - (unsigned)Instruction::PUSH1 + 1; - u256 p = 0; - for (i++; in--; i++) - p = (p << 8) | _ext.getCode(i); - if ((_ext.getCode(i) == (byte)Instruction::JUMP || _ext.getCode(i) == (byte)Instruction::JUMPI) && !(_ext.getCode(p) == (byte)Instruction::JUMP || _ext.getCode(p) == (byte)Instruction::JUMPI)) - if (p >= _ext.code.size()) - m_jumpDests.insert(p); - else - implicit.insert(p); - else {} - i--; - } - for (unsigned i = 0; i < _ext.code.size(); i += instructionInfo((Instruction)_ext.getCode(i)).additional + 1) - if (implicit.count(i)) - m_jumpDests.insert(i); - } u256 nextPC = m_curPC + 1; auto osteps = _steps;