diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index c40e8f6a0..9ee3f36e3 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1458,7 +1458,7 @@ void Main::on_debugCurrent_triggered() } } -void Main::on_debugDumpState_triggered(int _add) +void Main::debugDumpState(int _add) { if (auto item = ui->blocks->currentItem()) { @@ -1479,11 +1479,6 @@ void Main::on_debugDumpState_triggered(int _add) } } -void Main::on_debugDumpStatePre_triggered() -{ - on_debugDumpState_triggered(0); -} - void Main::on_contracts_currentItemChanged() { ui->contractInfo->clear(); @@ -1511,7 +1506,7 @@ void Main::on_contracts_currentItemChanged() } } -void Main::on_idealPeers_valueChanged() +void Main::on_idealPeers_valueChanged(int) { m_webThree->setIdealPeerCount(ui->idealPeers->value()); } @@ -1523,11 +1518,11 @@ void Main::on_ourAccounts_doubleClicked() qApp->clipboard()->setText(QString::fromStdString(toHex(h.asArray()))); } -void Main::on_log_doubleClicked() +/*void Main::on_log_doubleClicked() { ui->log->setPlainText(""); m_logHistory.clear(); -} +}*/ void Main::on_accounts_doubleClicked() { @@ -1634,7 +1629,7 @@ void Main::on_net_triggered() { web3()->setIdealPeerCount(ui->idealPeers->value()); web3()->setNetworkPreferences(netPrefs()); - ethereum()->setNetworkId(m_privateChain.size() ? sha3(m_privateChain.toStdString()) : 0); + ethereum()->setNetworkId(m_privateChain.size() ? sha3(m_privateChain.toStdString()) : h256()); // TODO: p2p // if (m_networkConfig.size()/* && ui->usePast->isChecked()*/) // web3()->restoreNetwork(bytesConstRef((byte*)m_networkConfig.data(), m_networkConfig.size())); diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 52b98d293..638469fbe 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -109,7 +109,7 @@ private slots: void on_go_triggered(); void on_net_triggered(); void on_connect_triggered(); - void on_idealPeers_valueChanged(); + void on_idealPeers_valueChanged(int); // Mining void on_mine_triggered(); @@ -142,7 +142,7 @@ private slots: void on_blocks_currentItemChanged(); // Logging - void on_log_doubleClicked(); +// void on_log_doubleClicked(); void on_verbosity_valueChanged(); // Misc @@ -162,8 +162,8 @@ private slots: // Debugger void on_debugCurrent_triggered(); - void on_debugDumpState_triggered(int _add = 1); - void on_debugDumpStatePre_triggered(); + void on_debugDumpState_triggered() { debugDumpState(1); } + void on_debugDumpStatePre_triggered() { debugDumpState(0); } // Whisper void on_newIdentity_triggered(); @@ -177,6 +177,8 @@ signals: void poll(); private: + void debugDumpState(int _add); + dev::p2p::NetworkPreferences netPrefs() const; QString lookup(QString const& _n) const; diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp index 1b9a62a2d..c59c80c39 100644 --- a/alethzero/Transact.cpp +++ b/alethzero/Transact.cpp @@ -55,7 +55,7 @@ Transact::Transact(Context* _c, QWidget* _parent): ui->valueUnits->setCurrentIndex(6); ui->gasPriceUnits->setCurrentIndex(4); ui->gasPrice->setValue(10); - on_destination_currentTextChanged(); + on_destination_currentTextChanged(QString()); } Transact::~Transact() @@ -147,7 +147,7 @@ string Transact::getFunctionHashes(dev::solidity::CompilerStack const& _compiler return ret; } -void Transact::on_destination_currentTextChanged() +void Transact::on_destination_currentTextChanged(QString) { if (ui->destination->currentText().size() && ui->destination->currentText() != "(Create Contract)") if (Address a = m_context->fromString(ui->destination->currentText())) diff --git a/alethzero/Transact.h b/alethzero/Transact.h index afb45f62d..f14005eff 100644 --- a/alethzero/Transact.h +++ b/alethzero/Transact.h @@ -44,12 +44,12 @@ public: void setEnvironment(QList _myKeys, dev::eth::Client* _eth, NatSpecFace* _natSpecDB); private slots: - void on_destination_currentTextChanged(); - void on_value_valueChanged() { updateFee(); } - void on_gas_valueChanged() { updateFee(); } - void on_valueUnits_currentIndexChanged() { updateFee(); } - void on_gasPriceUnits_currentIndexChanged() { updateFee(); } - void on_gasPrice_valueChanged() { updateFee(); } + void on_destination_currentTextChanged(QString); + void on_value_valueChanged(int) { updateFee(); } + void on_gas_valueChanged(int) { updateFee(); } + void on_valueUnits_currentIndexChanged(int) { updateFee(); } + void on_gasPriceUnits_currentIndexChanged(int) { updateFee(); } + void on_gasPrice_valueChanged(int) { updateFee(); } void on_data_textChanged() { rejigData(); } void on_optimize_clicked() { rejigData(); } void on_send_clicked(); diff --git a/evmjit/evmcc/test/arith/addmod.evm b/evmjit/evmcc/test/arith/addmod.evm deleted file mode 100644 index 4ca71e065..000000000 --- a/evmjit/evmcc/test/arith/addmod.evm +++ /dev/null @@ -1 +0,0 @@ -60646107b760271460005560006001f2 diff --git a/evmjit/evmcc/test/arith/addmod.lll b/evmjit/evmcc/test/arith/addmod.lll deleted file mode 100644 index 11a6b2cb9..000000000 --- a/evmjit/evmcc/test/arith/addmod.lll +++ /dev/null @@ -1,12 +0,0 @@ -;; Should return (1975 + 39) `mod` 100 = 14 = 0x0e -(asm -100 -1975 -39 -ADDMOD -0 -MSTORE8 -0 -1 -RETURN -) \ No newline at end of file diff --git a/evmjit/evmcc/test/arith/arith1.evm b/evmjit/evmcc/test/arith/arith1.evm deleted file mode 100644 index c7a029f52..000000000 --- a/evmjit/evmcc/test/arith/arith1.evm +++ /dev/null @@ -1 +0,0 @@ -60016001900160070260050160029004600490066021900560150160030260059007600303600960110860005460086000f2 diff --git a/evmjit/evmcc/test/arith/arith1.lll b/evmjit/evmcc/test/arith/arith1.lll deleted file mode 100644 index 4757a7420..000000000 --- a/evmjit/evmcc/test/arith/arith1.lll +++ /dev/null @@ -1,37 +0,0 @@ - -(asm -1 -1 -SWAP1 -ADD ;; 2 -7 -MUL ;; 14 -5 -ADD ;; 19 -2 -SWAP1 -DIV ;; 9 -4 -SWAP1 -MOD ;; 1 -33 -SWAP1 -SDIV;; 0 -21 -ADD ;; 21 -3 -MUL ;; 63 -5 -SWAP1 -SMOD;; 3 -3 -SUB ;; 0 -9 -17 -EXP ;; 17^9 -0 -MSTORE -8 -0 -RETURN -) \ No newline at end of file diff --git a/evmjit/evmcc/test/arith/arith_bnot.evm b/evmjit/evmcc/test/arith/arith_bnot.evm deleted file mode 100644 index 4cfaf8f55..000000000 --- a/evmjit/evmcc/test/arith/arith_bnot.evm +++ /dev/null @@ -1 +0,0 @@ -6201e2406000546000530960005460206000f2 diff --git a/evmjit/evmcc/test/arith/arith_bnot.lll b/evmjit/evmcc/test/arith/arith_bnot.lll deleted file mode 100644 index a83b05a9a..000000000 --- a/evmjit/evmcc/test/arith/arith_bnot.lll +++ /dev/null @@ -1,14 +0,0 @@ - -(asm -123456 -0 -MSTORE -0 -MLOAD -BNOT -0 -MSTORE -32 -0 -RETURN -) \ No newline at end of file diff --git a/evmjit/evmcc/test/arith/div.evm b/evmjit/evmcc/test/arith/div.evm deleted file mode 100644 index b68d5d202..000000000 --- a/evmjit/evmcc/test/arith/div.evm +++ /dev/null @@ -1 +0,0 @@ -60027ffedcba9876543210fedcba9876543210fedcba9876543210fedcba98765432100460005460206000f2 diff --git a/evmjit/evmcc/test/arith/div.lll b/evmjit/evmcc/test/arith/div.lll deleted file mode 100644 index 72c22bfdc..000000000 --- a/evmjit/evmcc/test/arith/div.lll +++ /dev/null @@ -1,10 +0,0 @@ -(asm -0x2 -0xfedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210 -DIV -0 -MSTORE -32 -0 -RETURN -) diff --git a/evmjit/evmcc/test/arith/fib1.evm b/evmjit/evmcc/test/arith/fib1.evm deleted file mode 100644 index 4c141314e..000000000 --- a/evmjit/evmcc/test/arith/fib1.evm +++ /dev/null @@ -1 +0,0 @@ -60016001818101818101818101818101818101818101818101818101818101818101818101818101818101818101818101818101818101 diff --git a/evmjit/evmcc/test/arith/fib1.lll b/evmjit/evmcc/test/arith/fib1.lll deleted file mode 100644 index 286bed275..000000000 --- a/evmjit/evmcc/test/arith/fib1.lll +++ /dev/null @@ -1,57 +0,0 @@ -;; Fibbonacci unrolled - -(asm -1 -1 -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -DUP2 -DUP2 -ADD -) \ No newline at end of file diff --git a/evmjit/evmcc/test/arith/mul.evm b/evmjit/evmcc/test/arith/mul.evm deleted file mode 100644 index 7e8afd268..000000000 --- a/evmjit/evmcc/test/arith/mul.evm +++ /dev/null @@ -1 +0,0 @@ -7001234567890abcdef0fedcba09876543217001234567890abcdef0fedcba09876543217001234567890abcdef0fedcba0987654321020260005460206000f2 diff --git a/evmjit/evmcc/test/arith/mul.lll b/evmjit/evmcc/test/arith/mul.lll deleted file mode 100644 index b0fa343bb..000000000 --- a/evmjit/evmcc/test/arith/mul.lll +++ /dev/null @@ -1,13 +0,0 @@ -(asm -0x1234567890abcdef0fedcba0987654321 -0x1234567890abcdef0fedcba0987654321 -0x1234567890abcdef0fedcba0987654321 -MUL -MUL -0 -MSTORE -32 -0 -RETURN -;; 47d0817e4167b1eb4f9fc722b133ef9d7d9a6fb4c2c1c442d000107a5e419561 -) diff --git a/evmjit/evmcc/test/arith/mulmod.evm b/evmjit/evmcc/test/arith/mulmod.evm deleted file mode 100644 index e34a06154..000000000 --- a/evmjit/evmcc/test/arith/mulmod.evm +++ /dev/null @@ -1 +0,0 @@ -6064601b60251560005560006001f2 diff --git a/evmjit/evmcc/test/arith/mulmod.lll b/evmjit/evmcc/test/arith/mulmod.lll deleted file mode 100644 index 5e87f0843..000000000 --- a/evmjit/evmcc/test/arith/mulmod.lll +++ /dev/null @@ -1,12 +0,0 @@ -;; Should return (27 * 37) `mod` 100 = 99 = 0x63 -(asm -100 -27 -37 -MULMOD -0 -MSTORE8 -0 -1 -RETURN -) \ No newline at end of file diff --git a/evmjit/evmcc/test/except/badinst1.evm b/evmjit/evmcc/test/except/badinst1.evm deleted file mode 100644 index 69aadac5e..000000000 --- a/evmjit/evmcc/test/except/badinst1.evm +++ /dev/null @@ -1 +0,0 @@ -4a diff --git a/evmjit/evmcc/test/ext/calldatacopy1.evm b/evmjit/evmcc/test/ext/calldatacopy1.evm deleted file mode 100644 index f20019651..000000000 --- a/evmjit/evmcc/test/ext/calldatacopy1.evm +++ /dev/null @@ -1 +0,0 @@ -60326000600a37600053600a6014f2 diff --git a/evmjit/evmcc/test/ext/calldatacopy1.lll b/evmjit/evmcc/test/ext/calldatacopy1.lll deleted file mode 100644 index 3d2ae0a78..000000000 --- a/evmjit/evmcc/test/ext/calldatacopy1.lll +++ /dev/null @@ -1,13 +0,0 @@ -(asm -50 ;; byte count -0 ;; source index in calldata array -10 ;; dest index in memory -CALLDATACOPY - -0 -MLOAD ;; to dump memory - -10 -20 -RETURN -) \ No newline at end of file diff --git a/evmjit/evmcc/test/ext/calldatacopy2.evm b/evmjit/evmcc/test/ext/calldatacopy2.evm deleted file mode 100644 index e8eea8da7..000000000 --- a/evmjit/evmcc/test/ext/calldatacopy2.evm +++ /dev/null @@ -1 +0,0 @@ -606464e8d4a510006000376000536000600af2 diff --git a/evmjit/evmcc/test/ext/calldatacopy2.lll b/evmjit/evmcc/test/ext/calldatacopy2.lll deleted file mode 100644 index 6bbea48d8..000000000 --- a/evmjit/evmcc/test/ext/calldatacopy2.lll +++ /dev/null @@ -1,13 +0,0 @@ -(asm -100 ;; byte count -1000000000000 ;; source index in calldata array -0 ;; dest index in memory -CALLDATACOPY - -0 -MLOAD ;; to dump memory - -0 -10 -RETURN -) \ No newline at end of file diff --git a/evmjit/evmcc/test/ext/codecopy1.evm b/evmjit/evmcc/test/ext/codecopy1.evm deleted file mode 100644 index d286f9232..000000000 --- a/evmjit/evmcc/test/ext/codecopy1.evm +++ /dev/null @@ -1 +0,0 @@ -60146000600a39600053600a6014f2 diff --git a/evmjit/evmcc/test/ext/codecopy1.lll b/evmjit/evmcc/test/ext/codecopy1.lll deleted file mode 100644 index 85a02b5d7..000000000 --- a/evmjit/evmcc/test/ext/codecopy1.lll +++ /dev/null @@ -1,13 +0,0 @@ -(asm -20 ;; byte count -0 ;; source index in code array -10 ;; dest index in memory -CODECOPY - -0 -MLOAD ;; to dump memory - -10 -20 -RETURN -) \ No newline at end of file diff --git a/evmjit/evmcc/test/ext/codecopy2.evm b/evmjit/evmcc/test/ext/codecopy2.evm deleted file mode 100644 index 71cd92525..000000000 --- a/evmjit/evmcc/test/ext/codecopy2.evm +++ /dev/null @@ -1 +0,0 @@ -606464e8d4a510006000396000536000600af2 diff --git a/evmjit/evmcc/test/ext/codecopy2.lll b/evmjit/evmcc/test/ext/codecopy2.lll deleted file mode 100644 index dcbbcaa46..000000000 --- a/evmjit/evmcc/test/ext/codecopy2.lll +++ /dev/null @@ -1,13 +0,0 @@ -(asm -100 ;; byte count -1000000000000 ;; source index in code array -0 ;; dest index in memory -CODECOPY - -0 -MLOAD ;; to dump memory - -0 -10 -RETURN -) \ No newline at end of file diff --git a/evmjit/evmcc/test/ext/codecopy3.evm b/evmjit/evmcc/test/ext/codecopy3.evm deleted file mode 100644 index e4b6a9253..000000000 --- a/evmjit/evmcc/test/ext/codecopy3.evm +++ /dev/null @@ -1 +0,0 @@ -3860006000396000536000600af2 diff --git a/evmjit/evmcc/test/ext/codecopy3.lll b/evmjit/evmcc/test/ext/codecopy3.lll deleted file mode 100644 index 80d9982c6..000000000 --- a/evmjit/evmcc/test/ext/codecopy3.lll +++ /dev/null @@ -1,13 +0,0 @@ -(asm -CODESIZE ;; byte count -0 ;; source index in code array -0 ;; dest index in memory -CODECOPY - -0 -MLOAD ;; to dump memory - -0 -10 -RETURN -) \ No newline at end of file diff --git a/evmjit/evmcc/test/ext/ext_test.evm b/evmjit/evmcc/test/ext/ext_test.evm deleted file mode 100644 index 580bd9675..000000000 --- a/evmjit/evmcc/test/ext/ext_test.evm +++ /dev/null @@ -1 +0,0 @@ -5a3031333234363a4041424344455a36600035602635601335387f1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff600054602060006000f06020600060206000600030610bb8f1600053611000545b60200260002030ff60016002f2 diff --git a/evmjit/evmcc/test/ext/ext_test.lll b/evmjit/evmcc/test/ext/ext_test.lll deleted file mode 100644 index 3287ae95f..000000000 --- a/evmjit/evmcc/test/ext/ext_test.lll +++ /dev/null @@ -1,55 +0,0 @@ - -(asm -PC -ADDRESS -BALANCE -CALLER -ORIGIN -CALLVALUE -CALLDATASIZE -GASPRICE -PREVHASH -COINBASE -TIMESTAMP -NUMBER -DIFFICULTY -GASLIMIT -PC -CALLDATASIZE -0 -CALLDATALOAD -38 -CALLDATALOAD -19 -CALLDATALOAD -CODESIZE -0x1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff -0 -MSTORE -32 -0 -0 -CREATE -32 -0 -32 -0 -0 -ADDRESS -3000 -CALL -0 -MLOAD -4096 -MSTORE -MSIZE -32 -MUL -0 -SHA3 -ADDRESS -SUICIDE -1 -2 -RETURN -) \ No newline at end of file diff --git a/evmjit/evmcc/test/ext/extcodecopy1.evm b/evmjit/evmcc/test/ext/extcodecopy1.evm deleted file mode 100644 index 6132b52d8..000000000 --- a/evmjit/evmcc/test/ext/extcodecopy1.evm +++ /dev/null @@ -1 +0,0 @@ -60c86000600a303c60005360006020f2 diff --git a/evmjit/evmcc/test/ext/extcodecopy1.lll b/evmjit/evmcc/test/ext/extcodecopy1.lll deleted file mode 100644 index c37054574..000000000 --- a/evmjit/evmcc/test/ext/extcodecopy1.lll +++ /dev/null @@ -1,11 +0,0 @@ -(asm -200 ;; byte count -0 ;; source index in code array -10 ;; dest index in memory -ADDRESS -EXTCODECOPY - -0 MLOAD ;; to dump memory - -0 32 RETURN -) \ No newline at end of file diff --git a/evmjit/evmcc/test/ext/store_delete.evm b/evmjit/evmcc/test/ext/store_delete.evm deleted file mode 100644 index d6acae03d..000000000 --- a/evmjit/evmcc/test/ext/store_delete.evm +++ /dev/null @@ -1 +0,0 @@ -6104d26063576000606357 diff --git a/evmjit/evmcc/test/ext/store_delete.lll b/evmjit/evmcc/test/ext/store_delete.lll deleted file mode 100644 index 3d8f0f23a..000000000 --- a/evmjit/evmcc/test/ext/store_delete.lll +++ /dev/null @@ -1,9 +0,0 @@ - -(asm -1234 -99 -SSTORE -0 -99 -SSTORE -) \ No newline at end of file diff --git a/evmjit/evmcc/test/ext/store_test.evm b/evmjit/evmcc/test/ext/store_test.evm deleted file mode 100644 index 54c9419b5..000000000 --- a/evmjit/evmcc/test/ext/store_test.evm +++ /dev/null @@ -1 +0,0 @@ -607b607c60015760005760015660005603 diff --git a/evmjit/evmcc/test/ext/store_test.lll b/evmjit/evmcc/test/ext/store_test.lll deleted file mode 100644 index c40471c40..000000000 --- a/evmjit/evmcc/test/ext/store_test.lll +++ /dev/null @@ -1,14 +0,0 @@ - -(asm -123 -124 -1 -SSTORE -0 -SSTORE -1 -SLOAD -0 -SLOAD -SUB -) \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/ackermann.ethel b/evmjit/evmcc/test/jump/ackermann.ethel deleted file mode 100644 index 971fd2b8d..000000000 --- a/evmjit/evmcc/test/jump/ackermann.ethel +++ /dev/null @@ -1,7 +0,0 @@ -let A m n = - if m == 0 then n+1 - else if n == 0 then A (m-1) 1 - else A (m-1) (A (m) (n-1)) - -return A 3 8 - diff --git a/evmjit/evmcc/test/jump/ackermann.evm b/evmjit/evmcc/test/jump/ackermann.evm deleted file mode 100644 index 964844045..000000000 --- a/evmjit/evmcc/test/jump/ackermann.evm +++ /dev/null @@ -1 +0,0 @@ -6009600360086012585d60005460206000f26000820e6047596000810e603859603460018303603084600185036012585d6012585d60445860436001830360016012585d604b5860018101905090509058 \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/badindirect1.evm b/evmjit/evmcc/test/jump/badindirect1.evm deleted file mode 100644 index b2a8aad67..000000000 --- a/evmjit/evmcc/test/jump/badindirect1.evm +++ /dev/null @@ -1 +0,0 @@ -601b602502585d diff --git a/evmjit/evmcc/test/jump/badindirect1.lll b/evmjit/evmcc/test/jump/badindirect1.lll deleted file mode 100644 index d6291be68..000000000 --- a/evmjit/evmcc/test/jump/badindirect1.lll +++ /dev/null @@ -1,9 +0,0 @@ -;; Indirect jump out of code - -(asm -27 -37 -MUL -JUMP -JUMPDEST -) \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/badindirect2.evm b/evmjit/evmcc/test/jump/badindirect2.evm deleted file mode 100644 index 22217523d..000000000 --- a/evmjit/evmcc/test/jump/badindirect2.evm +++ /dev/null @@ -1 +0,0 @@ -60016003600302596000600058 diff --git a/evmjit/evmcc/test/jump/badindirect2.lll b/evmjit/evmcc/test/jump/badindirect2.lll deleted file mode 100644 index 53a6294f7..000000000 --- a/evmjit/evmcc/test/jump/badindirect2.lll +++ /dev/null @@ -1,12 +0,0 @@ -;; Indirect jump into data - -(asm -1 ;; 0 -3 -3 -MUL ;; 6 -JUMPI ;; 7 -0 ;; 8 -0 -JUMP -) \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/badjump1.evm b/evmjit/evmcc/test/jump/badjump1.evm deleted file mode 100644 index 5c11a8661..000000000 --- a/evmjit/evmcc/test/jump/badjump1.evm +++ /dev/null @@ -1 +0,0 @@ -6103e758 diff --git a/evmjit/evmcc/test/jump/badjump1.lll b/evmjit/evmcc/test/jump/badjump1.lll deleted file mode 100644 index 1834a62ef..000000000 --- a/evmjit/evmcc/test/jump/badjump1.lll +++ /dev/null @@ -1,6 +0,0 @@ -;; Direct jump out of code. - -(asm -999 -JUMP -) \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/badjump2.evm b/evmjit/evmcc/test/jump/badjump2.evm deleted file mode 100644 index 900a1c15a..000000000 --- a/evmjit/evmcc/test/jump/badjump2.evm +++ /dev/null @@ -1 +0,0 @@ -6004586000600058 diff --git a/evmjit/evmcc/test/jump/badjump2.lll b/evmjit/evmcc/test/jump/badjump2.lll deleted file mode 100644 index ce61276d7..000000000 --- a/evmjit/evmcc/test/jump/badjump2.lll +++ /dev/null @@ -1,9 +0,0 @@ -;; Direct jump into data - -(asm -4 ;; 0 0-3 -JUMP ;; 2 -0 ;; 3 3-4 -0 ;; 5 4-7 -JUMP ;; 6 -) \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/call1.ethel b/evmjit/evmcc/test/jump/call1.ethel deleted file mode 100644 index 414ad0124..000000000 --- a/evmjit/evmcc/test/jump/call1.ethel +++ /dev/null @@ -1,5 +0,0 @@ -let f n = n + 1 - -return f 2 - - diff --git a/evmjit/evmcc/test/jump/call1.evm b/evmjit/evmcc/test/jump/call1.evm deleted file mode 100644 index 252aaf778..000000000 --- a/evmjit/evmcc/test/jump/call1.evm +++ /dev/null @@ -1 +0,0 @@ -600760026010585d60005460206000f28060010190509058 \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/call2.ethel b/evmjit/evmcc/test/jump/call2.ethel deleted file mode 100644 index bdeb9b734..000000000 --- a/evmjit/evmcc/test/jump/call2.ethel +++ /dev/null @@ -1,5 +0,0 @@ -let f a b = a + b - -return f 2 3 - - diff --git a/evmjit/evmcc/test/jump/call2.evm b/evmjit/evmcc/test/jump/call2.evm deleted file mode 100644 index 6832e044d..000000000 --- a/evmjit/evmcc/test/jump/call2.evm +++ /dev/null @@ -1 +0,0 @@ -6009600260036012585d60005460206000f2818101905090509058 \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/fac.ethel b/evmjit/evmcc/test/jump/fac.ethel deleted file mode 100644 index 8bfe94dd6..000000000 --- a/evmjit/evmcc/test/jump/fac.ethel +++ /dev/null @@ -1,5 +0,0 @@ -let fac n = - if n == 0 then 1 - else n * fac (n-1) - -return fac 60 \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/fac.evm b/evmjit/evmcc/test/jump/fac.evm deleted file mode 100644 index 04cd3e4f4..000000000 --- a/evmjit/evmcc/test/jump/fac.evm +++ /dev/null @@ -1 +0,0 @@ -6007603c6010585d60005460206000f26000810e6026596020600182036010585d8102602858600190509058 \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/fac_tail.ethel b/evmjit/evmcc/test/jump/fac_tail.ethel deleted file mode 100644 index 9ce5ecac7..000000000 --- a/evmjit/evmcc/test/jump/fac_tail.ethel +++ /dev/null @@ -1,5 +0,0 @@ -let fac a n = - if n == 0 then a - else fac (a*n) (n-1) - -return fac 1 60 \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/fac_tail.evm b/evmjit/evmcc/test/jump/fac_tail.evm deleted file mode 100644 index 8384d94e4..000000000 --- a/evmjit/evmcc/test/jump/fac_tail.evm +++ /dev/null @@ -1 +0,0 @@ -60096001603c6012585d60005460206000f26000810e6029596025818302600183036012585d602a5881905090509058 \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/fib1.ethel b/evmjit/evmcc/test/jump/fib1.ethel deleted file mode 100644 index 81b869f41..000000000 --- a/evmjit/evmcc/test/jump/fib1.ethel +++ /dev/null @@ -1,6 +0,0 @@ -let fib n = - if n < 3 then 1 - else fib (n-1) + fib (n-2) - -return fib 10 - diff --git a/evmjit/evmcc/test/jump/fib1.evm b/evmjit/evmcc/test/jump/fib1.evm deleted file mode 100644 index 5042a192f..000000000 --- a/evmjit/evmcc/test/jump/fib1.evm +++ /dev/null @@ -1 +0,0 @@ -6007600a6010585d60005460206000f26003810a602f596020600282036010585d602a600183036010585d01603158600190509058 \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/for1.evm b/evmjit/evmcc/test/jump/for1.evm deleted file mode 100644 index f8e65cbf2..000000000 --- a/evmjit/evmcc/test/jump/for1.evm +++ /dev/null @@ -1 +0,0 @@ -600a60805460006080530b0f60255960a0536080530160a054600160805303608054600558 diff --git a/evmjit/evmcc/test/jump/for1.lll b/evmjit/evmcc/test/jump/for1.lll deleted file mode 100644 index 419fc9b54..000000000 --- a/evmjit/evmcc/test/jump/for1.lll +++ /dev/null @@ -1,3 +0,0 @@ -(for [i]:10 (> @i 0) [i](- @i 1) - [j](+ @i @j) -) diff --git a/evmjit/evmcc/test/jump/for2.evm b/evmjit/evmcc/test/jump/for2.evm deleted file mode 100644 index 628297778..000000000 --- a/evmjit/evmcc/test/jump/for2.evm +++ /dev/null @@ -1 +0,0 @@ -6000608054600a6080530a0f60255960a0536080530160a054600160805301608054600558 diff --git a/evmjit/evmcc/test/jump/for2.lll b/evmjit/evmcc/test/jump/for2.lll deleted file mode 100644 index de17d65ac..000000000 --- a/evmjit/evmcc/test/jump/for2.lll +++ /dev/null @@ -1,3 +0,0 @@ -(for [i]:0 (< @i 10) [i](+ @i 1) - [j](+ @i @j) -) diff --git a/evmjit/evmcc/test/jump/if1.ethel b/evmjit/evmcc/test/jump/if1.ethel deleted file mode 100644 index 85c3e126b..000000000 --- a/evmjit/evmcc/test/jump/if1.ethel +++ /dev/null @@ -1 +0,0 @@ -return if 0 then 1 else 2 \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/if1.evm b/evmjit/evmcc/test/jump/if1.evm deleted file mode 100644 index 51fbe04bd..000000000 --- a/evmjit/evmcc/test/jump/if1.evm +++ /dev/null @@ -1 +0,0 @@ -60006300000010596002630000001258600160005460206000f2 \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/if2.ethel b/evmjit/evmcc/test/jump/if2.ethel deleted file mode 100644 index 2a58d6365..000000000 --- a/evmjit/evmcc/test/jump/if2.ethel +++ /dev/null @@ -1 +0,0 @@ -return if 1 then 1 else 2 \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/if2.evm b/evmjit/evmcc/test/jump/if2.evm deleted file mode 100644 index 6d823b374..000000000 --- a/evmjit/evmcc/test/jump/if2.evm +++ /dev/null @@ -1 +0,0 @@ -60016300000010596002630000001258600160005460206000f2 \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/indirect1.evm b/evmjit/evmcc/test/jump/indirect1.evm deleted file mode 100644 index ab6928304..000000000 --- a/evmjit/evmcc/test/jump/indirect1.evm +++ /dev/null @@ -1 +0,0 @@ -600460030158005d6001600054 diff --git a/evmjit/evmcc/test/jump/indirect1.lll b/evmjit/evmcc/test/jump/indirect1.lll deleted file mode 100644 index 1ee7dc347..000000000 --- a/evmjit/evmcc/test/jump/indirect1.lll +++ /dev/null @@ -1,13 +0,0 @@ -;; Indirect JUMP - -(asm -4 ;; 0 -3 ;; 2 -ADD ;; 4 -JUMP ;; 5 -STOP ;; 6 -JUMPDEST ;; 7 -1 -0 -MSTORE -) \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/indirect2.evm b/evmjit/evmcc/test/jump/indirect2.evm deleted file mode 100644 index e9697eaa1..000000000 --- a/evmjit/evmcc/test/jump/indirect2.evm +++ /dev/null @@ -1 +0,0 @@ -600860060158005d6001600054005d600260005400 diff --git a/evmjit/evmcc/test/jump/indirect2.lll b/evmjit/evmcc/test/jump/indirect2.lll deleted file mode 100644 index f2f068630..000000000 --- a/evmjit/evmcc/test/jump/indirect2.lll +++ /dev/null @@ -1,19 +0,0 @@ -;; Indirect JUMP - -(asm -8 ;; 0 -6 ;; 2 -ADD ;; 4 -JUMP ;; 5 --> 14 -STOP ;; 6 -JUMPDEST ;; 7 -1 ;; 8 -0 ;; 10 -MSTORE ;; 12 -STOP ;; 13 -JUMPDEST ;; 14 -2 -0 -MSTORE -STOP -) \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/indirect3.evm b/evmjit/evmcc/test/jump/indirect3.evm deleted file mode 100644 index 1fb0a356c..000000000 --- a/evmjit/evmcc/test/jump/indirect3.evm +++ /dev/null @@ -1 +0,0 @@ -6001600460050159005d6001600054 diff --git a/evmjit/evmcc/test/jump/indirect3.lll b/evmjit/evmcc/test/jump/indirect3.lll deleted file mode 100644 index d6a679f9a..000000000 --- a/evmjit/evmcc/test/jump/indirect3.lll +++ /dev/null @@ -1,14 +0,0 @@ -;; Indirect JUMP - -(asm -1 ;; 0 -4 ;; 2 -5 ;; 4 -ADD ;; 6 -JUMPI ;; 7 -STOP ;; 8 -JUMPDEST ;; 9 -1 -0 -MSTORE -) \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/indirect4.evm b/evmjit/evmcc/test/jump/indirect4.evm deleted file mode 100644 index f0e31a8f4..000000000 --- a/evmjit/evmcc/test/jump/indirect4.evm +++ /dev/null @@ -1 +0,0 @@ -60006007600501596001600054005d00 diff --git a/evmjit/evmcc/test/jump/indirect4.lll b/evmjit/evmcc/test/jump/indirect4.lll deleted file mode 100644 index 7fbe0b833..000000000 --- a/evmjit/evmcc/test/jump/indirect4.lll +++ /dev/null @@ -1,15 +0,0 @@ -;; Indirect JUMP - -(asm -0 ;; 0 -7 ;; 2 -5 ;; 4 -ADD ;; 6 -JUMPI ;; 7 -1 ;; 8 -0 ;; 9 -MSTORE ;; 10 -STOP ;; 11 -JUMPDEST ;; 12 -STOP -) \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/jump1.evm b/evmjit/evmcc/test/jump/jump1.evm deleted file mode 100644 index 0df9b4036..000000000 --- a/evmjit/evmcc/test/jump/jump1.evm +++ /dev/null @@ -1 +0,0 @@ -600458006001600154 diff --git a/evmjit/evmcc/test/jump/jump1.lll b/evmjit/evmcc/test/jump/jump1.lll deleted file mode 100644 index 33119edb3..000000000 --- a/evmjit/evmcc/test/jump/jump1.lll +++ /dev/null @@ -1,11 +0,0 @@ -;; Direct JUMP. -;; output: memory[1] == 1 - -(asm -4 ;; 0 -JUMP ;; 2 -STOP ;; 3 -1 ;; 4 -1 ;; 6 -MSTORE ;; 8 -) \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/jump2.evm b/evmjit/evmcc/test/jump/jump2.evm deleted file mode 100644 index 35d75941d..000000000 --- a/evmjit/evmcc/test/jump/jump2.evm +++ /dev/null @@ -1 +0,0 @@ -6008586001600154 diff --git a/evmjit/evmcc/test/jump/jump2.lll b/evmjit/evmcc/test/jump/jump2.lll deleted file mode 100644 index a70d50ecb..000000000 --- a/evmjit/evmcc/test/jump/jump2.lll +++ /dev/null @@ -1,10 +0,0 @@ -;; Direct JUMP to the end of code. -;; output: memory should have size 0. - -(asm -8 ;; 0 -JUMP ;; 2 -1 ;; 3 -1 ;; 5 -MSTORE ;; 7 -) \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/jump3.evm b/evmjit/evmcc/test/jump/jump3.evm deleted file mode 100644 index 599d4a764..000000000 --- a/evmjit/evmcc/test/jump/jump3.evm +++ /dev/null @@ -1 +0,0 @@ -602a586001600154 diff --git a/evmjit/evmcc/test/jump/jump3.lll b/evmjit/evmcc/test/jump/jump3.lll deleted file mode 100644 index bc897e30c..000000000 --- a/evmjit/evmcc/test/jump/jump3.lll +++ /dev/null @@ -1,10 +0,0 @@ -;; Direct JUMP past the end of code. -;; output: memory should have size 0. - -(asm -42 -JUMP -1 -1 -MSTORE -) \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/jump4.evm b/evmjit/evmcc/test/jump/jump4.evm deleted file mode 100644 index 41713f43e..000000000 --- a/evmjit/evmcc/test/jump/jump4.evm +++ /dev/null @@ -1 +0,0 @@ -600b6009580000600558005d6001600154 diff --git a/evmjit/evmcc/test/jump/jump4.lll b/evmjit/evmcc/test/jump/jump4.lll deleted file mode 100644 index 131baee2d..000000000 --- a/evmjit/evmcc/test/jump/jump4.lll +++ /dev/null @@ -1,17 +0,0 @@ -;; Direct JUMP. -;; output: memory[1] = 1 - -(asm -11 ;; 0 -9 ;; 2 -JUMP ;; 4 --> 9 -STOP ;; 5 -STOP ;; 6 -5 ;; 7 -JUMP ;; 9 --> 11 -STOP ;; 10 -JUMPDEST -1 ;; 11 -1 -MSTORE -) \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/jump5.evm b/evmjit/evmcc/test/jump/jump5.evm deleted file mode 100644 index c36d9615b..000000000 --- a/evmjit/evmcc/test/jump/jump5.evm +++ /dev/null @@ -1 +0,0 @@ -6005600e585d600160015400600f5800 diff --git a/evmjit/evmcc/test/jump/jump5.lll b/evmjit/evmcc/test/jump/jump5.lll deleted file mode 100644 index d28b7d4ac..000000000 --- a/evmjit/evmcc/test/jump/jump5.lll +++ /dev/null @@ -1,16 +0,0 @@ -;; Direct JUMP. -;; output: memory[1] = 1 - -(asm -5 ;; 0 -14 ;; 2 -JUMP ;; 4 --> 14 -JUMPDEST ;; 5 -1 ;; 6 -1 ;; 8 -MSTORE ;; 10 -STOP ;; 11 -15 ;; 12 -JUMP ;; 14 --> 5 -STOP ;; 15 -) \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/jump6.evm b/evmjit/evmcc/test/jump/jump6.evm deleted file mode 100644 index 029db7191..000000000 --- a/evmjit/evmcc/test/jump/jump6.evm +++ /dev/null @@ -1 +0,0 @@ -600358600f600d58006014600758005d6001600154005d600260025400 diff --git a/evmjit/evmcc/test/jump/jump6.lll b/evmjit/evmcc/test/jump/jump6.lll deleted file mode 100644 index 1116aa663..000000000 --- a/evmjit/evmcc/test/jump/jump6.lll +++ /dev/null @@ -1,32 +0,0 @@ -;; Direct JUMP. -;; output: memory[1] = 1 - -;; 0, 2 --> 3 .. 7 --> 13 -*-> 15 .. 19 - -(asm -3 ;; 0 -JUMP ;; 2 - -15 ;; 3 <- start -13 ;; 5 -JUMP ;; 7 <- b -STOP ;; 8 - -20 ;; 9 -7 ;; 11 - -JUMP ;; 13 <- a -STOP ;; 14 - -JUMPDEST ;; 15 <- c -1 ;; 16 -1 ;; 18 -MSTORE ;; 19 -STOP ;; 20 - -JUMPDEST ;; 21 <- d -2 ;; 22 -2 ;; 24 -MSTORE ;; 26 -STOP ;; 27 -) \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/jumpi_at_the_end.evm b/evmjit/evmcc/test/jump/jumpi_at_the_end.evm deleted file mode 100644 index 2d7411761..000000000 --- a/evmjit/evmcc/test/jump/jumpi_at_the_end.evm +++ /dev/null @@ -1 +0,0 @@ -600a6000545d6000536001900380600054600659 diff --git a/evmjit/evmcc/test/jump/jumpi_at_the_end.lll b/evmjit/evmcc/test/jump/jumpi_at_the_end.lll deleted file mode 100644 index 263ada6a7..000000000 --- a/evmjit/evmcc/test/jump/jumpi_at_the_end.lll +++ /dev/null @@ -1 +0,0 @@ -(asm 10 0 MSTORE JUMPDEST 0 MLOAD 1 SWAP1 SUB DUP1 0 MSTORE 6 JUMPI) \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/loop1.evm b/evmjit/evmcc/test/jump/loop1.evm deleted file mode 100644 index 7724d6308..000000000 --- a/evmjit/evmcc/test/jump/loop1.evm +++ /dev/null @@ -1 +0,0 @@ -600a600181038060025960005460015460025400 diff --git a/evmjit/evmcc/test/jump/loop1.lll b/evmjit/evmcc/test/jump/loop1.lll deleted file mode 100644 index 0044ec1fb..000000000 --- a/evmjit/evmcc/test/jump/loop1.lll +++ /dev/null @@ -1,27 +0,0 @@ -;; Produces 1 2 3 4 5 6 7 8 9 10 on the stack and exits - -(asm -10 - -;; 2 -1 -DUP2 -SUB -DUP1 -2 -JUMPI - -;; stack = 1 2 3 4 5 6 7 8 9 10 -0 -MSTORE -1 -MSTORE -2 -MSTORE -;;3 -;;MSTORE - -STOP -) - - diff --git a/evmjit/evmcc/test/jump/loop2.evm b/evmjit/evmcc/test/jump/loop2.evm deleted file mode 100644 index faffa4e5b..000000000 --- a/evmjit/evmcc/test/jump/loop2.evm +++ /dev/null @@ -1 +0,0 @@ -600a80600190038060025960005460015460025400 diff --git a/evmjit/evmcc/test/jump/loop2.lll b/evmjit/evmcc/test/jump/loop2.lll deleted file mode 100644 index 9996c52ba..000000000 --- a/evmjit/evmcc/test/jump/loop2.lll +++ /dev/null @@ -1,28 +0,0 @@ -;; Produces 1 2 3 4 5 6 7 8 9 10 on the stack and exits - -(asm -10 - -;; 2 -DUP1 -1 -SWAP1 -SUB -DUP1 -2 -JUMPI - -;; stack = 1 2 3 4 5 6 7 8 9 10 -0 -MSTORE -1 -MSTORE -2 -MSTORE -;;3 -;;MSTORE - -STOP -) - - diff --git a/evmjit/evmcc/test/jump/rec1.ethel b/evmjit/evmcc/test/jump/rec1.ethel deleted file mode 100644 index f83c8e81e..000000000 --- a/evmjit/evmcc/test/jump/rec1.ethel +++ /dev/null @@ -1,4 +0,0 @@ -let f n = - if n == 0 then 2 else f (n-1) - -return f 10 diff --git a/evmjit/evmcc/test/jump/rec1.evm b/evmjit/evmcc/test/jump/rec1.evm deleted file mode 100644 index 2ae62aff6..000000000 --- a/evmjit/evmcc/test/jump/rec1.evm +++ /dev/null @@ -1 +0,0 @@ -6007600a6010585d60005460206000f26000810e6024596020600182036010585d602658600290509058 \ No newline at end of file diff --git a/evmjit/evmcc/test/jump/when1.asm b/evmjit/evmcc/test/jump/when1.asm deleted file mode 100644 index 01d41c266..000000000 --- a/evmjit/evmcc/test/jump/when1.asm +++ /dev/null @@ -1,10 +0,0 @@ -.code: - PUSH 1 - NOT - PUSH [tag0] - JUMPI - PUSH 13 - PUSH 128 - MSTORE -tag0: - diff --git a/evmjit/evmcc/test/jump/when1.evm b/evmjit/evmcc/test/jump/when1.evm deleted file mode 100644 index 303b02623..000000000 --- a/evmjit/evmcc/test/jump/when1.evm +++ /dev/null @@ -1 +0,0 @@ -60010f600b59600d608054 diff --git a/evmjit/evmcc/test/jump/when1.lll b/evmjit/evmcc/test/jump/when1.lll deleted file mode 100644 index 990a6e64a..000000000 --- a/evmjit/evmcc/test/jump/when1.lll +++ /dev/null @@ -1,2 +0,0 @@ -(when (> 1 0) [i] 13) - \ No newline at end of file diff --git a/evmjit/evmcc/test/kv.evm b/evmjit/evmcc/test/kv.evm deleted file mode 100644 index 55141ea59..000000000 --- a/evmjit/evmcc/test/kv.evm +++ /dev/null @@ -1 +0,0 @@ -33604557602a8060106000396000f200604556330e0f602a59366080530a0f602a59602060805301356080533557604060805301608054600958 diff --git a/evmjit/evmcc/test/kv.lll b/evmjit/evmcc/test/kv.lll deleted file mode 100644 index c62d9fa70..000000000 --- a/evmjit/evmcc/test/kv.lll +++ /dev/null @@ -1,10 +0,0 @@ -{ - [[69]] (caller) - (return 0 (lll - (when (= (caller) @@69) - (for {} (< @i (calldatasize)) [i](+ @i 64) - [[ (calldataload @i) ]] (calldataload (+ @i 32)) - ) - ) - 0)) -} diff --git a/evmjit/evmcc/test/mem/byte.evm b/evmjit/evmcc/test/mem/byte.evm deleted file mode 100644 index ab63431ee..000000000 --- a/evmjit/evmcc/test/mem/byte.evm +++ /dev/null @@ -1 +0,0 @@ -7f112233445566778899001122334455667788990011223344556677889900aabb6000137f112233445566778899001122334455667788990011223344556677889900aabb6001137f112233445566778899001122334455667788990011223344556677889900aabb6002137f112233445566778899001122334455667788990011223344556677889900aabb6003137f112233445566778899001122334455667788990011223344556677889900aabb6004137f112233445566778899001122334455667788990011223344556677889900aabb6005137f112233445566778899001122334455667788990011223344556677889900aabb6006137f112233445566778899001122334455667788990011223344556677889900aabb6007137f112233445566778899001122334455667788990011223344556677889900aabb6008137f112233445566778899001122334455667788990011223344556677889900aabb6009137f112233445566778899001122334455667788990011223344556677889900aabb600a137f112233445566778899001122334455667788990011223344556677889900aabb600b137f112233445566778899001122334455667788990011223344556677889900aabb600c137f112233445566778899001122334455667788990011223344556677889900aabb600d137f112233445566778899001122334455667788990011223344556677889900aabb600e137f112233445566778899001122334455667788990011223344556677889900aabb600f137f112233445566778899001122334455667788990011223344556677889900aabb6010137f112233445566778899001122334455667788990011223344556677889900aabb6011137f112233445566778899001122334455667788990011223344556677889900aabb6012137f112233445566778899001122334455667788990011223344556677889900aabb6013137f112233445566778899001122334455667788990011223344556677889900aabb6014137f112233445566778899001122334455667788990011223344556677889900aabb6015137f112233445566778899001122334455667788990011223344556677889900aabb6016137f112233445566778899001122334455667788990011223344556677889900aabb6017137f112233445566778899001122334455667788990011223344556677889900aabb6018137f112233445566778899001122334455667788990011223344556677889900aabb6019137f112233445566778899001122334455667788990011223344556677889900aabb601a137f112233445566778899001122334455667788990011223344556677889900aabb601b137f112233445566778899001122334455667788990011223344556677889900aabb601c137f112233445566778899001122334455667788990011223344556677889900aabb601d137f112233445566778899001122334455667788990011223344556677889900aabb601e137f112233445566778899001122334455667788990011223344556677889900aabb601f137f112233445566778899001122334455667788990011223344556677889900aabb6020137f112233445566778899001122334455667788990011223344556677889900aabb6107de13 diff --git a/evmjit/evmcc/test/mem/byte.lll b/evmjit/evmcc/test/mem/byte.lll deleted file mode 100644 index 95b0f99dc..000000000 --- a/evmjit/evmcc/test/mem/byte.lll +++ /dev/null @@ -1,105 +0,0 @@ - -(asm -0x112233445566778899001122334455667788990011223344556677889900aabb -0 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -1 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -2 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -3 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -4 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -5 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -6 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -7 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -8 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -9 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -10 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -11 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -12 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -13 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -14 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -15 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -16 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -17 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -18 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -19 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -20 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -21 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -22 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -23 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -24 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -25 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -26 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -27 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -28 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -29 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -30 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -31 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -32 -BYTE -0x112233445566778899001122334455667788990011223344556677889900aabb -2014 -BYTE -) \ No newline at end of file diff --git a/evmjit/evmcc/test/mem/mem2.evm b/evmjit/evmcc/test/mem/mem2.evm deleted file mode 100644 index 49cc6e8b1..000000000 --- a/evmjit/evmcc/test/mem/mem2.evm +++ /dev/null @@ -1 +0,0 @@ -6001610d805b01556504409585d6df620493e05462061a80535b01 diff --git a/evmjit/evmcc/test/mem/mem2.lll b/evmjit/evmcc/test/mem/mem2.lll deleted file mode 100644 index 5345ee47c..000000000 --- a/evmjit/evmcc/test/mem/mem2.lll +++ /dev/null @@ -1,15 +0,0 @@ - -(asm ;; [] -1 -3456 -MSIZE -ADD -MSTORE8 ;; [02] -4675432994527 -300000 -MSTORE -400000 -MLOAD -MSIZE -ADD -) \ No newline at end of file diff --git a/evmjit/evmcc/test/mem/memtest1.evm b/evmjit/evmcc/test/mem/memtest1.evm deleted file mode 100644 index 0506bf928..000000000 --- a/evmjit/evmcc/test/mem/memtest1.evm +++ /dev/null @@ -1 +0,0 @@ -6002600055600360015560005360015301600254 diff --git a/evmjit/evmcc/test/mem/memtest1.lll b/evmjit/evmcc/test/mem/memtest1.lll deleted file mode 100644 index 4b4389ad8..000000000 --- a/evmjit/evmcc/test/mem/memtest1.lll +++ /dev/null @@ -1,18 +0,0 @@ - -(asm ;; [] -2 -0 -MSTORE8 ;; [02] -3 -1 -MSTORE8 ;; [02 03] -0 -MLOAD ;; [2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] -1 -MLOAD ;; [2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - ;; 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] -ADD -2 -MSTORE ;; [2 3 5 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - ;; 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] -) \ No newline at end of file diff --git a/evmjit/evmcc/test/mem/mstore1.evm b/evmjit/evmcc/test/mem/mstore1.evm deleted file mode 100644 index ba6141ab1..000000000 --- a/evmjit/evmcc/test/mem/mstore1.evm +++ /dev/null @@ -1 +0,0 @@ -6001600054 diff --git a/evmjit/evmcc/test/mem/mstore1.lll b/evmjit/evmcc/test/mem/mstore1.lll deleted file mode 100644 index 2d2ca32b5..000000000 --- a/evmjit/evmcc/test/mem/mstore1.lll +++ /dev/null @@ -1,6 +0,0 @@ - -(asm ;; [] -1 -0 -MSTORE ;; [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1] -) \ No newline at end of file diff --git a/evmjit/evmcc/test/ret/return1.evm b/evmjit/evmcc/test/ret/return1.evm deleted file mode 100644 index 8092cb007..000000000 --- a/evmjit/evmcc/test/ret/return1.evm +++ /dev/null @@ -1 +0,0 @@ -600160805460006080530b601b59600160005460206000f2602a58602760005460206000f26002608054 diff --git a/evmjit/evmcc/test/ret/return1.lll b/evmjit/evmcc/test/ret/return1.lll deleted file mode 100644 index 159d15ca3..000000000 --- a/evmjit/evmcc/test/ret/return1.lll +++ /dev/null @@ -1,6 +0,0 @@ -;; code should return 39 -;; i should remain 1 -{ - [i] 1 - ( if (> @i 0) { (return 39) [i] 2 } (return 1) ) -} \ No newline at end of file diff --git a/evmjit/evmcc/test/ret/return2.evm b/evmjit/evmcc/test/ret/return2.evm deleted file mode 100644 index e29da7664..000000000 --- a/evmjit/evmcc/test/ret/return2.evm +++ /dev/null @@ -1 +0,0 @@ -6001620f4240f2 diff --git a/evmjit/evmcc/test/ret/return2.lll b/evmjit/evmcc/test/ret/return2.lll deleted file mode 100644 index f5ee68f6e..000000000 --- a/evmjit/evmcc/test/ret/return2.lll +++ /dev/null @@ -1,6 +0,0 @@ - -(asm -1 -1000000 -RETURN ;; return 1 byte from index 1M -) \ No newline at end of file diff --git a/evmjit/evmcc/test/ret/return_test.evm b/evmjit/evmcc/test/ret/return_test.evm deleted file mode 100644 index 977cf7c19..000000000 --- a/evmjit/evmcc/test/ret/return_test.evm +++ /dev/null @@ -1 +0,0 @@ -60016064546002608454600360a45460606064f2 diff --git a/evmjit/evmcc/test/ret/return_test.lll b/evmjit/evmcc/test/ret/return_test.lll deleted file mode 100644 index c87a2d812..000000000 --- a/evmjit/evmcc/test/ret/return_test.lll +++ /dev/null @@ -1,15 +0,0 @@ - -(asm -1 -100 -MSTORE -2 -132 -MSTORE -3 -164 -MSTORE -96 -100 -RETURN -) \ No newline at end of file diff --git a/evmjit/evmcc/test/stack/oos.evm b/evmjit/evmcc/test/stack/oos.evm deleted file mode 100644 index ea2f1c890..000000000 --- a/evmjit/evmcc/test/stack/oos.evm +++ /dev/null @@ -1 +0,0 @@ -60018194505050509150 diff --git a/evmjit/evmcc/test/stack/oos.lll b/evmjit/evmcc/test/stack/oos.lll deleted file mode 100644 index 5394b06ba..000000000 --- a/evmjit/evmcc/test/stack/oos.lll +++ /dev/null @@ -1,11 +0,0 @@ -(asm ;; x . v y z -1 ;; 1 x . v y z -DUP2 ;; x 1 x . v y z -SWAP5 ;; y 1 x . v x z -POP ;; 1 x . v x z -POP ;; x . v x z -POP ;; . v x z -POP ;; v x z -SWAP2 ;; z x v -POP ;; x v -) diff --git a/evmjit/evmcc/test/stack/push_test.evm b/evmjit/evmcc/test/stack/push_test.evm deleted file mode 100644 index d624cee1d..000000000 --- a/evmjit/evmcc/test/stack/push_test.evm +++ /dev/null @@ -1 +0,0 @@ -60656107d26204a0c763026921f4640bc5588eb165372d0f1dca6e661ba1d901961c71670c55f7bc23038e3868056bc75e2d630fffff69021e19e0c9bab24000016a085d1c6e8050f0ea1c71bd6b0688be36543f3c36e638e37a6c03d41f73d55d0d482ae55555376dc76810d0fe03c91964d31c71c6f46e615dd0360c07d931663b14e38e38b16f2da3f99955a3adcf27ebb1caaaaaaa6e7014ccba6a8bb1ed35bd86bf065c71c71c2b7109491c5d4781b79c9009de6bfb8e38e38de8720414a0f6fdec81304d4c563e740bffffffffa573118427b3b4a05bc8a8a4de8459868000000000017406eb15e7331e727940d4ac54b7cdca1c71c71c71bd750567a91c9fefc96ebaa626a22f98c5e638e38e38e37a76032abd16c5b68006e15d5aa307e383f4e55555555555377701a6427bdc4f0d58eab5f48a3ec67f64e21c71c71c71c6f478080dd0a0c9b9ff2c2a0c740b06853a0a980ee38e38e38e38b17903c679cb5e8f2f9cb3b5d6652b0e7334f746faaaaaaaaaaaaa6e7a01b873815917ebb2bf3b890a1af495d6235bae3c71c71c71c71c2b7b07ae4cca96e1a55dfa49c85ad3c3e60e426b92fb8e38e38e38e38de87c036018bf074e292bcc7d6c8bea0f9699443046178bffffffffffffffa57d0e7d34c64a9c85d4460dbbca87196b61618a4bd2168000000000000000017e05b901f48a5b994d6572502bc4ea43140486666416aa1c71c71c71c71c71bd7f047889870c178fc477414ea231d70467a388fffe31b4e638e38e38e38e38e37a diff --git a/evmjit/evmcc/test/stack/push_test.lll b/evmjit/evmcc/test/stack/push_test.lll deleted file mode 100644 index 832daaec1..000000000 --- a/evmjit/evmcc/test/stack/push_test.lll +++ /dev/null @@ -1,35 +0,0 @@ - -(asm -101 ;; PUSH1 -2002 ;; PUSH2 -303303 ;; PUSH3 -40444404 ;; PUSH4 -50555555505 ;; PUSH5 -60666666666606 -7777777777777777 -888888888888888888 -99999999999999999999 -10000000000000000000001 -10111111111111111111111101 -2022222222222222222222222202 -303333333333333333333333333303 -4044444444444444444444444444444404 -505555555555555555555555555555555505 -60666666666666666666666666666666666606 -7077777777777777777777777777777777777707 -808888888888888888888888888888888888888808 -90999999999999999999999999999999999999999909 -100000000000000000000000000000000000000000000001 -10111111111111111111111111111111111111111111111101 -2022222222222222222222222222222222222222222222222202 -303333333333333333333333333333333333333333333333333303 -40444444444444444444444444444444444444444444444444444404 -50555555555555555555555555555555555555555555555555555555505 -6066666666666666666666666666666666666666666666666666666666606 -707777777777777777777777777777777777777777777777777777777777707 -808888888888888888888888888888888888888888888888888888888888888808 -90999999999999999999999999999999999999999999999999999999999999999909 -100000000000000000000000000000000000000000000000000000000000000000000001 -10111111111111111111111111111111111111111111111111111111111111111111111101 -2022222222222222222222222222222222222222222222222222222222222222222222222202 ;; PUSH32 -) \ No newline at end of file diff --git a/evmjit/evmcc/test/stack/stack_test.evm b/evmjit/evmcc/test/stack/stack_test.evm deleted file mode 100644 index 02417c967..000000000 --- a/evmjit/evmcc/test/stack/stack_test.evm +++ /dev/null @@ -1 +0,0 @@ -65372d0f1dca6e661925338e3e5c2b808280848184505050505050506104576108ae81819290 diff --git a/evmjit/evmcc/test/stack/stack_test.lll b/evmjit/evmcc/test/stack/stack_test.lll deleted file mode 100644 index fdf83594c..000000000 --- a/evmjit/evmcc/test/stack/stack_test.lll +++ /dev/null @@ -1,8 +0,0 @@ - -(asm -123 -SSTORE -SLOAD -123 -SUB -) \ No newline at end of file diff --git a/evmjit/evmcc/test/stack/stackjump.evm b/evmjit/evmcc/test/stack/stackjump.evm deleted file mode 100644 index baddec42e..000000000 --- a/evmjit/evmcc/test/stack/stackjump.evm +++ /dev/null @@ -1 +0,0 @@ -600460066009601358600a036000545b6000f260005401600958 \ No newline at end of file diff --git a/evmjit/evmcc/test/stack/stackjump.lll b/evmjit/evmcc/test/stack/stackjump.lll deleted file mode 100644 index f5da5e733..000000000 --- a/evmjit/evmcc/test/stack/stackjump.lll +++ /dev/null @@ -1,3 +0,0 @@ -(asm -0x4 0x6 0x9 0x13 JUMP 0xa SUB 0x0 MSTORE MSIZE 0x0 RETURN 0x0 MSTORE ADD 0x9 JUMP -) diff --git a/evmjit/evmcc/test/stack/swap.evm b/evmjit/evmcc/test/stack/swap.evm deleted file mode 100644 index d17f0ee09..000000000 --- a/evmjit/evmcc/test/stack/swap.evm +++ /dev/null @@ -1 +0,0 @@ -600560026001600c59505000906001601559505000036000546001601ff2 diff --git a/evmjit/evmcc/test/stack/swap.lll b/evmjit/evmcc/test/stack/swap.lll deleted file mode 100644 index 90dee585d..000000000 --- a/evmjit/evmcc/test/stack/swap.lll +++ /dev/null @@ -1,31 +0,0 @@ -(asm -5 ;; 0 -2 ;; 2 -1 ;; 4 -12 ;; 6 -JUMPI ;; 8 - -POP ;; 9 -POP ;; 10 -STOP ;; 11 - -;; stack = 2,1 -SWAP1 ;; 12 -1 ;; 13 -21 ;; 15 -JUMPI ;; 17 - -POP ;; 18 -POP ;; 19 -STOP ;; 20 - -;; stack = 1,2 -SUB ;; 21 -0 -MSTORE -1 -31 -RETURN ;; returns 03 -) - - diff --git a/evmjit/evmcc/test/stack/swapswap.evm b/evmjit/evmcc/test/stack/swapswap.evm deleted file mode 100644 index fb4f1bf75..000000000 --- a/evmjit/evmcc/test/stack/swapswap.evm +++ /dev/null @@ -1 +0,0 @@ -600260056001600c5950500090906001601659505000036000546001601ff2 diff --git a/evmjit/evmcc/test/stack/swapswap.lll b/evmjit/evmcc/test/stack/swapswap.lll deleted file mode 100644 index 1fedf726e..000000000 --- a/evmjit/evmcc/test/stack/swapswap.lll +++ /dev/null @@ -1,32 +0,0 @@ -(asm -2 ;; 0 -5 ;; 2 -1 ;; 4 -12 ;; 6 -JUMPI ;; 8 - -POP ;; 9 -POP ;; 10 -STOP ;; 11 - -;; stack = 2,1 -SWAP1 ;; 12 -SWAP1 ;; 13 -1 ;; 14 -22 ;; 16 -JUMPI ;; 18 - -POP ;; 19 -POP ;; 20 -STOP ;; 21 - -;; stack = 2,1 -SUB ;; 22 -0 -MSTORE -1 -31 -RETURN ;; returns 03 -) - - diff --git a/evmjit/evmcc/test/stack/test.evm b/evmjit/evmcc/test/stack/test.evm deleted file mode 100644 index ea2f1c890..000000000 --- a/evmjit/evmcc/test/stack/test.evm +++ /dev/null @@ -1 +0,0 @@ -60018194505050509150 diff --git a/evmjit/evmcc/test/vmtests/vmArithPerformanceTest.json b/evmjit/evmcc/test/vmtests/vmArithPerformanceTest.json deleted file mode 100644 index d9017517f..000000000 --- a/evmjit/evmcc/test/vmtests/vmArithPerformanceTest.json +++ /dev/null @@ -1,260 +0,0 @@ -{ - "arith-1" : { - "callcreates" : [ ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "10000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x600a60005260005160105760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600556", - "data" : "0x", - "gas" : "1000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "999538", - "out" : "0x0000000000000000000000000000000000000000000000000000001b9c636491", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x600a60005260005160105760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600556", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x600a60005260005160105760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600556", - "nonce" : "0", - "storage" : { } - } - } - } - - , - - "arith-2" : { - "callcreates" : [ ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "10000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x606460005260005160105760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600556", - "data" : "0x", - "gas" : "1000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "995488", - "out" : "0x0000000000000000000000000000000000000000000000000000001b9c636491", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x606460005260005160105760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600556", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x606460005260005160105760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600556", - "nonce" : "0", - "storage" : { } - } - } - } - - , - - "arith-3" : { - "callcreates" : [ ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "10000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x6103e860005260005160115760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600656", - "data" : "0x", - "gas" : "1000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "954988", - "out" : "0x0000000000000000000000000000000000000000000000000000001b9c636491", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x6103e860005260005160115760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600656", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x6103e860005260005160115760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600656", - "nonce" : "0", - "storage" : { } - } - } - } - - , - - "arith-4" : { - "callcreates" : [ ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "10000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x61271060005260005160115760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600656", - "data" : "0x", - "gas" : "1000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "549988", - "out" : "0x0000000000000000000000000000000000000000000000000000001b9c636491", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x61271060005260005160115760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600656", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x61271060005260005160115760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600656", - "nonce" : "0", - "storage" : { } - } - } - } - - - , - - - "arith-5" : { - "callcreates" : [ ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "10000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x620186a060005260005160125760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600756", - "data" : "0x", - "gas" : "10000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "5499988", - "out" : "0x0000000000000000000000000000000000000000000000000000001b9c636491", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x620186a060005260005160125760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600756", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x620186a060005260005160125760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600756", - "nonce" : "0", - "storage" : { } - } - } - } - -, - - "arith-6" : { - "callcreates" : [ ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "100000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x620f424060005260005160125760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600756", - "data" : "0x", - "gas" : "100000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "54999988", - "out" : "0x0000000000000000000000000000000000000000000000000000001b9c636491", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x620f424060005260005160125760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600756", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x620f424060005260005160125760206020f26001600190016007026005016002900460049006602190056015016003026005900760030360090160110a60205260005160019003600052600756", - "nonce" : "0", - "storage" : { } - } - } - } - -} diff --git a/evmjit/evmcc/test/vmtests/vmPerformanceTest.json b/evmjit/evmcc/test/vmtests/vmPerformanceTest.json deleted file mode 100644 index 604e45993..000000000 --- a/evmjit/evmcc/test/vmtests/vmPerformanceTest.json +++ /dev/null @@ -1,214 +0,0 @@ -{ - "mulmodloop" : { - "callcreates" : [ ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "10000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x60015b68010000000000000000908060010109600356", - "data" : "0x", - "gas" : "10000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "0", - "out" : "0x0", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x60015b68010000000000000000908060010109600356", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x60015b68010000000000000000908060010109600356", - "nonce" : "0", - "storage" : { } - } - } - }, - - - "for-1e06" : { - "callcreates" : [ ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "100000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x620f42406080525b6000608051111560285760a0516080510160a0526001608051036080526007565b", - "data" : "0x", - "gas" : "30000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "6999982", - "out" : "0x00", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x620f42406080525b6000608051111560285760a0516080510160a0526001608051036080526007565b", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x620f42406080525b6000608051111560285760a0516080510160a0526001608051036080526007565b", - "nonce" : "0", - "storage" : { } - } - } - }, - - "fib25" : { - "callcreates" : [ - ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "100000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x6007601e6010565b60005260206000f25b600381106030576021600282036010565b602b600183036010565b016033565b60015b90509056", - "data" : "0x", - "gas" : "40000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "5886377", - "out" : "0x00000000000000000000000000000000000000000000000000000000000cb228", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x6007601e6010565b60005260206000f25b600381106030576021600282036010565b602b600183036010565b016033565b60015b90509056", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x6007601e6010565b60005260206000f25b600381106030576021600282036010565b602b600183036010565b016033565b60015b90509056", - "nonce" : "0", - "storage" : { - } - } - } - }, - - "ackermann37" : { - "callcreates" : [ - ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "20000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x6009600360076012565b60005260206000f25b60008214604a5760008114603957603560018303603184600185036012565b6012565b6046565b60456001830360016012565b5b604f565b600181015b905090509056", - "data" : "0x", - "gas" : "20000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "913456", - "out" : "0x00000000000000000000000000000000000000000000000000000000000003fd", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x6009600360076012565b60005260206000f25b60008214604a5760008114603957603560018303603184600185036012565b6012565b6046565b60456001830360016012565b5b604f565b600181015b905090509056", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x6009600360076012565b60005260206000f25b60008214604a5760008114603957603560018303603184600185036012565b6012565b6046565b60456001830360016012565b5b604f565b600181015b905090509056", - "nonce" : "0", - "storage" : { - } - } - } - }, - - "jumptable100" : { - "callcreates" : [ - ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "10000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "0x6103e85b60019003806000146104605761001a600160005256005b610025600260005256005b610030600360005256005b61003b600460005256005b610046600560005256005b610051600660005256005b61005c600760005256005b610067600860005256005b610072600960005256005b61007d600a60005256005b610088600b60005256005b610093600c60005256005b61009e600d60005256005b6100a9600e60005256005b6100b4600f60005256005b6100bf601060005256005b6100ca601160005256005b6100d5601260005256005b6100e0601360005256005b6100eb601460005256005b6100f6601560005256005b610101601660005256005b61010c601760005256005b610117601860005256005b610122601960005256005b61012d601a60005256005b610138601b60005256005b610143601c60005256005b61014e601d60005256005b610159601e60005256005b610164601f60005256005b61016f602060005256005b61017a602160005256005b610185602260005256005b610190602360005256005b61019b602460005256005b6101a6602560005256005b6101b1602660005256005b6101bc602760005256005b6101c7602860005256005b6101d2602960005256005b6101dd602a60005256005b6101e8602b60005256005b6101f3602c60005256005b6101fe602d60005256005b610209602e60005256005b610214602f60005256005b61021f603060005256005b61022a603160005256005b610235603260005256005b610240603360005256005b61024b603460005256005b610256603560005256005b610261603660005256005b61026c603760005256005b610277603860005256005b610282603960005256005b61028d603a60005256005b610298603b60005256005b6102a3603c60005256005b6102ae603d60005256005b6102b9603e60005256005b6102c4603f60005256005b6102cf604060005256005b6102da604160005256005b6102e5604260005256005b6102f0604360005256005b6102fb604460005256005b610306604560005256005b610311604660005256005b61031c604760005256005b610327604860005256005b610332604960005256005b61033d604a60005256005b610348604b60005256005b610353604c60005256005b61035e604d60005256005b610369604e60005256005b610374604f60005256005b61037f605060005256005b61038a605160005256005b610395605260005256005b6103a0605360005256005b6103ab605460005256005b6103b6605560005256005b6103c1605660005256005b6103cc605760005256005b6103d7605860005256005b6103e2605960005256005b6103ed605a60005256005b6103f8605b60005256005b610403605c60005256005b61040e605d60005256005b610419605e60005256005b610424605f60005256005b61042f606060005256005b61043a606160005256005b610445606260005256005b610450606360005256005b61045b606460005256005b610003565b60206000f2", - "data" : "0x", - "gas" : "1000000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "389596", - "out" : "0x0000000000000000000000000000000000000000000000000000000000000064", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x6103e85b60019003806000146104605761001a600160005256005b610025600260005256005b610030600360005256005b61003b600460005256005b610046600560005256005b610051600660005256005b61005c600760005256005b610067600860005256005b610072600960005256005b61007d600a60005256005b610088600b60005256005b610093600c60005256005b61009e600d60005256005b6100a9600e60005256005b6100b4600f60005256005b6100bf601060005256005b6100ca601160005256005b6100d5601260005256005b6100e0601360005256005b6100eb601460005256005b6100f6601560005256005b610101601660005256005b61010c601760005256005b610117601860005256005b610122601960005256005b61012d601a60005256005b610138601b60005256005b610143601c60005256005b61014e601d60005256005b610159601e60005256005b610164601f60005256005b61016f602060005256005b61017a602160005256005b610185602260005256005b610190602360005256005b61019b602460005256005b6101a6602560005256005b6101b1602660005256005b6101bc602760005256005b6101c7602860005256005b6101d2602960005256005b6101dd602a60005256005b6101e8602b60005256005b6101f3602c60005256005b6101fe602d60005256005b610209602e60005256005b610214602f60005256005b61021f603060005256005b61022a603160005256005b610235603260005256005b610240603360005256005b61024b603460005256005b610256603560005256005b610261603660005256005b61026c603760005256005b610277603860005256005b610282603960005256005b61028d603a60005256005b610298603b60005256005b6102a3603c60005256005b6102ae603d60005256005b6102b9603e60005256005b6102c4603f60005256005b6102cf604060005256005b6102da604160005256005b6102e5604260005256005b6102f0604360005256005b6102fb604460005256005b610306604560005256005b610311604660005256005b61031c604760005256005b610327604860005256005b610332604960005256005b61033d604a60005256005b610348604b60005256005b610353604c60005256005b61035e604d60005256005b610369604e60005256005b610374604f60005256005b61037f605060005256005b61038a605160005256005b610395605260005256005b6103a0605360005256005b6103ab605460005256005b6103b6605560005256005b6103c1605660005256005b6103cc605760005256005b6103d7605860005256005b6103e2605960005256005b6103ed605a60005256005b6103f8605b60005256005b610403605c60005256005b61040e605d60005256005b610419605e60005256005b610424605f60005256005b61042f606060005256005b61043a606160005256005b610445606260005256005b610450606360005256005b61045b606460005256005b610003565b60206000f2", - "nonce" : "0", - "storage" : { - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "0x6103e85b60019003806000146104605761001a600160005256005b610025600260005256005b610030600360005256005b61003b600460005256005b610046600560005256005b610051600660005256005b61005c600760005256005b610067600860005256005b610072600960005256005b61007d600a60005256005b610088600b60005256005b610093600c60005256005b61009e600d60005256005b6100a9600e60005256005b6100b4600f60005256005b6100bf601060005256005b6100ca601160005256005b6100d5601260005256005b6100e0601360005256005b6100eb601460005256005b6100f6601560005256005b610101601660005256005b61010c601760005256005b610117601860005256005b610122601960005256005b61012d601a60005256005b610138601b60005256005b610143601c60005256005b61014e601d60005256005b610159601e60005256005b610164601f60005256005b61016f602060005256005b61017a602160005256005b610185602260005256005b610190602360005256005b61019b602460005256005b6101a6602560005256005b6101b1602660005256005b6101bc602760005256005b6101c7602860005256005b6101d2602960005256005b6101dd602a60005256005b6101e8602b60005256005b6101f3602c60005256005b6101fe602d60005256005b610209602e60005256005b610214602f60005256005b61021f603060005256005b61022a603160005256005b610235603260005256005b610240603360005256005b61024b603460005256005b610256603560005256005b610261603660005256005b61026c603760005256005b610277603860005256005b610282603960005256005b61028d603a60005256005b610298603b60005256005b6102a3603c60005256005b6102ae603d60005256005b6102b9603e60005256005b6102c4603f60005256005b6102cf604060005256005b6102da604160005256005b6102e5604260005256005b6102f0604360005256005b6102fb604460005256005b610306604560005256005b610311604660005256005b61031c604760005256005b610327604860005256005b610332604960005256005b61033d604a60005256005b610348604b60005256005b610353604c60005256005b61035e604d60005256005b610369604e60005256005b610374604f60005256005b61037f605060005256005b61038a605160005256005b610395605260005256005b6103a0605360005256005b6103ab605460005256005b6103b6605560005256005b6103c1605660005256005b6103cc605760005256005b6103d7605860005256005b6103e2605960005256005b6103ed605a60005256005b6103f8605b60005256005b610403605c60005256005b61040e605d60005256005b610419605e60005256005b610424605f60005256005b61042f606060005256005b61043a606160005256005b610445606260005256005b610450606360005256005b61045b606460005256005b610003565b60206000f2", - "nonce" : "0", - "storage" : { - } - } - } - }, - -} diff --git a/evmjit/evmcc/test/vmtests/vm_jump.json b/evmjit/evmcc/test/vmtests/vm_jump.json deleted file mode 100644 index 6b63edeae..000000000 --- a/evmjit/evmcc/test/vmtests/vm_jump.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "jumpi_at_the_end" : { - "callcreates" : [ ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "10000000", - "currentNumber" : "0", - "currentTimestamp" : "1", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "code" : "(asm 10 0 MSTORE JUMPDEST 0 MLOAD 1 SWAP1 SUB DUP1 0 MSTORE 6 JUMPI)", - "data" : "0x", - "gas" : "1000", - "gasPrice" : "100000000000000", - "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000" - }, - "gas" : "895", - "out" : "0x0", - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "(asm 10 0 MSTORE JUMPDEST 0 MLOAD 1 SWAP1 SUB DUP1 0 MSTORE 6 JUMPI)", - "nonce" : "0", - "storage" : {} - } - }, - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "1000000000000000000", - "code" : "(asm 10 0 MSTORE JUMPDEST 0 MLOAD 1 SWAP1 SUB DUP1 0 MSTORE 6 JUMPI)", - "nonce" : "0", - "storage" : {} - } - } - } -} diff --git a/evmjit/libevmjit/ExecStats.h b/evmjit/libevmjit/ExecStats.h index 498e21341..1ac9b6995 100644 --- a/evmjit/libevmjit/ExecStats.h +++ b/evmjit/libevmjit/ExecStats.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include "ExecutionEngine.h" diff --git a/evmjit/libevmjit/preprocessor/llvm_includes_end.h b/evmjit/libevmjit/preprocessor/llvm_includes_end.h index 023c8021e..2ead6dda3 100644 --- a/evmjit/libevmjit/preprocessor/llvm_includes_end.h +++ b/evmjit/libevmjit/preprocessor/llvm_includes_end.h @@ -1,5 +1,7 @@ #if defined(_MSC_VER) #pragma warning(pop) +#elif defined(__clang__) + #pragma clang diagnostic pop #else #pragma GCC diagnostic pop #endif diff --git a/evmjit/libevmjit/preprocessor/llvm_includes_start.h b/evmjit/libevmjit/preprocessor/llvm_includes_start.h index bf34ade99..9077bf43f 100644 --- a/evmjit/libevmjit/preprocessor/llvm_includes_start.h +++ b/evmjit/libevmjit/preprocessor/llvm_includes_start.h @@ -1,6 +1,10 @@ #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable: 4267 4244 4800) +#elif defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunused-parameter" + #pragma clang diagnostic ignored "-Wconversion" #else #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 561f2f405..2b4e6bc08 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -80,7 +80,7 @@ public: operator Arith() const { return fromBigEndian(m_data); } /// @returns true iff this is the empty hash. - operator bool() const { return ((Arith)*this) != 0; } + explicit operator bool() const { return ((Arith)*this) != 0; } // The obvious comparison operators. bool operator==(FixedHash const& _c) const { return m_data == _c.m_data; } diff --git a/libdevcrypto/CryptoPP.cpp b/libdevcrypto/CryptoPP.cpp index 2d0170fb9..43993e0c5 100644 --- a/libdevcrypto/CryptoPP.cpp +++ b/libdevcrypto/CryptoPP.cpp @@ -134,7 +134,7 @@ bool Secp256k1::verify(Signature const& _signature, bytesConstRef _message) bool Secp256k1::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed) { // todo: verify w/o recovery (if faster) - return _p == _hashed ? recover(_sig, _message) : recover(_sig, sha3(_message).ref()); + return (bool)_p == _hashed ? (bool)recover(_sig, _message) : (bool)recover(_sig, sha3(_message).ref()); } Public Secp256k1::recover(Signature _signature, bytesConstRef _message) diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp index 8726ebe95..fec010c2d 100644 --- a/libethcore/BlockInfo.cpp +++ b/libethcore/BlockInfo.cpp @@ -191,7 +191,7 @@ u256 BlockInfo::calculateDifficulty(BlockInfo const& _parent) const if (!parentHash) return c_genesisDifficulty; else - return timestamp >= _parent.timestamp + (c_protocolVersion == 49 ? 5 : 8) ? _parent.difficulty - (_parent.difficulty >> 10) : (_parent.difficulty + (_parent.difficulty >> 10)); + return max(1024, timestamp >= _parent.timestamp + (c_protocolVersion == 49 ? 5 : 8) ? _parent.difficulty - (_parent.difficulty >> 10) : (_parent.difficulty + (_parent.difficulty >> 10))); } void BlockInfo::verifyParent(BlockInfo const& _parent) const diff --git a/libethcore/ProofOfWork.h b/libethcore/ProofOfWork.h index 64ce502af..c3c3f192b 100644 --- a/libethcore/ProofOfWork.h +++ b/libethcore/ProofOfWork.h @@ -82,7 +82,7 @@ template std::pair ProofOfWorkEngine::mine(h256 const& _root, u256 const& _difficulty, unsigned _msTimeout, bool _continue, bool _turbo) { std::pair ret; - static std::mt19937_64 s_eng((time(0) + (unsigned)m_last)); + static std::mt19937_64 s_eng((time(0) + *reinterpret_cast(m_last.data()))); u256 s = (m_last = h256::random(s_eng)); bigint d = (bigint(1) << 256) / _difficulty; diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index d72762f36..11b9557df 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -257,7 +257,9 @@ LocalisedLogEntries Client::peekWatch(unsigned _watchId) const Guard l(m_filterLock); try { + cdebug << "peekWatch" << _watchId; auto& w = m_watches.at(_watchId); + cdebug << "lastPoll updated to " << chrono::duration_cast(chrono::system_clock::now().time_since_epoch()).count(); w.lastPoll = chrono::system_clock::now(); return w.changes; } catch (...) {} @@ -271,7 +273,9 @@ LocalisedLogEntries Client::checkWatch(unsigned _watchId) LocalisedLogEntries ret; try { + cdebug << "checkWatch" << _watchId; auto& w = m_watches.at(_watchId); + cdebug << "lastPoll updated to " << chrono::duration_cast(chrono::system_clock::now().time_since_epoch()).count(); std::swap(ret, w.changes); w.lastPoll = chrono::system_clock::now(); } catch (...) {} diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index c732f2dc1..dfa928675 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -94,7 +94,7 @@ private: h256Set neededBlocks(h256Set const& _exclude); /// Check to see if the network peer-state initialisation has happened. - bool isInitialised() const { return m_latestBlockSent; } + bool isInitialised() const { return (bool)m_latestBlockSent; } /// Initialises the network peer-state, doing the stuff that needs to be once-only. @returns true if it really was first. bool ensureInitialised(); diff --git a/libethereum/Transaction.h b/libethereum/Transaction.h index 0f88a4bc0..a9044970f 100644 --- a/libethereum/Transaction.h +++ b/libethereum/Transaction.h @@ -81,7 +81,7 @@ public: Address safeSender() const noexcept; /// @returns true if transaction is non-null. - operator bool() const { return m_type != NullTransaction; } + explicit operator bool() const { return m_type != NullTransaction; } /// @returns true if transaction is contract-creation. bool isCreation() const { return m_type == ContractCreation; } diff --git a/libevm/VM.cpp b/libevm/VM.cpp index a7ca91533..2ba18eda6 100644 --- a/libevm/VM.cpp +++ b/libevm/VM.cpp @@ -38,8 +38,7 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) auto gasForMem = [](bigint _size) -> bigint { bigint s = _size / 32; -// return (bigint)c_memoryGas * (s + s * s / 1024); - return (bigint)c_memoryGas * s; + return (bigint)c_memoryGas * (s + s * s / 1024); }; if (m_jumpDests.empty()) diff --git a/libevmcore/Assembly.cpp b/libevmcore/Assembly.cpp index 37c3ff18d..80ac8c68f 100644 --- a/libevmcore/Assembly.cpp +++ b/libevmcore/Assembly.cpp @@ -229,10 +229,11 @@ ostream& Assembly::streamRLP(ostream& _out, string const& _prefix) const return _out; } -AssemblyItem const& Assembly::append(AssemblyItem const& _i) +AssemblyItem const& Assembly::append(AssemblyItem const& _i, SourceLocation const& _location) { m_deposit += _i.deposit(); m_items.push_back(_i); + m_items.back().setLocation(_location); return back(); } diff --git a/libevmcore/Assembly.h b/libevmcore/Assembly.h index ffe13b34d..73d2b663c 100644 --- a/libevmcore/Assembly.h +++ b/libevmcore/Assembly.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "Exceptions.h" @@ -57,10 +58,13 @@ public: int deposit() const; bool match(AssemblyItem const& _i) const { return _i.m_type == UndefinedItem || (m_type == _i.m_type && (m_type != Operation || m_data == _i.m_data)); } + void setLocation(SourceLocation const& _location) { m_location = _location;} + SourceLocation const& getLocation() const { return m_location; } private: AssemblyItemType m_type; u256 m_data; + SourceLocation m_location; }; using AssemblyItems = std::vector; @@ -84,9 +88,9 @@ public: AssemblyItem append() { return append(newTag()); } void append(Assembly const& _a); void append(Assembly const& _a, int _deposit); - AssemblyItem const& append(AssemblyItem const& _i); - AssemblyItem const& append(std::string const& _data) { return append(newPushString(_data)); } - AssemblyItem const& append(bytes const& _data) { return append(newData(_data)); } + AssemblyItem const& append(AssemblyItem const& _i, SourceLocation const& _location = SourceLocation()); + AssemblyItem const& append(std::string const& _data, SourceLocation const& _location = SourceLocation()) { return append(newPushString(_data), _location); } + AssemblyItem const& append(bytes const& _data, SourceLocation const& _location = SourceLocation()) { return append(newData(_data), _location); } AssemblyItem appendSubSize(Assembly const& _a) { auto ret = newSub(_a); append(newPushSubSize(ret.data())); return ret; } /// Pushes the final size of the current assembly itself. Use this when the code is modified /// after compilation and CODESIZE is not an option. @@ -99,7 +103,8 @@ public: template Assembly& operator<<(T const& _d) { append(_d); return *this; } - AssemblyItem const& back() { return m_items.back(); } + AssemblyItems const& getItems() const { return m_items; } + AssemblyItem const& back() const { return m_items.back(); } std::string backString() const { return m_items.size() && m_items.back().m_type == PushString ? m_strings.at((h256)m_items.back().m_data) : std::string(); } void onePath() { if (asserts(!m_totalDeposit && !m_baseDeposit)) BOOST_THROW_EXCEPTION(InvalidDeposit()); m_baseDeposit = m_deposit; m_totalDeposit = INT_MAX; } diff --git a/libsolidity/BaseTypes.h b/libevmcore/SourceLocation.h similarity index 62% rename from libsolidity/BaseTypes.h rename to libevmcore/SourceLocation.h index 057289ef3..c373e9cf3 100644 --- a/libsolidity/BaseTypes.h +++ b/libevmcore/SourceLocation.h @@ -15,9 +15,9 @@ along with cpp-ethereum. If not, see . */ /** - * @author Christian - * @date 2014 - * Some elementary types for the parser. + * @author Lefteris Karapetsas + * @date 2015 + * Represents a location in a source file */ #pragma once @@ -28,18 +28,23 @@ namespace dev { -namespace solidity -{ /** * Representation of an interval of source positions. * The interval includes start and excludes end. */ -struct Location +struct SourceLocation { - Location(int _start, int _end, std::shared_ptr _sourceName): + SourceLocation(int _start, int _end, std::shared_ptr _sourceName): start(_start), end(_end), sourceName(_sourceName) { } - Location(): start(-1), end(-1) { } + SourceLocation(): start(-1), end(-1) { } + + SourceLocation(SourceLocation const& _other): + start(_other.start), end(_other.end), sourceName(_other.sourceName) {} + SourceLocation& operator=(SourceLocation const& _other) { start = _other.start; end = _other.end; sourceName = _other.sourceName; return *this;} + + bool operator==(SourceLocation const& _other) const { return start == _other.start && end == _other.end;} + bool operator!=(SourceLocation const& _other) const { return !operator==(_other); } bool isEmpty() const { return start == -1 && end == -1; } @@ -49,7 +54,7 @@ struct Location }; /// Stream output for Location (used e.g. in boost exceptions). -inline std::ostream& operator<<(std::ostream& _out, Location const& _location) +inline std::ostream& operator<<(std::ostream& _out, SourceLocation const& _location) { if (_location.isEmpty()) return _out << "NO_LOCATION_SPECIFIED"; @@ -57,4 +62,3 @@ inline std::ostream& operator<<(std::ostream& _out, Location const& _location) } } -} diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index a18785ae1..c37e8c374 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -603,19 +603,64 @@ void MemberAccess::checkTypeRequirements() if (!m_type) BOOST_THROW_EXCEPTION(createTypeError("Member \"" + *m_memberName + "\" not found or not " "visible in " + type.toString())); - m_isLValue = (type.getCategory() == Type::Category::Struct); + // This should probably move somewhere else. + if (type.getCategory() == Type::Category::Struct) + m_isLValue = true; + else if (type.getCategory() == Type::Category::Array) + { + auto const& arrayType(dynamic_cast(type)); + m_isLValue = (*m_memberName == "length" && + arrayType.getLocation() != ArrayType::Location::CallData && arrayType.isDynamicallySized()); + } + else + m_isLValue = false; } void IndexAccess::checkTypeRequirements() { m_base->checkTypeRequirements(); - if (m_base->getType()->getCategory() != Type::Category::Mapping) - BOOST_THROW_EXCEPTION(m_base->createTypeError("Indexed expression has to be a mapping (is " + - m_base->getType()->toString() + ")")); - MappingType const& type = dynamic_cast(*m_base->getType()); - m_index->expectType(*type.getKeyType()); - m_type = type.getValueType(); - m_isLValue = true; + switch (m_base->getType()->getCategory()) + { + case Type::Category::Array: + { + ArrayType const& type = dynamic_cast(*m_base->getType()); + if (!m_index) + BOOST_THROW_EXCEPTION(createTypeError("Index expression cannot be omitted.")); + m_index->expectType(IntegerType(256)); + m_type = type.getBaseType(); + m_isLValue = true; + break; + } + case Type::Category::Mapping: + { + MappingType const& type = dynamic_cast(*m_base->getType()); + if (!m_index) + BOOST_THROW_EXCEPTION(createTypeError("Index expression cannot be omitted.")); + m_index->expectType(*type.getKeyType()); + m_type = type.getValueType(); + m_isLValue = true; + break; + } + case Type::Category::TypeType: + { + TypeType const& type = dynamic_cast(*m_base->getType()); + if (!m_index) + m_type = make_shared(make_shared(ArrayType::Location::Memory, type.getActualType())); + else + { + m_index->checkTypeRequirements(); + auto length = dynamic_cast(m_index->getType().get()); + if (!length) + BOOST_THROW_EXCEPTION(m_index->createTypeError("Integer constant expected.")); + m_type = make_shared(make_shared( + ArrayType::Location::Memory, type.getActualType(), length->literalValue(nullptr))); + } + break; + } + default: + BOOST_THROW_EXCEPTION(m_base->createTypeError( + "Indexed expression has to be a type, mapping or array (is " + m_base->getType()->toString() + ")")); + } } void Identifier::checkTypeRequirements() diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 138abf36e..dea0fba63 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -27,9 +27,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -51,7 +51,7 @@ class ASTConstVisitor; class ASTNode: private boost::noncopyable { public: - explicit ASTNode(Location const& _location): m_location(_location) {} + explicit ASTNode(SourceLocation const& _location): m_location(_location) {} virtual ~ASTNode() {} @@ -71,7 +71,7 @@ public: } /// Returns the source code location of this node. - Location const& getLocation() const { return m_location; } + SourceLocation const& getLocation() const { return m_location; } /// Creates a @ref TypeError exception and decorates it with the location of the node and /// the given description @@ -85,7 +85,7 @@ public: ///@} private: - Location m_location; + SourceLocation m_location; }; /** @@ -94,7 +94,7 @@ private: class SourceUnit: public ASTNode { public: - SourceUnit(Location const& _location, std::vector> const& _nodes): + SourceUnit(SourceLocation const& _location, std::vector> const& _nodes): ASTNode(_location), m_nodes(_nodes) {} virtual void accept(ASTVisitor& _visitor) override; @@ -114,7 +114,7 @@ private: class ImportDirective: public ASTNode { public: - ImportDirective(Location const& _location, ASTPointer const& _identifier): + ImportDirective(SourceLocation const& _location, ASTPointer const& _identifier): ASTNode(_location), m_identifier(_identifier) {} virtual void accept(ASTVisitor& _visitor) override; @@ -135,7 +135,7 @@ public: /// Visibility ordered from restricted to unrestricted. enum class Visibility { Default, Private, Internal, Public, External }; - Declaration(Location const& _location, ASTPointer const& _name, + Declaration(SourceLocation const& _location, ASTPointer const& _name, Visibility _visibility = Visibility::Default): ASTNode(_location), m_name(_name), m_visibility(_visibility), m_scope(nullptr) {} @@ -205,7 +205,7 @@ protected: class ContractDefinition: public Declaration, public Documented { public: - ContractDefinition(Location const& _location, + ContractDefinition(SourceLocation const& _location, ASTPointer const& _name, ASTPointer const& _documentation, std::vector> const& _baseContracts, @@ -278,7 +278,7 @@ private: class InheritanceSpecifier: public ASTNode { public: - InheritanceSpecifier(Location const& _location, ASTPointer const& _baseName, + InheritanceSpecifier(SourceLocation const& _location, ASTPointer const& _baseName, std::vector> _arguments): ASTNode(_location), m_baseName(_baseName), m_arguments(_arguments) {} @@ -298,7 +298,7 @@ private: class StructDefinition: public Declaration { public: - StructDefinition(Location const& _location, + StructDefinition(SourceLocation const& _location, ASTPointer const& _name, std::vector> const& _members): Declaration(_location, _name), m_members(_members) {} @@ -323,7 +323,7 @@ private: class EnumDefinition: public Declaration { public: - EnumDefinition(Location const& _location, + EnumDefinition(SourceLocation const& _location, ASTPointer const& _name, std::vector> const& _members): Declaration(_location, _name), m_members(_members) {} @@ -344,7 +344,7 @@ private: class EnumValue: public Declaration { public: - EnumValue(Location const& _location, + EnumValue(SourceLocation const& _location, ASTPointer const& _name): Declaration(_location, _name) {} @@ -361,7 +361,7 @@ class EnumValue: public Declaration class ParameterList: public ASTNode { public: - ParameterList(Location const& _location, + ParameterList(SourceLocation const& _location, std::vector> const& _parameters): ASTNode(_location), m_parameters(_parameters) {} virtual void accept(ASTVisitor& _visitor) override; @@ -376,7 +376,7 @@ private: class FunctionDefinition: public Declaration, public VariableScope, public Documented { public: - FunctionDefinition(Location const& _location, ASTPointer const& _name, + FunctionDefinition(SourceLocation const& _location, ASTPointer const& _name, Declaration::Visibility _visibility, bool _isConstructor, ASTPointer const& _documentation, ASTPointer const& _parameters, @@ -431,7 +431,7 @@ private: class VariableDeclaration: public Declaration { public: - VariableDeclaration(Location const& _location, ASTPointer const& _type, + VariableDeclaration(SourceLocation const& _location, ASTPointer const& _type, ASTPointer const& _name, ASTPointer _value, Visibility _visibility, bool _isStateVar = false, bool _isIndexed = false): @@ -441,7 +441,7 @@ public: virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; - TypeName const* getTypeName() const { return m_typeName.get(); } + TypeName* getTypeName() { return m_typeName.get(); } ASTPointer const& getValue() const { return m_value; } /// Returns the declared or inferred type. Can be an empty pointer if no type was explicitly @@ -476,7 +476,7 @@ private: class ModifierDefinition: public Declaration, public VariableScope, public Documented { public: - ModifierDefinition(Location const& _location, + ModifierDefinition(SourceLocation const& _location, ASTPointer const& _name, ASTPointer const& _documentation, ASTPointer const& _parameters, @@ -506,7 +506,7 @@ private: class ModifierInvocation: public ASTNode { public: - ModifierInvocation(Location const& _location, ASTPointer const& _name, + ModifierInvocation(SourceLocation const& _location, ASTPointer const& _name, std::vector> _arguments): ASTNode(_location), m_modifierName(_name), m_arguments(_arguments) {} @@ -529,7 +529,7 @@ private: class EventDefinition: public Declaration, public VariableScope, public Documented { public: - EventDefinition(Location const& _location, + EventDefinition(SourceLocation const& _location, ASTPointer const& _name, ASTPointer const& _documentation, ASTPointer const& _parameters): @@ -560,7 +560,7 @@ class MagicVariableDeclaration: public Declaration { public: MagicVariableDeclaration(ASTString const& _name, std::shared_ptr const& _type): - Declaration(Location(), std::make_shared(_name)), m_type(_type) {} + Declaration(SourceLocation(), std::make_shared(_name)), m_type(_type) {} virtual void accept(ASTVisitor&) override { BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("MagicVariableDeclaration used inside real AST.")); } virtual void accept(ASTConstVisitor&) const override { BOOST_THROW_EXCEPTION(InternalCompilerError() @@ -581,14 +581,14 @@ private: class TypeName: public ASTNode { public: - explicit TypeName(Location const& _location): ASTNode(_location) {} + explicit TypeName(SourceLocation const& _location): ASTNode(_location) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; /// Retrieve the element of the type hierarchy this node refers to. Can return an empty shared /// pointer until the types have been resolved using the @ref NameAndTypeResolver. /// If it returns an empty shared pointer after that, this indicates that the type was not found. - virtual std::shared_ptr toType() const = 0; + virtual std::shared_ptr toType() = 0; }; /** @@ -598,14 +598,14 @@ public: class ElementaryTypeName: public TypeName { public: - explicit ElementaryTypeName(Location const& _location, Token::Value _type): + explicit ElementaryTypeName(SourceLocation const& _location, Token::Value _type): TypeName(_location), m_type(_type) { solAssert(Token::isElementaryTypeName(_type), ""); } virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; - virtual std::shared_ptr toType() const override { return Type::fromElementaryTypeName(m_type); } + virtual std::shared_ptr toType() override { return Type::fromElementaryTypeName(m_type); } Token::Value getTypeName() const { return m_type; } @@ -619,11 +619,11 @@ private: class UserDefinedTypeName: public TypeName { public: - UserDefinedTypeName(Location const& _location, ASTPointer const& _name): + UserDefinedTypeName(SourceLocation const& _location, ASTPointer const& _name): TypeName(_location), m_name(_name), m_referencedDeclaration(nullptr) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; - virtual std::shared_ptr toType() const override { return Type::fromUserDefinedTypeName(*this); } + virtual std::shared_ptr toType() override { return Type::fromUserDefinedTypeName(*this); } ASTString const& getName() const { return *m_name; } void setReferencedDeclaration(Declaration const& _referencedDeclaration) { m_referencedDeclaration = &_referencedDeclaration; } @@ -641,12 +641,12 @@ private: class Mapping: public TypeName { public: - Mapping(Location const& _location, ASTPointer const& _keyType, + Mapping(SourceLocation const& _location, ASTPointer const& _keyType, ASTPointer const& _valueType): TypeName(_location), m_keyType(_keyType), m_valueType(_valueType) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; - virtual std::shared_ptr toType() const override { return Type::fromMapping(*this); } + virtual TypePointer toType() override { return Type::fromMapping(*m_keyType, *m_valueType); } ElementaryTypeName const& getKeyType() const { return *m_keyType; } TypeName const& getValueType() const { return *m_valueType; } @@ -656,6 +656,27 @@ private: ASTPointer m_valueType; }; +/** + * An array type, can be "typename[]" or "typename[]". + */ +class ArrayTypeName: public TypeName +{ +public: + ArrayTypeName(SourceLocation const& _location, ASTPointer const& _baseType, + ASTPointer const& _length): + TypeName(_location), m_baseType(_baseType), m_length(_length) {} + virtual void accept(ASTVisitor& _visitor) override; + virtual void accept(ASTConstVisitor& _visitor) const override; + virtual std::shared_ptr toType() override { return Type::fromArrayTypeName(*m_baseType, m_length.get()); } + + TypeName const& getBaseType() const { return *m_baseType; } + Expression const* getLength() const { return m_length.get(); } + +private: + ASTPointer m_baseType; + ASTPointer m_length; ///< Length of the array, might be empty. +}; + /// @} /// Statements @@ -668,7 +689,7 @@ private: class Statement: public ASTNode { public: - explicit Statement(Location const& _location): ASTNode(_location) {} + explicit Statement(SourceLocation const& _location): ASTNode(_location) {} /// Check all type requirements, throws exception if some requirement is not met. /// This includes checking that operators are applicable to their arguments but also that @@ -682,7 +703,7 @@ public: class Block: public Statement { public: - Block(Location const& _location, std::vector> const& _statements): + Block(SourceLocation const& _location, std::vector> const& _statements): Statement(_location), m_statements(_statements) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; @@ -700,7 +721,7 @@ private: class PlaceholderStatement: public Statement { public: - PlaceholderStatement(Location const& _location): Statement(_location) {} + PlaceholderStatement(SourceLocation const& _location): Statement(_location) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; @@ -715,7 +736,7 @@ public: class IfStatement: public Statement { public: - IfStatement(Location const& _location, ASTPointer const& _condition, + IfStatement(SourceLocation const& _location, ASTPointer const& _condition, ASTPointer const& _trueBody, ASTPointer const& _falseBody): Statement(_location), m_condition(_condition), m_trueBody(_trueBody), m_falseBody(_falseBody) {} @@ -740,13 +761,13 @@ private: class BreakableStatement: public Statement { public: - BreakableStatement(Location const& _location): Statement(_location) {} + BreakableStatement(SourceLocation const& _location): Statement(_location) {} }; class WhileStatement: public BreakableStatement { public: - WhileStatement(Location const& _location, ASTPointer const& _condition, + WhileStatement(SourceLocation const& _location, ASTPointer const& _condition, ASTPointer const& _body): BreakableStatement(_location), m_condition(_condition), m_body(_body) {} virtual void accept(ASTVisitor& _visitor) override; @@ -767,7 +788,7 @@ private: class ForStatement: public BreakableStatement { public: - ForStatement(Location const& _location, + ForStatement(SourceLocation const& _location, ASTPointer const& _initExpression, ASTPointer const& _conditionExpression, ASTPointer const& _loopExpression, @@ -800,7 +821,7 @@ private: class Continue: public Statement { public: - Continue(Location const& _location): Statement(_location) {} + Continue(SourceLocation const& _location): Statement(_location) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; virtual void checkTypeRequirements() override {} @@ -809,7 +830,7 @@ public: class Break: public Statement { public: - Break(Location const& _location): Statement(_location) {} + Break(SourceLocation const& _location): Statement(_location) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; virtual void checkTypeRequirements() override {} @@ -818,7 +839,7 @@ public: class Return: public Statement { public: - Return(Location const& _location, ASTPointer _expression): + Return(SourceLocation const& _location, ASTPointer _expression): Statement(_location), m_expression(_expression), m_returnParameters(nullptr) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; @@ -843,7 +864,7 @@ private: class VariableDeclarationStatement: public Statement { public: - VariableDeclarationStatement(Location const& _location, ASTPointer _variable): + VariableDeclarationStatement(SourceLocation const& _location, ASTPointer _variable): Statement(_location), m_variable(_variable) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; @@ -862,7 +883,7 @@ private: class ExpressionStatement: public Statement { public: - ExpressionStatement(Location const& _location, ASTPointer _expression): + ExpressionStatement(SourceLocation const& _location, ASTPointer _expression): Statement(_location), m_expression(_expression) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; @@ -887,7 +908,7 @@ private: class Expression: public ASTNode { public: - Expression(Location const& _location): ASTNode(_location) {} + Expression(SourceLocation const& _location): ASTNode(_location) {} virtual void checkTypeRequirements() = 0; std::shared_ptr const& getType() const { return m_type; } @@ -918,7 +939,7 @@ protected: class Assignment: public Expression { public: - Assignment(Location const& _location, ASTPointer const& _leftHandSide, + Assignment(SourceLocation const& _location, ASTPointer const& _leftHandSide, Token::Value _assignmentOperator, ASTPointer const& _rightHandSide): Expression(_location), m_leftHandSide(_leftHandSide), m_assigmentOperator(_assignmentOperator), m_rightHandSide(_rightHandSide) @@ -946,7 +967,7 @@ private: class UnaryOperation: public Expression { public: - UnaryOperation(Location const& _location, Token::Value _operator, + UnaryOperation(SourceLocation const& _location, Token::Value _operator, ASTPointer const& _subExpression, bool _isPrefix): Expression(_location), m_operator(_operator), m_subExpression(_subExpression), m_isPrefix(_isPrefix) @@ -974,7 +995,7 @@ private: class BinaryOperation: public Expression { public: - BinaryOperation(Location const& _location, ASTPointer const& _left, + BinaryOperation(SourceLocation const& _location, ASTPointer const& _left, Token::Value _operator, ASTPointer const& _right): Expression(_location), m_left(_left), m_operator(_operator), m_right(_right) { @@ -1005,7 +1026,7 @@ private: class FunctionCall: public Expression { public: - FunctionCall(Location const& _location, ASTPointer const& _expression, + FunctionCall(SourceLocation const& _location, ASTPointer const& _expression, std::vector> const& _arguments, std::vector> const& _names): Expression(_location), m_expression(_expression), m_arguments(_arguments), m_names(_names) {} virtual void accept(ASTVisitor& _visitor) override; @@ -1032,7 +1053,7 @@ private: class NewExpression: public Expression { public: - NewExpression(Location const& _location, ASTPointer const& _contractName): + NewExpression(SourceLocation const& _location, ASTPointer const& _contractName): Expression(_location), m_contractName(_contractName) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; @@ -1053,7 +1074,7 @@ private: class MemberAccess: public Expression { public: - MemberAccess(Location const& _location, ASTPointer _expression, + MemberAccess(SourceLocation const& _location, ASTPointer _expression, ASTPointer const& _memberName): Expression(_location), m_expression(_expression), m_memberName(_memberName) {} virtual void accept(ASTVisitor& _visitor) override; @@ -1073,7 +1094,7 @@ private: class IndexAccess: public Expression { public: - IndexAccess(Location const& _location, ASTPointer const& _base, + IndexAccess(SourceLocation const& _location, ASTPointer const& _base, ASTPointer const& _index): Expression(_location), m_base(_base), m_index(_index) {} virtual void accept(ASTVisitor& _visitor) override; @@ -1081,7 +1102,7 @@ public: virtual void checkTypeRequirements() override; Expression const& getBaseExpression() const { return *m_base; } - Expression const& getIndexExpression() const { return *m_index; } + Expression const* getIndexExpression() const { return m_index.get(); } private: ASTPointer m_base; @@ -1095,7 +1116,7 @@ private: class PrimaryExpression: public Expression { public: - PrimaryExpression(Location const& _location): Expression(_location) {} + PrimaryExpression(SourceLocation const& _location): Expression(_location) {} }; /** @@ -1104,7 +1125,7 @@ public: class Identifier: public PrimaryExpression { public: - Identifier(Location const& _location, ASTPointer const& _name): + Identifier(SourceLocation const& _location, ASTPointer const& _name): PrimaryExpression(_location), m_name(_name) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; @@ -1139,7 +1160,7 @@ private: class ElementaryTypeNameExpression: public PrimaryExpression { public: - ElementaryTypeNameExpression(Location const& _location, Token::Value _typeToken): + ElementaryTypeNameExpression(SourceLocation const& _location, Token::Value _typeToken): PrimaryExpression(_location), m_typeToken(_typeToken) { solAssert(Token::isElementaryTypeName(_typeToken), ""); @@ -1168,7 +1189,7 @@ public: Finney = Token::SubFinney, Ether = Token::SubEther }; - Literal(Location const& _location, Token::Value _token, + Literal(SourceLocation const& _location, Token::Value _token, ASTPointer const& _value, SubDenomination _sub = SubDenomination::None): PrimaryExpression(_location), m_token(_token), m_value(_value), m_subDenomination(_sub) {} diff --git a/libsolidity/ASTForward.h b/libsolidity/ASTForward.h index 3a151b63e..0ba485a2f 100644 --- a/libsolidity/ASTForward.h +++ b/libsolidity/ASTForward.h @@ -53,6 +53,7 @@ class TypeName; class ElementaryTypeName; class UserDefinedTypeName; class Mapping; +class ArrayTypeName; class Statement; class Block; class PlaceholderStatement; diff --git a/libsolidity/ASTPrinter.cpp b/libsolidity/ASTPrinter.cpp index 209bb73e6..d0b27b317 100644 --- a/libsolidity/ASTPrinter.cpp +++ b/libsolidity/ASTPrinter.cpp @@ -155,6 +155,13 @@ bool ASTPrinter::visit(Mapping const& _node) return goDeeper(); } +bool ASTPrinter::visit(ArrayTypeName const& _node) +{ + writeLine("ArrayTypeName"); + printSourcePart(_node); + return goDeeper(); +} + bool ASTPrinter::visit(Statement const& _node) { writeLine("Statement"); @@ -419,6 +426,11 @@ void ASTPrinter::endVisit(Mapping const&) m_indentation--; } +void ASTPrinter::endVisit(ArrayTypeName const&) +{ + m_indentation--; +} + void ASTPrinter::endVisit(Statement const&) { m_indentation--; @@ -543,7 +555,7 @@ void ASTPrinter::printSourcePart(ASTNode const& _node) { if (!m_source.empty()) { - Location const& location(_node.getLocation()); + SourceLocation const& location(_node.getLocation()); *m_ostream << getIndentation() << " Source: " << escaped(m_source.substr(location.start, location.end - location.start), false) << endl; } diff --git a/libsolidity/ASTPrinter.h b/libsolidity/ASTPrinter.h index 7a0ef5a65..a1797383c 100644 --- a/libsolidity/ASTPrinter.h +++ b/libsolidity/ASTPrinter.h @@ -58,6 +58,7 @@ public: bool visit(ElementaryTypeName const& _node) override; bool visit(UserDefinedTypeName const& _node) override; bool visit(Mapping const& _node) override; + bool visit(ArrayTypeName const& _node) override; bool visit(Statement const& _node) override; bool visit(Block const& _node) override; bool visit(PlaceholderStatement const& _node) override; @@ -99,6 +100,7 @@ public: void endVisit(ElementaryTypeName const&) override; void endVisit(UserDefinedTypeName const&) override; void endVisit(Mapping const&) override; + void endVisit(ArrayTypeName const&) override; void endVisit(Statement const&) override; void endVisit(Block const&) override; void endVisit(PlaceholderStatement const&) override; diff --git a/libsolidity/ASTVisitor.h b/libsolidity/ASTVisitor.h index 2ecfbe4b1..3eeb9c456 100644 --- a/libsolidity/ASTVisitor.h +++ b/libsolidity/ASTVisitor.h @@ -59,6 +59,7 @@ public: virtual bool visit(ElementaryTypeName&) { return true; } virtual bool visit(UserDefinedTypeName&) { return true; } virtual bool visit(Mapping&) { return true; } + virtual bool visit(ArrayTypeName&) { return true; } virtual bool visit(Statement&) { return true; } virtual bool visit(Block&) { return true; } virtual bool visit(PlaceholderStatement&) { return true; } @@ -102,6 +103,7 @@ public: virtual void endVisit(ElementaryTypeName&) { } virtual void endVisit(UserDefinedTypeName&) { } virtual void endVisit(Mapping&) { } + virtual void endVisit(ArrayTypeName&) { } virtual void endVisit(Statement&) { } virtual void endVisit(Block&) { } virtual void endVisit(PlaceholderStatement&) { } @@ -149,6 +151,7 @@ public: virtual bool visit(ElementaryTypeName const&) { return true; } virtual bool visit(UserDefinedTypeName const&) { return true; } virtual bool visit(Mapping const&) { return true; } + virtual bool visit(ArrayTypeName const&) { return true; } virtual bool visit(Statement const&) { return true; } virtual bool visit(Block const&) { return true; } virtual bool visit(PlaceholderStatement const&) { return true; } @@ -192,6 +195,7 @@ public: virtual void endVisit(ElementaryTypeName const&) { } virtual void endVisit(UserDefinedTypeName const&) { } virtual void endVisit(Mapping const&) { } + virtual void endVisit(ArrayTypeName const&) { } virtual void endVisit(Statement const&) { } virtual void endVisit(Block const&) { } virtual void endVisit(PlaceholderStatement const&) { } diff --git a/libsolidity/AST_accept.h b/libsolidity/AST_accept.h index 5bd6993db..81ede8fc9 100644 --- a/libsolidity/AST_accept.h +++ b/libsolidity/AST_accept.h @@ -327,6 +327,28 @@ void Mapping::accept(ASTConstVisitor& _visitor) const _visitor.endVisit(*this); } +void ArrayTypeName::accept(ASTVisitor& _visitor) +{ + if (_visitor.visit(*this)) + { + m_baseType->accept(_visitor); + if (m_length) + m_length->accept(_visitor); + } + _visitor.endVisit(*this); +} + +void ArrayTypeName::accept(ASTConstVisitor& _visitor) const +{ + if (_visitor.visit(*this)) + { + m_baseType->accept(_visitor); + if (m_length) + m_length->accept(_visitor); + } + _visitor.endVisit(*this); +} + void Block::accept(ASTVisitor& _visitor) { if (_visitor.visit(*this)) @@ -604,7 +626,8 @@ void IndexAccess::accept(ASTVisitor& _visitor) if (_visitor.visit(*this)) { m_base->accept(_visitor); - m_index->accept(_visitor); + if (m_index) + m_index->accept(_visitor); } _visitor.endVisit(*this); } @@ -614,7 +637,8 @@ void IndexAccess::accept(ASTConstVisitor& _visitor) const if (_visitor.visit(*this)) { m_base->accept(_visitor); - m_index->accept(_visitor); + if (m_index) + m_index->accept(_visitor); } _visitor.endVisit(*this); } diff --git a/libsolidity/Compiler.cpp b/libsolidity/Compiler.cpp index e691394cb..2f75d2ea4 100644 --- a/libsolidity/Compiler.cpp +++ b/libsolidity/Compiler.cpp @@ -74,6 +74,7 @@ void Compiler::initializeContext(ContractDefinition const& _contract, m_context.setCompiledContracts(_contracts); m_context.setInheritanceHierarchy(_contract.getLinearizedBaseContracts()); registerStateVariables(_contract); + m_context.resetVisitedNodes(&_contract); } void Compiler::packIntoContractCreator(ContractDefinition const& _contract, CompilerContext const& _runtimeContext) @@ -128,6 +129,7 @@ void Compiler::packIntoContractCreator(ContractDefinition const& _contract, Comp void Compiler::appendBaseConstructorCall(FunctionDefinition const& _constructor, vector> const& _arguments) { + CompilerContext::LocationSetter locationSetter(m_context, &_constructor); FunctionType constructorType(_constructor); eth::AssemblyItem returnLabel = m_context.pushNewTag(); for (unsigned i = 0; i < _arguments.size(); ++i) @@ -138,6 +140,7 @@ void Compiler::appendBaseConstructorCall(FunctionDefinition const& _constructor, void Compiler::appendConstructorCall(FunctionDefinition const& _constructor) { + CompilerContext::LocationSetter locationSetter(m_context, &_constructor); eth::AssemblyItem returnTag = m_context.pushNewTag(); // copy constructor arguments from code to memory and then to stack, they are supplied after the actual program unsigned argumentSize = 0; @@ -247,7 +250,7 @@ void Compiler::appendReturnValuePacker(TypePointers const& _typeParameters) for (TypePointer const& type: _typeParameters) { CompilerUtils(m_context).copyToStackTop(stackDepth, *type); - ExpressionCompiler::appendTypeConversion(m_context, *type, *type, true); + ExpressionCompiler(m_context, m_optimize).appendTypeConversion(*type, *type, true); bool const c_padToWords = true; dataOffset += CompilerUtils(m_context).storeInMemory(dataOffset, *type, c_padToWords); stackDepth -= type->getSizeOnStack(); @@ -267,25 +270,27 @@ void Compiler::initializeStateVariables(ContractDefinition const& _contract) { for (ASTPointer const& variable: _contract.getStateVariables()) if (variable->getValue()) - ExpressionCompiler::appendStateVariableInitialization(m_context, *variable); + ExpressionCompiler(m_context, m_optimize).appendStateVariableInitialization(*variable); } bool Compiler::visit(VariableDeclaration const& _variableDeclaration) { solAssert(_variableDeclaration.isStateVariable(), "Compiler visit to non-state variable declaration."); + CompilerContext::LocationSetter locationSetter(m_context, &_variableDeclaration); m_context.startFunction(_variableDeclaration); m_breakTags.clear(); m_continueTags.clear(); m_context << m_context.getFunctionEntryLabel(_variableDeclaration); - ExpressionCompiler::appendStateVariableAccessor(m_context, _variableDeclaration); + ExpressionCompiler(m_context, m_optimize).appendStateVariableAccessor(_variableDeclaration); return false; } bool Compiler::visit(FunctionDefinition const& _function) { + CompilerContext::LocationSetter locationSetter(m_context, &_function); //@todo to simplify this, the calling convention could by changed such that // caller puts: [retarg0] ... [retargm] [return address] [arg0] ... [argn] // although note that this reduces the size of the visible stack @@ -355,7 +360,7 @@ bool Compiler::visit(FunctionDefinition const& _function) bool Compiler::visit(IfStatement const& _ifStatement) { StackHeightChecker checker(m_context); - + CompilerContext::LocationSetter locationSetter(m_context, &_ifStatement); compileExpression(_ifStatement.getCondition()); eth::AssemblyItem trueTag = m_context.appendConditionalJump(); if (_ifStatement.getFalseStatement()) @@ -372,7 +377,7 @@ bool Compiler::visit(IfStatement const& _ifStatement) bool Compiler::visit(WhileStatement const& _whileStatement) { StackHeightChecker checker(m_context); - + CompilerContext::LocationSetter locationSetter(m_context, &_whileStatement); eth::AssemblyItem loopStart = m_context.newTag(); eth::AssemblyItem loopEnd = m_context.newTag(); m_continueTags.push_back(loopStart); @@ -398,7 +403,7 @@ bool Compiler::visit(WhileStatement const& _whileStatement) bool Compiler::visit(ForStatement const& _forStatement) { StackHeightChecker checker(m_context); - + CompilerContext::LocationSetter locationSetter(m_context, &_forStatement); eth::AssemblyItem loopStart = m_context.newTag(); eth::AssemblyItem loopEnd = m_context.newTag(); m_continueTags.push_back(loopStart); @@ -433,15 +438,17 @@ bool Compiler::visit(ForStatement const& _forStatement) return false; } -bool Compiler::visit(Continue const&) +bool Compiler::visit(Continue const& _continueStatement) { + CompilerContext::LocationSetter locationSetter(m_context, &_continueStatement); if (!m_continueTags.empty()) m_context.appendJumpTo(m_continueTags.back()); return false; } -bool Compiler::visit(Break const&) +bool Compiler::visit(Break const& _breakStatement) { + CompilerContext::LocationSetter locationSetter(m_context, &_breakStatement); if (!m_breakTags.empty()) m_context.appendJumpTo(m_breakTags.back()); return false; @@ -449,6 +456,7 @@ bool Compiler::visit(Break const&) bool Compiler::visit(Return const& _return) { + CompilerContext::LocationSetter locationSetter(m_context, &_return); //@todo modifications are needed to make this work with functions returning multiple values if (Expression const* expression = _return.getExpression()) { @@ -467,6 +475,7 @@ bool Compiler::visit(Return const& _return) bool Compiler::visit(VariableDeclarationStatement const& _variableDeclarationStatement) { StackHeightChecker checker(m_context); + CompilerContext::LocationSetter locationSetter(m_context, &_variableDeclarationStatement); if (Expression const* expression = _variableDeclarationStatement.getExpression()) { compileExpression(*expression, _variableDeclarationStatement.getDeclaration().getType()); @@ -479,6 +488,7 @@ bool Compiler::visit(VariableDeclarationStatement const& _variableDeclarationSta bool Compiler::visit(ExpressionStatement const& _expressionStatement) { StackHeightChecker checker(m_context); + CompilerContext::LocationSetter locationSetter(m_context, &_expressionStatement); Expression const& expression = _expressionStatement.getExpression(); compileExpression(expression); CompilerUtils(m_context).popStackElement(*expression.getType()); @@ -486,9 +496,10 @@ bool Compiler::visit(ExpressionStatement const& _expressionStatement) return false; } -bool Compiler::visit(PlaceholderStatement const&) +bool Compiler::visit(PlaceholderStatement const& _placeholderStatement) { StackHeightChecker checker(m_context); + CompilerContext::LocationSetter locationSetter(m_context, &_placeholderStatement); ++m_modifierDepth; appendModifierOrFunctionCode(); --m_modifierDepth; @@ -504,8 +515,8 @@ void Compiler::appendModifierOrFunctionCode() else { ASTPointer const& modifierInvocation = m_currentFunction->getModifiers()[m_modifierDepth]; - ModifierDefinition const& modifier = m_context.getFunctionModifier(modifierInvocation->getName()->getName()); + CompilerContext::LocationSetter locationSetter(m_context, &modifier); solAssert(modifier.getParameters().size() == modifierInvocation->getArguments().size(), ""); for (unsigned i = 0; i < modifier.getParameters().size(); ++i) { @@ -530,9 +541,10 @@ void Compiler::appendModifierOrFunctionCode() void Compiler::compileExpression(Expression const& _expression, TypePointer const& _targetType) { - ExpressionCompiler::compileExpression(m_context, _expression, m_optimize); + ExpressionCompiler expressionCompiler(m_context, m_optimize); + expressionCompiler.compile(_expression); if (_targetType) - ExpressionCompiler::appendTypeConversion(m_context, *_expression.getType(), *_targetType); + expressionCompiler.appendTypeConversion(*_expression.getType(), *_targetType); } } diff --git a/libsolidity/Compiler.h b/libsolidity/Compiler.h index 28ab34adb..3ad2d8c61 100644 --- a/libsolidity/Compiler.h +++ b/libsolidity/Compiler.h @@ -26,6 +26,7 @@ #include #include #include +#include namespace dev { namespace solidity { @@ -42,6 +43,11 @@ public: bytes getRuntimeBytecode() { return m_runtimeContext.getAssembledBytecode(m_optimize);} void streamAssembly(std::ostream& _stream) const { m_context.streamAssembly(_stream); } + /// @returns Assembly items of the normal compiler context + eth::AssemblyItems const& getAssemblyItems() const { return m_context.getAssembly().getItems(); } + /// @returns Assembly items of the runtime compiler context + eth::AssemblyItems const& getRuntimeAssemblyItems() const { return m_runtimeContext.getAssembly().getItems(); } + private: /// Registers the non-function objects inside the contract with the context. void initializeContext(ContractDefinition const& _contract, diff --git a/libsolidity/CompilerContext.cpp b/libsolidity/CompilerContext.cpp index 01a71d7c9..18be337fa 100644 --- a/libsolidity/CompilerContext.cpp +++ b/libsolidity/CompilerContext.cpp @@ -40,7 +40,12 @@ void CompilerContext::addMagicGlobal(MagicVariableDeclaration const& _declaratio void CompilerContext::addStateVariable(VariableDeclaration const& _declaration) { m_stateVariables[&_declaration] = m_stateVariablesSize; - m_stateVariablesSize += _declaration.getType()->getStorageSize(); + bigint newSize = bigint(m_stateVariablesSize) + _declaration.getType()->getStorageSize(); + if (newSize >= bigint(1) << 256) + BOOST_THROW_EXCEPTION(TypeError() + << errinfo_comment("State variable does not fit in storage.") + << errinfo_sourceLocation(_declaration.getLocation())); + m_stateVariablesSize = u256(newSize); } void CompilerContext::startFunction(Declaration const& _function) @@ -60,8 +65,8 @@ void CompilerContext::addVariable(VariableDeclaration const& _declaration, void CompilerContext::addAndInitializeVariable(VariableDeclaration const& _declaration) { + LocationSetter locationSetter(*this, &_declaration); addVariable(_declaration); - int const size = _declaration.getType()->getSizeOnStack(); for (int i = 0; i < size; ++i) *this << u256(0); @@ -161,5 +166,40 @@ u256 CompilerContext::getStorageLocationOfVariable(const Declaration& _declarati return it->second; } +void CompilerContext::resetVisitedNodes(ASTNode const* _node) +{ + stack newStack; + newStack.push(_node); + std::swap(m_visitedNodes, newStack); +} + +CompilerContext& CompilerContext::operator<<(eth::AssemblyItem const& _item) +{ + solAssert(!m_visitedNodes.empty(), "No node on the visited stack"); + m_asm.append(_item, m_visitedNodes.top()->getLocation()); + return *this; +} + +CompilerContext& CompilerContext::operator<<(eth::Instruction _instruction) +{ + solAssert(!m_visitedNodes.empty(), "No node on the visited stack"); + m_asm.append(_instruction, m_visitedNodes.top()->getLocation()); + return *this; +} + +CompilerContext& CompilerContext::operator<<(u256 const& _value) +{ + solAssert(!m_visitedNodes.empty(), "No node on the visited stack"); + m_asm.append(_value, m_visitedNodes.top()->getLocation()); + return *this; +} + +CompilerContext& CompilerContext::operator<<(bytes const& _data) +{ + solAssert(!m_visitedNodes.empty(), "No node on the visited stack"); + m_asm.append(_data, m_visitedNodes.top()->getLocation()); + return *this; +} + } } diff --git a/libsolidity/CompilerContext.h b/libsolidity/CompilerContext.h index da2e7f4fe..94d6443e9 100644 --- a/libsolidity/CompilerContext.h +++ b/libsolidity/CompilerContext.h @@ -23,6 +23,7 @@ #pragma once #include +#include #include #include #include @@ -99,19 +100,34 @@ public: void appendProgramSize() { return m_asm.appendProgramSize(); } /// Adds data to the data section, pushes a reference to the stack eth::AssemblyItem appendData(bytes const& _data) { return m_asm.append(_data); } + /// Resets the stack of visited nodes with a new stack having only @c _node + void resetVisitedNodes(ASTNode const* _node); + /// Pops the stack of visited nodes + void popVisitedNodes() { m_visitedNodes.pop(); } + /// Pushes an ASTNode to the stack of visited nodes + void pushVisitedNodes(ASTNode const* _node) { m_visitedNodes.push(_node); } /// Append elements to the current instruction list and adjust @a m_stackOffset. - CompilerContext& operator<<(eth::AssemblyItem const& _item) { m_asm.append(_item); return *this; } - CompilerContext& operator<<(eth::Instruction _instruction) { m_asm.append(_instruction); return *this; } - CompilerContext& operator<<(u256 const& _value) { m_asm.append(_value); return *this; } - CompilerContext& operator<<(bytes const& _data) { m_asm.append(_data); return *this; } + CompilerContext& operator<<(eth::AssemblyItem const& _item); + CompilerContext& operator<<(eth::Instruction _instruction); + CompilerContext& operator<<(u256 const& _value); + CompilerContext& operator<<(bytes const& _data); eth::Assembly const& getAssembly() const { return m_asm; } void streamAssembly(std::ostream& _stream) const { _stream << m_asm; } bytes getAssembledBytecode(bool _optimize = false) { return m_asm.optimise(_optimize).assemble(); } -private: + /** + * Helper class to pop the visited nodes stack when a scope closes + */ + class LocationSetter: public ScopeGuard + { + public: + LocationSetter(CompilerContext& _compilerContext, ASTNode const* _node): + ScopeGuard(std::bind(&CompilerContext::popVisitedNodes, _compilerContext)) { _compilerContext.pushVisitedNodes(_node); } + }; eth::Assembly m_asm; +private: /// Magic global variables like msg, tx or this, distinguished by type. std::set m_magicGlobals; @@ -129,6 +145,8 @@ private: std::set m_functionsWithCode; /// List of current inheritance hierarchy from derived to base. std::vector m_inheritanceHierarchy; + /// Stack of current visited AST nodes, used for location attachment + std::stack m_visitedNodes; }; } diff --git a/libsolidity/CompilerStack.h b/libsolidity/CompilerStack.h index 8f77ef68a..812f41863 100644 --- a/libsolidity/CompilerStack.h +++ b/libsolidity/CompilerStack.h @@ -60,7 +60,7 @@ class CompilerStack: boost::noncopyable { public: /// Creates a new compiler stack. Adds standard sources if @a _addStandardSources. - explicit CompilerStack(bool _addStandardSources = false); + explicit CompilerStack(bool _addStandardSources = true); /// Adds a source object (e.g. file) to the parser. After this, parse has to be called again. /// @returns true if a source object by the name already existed and was replaced. diff --git a/libsolidity/CompilerUtils.cpp b/libsolidity/CompilerUtils.cpp index 047bc6d62..c7ce94456 100644 --- a/libsolidity/CompilerUtils.cpp +++ b/libsolidity/CompilerUtils.cpp @@ -36,14 +36,14 @@ const unsigned int CompilerUtils::dataStartOffset = 4; unsigned CompilerUtils::loadFromMemory(unsigned _offset, Type const& _type, bool _fromCalldata, bool _padToWordBoundaries) { - solAssert(_type.getCategory() != Type::Category::ByteArray, "Unable to statically load dynamic type."); + solAssert(_type.getCategory() != Type::Category::Array, "Unable to statically load dynamic type."); m_context << u256(_offset); return loadFromMemoryHelper(_type, _fromCalldata, _padToWordBoundaries); } void CompilerUtils::loadFromMemoryDynamic(Type const& _type, bool _fromCalldata, bool _padToWordBoundaries) { - solAssert(_type.getCategory() != Type::Category::ByteArray, "Byte arrays not yet implemented."); + solAssert(_type.getCategory() != Type::Category::Array, "Arrays not yet implemented."); m_context << eth::Instruction::DUP1; unsigned numBytes = loadFromMemoryHelper(_type, _fromCalldata, _padToWordBoundaries); // update memory counter @@ -55,7 +55,7 @@ void CompilerUtils::loadFromMemoryDynamic(Type const& _type, bool _fromCalldata, unsigned CompilerUtils::storeInMemory(unsigned _offset, Type const& _type, bool _padToWordBoundaries) { - solAssert(_type.getCategory() != Type::Category::ByteArray, "Unable to statically store dynamic type."); + solAssert(_type.getCategory() != Type::Category::Array, "Unable to statically store dynamic type."); unsigned numBytes = prepareMemoryStore(_type, _padToWordBoundaries); if (numBytes > 0) m_context << u256(_offset) << eth::Instruction::MSTORE; @@ -64,11 +64,12 @@ unsigned CompilerUtils::storeInMemory(unsigned _offset, Type const& _type, bool void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBoundaries) { - if (_type.getCategory() == Type::Category::ByteArray) + if (_type.getCategory() == Type::Category::Array) { - auto const& type = dynamic_cast(_type); + auto const& type = dynamic_cast(_type); + solAssert(type.isByteArray(), "Non byte arrays not yet implemented here."); - if (type.getLocation() == ByteArrayType::Location::CallData) + if (type.getLocation() == ArrayType::Location::CallData) { // stack: target source_offset source_len m_context << eth::Instruction::DUP1 << eth::Instruction::DUP3 << eth::Instruction::DUP5 @@ -79,7 +80,7 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound } else { - solAssert(type.getLocation() == ByteArrayType::Location::Storage, "Memory byte arrays not yet implemented."); + solAssert(type.getLocation() == ArrayType::Location::Storage, "Memory byte arrays not yet implemented."); m_context << eth::Instruction::DUP1 << eth::Instruction::SLOAD; // stack here: memory_offset storage_offset length_bytes // jump to end if length is zero @@ -163,16 +164,18 @@ void CompilerUtils::computeHashStatic(Type const& _type, bool _padToWordBoundari m_context << u256(length) << u256(0) << eth::Instruction::SHA3; } -void CompilerUtils::copyByteArrayToStorage(ByteArrayType const& _targetType, - ByteArrayType const& _sourceType) const +void CompilerUtils::copyByteArrayToStorage( + ArrayType const& _targetType, ArrayType const& _sourceType) const { // stack layout: [source_ref] target_ref (top) // need to leave target_ref on the stack at the end - solAssert(_targetType.getLocation() == ByteArrayType::Location::Storage, ""); + solAssert(_targetType.getLocation() == ArrayType::Location::Storage, ""); + solAssert(_targetType.isByteArray(), "Non byte arrays not yet implemented here."); + solAssert(_sourceType.isByteArray(), "Non byte arrays not yet implemented here."); switch (_sourceType.getLocation()) { - case ByteArrayType::Location::CallData: + case ArrayType::Location::CallData: { // This also assumes that after "length" we only have zeros, i.e. it cannot be used to // slice a byte array from calldata. @@ -224,7 +227,7 @@ void CompilerUtils::copyByteArrayToStorage(ByteArrayType const& _targetType, << eth::Instruction::POP << eth::Instruction::POP; break; } - case ByteArrayType::Location::Storage: + case ArrayType::Location::Storage: { // this copies source to target and also clears target if it was larger @@ -313,9 +316,10 @@ unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCallda return numBytes; } -void CompilerUtils::clearByteArray(ByteArrayType const& _type) const +void CompilerUtils::clearByteArray(ArrayType const& _type) const { - solAssert(_type.getLocation() == ByteArrayType::Location::Storage, ""); + solAssert(_type.getLocation() == ArrayType::Location::Storage, ""); + solAssert(_type.isByteArray(), "Non byte arrays not yet implemented here."); // fetch length m_context << eth::Instruction::DUP1 << eth::Instruction::SLOAD; diff --git a/libsolidity/CompilerUtils.h b/libsolidity/CompilerUtils.h index 5369d3bf2..2fb97d808 100644 --- a/libsolidity/CompilerUtils.h +++ b/libsolidity/CompilerUtils.h @@ -82,11 +82,11 @@ public: /// Copies a byte array to a byte array in storage. /// Stack pre: [source_reference] target_reference /// Stack post: target_reference - void copyByteArrayToStorage(ByteArrayType const& _targetType, ByteArrayType const& _sourceType) const; + void copyByteArrayToStorage(ArrayType const& _targetType, ArrayType const& _sourceType) const; /// Clears the length and data elements of the byte array referenced on the stack. /// Stack pre: reference /// Stack post: - void clearByteArray(ByteArrayType const& _type) const; + void clearByteArray(ArrayType const& _type) const; /// Bytes we need to the start of call data. /// - The size in bytes of the function (hash) identifier. diff --git a/libsolidity/Exceptions.h b/libsolidity/Exceptions.h index 0b25abee1..0d07c7064 100644 --- a/libsolidity/Exceptions.h +++ b/libsolidity/Exceptions.h @@ -24,7 +24,7 @@ #include #include -#include +#include namespace dev { @@ -38,7 +38,7 @@ struct CompilerError: virtual Exception {}; struct InternalCompilerError: virtual Exception {}; struct DocstringParsingError: virtual Exception {}; -using errinfo_sourceLocation = boost::error_info; +using errinfo_sourceLocation = boost::error_info; } } diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 461dfef14..430e46b06 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -29,6 +29,7 @@ #include #include #include +#include using namespace std; @@ -37,68 +38,198 @@ namespace dev namespace solidity { -void ExpressionCompiler::compileExpression(CompilerContext& _context, Expression const& _expression, bool _optimize) +void ExpressionCompiler::compile(Expression const& _expression) { - ExpressionCompiler compiler(_context, _optimize); - _expression.accept(compiler); + _expression.accept(*this); } -void ExpressionCompiler::appendTypeConversion(CompilerContext& _context, Type const& _typeOnStack, - Type const& _targetType, bool _cleanupNeeded) +void ExpressionCompiler::appendStateVariableInitialization(VariableDeclaration const& _varDecl) { - ExpressionCompiler compiler(_context); - compiler.appendTypeConversion(_typeOnStack, _targetType, _cleanupNeeded); -} + if (!_varDecl.getValue()) + return; + solAssert(!!_varDecl.getValue()->getType(), "Type information not available."); + CompilerContext::LocationSetter locationSetter(m_context, &_varDecl); + _varDecl.getValue()->accept(*this); + appendTypeConversion(*_varDecl.getValue()->getType(), *_varDecl.getType(), true); -void ExpressionCompiler::appendStateVariableAccessor(CompilerContext& _context, VariableDeclaration const& _varDecl, bool _optimize) -{ - ExpressionCompiler compiler(_context, _optimize); - compiler.appendStateVariableAccessor(_varDecl); + StorageItem(m_context, _varDecl).storeValue(*_varDecl.getType(), _varDecl.getLocation(), true); } -void ExpressionCompiler::appendStateVariableInitialization(CompilerContext& _context, VariableDeclaration const& _varDecl, bool _optimize) +void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& _varDecl) { - compileExpression(_context, *(_varDecl.getValue()), _optimize); - if (_varDecl.getValue()->getType()) - appendTypeConversion(_context, *(_varDecl.getValue())->getType(), *(_varDecl.getValue())->getType()); + CompilerContext::LocationSetter locationSetter(m_context, &_varDecl); + FunctionType accessorType(_varDecl); + + unsigned length = 0; + TypePointers const& paramTypes = accessorType.getParameterTypes(); + // move arguments to memory + for (TypePointer const& paramType: boost::adaptors::reverse(paramTypes)) + length += CompilerUtils(m_context).storeInMemory(length, *paramType, true); + + // retrieve the position of the variable + m_context << m_context.getStorageLocationOfVariable(_varDecl); + TypePointer returnType = _varDecl.getType(); + + for (TypePointer const& paramType: paramTypes) + { + // move offset to memory + CompilerUtils(m_context).storeInMemory(length); + unsigned argLen = CompilerUtils::getPaddedSize(paramType->getCalldataEncodedSize()); + length -= argLen; + m_context << u256(argLen + 32) << u256(length) << eth::Instruction::SHA3; + + returnType = dynamic_cast(*returnType).getValueType(); + } - ExpressionCompiler compiler(_context, _optimize); - compiler.appendStateVariableInitialization(_varDecl); + unsigned retSizeOnStack = 0; + solAssert(accessorType.getReturnParameterTypes().size() >= 1, ""); + if (StructType const* structType = dynamic_cast(returnType.get())) + { + auto const& names = accessorType.getReturnParameterNames(); + auto const& types = accessorType.getReturnParameterTypes(); + // struct + for (size_t i = 0; i < names.size(); ++i) + { + m_context << eth::Instruction::DUP1 + << structType->getStorageOffsetOfMember(names[i]) + << eth::Instruction::ADD; + StorageItem(m_context, types[i]).retrieveValue(SourceLocation(), true); + solAssert(types[i]->getSizeOnStack() == 1, "Returning struct elements with stack size != 1 not yet implemented."); + m_context << eth::Instruction::SWAP1; + retSizeOnStack += types[i]->getSizeOnStack(); + } + m_context << eth::Instruction::POP; + } + else + { + // simple value + solAssert(accessorType.getReturnParameterTypes().size() == 1, ""); + StorageItem(m_context, returnType).retrieveValue(SourceLocation(), true); + retSizeOnStack = returnType->getSizeOnStack(); + } + solAssert(retSizeOnStack <= 15, "Stack too deep."); + m_context << eth::dupInstruction(retSizeOnStack + 1) << eth::Instruction::JUMP; } -void ExpressionCompiler::appendStateVariableInitialization(VariableDeclaration const& _varDecl) +void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded) { - LValue var = LValue(m_context); - var.fromDeclaration(_varDecl, _varDecl.getValue()->getLocation()); - var.storeValue(*_varDecl.getType(), _varDecl.getLocation()); + // For a type extension, we need to remove all higher-order bits that we might have ignored in + // previous operations. + // @todo: store in the AST whether the operand might have "dirty" higher order bits + + if (_typeOnStack == _targetType && !_cleanupNeeded) + return; + Type::Category stackTypeCategory = _typeOnStack.getCategory(); + Type::Category targetTypeCategory = _targetType.getCategory(); + + if (stackTypeCategory == Type::Category::String) + { + StaticStringType const& typeOnStack = dynamic_cast(_typeOnStack); + if (targetTypeCategory == Type::Category::Integer) + { + // conversion from string to hash. no need to clean the high bit + // only to shift right because of opposite alignment + IntegerType const& targetIntegerType = dynamic_cast(_targetType); + solAssert(targetIntegerType.isHash(), "Only conversion between String and Hash is allowed."); + solAssert(targetIntegerType.getNumBits() == typeOnStack.getNumBytes() * 8, "The size should be the same."); + m_context << (u256(1) << (256 - typeOnStack.getNumBytes() * 8)) << eth::Instruction::SWAP1 << eth::Instruction::DIV; + } + else + { + // clear lower-order bytes for conversion to shorter strings - we always clean + solAssert(targetTypeCategory == Type::Category::String, "Invalid type conversion requested."); + StaticStringType const& targetType = dynamic_cast(_targetType); + if (targetType.getNumBytes() < typeOnStack.getNumBytes()) + { + if (targetType.getNumBytes() == 0) + m_context << eth::Instruction::DUP1 << eth::Instruction::XOR; + else + m_context << (u256(1) << (256 - targetType.getNumBytes() * 8)) + << eth::Instruction::DUP1 << eth::Instruction::SWAP2 + << eth::Instruction::DIV << eth::Instruction::MUL; + } + } + } + else if (stackTypeCategory == Type::Category::Enum) + solAssert(targetTypeCategory == Type::Category::Integer || + targetTypeCategory == Type::Category::Enum, ""); + else if (stackTypeCategory == Type::Category::Integer || + stackTypeCategory == Type::Category::Contract || + stackTypeCategory == Type::Category::IntegerConstant) + { + if (targetTypeCategory == Type::Category::String && stackTypeCategory == Type::Category::Integer) + { + // conversion from hash to string. no need to clean the high bit + // only to shift left because of opposite alignment + StaticStringType const& targetStringType = dynamic_cast(_targetType); + IntegerType const& typeOnStack = dynamic_cast(_typeOnStack); + solAssert(typeOnStack.isHash(), "Only conversion between String and Hash is allowed."); + solAssert(typeOnStack.getNumBits() == targetStringType.getNumBytes() * 8, "The size should be the same."); + m_context << (u256(1) << (256 - typeOnStack.getNumBits())) << eth::Instruction::MUL; + } + else if (targetTypeCategory == Type::Category::Enum) + // just clean + appendTypeConversion(_typeOnStack, *_typeOnStack.getRealType(), true); + else + { + solAssert(targetTypeCategory == Type::Category::Integer || targetTypeCategory == Type::Category::Contract, ""); + IntegerType addressType(0, IntegerType::Modifier::Address); + IntegerType const& targetType = targetTypeCategory == Type::Category::Integer + ? dynamic_cast(_targetType) : addressType; + if (stackTypeCategory == Type::Category::IntegerConstant) + { + IntegerConstantType const& constType = dynamic_cast(_typeOnStack); + // We know that the stack is clean, we only have to clean for a narrowing conversion + // where cleanup is forced. + if (targetType.getNumBits() < constType.getIntegerType()->getNumBits() && _cleanupNeeded) + appendHighBitsCleanup(targetType); + } + else + { + IntegerType const& typeOnStack = stackTypeCategory == Type::Category::Integer + ? dynamic_cast(_typeOnStack) : addressType; + // Widening: clean up according to source type width + // Non-widening and force: clean up according to target type bits + if (targetType.getNumBits() > typeOnStack.getNumBits()) + appendHighBitsCleanup(typeOnStack); + else if (_cleanupNeeded) + appendHighBitsCleanup(targetType); + } + } + } + else if (_typeOnStack != _targetType) + // All other types should not be convertible to non-equal types. + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid type conversion requested.")); } bool ExpressionCompiler::visit(Assignment const& _assignment) { + CompilerContext::LocationSetter locationSetter(m_context, &_assignment); _assignment.getRightHandSide().accept(*this); if (_assignment.getType()->isValueType()) appendTypeConversion(*_assignment.getRightHandSide().getType(), *_assignment.getType()); _assignment.getLeftHandSide().accept(*this); - solAssert(m_currentLValue.isValid(), "LValue not retrieved."); + solAssert(!!m_currentLValue, "LValue not retrieved."); Token::Value op = _assignment.getAssignmentOperator(); if (op != Token::Assign) // compound assignment { solAssert(_assignment.getType()->isValueType(), "Compound operators not implemented for non-value types."); - if (m_currentLValue.storesReferenceOnStack()) + if (m_currentLValue->storesReferenceOnStack()) m_context << eth::Instruction::SWAP1 << eth::Instruction::DUP2; - m_currentLValue.retrieveValue(_assignment.getLocation(), true); + m_currentLValue->retrieveValue(_assignment.getLocation(), true); appendOrdinaryBinaryOperatorCode(Token::AssignmentToBinaryOp(op), *_assignment.getType()); - if (m_currentLValue.storesReferenceOnStack()) + if (m_currentLValue->storesReferenceOnStack()) m_context << eth::Instruction::SWAP1; } - m_currentLValue.storeValue(*_assignment.getRightHandSide().getType(), _assignment.getLocation()); + m_currentLValue->storeValue(*_assignment.getRightHandSide().getType(), _assignment.getLocation()); m_currentLValue.reset(); return false; } bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation) { + CompilerContext::LocationSetter locationSetter(m_context, &_unaryOperation); //@todo type checking and creating code for an operator should be in the same place: // the operator should know how to convert itself and to which types it applies, so // put this code together with "Type::acceptsBinary/UnaryOperator" into a class that @@ -120,17 +251,17 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation) m_context << eth::Instruction::NOT; break; case Token::Delete: // delete - solAssert(m_currentLValue.isValid(), "LValue not retrieved."); - m_currentLValue.setToZero(_unaryOperation.getLocation()); + solAssert(!!m_currentLValue, "LValue not retrieved."); + m_currentLValue->setToZero(_unaryOperation.getLocation()); m_currentLValue.reset(); break; case Token::Inc: // ++ (pre- or postfix) case Token::Dec: // -- (pre- or postfix) - solAssert(m_currentLValue.isValid(), "LValue not retrieved."); - m_currentLValue.retrieveValue(_unaryOperation.getLocation()); + solAssert(!!m_currentLValue, "LValue not retrieved."); + m_currentLValue->retrieveValue(_unaryOperation.getLocation()); if (!_unaryOperation.isPrefixOperation()) { - if (m_currentLValue.storesReferenceOnStack()) + if (m_currentLValue->storesReferenceOnStack()) m_context << eth::Instruction::SWAP1 << eth::Instruction::DUP2; else m_context << eth::Instruction::DUP1; @@ -142,10 +273,11 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation) m_context << eth::Instruction::SWAP1 << eth::Instruction::SUB; // @todo avoid the swap // Stack for prefix: [ref] (*ref)+-1 // Stack for postfix: *ref [ref] (*ref)+-1 - if (m_currentLValue.storesReferenceOnStack()) + if (m_currentLValue->storesReferenceOnStack()) m_context << eth::Instruction::SWAP1; - m_currentLValue.storeValue(*_unaryOperation.getType(), _unaryOperation.getLocation(), - !_unaryOperation.isPrefixOperation()); + m_currentLValue->storeValue( + *_unaryOperation.getType(), _unaryOperation.getLocation(), + !_unaryOperation.isPrefixOperation()); m_currentLValue.reset(); break; case Token::Add: // + @@ -163,6 +295,7 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation) bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation) { + CompilerContext::LocationSetter locationSetter(m_context, &_binaryOperation); Expression const& leftExpression = _binaryOperation.getLeftExpression(); Expression const& rightExpression = _binaryOperation.getRightExpression(); Type const& commonType = _binaryOperation.getCommonType(); @@ -175,7 +308,7 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation) else { bool cleanupNeeded = commonType.getCategory() == Type::Category::Integer && - (Token::isCompareOp(c_op) || c_op == Token::Div || c_op == Token::Mod); + (Token::isCompareOp(c_op) || c_op == Token::Div || c_op == Token::Mod); // for commutative operators, push the literal as late as possible to allow improved optimization auto isLiteral = [](Expression const& _e) @@ -209,6 +342,7 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation) bool ExpressionCompiler::visit(FunctionCall const& _functionCall) { + CompilerContext::LocationSetter locationSetter(m_context, &_functionCall); using Location = FunctionType::Location; if (_functionCall.isTypeConversion()) { @@ -426,6 +560,7 @@ bool ExpressionCompiler::visit(NewExpression const&) void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) { + CompilerContext::LocationSetter locationSetter(m_context, &_memberAccess); ASTString const& member = _memberAccess.getMemberName(); switch (_memberAccess.getExpression().getType()->getCategory()) { @@ -499,8 +634,7 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) { StructType const& type = dynamic_cast(*_memberAccess.getExpression().getType()); m_context << type.getStorageOffsetOfMember(member) << eth::Instruction::ADD; - m_currentLValue = LValue(m_context, LValue::LValueType::Storage, _memberAccess.getType()); - m_currentLValue.retrieveValueIfLValueNotRequested(_memberAccess); + setLValueToStorageItem(_memberAccess); break; } case Type::Category::Enum: @@ -530,22 +664,28 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) m_context << enumType->getMemberValue(_memberAccess.getMemberName()); break; } - case Type::Category::ByteArray: + case Type::Category::Array: { - solAssert(member == "length", "Illegal bytearray member."); - auto const& type = dynamic_cast(*_memberAccess.getExpression().getType()); - switch (type.getLocation()) + solAssert(member == "length", "Illegal array member."); + auto const& type = dynamic_cast(*_memberAccess.getExpression().getType()); + if (!type.isDynamicallySized()) { - case ByteArrayType::Location::CallData: - m_context << eth::Instruction::SWAP1 << eth::Instruction::POP; - break; - case ByteArrayType::Location::Storage: - m_context << eth::Instruction::SLOAD; - break; - default: - solAssert(false, "Unsupported byte array location."); - break; + CompilerUtils(m_context).popStackElement(type); + m_context << type.getLength(); } + else + switch (type.getLocation()) + { + case ArrayType::Location::CallData: + m_context << eth::Instruction::SWAP1 << eth::Instruction::POP; + break; + case ArrayType::Location::Storage: + setLValueToStorageItem(_memberAccess); + break; + default: + solAssert(false, "Unsupported array location."); + break; + } break; } default: @@ -555,21 +695,57 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) { + CompilerContext::LocationSetter locationSetter(m_context, &_indexAccess); _indexAccess.getBaseExpression().accept(*this); Type const& baseType = *_indexAccess.getBaseExpression().getType(); - solAssert(baseType.getCategory() == Type::Category::Mapping, ""); - Type const& keyType = *dynamic_cast(baseType).getKeyType(); - m_context << u256(0); - appendExpressionCopyToMemory(keyType, _indexAccess.getIndexExpression()); - solAssert(baseType.getSizeOnStack() == 1, - "Unexpected: Not exactly one stack slot taken by subscriptable expression."); - m_context << eth::Instruction::SWAP1; - appendTypeMoveToMemory(IntegerType(256)); - m_context << u256(0) << eth::Instruction::SHA3; - - m_currentLValue = LValue(m_context, LValue::LValueType::Storage, _indexAccess.getType()); - m_currentLValue.retrieveValueIfLValueNotRequested(_indexAccess); + if (baseType.getCategory() == Type::Category::Mapping) + { + Type const& keyType = *dynamic_cast(baseType).getKeyType(); + m_context << u256(0); + solAssert(_indexAccess.getIndexExpression(), "Index expression expected."); + appendExpressionCopyToMemory(keyType, *_indexAccess.getIndexExpression()); + solAssert(baseType.getSizeOnStack() == 1, + "Unexpected: Not exactly one stack slot taken by subscriptable expression."); + m_context << eth::Instruction::SWAP1; + appendTypeMoveToMemory(IntegerType(256)); + m_context << u256(0) << eth::Instruction::SHA3; + setLValueToStorageItem( _indexAccess); + } + else if (baseType.getCategory() == Type::Category::Array) + { + ArrayType const& arrayType = dynamic_cast(baseType); + solAssert(arrayType.getLocation() == ArrayType::Location::Storage, + "TODO: Index acces only implemented for storage arrays."); + solAssert(!arrayType.isByteArray(), "TODO: Index acces not implemented for byte arrays."); + solAssert(_indexAccess.getIndexExpression(), "Index expression expected."); + + _indexAccess.getIndexExpression()->accept(*this); + // retrieve length + if (arrayType.isDynamicallySized()) + m_context << eth::Instruction::DUP2 << eth::Instruction::SLOAD; + else + m_context << arrayType.getLength(); + // stack: + // check out-of-bounds access + m_context << eth::Instruction::DUP2 << eth::Instruction::LT; + eth::AssemblyItem legalAccess = m_context.appendConditionalJump(); + // out-of-bounds access throws exception (just STOP for now) + m_context << eth::Instruction::STOP; + + m_context << legalAccess; + // stack: + m_context << arrayType.getBaseType()->getStorageSize() << eth::Instruction::MUL; + if (arrayType.isDynamicallySized()) + { + m_context << eth::Instruction::SWAP1; + CompilerUtils(m_context).computeHashStatic(); + } + m_context << eth::Instruction::ADD; + setLValueToStorageItem(_indexAccess); + } + else + solAssert(false, "Index access only allowed for mappings or arrays."); return false; } @@ -587,10 +763,7 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier) else if (FunctionDefinition const* functionDef = dynamic_cast(declaration)) m_context << m_context.getVirtualFunctionEntryLabel(*functionDef).pushTag(); else if (dynamic_cast(declaration)) - { - m_currentLValue.fromDeclaration(*declaration, _identifier.getLocation()); - m_currentLValue.retrieveValueIfLValueNotRequested(_identifier); - } + setLValueFromDeclaration(*declaration, _identifier); else if (dynamic_cast(declaration)) { // no-op @@ -747,96 +920,6 @@ void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator) } } -void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded) -{ - // For a type extension, we need to remove all higher-order bits that we might have ignored in - // previous operations. - // @todo: store in the AST whether the operand might have "dirty" higher order bits - - if (_typeOnStack == _targetType && !_cleanupNeeded) - return; - Type::Category stackTypeCategory = _typeOnStack.getCategory(); - Type::Category targetTypeCategory = _targetType.getCategory(); - - if (stackTypeCategory == Type::Category::String) - { - StaticStringType const& typeOnStack = dynamic_cast(_typeOnStack); - if (targetTypeCategory == Type::Category::Integer) - { - // conversion from string to hash. no need to clean the high bit - // only to shift right because of opposite alignment - IntegerType const& targetIntegerType = dynamic_cast(_targetType); - solAssert(targetIntegerType.isHash(), "Only conversion between String and Hash is allowed."); - solAssert(targetIntegerType.getNumBits() == typeOnStack.getNumBytes() * 8, "The size should be the same."); - m_context << (u256(1) << (256 - typeOnStack.getNumBytes() * 8)) << eth::Instruction::SWAP1 << eth::Instruction::DIV; - } - else - { - // clear lower-order bytes for conversion to shorter strings - we always clean - solAssert(targetTypeCategory == Type::Category::String, "Invalid type conversion requested."); - StaticStringType const& targetType = dynamic_cast(_targetType); - if (targetType.getNumBytes() < typeOnStack.getNumBytes()) - { - if (targetType.getNumBytes() == 0) - m_context << eth::Instruction::DUP1 << eth::Instruction::XOR; - else - m_context << (u256(1) << (256 - targetType.getNumBytes() * 8)) - << eth::Instruction::DUP1 << eth::Instruction::SWAP2 - << eth::Instruction::DIV << eth::Instruction::MUL; - } - } - } - else if (stackTypeCategory == Type::Category::Enum) - solAssert(targetTypeCategory == Type::Category::Integer || - targetTypeCategory == Type::Category::Enum, ""); - else if (stackTypeCategory == Type::Category::Integer || stackTypeCategory == Type::Category::Contract || - stackTypeCategory == Type::Category::IntegerConstant) - { - if (targetTypeCategory == Type::Category::String && stackTypeCategory == Type::Category::Integer) - { - // conversion from hash to string. no need to clean the high bit - // only to shift left because of opposite alignment - StaticStringType const& targetStringType = dynamic_cast(_targetType); - IntegerType const& typeOnStack = dynamic_cast(_typeOnStack); - solAssert(typeOnStack.isHash(), "Only conversion between String and Hash is allowed."); - solAssert(typeOnStack.getNumBits() == targetStringType.getNumBytes() * 8, "The size should be the same."); - m_context << (u256(1) << (256 - typeOnStack.getNumBits())) << eth::Instruction::MUL; - } - else if (targetTypeCategory == Type::Category::Enum) - // just clean - appendTypeConversion(_typeOnStack, *_typeOnStack.getRealType(), true); - else - { - solAssert(targetTypeCategory == Type::Category::Integer || targetTypeCategory == Type::Category::Contract, ""); - IntegerType addressType(0, IntegerType::Modifier::Address); - IntegerType const& targetType = targetTypeCategory == Type::Category::Integer - ? dynamic_cast(_targetType) : addressType; - if (stackTypeCategory == Type::Category::IntegerConstant) - { - IntegerConstantType const& constType = dynamic_cast(_typeOnStack); - // We know that the stack is clean, we only have to clean for a narrowing conversion - // where cleanup is forced. - if (targetType.getNumBits() < constType.getIntegerType()->getNumBits() && _cleanupNeeded) - appendHighBitsCleanup(targetType); - } - else - { - IntegerType const& typeOnStack = stackTypeCategory == Type::Category::Integer - ? dynamic_cast(_typeOnStack) : addressType; - // Widening: clean up according to source type width - // Non-widening and force: clean up according to target type bits - if (targetType.getNumBits() > typeOnStack.getNumBits()) - appendHighBitsCleanup(typeOnStack); - else if (_cleanupNeeded) - appendHighBitsCleanup(targetType); - } - } - } - else if (_typeOnStack != _targetType) - // All other types should not be convertible to non-equal types. - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid type conversion requested.")); -} - void ExpressionCompiler::appendHighBitsCleanup(IntegerType const& _typeOnStack) { if (_typeOnStack.getNumBits() == 256) @@ -947,318 +1030,21 @@ void ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, appendTypeMoveToMemory(_expectedType); } -void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& _varDecl) +void ExpressionCompiler::setLValueFromDeclaration(Declaration const& _declaration, Expression const& _expression) { - FunctionType accessorType(_varDecl); - - unsigned length = 0; - TypePointers const& paramTypes = accessorType.getParameterTypes(); - // move arguments to memory - for (TypePointer const& paramType: boost::adaptors::reverse(paramTypes)) - length += CompilerUtils(m_context).storeInMemory(length, *paramType, true); - - // retrieve the position of the variable - m_context << m_context.getStorageLocationOfVariable(_varDecl); - TypePointer returnType = _varDecl.getType(); - - for (TypePointer const& paramType: paramTypes) - { - // move offset to memory - CompilerUtils(m_context).storeInMemory(length); - unsigned argLen = CompilerUtils::getPaddedSize(paramType->getCalldataEncodedSize()); - length -= argLen; - m_context << u256(argLen + 32) << u256(length) << eth::Instruction::SHA3; - - returnType = dynamic_cast(*returnType).getValueType(); - } - - unsigned retSizeOnStack = 0; - solAssert(accessorType.getReturnParameterTypes().size() >= 1, ""); - if (StructType const* structType = dynamic_cast(returnType.get())) - { - auto const& names = accessorType.getReturnParameterNames(); - auto const& types = accessorType.getReturnParameterTypes(); - // struct - for (size_t i = 0; i < names.size(); ++i) - { - m_context << eth::Instruction::DUP1 - << structType->getStorageOffsetOfMember(names[i]) - << eth::Instruction::ADD; - m_currentLValue = LValue(m_context, LValue::LValueType::Storage, types[i]); - m_currentLValue.retrieveValue(Location(), true); - solAssert(types[i]->getSizeOnStack() == 1, "Returning struct elements with stack size != 1 not yet implemented."); - m_context << eth::Instruction::SWAP1; - retSizeOnStack += types[i]->getSizeOnStack(); - } - m_context << eth::Instruction::POP; - } - else - { - // simple value - solAssert(accessorType.getReturnParameterTypes().size() == 1, ""); - m_currentLValue = LValue(m_context, LValue::LValueType::Storage, returnType); - m_currentLValue.retrieveValue(Location(), true); - retSizeOnStack = returnType->getSizeOnStack(); - } - solAssert(retSizeOnStack <= 15, "Stack too deep."); - m_context << eth::dupInstruction(retSizeOnStack + 1) << eth::Instruction::JUMP; -} - -ExpressionCompiler::LValue::LValue(CompilerContext& _compilerContext, LValueType _type, - TypePointer const& _dataType, unsigned _baseStackOffset): - m_context(&_compilerContext), m_type(_type), m_dataType(_dataType), - m_baseStackOffset(_baseStackOffset) -{ - //@todo change the type cast for arrays - solAssert(m_dataType->getStorageSize() <= numeric_limits::max(), - "The storage size of " + m_dataType->toString() + " should fit in unsigned"); - if (m_type == LValueType::Storage) - m_size = unsigned(m_dataType->getStorageSize()); - else - m_size = unsigned(m_dataType->getSizeOnStack()); -} - -void ExpressionCompiler::LValue::fromDeclaration(Declaration const& _declaration, Location const& _location) -{ - if (m_context->isLocalVariable(&_declaration)) - { - m_type = LValueType::Stack; - m_dataType = _declaration.getType(); - m_size = m_dataType->getSizeOnStack(); - m_baseStackOffset = m_context->getBaseStackOffsetOfVariable(_declaration); - } - else if (m_context->isStateVariable(&_declaration)) - { - *m_context << m_context->getStorageLocationOfVariable(_declaration); - m_type = LValueType::Storage; - m_dataType = _declaration.getType(); - solAssert(m_dataType->getStorageSize() <= numeric_limits::max(), - "The storage size of " + m_dataType->toString() + " should fit in an unsigned"); - m_size = unsigned(m_dataType->getStorageSize()); - } + if (m_context.isLocalVariable(&_declaration)) + setLValue(_expression, _declaration); + else if (m_context.isStateVariable(&_declaration)) + setLValue(_expression, _declaration); else - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_location) - << errinfo_comment("Identifier type not supported or identifier not found.")); + BOOST_THROW_EXCEPTION(InternalCompilerError() + << errinfo_sourceLocation(_expression.getLocation()) + << errinfo_comment("Identifier type not supported or identifier not found.")); } -void ExpressionCompiler::LValue::retrieveValue(Location const& _location, bool _remove) const +void ExpressionCompiler::setLValueToStorageItem(Expression const& _expression) { - switch (m_type) - { - case LValueType::Stack: - { - unsigned stackPos = m_context->baseToCurrentStackOffset(unsigned(m_baseStackOffset)); - if (stackPos >= 15) //@todo correct this by fetching earlier or moving to memory - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_location) - << errinfo_comment("Stack too deep.")); - for (unsigned i = 0; i < m_size; ++i) - *m_context << eth::dupInstruction(stackPos + 1); - break; - } - case LValueType::Storage: - retrieveValueFromStorage(_remove); - break; - case LValueType::Memory: - if (!m_dataType->isValueType()) - break; // no distinction between value and reference for non-value types - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_location) - << errinfo_comment("Location type not yet implemented.")); - break; - default: - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_location) - << errinfo_comment("Unsupported location type.")); - break; - } -} - -void ExpressionCompiler::LValue::retrieveValueFromStorage(bool _remove) const -{ - if (!m_dataType->isValueType()) - return; // no distinction between value and reference for non-value types - if (!_remove) - *m_context << eth::Instruction::DUP1; - if (m_size == 1) - *m_context << eth::Instruction::SLOAD; - else - for (unsigned i = 0; i < m_size; ++i) - { - *m_context << eth::Instruction::DUP1 << eth::Instruction::SLOAD << eth::Instruction::SWAP1; - if (i + 1 < m_size) - *m_context << u256(1) << eth::Instruction::ADD; - else - *m_context << eth::Instruction::POP; - } -} - -void ExpressionCompiler::LValue::storeValue(Type const& _sourceType, Location const& _location, bool _move) const -{ - switch (m_type) - { - case LValueType::Stack: - { - unsigned stackDiff = m_context->baseToCurrentStackOffset(unsigned(m_baseStackOffset)) - m_size + 1; - if (stackDiff > 16) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_location) - << errinfo_comment("Stack too deep.")); - else if (stackDiff > 0) - for (unsigned i = 0; i < m_size; ++i) - *m_context << eth::swapInstruction(stackDiff) << eth::Instruction::POP; - if (!_move) - retrieveValue(_location); - break; - } - case LValueType::Storage: - // stack layout: value value ... value target_ref - if (m_dataType->isValueType()) - { - if (!_move) // copy values - { - if (m_size + 1 > 16) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_location) - << errinfo_comment("Stack too deep.")); - for (unsigned i = 0; i < m_size; ++i) - *m_context << eth::dupInstruction(m_size + 1) << eth::Instruction::SWAP1; - } - if (m_size > 0) // store high index value first - *m_context << u256(m_size - 1) << eth::Instruction::ADD; - for (unsigned i = 0; i < m_size; ++i) - { - if (i + 1 >= m_size) - *m_context << eth::Instruction::SSTORE; - else - // stack here: value value ... value value (target_ref+offset) - *m_context << eth::Instruction::SWAP1 << eth::Instruction::DUP2 - << eth::Instruction::SSTORE - << u256(1) << eth::Instruction::SWAP1 << eth::Instruction::SUB; - } - } - else - { - solAssert(_sourceType.getCategory() == m_dataType->getCategory(), "Wrong type conversation for assignment."); - if (m_dataType->getCategory() == Type::Category::ByteArray) - { - CompilerUtils(*m_context).copyByteArrayToStorage( - dynamic_cast(*m_dataType), - dynamic_cast(_sourceType)); - if (_move) - *m_context << eth::Instruction::POP; - } - else if (m_dataType->getCategory() == Type::Category::Struct) - { - // stack layout: source_ref target_ref - auto const& structType = dynamic_cast(*m_dataType); - solAssert(structType == _sourceType, "Struct assignment with conversion."); - for (auto const& member: structType.getMembers()) - { - // assign each member that is not a mapping - TypePointer const& memberType = member.second; - if (memberType->getCategory() == Type::Category::Mapping) - continue; - *m_context << structType.getStorageOffsetOfMember(member.first) - << eth::Instruction::DUP3 << eth::Instruction::DUP2 - << eth::Instruction::ADD; - // stack: source_ref target_ref member_offset source_member_ref - LValue rightHandSide(*m_context, LValueType::Storage, memberType); - rightHandSide.retrieveValue(_location, true); - // stack: source_ref target_ref member_offset source_value... - *m_context << eth::dupInstruction(2 + memberType->getSizeOnStack()) - << eth::dupInstruction(2 + memberType->getSizeOnStack()) - << eth::Instruction::ADD; - // stack: source_ref target_ref member_offset source_value... target_member_ref - LValue memberLValue(*m_context, LValueType::Storage, memberType); - memberLValue.storeValue(*memberType, _location, true); - *m_context << eth::Instruction::POP; - } - if (_move) - *m_context << eth::Instruction::POP; - else - *m_context << eth::Instruction::SWAP1; - *m_context << eth::Instruction::POP; - } - else - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_location) - << errinfo_comment("Invalid non-value type for assignment.")); - } - break; - case LValueType::Memory: - if (!m_dataType->isValueType()) - break; // no distinction between value and reference for non-value types - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_location) - << errinfo_comment("Location type not yet implemented.")); - break; - default: - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_location) - << errinfo_comment("Unsupported location type.")); - break; - } -} - -void ExpressionCompiler::LValue::setToZero(Location const& _location) const -{ - switch (m_type) - { - case LValueType::Stack: - { - unsigned stackDiff = m_context->baseToCurrentStackOffset(unsigned(m_baseStackOffset)); - if (stackDiff > 16) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_location) - << errinfo_comment("Stack too deep.")); - solAssert(stackDiff >= m_size - 1, ""); - for (unsigned i = 0; i < m_size; ++i) - *m_context << u256(0) << eth::swapInstruction(stackDiff + 1 - i) - << eth::Instruction::POP; - break; - } - case LValueType::Storage: - if (m_dataType->getCategory() == Type::Category::ByteArray) - CompilerUtils(*m_context).clearByteArray(dynamic_cast(*m_dataType)); - else if (m_dataType->getCategory() == Type::Category::Struct) - { - // stack layout: ref - auto const& structType = dynamic_cast(*m_dataType); - for (auto const& member: structType.getMembers()) - { - // zero each member that is not a mapping - TypePointer const& memberType = member.second; - if (memberType->getCategory() == Type::Category::Mapping) - continue; - *m_context << structType.getStorageOffsetOfMember(member.first) - << eth::Instruction::DUP2 << eth::Instruction::ADD; - LValue memberValue(*m_context, LValueType::Storage, memberType); - memberValue.setToZero(); - } - *m_context << eth::Instruction::POP; - } - else - { - if (m_size == 0) - *m_context << eth::Instruction::POP; - for (unsigned i = 0; i < m_size; ++i) - if (i + 1 >= m_size) - *m_context << u256(0) << eth::Instruction::SWAP1 << eth::Instruction::SSTORE; - else - *m_context << u256(0) << eth::Instruction::DUP2 << eth::Instruction::SSTORE - << u256(1) << eth::Instruction::ADD; - } - break; - case LValueType::Memory: - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_location) - << errinfo_comment("Location type not yet implemented.")); - break; - default: - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_location) - << errinfo_comment("Unsupported location type.")); - break; - } -} - -void ExpressionCompiler::LValue::retrieveValueIfLValueNotRequested(Expression const& _expression) -{ - if (!_expression.lvalueRequested()) - { - retrieveValue(_expression.getLocation(), true); - reset(); - } + setLValue(_expression, _expression.getType()); } } diff --git a/libsolidity/ExpressionCompiler.h b/libsolidity/ExpressionCompiler.h index 889c58b19..9cab757ea 100644 --- a/libsolidity/ExpressionCompiler.h +++ b/libsolidity/ExpressionCompiler.h @@ -25,8 +25,10 @@ #include #include #include -#include +#include +#include #include +#include namespace dev { namespace eth @@ -39,7 +41,7 @@ namespace solidity { class CompilerContext; class Type; class IntegerType; -class ByteArrayType; +class ArrayType; class StaticStringType; /** @@ -50,22 +52,28 @@ class StaticStringType; class ExpressionCompiler: private ASTConstVisitor { public: - /// Compile the given @a _expression into the @a _context. - static void compileExpression(CompilerContext& _context, Expression const& _expression, bool _optimize = false); - - /// Appends code to remove dirty higher order bits in case of an implicit promotion to a wider type. - static void appendTypeConversion(CompilerContext& _context, Type const& _typeOnStack, - Type const& _targetType, bool _cleanupNeeded = false); /// Appends code for a State Variable accessor function static void appendStateVariableAccessor(CompilerContext& _context, VariableDeclaration const& _varDecl, bool _optimize = false); - /// Appends code for a State Variable Initialization function - static void appendStateVariableInitialization(CompilerContext& _context, VariableDeclaration const& _varDecl, bool _optimize = false); - -private: explicit ExpressionCompiler(CompilerContext& _compilerContext, bool _optimize = false): - m_optimize(_optimize), m_context(_compilerContext), m_currentLValue(m_context) {} + m_optimize(_optimize), m_context(_compilerContext) {} + + /// Compile the given @a _expression and leave its value on the stack. + void compile(Expression const& _expression); + + /// Appends code to set a state variable to its initial value/expression. + void appendStateVariableInitialization(VariableDeclaration const& _varDecl); + + /// Appends code for a State Variable accessor function + void appendStateVariableAccessor(VariableDeclaration const& _varDecl); + + /// Appends an implicit or explicit type conversion. For now this comprises only erasing + /// higher-order bits (@see appendHighBitCleanup) when widening integer. + /// If @a _cleanupNeeded, high order bits cleanup is also done if no type conversion would be + /// necessary. + void appendTypeConversion(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded = false); +private: virtual bool visit(Assignment const& _assignment) override; virtual bool visit(UnaryOperation const& _unaryOperation) override; virtual bool visit(BinaryOperation const& _binaryOperation) override; @@ -87,11 +95,6 @@ private: void appendShiftOperatorCode(Token::Value _operator); /// @} - /// Appends an implicit or explicit type conversion. For now this comprises only erasing - /// higher-order bits (@see appendHighBitCleanup) when widening integer. - /// If @a _cleanupNeeded, high order bits cleanup is also done if no type conversion would be - /// necessary. - void appendTypeConversion(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded = false); //// Appends code that cleans higher-order bits for integer types. void appendHighBitsCleanup(IntegerType const& _typeOnStack); @@ -111,77 +114,34 @@ private: /// expected to be on the stack and is updated by this call. void appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression); - /// Appends code for a State Variable accessor function - void appendStateVariableAccessor(VariableDeclaration const& _varDecl); - - /// Appends code for a State Variable initialization - void appendStateVariableInitialization(VariableDeclaration const& _varDecl); - - /** - * Helper class to store and retrieve lvalues to and from various locations. - * All types except STACK store a reference in a slot on the stack, STACK just - * stores the base stack offset of the variable in @a m_baseStackOffset. - */ - class LValue - { - public: - enum class LValueType { None, Stack, Memory, Storage }; - - explicit LValue(CompilerContext& _compilerContext): m_context(&_compilerContext) { reset(); } - LValue(CompilerContext& _compilerContext, LValueType _type, - std::shared_ptr const& _dataType, unsigned _baseStackOffset = 0); - - /// Set type according to the declaration and retrieve the reference. - /// @a _location is the current location - void fromDeclaration(Declaration const& _declaration, Location const& _location); - - void reset() { m_type = LValueType::None; m_dataType.reset(); m_baseStackOffset = 0; m_size = 0; } - - bool isValid() const { return m_type != LValueType::None; } - bool isInOnStack() const { return m_type == LValueType::Stack; } - bool isInMemory() const { return m_type == LValueType::Memory; } - bool isInStorage() const { return m_type == LValueType::Storage; } - - /// @returns true if this lvalue reference type occupies a slot on the stack. - bool storesReferenceOnStack() const { return m_type == LValueType::Storage || m_type == LValueType::Memory; } - - /// Copies the value of the current lvalue to the top of the stack and, if @a _remove is true, - /// also removes the reference from the stack (note that is does not reset the type to @a NONE). - /// @a _location source location of the current expression, used for error reporting. - void retrieveValue(Location const& _location, bool _remove = false) const; - /// Moves a value from the stack to the lvalue. Removes the value if @a _move is true. - /// @a _location is the source location of the expression that caused this operation. - /// Stack pre: value [lvalue_ref] - /// Stack post if !_move: value_of(lvalue_ref) - void storeValue(Type const& _sourceType, Location const& _location = Location(), bool _move = false) const; - /// Stores zero in the lvalue. - /// @a _location is the source location of the requested operation - void setToZero(Location const& _location = Location()) const; - /// Convenience function to convert the stored reference to a value and reset type to NONE if - /// the reference was not requested by @a _expression. - void retrieveValueIfLValueNotRequested(Expression const& _expression); - - private: - /// Convenience function to retrieve Value from Storage. Specific version of @ref retrieveValue - void retrieveValueFromStorage(bool _remove = false) const; - /// Copies from a byte array to a byte array in storage, both references on the stack. - void copyByteArrayToStorage(ByteArrayType const& _targetType, ByteArrayType const& _sourceType) const; - - CompilerContext* m_context; - LValueType m_type = LValueType::None; - std::shared_ptr m_dataType; - /// If m_type is STACK, this is base stack offset (@see - /// CompilerContext::getBaseStackOffsetOfVariable) of a local variable. - unsigned m_baseStackOffset = 0; - /// Size of the value of this lvalue on the stack or the storage. - unsigned m_size = 0; - }; + /// Sets the current LValue to a new one (of the appropriate type) from the given declaration. + /// Also retrieves the value if it was not requested by @a _expression. + void setLValueFromDeclaration(Declaration const& _declaration, Expression const& _expression); + /// Sets the current LValue to a StorageItem holding the type of @a _expression. The reference is assumed + /// to be on the stack. + /// Also retrieves the value if it was not requested by @a _expression. + void setLValueToStorageItem(Expression const& _expression); + /// Sets the current LValue to a new LValue constructed from the arguments. + /// Also retrieves the value if it was not requested by @a _expression. + template + void setLValue(Expression const& _expression, _Arguments const&... _arguments); bool m_optimize; CompilerContext& m_context; - LValue m_currentLValue; + std::unique_ptr m_currentLValue; }; +template +void ExpressionCompiler::setLValue(Expression const& _expression, _Arguments const&... _arguments) +{ + solAssert(!m_currentLValue, "Current LValue not reset before trying to set new one."); + std::unique_ptr<_LValueType> lvalue(new _LValueType(m_context, _arguments...)); + if (_expression.lvalueRequested()) + m_currentLValue = move(lvalue); + else + lvalue->retrieveValue(_expression.getLocation(), true); + +} } } diff --git a/libsolidity/LValue.cpp b/libsolidity/LValue.cpp new file mode 100644 index 000000000..db59c41af --- /dev/null +++ b/libsolidity/LValue.cpp @@ -0,0 +1,223 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** + * @author Christian + * @date 2015 + * LValues for use in the expresison compiler. + */ + +#include +#include +#include +#include +#include + +using namespace std; +using namespace dev; +using namespace solidity; + + +StackVariable::StackVariable(CompilerContext& _compilerContext, Declaration const& _declaration): + LValue(_compilerContext, _declaration.getType()), + m_baseStackOffset(m_context.getBaseStackOffsetOfVariable(_declaration)), + m_size(m_dataType->getSizeOnStack()) +{ +} + +void StackVariable::retrieveValue(SourceLocation const& _location, bool _remove) const +{ + (void)_remove; + unsigned stackPos = m_context.baseToCurrentStackOffset(m_baseStackOffset); + if (stackPos >= 15) //@todo correct this by fetching earlier or moving to memory + BOOST_THROW_EXCEPTION(CompilerError() + << errinfo_sourceLocation(_location) << errinfo_comment("Stack too deep.")); + for (unsigned i = 0; i < m_size; ++i) + m_context << eth::dupInstruction(stackPos + 1); +} + +void StackVariable::storeValue(Type const& _sourceType, SourceLocation const& _location, bool _move) const +{ + (void)_sourceType; + unsigned stackDiff = m_context.baseToCurrentStackOffset(m_baseStackOffset) - m_size + 1; + if (stackDiff > 16) + BOOST_THROW_EXCEPTION(CompilerError() + << errinfo_sourceLocation(_location) << errinfo_comment("Stack too deep.")); + else if (stackDiff > 0) + for (unsigned i = 0; i < m_size; ++i) + m_context << eth::swapInstruction(stackDiff) << eth::Instruction::POP; + if (!_move) + retrieveValue(_location); +} + +void StackVariable::setToZero(SourceLocation const& _location) const +{ + unsigned stackDiff = m_context.baseToCurrentStackOffset(m_baseStackOffset); + if (stackDiff > 16) + BOOST_THROW_EXCEPTION(CompilerError() + << errinfo_sourceLocation(_location) << errinfo_comment("Stack too deep.")); + solAssert(stackDiff >= m_size - 1, ""); + for (unsigned i = 0; i < m_size; ++i) + m_context << u256(0) << eth::swapInstruction(stackDiff + 1 - i) + << eth::Instruction::POP; +} + + +StorageItem::StorageItem(CompilerContext& _compilerContext, Declaration const& _declaration): + StorageItem(_compilerContext, _declaration.getType()) +{ + m_context << m_context.getStorageLocationOfVariable(_declaration); +} + +StorageItem::StorageItem(CompilerContext& _compilerContext, TypePointer const& _type): + LValue(_compilerContext, _type) +{ + if (m_dataType->isValueType()) + { + solAssert(m_dataType->getStorageSize() == m_dataType->getSizeOnStack(), ""); + solAssert(m_dataType->getStorageSize() <= numeric_limits::max(), + "The storage size of " + m_dataType->toString() + " should fit in an unsigned"); + m_size = unsigned(m_dataType->getStorageSize()); + } + else + m_size = 0; // unused +} + +void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const +{ + if (!m_dataType->isValueType()) + return; // no distinction between value and reference for non-value types + if (!_remove) + m_context << eth::Instruction::DUP1; + if (m_size == 1) + m_context << eth::Instruction::SLOAD; + else + for (unsigned i = 0; i < m_size; ++i) + { + m_context << eth::Instruction::DUP1 << eth::Instruction::SLOAD << eth::Instruction::SWAP1; + if (i + 1 < m_size) + m_context << u256(1) << eth::Instruction::ADD; + else + m_context << eth::Instruction::POP; + } +} + +void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _location, bool _move) const +{ + // stack layout: value value ... value target_ref + if (m_dataType->isValueType()) + { + if (!_move) // copy values + { + if (m_size + 1 > 16) + BOOST_THROW_EXCEPTION(CompilerError() + << errinfo_sourceLocation(_location) << errinfo_comment("Stack too deep.")); + for (unsigned i = 0; i < m_size; ++i) + m_context << eth::dupInstruction(m_size + 1) << eth::Instruction::SWAP1; + } + if (m_size > 1) // store high index value first + m_context << u256(m_size - 1) << eth::Instruction::ADD; + for (unsigned i = 0; i < m_size; ++i) + { + if (i + 1 >= m_size) + m_context << eth::Instruction::SSTORE; + else + // stack here: value value ... value value (target_ref+offset) + m_context << eth::Instruction::SWAP1 << eth::Instruction::DUP2 + << eth::Instruction::SSTORE + << u256(1) << eth::Instruction::SWAP1 << eth::Instruction::SUB; + } + } + else + { + solAssert(_sourceType.getCategory() == m_dataType->getCategory(), + "Wrong type conversation for assignment."); + if (m_dataType->getCategory() == Type::Category::Array) + { + CompilerUtils(m_context).copyByteArrayToStorage( + dynamic_cast(*m_dataType), + dynamic_cast(_sourceType)); + if (_move) + m_context << eth::Instruction::POP; + } + else if (m_dataType->getCategory() == Type::Category::Struct) + { + // stack layout: source_ref target_ref + auto const& structType = dynamic_cast(*m_dataType); + solAssert(structType == _sourceType, "Struct assignment with conversion."); + for (auto const& member: structType.getMembers()) + { + // assign each member that is not a mapping + TypePointer const& memberType = member.second; + if (memberType->getCategory() == Type::Category::Mapping) + continue; + m_context << structType.getStorageOffsetOfMember(member.first) + << eth::Instruction::DUP3 << eth::Instruction::DUP2 << eth::Instruction::ADD; + // stack: source_ref target_ref member_offset source_member_ref + StorageItem(m_context, memberType).retrieveValue(_location, true); + // stack: source_ref target_ref member_offset source_value... + m_context << eth::dupInstruction(2 + memberType->getSizeOnStack()) + << eth::dupInstruction(2 + memberType->getSizeOnStack()) << eth::Instruction::ADD; + // stack: source_ref target_ref member_offset source_value... target_member_ref + StorageItem(m_context, memberType).storeValue(*memberType, _location, true); + m_context << eth::Instruction::POP; + } + if (_move) + m_context << eth::Instruction::POP; + else + m_context << eth::Instruction::SWAP1; + m_context << eth::Instruction::POP; + } + else + BOOST_THROW_EXCEPTION(InternalCompilerError() + << errinfo_sourceLocation(_location) << errinfo_comment("Invalid non-value type for assignment.")); + } +} + + +void StorageItem::setToZero(SourceLocation const& _location) const +{ + (void)_location; + if (m_dataType->getCategory() == Type::Category::Array) + CompilerUtils(m_context).clearByteArray(dynamic_cast(*m_dataType)); + else if (m_dataType->getCategory() == Type::Category::Struct) + { + // stack layout: ref + auto const& structType = dynamic_cast(*m_dataType); + for (auto const& member: structType.getMembers()) + { + // zero each member that is not a mapping + TypePointer const& memberType = member.second; + if (memberType->getCategory() == Type::Category::Mapping) + continue; + m_context << structType.getStorageOffsetOfMember(member.first) + << eth::Instruction::DUP2 << eth::Instruction::ADD; + StorageItem(m_context, memberType).setToZero(); + } + m_context << eth::Instruction::POP; + } + else + { + if (m_size == 0) + m_context << eth::Instruction::POP; + for (unsigned i = 0; i < m_size; ++i) + if (i + 1 >= m_size) + m_context << u256(0) << eth::Instruction::SWAP1 << eth::Instruction::SSTORE; + else + m_context << u256(0) << eth::Instruction::DUP2 << eth::Instruction::SSTORE + << u256(1) << eth::Instruction::ADD; + } +} diff --git a/libsolidity/LValue.h b/libsolidity/LValue.h new file mode 100644 index 000000000..bfa681a48 --- /dev/null +++ b/libsolidity/LValue.h @@ -0,0 +1,112 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** + * @author Christian + * @date 2015 + * LValues for use in the expresison compiler. + */ + +#pragma once + +#include +#include + +namespace dev +{ +namespace solidity +{ + +class Declaration; +class Type; +class CompilerContext; + +/** + * Abstract class used to retrieve, delete and store data in lvalues/variables. + */ +class LValue +{ +protected: + LValue(CompilerContext& _compilerContext, std::shared_ptr const& _dataType): + m_context(_compilerContext), m_dataType(_dataType) {} + +public: + /// @returns true if this lvalue reference type occupies a slot on the stack. + virtual bool storesReferenceOnStack() const = 0; + /// Copies the value of the current lvalue to the top of the stack and, if @a _remove is true, + /// also removes the reference from the stack. + /// @a _location source location of the current expression, used for error reporting. + virtual void retrieveValue(SourceLocation const& _location, bool _remove = false) const = 0; + /// Moves a value from the stack to the lvalue. Removes the value if @a _move is true. + /// @a _location is the source location of the expression that caused this operation. + /// Stack pre: value [lvalue_ref] + /// Stack post: if !_move: value_of(lvalue_ref) + virtual void storeValue(Type const& _sourceType, + SourceLocation const& _location = SourceLocation(), bool _move = false) const = 0; + /// Stores zero in the lvalue. + /// @a _location is the source location of the requested operation + virtual void setToZero(SourceLocation const& _location = SourceLocation()) const = 0; + +protected: + CompilerContext& m_context; + std::shared_ptr m_dataType; +}; + +/** + * Local variable that is completely stored on the stack. + */ +class StackVariable: public LValue +{ +public: + explicit StackVariable(CompilerContext& _compilerContext, Declaration const& _declaration); + + virtual bool storesReferenceOnStack() const { return false; } + virtual void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; + virtual void storeValue(Type const& _sourceType, + SourceLocation const& _location = SourceLocation(), bool _move = false) const override; + virtual void setToZero(SourceLocation const& _location = SourceLocation()) const override; + +private: + /// Base stack offset (@see CompilerContext::getBaseStackOffsetOfVariable) of the local variable. + unsigned m_baseStackOffset; + /// Number of stack elements occupied by the value (not the reference). + unsigned m_size; +}; + +/** + * Reference to some item in storage. The (starting) position of the item is stored on the stack. + */ +class StorageItem: public LValue +{ +public: + /// Constructs the LValue and pushes the location of @a _declaration onto the stack. + explicit StorageItem(CompilerContext& _compilerContext, Declaration const& _declaration); + /// Constructs the LValue and assumes that the storage reference is already on the stack. + explicit StorageItem(CompilerContext& _compilerContext, std::shared_ptr const& _type); + virtual bool storesReferenceOnStack() const { return true; } + virtual void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; + virtual void storeValue(Type const& _sourceType, + SourceLocation const& _location = SourceLocation(), bool _move = false) const override; + virtual void setToZero(SourceLocation const& _location = SourceLocation()) const override; + +private: + /// Number of stack elements occupied by the value (not the reference). + /// Only used for value types. + unsigned m_size; +}; + +} +} diff --git a/libsolidity/NameAndTypeResolver.cpp b/libsolidity/NameAndTypeResolver.cpp index 15e1ac6f5..f6ee2f1d0 100644 --- a/libsolidity/NameAndTypeResolver.cpp +++ b/libsolidity/NameAndTypeResolver.cpp @@ -334,10 +334,10 @@ void ReferencesResolver::endVisit(VariableDeclaration& _variable) if (_variable.getTypeName()) { TypePointer type = _variable.getTypeName()->toType(); - // All byte array parameter types should point to call data + // All array parameter types should point to call data if (_variable.isExternalFunctionParameter()) - if (auto const* byteArrayType = dynamic_cast(type.get())) - type = byteArrayType->copyForLocation(ByteArrayType::Location::CallData); + if (auto const* arrayType = dynamic_cast(type.get())) + type = arrayType->copyForLocation(ArrayType::Location::CallData); _variable.setType(type); if (!_variable.getType()) diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index 9fe1af22e..3c88efc7c 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include #include @@ -41,8 +41,11 @@ class Parser::ASTNodeFactory public: ASTNodeFactory(Parser const& _parser): m_parser(_parser), m_location(_parser.getPosition(), -1, _parser.getSourceName()) {} + ASTNodeFactory(Parser const& _parser, ASTPointer const& _childNode): + m_parser(_parser), m_location(_childNode->getLocation()) {} void markEndPosition() { m_location.end = m_parser.getEndPosition(); } + void setLocation(SourceLocation const& _location) { m_location = _location; } void setLocationEmpty() { m_location.end = m_location.start; } /// Set the end position to the one of the given node. void setEndPositionFromNode(ASTPointer const& _node) { m_location.end = _node->getLocation().end; } @@ -57,7 +60,7 @@ public: private: Parser const& m_parser; - Location m_location; + SourceLocation m_location; }; ASTPointer Parser::parse(shared_ptr const& _scanner) @@ -299,12 +302,20 @@ ASTPointer Parser::parseEnumDefinition() return nodeFactory.createNode(name, members); } -ASTPointer Parser::parseVariableDeclaration(VarDeclParserOptions const& _options) +ASTPointer Parser::parseVariableDeclaration( + VarDeclParserOptions const& _options, ASTPointer const& _lookAheadArrayType) { - ASTNodeFactory nodeFactory(*this); - ASTPointer type = parseTypeName(_options.allowVar); - if (type != nullptr) - nodeFactory.setEndPositionFromNode(type); + ASTNodeFactory nodeFactory = _lookAheadArrayType ? + ASTNodeFactory(*this, _lookAheadArrayType) : ASTNodeFactory(*this); + ASTPointer type; + if (_lookAheadArrayType) + type = _lookAheadArrayType; + else + { + type = parseTypeName(_options.allowVar); + if (type != nullptr) + nodeFactory.setEndPositionFromNode(type); + } bool isIndexed = false; ASTPointer identifier; Token::Value token = m_scanner->getCurrentToken(); @@ -407,6 +418,7 @@ ASTPointer Parser::parseIdentifier() ASTPointer Parser::parseTypeName(bool _allowVar) { + ASTNodeFactory nodeFactory(*this); ASTPointer type; Token::Value token = m_scanner->getCurrentToken(); if (Token::isElementaryTypeName(token)) @@ -421,9 +433,7 @@ ASTPointer Parser::parseTypeName(bool _allowVar) m_scanner->next(); } else if (token == Token::Mapping) - { type = parseMapping(); - } else if (token == Token::Identifier) { ASTNodeFactory nodeFactory(*this); @@ -432,6 +442,18 @@ ASTPointer Parser::parseTypeName(bool _allowVar) } else BOOST_THROW_EXCEPTION(createParserError("Expected type name")); + + // Parse "[...]" postfixes for arrays. + while (m_scanner->getCurrentToken() == Token::LBrack) + { + m_scanner->next(); + ASTPointer length; + if (m_scanner->getCurrentToken() != Token::RBrack) + length = parseExpression(); + nodeFactory.markEndPosition(); + expectToken(Token::RBrack); + type = nodeFactory.createNode(type, length); + } return type; } @@ -530,7 +552,7 @@ ASTPointer Parser::parseStatement() } // fall-through default: - statement = parseVarDeclOrExprStmt(); + statement = parseSimpleStatement(); } expectToken(Token::Semicolon); return statement; @@ -579,7 +601,7 @@ ASTPointer Parser::parseForStatement() // LTODO: Maybe here have some predicate like peekExpression() instead of checking for semicolon and RParen? if (m_scanner->getCurrentToken() != Token::Semicolon) - initExpression = parseVarDeclOrExprStmt(); + initExpression = parseSimpleStatement(); expectToken(Token::Semicolon); if (m_scanner->getCurrentToken() != Token::Semicolon) @@ -598,48 +620,89 @@ ASTPointer Parser::parseForStatement() body); } -ASTPointer Parser::parseVarDeclOrExprStmt() +ASTPointer Parser::parseSimpleStatement() { - if (peekVariableDeclarationStatement()) + // These two cases are very hard to distinguish: + // x[7 * 20 + 3] a; - x[7 * 20 + 3] = 9; + // In the first case, x is a type name, in the second it is the name of a variable. + switch (peekStatementType()) + { + case LookAheadInfo::VariableDeclarationStatement: return parseVariableDeclarationStatement(); - else + case LookAheadInfo::ExpressionStatement: return parseExpressionStatement(); + default: + break; + } + + // At this point, we have '(Identifier|ElementaryTypeName) "["'. + // We parse '(Identifier|ElementaryTypeName) ( "[" Expression "]" )+' and then decide whether to hand this over + // to ExpressionStatement or create a VariableDeclarationStatement out of it. + ASTPointer primary; + if (m_scanner->getCurrentToken() == Token::Identifier) + primary = parseIdentifier(); + else + { + primary = ASTNodeFactory(*this).createNode(m_scanner->getCurrentToken()); + m_scanner->next(); + } + vector, SourceLocation>> indices; + solAssert(m_scanner->getCurrentToken() == Token::LBrack, ""); + SourceLocation indexLocation = primary->getLocation(); + do + { + expectToken(Token::LBrack); + ASTPointer index; + if (m_scanner->getCurrentToken() != Token::RBrack) + index = parseExpression(); + indexLocation.end = getEndPosition(); + indices.push_back(make_pair(index, indexLocation)); + expectToken(Token::RBrack); + } + while (m_scanner->getCurrentToken() == Token::LBrack); + + if (m_scanner->getCurrentToken() == Token::Identifier) + return parseVariableDeclarationStatement(typeNameIndexAccessStructure(primary, indices)); + else + return parseExpressionStatement(expressionFromIndexAccessStructure(primary, indices)); } -ASTPointer Parser::parseVariableDeclarationStatement() +ASTPointer Parser::parseVariableDeclarationStatement( + ASTPointer const& _lookAheadArrayType) { - ASTNodeFactory nodeFactory(*this); VarDeclParserOptions options; options.allowVar = true; options.allowInitialValue = true; - ASTPointer variable = parseVariableDeclaration(options); + ASTPointer variable = parseVariableDeclaration(options, _lookAheadArrayType); + ASTNodeFactory nodeFactory(*this, variable); return nodeFactory.createNode(variable); } -ASTPointer Parser::parseExpressionStatement() +ASTPointer Parser::parseExpressionStatement( + ASTPointer const& _lookAheadIndexAccessStructure) { - ASTNodeFactory nodeFactory(*this); - ASTPointer expression = parseExpression(); - nodeFactory.setEndPositionFromNode(expression); - return nodeFactory.createNode(expression); + ASTPointer expression = parseExpression(_lookAheadIndexAccessStructure); + return ASTNodeFactory(*this, expression).createNode(expression); } -ASTPointer Parser::parseExpression() +ASTPointer Parser::parseExpression( + ASTPointer const& _lookAheadIndexAccessStructure) { - ASTNodeFactory nodeFactory(*this); - ASTPointer expression = parseBinaryExpression(); + ASTPointer expression = parseBinaryExpression(4, _lookAheadIndexAccessStructure); if (!Token::isAssignmentOp(m_scanner->getCurrentToken())) return expression; Token::Value assignmentOperator = expectAssignmentOperator(); ASTPointer rightHandSide = parseExpression(); + ASTNodeFactory nodeFactory(*this, expression); nodeFactory.setEndPositionFromNode(rightHandSide); return nodeFactory.createNode(expression, assignmentOperator, rightHandSide); } -ASTPointer Parser::parseBinaryExpression(int _minPrecedence) +ASTPointer Parser::parseBinaryExpression(int _minPrecedence, + ASTPointer const& _lookAheadIndexAccessStructure) { - ASTNodeFactory nodeFactory(*this); - ASTPointer expression = parseUnaryExpression(); + ASTPointer expression = parseUnaryExpression(_lookAheadIndexAccessStructure); + ASTNodeFactory nodeFactory(*this, expression); int precedence = Token::precedence(m_scanner->getCurrentToken()); for (; precedence >= _minPrecedence; --precedence) while (Token::precedence(m_scanner->getCurrentToken()) == precedence) @@ -653,11 +716,13 @@ ASTPointer Parser::parseBinaryExpression(int _minPrecedence) return expression; } -ASTPointer Parser::parseUnaryExpression() +ASTPointer Parser::parseUnaryExpression( + ASTPointer const& _lookAheadIndexAccessStructure) { - ASTNodeFactory nodeFactory(*this); + ASTNodeFactory nodeFactory = _lookAheadIndexAccessStructure ? + ASTNodeFactory(*this, _lookAheadIndexAccessStructure) : ASTNodeFactory(*this); Token::Value token = m_scanner->getCurrentToken(); - if (Token::isUnaryOp(token) || Token::isCountOp(token)) + if (!_lookAheadIndexAccessStructure && (Token::isUnaryOp(token) || Token::isCountOp(token))) { // prefix expression m_scanner->next(); @@ -668,7 +733,7 @@ ASTPointer Parser::parseUnaryExpression() else { // potential postfix expression - ASTPointer subExpression = parseLeftHandSideExpression(); + ASTPointer subExpression = parseLeftHandSideExpression(_lookAheadIndexAccessStructure); token = m_scanner->getCurrentToken(); if (!Token::isCountOp(token)) return subExpression; @@ -678,11 +743,16 @@ ASTPointer Parser::parseUnaryExpression() } } -ASTPointer Parser::parseLeftHandSideExpression() +ASTPointer Parser::parseLeftHandSideExpression( + ASTPointer const& _lookAheadIndexAccessStructure) { - ASTNodeFactory nodeFactory(*this); + ASTNodeFactory nodeFactory = _lookAheadIndexAccessStructure ? + ASTNodeFactory(*this, _lookAheadIndexAccessStructure) : ASTNodeFactory(*this); + ASTPointer expression; - if (m_scanner->getCurrentToken() == Token::New) + if (_lookAheadIndexAccessStructure) + expression = _lookAheadIndexAccessStructure; + else if (m_scanner->getCurrentToken() == Token::New) { expectToken(Token::New); ASTPointer contractName(parseIdentifier()); @@ -699,7 +769,9 @@ ASTPointer Parser::parseLeftHandSideExpression() case Token::LBrack: { m_scanner->next(); - ASTPointer index = parseExpression(); + ASTPointer index; + if (m_scanner->getCurrentToken() != Token::RBrack) + index = parseExpression(); nodeFactory.markEndPosition(); expectToken(Token::RBrack); expression = nodeFactory.createNode(expression, index); @@ -774,10 +846,7 @@ ASTPointer Parser::parsePrimaryExpression() m_scanner->next(); } else - { BOOST_THROW_EXCEPTION(createParserError("Expected primary expression.")); - return ASTPointer(); // this is not reached - } break; } return expression; @@ -824,18 +893,55 @@ pair>, vector>> Parser::pars return ret; } +Parser::LookAheadInfo Parser::peekStatementType() const +{ + // Distinguish between variable declaration (and potentially assignment) and expression statement + // (which include assignments to other expressions and pre-declared variables). + // We have a variable declaration if we get a keyword that specifies a type name. + // If it is an identifier or an elementary type name followed by an identifier, we also have + // a variable declaration. + // If we get an identifier followed by a "[", it can be both ("type[9] a;" or "arr[9] = 7;"). + // In all other cases, we have an expression statement. + Token::Value token(m_scanner->getCurrentToken()); + bool mightBeTypeName = (Token::isElementaryTypeName(token) || token == Token::Identifier); + if (token == Token::Mapping || token == Token::Var || + (mightBeTypeName && m_scanner->peekNextToken() == Token::Identifier)) + return LookAheadInfo::VariableDeclarationStatement; + if (mightBeTypeName && m_scanner->peekNextToken() == Token::LBrack) + return LookAheadInfo::IndexAccessStructure; + return LookAheadInfo::ExpressionStatement; +} + +ASTPointer Parser::typeNameIndexAccessStructure( + ASTPointer const& _primary, vector, SourceLocation>> const& _indices) +{ + ASTNodeFactory nodeFactory(*this, _primary); + ASTPointer type; + if (auto identifier = dynamic_cast(_primary.get())) + type = nodeFactory.createNode(make_shared(identifier->getName())); + else if (auto typeName = dynamic_cast(_primary.get())) + type = nodeFactory.createNode(typeName->getTypeToken()); + else + solAssert(false, "Invalid type name for array look-ahead."); + for (auto const& lengthExpression: _indices) + { + nodeFactory.setLocation(lengthExpression.second); + type = nodeFactory.createNode(type, lengthExpression.first); + } + return type; +} -bool Parser::peekVariableDeclarationStatement() +ASTPointer Parser::expressionFromIndexAccessStructure( + ASTPointer const& _primary, vector, SourceLocation>> const& _indices) { - // distinguish between variable declaration (and potentially assignment) and expression statement - // (which include assignments to other expressions and pre-declared variables) - // We have a variable declaration if we get a keyword that specifies a type name, or - // in the case of a user-defined type, we have two identifiers following each other. - return (m_scanner->getCurrentToken() == Token::Mapping || - m_scanner->getCurrentToken() == Token::Var || - ((Token::isElementaryTypeName(m_scanner->getCurrentToken()) || - m_scanner->getCurrentToken() == Token::Identifier) && - m_scanner->peekNextToken() == Token::Identifier)); + ASTNodeFactory nodeFactory(*this, _primary); + ASTPointer expression(_primary); + for (auto const& index: _indices) + { + nodeFactory.setLocation(index.second); + expression = nodeFactory.createNode(expression, index.first); + } + return expression; } void Parser::expectToken(Token::Value _value) @@ -877,7 +983,7 @@ ASTPointer Parser::createEmptyParameterList() ParserError Parser::createParserError(string const& _description) const { - return ParserError() << errinfo_sourceLocation(Location(getPosition(), getPosition(), getSourceName())) + return ParserError() << errinfo_sourceLocation(SourceLocation(getPosition(), getPosition(), getSourceName())) << errinfo_comment(_description); } diff --git a/libsolidity/Parser.h b/libsolidity/Parser.h index 4034aec85..87eb2f8ff 100644 --- a/libsolidity/Parser.h +++ b/libsolidity/Parser.h @@ -64,7 +64,9 @@ private: ASTPointer parseStructDefinition(); ASTPointer parseEnumDefinition(); ASTPointer parseEnumValue(); - ASTPointer parseVariableDeclaration(VarDeclParserOptions const& _options = VarDeclParserOptions()); + ASTPointer parseVariableDeclaration( + VarDeclParserOptions const& _options = VarDeclParserOptions(), + ASTPointer const& _lookAheadArrayType = ASTPointer()); ASTPointer parseModifierDefinition(); ASTPointer parseEventDefinition(); ASTPointer parseModifierInvocation(); @@ -77,13 +79,20 @@ private: ASTPointer parseIfStatement(); ASTPointer parseWhileStatement(); ASTPointer parseForStatement(); - ASTPointer parseVarDeclOrExprStmt(); - ASTPointer parseVariableDeclarationStatement(); - ASTPointer parseExpressionStatement(); - ASTPointer parseExpression(); - ASTPointer parseBinaryExpression(int _minPrecedence = 4); - ASTPointer parseUnaryExpression(); - ASTPointer parseLeftHandSideExpression(); + /// A "simple statement" can be a variable declaration statement or an expression statement. + ASTPointer parseSimpleStatement(); + ASTPointer parseVariableDeclarationStatement( + ASTPointer const& _lookAheadArrayType = ASTPointer()); + ASTPointer parseExpressionStatement( + ASTPointer const& _lookAheadIndexAccessStructure = ASTPointer()); + ASTPointer parseExpression( + ASTPointer const& _lookAheadIndexAccessStructure = ASTPointer()); + ASTPointer parseBinaryExpression(int _minPrecedence = 4, + ASTPointer const& _lookAheadIndexAccessStructure = ASTPointer()); + ASTPointer parseUnaryExpression( + ASTPointer const& _lookAheadIndexAccessStructure = ASTPointer()); + ASTPointer parseLeftHandSideExpression( + ASTPointer const& _lookAheadIndexAccessStructure = ASTPointer()); ASTPointer parsePrimaryExpression(); std::vector> parseFunctionCallListArguments(); std::pair>, std::vector>> parseFunctionCallArguments(); @@ -92,9 +101,24 @@ private: ///@{ ///@name Helper functions - /// Peeks ahead in the scanner to determine if a variable declaration statement is going to follow - bool peekVariableDeclarationStatement(); + /// Used as return value of @see peekStatementType. + enum class LookAheadInfo + { + IndexAccessStructure, VariableDeclarationStatement, ExpressionStatement + }; + /// Performs limited look-ahead to distinguish between variable declaration and expression statement. + /// For source code of the form "a[][8]" ("IndexAccessStructure"), this is not possible to + /// decide with constant look-ahead. + LookAheadInfo peekStatementType() const; + /// Returns a typename parsed in look-ahead fashion from something like "a[8][2**70]". + ASTPointer typeNameIndexAccessStructure( + ASTPointer const& _primary, + std::vector, SourceLocation>> const& _indices); + /// Returns an expression parsed in look-ahead fashion from something like "a[8][2**70]". + ASTPointer expressionFromIndexAccessStructure( + ASTPointer const& _primary, + std::vector, SourceLocation>> const& _indices); /// If current token value is not _value, throw exception otherwise advance token. void expectToken(Token::Value _value); Token::Value expectAssignmentOperator(); diff --git a/libsolidity/Scanner.h b/libsolidity/Scanner.h index d93b79df0..b57b8a189 100644 --- a/libsolidity/Scanner.h +++ b/libsolidity/Scanner.h @@ -55,7 +55,7 @@ #include #include #include -#include +#include #include namespace dev @@ -120,14 +120,14 @@ public: return m_currentToken.token; } - Location getCurrentLocation() const { return m_currentToken.location; } + SourceLocation getCurrentLocation() const { return m_currentToken.location; } std::string const& getCurrentLiteral() const { return m_currentToken.literal; } ///@} ///@{ ///@name Information about the current comment token - Location getCurrentCommentLocation() const { return m_skippedComment.location; } + SourceLocation getCurrentCommentLocation() const { return m_skippedComment.location; } std::string const& getCurrentCommentLiteral() const { return m_skippedComment.literal; } /// Called by the parser during FunctionDefinition parsing to clear the current comment void clearCurrentCommentLiteral() { m_skippedComment.literal.clear(); } @@ -139,7 +139,7 @@ public: /// Returns the next token without advancing input. Token::Value peekNextToken() const { return m_nextToken.token; } - Location peekLocation() const { return m_nextToken.location; } + SourceLocation peekLocation() const { return m_nextToken.location; } std::string const& peekLiteral() const { return m_nextToken.literal; } ///@} @@ -158,7 +158,7 @@ private: struct TokenDesc { Token::Value token; - Location location; + SourceLocation location; std::string literal; }; diff --git a/libsolidity/SourceReferenceFormatter.cpp b/libsolidity/SourceReferenceFormatter.cpp index c61f9b685..489a676ed 100644 --- a/libsolidity/SourceReferenceFormatter.cpp +++ b/libsolidity/SourceReferenceFormatter.cpp @@ -33,7 +33,7 @@ namespace solidity { void SourceReferenceFormatter::printSourceLocation(ostream& _stream, - Location const& _location, + SourceLocation const& _location, Scanner const& _scanner) { int startLine; @@ -63,7 +63,7 @@ void SourceReferenceFormatter::printExceptionInformation(ostream& _stream, string const& _name, CompilerStack const& _compiler) { - Location const* location = boost::get_error_info(_exception); + SourceLocation const* location = boost::get_error_info(_exception); Scanner const* scanner; if (location) diff --git a/libsolidity/SourceReferenceFormatter.h b/libsolidity/SourceReferenceFormatter.h index 98f1c745d..304e6a273 100644 --- a/libsolidity/SourceReferenceFormatter.h +++ b/libsolidity/SourceReferenceFormatter.h @@ -23,7 +23,7 @@ #pragma once #include -#include +#include namespace dev { @@ -39,7 +39,7 @@ class CompilerStack; // forward struct SourceReferenceFormatter { public: - static void printSourceLocation(std::ostream& _stream, Location const& _location, Scanner const& _scanner); + static void printSourceLocation(std::ostream& _stream, SourceLocation const& _location, Scanner const& _scanner); static void printExceptionInformation(std::ostream& _stream, Exception const& _exception, std::string const& _name, CompilerStack const& _compiler); }; diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index ce51336df..adcd2e542 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -58,7 +58,7 @@ TypePointer Type::fromElementaryTypeName(Token::Value _typeToken) else if (Token::String0 <= _typeToken && _typeToken <= Token::String32) return make_shared(int(_typeToken) - int(Token::String0)); else if (_typeToken == Token::Bytes) - return make_shared(ByteArrayType::Location::Storage); + return make_shared(ArrayType::Location::Storage); else BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unable to convert elementary typename " + std::string(Token::toString(_typeToken)) + " to type.")); @@ -83,17 +83,35 @@ TypePointer Type::fromUserDefinedTypeName(UserDefinedTypeName const& _typeName) return TypePointer(); } -TypePointer Type::fromMapping(Mapping const& _typeName) +TypePointer Type::fromMapping(ElementaryTypeName& _keyType, TypeName& _valueType) { - TypePointer keyType = _typeName.getKeyType().toType(); + TypePointer keyType = _keyType.toType(); if (!keyType) BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Error resolving type name.")); - TypePointer valueType = _typeName.getValueType().toType(); + TypePointer valueType = _valueType.toType(); if (!valueType) - BOOST_THROW_EXCEPTION(_typeName.getValueType().createTypeError("Invalid type name")); + BOOST_THROW_EXCEPTION(_valueType.createTypeError("Invalid type name.")); return make_shared(keyType, valueType); } +TypePointer Type::fromArrayTypeName(TypeName& _baseTypeName, Expression* _length) +{ + TypePointer baseType = _baseTypeName.toType(); + if (!baseType) + BOOST_THROW_EXCEPTION(_baseTypeName.createTypeError("Invalid type name.")); + if (_length) + { + if (!_length->getType()) + _length->checkTypeRequirements(); + auto const* length = dynamic_cast(_length->getType().get()); + if (!length) + BOOST_THROW_EXCEPTION(_length->createTypeError("Invalid array length.")); + return make_shared(ArrayType::Location::Storage, baseType, length->literalValue(nullptr)); + } + else + return make_shared(ArrayType::Location::Storage, baseType); +} + TypePointer Type::forLiteral(Literal const& _literal) { switch (_literal.getToken()) @@ -517,27 +535,40 @@ TypePointer ContractType::unaryOperatorResult(Token::Value _operator) const return _operator == Token::Delete ? make_shared() : TypePointer(); } -bool ByteArrayType::isImplicitlyConvertibleTo(const Type& _convertTo) const +bool ArrayType::isImplicitlyConvertibleTo(const Type& _convertTo) const { return _convertTo.getCategory() == getCategory(); } -TypePointer ByteArrayType::unaryOperatorResult(Token::Value _operator) const +TypePointer ArrayType::unaryOperatorResult(Token::Value _operator) const { if (_operator == Token::Delete) return make_shared(); return TypePointer(); } -bool ByteArrayType::operator==(Type const& _other) const +bool ArrayType::operator==(Type const& _other) const { if (_other.getCategory() != getCategory()) return false; - ByteArrayType const& other = dynamic_cast(_other); + ArrayType const& other = dynamic_cast(_other); return other.m_location == m_location; } -unsigned ByteArrayType::getSizeOnStack() const +u256 ArrayType::getStorageSize() const +{ + if (isDynamicallySized()) + return 1; + else + { + bigint size = bigint(getLength()) * getBaseType()->getStorageSize(); + if (size >= bigint(1) << 256) + BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Array too large for storage.")); + return max(1, u256(size)); + } +} + +unsigned ArrayType::getSizeOnStack() const { if (m_location == Location::CallData) // offset, length (stack top) @@ -547,12 +578,30 @@ unsigned ByteArrayType::getSizeOnStack() const return 1; } -shared_ptr ByteArrayType::copyForLocation(ByteArrayType::Location _location) const +string ArrayType::toString() const { - return make_shared(_location); + if (isByteArray()) + return "bytes"; + string ret = getBaseType()->toString() + "["; + if (!isDynamicallySized()) + ret += getLength().str(); + return ret + "]"; +} + +shared_ptr ArrayType::copyForLocation(ArrayType::Location _location) const +{ + auto copy = make_shared(_location); + copy->m_isByteArray = m_isByteArray; + if (m_baseType->getCategory() == Type::Category::Array) + copy->m_baseType = dynamic_cast(*m_baseType).copyForLocation(_location); + else + copy->m_baseType = m_baseType; + copy->m_hasDynamicLength = m_hasDynamicLength; + copy->m_length = m_length; + return copy; } -const MemberList ByteArrayType::s_byteArrayMemberList = MemberList({{"length", make_shared(256)}}); +const MemberList ArrayType::s_arrayTypeMemberList = MemberList({{"length", make_shared(256)}}); bool ContractType::operator==(Type const& _other) const { @@ -629,10 +678,12 @@ bool StructType::operator==(Type const& _other) const u256 StructType::getStorageSize() const { - u256 size = 0; + bigint size = 0; for (pair const& member: getMembers()) size += member.second->getStorageSize(); - return max(1, size); + if (size >= bigint(1) << 256) + BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Struct too large for storage.")); + return max(1, u256(size)); } bool StructType::canLiveOutsideStorage() const @@ -1040,7 +1091,7 @@ MagicType::MagicType(MagicType::Kind _kind): m_members = MemberList({{"sender", make_shared(0, IntegerType::Modifier::Address)}, {"gas", make_shared(256)}, {"value", make_shared(256)}, - {"data", make_shared(ByteArrayType::Location::CallData)}}); + {"data", make_shared(ArrayType::Location::CallData)}}); break; case Kind::Transaction: m_members = MemberList({{"origin", make_shared(0, IntegerType::Modifier::Address)}, diff --git a/libsolidity/Types.h b/libsolidity/Types.h index af64f1cb5..9961f03a3 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -36,8 +36,6 @@ namespace dev namespace solidity { -// @todo realMxN, dynamic strings, text, arrays - class Type; // forward class FunctionType; // forward using TypePointer = std::shared_ptr; @@ -78,7 +76,7 @@ class Type: private boost::noncopyable, public std::enable_shared_from_this[]) + * and dynamically-sized array ([]). */ -class ByteArrayType: public Type +class ArrayType: public Type { public: enum class Location { Storage, CallData, Memory }; - virtual Category getCategory() const override { return Category::ByteArray; } - explicit ByteArrayType(Location _location): m_location(_location) {} + virtual Category getCategory() const override { return Category::Array; } + + /// Constructor for a byte array ("bytes") + explicit ArrayType(Location _location): + m_location(_location), m_isByteArray(true), m_baseType(std::make_shared(8)) {} + /// Constructor for a dynamically sized array type ("type[]") + ArrayType(Location _location, const TypePointer &_baseType): + m_location(_location), m_baseType(_baseType) {} + /// Constructor for a fixed-size array type ("type[20]") + ArrayType(Location _location, const TypePointer &_baseType, u256 const& _length): + m_location(_location), m_baseType(_baseType), m_hasDynamicLength(false), m_length(_length) {} + virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; virtual bool operator==(const Type& _other) const override; - virtual bool isDynamicallySized() const { return true; } + virtual bool isDynamicallySized() const { return m_hasDynamicLength; } + virtual u256 getStorageSize() const override; virtual unsigned getSizeOnStack() const override; - virtual std::string toString() const override { return "bytes"; } - virtual MemberList const& getMembers() const override { return s_byteArrayMemberList; } + virtual std::string toString() const override; + virtual MemberList const& getMembers() const override { return s_arrayTypeMemberList; } Location getLocation() const { return m_location; } + bool isByteArray() const { return m_isByteArray; } + TypePointer const& getBaseType() const { solAssert(!!m_baseType, ""); return m_baseType;} + u256 const& getLength() const { return m_length; } /// @returns a copy of this type with location changed to @a _location /// @todo this might move as far up as Type later - std::shared_ptr copyForLocation(Location _location) const; + std::shared_ptr copyForLocation(Location _location) const; private: Location m_location; - static const MemberList s_byteArrayMemberList; + bool m_isByteArray = false; ///< Byte arrays ("bytes") have different semantics from ordinary arrays. + TypePointer m_baseType; + bool m_hasDynamicLength = true; + u256 m_length; + static const MemberList s_arrayTypeMemberList; }; /** diff --git a/libsolidity/grammar.txt b/libsolidity/grammar.txt index a3b246873..6503516c6 100644 --- a/libsolidity/grammar.txt +++ b/libsolidity/grammar.txt @@ -18,8 +18,9 @@ ParameterList = '(' ( VariableDeclaration (',' VariableDeclaration)* )? ')' // semantic restriction: mappings and structs (recursively) containing mappings // are not allowed in argument lists VariableDeclaration = TypeName Identifier -TypeName = ElementaryTypeName | Identifier | Mapping +TypeName = ElementaryTypeName | Identifier | Mapping | ArrayTypeName Mapping = 'mapping' '(' ElementaryTypeName '=>' TypeName ')' +ArrayTypeName = TypeName '[' (Expression)? ']' Block = '{' Statement* '}' Statement = IfStatement | WhileStatement | Block | @@ -42,5 +43,5 @@ Assignment = Expression (AssignmentOp Expression) FunctionCall = Expression '(' Expression ( ',' Expression )* ')' NewExpression = 'new' Identifier MemberAccess = Expression '.' Identifier -IndexAccess = Expression '[' Expresison ']' +IndexAccess = Expression '[' (Expresison)? ']' PrimaryExpression = Identifier | NumberLiteral | StringLiteral | ElementaryTypeName | '(' Expression ')' diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index 6ab701899..dbf3b2ec9 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -701,10 +701,10 @@ std::string WebThreeStubServerBase::eth_transact(Json::Value const& _json) { std::string ret; TransactionSkeleton t = toTransaction(_json); - if (t.creation) - ret = right160(sha3(rlpList(t.from, client()->countAt(t.from))));; if (!t.from) t.from = m_accounts->getDefaultTransactAccount(); + if (t.creation) + ret = toJS(right160(sha3(rlpList(t.from, client()->countAt(t.from)))));; if (!t.gasPrice) t.gasPrice = 10 * dev::eth::szabo; if (!t.gas) diff --git a/libwhisper/Common.cpp b/libwhisper/Common.cpp index f17ad638b..c29ac6bf6 100644 --- a/libwhisper/Common.cpp +++ b/libwhisper/Common.cpp @@ -71,7 +71,7 @@ bool TopicFilter::matches(Envelope const& _e) const for (unsigned i = 0; i < t.size(); ++i) { for (auto et: _e.topic()) - if (((t[i].first ^ et) & t[i].second) == 0) + if (((t[i].first ^ et) & t[i].second) == CollapsedTopicPart()) goto NEXT_TOPICPART; // failed to match topicmask against any topics: move on to next mask goto NEXT_TOPICMASK; diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 45198c114..110bdc141 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -370,7 +370,7 @@ void ClientModel::onNewTransaction() QString function; QString returned; - bool creation = tr.contractAddress != 0; + bool creation = (bool)tr.contractAddress; //TODO: handle value transfer FixedHash<4> functionHash; @@ -403,7 +403,7 @@ void ClientModel::onNewTransaction() if (creation) returned = QString::fromStdString(toJS(tr.contractAddress)); - Address contractAddress = tr.address != 0 ? tr.address : tr.contractAddress; + Address contractAddress = (bool)tr.address ? tr.address : tr.contractAddress; auto contractAddressIter = m_contractNames.find(contractAddress); if (contractAddressIter != m_contractNames.end()) { diff --git a/mix/CodeHighlighter.cpp b/mix/CodeHighlighter.cpp index 86dfe9e5d..5a7b1f4d5 100644 --- a/mix/CodeHighlighter.cpp +++ b/mix/CodeHighlighter.cpp @@ -64,7 +64,7 @@ namespace }; } -CodeHighlighter::FormatRange::FormatRange(CodeHighlighterSettings::Token _t, dev::solidity::Location const& _location): +CodeHighlighter::FormatRange::FormatRange(CodeHighlighterSettings::Token _t, dev::SourceLocation const& _location): token(_t), start(_location.start), length(_location.end - _location.start) {} @@ -101,7 +101,7 @@ void CodeHighlighter::processAST(dev::solidity::ASTNode const& _ast) void CodeHighlighter::processError(dev::Exception const& _exception) { - Location const* location = boost::get_error_info(_exception); + SourceLocation const* location = boost::get_error_info(_exception); if (location) m_formats.push_back(FormatRange(CodeHighlighterSettings::CompilationError, *location)); } diff --git a/mix/CodeHighlighter.h b/mix/CodeHighlighter.h index 3bdff5647..7fce7ed95 100644 --- a/mix/CodeHighlighter.h +++ b/mix/CodeHighlighter.h @@ -32,11 +32,10 @@ namespace dev { struct Exception; - +struct SourceLocation; namespace solidity { class ASTNode; - struct Location; } namespace mix @@ -74,7 +73,7 @@ public: struct FormatRange { FormatRange(CodeHighlighterSettings::Token _t, int _start, int _length): token(_t), start(_start), length(_length) {} - FormatRange(CodeHighlighterSettings::Token _t, solidity::Location const& _location); + FormatRange(CodeHighlighterSettings::Token _t, SourceLocation const& _location); bool operator<(FormatRange const& _other) const { return start < _other.start || (start == _other.start && length < _other.length); } CodeHighlighterSettings::Token token; diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index 7a38594ce..6978cc936 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -212,7 +213,7 @@ void CodeModel::runCompilationJob(int _jobId) { std::ostringstream error; solidity::SourceReferenceFormatter::printExceptionInformation(error, _exception, "Error", cs); - solidity::Location const* location = boost::get_error_info(_exception); + SourceLocation const* location = boost::get_error_info(_exception); QString message = QString::fromStdString(error.str()); CompiledContract* contract = nullptr; if (location && location->sourceName.get() && (contract = contractByDocumentId(QString::fromStdString(*location->sourceName)))) diff --git a/mix/FileIo.cpp b/mix/FileIo.cpp index 818d8c887..78eb6c9da 100644 --- a/mix/FileIo.cpp +++ b/mix/FileIo.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of cpp-ethereum. - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . */ /** @file FileIo.cpp * @author Arkadiy Paronyan arkadiy@ethdev.com @@ -20,30 +20,51 @@ * Ethereum IDE client. */ +#include #include #include #include #include #include +#include +#include +#include +#include +#include #include "FileIo.h" +using namespace dev; +using namespace dev::crypto; using namespace dev::mix; -void FileIo::makeDir(QString const& _url) +QString FileIo::pathFromUrl(QString const& _url) { QUrl url(_url); - QDir dirPath(url.path()); + QString path(url.path()); + if (url.scheme() == "qrc") + path = ":" + path; +#ifdef WIN32 + if (url.scheme() == "file") + { + if (path.startsWith("/")) + path = path.right(path.length() - 1); + if (!url.host().isEmpty()) + path = url.host() + ":/" + path; + } +#endif + return path; +} + +void FileIo::makeDir(QString const& _url) +{ + QDir dirPath(pathFromUrl(_url)); if (!dirPath.exists()) dirPath.mkpath(dirPath.path()); } QString FileIo::readFile(QString const& _url) { - QUrl url(_url); - QString path(url.path()); - if (url.scheme() == "qrc") - path = ":" + path; - QFile file(path); + QFile file(pathFromUrl(_url)); if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { QTextStream stream(&file); @@ -57,8 +78,7 @@ QString FileIo::readFile(QString const& _url) void FileIo::writeFile(QString const& _url, QString const& _data) { - QUrl url(_url); - QFile file(url.path()); + QFile file(pathFromUrl(_url)); if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream stream(&file); @@ -76,9 +96,7 @@ void FileIo::copyFile(QString const& _sourceUrl, QString const& _destUrl) return; } - QUrl sourceUrl(_sourceUrl); - QUrl destUrl(_destUrl); - if (!QFile::copy(sourceUrl.path(), destUrl.path())) + if (!QFile::copy(pathFromUrl(_sourceUrl), pathFromUrl(_destUrl))) error(tr("Error copying file %1 to %2").arg(_sourceUrl).arg(_destUrl)); } @@ -89,15 +107,77 @@ QString FileIo::getHomePath() const void FileIo::moveFile(QString const& _sourceUrl, QString const& _destUrl) { - QUrl sourceUrl(_sourceUrl); - QUrl destUrl(_destUrl); - if (!QFile::rename(sourceUrl.path(), destUrl.path())) + if (!QFile::rename(pathFromUrl(_sourceUrl), pathFromUrl(_destUrl))) error(tr("Error moving file %1 to %2").arg(_sourceUrl).arg(_destUrl)); } bool FileIo::fileExists(QString const& _url) { - QUrl url(_url); - QFile file(url.path()); + QFile file(pathFromUrl(_url)); return file.exists(); } + +QStringList FileIo::makePackage(QString const& _deploymentFolder) +{ + Json::Value manifest; + Json::Value entries(Json::arrayValue); + + QDir deployDir = QDir(pathFromUrl(_deploymentFolder)); + dev::RLPStream rlpStr; + int k = 1; + std::vector files; + for (auto item: deployDir.entryInfoList(QDir::Files)) + { + QFile qFile(item.filePath()); + if (qFile.open(QIODevice::ReadOnly)) + { + k++; + QFileInfo fileInfo = QFileInfo(qFile.fileName()); + Json::Value jsonValue; + std::string path = fileInfo.fileName() == "index.html" ? "/" : fileInfo.fileName().toStdString(); + jsonValue["path"] = path; //TODO: Manage relative sub folder + jsonValue["file"] = "/" + fileInfo.fileName().toStdString(); + jsonValue["contentType"] = "text/html"; //TODO: manage multiple content type + QByteArray a = qFile.readAll(); + bytes data = bytes(a.begin(), a.end()); + files.push_back(data); + jsonValue["hash"] = toHex(dev::sha3(data).ref()); + entries.append(jsonValue); + } + qFile.close(); + } + rlpStr.appendList(k); + + std::stringstream jsonStr; + jsonStr << manifest; + QByteArray b = QString::fromStdString(jsonStr.str()).toUtf8(); + rlpStr.append(bytesConstRef((const unsigned char*)b.data(), b.size())); + + for (unsigned int k = 0; k < files.size(); k++) + rlpStr.append(files.at(k)); + + manifest["entries"] = entries; + bytes dapp = rlpStr.out(); + dev::h256 dappHash = dev::sha3(dapp); + //encrypt + KeyPair key(dappHash); + Secp256k1 enc; + enc.encrypt(key.pub(), dapp); + + QUrl url(_deploymentFolder + "package.dapp"); + QFile compressed(url.path()); + QByteArray qFileBytes((char*)dapp.data(), dapp.size()); + if (compressed.open(QIODevice::WriteOnly)) + { + compressed.write(qFileBytes); + compressed.flush(); + } + else + error(tr("Error creating package.dapp")); + compressed.close(); + QStringList ret; + ret.append(QString::fromStdString(toHex(dappHash.ref()))); + ret.append(qFileBytes.toBase64()); + return ret; +} + diff --git a/mix/FileIo.h b/mix/FileIo.h index 08d49e099..624b1d921 100644 --- a/mix/FileIo.h +++ b/mix/FileIo.h @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of cpp-ethereum. - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . */ /** @file FileIo.h * @author Arkadiy Paronyan arkadiy@ethdev.com @@ -22,6 +22,7 @@ #pragma once +#include #include namespace dev @@ -52,9 +53,12 @@ public: Q_INVOKABLE void moveFile(QString const& _sourceUrl, QString const& _destUrl); /// Check if file exists Q_INVOKABLE bool fileExists(QString const& _url); + /// Compress a folder, @returns sha3 of the compressed file. + Q_INVOKABLE QStringList makePackage(QString const& _deploymentFolder); private: QString getHomePath() const; + QString pathFromUrl(QString const& _url); }; } diff --git a/mix/MixApplication.cpp b/mix/MixApplication.cpp index deff7c011..821167a3f 100644 --- a/mix/MixApplication.cpp +++ b/mix/MixApplication.cpp @@ -33,7 +33,7 @@ using namespace dev::mix; -MixApplication::MixApplication(int _argc, char* _argv[]): +MixApplication::MixApplication(int& _argc, char* _argv[]): QApplication(_argc, _argv), m_engine(new QQmlApplicationEngine()), m_appContext(new AppContext(m_engine.get())) { setOrganizationName(tr("Ethereum")); diff --git a/mix/MixApplication.h b/mix/MixApplication.h index 86c1126fc..acfe4e547 100644 --- a/mix/MixApplication.h +++ b/mix/MixApplication.h @@ -40,7 +40,7 @@ class MixApplication: public QApplication Q_OBJECT public: - MixApplication(int _argc, char* _argv[]); + MixApplication(int& _argc, char* _argv[]); virtual ~MixApplication(); AppContext* context() { return m_appContext.get(); } QQmlApplicationEngine* engine() { return m_engine.get(); } diff --git a/mix/QVariableDefinition.h b/mix/QVariableDefinition.h index 1825c2567..8d890539b 100644 --- a/mix/QVariableDefinition.h +++ b/mix/QVariableDefinition.h @@ -53,6 +53,8 @@ public: virtual bytes encodeValue() = 0; /// Decode the return value @a _rawValue. virtual void decodeValue(dev::bytes const& _rawValue) = 0; + /// returns String representation of the encoded value. + Q_INVOKABLE QString encodeValueAsString() { return QString::fromStdString(dev::toHex(encodeValue())); } protected: QString m_value; diff --git a/mix/qml/DeploymentDialog.qml b/mix/qml/DeploymentDialog.qml new file mode 100644 index 000000000..5033d02b8 --- /dev/null +++ b/mix/qml/DeploymentDialog.qml @@ -0,0 +1,232 @@ +import QtQuick 2.2 +import QtQuick.Controls 1.1 +import QtQuick.Layouts 1.1 +import QtQuick.Window 2.0 +import QtQuick.Dialogs 1.1 +import QtQuick.Controls.Styles 1.3 +import org.ethereum.qml.QEther 1.0 +import "js/TransactionHelper.js" as TransactionHelper +import "js/ProjectModel.js" as ProjectModelCode +import "js/QEtherHelper.js" as QEtherHelper +import "." + + +Window { + id: modalDeploymentDialog + modality: Qt.ApplicationModal + width: 600 + height: 350 + visible: false + property alias applicationUrlEth: applicationUrlEth.text + property alias applicationUrlHttp: applicationUrlHttp.text + property string urlHintContract: "c83d3e22645fb015d02043a744921cc2f828c64d" + property string packageHash + property alias packageBase64: base64Value.text + property string eth: "afb7cdbd076674fd2c67f8a66518e3145b184ae4"; + property string wallet: "c83d3e22645fb015d02043a744921cc2f828c64d"; + + color: Style.generic.layout.backgroundColor + + function close() + { + visible = false; + } + + function open() + { + modalDeploymentDialog.setX((Screen.width - width) / 2); + modalDeploymentDialog.setY((Screen.height - height) / 2); + visible = true; + } + + function pad(h) + { + // TODO move this to QHashType class + while (h.length < 64) + { + h = '0' + h; + } + return h; + } + + Rectangle + { + anchors.fill : parent + anchors.margins: 10 + color: Style.generic.layout.backgroundColor + GridLayout + { + columns: 2 + anchors.top: parent.top + anchors.left: parent.left + width: parent.width + DefaultLabel + { + text: qsTr("Ethereum Application URL: ") + } + + DefaultTextField + { + Layout.fillWidth: true + id: applicationUrlEth + } + + DefaultLabel + { + text: qsTr("Web Application Ressources URL: ") + } + + DefaultTextField + { + Layout.fillWidth: true + id: applicationUrlHttp + } + + DefaultLabel + { + text: qsTr("Package (Base64): ") + } + + TextArea + { + Layout.fillWidth: true + readOnly: true + id: base64Value + height: 60 + enabled: base64Value.text != "" + } + } + + MessageDialog { + id: deployDialog + standardButtons: StandardButton.Ok + icon: StandardIcon.Warning + } + + RowLayout + { + anchors.bottom: parent.bottom + anchors.right: parent.right; + anchors.bottomMargin: 10 + Button { + text: qsTr("Deploy to Ethereum"); + tooltip: qsTr("Deploy contract and package resources files.") + onClicked: { + deployWarningDialog.open(); + } + } + + Button { + text: qsTr("Register Web Application"); + tooltip: qsTr("Register hosted Web Application.") + onClicked: { + if (applicationUrlHttp.text === "" || deploymentDialog.packageHash === "") + { + deployDialog.title = text; + deployDialog.text = qsTr("Please provide the link where the resources are stored and ensure the package is aleary built using the deployment step. ") + deployDialog.open(); + } + else + ProjectModelCode.registerToUrlHint(); + } + } + + Button { + text: qsTr("Close"); + onClicked: close(); + } + + Button { + text: qsTr("Check Ownership"); + visible : false + onClicked: { + var requests = []; + var ethStr = QEtherHelper.createString("wallet"); + + var ethHash = QEtherHelper.createHash(eth); + + requests.push({ //owner + jsonrpc: "2.0", + method: "eth_call", + params: [ { "to": '0x' + modalDeploymentDialog.eth, "data": "0xec7b9200" + ethStr.encodeValueAsString() } ], + id: 3 + }); + + requests.push({ //register + jsonrpc: "2.0", + method: "eth_call", + params: [ { "to": '0x' + modalDeploymentDialog.eth, "data": "0x6be16bed" + ethStr.encodeValueAsString() } ], + id: 4 + }); + + var jsonRpcUrl = "http://localhost:8080"; + var rpcRequest = JSON.stringify(requests); + var httpRequest = new XMLHttpRequest(); + httpRequest.open("POST", jsonRpcUrl, true); + httpRequest.setRequestHeader("Content-type", "application/json"); + httpRequest.setRequestHeader("Content-length", rpcRequest.length); + httpRequest.setRequestHeader("Connection", "close"); + httpRequest.onreadystatechange = function() { + if (httpRequest.readyState === XMLHttpRequest.DONE) { + if (httpRequest.status === 200) { + console.log(httpRequest.responseText); + } else { + var errorText = qsTr("path registration failed ") + httpRequest.status; + console.log(errorText); + } + } + } + httpRequest.send(rpcRequest); + } + } + + + Button { + text: qsTr("Generate registrar init"); + visible: false + onClicked: { + console.log("registering eth/wallet") + var jsonRpcRequestId = 0; + + var requests = []; + + var walletStr = QEtherHelper.createString("wallet"); + + requests.push({ //reserve + jsonrpc: "2.0", + method: "eth_transact", + params: [ { "to": '0x' + modalDeploymentDialog.eth, "data": "0x1c83171b" + walletStr.encodeValueAsString() } ], + id: jsonRpcRequestId++ + }); + + + requests.push({ //setRegister + jsonrpc: "2.0", + method: "eth_transact", + params: [ { "to": '0x' + modalDeploymentDialog.eth, "data": "0x96077307" + walletStr.encodeValueAsString() + pad(wallet) } ], + id: jsonRpcRequestId++ + }); + + var jsonRpcUrl = "http://localhost:8080"; + var rpcRequest = JSON.stringify(requests); + var httpRequest = new XMLHttpRequest(); + httpRequest.open("POST", jsonRpcUrl, true); + httpRequest.setRequestHeader("Content-type", "application/json"); + httpRequest.setRequestHeader("Content-length", rpcRequest.length); + httpRequest.setRequestHeader("Connection", "close"); + httpRequest.onreadystatechange = function() { + if (httpRequest.readyState === XMLHttpRequest.DONE) { + if (httpRequest.status === 200) { + console.log(httpRequest.responseText); + } else { + var errorText = qsTr("path registration failed ") + httpRequest.status; + console.log(errorText); + } + } + } + httpRequest.send(rpcRequest); + } + } + } + } +} diff --git a/mix/qml/NewProjectDialog.qml b/mix/qml/NewProjectDialog.qml index 4fcb524b2..1ec53e1d9 100644 --- a/mix/qml/NewProjectDialog.qml +++ b/mix/qml/NewProjectDialog.qml @@ -101,6 +101,8 @@ Window { var u = createProjectFileDialog.fileUrl.toString(); if (u.indexOf("file://") == 0) u = u.substring(7, u.length) + if (Qt.platform.os == "windows" && u.indexOf("/") == 0) + u = u.substring(1, u.length); pathField.text = u; } } diff --git a/mix/qml/ProjectModel.qml b/mix/qml/ProjectModel.qml index 97dec227c..19008be5e 100644 --- a/mix/qml/ProjectModel.qml +++ b/mix/qml/ProjectModel.qml @@ -21,6 +21,7 @@ Item { signal newProject(var projectData) signal documentSaved(var documentId) signal deploymentStarted() + signal deploymentStepChanged(string message) signal deploymentComplete() signal deploymentError(string error) @@ -31,7 +32,7 @@ Item { property string projectPath: "" property string projectTitle: "" property string currentDocumentId: "" - property string deploymentAddress: "" + property var deploymentAddresses: [] property var listModel: projectListModel property var stateListModel: projectStateListModel.model property CodeEditorView codeEditor: null @@ -55,6 +56,7 @@ Item { function getDocumentIndex(documentId) { return ProjectModelCode.getDocumentIndex(documentId); } function addExistingFiles(paths) { ProjectModelCode.doAddExistingFiles(paths); } function deployProject() { ProjectModelCode.deployProject(false); } + function registerToUrlHint() { ProjectModelCode.registerToUrlHint(); } Connections { target: appContext @@ -91,15 +93,44 @@ Item { MessageDialog { id: deployWarningDialog + property bool redeploy title: qsTr("Project") - text: qsTr("This project has been already deployed to the network. Do you want to re-deploy it?") - standardButtons: StandardButton.Ok | StandardButton.Cancel + text: + { + if (Object.keys(projectModel.deploymentAddresses).length > 0) + { + redeploy = true + standardButtons = StandardButton.Ok | StandardButton.Reset | StandardButton.Abort; + return qsTr("This project has been already deployed to the network. Do you want to repackage the resources only, or also reset the deployed contract to its initial state?") + } + else + { + redeploy = false; + standardButtons = StandardButton.Ok | StandardButton.Abort; + return qsTr("This action will deploy to the network. Do you want to deploy it?") + } + } icon: StandardIcon.Question onAccepted: { - ProjectModelCode.deployProject(true); + ProjectModelCode.startDeployProject(!redeploy); + } + onReset: { + ProjectModelCode.startDeployProject(true); } } + MessageDialog { + id: deployRessourcesDialog + title: qsTr("Project") + standardButtons: StandardButton.Ok + icon: StandardIcon.Info + } + + DeploymentDialog + { + id: deploymentDialog + } + ListModel { id: projectListModel } diff --git a/mix/qml/StatusPane.qml b/mix/qml/StatusPane.qml index 6a8a0093d..1f226279d 100644 --- a/mix/qml/StatusPane.qml +++ b/mix/qml/StatusPane.qml @@ -47,6 +47,7 @@ Rectangle { onDeploymentStarted: infoMessage(qsTr("Running deployment...")); onDeploymentError: infoMessage(error); onDeploymentComplete: infoMessage(qsTr("Deployment complete")); + onDeploymentStepChanged: infoMessage(message); } Connections { target: codeModel diff --git a/mix/qml/Style.qml b/mix/qml/Style.qml index 9e4b6f268..c317177a3 100644 --- a/mix/qml/Style.qml +++ b/mix/qml/Style.qml @@ -11,6 +11,7 @@ QtObject { property QtObject generic: QtObject { property QtObject layout: QtObject { property string separatorColor: "#808080" + property string backgroundColor: "#ededed" } property QtObject size: QtObject { property string titlePointSize: absoluteSize(0) diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index e5a8bc746..434f8a850 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -405,7 +405,7 @@ Window { return boolViewComp; else if (type.indexOf("string") !== -1) return stringViewComp; - else if (type.indexOf("hash") !== -1) + else if (type.indexOf("hash") !== -1 || type.indexOf("address") !== -1) return hashViewComp; else return null; diff --git a/mix/qml/js/ProjectModel.js b/mix/qml/js/ProjectModel.js index 9ca9bae39..d60dc4124 100644 --- a/mix/qml/js/ProjectModel.js +++ b/mix/qml/js/ProjectModel.js @@ -19,6 +19,7 @@ * @date 2015 * Ethereum IDE client. */ +Qt.include("QEtherHelper.js") var htmlTemplate = "\n\n\n\n\n\n\n"; var contractTemplate = "contract Contract {\n}\n"; @@ -45,7 +46,11 @@ function saveProject() { var projectData = { files: [], title: projectTitle, - deploymentAddress: deploymentAddress + deploymentAddresses: deploymentAddresses, + applicationUrlEth: deploymentDialog.applicationUrlEth, + applicationUrlHttp: deploymentDialog.applicationUrlHttp, + packageHash: deploymentDialog.packageHash, + packageBase64: deploymentDialog.packageBase64 }; for (var i = 0; i < projectListModel.count; i++) projectData.files.push(projectListModel.get(i).fileName) @@ -63,11 +68,19 @@ function loadProject(path) { var projectFile = path + projectFileName; var json = fileIo.readFile(projectFile); var projectData = JSON.parse(json); + if (projectData.packageHash) + deploymentDialog.packageHash = projectData.packageHash + if (projectData.packageBase64) + deploymentDialog.packageBase64 = projectData.packageBase64 + if (projectData.applicationUrlEth) + deploymentDialog.applicationUrlEth = projectData.applicationUrlEth + if (projectData.applicationUrlHttp) + deploymentDialog.applicationUrlHttp = projectData.applicationUrlHttp if (!projectData.title) { var parts = path.split("/"); projectData.title = parts[parts.length - 2]; } - deploymentAddress = projectData.deploymentAddress ? projectData.deploymentAddress : ""; + deploymentAddresses = projectData.deploymentAddresses ? projectData.deploymentAddresses : []; projectTitle = projectData.title; projectPath = path; if (!projectData.files) @@ -272,22 +285,27 @@ function generateFileName(name, extension) { var jsonRpcRequestId = 1; function deployProject(force) { - saveAll(); //TODO: ask user + deploymentDialog.open(); +} - if (!force && deploymentAddress !== "") { - deployWarningDialog.visible = true; +function startDeployProject(erasePrevious) +{ + var date = new Date(); + var deploymentId = date.toLocaleString(Qt.locale(), "ddMMyyHHmmsszzz"); + if (!erasePrevious) + { + finalizeDeployment(deploymentId, projectModel.deploymentAddresses); return; } - var date = new Date(); - var deploymentId = date.toLocaleString(Qt.locale(), "ddMMyyHHmmsszzz"); - var jsonRpcUrl = "http://127.0.0.1:8080"; + var jsonRpcUrl = "http://127.0.0.1:8080"; console.log("Deploying " + deploymentId + " to " + jsonRpcUrl); deploymentStarted(); var requests = []; var requestNames = []; + for (var c in codeModel.contracts) { //TODO: order based on dependencies var code = codeModel.contracts[c].codeHex; requests.push({ @@ -299,8 +317,8 @@ function deployProject(force) { requestNames.push(c); } - var rpcRequest = JSON.stringify(requests);; - var httpRequest = new XMLHttpRequest() + var rpcRequest = JSON.stringify(requests); + var httpRequest = new XMLHttpRequest(); httpRequest.open("POST", jsonRpcUrl, true); httpRequest.setRequestHeader("Content-type", "application/json"); httpRequest.setRequestHeader("Content-length", rpcRequest.length); @@ -311,8 +329,8 @@ function deployProject(force) { var rpcResponse = JSON.parse(httpRequest.responseText); if (rpcResponse.length === requestNames.length) { var contractAddresses = {}; - for (var r = 0; r < rpcResponse.lenght; r++) - contractAddresses[requestNames[r]] = rpcResponse.result; + for (var r = 0; r < rpcResponse.length; r++) + contractAddresses[requestNames[r]] = rpcResponse[r].result; finalizeDeployment(deploymentId, contractAddresses); } } else { @@ -326,7 +344,7 @@ function deployProject(force) { } function finalizeDeployment(deploymentId, addresses) { - //create a dir for frontend files and copy them + deploymentStepChanged(qsTr("Packaging application ...")); var deploymentDir = projectPath + deploymentId + "/"; fileIo.makeDir(deploymentDir); for (var i = 0; i < projectListModel.count; i++) { @@ -369,7 +387,203 @@ function finalizeDeployment(deploymentId, addresses) { //copy scripts fileIo.copyFile("qrc:///js/bignumber.min.js", deploymentDir + "bignumber.min.js"); fileIo.copyFile("qrc:///js/webthree.js", deploymentDir + "ethereum.js"); - deploymentAddress = address; + deploymentAddresses = addresses; saveProject(); - deploymentComplete(); + + var packageRet = fileIo.makePackage(deploymentDir); + deploymentDialog.packageHash = packageRet[0]; + deploymentDialog.packageBase64 = packageRet[1]; + + var applicationUrlEth = deploymentDialog.applicationUrlEth; + applicationUrlEth = formatAppUrl(applicationUrlEth); + + deploymentStepChanged(qsTr("Registering application on the Ethereum network ...")); + checkRegistration(applicationUrlEth, deploymentDialog.eth, function () { + deploymentComplete(); + deployRessourcesDialog.text = qsTr("Register Web Application to finalize deployment."); + deployRessourcesDialog.open(); + }); +} + +function rpcCall(requests, callBack) +{ + var jsonRpcUrl = "http://localhost:8080"; + var rpcRequest = JSON.stringify(requests); + var httpRequest = new XMLHttpRequest(); + httpRequest.open("POST", jsonRpcUrl, true); + httpRequest.setRequestHeader("Content-type", "application/json"); + httpRequest.setRequestHeader("Content-length", rpcRequest.length); + httpRequest.setRequestHeader("Connection", "close"); + httpRequest.onreadystatechange = function() { + if (httpRequest.readyState === XMLHttpRequest.DONE) { + if (httpRequest.status !== 200) + { + var errorText = qsTr("Deployment error: Error while registering Dapp ") + httpRequest.status; + console.log(errorText); + deploymentError(errorText); + return; + } + callBack(httpRequest.status, httpRequest.responseText) + } + } + httpRequest.send(rpcRequest); +} + + +function checkRegistration(dappUrl, addr, callBack) +{ + var requests = []; + var data = ""; + if (dappUrl.length > 0) + { + //checking path (register). + var str = createString(dappUrl[0]); + data = "0x6be16bed" + str.encodeValueAsString(); + console.log("checking if path exists (register) => " + JSON.stringify(dappUrl)); + requests.push({ + jsonrpc: "2.0", + method: "eth_call", + params: [ { "to": '0x' + addr, "data": data } ], + id: jsonRpcRequestId++ + }); + + rpcCall(requests, function (httpRequest, response) { + var address = JSON.parse(response)[0].result.replace('0x', ''); + if (address === "") + { + var errorTxt = qsTr("Path does not exists " + JSON.stringify(dappUrl) + " cannot continue"); + deploymentError(errorTxt); + console.log(errorTxt); + return; + } + + dappUrl.splice(0, 1); + checkRegistration(dappUrl, address, callBack); + }); + } + else + { + var paramTitle = createString(projectModel.projectTitle); + requests.push({ + //owner() + jsonrpc: "2.0", + method: "eth_call", + params: [ { "to": '0x' + addr, "data": "0xec7b9200" + paramTitle.encodeValueAsString() } ], + id: jsonRpcRequestId++ + }); + + requests.push({ + //accounts + jsonrpc: "2.0", + method: "eth_accounts", + params: null, + id: jsonRpcRequestId++ + }); + + rpcCall(requests, function (httpRequest, response) { + requests = []; + var res = JSON.parse(response); + var currentOwner = res[0].result; + var noOwner = currentOwner.replace('0x', '').replace(/0/g, '') === ''; + + if (noOwner) + { + requests.push({ + //reserve() + jsonrpc: "2.0", + method: "eth_transact", + params: [ { "to": '0x' + addr, "data": "0x1c83171b" + paramTitle.encodeValueAsString() } ], + id: jsonRpcRequestId++ + }); + } + else + { + var bOwner = false; + currentOwner = normalizeAddress(currentOwner); + for (var u in res[1].result) + { + if (normalizeAddress(res[1].result[u]) === currentOwner) + bOwner = true; + } + + if (!bOwner) + { + var errorTxt = qsTr("Current user is not the owner of this path. Cannot continue") + deploymentError(errorTxt); + console.log(errorTxt); + return; + } + } + console.log("setContentHash"); + requests.push({ + //setContent() + jsonrpc: "2.0", + method: "eth_transact", + params: [ { "to": '0x' + addr, "data": "0x5d574e32" + paramTitle.encodeValueAsString() + deploymentDialog.packageHash } ], + id: jsonRpcRequestId++ + }); + rpcCall(requests, function (httpRequest, response) { + callBack(); + }); + }); + } } + +function registerToUrlHint() +{ + deploymentStepChanged(qsTr("Registering application Resources (" + deploymentDialog.applicationUrlHttp) + ") ..."); + var requests = []; + var paramUrlHttp = createString(deploymentDialog.applicationUrlHttp); + requests.push({ + //urlHint => suggestUrl + jsonrpc: "2.0", + method: "eth_transact", + params: [ { "to": '0x' + deploymentDialog.urlHintContract, "data": "0x4983e19c" + deploymentDialog.packageHash + paramUrlHttp.encodeValueAsString() } ], + id: jsonRpcRequestId++ + }); + + rpcCall(requests, function (httpRequest, response) { + deploymentComplete(); + }); +} + +function normalizeAddress(addr) +{ + addr = addr.replace('0x', ''); + var i = 0; + for (var k in addr) + { + if (addr[k] !== "0") + break; + else + i++; + } + return addr.substring(i); +} + +function formatAppUrl(url) +{ + var slash = url.indexOf("/"); + var dot = url.indexOf("."); + if (slash === -1 && dot === -1) + return url; + if ((slash !== -1 && slash < dot) || dot === -1) + return url.split("/"); + else + { + var dotted; + var ret = []; + if (slash !== -1) + { + ret.push(url.split("/")); + dotted = ret[0].split("."); + } + else + dotted = url.split("."); + + for (var k in dotted) + ret.unshift(dotted[k]); + return ret; + } +} + diff --git a/mix/qml/js/QEtherHelper.js b/mix/qml/js/QEtherHelper.js index 7563941d2..71ee258c3 100644 --- a/mix/qml/js/QEtherHelper.js +++ b/mix/qml/js/QEtherHelper.js @@ -15,3 +15,19 @@ function createBigInt(_value) return bigint; } +function createString(_value) +{ + var stringComponent = Qt.createComponent("qrc:/qml/QStringType.qml"); + var stringC = stringComponent.createObject(); + stringC.setValue(_value); + return stringC; +} + +function createHash(_value) +{ + var hComponent = Qt.createComponent("qrc:/qml/QHashType.qml"); + var hC = hComponent.createObject(); + hC.setValue(_value); + return hC; +} + diff --git a/mix/res.qrc b/mix/res.qrc index 20e51a9b3..b2a6385a1 100644 --- a/mix/res.qrc +++ b/mix/res.qrc @@ -101,5 +101,6 @@ qml/Style.qml qml/WebPreviewStyle.qml qml/img/available_updates.png + qml/DeploymentDialog.qml diff --git a/test/Assembly.cpp b/test/Assembly.cpp new file mode 100644 index 000000000..3869919e7 --- /dev/null +++ b/test/Assembly.cpp @@ -0,0 +1,129 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** + * @author Lefteris Karapetsas + * @date 2015 + * Unit tests for Assembly Items from evmcore/Assembly.h + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace dev::eth; + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +namespace +{ + +eth::AssemblyItems compileContract(const string& _sourceCode) +{ + Parser parser; + ASTPointer sourceUnit; + BOOST_REQUIRE_NO_THROW(sourceUnit = parser.parse(make_shared(CharStream(_sourceCode)))); + NameAndTypeResolver resolver({}); + resolver.registerDeclarations(*sourceUnit); + for (ASTPointer const& node: sourceUnit->getNodes()) + if (ContractDefinition* contract = dynamic_cast(node.get())) + { + BOOST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*contract)); + } + for (ASTPointer const& node: sourceUnit->getNodes()) + if (ContractDefinition* contract = dynamic_cast(node.get())) + { + BOOST_REQUIRE_NO_THROW(resolver.checkTypeRequirements(*contract)); + } + for (ASTPointer const& node: sourceUnit->getNodes()) + if (ContractDefinition* contract = dynamic_cast(node.get())) + { + Compiler compiler; + compiler.compileContract(*contract, map{}); + + return compiler.getRuntimeAssemblyItems(); + } + BOOST_FAIL("No contract found in source."); + return AssemblyItems(); +} + +void checkAssemblyLocations(AssemblyItems const& _items, std::vector _locations) +{ + size_t i = 0; + BOOST_CHECK_EQUAL(_items.size(), _locations.size()); + for (auto const& it: _items) + { + BOOST_CHECK_MESSAGE(it.getLocation() == _locations[i], + std::string("Location mismatch for assembly item ") + std::to_string(i)); + ++i; + } + +} + +} // end anonymous namespace + +BOOST_AUTO_TEST_SUITE(Assembly) + +BOOST_AUTO_TEST_CASE(location_test) +{ + char const* sourceCode = "contract test {\n" + " function f() returns (uint256 a)\n" + " {\n" + " return 16;\n" + " }\n" + "}\n"; + std::shared_ptr n = make_shared("source"); + AssemblyItems items = compileContract(sourceCode); + std::vector locations { + SourceLocation(0, 77, n), SourceLocation(0, 77, n), + SourceLocation(0, 77, n), SourceLocation(0, 77, n), + SourceLocation(0, 77, n), SourceLocation(0, 77, n), + SourceLocation(0, 77, n), SourceLocation(0, 77, n), + SourceLocation(), SourceLocation(), + SourceLocation(0, 77, n), SourceLocation(0, 77, n), + SourceLocation(), SourceLocation(), SourceLocation(), + SourceLocation(0, 77, n), SourceLocation(0, 77, n), + SourceLocation(0, 77, n), SourceLocation(0, 77, n), + SourceLocation(0, 77, n), SourceLocation(0, 77, n), + SourceLocation(0, 77, n), + SourceLocation(18, 75, n), SourceLocation(40, 49, n), + SourceLocation(61, 70, n), SourceLocation(61, 70, n), SourceLocation(61, 70, n), + SourceLocation(), SourceLocation(), + SourceLocation(61, 70, n), SourceLocation(61, 70, n), SourceLocation(61, 70, n) + }; + checkAssemblyLocations(items, locations); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} +} // end namespaces + diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index 20bc81599..f52b52d1c 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -2137,7 +2137,7 @@ BOOST_AUTO_TEST_CASE(event_lots_of_data) callContractFunctionWithValue("deposit(hash256)", value, id); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); - BOOST_CHECK(m_logs[0].data == encodeArgs(m_sender, id, value, true)); + BOOST_CHECK(m_logs[0].data == encodeArgs((u160)m_sender, id, value, true)); BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(address,hash256,uint256,bool)"))); } @@ -2667,6 +2667,107 @@ BOOST_AUTO_TEST_CASE(bytes_in_arguments) == encodeArgs(12, (8 + 9) * 3, 13, u256(innercalldata1.length()))); } +BOOST_AUTO_TEST_CASE(fixed_arrays_in_storage) +{ + char const* sourceCode = R"( + contract c { + struct Data { uint x; uint y; } + Data[2**10] data; + uint[2**10 + 3] ids; + function setIDStatic(uint id) { ids[2] = id; } + function setID(uint index, uint id) { ids[index] = id; } + function setData(uint index, uint x, uint y) { data[index].x = x; data[index].y = y; } + function getID(uint index) returns (uint) { return ids[index]; } + function getData(uint index) returns (uint x, uint y) { x = data[index].x; y = data[index].y; } + function getLengths() returns (uint l1, uint l2) { l1 = data.length; l2 = ids.length; } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("setIDStatic(uint256)", 11) == bytes()); + BOOST_CHECK(callContractFunction("getID(uint256)", 2) == encodeArgs(11)); + BOOST_CHECK(callContractFunction("setID(uint256,uint256)", 7, 8) == bytes()); + BOOST_CHECK(callContractFunction("getID(uint256)", 7) == encodeArgs(8)); + BOOST_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 7, 8, 9) == bytes()); + BOOST_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 8, 10, 11) == bytes()); + BOOST_CHECK(callContractFunction("getData(uint256)", 7) == encodeArgs(8, 9)); + BOOST_CHECK(callContractFunction("getData(uint256)", 8) == encodeArgs(10, 11)); + BOOST_CHECK(callContractFunction("getLengths()") == encodeArgs(u256(1) << 10, (u256(1) << 10) + 3)); +} + +BOOST_AUTO_TEST_CASE(dynamic_arrays_in_storage) +{ + char const* sourceCode = R"( + contract c { + struct Data { uint x; uint y; } + Data[] data; + uint[] ids; + function setIDStatic(uint id) { ids[2] = id; } + function setID(uint index, uint id) { ids[index] = id; } + function setData(uint index, uint x, uint y) { data[index].x = x; data[index].y = y; } + function getID(uint index) returns (uint) { return ids[index]; } + function getData(uint index) returns (uint x, uint y) { x = data[index].x; y = data[index].y; } + function getLengths() returns (uint l1, uint l2) { l1 = data.length; l2 = ids.length; } + function setLengths(uint l1, uint l2) { data.length = l1; ids.length = l2; } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("getLengths()") == encodeArgs(0, 0)); + BOOST_CHECK(callContractFunction("setLengths(uint256,uint256)", 48, 49) == bytes()); + BOOST_CHECK(callContractFunction("getLengths()") == encodeArgs(48, 49)); + BOOST_CHECK(callContractFunction("setIDStatic(uint256)", 11) == bytes()); + BOOST_CHECK(callContractFunction("getID(uint256)", 2) == encodeArgs(11)); + BOOST_CHECK(callContractFunction("setID(uint256,uint256)", 7, 8) == bytes()); + BOOST_CHECK(callContractFunction("getID(uint256)", 7) == encodeArgs(8)); + BOOST_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 7, 8, 9) == bytes()); + BOOST_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 8, 10, 11) == bytes()); + BOOST_CHECK(callContractFunction("getData(uint256)", 7) == encodeArgs(8, 9)); + BOOST_CHECK(callContractFunction("getData(uint256)", 8) == encodeArgs(10, 11)); +} + +BOOST_AUTO_TEST_CASE(fixed_out_of_bounds_array_access) +{ + char const* sourceCode = R"( + contract c { + uint[4] data; + function set(uint index, uint value) returns (bool) { data[index] = value; return true; } + function get(uint index) returns (uint) { return data[index]; } + function length() returns (uint) { return data.length; } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("length()") == encodeArgs(4)); + BOOST_CHECK(callContractFunction("set(uint256,uint256)", 3, 4) == encodeArgs(true)); + BOOST_CHECK(callContractFunction("set(uint256,uint256)", 4, 5) == bytes()); + BOOST_CHECK(callContractFunction("set(uint256,uint256)", 400, 5) == bytes()); + BOOST_CHECK(callContractFunction("get(uint256)", 3) == encodeArgs(4)); + BOOST_CHECK(callContractFunction("get(uint256)", 4) == bytes()); + BOOST_CHECK(callContractFunction("get(uint256)", 400) == bytes()); + BOOST_CHECK(callContractFunction("length()") == encodeArgs(4)); +} + +BOOST_AUTO_TEST_CASE(dynamic_out_of_bounds_array_access) +{ + char const* sourceCode = R"( + contract c { + uint[] data; + function enlarge(uint amount) returns (uint) { return data.length += amount; } + function set(uint index, uint value) returns (bool) { data[index] = value; return true; } + function get(uint index) returns (uint) { return data[index]; } + function length() returns (uint) { return data.length; } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("length()") == encodeArgs(0)); + BOOST_CHECK(callContractFunction("get(uint256)", 3) == bytes()); + BOOST_CHECK(callContractFunction("enlarge(uint256)", 4) == encodeArgs(4)); + BOOST_CHECK(callContractFunction("length()") == encodeArgs(4)); + BOOST_CHECK(callContractFunction("set(uint256,uint256)", 3, 4) == encodeArgs(true)); + BOOST_CHECK(callContractFunction("get(uint256)", 3) == encodeArgs(4)); + BOOST_CHECK(callContractFunction("length()") == encodeArgs(4)); + BOOST_CHECK(callContractFunction("set(uint256,uint256)", 4, 8) == bytes()); + BOOST_CHECK(callContractFunction("length()") == encodeArgs(4)); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/SolidityExpressionCompiler.cpp b/test/SolidityExpressionCompiler.cpp index 9cd13dcfd..3340334f8 100644 --- a/test/SolidityExpressionCompiler.cpp +++ b/test/SolidityExpressionCompiler.cpp @@ -127,6 +127,7 @@ bytes compileFirstExpression(const string& _sourceCode, vector> _ BOOST_REQUIRE(extractor.getExpression() != nullptr); CompilerContext context; + context.resetVisitedNodes(contract); context.setInheritanceHierarchy(inheritanceHierarchy); unsigned parametersSize = _localVariables.size(); // assume they are all one slot on the stack context.adjustStackOffset(parametersSize); @@ -134,7 +135,7 @@ bytes compileFirstExpression(const string& _sourceCode, vector> _ context.addVariable(dynamic_cast(resolveDeclaration(variable, resolver)), parametersSize--); - ExpressionCompiler::compileExpression(context, *extractor.getExpression()); + ExpressionCompiler(context).compile(*extractor.getExpression()); for (vector const& function: _functions) context << context.getFunctionEntryLabel(dynamic_cast(resolveDeclaration(function, resolver))); diff --git a/test/SolidityInterface.cpp b/test/SolidityInterface.cpp index a73c118bb..354715182 100644 --- a/test/SolidityInterface.cpp +++ b/test/SolidityInterface.cpp @@ -50,7 +50,7 @@ public: string getSourcePart(ASTNode const& _node) const { - Location location = _node.getLocation(); + SourceLocation location = _node.getLocation(); BOOST_REQUIRE(!location.isEmpty()); return m_interface.substr(location.start, location.end - location.start); } diff --git a/test/SolidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp index df970a6ed..4809aac1e 100644 --- a/test/SolidityNameAndTypeResolution.cpp +++ b/test/SolidityNameAndTypeResolution.cpp @@ -1176,6 +1176,15 @@ BOOST_AUTO_TEST_CASE(test_for_bug_override_function_with_bytearray_type) BOOST_CHECK_NO_THROW(parseTextAndResolveNamesWithChecks(sourceCode)); } +BOOST_AUTO_TEST_CASE(array_with_nonconstant_length) +{ + char const* text = R"( + contract c { + function f(uint a) { uint8[a] x; } + })"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/SolidityParser.cpp b/test/SolidityParser.cpp index 69bbc6e0a..75eba8bc6 100644 --- a/test/SolidityParser.cpp +++ b/test/SolidityParser.cpp @@ -480,6 +480,18 @@ BOOST_AUTO_TEST_CASE(statement_starting_with_type_conversion) char const* text = "contract test {\n" " function fun() {\n" " uint64(2);\n" + " uint64[7](3);\n" + " uint64[](3);\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(type_conversion_to_dynamic_array) +{ + char const* text = "contract test {\n" + " function fun() {\n" + " var x = uint64[](3);\n" " }\n" "}\n"; BOOST_CHECK_NO_THROW(parseText(text)); @@ -753,6 +765,45 @@ BOOST_AUTO_TEST_CASE(external_variable) BOOST_CHECK_THROW(parseText(text), ParserError); } +BOOST_AUTO_TEST_CASE(arrays_in_storage) +{ + char const* text = R"( + contract c { + uint[10] a; + uint[] a2; + struct x { uint[2**20] b; y[0] c; } + struct y { uint d; mapping(uint=>x)[] e; } + })"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(arrays_in_events) +{ + char const* text = R"( + contract c { + event e(uint[10] a, string7[8] indexed b, c[3] x); + })"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(arrays_in_expressions) +{ + char const* text = R"( + contract c { + function f() { c[10] a = 7; uint8[10 * 2] x; } + })"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(multi_arrays) +{ + char const* text = R"( + contract c { + mapping(uint => mapping(uint => int8)[8][][9])[] x; + })"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/stSolidityTestFiller.json b/test/stSolidityTestFiller.json index 973c52a8d..253ba8016 100644 --- a/test/stSolidityTestFiller.json +++ b/test/stSolidityTestFiller.json @@ -76,14 +76,6 @@ "//" : " if (!testCryptographicFunctions()) ", "//" : " res = hash(int(res) + int(0x00000f0000000000000000000000000000000000000000000000000000000000)); ", "//" : " ", - "//" : " //Tested 27.01.2015 ", - "//" : " //should run out of gas ", - "//" : " //if (!testInfiniteLoop()) ", - "//" : " // res = hash(int(res) + int(0x000f000000000000000000000000000000000000000000000000000000000000)); ", - "//" : " // ", - "//" : " //should run out of gas ", - "//" : " //if (!testRecursiveMethods()) ", - "//" : " // res = hash(int(res) + int(0x0000000000000000000000000000000000000000000000000000000000000000)); ", "//" : " } ", "//" : " ", "//" : " function testCryptographicFunctions() returns (bool res) ", @@ -155,25 +147,6 @@ "//" : " ", "//" : " } ", "//" : " ", - "//" : " function testInfiniteLoop() returns (bool res) ", - "//" : " { ", - "//" : " res = false; ", - "//" : " while(true){} ", - "//" : " return true; ", - "//" : " } ", - "//" : " ", - "//" : " function testRecursiveMethods() returns (bool res) ", - "//" : " { ", - "//" : " res = false; ", - "//" : " testRecursiveMethods2(); ", - "//" : " return true; ", - "//" : " } ", - "//" : " function testRecursiveMethods2() ", - "//" : " { ", - "//" : " testRecursiveMethods(); ", - "//" : "} ", - "//" : " ", - "//" : " ", "//" : " function testContractSuicide() returns (bool res) ", "//" : " { ", "//" : " TestContract a = new TestContract(); ", @@ -219,7 +192,6 @@ "//" : " } ", "//" : " } ", "//" : " ", - "//" : " ", "//" : " if (i == 0) ", "//" : " return true; ", "//" : " ", @@ -264,7 +236,7 @@ }, "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "100000", "//": "contract subcaller ", "//": "{ ", @@ -294,6 +266,12 @@ "nonce" : "0", "storage" : { } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000", + "nonce" : "0", + "code" : "", + "storage": {} } }, "transaction" : @@ -304,7 +282,7 @@ "gasPrice" : "1", "nonce" : "0", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "to" : "a94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", "value" : "1" } }, @@ -320,7 +298,7 @@ }, "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "100000", "//" : "contract recursiveMethods ", "//" : "{ ", @@ -343,17 +321,23 @@ "nonce" : "0", "storage" : { } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000", + "nonce" : "0", + "code" : "", + "storage": {} } }, "transaction" : { "//" : "testRecursiveMethods()", "data" : "0x981a3165", - "gasLimit" : "7000", + "gasLimit" : "2000", "gasPrice" : "1", "nonce" : "0", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "to" : "a94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", "value" : "1" } }, @@ -369,7 +353,7 @@ }, "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "100000", "//" : "contract recursiveMethods ", "//" : "{ ", @@ -392,6 +376,12 @@ "nonce" : "0", "storage" : { } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "500", + "nonce" : "0", + "code" : "", + "storage": {} } }, "transaction" : @@ -402,7 +392,7 @@ "gasPrice" : "1", "nonce" : "0", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "to" : "a94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", "value" : "1" } }, @@ -418,7 +408,7 @@ }, "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "1000000", "//" : "contract recursiveCreate1 ", "//" : "{ ", @@ -461,6 +451,12 @@ "nonce" : "0", "storage" : { } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "500000", + "nonce" : "0", + "code" : "", + "storage": {} } }, "transaction" : @@ -471,12 +467,12 @@ "gasPrice" : "1", "nonce" : "0", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "to" : "a94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", "value" : "1" } }, - "AmbigiousMethod" : { + "AmbiguousMethod" : { "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", "currentDifficulty" : "45678256", @@ -487,12 +483,35 @@ }, "pre" : { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "100000", + "//" : "contract contract1 ", + "//" : "{ ", + "//" : " uint value; ", + "//" : " function run() ", + "//" : " { ", + "//" : " value = 225; ", + "//" : " } ", + "//" : "} ", + "//" : " ", + "//" : "contract contract2 ", + "//" : "{ ", + "//" : " uint value2; ", + "//" : " function run() ", + "//" : " { ", + "//" : " value2 = 335; ", + "//" : " } ", + "//" : "} ", "code" : "0x60003560e060020a90048063c040622614601557005b601b6021565b60006000f35b61014f60008190555056", "nonce" : "0", "storage" : { } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "500", + "nonce" : "0", + "code" : "", + "storage": {} } }, "transaction" : @@ -503,6 +522,61 @@ "gasPrice" : "1", "nonce" : "0", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "1" + } + }, + + "QuadraticComplexity" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "45678256", + "currentGasLimit" : "100000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : + { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000", + "//" : "contract caller ", + "//" : "{ ", + "//" : " int value; ", + "//" : " function run(int count) ", + "//" : " { ", + "//" : " value = count; ", + "//" : " address a = 0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b; ", + "//" : " while(count > 0) ", + "//" : " { ", + "//" : " a.call('just', 'call'); ", + "//" : " count = count - 1; ", + "//" : " } ", + "//" : " } ", + "//" : "} ", + "code" : "0x60003560e060020a9004806361a4770614601557005b601e6004356024565b60006000f35b60008160008190555073b94f5374fce5edbc8e2a8697c15331677e6ebf0b90505b600082131560bf5780600160a060020a03166000600060007f6a7573740000000000000000000000000000000000000000000000000000000081526004017f63616c6c000000000000000000000000000000000000000000000000000000008152602001600060008560155a03f150506001820391506045565b505056", + "nonce" : "0", + "storage" : { + } + }, + + "b94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "100000", + "code" : "{ (CALLDATACOPY 0 0 32) }", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : + { + "//" : "run(int256)", + "data" : "0x61a47706000000000000000000000000000000000000000000000000000000000000c350", + "gasLimit" : "904+68*x+e", + "gasLimit" : "3500000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "to" : "a94f5374fce5edbc8e2a8697c15331677e6ebf0b", "value" : "1" } diff --git a/test/stTransactionTestFiller.json b/test/stTransactionTestFiller.json index 73026608d..37b752f86 100644 --- a/test/stTransactionTestFiller.json +++ b/test/stTransactionTestFiller.json @@ -842,78 +842,6 @@ } }, - "TransactionMakeAccountBalanceOverflow" : { - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "45678256", - "currentGasLimit" : "1000000", - "currentNumber" : "0", - "currentTimestamp" : 1, - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "pre" : - { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "100000", - "code" : "", - "nonce" : "0", - "storage" : { - } - }, - - "b94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", - "code" : "", - "nonce" : "0", - "storage" : { - } - } - }, - "transaction" : - { - "data" : "", - "gasLimit" : "1000", - "gasPrice" : "1", - "nonce" : "0", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "to" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "value" : "100" - } - }, - - "TransactionMakeAccountNonceOverflow" : { - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "1", - "currentGasLimit" : "1000000", - "currentNumber" : "0", - "currentTimestamp" : 1, - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "pre" : - { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "100000", - "code" : "", - "nonce" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", - "nonce" : "10000", - "storage" : { - } - } - }, - "transaction" : - { - "data" : "", - "gasLimit" : "1000", - "gasPrice" : "1", - "nonce" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", - "nonce" : "10000", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "to" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "value" : "100" - } - }, - "UserTransactionZeroCost" : { "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", diff --git a/test/vmArithmeticTestFiller.json b/test/vmArithmeticTestFiller.json index 329e2e507..36d11875b 100644 --- a/test/vmArithmeticTestFiller.json +++ b/test/vmArithmeticTestFiller.json @@ -365,6 +365,33 @@ } }, + "mul7": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(asm 0x1234567890abcdef0fedcba0987654321 0x1234567890abcdef0fedcba0987654321 0x1234567890abcdef0fedcba0987654321 MUL MUL 0 MSTORE 32 0 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, "sub0": { "env" : { @@ -534,6 +561,34 @@ } }, + "div1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(asm 0x2 0xfedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210 DIV 0 MSTORE 32 0 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + "divByNonZero0": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", @@ -1627,6 +1682,34 @@ } }, + "mulmod4": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(asm 100 27 37 MULMOD 0 MSTORE8 0 1 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + "mulmoddivByZero": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", @@ -4370,5 +4453,89 @@ "gasPrice" : "100000000000000", "gas" : "10000" } + }, + + "not1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(asm 123456 0 MSTORE 0 MLOAD NOT 0 MSTORE 32 0 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "arith1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(asm 1 1 SWAP1 ADD 7 MUL 5 ADD 2 SWAP1 DIV 4 SWAP1 1 33 SWAP1 SDIV 21 ADD 3 MUL 5 SWAP1 SMOD 3 SUB 9 17 EXP 0 MSTORE 8 0 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "fibbonacci_unrolled": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(asm 1 1 DUP2 DUP2 ADD DUP2 DUP2 ADD DUP2 DUP2 ADD DUP2 DUP2 ADD DUP2 DUP2 ADD DUP2 DUP2 ADD DUP2 DUP2 ADD DUP2 DUP2 ADD DUP2 DUP2 ADD DUP2 DUP2 ADD DUP2 DUP2 ADD DUP2 DUP2 ADD DUP2 DUP2 ADD DUP2 DUP2 ADD DUP2 DUP2 ADD DUP2 DUP2 ADD DUP2 DUP2 ADD 0 MSTORE 32 0 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } } } diff --git a/test/vmEnvironmentalInfoTestFiller.json b/test/vmEnvironmentalInfoTestFiller.json index bca2c387a..3f99b3db7 100644 --- a/test/vmEnvironmentalInfoTestFiller.json +++ b/test/vmEnvironmentalInfoTestFiller.json @@ -1158,6 +1158,34 @@ "gasPrice" : "123456789", "gas" : "100000000000" } - } + }, + + "env1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "5211", + "currentGasLimit" : "10000013", + "currentDifficulty" : "231883281", + "currentTimestamp" : "42", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "10000000000000033000", + "nonce" : "88", + "code" : "(asm PC ADDRESS BALANCE CALLER ORIGIN CALLVALUE CALLDATASIZE GASPRICE PREVHASH COINBASE TIMESTAMP NUMBER DIFFICULTY GASLIMIT PC CALLDATASIZE 0 CALLDATALOAD 38 CALLDATALOAD 19 CALLDATALOAD CODESIZE 0x1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff 0 MSTORE 32 0 0 CREATE 32 0 32 0 0 ADDRESS 3000 CALL 0 MLOAD 4096 MSTORE MSIZE 32 MUL 0 SHA3 ADDRESS SUICIDE 1 2 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "10000000001111111", + "data" : "0xdeadbeef", + "gasPrice" : "2015", + "gas" : "100000000001" + } + }, } diff --git a/test/vmIOandFlowOperationsTestFiller.json b/test/vmIOandFlowOperationsTestFiller.json index e794fb2c9..6822b3fcc 100644 --- a/test/vmIOandFlowOperationsTestFiller.json +++ b/test/vmIOandFlowOperationsTestFiller.json @@ -3003,5 +3003,482 @@ "gasPrice" : "100000000000000", "gas" : "10000" } + }, + + "byte1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(asm 0x112233445566778899001122334455667788990011223344556677889900aabb 0 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 1 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 2 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 3 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 4 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 5 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 6 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 7 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 8 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 9 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 10 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 11 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 12 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 13 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 14 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 15 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 16 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 17 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 18 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 19 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 20 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 21 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 22 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 23 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 24 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 25 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 26 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 27 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 28 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 29 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 30 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 31 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 32 BYTE 0x112233445566778899001122334455667788990011223344556677889900aabb 2014 BYTE 0 0 SSTORE)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "memory1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(asm 2 0 MSTORE8 3 1 MSTORE8 0 MLOAD 1 MLOAD ADD 2 MSTORE 64 0 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "return1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(asm 1 1000000 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "return2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{ [i] 1 ( if (> @i 0) { (return 39) [i] 2 } (return 1) ) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "stackjump1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(asm 0x4 0x6 0x9 0x14 JUMP JUMPDEST 0xa SUB 0x0 MSTORE MSIZE 0x0 RETURN JUMPDEST 0x0 MSTORE ADD 0x9 JUMP)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "kv1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{ [[69]] (caller) (return 0 (lll (when (= (caller) @@69) (for {} (< @i (calldatasize)) [i](+ @i 64) [[ (calldataload @i) ]] (calldataload (+ @i 32)) ) ) 0))}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "jumpi_at_the_end" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "10000000", + "currentNumber" : "0", + "currentTimestamp" : "1", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "code" : "(asm 10 0 MSTORE JUMPDEST 0 MLOAD 1 SWAP1 SUB DUP1 0 MSTORE 6 JUMPI)", + "data" : "0x", + "gas" : "1000", + "gasPrice" : "100000000000000", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "code" : "(asm 10 0 MSTORE JUMPDEST 0 MLOAD 1 SWAP1 SUB DUP1 0 MSTORE 5 JUMPI)", + "nonce" : "0", + "storage" : {} + } + } + }, + + "bad_indirect_jump1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(asm 27 37 MUL JUMP JUMPDEST)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "bad_indirect_jump2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(asm 1 3 3 MUL JUMPI 0 0 JUMP)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "for_loop1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(for [i]:10 (> @i 0) [i](- @i 1) [j](+ @i @j))", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "for_loop2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(for [i]:0 (< @i 10) [i](+ @i 1) [j](+ @i @j))", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "indirect_jump1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(asm 4 3 ADD JUMP STOP JUMPDEST 1 0 MSTORE MSIZE 0 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "indirect_jump2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(asm 8 6 ADD JUMP STOP JUMPDEST 1 0 MSTORE STOP JUMPDEST 2 0 MSTORE MSIZE 0 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "indirect_jump3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(asm 1 4 5 ADD JUMPI STOP JUMPDEST 1 0 MSTORE MSIZE 0 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "indirect_jump4": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(asm 0 7 5 ADD JUMPI 1 0 MSTORE STOP JUMPDEST)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "stack_loop": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(asm 10 JUMPDEST 1 DUP2 SUB DUP1 2 JUMPI 0 MSTORE8 1 MSTORE8 2 MSTORE8 3 MSTORE8 4 MSTORE8 5 MSTORE8 6 MSTORE8 7 MSTORE8 8 MSTORE8 9 MSTORE8 MSIZE 0 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "when": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(when (> 1 0) [i] 13)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } } } diff --git a/test/vmPushDupSwapTestFiller.json b/test/vmPushDupSwapTestFiller.json index a9b69f79e..1aca47922 100644 --- a/test/vmPushDupSwapTestFiller.json +++ b/test/vmPushDupSwapTestFiller.json @@ -981,6 +981,34 @@ } }, + "push33": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(asm 101 2002 303303 40444404 50555555505 60666666666606 7777777777777777 888888888888888888 99999999999999999999 10000000000000000000001 10111111111111111111111101 2022222222222222222222222202 303333333333333333333333333303 4044444444444444444444444444444404 505555555555555555555555555555555505 60666666666666666666666666666666666606 7077777777777777777777777777777777777707 808888888888888888888888888888888888888808 90999999999999999999999999999999999999999909 100000000000000000000000000000000000000000000001 10111111111111111111111111111111111111111111111101 2022222222222222222222222222222222222222222222222202 303333333333333333333333333333333333333333333333333303 40444444444444444444444444444444444444444444444444444404 50555555555555555555555555555555555555555555555555555555505 6066666666666666666666666666666666666666666666666666666666606 707777777777777777777777777777777777777777777777777777777777707 808888888888888888888888888888888888888888888888888888888888888808 90999999999999999999999999999999999999999999999999999999999999999909 100000000000000000000000000000000000000000000000000000000000000000000001 10111111111111111111111111111111111111111111111111111111111111111111111101 2022222222222222222222222222222222222222222222222222222222222222222222222202)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "32" + } + }, + "dup1": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", @@ -1931,5 +1959,33 @@ "gasPrice" : "100000000000000", "gas" : "10000" } + }, + + "swapjump1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "(asm 5 2 1 12 JUMPI POP POP STOP JUMPDEST SWAP1 1 22 JUMPI POP POP STOP JUMPDEST SUB 0 MSTORE 1 31 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } } }