From 5dc7609c8080e59e8a7d053793a25e20038f8fe2 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 5 Nov 2014 23:35:00 +0100 Subject: [PATCH 1/6] Minor cleanup. --- libsolidity/AST.cpp | 20 +------------------- libsolidity/AST.h | 4 ++-- 2 files changed, 3 insertions(+), 21 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 026aef975..44cf39291 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -283,14 +283,6 @@ void WhileStatement::checkTypeRequirements() m_body->checkTypeRequirements(); } -void Continue::checkTypeRequirements() -{ -} - -void Break::checkTypeRequirements() -{ -} - void Return::checkTypeRequirements() { if (!m_expression) @@ -326,8 +318,6 @@ void VariableDefinition::checkTypeRequirements() void Assignment::checkTypeRequirements() { - //@todo lefthandside actually has to be assignable - // add a feature to the type system to check that m_leftHandSide->checkTypeRequirements(); if (!m_leftHandSide->isLvalue()) BOOST_THROW_EXCEPTION(createTypeError("Expression has to be an lvalue.")); @@ -366,8 +356,8 @@ void UnaryOperation::checkTypeRequirements() void BinaryOperation::checkTypeRequirements() { - m_right->checkTypeRequirements(); m_left->checkTypeRequirements(); + m_right->checkTypeRequirements(); if (m_right->getType()->isImplicitlyConvertibleTo(*m_left->getType())) m_commonType = m_left->getType(); else if (m_left->getType()->isImplicitlyConvertibleTo(*m_right->getType())) @@ -446,14 +436,6 @@ void Identifier::checkTypeRequirements() if (asserts(m_referencedDeclaration)) 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(m_referencedDeclaration); if (variable) { diff --git a/libsolidity/AST.h b/libsolidity/AST.h index f42ff47d0..793ce863f 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -390,7 +390,7 @@ class Continue: public Statement public: Continue(Location const& _location): Statement(_location) {} virtual void accept(ASTVisitor& _visitor) override; - virtual void checkTypeRequirements() override; + virtual void checkTypeRequirements() override {} }; class Break: public Statement @@ -398,7 +398,7 @@ class Break: public Statement public: Break(Location const& _location): Statement(_location) {} virtual void accept(ASTVisitor& _visitor) override; - virtual void checkTypeRequirements() override; + virtual void checkTypeRequirements() override {} }; class Return: public Statement From 8e02768b104b563fe28a1b70894f7f910b3124fb Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 5 Nov 2014 18:37:27 +0100 Subject: [PATCH 2/6] Tests for break and continue in nested loops. --- test/solidityEndToEndTest.cpp | 36 +++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp index b28b8499a..7b9e07384 100644 --- a/test/solidityEndToEndTest.cpp +++ b/test/solidityEndToEndTest.cpp @@ -151,6 +151,42 @@ BOOST_AUTO_TEST_CASE(while_loop) BOOST_CHECK(framework.callFunction(0, u256(4)) == toBigEndian(u256(24))); } +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; + framework.compileAndRun(sourceCode); + 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(2)) == toBigEndian(u256(1))); + BOOST_CHECK(framework.callFunction(0, u256(3)) == toBigEndian(u256(2))); + 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) { // note that the index of a function is its index in the sorted sequence of functions From c87f1c76b4f36d816bc84eb5e0830a7855468b16 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 5 Nov 2014 18:44:05 +0100 Subject: [PATCH 3/6] Ignore break and continue outside of loops. --- libsolidity/Compiler.cpp | 10 ++++------ test/solidityEndToEndTest.cpp | 13 +++++++++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/libsolidity/Compiler.cpp b/libsolidity/Compiler.cpp index 654eceadb..d05552b9e 100644 --- a/libsolidity/Compiler.cpp +++ b/libsolidity/Compiler.cpp @@ -252,17 +252,15 @@ bool Compiler::visit(WhileStatement& _whileStatement) bool Compiler::visit(Continue&) { - if (asserts(!m_continueTags.empty())) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Jump tag not available for \"continue\".")); - m_context.appendJumpTo(m_continueTags.back()); + if (!m_continueTags.empty()) + m_context.appendJumpTo(m_continueTags.back()); return false; } bool Compiler::visit(Break&) { - if (asserts(!m_breakTags.empty())) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Jump tag not available for \"break\".")); - m_context.appendJumpTo(m_breakTags.back()); + if (!m_breakTags.empty()) + m_context.appendJumpTo(m_breakTags.back()); return false; } diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp index 7b9e07384..116310aed 100644 --- a/test/solidityEndToEndTest.cpp +++ b/test/solidityEndToEndTest.cpp @@ -151,6 +151,19 @@ BOOST_AUTO_TEST_CASE(while_loop) BOOST_CHECK(framework.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 From 41da8fb27abb19de164ea9057e5789a18f1801bf Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 6 Nov 2014 14:57:46 +0000 Subject: [PATCH 4/6] Fix ECRECOVER to zero out the first 12 bytes of result. --- libethereum/State.cpp | 1 + stdserv.js | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index c125a687b..c2bccad42 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -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)) ret = dev::sha3(bytesConstRef(&(pubkey[1]), 64)); + memset(ret.data(), 0, 12); memcpy(_out.data(), &ret, min(_out.size(), sizeof(ret))); } diff --git a/stdserv.js b/stdserv.js index 68d33ddd9..55ae90d86 100644 --- a/stdserv.js +++ b/stdserv.js @@ -55,6 +55,14 @@ eth.transact({ 'code': nameRegCode }, function(a) { nameReg = a; }); env.note('Register 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 dnsReg; From 4014a3d0c81d3765645fdd91fd87137b8151f7c4 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 6 Nov 2014 15:21:53 +0000 Subject: [PATCH 5/6] Fix all the asBytes stuff. --- alethzero/MainWin.cpp | 2 +- libdevcore/CommonJS.cpp | 3 +-- libweb3jsonrpc/WebThreeStubServer.cpp | 14 +++++++------- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index cd6cad11a..56a9e35bc 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1268,7 +1268,7 @@ void Main::on_blocks_currentItemChanged() s << "   #" << tx.nonce() << ""; s << "
Gas price: " << formatBalance(tx.gasPrice()) << ""; s << "
Gas: " << tx.gas() << ""; - s << "
V: " << hex << nouppercase << (int)tx.signature().v << ""; + s << "
V: " << hex << nouppercase << (int)tx.signature().v << " + 27"; s << "
R: " << hex << nouppercase << tx.signature().r << ""; s << "
S: " << hex << nouppercase << tx.signature().s << ""; s << "
Msg: " << tx.sha3(eth::WithoutSignature) << ""; diff --git a/libdevcore/CommonJS.cpp b/libdevcore/CommonJS.cpp index d362f66ab..96f4b1896 100644 --- a/libdevcore/CommonJS.cpp +++ b/libdevcore/CommonJS.cpp @@ -35,8 +35,7 @@ bytes jsToBytes(std::string const& _s) // Decimal return toCompactBigEndian(bigint(_s)); else - // Binary - return asBytes(_s); + return bytes(); } std::string jsPadded(std::string const& _s, unsigned _l, unsigned _r) diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 89d45f4e0..031fc907a 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -211,7 +211,7 @@ static shh::Message toMessage(Json::Value const& _json) if (!_json["to"].empty()) ret.setTo(jsToPublic(_json["to"].asString())); if (!_json["payload"].empty()) - ret.setPayload(asBytes(_json["payload"].asString())); + ret.setPayload(jsToBytes(_json["payload"].asString())); return ret; } @@ -228,10 +228,10 @@ static shh::Envelope toSealed(Json::Value const& _json, shh::Message const& _m, if (!_json["topic"].empty()) { if (_json["topic"].isString()) - bt.shift(asBytes(jsPadded(_json["topic"].asString(), 32))); + bt.shift(jsToBytes(_json["topic"])); else if (_json["topic"].isArray()) for (auto i: _json["topic"]) - bt.shift(asBytes(jsPadded(i.asString(), 32))); + bt.shift(jsToBytes(i.asString())); } return _m.seal(_from, bt, ttl, workToProve); } @@ -247,12 +247,12 @@ static pair toWatch(Json::Value const& _json) if (!_json["topic"].empty()) { if (_json["topic"].isString()) - bt.shift(asBytes(jsPadded(_json["topic"].asString(), 32))); + bt.shift(jsToBytes(_json["topic"].asString())); else if (_json["topic"].isArray()) for (auto i: _json["topic"]) { if (i.isString()) - bt.shift(asBytes(jsPadded(i.asString(), 32))); + bt.shift(jsToBytes(i.asString())); else bt.shift(); } @@ -372,10 +372,10 @@ static TransactionSkeleton toTransaction(Json::Value const& _json) ret.data = jsToBytes(_json["code"].asString()); else if (_json["data"].isArray()) 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()) 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()) for (auto i: _json["dataclose"]) dev::operator +=(ret.data, jsToBytes(i.asString())); From d395b82f1b5705807048162430f4d3d28c504169 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 6 Nov 2014 15:47:19 +0000 Subject: [PATCH 6/6] Nicer uncle info. Fix for fromAscii/toAscii and asBytes usage. --- alethzero/MainWin.cpp | 7 +++++++ libjsqrc/main.js | 4 +++- libweb3jsonrpc/WebThreeStubServer.cpp | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 56a9e35bc..6d91767b8 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1243,6 +1243,13 @@ void Main::on_blocks_currentItemChanged() s << "
Log Bloom: " << info.logBloom << ""; s << "
Transactions: " << block[1].itemCount() << " @" << info.transactionsRoot << ""; s << "
Uncles: " << block[2].itemCount() << " @" << info.sha3Uncles << ""; + for (auto u: block[2]) + { + BlockInfo uncle = BlockInfo::fromHeader(u.data()); + s << "
 Hash: " << uncle.hash << ""; + s << "
 Parent: " << uncle.parentHash << ""; + s << "
 Number: " << uncle.number << ""; + } if (info.parentHash) s << "
Pre: " << BlockInfo(ethereum()->blockChain().block(info.parentHash)).stateRoot << ""; else diff --git a/libjsqrc/main.js b/libjsqrc/main.js index 3e0a62c40..821de6382 100644 --- a/libjsqrc/main.js +++ b/libjsqrc/main.js @@ -217,6 +217,8 @@ // Find termination var str = ""; var i = 0, l = hex.length; + if (hex.substring(0, 2) == '0x') + i = 2; for(; i < l; i+=2) { var code = hex.charCodeAt(i) if(code == 0) { @@ -238,7 +240,7 @@ var hex = this.toHex(str); while(hex.length < pad*2) hex += "00"; - return hex + return "0x" + hex }, eth: { diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 031fc907a..5b7b56a19 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -228,7 +228,7 @@ static shh::Envelope toSealed(Json::Value const& _json, shh::Message const& _m, if (!_json["topic"].empty()) { if (_json["topic"].isString()) - bt.shift(jsToBytes(_json["topic"])); + bt.shift(jsToBytes(_json["topic"].asString())); else if (_json["topic"].isArray()) for (auto i: _json["topic"]) bt.shift(jsToBytes(i.asString()));