Browse Source

Merge branch 'develop' of https://github.com/ethereum/cpp-ethereum into mix_tx

cl-refactor
arkpar 10 years ago
parent
commit
3f982faeed
  1. 2
      alethzero/MainWin.cpp
  2. 2
      libethcore/CommonEth.cpp
  3. 2
      libjsqrc/ethereumjs/example/balance.html
  4. 3
      libsolidity/AST.cpp
  5. 12
      libsolidity/ASTPrinter.cpp
  6. 2
      libsolidity/ASTPrinter.h
  7. 4
      libsolidity/ASTVisitor.h
  8. 98
      libsolidity/CompilerStack.cpp
  9. 10
      libsolidity/CompilerStack.h
  10. 15
      libsolidity/Parser.cpp
  11. 1
      libsolidity/Parser.h
  12. 2
      libsolidity/Types.h
  13. 2
      libweb3jsonrpc/WebThreeStubServerBase.cpp
  14. 2
      test/SolidityABIJSON.cpp
  15. 31
      test/SolidityEndToEndTest.cpp
  16. 2
      test/SolidityNatspecJSON.cpp
  17. 6
      test/solidityExecutionFramework.h

2
alethzero/MainWin.cpp

@ -726,7 +726,7 @@ void Main::readSettings(bool _skipGeometry)
ui->enableOptimizer->setChecked(m_enableOptimizer);
ui->clientName->setText(s.value("clientName", "").toString());
if (ui->clientName->text().isEmpty())
ui->clientName->setText(QInputDialog::getText(this, "Enter identity", "Enter a name that will identify you on the peer network"));
ui->clientName->setText(QInputDialog::getText(nullptr, "Enter identity", "Enter a name that will identify you on the peer network"));
ui->idealPeers->setValue(s.value("idealPeers", ui->idealPeers->value()).toInt());
ui->port->setValue(s.value("port", ui->port->value()).toInt());
ui->nameReg->setText(s.value("nameReg", "").toString());

2
libethcore/CommonEth.cpp

@ -32,7 +32,7 @@ namespace dev
namespace eth
{
const unsigned c_protocolVersion = 51;
const unsigned c_protocolVersion = 52;
const unsigned c_databaseVersion = 5;
static const vector<pair<u256, string>> g_units =

2
libjsqrc/ethereumjs/example/balance.html

@ -17,7 +17,7 @@
var originalBalance = web3.toDecimal(balance);
document.getElementById('original').innerText = 'original balance: ' + originalBalance + ' watching...';
web3.eth.watch({altered: coinbase}).changed(function() {
web3.eth.watch('pending').changed(function() {
balance = web3.eth.balanceAt(coinbase)
var currentBalance = web3.toDecimal(balance);
document.getElementById("current").innerText = 'current: ' + currentBalance;

3
libsolidity/AST.cpp

@ -414,8 +414,7 @@ void FunctionCall::checkTypeRequirements()
//@todo for structs, we have to check the number of arguments to be equal to the
// number of non-mapping members
if (m_arguments.size() != 1)
BOOST_THROW_EXCEPTION(createTypeError("More than one argument for "
"explicit type conersion."));
BOOST_THROW_EXCEPTION(createTypeError("More than one argument for explicit type conversion."));
if (!m_arguments.front()->getType()->isExplicitlyConvertibleTo(*type.getActualType()))
BOOST_THROW_EXCEPTION(createTypeError("Explicit type conversion not allowed."));
m_type = type.getActualType();

12
libsolidity/ASTPrinter.cpp

@ -57,6 +57,13 @@ bool ASTPrinter::visit(ContractDefinition const& _node)
return goDeeper();
}
bool ASTPrinter::visit(InheritanceSpecifier const& _node)
{
writeLine("InheritanceSpecifier \"" + _node.getName()->getName() + "\"");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(StructDefinition const& _node)
{
writeLine("StructDefinition \"" + _node.getName() + "\"");
@ -323,6 +330,11 @@ void ASTPrinter::endVisit(ContractDefinition const&)
m_indentation--;
}
void ASTPrinter::endVisit(InheritanceSpecifier const&)
{
m_indentation--;
}
void ASTPrinter::endVisit(StructDefinition const&)
{
m_indentation--;

2
libsolidity/ASTPrinter.h

@ -44,6 +44,7 @@ public:
bool visit(ImportDirective const& _node) override;
bool visit(ContractDefinition const& _node) override;
bool visit(InheritanceSpecifier const& _node) override;
bool visit(StructDefinition const& _node) override;
bool visit(ParameterList const& _node) override;
bool visit(FunctionDefinition const& _node) override;
@ -81,6 +82,7 @@ public:
void endVisit(ImportDirective const&) override;
void endVisit(ContractDefinition const&) override;
void endVisit(InheritanceSpecifier const&) override;
void endVisit(StructDefinition const&) override;
void endVisit(ParameterList const&) override;
void endVisit(FunctionDefinition const&) override;

4
libsolidity/ASTVisitor.h

@ -45,6 +45,7 @@ public:
virtual bool visit(SourceUnit&) { return true; }
virtual bool visit(ImportDirective&) { return true; }
virtual bool visit(ContractDefinition&) { return true; }
virtual bool visit(InheritanceSpecifier&) { return true; }
virtual bool visit(StructDefinition&) { return true; }
virtual bool visit(ParameterList&) { return true; }
virtual bool visit(FunctionDefinition&) { return true; }
@ -84,6 +85,7 @@ public:
virtual void endVisit(SourceUnit&) { }
virtual void endVisit(ImportDirective&) { }
virtual void endVisit(ContractDefinition&) { }
virtual void endVisit(InheritanceSpecifier&) { }
virtual void endVisit(StructDefinition&) { }
virtual void endVisit(ParameterList&) { }
virtual void endVisit(FunctionDefinition&) { }
@ -127,6 +129,7 @@ public:
virtual bool visit(SourceUnit const&) { return true; }
virtual bool visit(ImportDirective const&) { return true; }
virtual bool visit(ContractDefinition const&) { return true; }
virtual bool visit(InheritanceSpecifier const&) { return true; }
virtual bool visit(StructDefinition const&) { return true; }
virtual bool visit(ParameterList const&) { return true; }
virtual bool visit(FunctionDefinition const&) { return true; }
@ -166,6 +169,7 @@ public:
virtual void endVisit(SourceUnit const&) { }
virtual void endVisit(ImportDirective const&) { }
virtual void endVisit(ContractDefinition const&) { }
virtual void endVisit(InheritanceSpecifier const&) { }
virtual void endVisit(StructDefinition const&) { }
virtual void endVisit(ParameterList const&) { }
virtual void endVisit(FunctionDefinition const&) { }

98
libsolidity/CompilerStack.cpp

@ -40,18 +40,39 @@ namespace dev
namespace solidity
{
const map<string, string> StandardSources = map<string, string>{
{"coin", R"(import "CoinReg";import "Config";import "configUser";contract coin is configUser{function coin(string3 name, uint denom) {CoinReg(Config(configAddr()).lookup(3)).register(name, denom);}})"},
{"Coin", R"(contract Coin{function isApprovedFor(address _target,address _proxy)constant returns(bool _r){}function isApproved(address _proxy)constant returns(bool _r){}function sendCoinFrom(address _from,uint256 _val,address _to){}function coinBalanceOf(address _a)constant returns(uint256 _r){}function sendCoin(uint256 _val,address _to){}function coinBalance()constant returns(uint256 _r){}function approve(address _a){}})"},
{"CoinReg", R"(contract CoinReg{function count()constant returns(uint256 r){}function info(uint256 i)constant returns(address addr,string3 name,uint256 denom){}function register(string3 name,uint256 denom){}function unregister(){}})"},
{"configUser", R"(contract configUser{function configAddr()constant returns(address a){ return 0xc6d9d2cd449a754c494264e1809c50e34d64562b;}})"},
{"Config", R"(contract Config{function lookup(uint256 service)constant returns(address a){}function kill(){}function unregister(uint256 id){}function register(uint256 id,address service){}})"},
{"mortal", R"(import "owned";contract mortal is owned {function kill() { if (msg.sender == owner) suicide(owner); }})"},
{"named", R"(import "Config";import "NameReg";import "configUser";contract named is configUser {function named(string32 name) {NameReg(Config(configAddr()).lookup(1)).register(name);}})"},
{"NameReg", R"(contract NameReg{function register(string32 name){}function addressOf(string32 name)constant returns(address addr){}function unregister(){}function nameOf(address addr)constant returns(string32 name){}})"},
{"owned", R"(contract owned{function owned(){owner = msg.sender;}modifier onlyowner(){if(msg.sender==owner)_}address owner;})"},
{"service", R"(import "Config";import "configUser";contract service is configUser{function service(uint _n){Config(configAddr()).register(_n, this);}})"},
{"std", R"(import "owned";import "mortal";import "Config";import "configUser";import "NameReg";import "named";)"}
};
CompilerStack::CompilerStack(bool _addStandardSources):
m_addStandardSources(_addStandardSources), m_parseSuccessful(false)
{
if (m_addStandardSources)
addSources(StandardSources);
}
bool CompilerStack::addSource(string const& _name, string const& _content)
{
bool existed = m_sources.count(_name) != 0;
reset(true);
m_sources[_name].scanner = make_shared<Scanner>(CharStream(expanded(_content)), _name);
m_sources[_name].scanner = make_shared<Scanner>(CharStream(_content), _name);
return existed;
}
void CompilerStack::setSource(string const& _sourceCode)
{
reset();
addSource("", expanded(_sourceCode));
addSource("", _sourceCode);
}
void CompilerStack::parse()
@ -91,7 +112,6 @@ void CompilerStack::parse()
void CompilerStack::parse(string const& _sourceCode)
{
setSource(_sourceCode);
addSources(StandardSources);
parse();
}
@ -125,64 +145,6 @@ void CompilerStack::compile(bool _optimize)
}
}
const map<string, string> StandardSources = map<string, string>{
/* { "Config", "contract Config{function lookup(uint256 service)constant returns(address a){}function kill(){}function unregister(uint256 id){}function register(uint256 id,address service){}}" },
{ "owned", "contract owned{function owned(){owner = msg.sender;}address owner;}" },
{ "mortal", "import \"owned\";\ncontract mortal is owned {function kill() { if (msg.sender == owner) suicide(owner); }}" },
{ "NameReg", "contract NameReg{function register(string32 name){}function addressOf(string32 name)constant returns(address addr){}function unregister(){}function nameOf(address addr)constant returns(string32 name){}}" },
{ "named", "import \"Config\";\nimport \"NameReg\";\ncontract named {function named(string32 name) {NameReg(Config().lookup(1)).register(name);}}" },
{ "std", "import \"owned\";\nimport \"mortal\";\nimport \"Config\";\nimport \"NameReg\";\nimport \"named\";\n" },
*/};
////// BEGIN: TEMPORARY ONLY
/// remove once import works properly and we have genesis contracts
string CompilerStack::expanded(string const& _sourceCode)
{
const map<string, string> c_standardSources = map<string, string>{
{ "Config", "contract Config{function lookup(uint256 service)constant returns(address a){}function kill(){}function unregister(uint256 id){}function register(uint256 id,address service){}}" },
{ "Coin", "contract Coin{function isApprovedFor(address _target,address _proxy)constant returns(bool _r){}function isApproved(address _proxy)constant returns(bool _r){}function sendCoinFrom(address _from,uint256 _val,address _to){}function coinBalanceOf(address _a)constant returns(uint256 _r){}function sendCoin(uint256 _val,address _to){}function coinBalance()constant returns(uint256 _r){}function approve(address _a){}}"},
{ "CoinReg", "contract CoinReg{function count()constant returns(uint256 r){}function info(uint256 i)constant returns(address addr,string3 name,uint256 denom){}function register(string3 name,uint256 denom){}function unregister(){}}" },
{ "coin", "#require CoinReg\ncontract coin {function coin(string3 name, uint denom) {CoinReg(Config().lookup(3)).register(name, denom);}}" },
{ "service", "#require Config\ncontract service{function service(uint _n){Config().register(_n, this);}}" },
{ "owned", "contract owned{function owned(){owner = msg.sender;}modifier onlyowner(){if(msg.sender==owner)_}address owner;}" },
{ "mortal", "#require owned\ncontract mortal is owned {function kill() { if (msg.sender == owner) suicide(owner); }}" },
{ "NameReg", "contract NameReg{function register(string32 name){}function addressOf(string32 name)constant returns(address addr){}function unregister(){}function nameOf(address addr)constant returns(string32 name){}}" },
{ "named", "#require Config NameReg\ncontract named {function named(string32 name) {NameReg(Config().lookup(1)).register(name);}}" },
{ "std", "#require owned mortal Config NameReg named" },
};
string sub;
set<string> got;
function<string(string const&)> localExpanded;
localExpanded = [&](string const& s) -> string
{
string ret = s;
for (size_t p = 0; p != string::npos;)
if ((p = ret.find("#require ")) != string::npos)
{
string n = ret.substr(p + 9, ret.find_first_of('\n', p + 9) - p - 9);
ret.replace(p, n.size() + 9, "");
vector<string> rs;
boost::split(rs, n, boost::is_any_of(" \t,"), boost::token_compress_on);
for (auto const& r: rs)
if (!got.count(r))
{
if (c_standardSources.count(r))
sub.append("\n" + localExpanded(c_standardSources.at(r)) + "\n");
got.insert(r);
}
}
// TODO: remove once we have genesis contracts.
else if ((p = ret.find("Config()")) != string::npos)
ret.replace(p, 8, "Config(0xc6d9d2cd449a754c494264e1809c50e34d64562b)");
return ret;
};
return sub + localExpanded(_sourceCode);
}
////// END: TEMPORARY ONLY
bytes const& CompilerStack::compile(string const& _sourceCode, bool _optimize)
{
parse(_sourceCode);
@ -278,7 +240,11 @@ void CompilerStack::reset(bool _keepSources)
for (auto sourcePair: m_sources)
sourcePair.second.reset();
else
{
m_sources.clear();
if (m_addStandardSources)
addSources(StandardSources);
}
m_globalContext.reset();
m_sourceOrder.clear();
m_contracts.clear();
@ -320,10 +286,12 @@ CompilerStack::Contract const& CompilerStack::getContract(string const& _contrac
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("No compiled contracts found."));
string contractName = _contractName;
if (_contractName.empty())
// try to find the "last contract"
for (ASTPointer<ASTNode> const& node: m_sourceOrder.back()->ast->getNodes())
if (auto contract = dynamic_cast<ContractDefinition const*>(node.get()))
contractName = contract->getName();
// try to find some user-supplied contract
for (auto const& it: m_sources)
if (!StandardSources.count(it.first))
for (ASTPointer<ASTNode> const& node: it.second.ast->getNodes())
if (auto contract = dynamic_cast<ContractDefinition const*>(node.get()))
contractName = contract->getName();
auto it = m_contracts.find(contractName);
if (it == m_contracts.end())
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Contract " + _contractName + " not found."));

10
libsolidity/CompilerStack.h

@ -59,7 +59,8 @@ extern const std::map<std::string, std::string> StandardSources;
class CompilerStack: boost::noncopyable
{
public:
CompilerStack(): m_parseSuccessful(false) {}
/// Creates a new compiler stack. Adds standard sources if @a _addStandardSources.
explicit CompilerStack(bool _addStandardSources = true);
/// Adds a source object (e.g. file) to the parser. After this, parse has to be called again.
/// @returns true if a source object by the name already existed and was replaced.
@ -68,7 +69,7 @@ public:
void setSource(std::string const& _sourceCode);
/// Parses all source units that were added
void parse();
/// Sets the given source code as the only source unit and parses it.
/// Sets the given source code as the only source unit apart from standard sources and parses it.
void parse(std::string const& _sourceCode);
/// Returns a list of the contract names in the sources.
std::vector<std::string> getContractNames() const;
@ -141,16 +142,13 @@ private:
Contract();
};
/// Expand source code with preprocessor-like includes.
/// @todo Replace with better framework.
std::string expanded(std::string const& _sourceCode);
void reset(bool _keepSources = false);
void resolveImports();
Contract const& getContract(std::string const& _contractName = "") const;
Source const& getSource(std::string const& _sourceName = "") const;
bool m_addStandardSources; ///< If true, standard sources are added.
bool m_parseSuccessful;
std::map<std::string const, Source> m_sources;
std::shared_ptr<GlobalContext> m_globalContext;

15
libsolidity/Parser.cpp

@ -167,7 +167,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier()
{
ASTNodeFactory nodeFactory(*this);
ASTPointer<Identifier> name = ASTNodeFactory(*this).createNode<Identifier>(expectIdentifierToken());
ASTPointer<Identifier> name(parseIdentifier());
vector<ASTPointer<Expression>> arguments;
if (m_scanner->getCurrentToken() == Token::LPAREN)
{
@ -283,7 +283,7 @@ ASTPointer<ModifierDefinition> Parser::parseModifierDefinition()
ASTPointer<ModifierInvocation> Parser::parseModifierInvocation()
{
ASTNodeFactory nodeFactory(*this);
ASTPointer<Identifier> name = ASTNodeFactory(*this).createNode<Identifier>(expectIdentifierToken());
ASTPointer<Identifier> name(parseIdentifier());
vector<ASTPointer<Expression>> arguments;
if (m_scanner->getCurrentToken() == Token::LPAREN)
{
@ -297,6 +297,13 @@ ASTPointer<ModifierInvocation> Parser::parseModifierInvocation()
return nodeFactory.createNode<ModifierInvocation>(name, arguments);
}
ASTPointer<Identifier> Parser::parseIdentifier()
{
ASTNodeFactory nodeFactory(*this);
nodeFactory.markEndPosition();
return nodeFactory.createNode<Identifier>(expectIdentifierToken());
}
ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar)
{
ASTPointer<TypeName> type;
@ -584,8 +591,8 @@ ASTPointer<Expression> Parser::parseLeftHandSideExpression()
if (m_scanner->getCurrentToken() == Token::NEW)
{
expectToken(Token::NEW);
ASTPointer<Identifier> contractName = ASTNodeFactory(*this).createNode<Identifier>(expectIdentifierToken());
nodeFactory.markEndPosition();
ASTPointer<Identifier> contractName(parseIdentifier());
nodeFactory.setEndPositionFromNode(contractName);
expression = nodeFactory.createNode<NewExpression>(contractName);
}
else

1
libsolidity/Parser.h

@ -55,6 +55,7 @@ private:
ASTPointer<VariableDeclaration> parseVariableDeclaration(bool _allowVar);
ASTPointer<ModifierDefinition> parseModifierDefinition();
ASTPointer<ModifierInvocation> parseModifierInvocation();
ASTPointer<Identifier> parseIdentifier();
ASTPointer<TypeName> parseTypeName(bool _allowVar);
ASTPointer<Mapping> parseMapping();
ASTPointer<ParameterList> parseParameterList(bool _allowEmpty = true);

2
libsolidity/Types.h

@ -452,6 +452,7 @@ public:
virtual bool canBeStored() const override { return false; }
virtual u256 getStorageSize() const override { BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage size of non-storable type type requested.")); }
virtual bool canLiveOutsideStorage() const override { return false; }
virtual unsigned getSizeOnStack() const override { return 0; }
virtual std::string toString() const override { return "type(" + m_actualType->toString() + ")"; }
virtual MemberList const& getMembers() const override;
@ -477,6 +478,7 @@ public:
virtual bool canBeStored() const override { return false; }
virtual u256 getStorageSize() const override { BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage size of non-storable type type requested.")); }
virtual bool canLiveOutsideStorage() const override { return false; }
virtual unsigned getSizeOnStack() const override { return 0; }
virtual bool operator==(Type const& _other) const override;
virtual std::string toString() const override;

2
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -62,7 +62,7 @@ static Json::Value toJson(dev::eth::Transaction const& _t)
res["hash"] = toJS(_t.sha3());
res["input"] = jsFromBinary(_t.data());
res["to"] = toJS(_t.receiveAddress());
res["from"] = toJS(_t.sender());
res["from"] = toJS(_t.safeSender());
res["gas"] = (int)_t.gas();
res["gasPrice"] = toJS(_t.gasPrice());
res["nonce"] = toJS(_t.nonce());

2
test/SolidityABIJSON.cpp

@ -35,6 +35,8 @@ namespace test
class InterfaceChecker
{
public:
InterfaceChecker(): m_compilerStack(false) {}
void checkInterface(std::string const& _code, std::string const& _expectedInterfaceString)
{
try

31
test/SolidityEndToEndTest.cpp

@ -1862,6 +1862,37 @@ BOOST_AUTO_TEST_CASE(function_modifier_for_constructor)
BOOST_CHECK(callContractFunction("getData()") == encodeArgs(4 | 2));
}
BOOST_AUTO_TEST_CASE(use_std_lib)
{
char const* sourceCode = R"(
import "mortal";
contract Icarus is mortal { }
)";
u256 amount(130);
u160 address(23);
compileAndRun(sourceCode, amount, "Icarus");
u256 balanceBefore = m_state.balance(m_sender);
BOOST_CHECK(callContractFunction("kill()") == bytes());
BOOST_CHECK(!m_state.addressHasCode(m_contractAddress));
BOOST_CHECK(m_state.balance(m_sender) > balanceBefore);
}
BOOST_AUTO_TEST_CASE(crazy_elementary_typenames_on_stack)
{
char const* sourceCode = R"(
contract C {
function f() returns (uint r) {
uint; uint; uint; uint;
int x = -7;
var a = uint;
return a(x);
}
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(-7)));
}
BOOST_AUTO_TEST_SUITE_END()
}

2
test/SolidityNatspecJSON.cpp

@ -36,6 +36,8 @@ namespace test
class DocumentationChecker
{
public:
DocumentationChecker(): m_compilerStack(false) {}
void checkNatspec(std::string const& _code,
std::string const& _expectedDocumentationString,
bool _userDocumentation)

6
test/solidityExecutionFramework.h

@ -45,10 +45,12 @@ public:
bytes const& compileAndRun(std::string const& _sourceCode, u256 const& _value = 0, std::string const& _contractName = "")
{
dev::solidity::CompilerStack compiler;
// add standard sources only if contract name is given
dev::solidity::CompilerStack compiler(!_contractName.empty());
try
{
compiler.compile(_sourceCode, m_optimize);
compiler.addSource("", _sourceCode);
compiler.compile(m_optimize);
}
catch(boost::exception const& _e)
{

Loading…
Cancel
Save