Browse Source

Merge branch 'develop' into jsonrpc_interface

cl-refactor
Marek Kotewicz 10 years ago
parent
commit
3542fa751a
  1. 2
      CMakeLists.txt
  2. 2
      alethzero/CMakeLists.txt
  3. 43
      alethzero/MainWin.cpp
  4. 4
      alethzero/MainWin.h
  5. 36
      alethzero/OurWebThreeStubServer.cpp
  6. 38
      alethzero/OurWebThreeStubServer.h
  7. 2
      eth/main.cpp
  8. 2
      iethxi/MainWin.cpp
  9. 3
      libdevcore/CommonJS.cpp
  10. 2
      libethereum/Executive.h
  11. 3
      libethereum/State.cpp
  12. 2
      libevm/CMakeLists.txt
  13. 2
      libevm/ExtVMFace.h
  14. 2
      libevm/VM.h
  15. 0
      libevmcore/Assembly.cpp
  16. 2
      libevmcore/Assembly.h
  17. 2
      libevmcore/CMakeLists.txt
  18. 36
      libevmcore/Exceptions.h
  19. 0
      libevmcore/Instruction.cpp
  20. 7
      libevmcore/Instruction.h
  21. 4
      libjsqrc/main.js
  22. 1
      liblll/All.h
  23. 2
      liblll/CMakeLists.txt
  24. 2
      liblll/CodeFragment.cpp
  25. 4
      liblll/CodeFragment.h
  26. 3
      liblll/Exceptions.h
  27. 2
      libpyserpent/CMakeLists.txt
  28. 2
      libqethereum/QmlEthereum.cpp
  29. 2
      libserpent/CMakeLists.txt
  30. 38
      libsolidity/AST.cpp
  31. 7
      libsolidity/AST.h
  32. 3
      libsolidity/CMakeLists.txt
  33. 11
      libsolidity/Compiler.cpp
  34. 4
      libsolidity/CompilerContext.h
  35. 87
      libsolidity/ExpressionCompiler.cpp
  36. 12
      libsolidity/ExpressionCompiler.h
  37. 106
      libsolidity/Scanner.cpp
  38. 2
      libsolidity/Scanner.h
  39. 84
      libsolidity/Token.h
  40. 57
      libsolidity/Types.cpp
  41. 5
      libsolidity/Types.h
  42. 22
      libweb3jsonrpc/WebThreeStubServer.cpp
  43. 2
      lllc/CMakeLists.txt
  44. 2
      lllc/main.cpp
  45. 2
      neth/main.cpp
  46. 2
      sc/CMakeLists.txt
  47. 8
      stdserv.js
  48. 2
      test/createRandomTest.cpp
  49. 8
      test/solidityCompiler.cpp
  50. 192
      test/solidityEndToEndTest.cpp
  51. 74
      test/solidityExpressionCompiler.cpp
  52. 16
      test/solidityNameAndTypeResolution.cpp
  53. 26
      test/solidityScanner.cpp
  54. 2
      test/vm.h
  55. 2
      third/CMakeLists.txt
  56. 2
      walleth/MainWin.cpp
  57. 6
      windows/LibEthereum.vcxproj
  58. 14
      windows/LibEthereum.vcxproj.filters

2
CMakeLists.txt

@ -106,7 +106,7 @@ include(EthDependenciesDeprecated)
createBuildInfo() createBuildInfo()
add_subdirectory(libdevcore) add_subdirectory(libdevcore)
add_subdirectory(libevmface) add_subdirectory(libevmcore)
add_subdirectory(liblll) add_subdirectory(liblll)
add_subdirectory(libserpent) add_subdirectory(libserpent)
add_subdirectory(libsolidity) add_subdirectory(libsolidity)

2
alethzero/CMakeLists.txt

@ -53,7 +53,7 @@ else ()
endif () endif ()
qt5_use_modules(${EXECUTEABLE} Core)# Gui Widgets Network WebKit WebKitWidgets) qt5_use_modules(${EXECUTEABLE} Core)# Gui Widgets Network WebKit WebKitWidgets)
target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore devcrypto secp256k1 gmp ${CRYPTOPP_LS} serpent lll solidity evmface devcore web3jsonrpc jsqrc) target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore devcrypto secp256k1 gmp ${CRYPTOPP_LS} serpent lll solidity evmcore devcore web3jsonrpc jsqrc)
if (APPLE) if (APPLE)
# First have qt5 install plugins and frameworks # First have qt5 install plugins and frameworks

43
alethzero/MainWin.cpp

@ -50,6 +50,7 @@
#include "MiningView.h" #include "MiningView.h"
#include "BuildInfo.h" #include "BuildInfo.h"
#include "MainWin.h" #include "MainWin.h"
#include "OurWebThreeStubServer.h"
#include "ui_Main.h" #include "ui_Main.h"
using namespace std; using namespace std;
using namespace dev; using namespace dev;
@ -154,7 +155,8 @@ Main::Main(QWidget *parent) :
// w3stubserver, on dealloc, deletes m_qwebConnector // w3stubserver, on dealloc, deletes m_qwebConnector
m_qwebConnector = new QWebThreeConnector(); // owned by WebThreeStubServer m_qwebConnector = new QWebThreeConnector(); // owned by WebThreeStubServer
m_server.reset(new WebThreeStubServer(m_qwebConnector, *web3(), keysAsVector(m_myKeys))); m_server.reset(new OurWebThreeStubServer(m_qwebConnector, *web3(), keysAsVector(m_myKeys)));
connect(&*m_server, SIGNAL(onNewId(QString)), SLOT(addNewId(QString)));
m_server->setIdentities(keysAsVector(owned())); m_server->setIdentities(keysAsVector(owned()));
m_server->StartListening(); m_server->StartListening();
@ -205,12 +207,28 @@ Main::~Main()
writeSettings(); writeSettings();
} }
void Main::on_newIdentity_triggered()
{
KeyPair kp = KeyPair::create();
m_myIdentities.append(kp);
m_server->setIdentities(keysAsVector(owned()));
refreshWhisper();
}
void Main::refreshWhisper()
{
ui->shhFrom->clear();
for (auto i: m_server->ids())
ui->shhFrom->addItem(QString::fromStdString(toHex(i.first.ref())));
}
void Main::addNewId(QString _ids) void Main::addNewId(QString _ids)
{ {
Secret _id = jsToSecret(_ids.toStdString()); Secret _id = jsToSecret(_ids.toStdString());
KeyPair kp(_id); KeyPair kp(_id);
m_myIdentities.push_back(kp); m_myIdentities.push_back(kp);
m_server->setIdentities(keysAsVector(owned())); m_server->setIdentities(keysAsVector(owned()));
refreshWhisper();
} }
dev::p2p::NetworkPreferences Main::netPrefs() const dev::p2p::NetworkPreferences Main::netPrefs() const
@ -1243,6 +1261,13 @@ void Main::on_blocks_currentItemChanged()
s << "<br/>Log Bloom: <b>" << info.logBloom << "</b>"; s << "<br/>Log Bloom: <b>" << info.logBloom << "</b>";
s << "<br/>Transactions: <b>" << block[1].itemCount() << "</b> @<b>" << info.transactionsRoot << "</b>"; s << "<br/>Transactions: <b>" << block[1].itemCount() << "</b> @<b>" << info.transactionsRoot << "</b>";
s << "<br/>Uncles: <b>" << block[2].itemCount() << "</b> @<b>" << info.sha3Uncles << "</b>"; s << "<br/>Uncles: <b>" << block[2].itemCount() << "</b> @<b>" << info.sha3Uncles << "</b>";
for (auto u: block[2])
{
BlockInfo uncle = BlockInfo::fromHeader(u.data());
s << "<br/><span style=\"margin-left: 2em\">&nbsp;</span>Hash: <b>" << uncle.hash << "</b>";
s << "<br/><span style=\"margin-left: 2em\">&nbsp;</span>Parent: <b>" << uncle.parentHash << "</b>";
s << "<br/><span style=\"margin-left: 2em\">&nbsp;</span>Number: <b>" << uncle.number << "</b>";
}
if (info.parentHash) if (info.parentHash)
s << "<br/>Pre: <b>" << BlockInfo(ethereum()->blockChain().block(info.parentHash)).stateRoot << "</b>"; s << "<br/>Pre: <b>" << BlockInfo(ethereum()->blockChain().block(info.parentHash)).stateRoot << "</b>";
else else
@ -1268,7 +1293,7 @@ void Main::on_blocks_currentItemChanged()
s << "&nbsp;&emsp;&nbsp;#<b>" << tx.nonce() << "</b>"; s << "&nbsp;&emsp;&nbsp;#<b>" << tx.nonce() << "</b>";
s << "<br/>Gas price: <b>" << formatBalance(tx.gasPrice()) << "</b>"; s << "<br/>Gas price: <b>" << formatBalance(tx.gasPrice()) << "</b>";
s << "<br/>Gas: <b>" << tx.gas() << "</b>"; s << "<br/>Gas: <b>" << tx.gas() << "</b>";
s << "<br/>V: <b>" << hex << nouppercase << (int)tx.signature().v << "</b>"; s << "<br/>V: <b>" << hex << nouppercase << (int)tx.signature().v << " + 27</b>";
s << "<br/>R: <b>" << hex << nouppercase << tx.signature().r << "</b>"; s << "<br/>R: <b>" << hex << nouppercase << tx.signature().r << "</b>";
s << "<br/>S: <b>" << hex << nouppercase << tx.signature().s << "</b>"; s << "<br/>S: <b>" << hex << nouppercase << tx.signature().s << "</b>";
s << "<br/>Msg: <b>" << tx.sha3(eth::WithoutSignature) << "</b>"; s << "<br/>Msg: <b>" << tx.sha3(eth::WithoutSignature) << "</b>";
@ -2169,20 +2194,6 @@ void Main::on_post_clicked()
whisper()->inject(m.seal(from, topicFromText(ui->shhTopic->toPlainText()), ui->shhTtl->value(), ui->shhWork->value())); whisper()->inject(m.seal(from, topicFromText(ui->shhTopic->toPlainText()), ui->shhTtl->value(), ui->shhWork->value()));
} }
void Main::on_newIdentity_triggered()
{
KeyPair kp = KeyPair::create();
m_myIdentities.append(kp);
m_server->setIdentities(keysAsVector(owned()));
}
void Main::refreshWhisper()
{
ui->shhFrom->clear();
for (auto i: m_server ->ids())
ui->shhFrom->addItem(QString::fromStdString(toHex(i.first.ref())));
}
void Main::refreshWhispers() void Main::refreshWhispers()
{ {
ui->whispers->clear(); ui->whispers->clear();

4
alethzero/MainWin.h

@ -47,7 +47,7 @@ class MessageFilter;
}} }}
class QQuickView; class QQuickView;
class WebThreeStubServer; class OurWebThreeStubServer;
struct WorldState struct WorldState
{ {
@ -256,6 +256,6 @@ private:
bool m_logChanged = true; bool m_logChanged = true;
QWebThreeConnector* m_qwebConnector; QWebThreeConnector* m_qwebConnector;
std::unique_ptr<WebThreeStubServer> m_server; std::unique_ptr<OurWebThreeStubServer> m_server;
QWebThree* m_qweb = nullptr; QWebThree* m_qweb = nullptr;
}; };

36
alethzero/OurWebThreeStubServer.cpp

@ -0,0 +1,36 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/** @file OurWebThreeStubServer.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "OurWebThreeStubServer.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
OurWebThreeStubServer::OurWebThreeStubServer(jsonrpc::AbstractServerConnector* _conn, dev::WebThreeDirect& _web3, std::vector<dev::KeyPair> const& _accounts):
WebThreeStubServer(_conn, _web3, _accounts)
{}
std::string OurWebThreeStubServer::newIdentity()
{
dev::KeyPair kp = dev::KeyPair::create();
emit onNewId(QString::fromStdString(toJS(kp.sec())));
return toJS(kp.pub());
}

38
alethzero/OurWebThreeStubServer.h

@ -0,0 +1,38 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/** @file OurWebThreeStubServer.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include <QtCore/QObject>
#include <libdevcore/CommonJS.h>
#include <libdevcrypto/Common.h>
#include <libweb3jsonrpc/WebThreeStubServer.h>
class OurWebThreeStubServer: public QObject, public WebThreeStubServer
{
Q_OBJECT
public:
OurWebThreeStubServer(jsonrpc::AbstractServerConnector* _conn, dev::WebThreeDirect& _web3, std::vector<dev::KeyPair> const& _accounts);
virtual std::string newIdentity() override;
signals:
void onNewId(QString _s);
};

2
eth/main.cpp

@ -32,7 +32,7 @@
#include <libweb3jsonrpc/CorsHttpServer.h> #include <libweb3jsonrpc/CorsHttpServer.h>
#endif #endif
#include <libdevcrypto/FileSystem.h> #include <libdevcrypto/FileSystem.h>
#include <libevmface/Instruction.h> #include <libevmcore/Instruction.h>
#include <libevm/VM.h> #include <libevm/VM.h>
#include <libethereum/All.h> #include <libethereum/All.h>
#include <libwebthree/WebThree.h> #include <libwebthree/WebThree.h>

2
iethxi/MainWin.cpp

@ -9,7 +9,7 @@
#include <QtCore/QtCore> #include <QtCore/QtCore>
#include <libethcore/FileSystem.h> #include <libethcore/FileSystem.h>
#include <libethcore/Dagger.h> #include <libethcore/Dagger.h>
#include <libevmface/Instruction.h> #include <libevmcore/Instruction.h>
#include <libethereum/Client.h> #include <libethereum/Client.h>
#include <libethereum/EthereumHost.h> #include <libethereum/EthereumHost.h>
#include "BuildInfo.h" #include "BuildInfo.h"

3
libdevcore/CommonJS.cpp

@ -35,8 +35,7 @@ bytes jsToBytes(std::string const& _s)
// Decimal // Decimal
return toCompactBigEndian(bigint(_s)); return toCompactBigEndian(bigint(_s));
else else
// Binary return bytes();
return asBytes(_s);
} }
std::string jsPadded(std::string const& _s, unsigned _l, unsigned _r) std::string jsPadded(std::string const& _s, unsigned _l, unsigned _r)

2
libethereum/Executive.h

@ -23,7 +23,7 @@
#include <functional> #include <functional>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libevmface/Instruction.h> #include <libevmcore/Instruction.h>
#include <libethcore/CommonEth.h> #include <libethcore/CommonEth.h>
#include <libevm/ExtVMFace.h> #include <libevm/ExtVMFace.h>
#include "Transaction.h" #include "Transaction.h"

3
libethereum/State.cpp

@ -26,7 +26,7 @@
#include <random> #include <random>
#include <secp256k1/secp256k1.h> #include <secp256k1/secp256k1.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libevmface/Instruction.h> #include <libevmcore/Instruction.h>
#include <libethcore/Exceptions.h> #include <libethcore/Exceptions.h>
#include <libevm/VM.h> #include <libevm/VM.h>
#include "BlockChain.h" #include "BlockChain.h"
@ -60,6 +60,7 @@ void ecrecoverCode(bytesConstRef _in, bytesRef _out)
if (secp256k1_ecdsa_recover_compact(in.hash.data(), 32, in.r.data(), pubkey, &pubkeylen, 0, (int)(u256)in.v - 27)) if (secp256k1_ecdsa_recover_compact(in.hash.data(), 32, in.r.data(), pubkey, &pubkeylen, 0, (int)(u256)in.v - 27))
ret = dev::sha3(bytesConstRef(&(pubkey[1]), 64)); ret = dev::sha3(bytesConstRef(&(pubkey[1]), 64));
memset(ret.data(), 0, 12);
memcpy(_out.data(), &ret, min(_out.size(), sizeof(ret))); memcpy(_out.data(), &ret, min(_out.size(), sizeof(ret)));
} }

2
libevm/CMakeLists.txt

@ -17,7 +17,7 @@ include_directories(..)
target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} ethcore)
target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcrypto)
target_link_libraries(${EXECUTABLE} evmface) target_link_libraries(${EXECUTABLE} evmcore)
target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcore)
target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} secp256k1)
target_link_libraries(${EXECUTABLE} gmp) target_link_libraries(${EXECUTABLE} gmp)

2
libevm/ExtVMFace.h

@ -27,7 +27,7 @@
#include <libdevcore/CommonData.h> #include <libdevcore/CommonData.h>
#include <libdevcore/RLP.h> #include <libdevcore/RLP.h>
#include <libdevcrypto/SHA3.h> #include <libdevcrypto/SHA3.h>
#include <libevmface/Instruction.h> #include <libevmcore/Instruction.h>
#include <libethcore/CommonEth.h> #include <libethcore/CommonEth.h>
#include <libethcore/BlockInfo.h> #include <libethcore/BlockInfo.h>

2
libevm/VM.h

@ -24,7 +24,7 @@
#include <unordered_map> #include <unordered_map>
#include <libdevcore/Exceptions.h> #include <libdevcore/Exceptions.h>
#include <libethcore/CommonEth.h> #include <libethcore/CommonEth.h>
#include <libevmface/Instruction.h> #include <libevmcore/Instruction.h>
#include <libdevcrypto/SHA3.h> #include <libdevcrypto/SHA3.h>
#include <libethcore/BlockInfo.h> #include <libethcore/BlockInfo.h>
#include "FeeStructure.h" #include "FeeStructure.h"

0
liblll/Assembly.cpp → libevmcore/Assembly.cpp

2
liblll/Assembly.h → libevmcore/Assembly.h

@ -24,7 +24,7 @@
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libevmface/Instruction.h> #include <libevmcore/Instruction.h>
#include "Exceptions.h" #include "Exceptions.h"
namespace dev namespace dev

2
libevmface/CMakeLists.txt → libevmcore/CMakeLists.txt

@ -4,7 +4,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB")
aux_source_directory(. SRC_LIST) aux_source_directory(. SRC_LIST)
set(EXECUTABLE evmface) set(EXECUTABLE evmcore)
file(GLOB HEADERS "*.h") file(GLOB HEADERS "*.h")
if(ETH_STATIC) if(ETH_STATIC)

36
libevmcore/Exceptions.h

@ -0,0 +1,36 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/** @file Exceptions.h
* @author Christian <c@ethdev.com>
* @date 2014
*/
#pragma once
#include <libdevcore/Exceptions.h>
namespace dev
{
namespace eth
{
struct AssemblyException: virtual Exception {};
struct InvalidDeposit: virtual AssemblyException {};
struct InvalidOpcode: virtual AssemblyException {};
}
}

0
libevmface/Instruction.cpp → libevmcore/Instruction.cpp

7
libevmface/Instruction.h → libevmcore/Instruction.h

@ -22,18 +22,13 @@
#pragma once #pragma once
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/Exceptions.h> #include <libevmcore/Exceptions.h>
namespace boost { namespace spirit { class utree; } }
namespace sp = boost::spirit;
namespace dev namespace dev
{ {
namespace eth namespace eth
{ {
struct InvalidOpcode: virtual Exception {};
/// Virtual machine bytecode instruction. /// Virtual machine bytecode instruction.
enum class Instruction: uint8_t enum class Instruction: uint8_t
{ {

4
libjsqrc/main.js

@ -218,6 +218,8 @@
// Find termination // Find termination
var str = ""; var str = "";
var i = 0, l = hex.length; var i = 0, l = hex.length;
if (hex.substring(0, 2) == '0x')
i = 2;
for(; i < l; i+=2) { for(; i < l; i+=2) {
var code = hex.charCodeAt(i) var code = hex.charCodeAt(i)
if(code == 0) { if(code == 0) {
@ -239,7 +241,7 @@
var hex = this.toHex(str); var hex = this.toHex(str);
while(hex.length < pad*2) while(hex.length < pad*2)
hex += "00"; hex += "00";
return hex return "0x" + hex
}, },
eth: { eth: {

1
liblll/All.h

@ -1,6 +1,5 @@
#pragma once #pragma once
#include "Assembly.h"
#include "CodeFragment.h" #include "CodeFragment.h"
#include "Compiler.h" #include "Compiler.h"
#include "CompilerState.h" #include "CompilerState.h"

2
liblll/CMakeLists.txt

@ -15,7 +15,7 @@ endif()
include_directories(..) include_directories(..)
target_link_libraries(${EXECUTABLE} evmface) target_link_libraries(${EXECUTABLE} evmcore)
target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcore)

2
liblll/CodeFragment.cpp

@ -25,7 +25,7 @@
#include <boost/spirit/include/support_utree.hpp> #include <boost/spirit/include/support_utree.hpp>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libevmface/Instruction.h> #include <libevmcore/Instruction.h>
#include "CompilerState.h" #include "CompilerState.h"
#include "Parser.h" #include "Parser.h"
using namespace std; using namespace std;

4
liblll/CodeFragment.h

@ -22,8 +22,8 @@
#pragma once #pragma once
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libevmface/Instruction.h> #include <libevmcore/Instruction.h>
#include "Assembly.h" #include <libevmcore/Assembly.h>
#include "Exceptions.h" #include "Exceptions.h"
namespace boost { namespace spirit { class utree; } } namespace boost { namespace spirit { class utree; } }

3
liblll/Exceptions.h

@ -32,16 +32,13 @@ namespace eth
class CompilerException: public dev::Exception {}; class CompilerException: public dev::Exception {};
class InvalidOperation: public CompilerException {}; class InvalidOperation: public CompilerException {};
class IntegerOutOfRange: public CompilerException {}; class IntegerOutOfRange: public CompilerException {};
class StringTooLong: public CompilerException {};
class EmptyList: public CompilerException {}; class EmptyList: public CompilerException {};
class DataNotExecutable: public CompilerException {}; class DataNotExecutable: public CompilerException {};
class IncorrectParameterCount: public CompilerException {}; class IncorrectParameterCount: public CompilerException {};
class InvalidDeposit: public CompilerException {};
class InvalidName: public CompilerException {}; class InvalidName: public CompilerException {};
class InvalidMacroArgs: public CompilerException {}; class InvalidMacroArgs: public CompilerException {};
class InvalidLiteral: public CompilerException {}; class InvalidLiteral: public CompilerException {};
class BareSymbol: public CompilerException {}; class BareSymbol: public CompilerException {};
class ExpectedLiteral: public CompilerException {};
} }
} }

2
libpyserpent/CMakeLists.txt

@ -13,7 +13,7 @@ include_directories(..)
target_link_libraries(${EXECUTABLE} serpent) target_link_libraries(${EXECUTABLE} serpent)
target_link_libraries(${EXECUTABLE} lll) target_link_libraries(${EXECUTABLE} lll)
target_link_libraries(${EXECUTABLE} evmface) target_link_libraries(${EXECUTABLE} evmcore)
target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcore)
target_link_libraries(${EXECUTABLE} ${PYTHON_LS}) target_link_libraries(${EXECUTABLE} ${PYTHON_LS})

2
libqethereum/QmlEthereum.cpp

@ -4,7 +4,7 @@
#include <QtCore/QtCore> #include <QtCore/QtCore>
#include <QtWebKitWidgets/QWebFrame> #include <QtWebKitWidgets/QWebFrame>
#include <libdevcrypto/FileSystem.h> #include <libdevcrypto/FileSystem.h>
#include <libevmface/Instruction.h> #include <libevmcore/Instruction.h>
#include <liblll/Compiler.h> #include <liblll/Compiler.h>
#include <libethereum/Client.h> #include <libethereum/Client.h>
#include <libethereum/EthereumHost.h> #include <libethereum/EthereumHost.h>

2
libserpent/CMakeLists.txt

@ -16,7 +16,7 @@ endif()
include_directories(..) include_directories(..)
target_link_libraries(${EXECUTABLE} lll) target_link_libraries(${EXECUTABLE} lll)
target_link_libraries(${EXECUTABLE} evmface) target_link_libraries(${EXECUTABLE} evmcore)
target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcore)
if("${TARGET_PLATFORM}" STREQUAL "w64") if("${TARGET_PLATFORM}" STREQUAL "w64")

38
libsolidity/AST.cpp

@ -283,14 +283,6 @@ void WhileStatement::checkTypeRequirements()
m_body->checkTypeRequirements(); m_body->checkTypeRequirements();
} }
void Continue::checkTypeRequirements()
{
}
void Break::checkTypeRequirements()
{
}
void Return::checkTypeRequirements() void Return::checkTypeRequirements()
{ {
if (!m_expression) if (!m_expression)
@ -326,8 +318,6 @@ void VariableDefinition::checkTypeRequirements()
void Assignment::checkTypeRequirements() void Assignment::checkTypeRequirements()
{ {
//@todo lefthandside actually has to be assignable
// add a feature to the type system to check that
m_leftHandSide->checkTypeRequirements(); m_leftHandSide->checkTypeRequirements();
if (!m_leftHandSide->isLvalue()) if (!m_leftHandSide->isLvalue())
BOOST_THROW_EXCEPTION(createTypeError("Expression has to be an lvalue.")); BOOST_THROW_EXCEPTION(createTypeError("Expression has to be an lvalue."));
@ -347,9 +337,11 @@ void ExpressionStatement::checkTypeRequirements()
void Expression::expectType(Type const& _expectedType) void Expression::expectType(Type const& _expectedType)
{ {
checkTypeRequirements(); checkTypeRequirements();
if (!getType()->isImplicitlyConvertibleTo(_expectedType)) Type const& type = *getType();
BOOST_THROW_EXCEPTION(createTypeError("Type not implicitly convertible to expected type.")); if (!type.isImplicitlyConvertibleTo(_expectedType))
//@todo provide more information to the exception BOOST_THROW_EXCEPTION(createTypeError("Type " + type.toString() +
" not implicitly convertible to expected type "
+ _expectedType.toString() + "."));
} }
void UnaryOperation::checkTypeRequirements() void UnaryOperation::checkTypeRequirements()
@ -366,21 +358,25 @@ void UnaryOperation::checkTypeRequirements()
void BinaryOperation::checkTypeRequirements() void BinaryOperation::checkTypeRequirements()
{ {
m_right->checkTypeRequirements();
m_left->checkTypeRequirements(); m_left->checkTypeRequirements();
m_right->checkTypeRequirements();
if (m_right->getType()->isImplicitlyConvertibleTo(*m_left->getType())) if (m_right->getType()->isImplicitlyConvertibleTo(*m_left->getType()))
m_commonType = m_left->getType(); m_commonType = m_left->getType();
else if (m_left->getType()->isImplicitlyConvertibleTo(*m_right->getType())) else if (m_left->getType()->isImplicitlyConvertibleTo(*m_right->getType()))
m_commonType = m_right->getType(); m_commonType = m_right->getType();
else else
BOOST_THROW_EXCEPTION(createTypeError("No common type found in binary operation.")); BOOST_THROW_EXCEPTION(createTypeError("No common type found in binary operation: " +
m_left->getType()->toString() + " vs. " +
m_right->getType()->toString()));
if (Token::isCompareOp(m_operator)) if (Token::isCompareOp(m_operator))
m_type = make_shared<BoolType>(); m_type = make_shared<BoolType>();
else else
{ {
m_type = m_commonType; m_type = m_commonType;
if (!m_commonType->acceptsBinaryOperator(m_operator)) if (!m_commonType->acceptsBinaryOperator(m_operator))
BOOST_THROW_EXCEPTION(createTypeError("Operator not compatible with type.")); BOOST_THROW_EXCEPTION(createTypeError("Operator " + string(Token::toString(m_operator)) +
" not compatible with type " +
m_commonType->toString()));
} }
} }
@ -446,14 +442,6 @@ void Identifier::checkTypeRequirements()
if (asserts(m_referencedDeclaration)) if (asserts(m_referencedDeclaration))
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Identifier not resolved.")); BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Identifier not resolved."));
//@todo these dynamic casts here are not really nice...
// is i useful to have an AST visitor here?
// or can this already be done in NameAndTypeResolver?
// the only problem we get there is that in
// var x;
// x = 2;
// var y = x;
// the type of x is not yet determined.
VariableDeclaration* variable = dynamic_cast<VariableDeclaration*>(m_referencedDeclaration); VariableDeclaration* variable = dynamic_cast<VariableDeclaration*>(m_referencedDeclaration);
if (variable) if (variable)
{ {
@ -497,6 +485,8 @@ void ElementaryTypeNameExpression::checkTypeRequirements()
void Literal::checkTypeRequirements() void Literal::checkTypeRequirements()
{ {
m_type = Type::forLiteral(*this); m_type = Type::forLiteral(*this);
if (!m_type)
BOOST_THROW_EXCEPTION(createTypeError("Literal value too large."));
} }
} }

7
libsolidity/AST.h

@ -390,7 +390,7 @@ class Continue: public Statement
public: public:
Continue(Location const& _location): Statement(_location) {} Continue(Location const& _location): Statement(_location) {}
virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTVisitor& _visitor) override;
virtual void checkTypeRequirements() override; virtual void checkTypeRequirements() override {}
}; };
class Break: public Statement class Break: public Statement
@ -398,7 +398,7 @@ class Break: public Statement
public: public:
Break(Location const& _location): Statement(_location) {} Break(Location const& _location): Statement(_location) {}
virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTVisitor& _visitor) override;
virtual void checkTypeRequirements() override; virtual void checkTypeRequirements() override {}
}; };
class Return: public Statement class Return: public Statement
@ -565,12 +565,15 @@ public:
Expression& getLeftExpression() const { return *m_left; } Expression& getLeftExpression() const { return *m_left; }
Expression& getRightExpression() const { return *m_right; } Expression& getRightExpression() const { return *m_right; }
Token::Value getOperator() const { return m_operator; } Token::Value getOperator() const { return m_operator; }
Type const& getCommonType() const { return *m_commonType; }
private: private:
ASTPointer<Expression> m_left; ASTPointer<Expression> m_left;
Token::Value m_operator; Token::Value m_operator;
ASTPointer<Expression> m_right; ASTPointer<Expression> m_right;
/// The common type that is used for the operation, not necessarily the result type (e.g. for
/// comparisons, this is always bool).
std::shared_ptr<Type const> m_commonType; std::shared_ptr<Type const> m_commonType;
}; };

3
libsolidity/CMakeLists.txt

@ -16,8 +16,7 @@ file(GLOB HEADERS "*.h")
include_directories(..) include_directories(..)
# @todo we only depend on Assembly, not on all of lll target_link_libraries(${EXECUTABLE} evmcore devcore)
target_link_libraries(${EXECUTABLE} evmface devcore lll)
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

11
libsolidity/Compiler.cpp

@ -252,16 +252,14 @@ bool Compiler::visit(WhileStatement& _whileStatement)
bool Compiler::visit(Continue&) bool Compiler::visit(Continue&)
{ {
if (asserts(!m_continueTags.empty())) if (!m_continueTags.empty())
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Jump tag not available for \"continue\"."));
m_context.appendJumpTo(m_continueTags.back()); m_context.appendJumpTo(m_continueTags.back());
return false; return false;
} }
bool Compiler::visit(Break&) bool Compiler::visit(Break&)
{ {
if (asserts(!m_breakTags.empty())) if (!m_breakTags.empty())
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Jump tag not available for \"break\"."));
m_context.appendJumpTo(m_breakTags.back()); m_context.appendJumpTo(m_breakTags.back());
return false; return false;
} }
@ -273,7 +271,7 @@ bool Compiler::visit(Return& _return)
{ {
ExpressionCompiler::compileExpression(m_context, *expression); ExpressionCompiler::compileExpression(m_context, *expression);
VariableDeclaration const& firstVariable = *_return.getFunctionReturnParameters().getParameters().front(); VariableDeclaration const& firstVariable = *_return.getFunctionReturnParameters().getParameters().front();
ExpressionCompiler::cleanHigherOrderBitsIfNeeded(*expression->getType(), *firstVariable.getType()); ExpressionCompiler::appendTypeConversion(m_context, *expression->getType(), *firstVariable.getType());
int stackPosition = m_context.getStackPositionOfVariable(firstVariable); int stackPosition = m_context.getStackPositionOfVariable(firstVariable);
m_context << eth::swapInstruction(stackPosition) << eth::Instruction::POP; m_context << eth::swapInstruction(stackPosition) << eth::Instruction::POP;
} }
@ -286,7 +284,8 @@ bool Compiler::visit(VariableDefinition& _variableDefinition)
if (Expression* expression = _variableDefinition.getExpression()) if (Expression* expression = _variableDefinition.getExpression())
{ {
ExpressionCompiler::compileExpression(m_context, *expression); ExpressionCompiler::compileExpression(m_context, *expression);
ExpressionCompiler::cleanHigherOrderBitsIfNeeded(*expression->getType(), ExpressionCompiler::appendTypeConversion(m_context,
*expression->getType(),
*_variableDefinition.getDeclaration().getType()); *_variableDefinition.getDeclaration().getType());
int stackPosition = m_context.getStackPositionOfVariable(_variableDefinition.getDeclaration()); int stackPosition = m_context.getStackPositionOfVariable(_variableDefinition.getDeclaration());
m_context << eth::swapInstruction(stackPosition) << eth::Instruction::POP; m_context << eth::swapInstruction(stackPosition) << eth::Instruction::POP;

4
libsolidity/CompilerContext.h

@ -23,8 +23,8 @@
#pragma once #pragma once
#include <ostream> #include <ostream>
#include <libevmface/Instruction.h> #include <libevmcore/Instruction.h>
#include <liblll/Assembly.h> #include <libevmcore/Assembly.h>
#include <libsolidity/Types.h> #include <libsolidity/Types.h>
namespace dev { namespace dev {

87
libsolidity/ExpressionCompiler.cpp

@ -37,6 +37,13 @@ void ExpressionCompiler::compileExpression(CompilerContext& _context, Expression
_expression.accept(compiler); _expression.accept(compiler);
} }
void ExpressionCompiler::appendTypeConversion(CompilerContext& _context,
Type const& _typeOnStack, Type const& _targetType)
{
ExpressionCompiler compiler(_context);
compiler.appendTypeConversion(_typeOnStack, _targetType);
}
bool ExpressionCompiler::visit(Assignment& _assignment) bool ExpressionCompiler::visit(Assignment& _assignment)
{ {
m_currentLValue = nullptr; m_currentLValue = nullptr;
@ -44,7 +51,7 @@ bool ExpressionCompiler::visit(Assignment& _assignment)
Expression& rightHandSide = _assignment.getRightHandSide(); Expression& rightHandSide = _assignment.getRightHandSide();
rightHandSide.accept(*this); rightHandSide.accept(*this);
Type const& resultType = *_assignment.getType(); Type const& resultType = *_assignment.getType();
cleanHigherOrderBitsIfNeeded(*rightHandSide.getType(), resultType); appendTypeConversion(*rightHandSide.getType(), resultType);
_assignment.getLeftHandSide().accept(*this); _assignment.getLeftHandSide().accept(*this);
Token::Value op = _assignment.getAssignmentOperator(); Token::Value op = _assignment.getAssignmentOperator();
@ -113,7 +120,7 @@ bool ExpressionCompiler::visit(BinaryOperation& _binaryOperation)
{ {
Expression& leftExpression = _binaryOperation.getLeftExpression(); Expression& leftExpression = _binaryOperation.getLeftExpression();
Expression& rightExpression = _binaryOperation.getRightExpression(); Expression& rightExpression = _binaryOperation.getRightExpression();
Type const& resultType = *_binaryOperation.getType(); Type const& commonType = _binaryOperation.getCommonType();
Token::Value const op = _binaryOperation.getOperator(); Token::Value const op = _binaryOperation.getOperator();
if (op == Token::AND || op == Token::OR) if (op == Token::AND || op == Token::OR)
@ -121,23 +128,21 @@ bool ExpressionCompiler::visit(BinaryOperation& _binaryOperation)
// special case: short-circuiting // special case: short-circuiting
appendAndOrOperatorCode(_binaryOperation); appendAndOrOperatorCode(_binaryOperation);
} }
else if (Token::isCompareOp(op))
{
leftExpression.accept(*this);
rightExpression.accept(*this);
// the types to compare have to be the same, but the resulting type is always bool
if (asserts(*leftExpression.getType() == *rightExpression.getType()))
BOOST_THROW_EXCEPTION(InternalCompilerError());
appendCompareOperatorCode(op, *leftExpression.getType());
}
else else
{ {
bool cleanupNeeded = false;
if (commonType.getCategory() == Type::Category::INTEGER)
if (Token::isCompareOp(op) || op == Token::DIV || op == Token::MOD)
cleanupNeeded = true;
leftExpression.accept(*this); leftExpression.accept(*this);
cleanHigherOrderBitsIfNeeded(*leftExpression.getType(), resultType); appendTypeConversion(*leftExpression.getType(), commonType, cleanupNeeded);
rightExpression.accept(*this); rightExpression.accept(*this);
cleanHigherOrderBitsIfNeeded(*rightExpression.getType(), resultType); appendTypeConversion(*rightExpression.getType(), commonType, cleanupNeeded);
appendOrdinaryBinaryOperatorCode(op, resultType); if (Token::isCompareOp(op))
appendCompareOperatorCode(op, commonType);
else
appendOrdinaryBinaryOperatorCode(op, commonType);
} }
// do not visit the child nodes, we already did that explicitly // do not visit the child nodes, we already did that explicitly
@ -153,7 +158,7 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall)
BOOST_THROW_EXCEPTION(InternalCompilerError()); BOOST_THROW_EXCEPTION(InternalCompilerError());
Expression& firstArgument = *_functionCall.getArguments().front(); Expression& firstArgument = *_functionCall.getArguments().front();
firstArgument.accept(*this); firstArgument.accept(*this);
cleanHigherOrderBitsIfNeeded(*firstArgument.getType(), *_functionCall.getType()); appendTypeConversion(*firstArgument.getType(), *_functionCall.getType());
} }
else else
{ {
@ -170,7 +175,7 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall)
for (unsigned i = 0; i < arguments.size(); ++i) for (unsigned i = 0; i < arguments.size(); ++i)
{ {
arguments[i]->accept(*this); arguments[i]->accept(*this);
cleanHigherOrderBitsIfNeeded(*arguments[i]->getType(), appendTypeConversion(*arguments[i]->getType(),
*function.getParameters()[i]->getType()); *function.getParameters()[i]->getType());
} }
@ -233,28 +238,6 @@ void ExpressionCompiler::endVisit(Literal& _literal)
} }
} }
void ExpressionCompiler::cleanHigherOrderBitsIfNeeded(Type const& _typeOnStack, Type const& _targetType)
{
// If the type of one of the operands is extended, 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)
return;
if (_typeOnStack.getCategory() == Type::Category::INTEGER &&
_targetType.getCategory() == Type::Category::INTEGER)
{
//@todo
}
else
{
// If we get here, there is either an implementation missing to clean higher oder bits
// for non-integer types that are explicitly convertible or we got here in error.
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid type conversion requested."));
}
}
void ExpressionCompiler::appendAndOrOperatorCode(BinaryOperation& _binaryOperation) void ExpressionCompiler::appendAndOrOperatorCode(BinaryOperation& _binaryOperation)
{ {
Token::Value const op = _binaryOperation.getOperator(); Token::Value const op = _binaryOperation.getOperator();
@ -379,6 +362,32 @@ void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator)
} }
} }
void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded)
{
// If the type of one of the operands is extended, 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;
if (_typeOnStack.getCategory() == Type::Category::INTEGER)
appendHighBitsCleanup(dynamic_cast<IntegerType const&>(_typeOnStack));
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)
return;
else if (_typeOnStack.isSigned())
m_context << u256(_typeOnStack.getNumBits() / 8 - 1) << eth::Instruction::SIGNEXTEND;
else
m_context << ((u256(1) << _typeOnStack.getNumBits()) - 1) << eth::Instruction::AND;
}
void ExpressionCompiler::storeInLValue(Expression const& _expression) void ExpressionCompiler::storeInLValue(Expression const& _expression)
{ {
moveToLValue(_expression); moveToLValue(_expression);

12
libsolidity/ExpressionCompiler.h

@ -26,6 +26,8 @@ namespace dev {
namespace solidity { namespace solidity {
class CompilerContext; // forward class CompilerContext; // forward
class Type; // forward
class IntegerType; // forward
/// Compiler for expressions, i.e. converts an AST tree whose root is an Expression into a stream /// Compiler for expressions, i.e. converts an AST tree whose root is an Expression into a stream
/// of EVM instructions. It needs a compiler context that is the same for the whole compilation /// of EVM instructions. It needs a compiler context that is the same for the whole compilation
@ -37,7 +39,7 @@ public:
static void compileExpression(CompilerContext& _context, Expression& _expression); static void compileExpression(CompilerContext& _context, Expression& _expression);
/// Appends code to remove dirty higher order bits in case of an implicit promotion to a wider type. /// Appends code to remove dirty higher order bits in case of an implicit promotion to a wider type.
static void cleanHigherOrderBitsIfNeeded(Type const& _typeOnStack, Type const& _targetType); static void appendTypeConversion(CompilerContext& _context, Type const& _typeOnStack, Type const& _targetType);
private: private:
ExpressionCompiler(CompilerContext& _compilerContext): m_currentLValue(nullptr), m_context(_compilerContext) {} ExpressionCompiler(CompilerContext& _compilerContext): m_currentLValue(nullptr), m_context(_compilerContext) {}
@ -62,6 +64,14 @@ private:
void appendShiftOperatorCode(Token::Value _operator); 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 types.
/// 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);
/// Stores the value on top of the stack in the current lvalue and copies that value to the /// Stores the value on top of the stack in the current lvalue and copies that value to the
/// top of the stack again /// top of the stack again
void storeInLValue(Expression const& _expression); void storeInLValue(Expression const& _expression);

106
libsolidity/Scanner.cpp

@ -271,7 +271,7 @@ void Scanner::scanToken()
token = Token::ADD; token = Token::ADD;
break; break;
case '-': case '-':
// - -- -= // - -- -= Number
advance(); advance();
if (m_char == '-') if (m_char == '-')
{ {
@ -280,6 +280,8 @@ void Scanner::scanToken()
} }
else if (m_char == '=') else if (m_char == '=')
token = selectToken(Token::ASSIGN_SUB); token = selectToken(Token::ASSIGN_SUB);
else if (m_char == '.' || IsDecimalDigit(m_char))
token = scanNumber('-');
else else
token = Token::SUB; token = Token::SUB;
break; break;
@ -331,7 +333,7 @@ void Scanner::scanToken()
// . Number // . Number
advance(); advance();
if (IsDecimalDigit(m_char)) if (IsDecimalDigit(m_char))
token = scanNumber(true); token = scanNumber('.');
else else
token = Token::PERIOD; token = Token::PERIOD;
break; break;
@ -372,7 +374,7 @@ void Scanner::scanToken()
if (IsIdentifierStart(m_char)) if (IsIdentifierStart(m_char))
token = scanIdentifierOrKeyword(); token = scanIdentifierOrKeyword();
else if (IsDecimalDigit(m_char)) else if (IsDecimalDigit(m_char))
token = scanNumber(false); token = scanNumber();
else if (skipWhitespace()) else if (skipWhitespace())
token = Token::WHITESPACE; token = Token::WHITESPACE;
else if (isSourcePastEndOfInput()) else if (isSourcePastEndOfInput())
@ -461,14 +463,11 @@ void Scanner::scanDecimalDigits()
} }
Token::Value Scanner::scanNumber(bool _periodSeen) Token::Value Scanner::scanNumber(char _charSeen)
{ {
// the first digit of the number or the fraction enum { DECIMAL, HEX, BINARY } kind = DECIMAL;
if (asserts(IsDecimalDigit(m_char)))
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Number does not start with decimal digit."));
enum { DECIMAL, HEX, OCTAL, IMPLICIT_OCTAL, BINARY } kind = DECIMAL;
LiteralScope literal(this); LiteralScope literal(this);
if (_periodSeen) if (_charSeen == '.')
{ {
// we have already seen a decimal point of the float // we have already seen a decimal point of the float
addLiteralChar('.'); addLiteralChar('.');
@ -476,12 +475,13 @@ Token::Value Scanner::scanNumber(bool _periodSeen)
} }
else else
{ {
if (_charSeen == '-')
addLiteralChar('-');
// if the first character is '0' we must check for octals and hex // if the first character is '0' we must check for octals and hex
if (m_char == '0') if (m_char == '0')
{ {
addLiteralCharAndAdvance(); addLiteralCharAndAdvance();
// either 0, 0exxx, 0Exxx, 0.xxx, a hex number, a binary number or // either 0, 0exxx, 0Exxx, 0.xxx or a hex number
// an octal number.
if (m_char == 'x' || m_char == 'X') if (m_char == 'x' || m_char == 'X')
{ {
// hex number // hex number
@ -556,17 +556,73 @@ Token::Value Scanner::scanNumber(bool _periodSeen)
KEYWORD("function", Token::FUNCTION) \ KEYWORD("function", Token::FUNCTION) \
KEYWORD_GROUP('h') \ KEYWORD_GROUP('h') \
KEYWORD("hash", Token::HASH) \ KEYWORD("hash", Token::HASH) \
KEYWORD("hash8", Token::HASH8) \
KEYWORD("hash16", Token::HASH16) \
KEYWORD("hash24", Token::HASH24) \
KEYWORD("hash32", Token::HASH32) \ KEYWORD("hash32", Token::HASH32) \
KEYWORD("hash40", Token::HASH40) \
KEYWORD("hash48", Token::HASH48) \
KEYWORD("hash56", Token::HASH56) \
KEYWORD("hash64", Token::HASH64) \ KEYWORD("hash64", Token::HASH64) \
KEYWORD("hash72", Token::HASH72) \
KEYWORD("hash80", Token::HASH80) \
KEYWORD("hash88", Token::HASH88) \
KEYWORD("hash96", Token::HASH96) \
KEYWORD("hash104", Token::HASH104) \
KEYWORD("hash112", Token::HASH112) \
KEYWORD("hash120", Token::HASH120) \
KEYWORD("hash128", Token::HASH128) \ KEYWORD("hash128", Token::HASH128) \
KEYWORD("hash136", Token::HASH136) \
KEYWORD("hash144", Token::HASH144) \
KEYWORD("hash152", Token::HASH152) \
KEYWORD("hash160", Token::HASH160) \
KEYWORD("hash168", Token::HASH168) \
KEYWORD("hash178", Token::HASH176) \
KEYWORD("hash184", Token::HASH184) \
KEYWORD("hash192", Token::HASH192) \
KEYWORD("hash200", Token::HASH200) \
KEYWORD("hash208", Token::HASH208) \
KEYWORD("hash216", Token::HASH216) \
KEYWORD("hash224", Token::HASH224) \
KEYWORD("hash232", Token::HASH232) \
KEYWORD("hash240", Token::HASH240) \
KEYWORD("hash248", Token::HASH248) \
KEYWORD("hash256", Token::HASH256) \ KEYWORD("hash256", Token::HASH256) \
KEYWORD_GROUP('i') \ KEYWORD_GROUP('i') \
KEYWORD("if", Token::IF) \ KEYWORD("if", Token::IF) \
KEYWORD("in", Token::IN) \ KEYWORD("in", Token::IN) \
KEYWORD("int", Token::INT) \ KEYWORD("int", Token::INT) \
KEYWORD("int8", Token::INT8) \
KEYWORD("int16", Token::INT16) \
KEYWORD("int24", Token::INT24) \
KEYWORD("int32", Token::INT32) \ KEYWORD("int32", Token::INT32) \
KEYWORD("int40", Token::INT40) \
KEYWORD("int48", Token::INT48) \
KEYWORD("int56", Token::INT56) \
KEYWORD("int64", Token::INT64) \ KEYWORD("int64", Token::INT64) \
KEYWORD("int72", Token::INT72) \
KEYWORD("int80", Token::INT80) \
KEYWORD("int88", Token::INT88) \
KEYWORD("int96", Token::INT96) \
KEYWORD("int104", Token::INT104) \
KEYWORD("int112", Token::INT112) \
KEYWORD("int120", Token::INT120) \
KEYWORD("int128", Token::INT128) \ KEYWORD("int128", Token::INT128) \
KEYWORD("int136", Token::INT136) \
KEYWORD("int144", Token::INT144) \
KEYWORD("int152", Token::INT152) \
KEYWORD("int160", Token::INT160) \
KEYWORD("int168", Token::INT168) \
KEYWORD("int178", Token::INT176) \
KEYWORD("int184", Token::INT184) \
KEYWORD("int192", Token::INT192) \
KEYWORD("int200", Token::INT200) \
KEYWORD("int208", Token::INT208) \
KEYWORD("int216", Token::INT216) \
KEYWORD("int224", Token::INT224) \
KEYWORD("int232", Token::INT232) \
KEYWORD("int240", Token::INT240) \
KEYWORD("int248", Token::INT248) \
KEYWORD("int256", Token::INT256) \ KEYWORD("int256", Token::INT256) \
KEYWORD_GROUP('l') \ KEYWORD_GROUP('l') \
KEYWORD_GROUP('m') \ KEYWORD_GROUP('m') \
@ -591,9 +647,37 @@ Token::Value Scanner::scanNumber(bool _periodSeen)
KEYWORD("true", Token::TRUE_LITERAL) \ KEYWORD("true", Token::TRUE_LITERAL) \
KEYWORD_GROUP('u') \ KEYWORD_GROUP('u') \
KEYWORD("uint", Token::UINT) \ KEYWORD("uint", Token::UINT) \
KEYWORD("uint8", Token::UINT8) \
KEYWORD("uint16", Token::UINT16) \
KEYWORD("uint24", Token::UINT24) \
KEYWORD("uint32", Token::UINT32) \ KEYWORD("uint32", Token::UINT32) \
KEYWORD("uint40", Token::UINT40) \
KEYWORD("uint48", Token::UINT48) \
KEYWORD("uint56", Token::UINT56) \
KEYWORD("uint64", Token::UINT64) \ KEYWORD("uint64", Token::UINT64) \
KEYWORD("uint72", Token::UINT72) \
KEYWORD("uint80", Token::UINT80) \
KEYWORD("uint88", Token::UINT88) \
KEYWORD("uint96", Token::UINT96) \
KEYWORD("uint104", Token::UINT104) \
KEYWORD("uint112", Token::UINT112) \
KEYWORD("uint120", Token::UINT120) \
KEYWORD("uint128", Token::UINT128) \ KEYWORD("uint128", Token::UINT128) \
KEYWORD("uint136", Token::UINT136) \
KEYWORD("uint144", Token::UINT144) \
KEYWORD("uint152", Token::UINT152) \
KEYWORD("uint160", Token::UINT160) \
KEYWORD("uint168", Token::UINT168) \
KEYWORD("uint178", Token::UINT176) \
KEYWORD("uint184", Token::UINT184) \
KEYWORD("uint192", Token::UINT192) \
KEYWORD("uint200", Token::UINT200) \
KEYWORD("uint208", Token::UINT208) \
KEYWORD("uint216", Token::UINT216) \
KEYWORD("uint224", Token::UINT224) \
KEYWORD("uint232", Token::UINT232) \
KEYWORD("uint240", Token::UINT240) \
KEYWORD("uint248", Token::UINT248) \
KEYWORD("uint256", Token::UINT256) \ KEYWORD("uint256", Token::UINT256) \
KEYWORD("ureal", Token::UREAL) \ KEYWORD("ureal", Token::UREAL) \
KEYWORD_GROUP('v') \ KEYWORD_GROUP('v') \

2
libsolidity/Scanner.h

@ -180,7 +180,7 @@ private:
Token::Value skipMultiLineComment(); Token::Value skipMultiLineComment();
void scanDecimalDigits(); void scanDecimalDigits();
Token::Value scanNumber(bool _periodSeen); Token::Value scanNumber(char _charSeen = 0);
Token::Value scanIdentifierOrKeyword(); Token::Value scanIdentifierOrKeyword();
Token::Value scanString(); Token::Value scanString();

84
libsolidity/Token.h

@ -169,19 +169,103 @@ namespace solidity
* the implementation in Types.cpp has to be synced to this here * the implementation in Types.cpp has to be synced to this here
* TODO more to be added */ \ * TODO more to be added */ \
K(INT, "int", 0) \ K(INT, "int", 0) \
K(INT8, "int8", 0) \
K(INT16, "int16", 0) \
K(INT24, "int24", 0) \
K(INT32, "int32", 0) \ K(INT32, "int32", 0) \
K(INT40, "int40", 0) \
K(INT48, "int48", 0) \
K(INT56, "int56", 0) \
K(INT64, "int64", 0) \ K(INT64, "int64", 0) \
K(INT72, "int72", 0) \
K(INT80, "int80", 0) \
K(INT88, "int88", 0) \
K(INT96, "int96", 0) \
K(INT104, "int104", 0) \
K(INT112, "int112", 0) \
K(INT120, "int120", 0) \
K(INT128, "int128", 0) \ K(INT128, "int128", 0) \
K(INT136, "int136", 0) \
K(INT144, "int144", 0) \
K(INT152, "int152", 0) \
K(INT160, "int160", 0) \
K(INT168, "int168", 0) \
K(INT176, "int178", 0) \
K(INT184, "int184", 0) \
K(INT192, "int192", 0) \
K(INT200, "int200", 0) \
K(INT208, "int208", 0) \
K(INT216, "int216", 0) \
K(INT224, "int224", 0) \
K(INT232, "int232", 0) \
K(INT240, "int240", 0) \
K(INT248, "int248", 0) \
K(INT256, "int256", 0) \ K(INT256, "int256", 0) \
K(UINT, "uint", 0) \ K(UINT, "uint", 0) \
K(UINT8, "uint8", 0) \
K(UINT16, "uint16", 0) \
K(UINT24, "uint24", 0) \
K(UINT32, "uint32", 0) \ K(UINT32, "uint32", 0) \
K(UINT40, "uint40", 0) \
K(UINT48, "uint48", 0) \
K(UINT56, "uint56", 0) \
K(UINT64, "uint64", 0) \ K(UINT64, "uint64", 0) \
K(UINT72, "uint72", 0) \
K(UINT80, "uint80", 0) \
K(UINT88, "uint88", 0) \
K(UINT96, "uint96", 0) \
K(UINT104, "uint104", 0) \
K(UINT112, "uint112", 0) \
K(UINT120, "uint120", 0) \
K(UINT128, "uint128", 0) \ K(UINT128, "uint128", 0) \
K(UINT136, "uint136", 0) \
K(UINT144, "uint144", 0) \
K(UINT152, "uint152", 0) \
K(UINT160, "uint160", 0) \
K(UINT168, "uint168", 0) \
K(UINT176, "uint178", 0) \
K(UINT184, "uint184", 0) \
K(UINT192, "uint192", 0) \
K(UINT200, "uint200", 0) \
K(UINT208, "uint208", 0) \
K(UINT216, "uint216", 0) \
K(UINT224, "uint224", 0) \
K(UINT232, "uint232", 0) \
K(UINT240, "uint240", 0) \
K(UINT248, "uint248", 0) \
K(UINT256, "uint256", 0) \ K(UINT256, "uint256", 0) \
K(HASH, "hash", 0) \ K(HASH, "hash", 0) \
K(HASH8, "hash8", 0) \
K(HASH16, "hash16", 0) \
K(HASH24, "hash24", 0) \
K(HASH32, "hash32", 0) \ K(HASH32, "hash32", 0) \
K(HASH40, "hash40", 0) \
K(HASH48, "hash48", 0) \
K(HASH56, "hash56", 0) \
K(HASH64, "hash64", 0) \ K(HASH64, "hash64", 0) \
K(HASH72, "hash72", 0) \
K(HASH80, "hash80", 0) \
K(HASH88, "hash88", 0) \
K(HASH96, "hash96", 0) \
K(HASH104, "hash104", 0) \
K(HASH112, "hash112", 0) \
K(HASH120, "hash120", 0) \
K(HASH128, "hash128", 0) \ K(HASH128, "hash128", 0) \
K(HASH136, "hash136", 0) \
K(HASH144, "hash144", 0) \
K(HASH152, "hash152", 0) \
K(HASH160, "hash160", 0) \
K(HASH168, "hash168", 0) \
K(HASH176, "hash178", 0) \
K(HASH184, "hash184", 0) \
K(HASH192, "hash192", 0) \
K(HASH200, "hash200", 0) \
K(HASH208, "hash208", 0) \
K(HASH216, "hash216", 0) \
K(HASH224, "hash224", 0) \
K(HASH232, "hash232", 0) \
K(HASH240, "hash240", 0) \
K(HASH248, "hash248", 0) \
K(HASH256, "hash256", 0) \ K(HASH256, "hash256", 0) \
K(ADDRESS, "address", 0) \ K(ADDRESS, "address", 0) \
K(BOOL, "bool", 0) \ K(BOOL, "bool", 0) \

57
libsolidity/Types.cpp

@ -25,12 +25,14 @@
#include <libsolidity/Types.h> #include <libsolidity/Types.h>
#include <libsolidity/AST.h> #include <libsolidity/AST.h>
using namespace std;
namespace dev namespace dev
{ {
namespace solidity namespace solidity
{ {
std::shared_ptr<Type> Type::fromElementaryTypeName(Token::Value _typeToken) shared_ptr<Type> Type::fromElementaryTypeName(Token::Value _typeToken)
{ {
if (asserts(Token::isElementaryTypeName(_typeToken))) if (asserts(Token::isElementaryTypeName(_typeToken)))
BOOST_THROW_EXCEPTION(InternalCompilerError()); BOOST_THROW_EXCEPTION(InternalCompilerError());
@ -38,58 +40,63 @@ std::shared_ptr<Type> Type::fromElementaryTypeName(Token::Value _typeToken)
if (Token::INT <= _typeToken && _typeToken <= Token::HASH256) if (Token::INT <= _typeToken && _typeToken <= Token::HASH256)
{ {
int offset = _typeToken - Token::INT; int offset = _typeToken - Token::INT;
int bits = offset % 5; int bytes = offset % 33;
if (bits == 0) if (bytes == 0)
bits = 256; bytes = 32;
else int modifier = offset / 33;
bits = (1 << (bits - 1)) * 32; return make_shared<IntegerType>(bytes * 8,
int modifier = offset / 5;
return std::make_shared<IntegerType>(bits,
modifier == 0 ? IntegerType::Modifier::SIGNED : modifier == 0 ? IntegerType::Modifier::SIGNED :
modifier == 1 ? IntegerType::Modifier::UNSIGNED : modifier == 1 ? IntegerType::Modifier::UNSIGNED :
IntegerType::Modifier::HASH); IntegerType::Modifier::HASH);
} }
else if (_typeToken == Token::ADDRESS) else if (_typeToken == Token::ADDRESS)
return std::make_shared<IntegerType>(0, IntegerType::Modifier::ADDRESS); return make_shared<IntegerType>(0, IntegerType::Modifier::ADDRESS);
else if (_typeToken == Token::BOOL) else if (_typeToken == Token::BOOL)
return std::make_shared<BoolType>(); return make_shared<BoolType>();
else else
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unable to convert elementary typename " + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unable to convert elementary typename " +
std::string(Token::toString(_typeToken)) + " to type.")); std::string(Token::toString(_typeToken)) + " to type."));
return std::shared_ptr<Type>(); return shared_ptr<Type>();
} }
std::shared_ptr<Type> Type::fromUserDefinedTypeName(UserDefinedTypeName const& _typeName) shared_ptr<Type> Type::fromUserDefinedTypeName(UserDefinedTypeName const& _typeName)
{ {
return std::make_shared<StructType>(*_typeName.getReferencedStruct()); return make_shared<StructType>(*_typeName.getReferencedStruct());
} }
std::shared_ptr<Type> Type::fromMapping(Mapping const&) shared_ptr<Type> Type::fromMapping(Mapping const&)
{ {
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Mapping types not yet implemented.")); BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Mapping types not yet implemented."));
return std::shared_ptr<Type>(); return shared_ptr<Type>();
} }
std::shared_ptr<Type> Type::forLiteral(Literal const& _literal) shared_ptr<Type> Type::forLiteral(Literal const& _literal)
{ {
switch (_literal.getToken()) switch (_literal.getToken())
{ {
case Token::TRUE_LITERAL: case Token::TRUE_LITERAL:
case Token::FALSE_LITERAL: case Token::FALSE_LITERAL:
return std::make_shared<BoolType>(); return make_shared<BoolType>();
case Token::NUMBER: case Token::NUMBER:
return IntegerType::smallestTypeForLiteral(_literal.getValue()); return IntegerType::smallestTypeForLiteral(_literal.getValue());
case Token::STRING_LITERAL: case Token::STRING_LITERAL:
return std::shared_ptr<Type>(); // @todo return shared_ptr<Type>(); // @todo
default: default:
return std::shared_ptr<Type>(); return shared_ptr<Type>();
} }
} }
std::shared_ptr<IntegerType> IntegerType::smallestTypeForLiteral(std::string const&) shared_ptr<IntegerType> IntegerType::smallestTypeForLiteral(string const& _literal)
{ {
//@todo bigint value(_literal);
return std::make_shared<IntegerType>(256, Modifier::UNSIGNED); bool isSigned = value < 0 || (!_literal.empty() && _literal.front() == '-');
if (isSigned)
// convert to positive number of same bit requirements
value = ((-value) - 1) << 1;
unsigned bytes = max(bytesRequired(value), 1u);
if (bytes > 32)
return shared_ptr<IntegerType>();
return make_shared<IntegerType>(bytes * 8, isSigned ? Modifier::SIGNED : Modifier::UNSIGNED);
} }
IntegerType::IntegerType(int _bits, IntegerType::Modifier _modifier): IntegerType::IntegerType(int _bits, IntegerType::Modifier _modifier):
@ -155,19 +162,17 @@ bool IntegerType::operator==(Type const& _other) const
return other.m_bits == m_bits && other.m_modifier == m_modifier; return other.m_bits == m_bits && other.m_modifier == m_modifier;
} }
std::string IntegerType::toString() const string IntegerType::toString() const
{ {
if (isAddress()) if (isAddress())
return "address"; return "address";
std::string prefix = isHash() ? "hash" : (isSigned() ? "int" : "uint"); string prefix = isHash() ? "hash" : (isSigned() ? "int" : "uint");
return prefix + dev::toString(m_bits); return prefix + dev::toString(m_bits);
} }
u256 IntegerType::literalValue(Literal const& _literal) const u256 IntegerType::literalValue(Literal const& _literal) const
{ {
bigint value(_literal.getValue()); bigint value(_literal.getValue());
//@todo check that the number is not too large
//@todo does this work for signed numbers?
return u256(value); return u256(value);
} }

5
libsolidity/Types.h

@ -56,7 +56,8 @@ public:
static std::shared_ptr<Type> fromMapping(Mapping const& _typeName); static std::shared_ptr<Type> fromMapping(Mapping const& _typeName);
/// @} /// @}
/// Auto-detect the proper type for a literal /// Auto-detect the proper type for a literal. @returns an empty pointer if the literal does
/// not fit any type.
static std::shared_ptr<Type> forLiteral(Literal const& _literal); static std::shared_ptr<Type> forLiteral(Literal const& _literal);
virtual Category getCategory() const = 0; virtual Category getCategory() const = 0;
@ -95,6 +96,8 @@ public:
}; };
virtual Category getCategory() const override { return Category::INTEGER; } virtual Category getCategory() const override { return Category::INTEGER; }
/// @returns the smallest integer type for the given literal or an empty pointer
/// if no type fits.
static std::shared_ptr<IntegerType> smallestTypeForLiteral(std::string const& _literal); static std::shared_ptr<IntegerType> smallestTypeForLiteral(std::string const& _literal);
explicit IntegerType(int _bits, Modifier _modifier = Modifier::UNSIGNED); explicit IntegerType(int _bits, Modifier _modifier = Modifier::UNSIGNED);

22
libweb3jsonrpc/WebThreeStubServer.cpp

@ -22,7 +22,7 @@
*/ */
#include "WebThreeStubServer.h" #include "WebThreeStubServer.h"
#include <libevmface/Instruction.h> #include <libevmcore/Instruction.h>
#include <liblll/Compiler.h> #include <liblll/Compiler.h>
#include <libethereum/Client.h> #include <libethereum/Client.h>
#include <libwebthree/WebThree.h> #include <libwebthree/WebThree.h>
@ -213,7 +213,7 @@ static shh::Message toMessage(Json::Value const& _json)
if (!_json["to"].empty()) if (!_json["to"].empty())
ret.setTo(jsToPublic(_json["to"].asString())); ret.setTo(jsToPublic(_json["to"].asString()));
if (!_json["payload"].empty()) if (!_json["payload"].empty())
ret.setPayload(asBytes(_json["payload"].asString())); ret.setPayload(jsToBytes(_json["payload"].asString()));
return ret; return ret;
} }
@ -230,10 +230,10 @@ static shh::Envelope toSealed(Json::Value const& _json, shh::Message const& _m,
if (!_json["topic"].empty()) if (!_json["topic"].empty())
{ {
if (_json["topic"].isString()) if (_json["topic"].isString())
bt.shift(asBytes(jsPadded(_json["topic"].asString(), 32))); bt.shift(jsToBytes(_json["topic"].asString()));
else if (_json["topic"].isArray()) else if (_json["topic"].isArray())
for (auto i: _json["topic"]) for (auto i: _json["topic"])
bt.shift(asBytes(jsPadded(i.asString(), 32))); bt.shift(jsToBytes(i.asString()));
} }
return _m.seal(_from, bt, ttl, workToProve); return _m.seal(_from, bt, ttl, workToProve);
} }
@ -249,12 +249,12 @@ static pair<shh::TopicMask, Public> toWatch(Json::Value const& _json)
if (!_json["topic"].empty()) if (!_json["topic"].empty())
{ {
if (_json["topic"].isString()) if (_json["topic"].isString())
bt.shift(asBytes(jsPadded(_json["topic"].asString(), 32))); bt.shift(jsToBytes(_json["topic"].asString()));
else if (_json["topic"].isArray()) else if (_json["topic"].isArray())
for (auto i: _json["topic"]) for (auto i: _json["topic"])
{ {
if (i.isString()) if (i.isString())
bt.shift(asBytes(jsPadded(i.asString(), 32))); bt.shift(jsToBytes(i.asString()));
else else
bt.shift(); bt.shift();
} }
@ -271,7 +271,7 @@ static Json::Value toJson(h256 const& _h, shh::Envelope const& _e, shh::Message
res["ttl"] = (int)_e.ttl(); res["ttl"] = (int)_e.ttl();
res["workProved"] = (int)_e.workProved(); res["workProved"] = (int)_e.workProved();
res["topic"] = toJS(_e.topic()); res["topic"] = toJS(_e.topic());
res["payload"] = asString(_m.payload()); res["payload"] = toJS(_m.payload());
res["from"] = toJS(_m.from()); res["from"] = toJS(_m.from());
res["to"] = toJS(_m.to()); res["to"] = toJS(_m.to());
return res; return res;
@ -374,10 +374,10 @@ static TransactionSkeleton toTransaction(Json::Value const& _json)
ret.data = jsToBytes(_json["code"].asString()); ret.data = jsToBytes(_json["code"].asString());
else if (_json["data"].isArray()) else if (_json["data"].isArray())
for (auto i: _json["data"]) for (auto i: _json["data"])
dev::operator +=(ret.data, asBytes(jsPadded(i.asString(), 32))); dev::operator +=(ret.data, jsToBytes(jsPadded(i.asString(), 32)));
else if (_json["code"].isArray()) else if (_json["code"].isArray())
for (auto i: _json["code"]) for (auto i: _json["code"])
dev::operator +=(ret.data, asBytes(jsPadded(i.asString(), 32))); dev::operator +=(ret.data, jsToBytes(jsPadded(i.asString(), 32)));
else if (_json["dataclose"].isArray()) else if (_json["dataclose"].isArray())
for (auto i: _json["dataclose"]) for (auto i: _json["dataclose"])
dev::operator +=(ret.data, jsToBytes(i.asString())); dev::operator +=(ret.data, jsToBytes(i.asString()));
@ -511,6 +511,7 @@ std::string WebThreeStubServer::shh_newGroup(std::string const& _id, std::string
std::string WebThreeStubServer::shh_newIdentity() std::string WebThreeStubServer::shh_newIdentity()
{ {
cnote << this << m_ids;
KeyPair kp = KeyPair::create(); KeyPair kp = KeyPair::create();
m_ids[kp.pub()] = kp.secret(); m_ids[kp.pub()] = kp.secret();
return toJS(kp.pub()); return toJS(kp.pub());
@ -538,6 +539,7 @@ int WebThreeStubServer::eth_peerCount()
bool WebThreeStubServer::shh_post(Json::Value const& _json) bool WebThreeStubServer::shh_post(Json::Value const& _json)
{ {
cnote << this << m_ids;
shh::Message m = toMessage(_json); shh::Message m = toMessage(_json);
Secret from; Secret from;
@ -623,7 +625,7 @@ Json::Value WebThreeStubServer::shh_changed(int const& _id)
} }
else else
m = e.open(); m = e.open();
ret.append(toJson(h,e,m)); ret.append(toJson(h, e, m));
} }
return ret; return ret;

2
lllc/CMakeLists.txt

@ -9,7 +9,7 @@ set(EXECUTABLE lllc)
add_executable(${EXECUTABLE} ${SRC_LIST}) add_executable(${EXECUTABLE} ${SRC_LIST})
target_link_libraries(${EXECUTABLE} lll) target_link_libraries(${EXECUTABLE} lll)
target_link_libraries(${EXECUTABLE} evmface) target_link_libraries(${EXECUTABLE} evmcore)
target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcore)
if ("${TARGET_PLATFORM}" STREQUAL "w64") if ("${TARGET_PLATFORM}" STREQUAL "w64")

2
lllc/main.cpp

@ -25,7 +25,7 @@
#include <liblll/Compiler.h> #include <liblll/Compiler.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libdevcore/CommonData.h> #include <libdevcore/CommonData.h>
#include <libevmface/Instruction.h> #include <libevmcore/Instruction.h>
#include "BuildInfo.h" #include "BuildInfo.h"
using namespace std; using namespace std;
using namespace dev; using namespace dev;

2
neth/main.cpp

@ -30,7 +30,7 @@
#include <jsonrpc/connectors/httpserver.h> #include <jsonrpc/connectors/httpserver.h>
#endif #endif
#include <libdevcrypto/FileSystem.h> #include <libdevcrypto/FileSystem.h>
#include <libevmface/Instruction.h> #include <libevmcore/Instruction.h>
#include <libethereum/All.h> #include <libethereum/All.h>
#if ETH_JSONRPC #if ETH_JSONRPC
#include <libweb3jsonrpc/WebThreeStubServer.h> #include <libweb3jsonrpc/WebThreeStubServer.h>

2
sc/CMakeLists.txt

@ -10,7 +10,7 @@ add_executable(${EXECUTABLE} ${SRC_LIST})
target_link_libraries(${EXECUTABLE} serpent) target_link_libraries(${EXECUTABLE} serpent)
target_link_libraries(${EXECUTABLE} lll) target_link_libraries(${EXECUTABLE} lll)
target_link_libraries(${EXECUTABLE} evmface) target_link_libraries(${EXECUTABLE} evmcore)
target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcore)
if ("${TARGET_PLATFORM}" STREQUAL "w64") if ("${TARGET_PLATFORM}" STREQUAL "w64")

8
stdserv.js

@ -55,6 +55,14 @@ eth.transact({ 'code': nameRegCode }, function(a) { nameReg = a; });
env.note('Register NameReg...') env.note('Register NameReg...')
eth.transact({ 'to': config, 'data': ['0', nameReg] }); eth.transact({ 'to': config, 'data': ['0', nameReg] });
var nameRegJeff;
env.note('Create NameRegJeff...')
eth.transact({ 'code': nameRegCode }, function(a) { nameRegJeff = a; });
env.note('Register NameRegJeff...')
eth.transact({ 'to': config, 'data': ['4', nameReg] });
var dnsRegCode = '0x60006000546000600053602001546000600053604001546020604060206020600073661005d2720d855f1d9976f88bb10c1a3398c77f6103e8f17f7265676973746572000000000000000000000000000000000000000000000000600053606001600060200201547f446e735265670000000000000000000000000000000000000000000000000000600053606001600160200201546000600060006000604060606000600053604001536103e8f1327f6f776e65720000000000000000000000000000000000000000000000000000005761011663000000e46000396101166000f20060006000547f72656769737465720000000000000000000000000000000000000000000000006000602002350e0f630000006d596000600160200235560e0f630000006c59600032560e0f0f6300000057596000325657600260200235600160200235576001602002353257007f64657265676973746572000000000000000000000000000000000000000000006000602002350e0f63000000b95960016020023532560e0f63000000b959600032576000600160200235577f6b696c6c000000000000000000000000000000000000000000000000000000006000602002350e0f630000011559327f6f776e6572000000000000000000000000000000000000000000000000000000560e0f63000001155932ff00'; var dnsRegCode = '0x60006000546000600053602001546000600053604001546020604060206020600073661005d2720d855f1d9976f88bb10c1a3398c77f6103e8f17f7265676973746572000000000000000000000000000000000000000000000000600053606001600060200201547f446e735265670000000000000000000000000000000000000000000000000000600053606001600160200201546000600060006000604060606000600053604001536103e8f1327f6f776e65720000000000000000000000000000000000000000000000000000005761011663000000e46000396101166000f20060006000547f72656769737465720000000000000000000000000000000000000000000000006000602002350e0f630000006d596000600160200235560e0f630000006c59600032560e0f0f6300000057596000325657600260200235600160200235576001602002353257007f64657265676973746572000000000000000000000000000000000000000000006000602002350e0f63000000b95960016020023532560e0f63000000b959600032576000600160200235577f6b696c6c000000000000000000000000000000000000000000000000000000006000602002350e0f630000011559327f6f776e6572000000000000000000000000000000000000000000000000000000560e0f63000001155932ff00';
var dnsReg; var dnsReg;

2
test/createRandomTest.cpp

@ -31,7 +31,7 @@
#include <json_spirit/json_spirit_writer_template.h> #include <json_spirit/json_spirit_writer_template.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libdevcore/CommonData.h> #include <libdevcore/CommonData.h>
#include <libevmface/Instruction.h> #include <libevmcore/Instruction.h>
#include "vm.h" #include "vm.h"
using namespace std; using namespace std;

8
test/solidityCompiler.cpp

@ -119,10 +119,10 @@ BOOST_AUTO_TEST_CASE(different_argument_numbers)
byte(Instruction::JUMPDEST), // beginning of g byte(Instruction::JUMPDEST), // beginning of g
byte(Instruction::PUSH1), 0x0, byte(Instruction::PUSH1), 0x0,
byte(Instruction::DUP1), // initialized e and h byte(Instruction::DUP1), // initialized e and h
byte(Instruction::PUSH1), byte(0x20 + shift), // ret address byte(Instruction::PUSH1), byte(0x29 + shift), // ret address
byte(Instruction::PUSH1), 0x1, byte(Instruction::PUSH1), 0x1, byte(Instruction::PUSH1), 0xff, byte(Instruction::AND),
byte(Instruction::PUSH1), 0x2, byte(Instruction::PUSH1), 0x2, byte(Instruction::PUSH1), 0xff, byte(Instruction::AND),
byte(Instruction::PUSH1), 0x3, byte(Instruction::PUSH1), 0x3, byte(Instruction::PUSH1), 0xff, byte(Instruction::AND),
byte(Instruction::PUSH1), byte(0x1 + shift), byte(Instruction::PUSH1), byte(0x1 + shift),
// stack here: ret e h 0x20 1 2 3 0x1 // stack here: ret e h 0x20 1 2 3 0x1
byte(Instruction::JUMP), byte(Instruction::JUMP),

192
test/solidityEndToEndTest.cpp

@ -41,31 +41,31 @@ class ExecutionFramework
public: public:
ExecutionFramework() { g_logVerbosity = 0; } ExecutionFramework() { g_logVerbosity = 0; }
bytes compileAndRun(std::string const& _sourceCode) bytes const& compileAndRun(std::string const& _sourceCode)
{ {
bytes code = dev::solidity::CompilerStack::compile(_sourceCode); bytes code = dev::solidity::CompilerStack::compile(_sourceCode);
sendMessage(code, true); sendMessage(code, true);
BOOST_REQUIRE(!m_output.empty());
return m_output; return m_output;
} }
bytes callFunction(byte _index, bytes const& _data) bytes const& callFunction(byte _index, bytes const& _data)
{ {
sendMessage(bytes(1, _index) + _data, false); sendMessage(bytes(1, _index) + _data, false);
return m_output; return m_output;
} }
bytes callFunction(byte _index, u256 const& _argument1) bytes const& callFunction(byte _index, u256 const& _argument1)
{ {
callFunction(_index, toBigEndian(_argument1)); return callFunction(_index, toBigEndian(_argument1));
return m_output;
} }
private: private:
void sendMessage(bytes const& _data, bool _isCreation) void sendMessage(bytes const& _data, bool _isCreation)
{ {
eth::Executive executive(m_state); eth::Executive executive(m_state);
eth::Transaction t = _isCreation ? eth::Transaction(0, m_gasPrice, m_gas, _data) eth::Transaction t = _isCreation ? eth::Transaction(0, m_gasPrice, m_gas, _data, 0, KeyPair::create().sec())
: eth::Transaction(0, m_gasPrice, m_gas, m_contractAddress, _data); : eth::Transaction(0, m_gasPrice, m_gas, m_contractAddress, _data, 0, KeyPair::create().sec());
bytes transactionRLP = t.rlp(); bytes transactionRLP = t.rlp();
try try
{ {
@ -77,13 +77,14 @@ private:
{ {
BOOST_REQUIRE(!executive.create(Address(), 0, m_gasPrice, m_gas, &_data, Address())); BOOST_REQUIRE(!executive.create(Address(), 0, m_gasPrice, m_gas, &_data, Address()));
m_contractAddress = executive.newAddress(); m_contractAddress = executive.newAddress();
BOOST_REQUIRE(m_contractAddress);
BOOST_REQUIRE(m_state.addressHasCode(m_contractAddress)); BOOST_REQUIRE(m_state.addressHasCode(m_contractAddress));
} }
else else
BOOST_REQUIRE(!executive.call(m_contractAddress, Address(), 0, m_gasPrice, &_data, m_gas, Address())); BOOST_REQUIRE(!executive.call(m_contractAddress, Address(), 0, m_gasPrice, &_data, m_gas, Address()));
BOOST_REQUIRE(executive.go()); BOOST_REQUIRE(executive.go());
executive.finalize(); executive.finalize();
m_output = executive.out().toBytes(); m_output = executive.out().toVector();
} }
Address m_contractAddress; Address m_contractAddress;
@ -93,27 +94,24 @@ private:
bytes m_output; bytes m_output;
}; };
BOOST_AUTO_TEST_SUITE(SolidityCompilerEndToEndTest) BOOST_FIXTURE_TEST_SUITE(SolidityCompilerEndToEndTest, ExecutionFramework)
BOOST_AUTO_TEST_CASE(smoke_test) BOOST_AUTO_TEST_CASE(smoke_test)
{ {
char const* sourceCode = "contract test {\n" char const* sourceCode = "contract test {\n"
" function f(uint a) returns(uint d) { return a * 7; }\n" " function f(uint a) returns(uint d) { return a * 7; }\n"
"}\n"; "}\n";
ExecutionFramework framework; compileAndRun(sourceCode);
framework.compileAndRun(sourceCode);
u256 a = 0x200030004; u256 a = 0x200030004;
bytes result = framework.callFunction(0, a); BOOST_CHECK(callFunction(0, a) == toBigEndian(a * 7));
BOOST_CHECK(result == toBigEndian(a * 7));
} }
BOOST_AUTO_TEST_CASE(empty_contract) BOOST_AUTO_TEST_CASE(empty_contract)
{ {
char const* sourceCode = "contract test {\n" char const* sourceCode = "contract test {\n"
"}\n"; "}\n";
ExecutionFramework framework; compileAndRun(sourceCode);
framework.compileAndRun(sourceCode); BOOST_CHECK(callFunction(0, bytes()).empty());
BOOST_CHECK(framework.callFunction(0, bytes()).empty());
} }
BOOST_AUTO_TEST_CASE(recursive_calls) BOOST_AUTO_TEST_CASE(recursive_calls)
@ -124,13 +122,12 @@ BOOST_AUTO_TEST_CASE(recursive_calls)
" else return n * f(n - 1);\n" " else return n * f(n - 1);\n"
" }\n" " }\n"
"}\n"; "}\n";
ExecutionFramework framework; compileAndRun(sourceCode);
framework.compileAndRun(sourceCode); BOOST_CHECK(callFunction(0, u256(0)) == toBigEndian(u256(1)));
BOOST_CHECK(framework.callFunction(0, u256(0)) == toBigEndian(u256(1))); BOOST_CHECK(callFunction(0, u256(1)) == toBigEndian(u256(1)));
BOOST_CHECK(framework.callFunction(0, u256(1)) == toBigEndian(u256(1))); BOOST_CHECK(callFunction(0, u256(2)) == toBigEndian(u256(2)));
BOOST_CHECK(framework.callFunction(0, u256(2)) == toBigEndian(u256(2))); BOOST_CHECK(callFunction(0, u256(3)) == toBigEndian(u256(6)));
BOOST_CHECK(framework.callFunction(0, u256(3)) == toBigEndian(u256(6))); BOOST_CHECK(callFunction(0, u256(4)) == toBigEndian(u256(24)));
BOOST_CHECK(framework.callFunction(0, u256(4)) == toBigEndian(u256(24)));
} }
BOOST_AUTO_TEST_CASE(while_loop) BOOST_AUTO_TEST_CASE(while_loop)
@ -142,13 +139,61 @@ BOOST_AUTO_TEST_CASE(while_loop)
" while (i <= n) nfac *= i++;\n" " while (i <= n) nfac *= i++;\n"
" }\n" " }\n"
"}\n"; "}\n";
compileAndRun(sourceCode);
BOOST_CHECK(callFunction(0, u256(0)) == toBigEndian(u256(1)));
BOOST_CHECK(callFunction(0, u256(1)) == toBigEndian(u256(1)));
BOOST_CHECK(callFunction(0, u256(2)) == toBigEndian(u256(2)));
BOOST_CHECK(callFunction(0, u256(3)) == toBigEndian(u256(6)));
BOOST_CHECK(callFunction(0, u256(4)) == toBigEndian(u256(24)));
}
BOOST_AUTO_TEST_CASE(break_outside_loop)
{
// break and continue outside loops should be simply ignored
char const* sourceCode = "contract test {\n"
" function f(uint x) returns(uint y) {\n"
" break; continue; return 2;\n"
" }\n"
"}\n";
ExecutionFramework framework;
framework.compileAndRun(sourceCode);
BOOST_CHECK(framework.callFunction(0, u256(0)) == toBigEndian(u256(2)));
}
BOOST_AUTO_TEST_CASE(nested_loops)
{
// tests that break and continue statements in nested loops jump to the correct place
char const* sourceCode = "contract test {\n"
" function f(uint x) returns(uint y) {\n"
" while (x > 1) {\n"
" if (x == 10) break;\n"
" while (x > 5) {\n"
" if (x == 8) break;\n"
" x--;\n"
" if (x == 6) continue;\n"
" return x;\n"
" }\n"
" x--;\n"
" if (x == 3) continue;\n"
" break;\n"
" }\n"
" return x;\n"
" }\n"
"}\n";
ExecutionFramework framework; ExecutionFramework framework;
framework.compileAndRun(sourceCode); framework.compileAndRun(sourceCode);
BOOST_CHECK(framework.callFunction(0, u256(0)) == toBigEndian(u256(1))); BOOST_CHECK(framework.callFunction(0, u256(0)) == toBigEndian(u256(0)));
BOOST_CHECK(framework.callFunction(0, u256(1)) == toBigEndian(u256(1))); BOOST_CHECK(framework.callFunction(0, u256(1)) == toBigEndian(u256(1)));
BOOST_CHECK(framework.callFunction(0, u256(2)) == toBigEndian(u256(2))); BOOST_CHECK(framework.callFunction(0, u256(2)) == toBigEndian(u256(1)));
BOOST_CHECK(framework.callFunction(0, u256(3)) == toBigEndian(u256(6))); BOOST_CHECK(framework.callFunction(0, u256(3)) == toBigEndian(u256(2)));
BOOST_CHECK(framework.callFunction(0, u256(4)) == toBigEndian(u256(24))); BOOST_CHECK(framework.callFunction(0, u256(4)) == toBigEndian(u256(2)));
BOOST_CHECK(framework.callFunction(0, u256(5)) == toBigEndian(u256(4)));
BOOST_CHECK(framework.callFunction(0, u256(6)) == toBigEndian(u256(5)));
BOOST_CHECK(framework.callFunction(0, u256(7)) == toBigEndian(u256(5)));
BOOST_CHECK(framework.callFunction(0, u256(8)) == toBigEndian(u256(7)));
BOOST_CHECK(framework.callFunction(0, u256(9)) == toBigEndian(u256(8)));
BOOST_CHECK(framework.callFunction(0, u256(10)) == toBigEndian(u256(10)));
BOOST_CHECK(framework.callFunction(0, u256(11)) == toBigEndian(u256(10)));
} }
BOOST_AUTO_TEST_CASE(calling_other_functions) BOOST_AUTO_TEST_CASE(calling_other_functions)
@ -168,13 +213,12 @@ BOOST_AUTO_TEST_CASE(calling_other_functions)
" return 3 * x + 1;\n" " return 3 * x + 1;\n"
" }\n" " }\n"
"}\n"; "}\n";
ExecutionFramework framework; compileAndRun(sourceCode);
framework.compileAndRun(sourceCode); BOOST_CHECK(callFunction(2, u256(0)) == toBigEndian(u256(0)));
BOOST_CHECK(framework.callFunction(2, u256(0)) == toBigEndian(u256(0))); BOOST_CHECK(callFunction(2, u256(1)) == toBigEndian(u256(1)));
BOOST_CHECK(framework.callFunction(2, u256(1)) == toBigEndian(u256(1))); BOOST_CHECK(callFunction(2, u256(2)) == toBigEndian(u256(1)));
BOOST_CHECK(framework.callFunction(2, u256(2)) == toBigEndian(u256(1))); BOOST_CHECK(callFunction(2, u256(8)) == toBigEndian(u256(1)));
BOOST_CHECK(framework.callFunction(2, u256(8)) == toBigEndian(u256(1))); BOOST_CHECK(callFunction(2, u256(127)) == toBigEndian(u256(1)));
BOOST_CHECK(framework.callFunction(2, u256(127)) == toBigEndian(u256(1)));
} }
BOOST_AUTO_TEST_CASE(many_local_variables) BOOST_AUTO_TEST_CASE(many_local_variables)
@ -186,12 +230,25 @@ BOOST_AUTO_TEST_CASE(many_local_variables)
" y += b + x2;\n" " y += b + x2;\n"
" }\n" " }\n"
"}\n"; "}\n";
ExecutionFramework framework; compileAndRun(sourceCode);
framework.compileAndRun(sourceCode); BOOST_CHECK(callFunction(0, toBigEndian(u256(0x1000)) + toBigEndian(u256(0x10000)) + toBigEndian(u256(0x100000)))
BOOST_CHECK(framework.callFunction(0, toBigEndian(u256(0x1000)) + toBigEndian(u256(0x10000)) + toBigEndian(u256(0x100000)))
== toBigEndian(u256(0x121121))); == toBigEndian(u256(0x121121)));
} }
BOOST_AUTO_TEST_CASE(packing_unpacking_types)
{
char const* sourceCode = "contract test {\n"
" function run(bool a, uint32 b, uint64 c) returns(uint256 y) {\n"
" if (a) y = 1;\n"
" y = y * 0x100000000 | ~b;\n"
" y = y * 0x10000000000000000 | ~c;\n"
" }\n"
"}\n";
compileAndRun(sourceCode);
BOOST_CHECK(callFunction(0, fromHex("01""0f0f0f0f""f0f0f0f0f0f0f0f0"))
== fromHex("00000000000000000000000000000000000000""01""f0f0f0f0""0f0f0f0f0f0f0f0f"));
}
BOOST_AUTO_TEST_CASE(multiple_return_values) BOOST_AUTO_TEST_CASE(multiple_return_values)
{ {
char const* sourceCode = "contract test {\n" char const* sourceCode = "contract test {\n"
@ -199,9 +256,8 @@ BOOST_AUTO_TEST_CASE(multiple_return_values)
" y1 = x2; y2 = x1;\n" " y1 = x2; y2 = x1;\n"
" }\n" " }\n"
"}\n"; "}\n";
ExecutionFramework framework; compileAndRun(sourceCode);
framework.compileAndRun(sourceCode); BOOST_CHECK(callFunction(0, bytes(1, 1) + toBigEndian(u256(0xcd)))
BOOST_CHECK(framework.callFunction(0, bytes(1, 1) + toBigEndian(u256(0xcd)))
== toBigEndian(u256(0xcd)) + bytes(1, 1) + toBigEndian(u256(0))); == toBigEndian(u256(0xcd)) + bytes(1, 1) + toBigEndian(u256(0)));
} }
@ -213,13 +269,59 @@ BOOST_AUTO_TEST_CASE(short_circuiting)
" return x;" " return x;"
" }\n" " }\n"
"}\n"; "}\n";
ExecutionFramework framework; compileAndRun(sourceCode);
framework.compileAndRun(sourceCode); BOOST_CHECK(callFunction(0, u256(0)) == toBigEndian(u256(0)));
BOOST_CHECK(framework.callFunction(0, u256(0)) == toBigEndian(u256(0))); BOOST_CHECK(callFunction(0, u256(1)) == toBigEndian(u256(8)));
BOOST_CHECK(framework.callFunction(0, u256(1)) == toBigEndian(u256(8))); }
BOOST_AUTO_TEST_CASE(high_bits_cleaning)
{
char const* sourceCode = "contract test {\n"
" function run() returns(uint256 y) {\n"
" uint32 x = uint32(0xffffffff) + 10;\n"
" if (x >= 0xffffffff) return 0;\n"
" return x;"
" }\n"
"}\n";
compileAndRun(sourceCode);
BOOST_CHECK(callFunction(0, bytes()) == toBigEndian(u256(9)));
}
BOOST_AUTO_TEST_CASE(sign_extension)
{
char const* sourceCode = "contract test {\n"
" function run() returns(uint256 y) {\n"
" int64 x = -int32(0xff);\n"
" if (x >= 0xff) return 0;\n"
" return -uint256(x);"
" }\n"
"}\n";
compileAndRun(sourceCode);
BOOST_CHECK(callFunction(0, bytes()) == toBigEndian(u256(0xff)));
}
BOOST_AUTO_TEST_CASE(small_unsigned_types)
{
char const* sourceCode = "contract test {\n"
" function run() returns(uint256 y) {\n"
" uint32 x = uint32(0xffffff) * 0xffffff;\n"
" return x / 0x100;"
" }\n"
"}\n";
compileAndRun(sourceCode);
BOOST_CHECK(callFunction(0, bytes()) == toBigEndian(u256(0xfe0000)));
} }
//@todo test smaller types BOOST_AUTO_TEST_CASE(small_signed_types)
{
char const* sourceCode = "contract test {\n"
" function run() returns(int256 y) {\n"
" return -int32(10) * -int64(20);\n"
" }\n"
"}\n";
compileAndRun(sourceCode);
BOOST_CHECK(callFunction(0, bytes()) == toBigEndian(u256(200)));
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

74
test/solidityExpressionCompiler.cpp

@ -154,8 +154,8 @@ BOOST_AUTO_TEST_CASE(comparison)
"}\n"; "}\n";
bytes code = compileFirstExpression(sourceCode); bytes code = compileFirstExpression(sourceCode);
bytes expectation({byte(eth::Instruction::PUSH2), 0x10, 0xaa, bytes expectation({byte(eth::Instruction::PUSH2), 0x10, 0xaa, byte(eth::Instruction::PUSH2), 0xff, 0xff, byte(eth::Instruction::AND),
byte(eth::Instruction::PUSH2), 0x11, 0xaa, byte(eth::Instruction::PUSH2), 0x11, 0xaa, byte(eth::Instruction::PUSH2), 0xff, 0xff, byte(eth::Instruction::AND),
byte(eth::Instruction::GT), byte(eth::Instruction::GT),
byte(eth::Instruction::PUSH1), 0x1, byte(eth::Instruction::PUSH1), 0x1,
byte(eth::Instruction::EQ), byte(eth::Instruction::EQ),
@ -172,16 +172,16 @@ BOOST_AUTO_TEST_CASE(short_circuiting)
bytes expectation({byte(eth::Instruction::PUSH1), 0xa, bytes expectation({byte(eth::Instruction::PUSH1), 0xa,
byte(eth::Instruction::PUSH1), 0x8, byte(eth::Instruction::PUSH1), 0x8,
byte(eth::Instruction::ADD), byte(eth::Instruction::ADD), byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND),
byte(eth::Instruction::PUSH1), 0x4, byte(eth::Instruction::PUSH1), 0x4, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND),
byte(eth::Instruction::GT), byte(eth::Instruction::GT),
byte(eth::Instruction::ISZERO), // after this we have 10 + 8 >= 4 byte(eth::Instruction::ISZERO), // after this we have 10 + 8 >= 4
byte(eth::Instruction::DUP1), byte(eth::Instruction::DUP1),
byte(eth::Instruction::PUSH1), 0x14, byte(eth::Instruction::PUSH1), 0x20,
byte(eth::Instruction::JUMPI), // short-circuit if it is true byte(eth::Instruction::JUMPI), // short-circuit if it is true
byte(eth::Instruction::POP), byte(eth::Instruction::POP),
byte(eth::Instruction::PUSH1), 0x2, byte(eth::Instruction::PUSH1), 0x2, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND),
byte(eth::Instruction::PUSH1), 0x9, byte(eth::Instruction::PUSH1), 0x9, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND),
byte(eth::Instruction::EQ), byte(eth::Instruction::EQ),
byte(eth::Instruction::ISZERO), // after this we have 2 != 9 byte(eth::Instruction::ISZERO), // after this we have 2 != 9
byte(eth::Instruction::JUMPDEST), byte(eth::Instruction::JUMPDEST),
@ -197,10 +197,11 @@ BOOST_AUTO_TEST_CASE(arithmetics)
" function f() { var x = (1 * (2 / (3 % (4 + (5 - (6 | (7 & (8 ^ 9)))))))); }" " function f() { var x = (1 * (2 / (3 % (4 + (5 - (6 | (7 & (8 ^ 9)))))))); }"
"}\n"; "}\n";
bytes code = compileFirstExpression(sourceCode); bytes code = compileFirstExpression(sourceCode);
bytes expectation({byte(eth::Instruction::PUSH1), 0x1, bytes expectation({byte(eth::Instruction::PUSH1), 0x1,
byte(eth::Instruction::PUSH1), 0x2, byte(eth::Instruction::PUSH1), 0x2,
byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND),
byte(eth::Instruction::PUSH1), 0x3, byte(eth::Instruction::PUSH1), 0x3,
byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND),
byte(eth::Instruction::PUSH1), 0x4, byte(eth::Instruction::PUSH1), 0x4,
byte(eth::Instruction::PUSH1), 0x5, byte(eth::Instruction::PUSH1), 0x5,
byte(eth::Instruction::PUSH1), 0x6, byte(eth::Instruction::PUSH1), 0x6,
@ -213,8 +214,10 @@ BOOST_AUTO_TEST_CASE(arithmetics)
byte(eth::Instruction::SWAP1), byte(eth::Instruction::SWAP1),
byte(eth::Instruction::SUB), byte(eth::Instruction::SUB),
byte(eth::Instruction::ADD), byte(eth::Instruction::ADD),
byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND),
byte(eth::Instruction::SWAP1), byte(eth::Instruction::SWAP1),
byte(eth::Instruction::MOD), byte(eth::Instruction::MOD),
byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND),
byte(eth::Instruction::SWAP1), byte(eth::Instruction::SWAP1),
byte(eth::Instruction::DIV), byte(eth::Instruction::DIV),
byte(eth::Instruction::MUL)}); byte(eth::Instruction::MUL)});
@ -224,15 +227,15 @@ BOOST_AUTO_TEST_CASE(arithmetics)
BOOST_AUTO_TEST_CASE(unary_operators) BOOST_AUTO_TEST_CASE(unary_operators)
{ {
char const* sourceCode = "contract test {\n" char const* sourceCode = "contract test {\n"
" function f() { var x = !(~+-1 == 2); }" " function f() { var x = !(~+- 1 == 2); }"
"}\n"; "}\n";
bytes code = compileFirstExpression(sourceCode); bytes code = compileFirstExpression(sourceCode);
bytes expectation({byte(eth::Instruction::PUSH1), 0x1, bytes expectation({byte(eth::Instruction::PUSH1), 0x1,
byte(eth::Instruction::PUSH1), 0x0, byte(eth::Instruction::PUSH1), 0x0,
byte(eth::Instruction::SUB), byte(eth::Instruction::SUB),
byte(eth::Instruction::NOT), byte(eth::Instruction::NOT), byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND),
byte(eth::Instruction::PUSH1), 0x2, byte(eth::Instruction::PUSH1), 0x2, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND),
byte(eth::Instruction::EQ), byte(eth::Instruction::EQ),
byte(eth::Instruction::ISZERO)}); byte(eth::Instruction::ISZERO)});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
@ -305,7 +308,7 @@ BOOST_AUTO_TEST_CASE(assignment)
byte(eth::Instruction::POP), byte(eth::Instruction::POP),
byte(eth::Instruction::DUP2), byte(eth::Instruction::DUP2),
// Stack here: a+b b a+b // Stack here: a+b b a+b
byte(eth::Instruction::PUSH1), 0x2, byte(eth::Instruction::PUSH1), 0x2, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND),
byte(eth::Instruction::MUL)}); byte(eth::Instruction::MUL)});
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
} }
@ -320,17 +323,17 @@ BOOST_AUTO_TEST_CASE(function_call)
{{"test", "f", "a"}, {"test", "f", "b"}}); {{"test", "f", "a"}, {"test", "f", "b"}});
// Stack: a, b // Stack: a, b
bytes expectation({byte(eth::Instruction::PUSH1), 0x0a, bytes expectation({byte(eth::Instruction::PUSH1), 0x0d,
byte(eth::Instruction::DUP3), byte(eth::Instruction::DUP3),
byte(eth::Instruction::PUSH1), 0x01, byte(eth::Instruction::PUSH1), 0x01, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND),
byte(eth::Instruction::ADD), byte(eth::Instruction::ADD),
// Stack here: a b <ret label> (a+1) // Stack here: a b <ret label> (a+1)
byte(eth::Instruction::DUP3), byte(eth::Instruction::DUP3),
byte(eth::Instruction::PUSH1), 0x14, byte(eth::Instruction::PUSH1), 0x1a,
byte(eth::Instruction::JUMP), byte(eth::Instruction::JUMP),
byte(eth::Instruction::JUMPDEST), byte(eth::Instruction::JUMPDEST),
// Stack here: a b g(a+1, b) // Stack here: a b g(a+1, b)
byte(eth::Instruction::PUSH1), 0x02, byte(eth::Instruction::PUSH1), 0x02, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND),
byte(eth::Instruction::MUL), byte(eth::Instruction::MUL),
// Stack here: a b g(a+1, b)*2 // Stack here: a b g(a+1, b)*2
byte(eth::Instruction::DUP3), byte(eth::Instruction::DUP3),
@ -344,6 +347,45 @@ BOOST_AUTO_TEST_CASE(function_call)
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
} }
BOOST_AUTO_TEST_CASE(negative_literals_8bits)
{
// these all fit in 8 bits
char const* sourceCode = "contract test {\n"
" function f() { int8 x = -0 + -1 + -0x01 + -127 + -128; }\n"
"}\n";
bytes code = compileFirstExpression(sourceCode);
bytes expectation(bytes({byte(eth::Instruction::PUSH1), 0x00,
byte(eth::Instruction::PUSH32)}) + bytes(32, 0xff) +
bytes({byte(eth::Instruction::ADD),
byte(eth::Instruction::PUSH32)}) + bytes(32, 0xff) +
bytes({byte(eth::Instruction::ADD),
byte(eth::Instruction::PUSH32)}) + bytes(31, 0xff) + bytes(1, 0x81) +
bytes({byte(eth::Instruction::ADD),
byte(eth::Instruction::PUSH32)}) + bytes(31, 0xff) + bytes(1, 0x80) +
bytes({byte(eth::Instruction::ADD)}));
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
BOOST_AUTO_TEST_CASE(negative_literals_16bits)
{
// -1 should need 8 bits, -129 should need 16 bits, how many bits are used is visible
// from the SIGNEXTEND opcodes
char const* sourceCode = "contract test {\n"
" function f() { int64 x = int64(-1 + -129); }\n"
"}\n";
bytes code = compileFirstExpression(sourceCode);
bytes expectation(bytes({byte(eth::Instruction::PUSH32)}) + bytes(32, 0xff) +
bytes({byte(eth::Instruction::PUSH1), 0x00,
byte(eth::Instruction::SIGNEXTEND),
byte(eth::Instruction::PUSH32)}) + bytes(31, 0xff) + bytes(1, 0x7f) +
bytes({byte(eth::Instruction::ADD),
byte(eth::Instruction::PUSH1), 0x01,
byte(eth::Instruction::SIGNEXTEND)}));
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }

16
test/solidityNameAndTypeResolution.cpp

@ -162,6 +162,22 @@ BOOST_AUTO_TEST_CASE(type_checking_function_call)
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
} }
BOOST_AUTO_TEST_CASE(type_conversion_for_comparison)
{
char const* text = "contract test {\n"
" function f() { uint32(2) == int64(2); }"
"}\n";
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
}
BOOST_AUTO_TEST_CASE(type_conversion_for_comparison_invalid)
{
char const* text = "contract test {\n"
" function f() { int32(2) == uint64(2); }"
"}\n";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(type_inference_explicit_conversion) BOOST_AUTO_TEST_CASE(type_inference_explicit_conversion)
{ {
char const* text = "contract test {\n" char const* text = "contract test {\n"

26
test/solidityScanner.cpp

@ -97,6 +97,27 @@ BOOST_AUTO_TEST_CASE(hex_numbers)
BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS);
} }
BOOST_AUTO_TEST_CASE(negative_numbers)
{
Scanner scanner(CharStream("var x = -.2 + -0x78 + -7.3 + 8.9;"));
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::VAR);
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER);
BOOST_CHECK_EQUAL(scanner.next(), Token::ASSIGN);
BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER);
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "-.2");
BOOST_CHECK_EQUAL(scanner.next(), Token::ADD);
BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER);
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "-0x78");
BOOST_CHECK_EQUAL(scanner.next(), Token::ADD);
BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER);
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "-7.3");
BOOST_CHECK_EQUAL(scanner.next(), Token::ADD);
BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER);
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "8.9");
BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON);
BOOST_CHECK_EQUAL(scanner.next(), Token::EOS);
}
BOOST_AUTO_TEST_CASE(locations) BOOST_AUTO_TEST_CASE(locations)
{ {
Scanner scanner(CharStream("function_identifier has ; -0x743/*comment*/\n ident //comment")); Scanner scanner(CharStream("function_identifier has ; -0x743/*comment*/\n ident //comment"));
@ -109,11 +130,8 @@ BOOST_AUTO_TEST_CASE(locations)
BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON);
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 24); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 24);
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 25); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 25);
BOOST_CHECK_EQUAL(scanner.next(), Token::SUB);
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 26);
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 27);
BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER);
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 27); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 26);
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 32); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 32);
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER);
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 45); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 45);

2
test/vm.h

@ -29,7 +29,7 @@ along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
#include "JsonSpiritHeaders.h" #include "JsonSpiritHeaders.h"
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libevmface/Instruction.h> #include <libevmcore/Instruction.h>
#include <libevm/ExtVMFace.h> #include <libevm/ExtVMFace.h>
#include <libevm/VM.h> #include <libevm/VM.h>
#include <liblll/Compiler.h> #include <liblll/Compiler.h>

2
third/CMakeLists.txt

@ -53,7 +53,7 @@ else ()
endif () endif ()
qt5_use_modules(${EXECUTEABLE} Core)# Gui Widgets Network WebKit WebKitWidgets) qt5_use_modules(${EXECUTEABLE} Core)# Gui Widgets Network WebKit WebKitWidgets)
target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore secp256k1 gmp ${CRYPTOPP_LS} serpent lll evmface devcore web3jsonrpc jsqrc) target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore secp256k1 gmp ${CRYPTOPP_LS} serpent lll evmcore devcore web3jsonrpc jsqrc)
if (APPLE) if (APPLE)
# First have qt5 install plugins and frameworks # First have qt5 install plugins and frameworks

2
walleth/MainWin.cpp

@ -9,7 +9,7 @@
#include <QtCore/QtCore> #include <QtCore/QtCore>
#include <libdevcrypto/FileSystem.h> #include <libdevcrypto/FileSystem.h>
#include <libethcore/Dagger.h> #include <libethcore/Dagger.h>
#include <libevmface/Instruction.h> #include <libevmcore/Instruction.h>
#include <libethereum/Client.h> #include <libethereum/Client.h>
#include <libethereum/EthereumHost.h> #include <libethereum/EthereumHost.h>
#include "BuildInfo.h" #include "BuildInfo.h"

6
windows/LibEthereum.vcxproj

@ -125,7 +125,7 @@
<ClCompile Include="..\libethereum\Transaction.cpp" /> <ClCompile Include="..\libethereum\Transaction.cpp" />
<ClCompile Include="..\libethereum\TransactionQueue.cpp" /> <ClCompile Include="..\libethereum\TransactionQueue.cpp" />
<ClCompile Include="..\libethereum\Utility.cpp" /> <ClCompile Include="..\libethereum\Utility.cpp" />
<ClCompile Include="..\libevmface\Instruction.cpp" /> <ClCompile Include="..\libevmcore\Instruction.cpp" />
<ClCompile Include="..\libevm\ExtVMFace.cpp"> <ClCompile Include="..\libevm\ExtVMFace.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@ -341,7 +341,7 @@
<ClInclude Include="..\libethereum\Transaction.h" /> <ClInclude Include="..\libethereum\Transaction.h" />
<ClInclude Include="..\libethereum\TransactionQueue.h" /> <ClInclude Include="..\libethereum\TransactionQueue.h" />
<ClInclude Include="..\libethereum\Utility.h" /> <ClInclude Include="..\libethereum\Utility.h" />
<ClInclude Include="..\libevmface\Instruction.h" /> <ClInclude Include="..\libevmcore\Instruction.h" />
<ClInclude Include="..\libevm\All.h"> <ClInclude Include="..\libevm\All.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@ -367,7 +367,7 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClInclude> </ClInclude>
<ClInclude Include="..\liblll\All.h" /> <ClInclude Include="..\liblll\All.h" />
<ClInclude Include="..\liblll\Assembly.h" /> <ClInclude Include="..\libevmcore\Assembly.h" />
<ClInclude Include="..\liblll\CodeFragment.h" /> <ClInclude Include="..\liblll\CodeFragment.h" />
<ClInclude Include="..\liblll\Compiler.h" /> <ClInclude Include="..\liblll\Compiler.h" />
<ClInclude Include="..\liblll\CompilerState.h" /> <ClInclude Include="..\liblll\CompilerState.h" />

14
windows/LibEthereum.vcxproj.filters

@ -37,8 +37,8 @@
<ClCompile Include="..\libevm\VM.cpp"> <ClCompile Include="..\libevm\VM.cpp">
<Filter>libevm</Filter> <Filter>libevm</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\libevmface\Instruction.cpp"> <ClCompile Include="..\libevmcore\Instruction.cpp">
<Filter>libevmface</Filter> <Filter>libevmcore</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\liblll\Assembly.cpp"> <ClCompile Include="..\liblll\Assembly.cpp">
<Filter>liblll</Filter> <Filter>liblll</Filter>
@ -243,14 +243,14 @@
<ClInclude Include="..\libevm\All.h"> <ClInclude Include="..\libevm\All.h">
<Filter>libevm</Filter> <Filter>libevm</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\libevmface\Instruction.h"> <ClInclude Include="..\libevmcore\Instruction.h">
<Filter>libevmface</Filter> <Filter>libevmcore</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\liblll\All.h"> <ClInclude Include="..\liblll\All.h">
<Filter>liblll</Filter> <Filter>liblll</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\liblll\Assembly.h"> <ClInclude Include="..\libevmcore\Assembly.h">
<Filter>liblll</Filter> <Filter>libevmcore</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\liblll\CodeFragment.h"> <ClInclude Include="..\liblll\CodeFragment.h">
<Filter>liblll</Filter> <Filter>liblll</Filter>
@ -449,7 +449,7 @@
<Filter Include="libevm"> <Filter Include="libevm">
<UniqueIdentifier>{37c37803-1515-47c1-b7e6-3879f4429ab3}</UniqueIdentifier> <UniqueIdentifier>{37c37803-1515-47c1-b7e6-3879f4429ab3}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="libevmface"> <Filter Include="libevmcore">
<UniqueIdentifier>{ed9ad1b3-700c-47f9-8548-a90b5ef179ac}</UniqueIdentifier> <UniqueIdentifier>{ed9ad1b3-700c-47f9-8548-a90b5ef179ac}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="liblll"> <Filter Include="liblll">

Loading…
Cancel
Save