From 44525c5f06082e1b69dc24f72ce90aa9df19ac4b Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 6 Jul 2014 04:23:13 +0200 Subject: [PATCH] Compiler fixes. Updates for coins. --- alethzero/MainWin.cpp | 41 +++++++---- libethereum/Client.cpp | 4 +- liblll/Assembly.cpp | 2 + liblll/CodeFragment.cpp | 3 + liblll/CompilerState.cpp | 16 +++-- liblll/CompilerState.h | 2 +- liblll/Parser.cpp | 13 ++-- stdserv.js | 147 +++++++++++++++++++++++++++++---------- 8 files changed, 161 insertions(+), 67 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index fd3b2a5a6..851e45aa1 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -274,6 +274,18 @@ void Main::eval(QString const& _js) ui->jsConsole->setHtml(s); } +QString fromRaw(eth::h256 _n) +{ + if (_n) + { + std::string s((char const*)_n.data(), 32); + if (s.find_first_of('\0') != string::npos) + s.resize(s.find_first_of('\0')); + return QString::fromStdString(s); + } + return QString(); +} + QString Main::pretty(eth::Address _a) const { h256 n; @@ -284,14 +296,7 @@ QString Main::pretty(eth::Address _a) const if (!n) n = state().storage(m_nameReg, (u160)(_a)); - if (n) - { - std::string s((char const*)n.data(), 32); - if (s.find_first_of('\0') != string::npos) - s.resize(s.find_first_of('\0')); - return QString::fromStdString(s); - } - return QString(); + return fromRaw(n); } QString Main::render(eth::Address _a) const @@ -494,7 +499,7 @@ void Main::updateBlockCount() { auto d = m_client->blockChain().details(); auto diff = BlockInfo(m_client->blockChain().block()).difficulty; - ui->blockCount->setText(QString("#%1 @%3 T%2").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff))); + ui->blockCount->setText(QString("#%1 @%3 T%2 N%4").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)).arg(eth::c_protocolVersion)); } void Main::on_blockChainFilter_textChanged() @@ -659,8 +664,11 @@ void Main::refresh(bool _override) m_keysChanged = false; ui->ourAccounts->clear(); u256 totalBalance = 0; - u256 totalGavCoinBalance = 0; - Address gavCoin = fromString("GavCoin"); + map> altCoins; + Address coinsAddr = right160(st.storage(c_config, 1)); + for (unsigned i = 0; i < st.storage(coinsAddr, 0); ++i) + altCoins[right160(st.storage(coinsAddr, st.storage(coinsAddr, i + 1)))] = make_pair(fromRaw(st.storage(coinsAddr, i + 1)), 0); +// u256 totalGavCoinBalance = 0; for (auto i: m_myKeys) { u256 b = st.balance(i.address()); @@ -668,10 +676,15 @@ void Main::refresh(bool _override) ->setData(Qt::UserRole, QByteArray((char const*)i.address().data(), Address::size)); totalBalance += b; - totalGavCoinBalance += st.storage(gavCoin, (u160)i.address()); + for (auto& c: altCoins) + c.second.second += (u256)st.storage(c.first, (u160)i.address()); } - ui->balance->setText(QString::fromStdString(toString(totalGavCoinBalance) + " GAV | " + formatBalance(totalBalance))); + QString b; + for (auto const& c: altCoins) + if (c.second.second) + b += QString::fromStdString(toString(c.second.second)) + " " + c.second.first.toUpper() + " | "; + ui->balance->setText(b + QString::fromStdString(formatBalance(totalBalance))); } } @@ -1019,7 +1032,7 @@ void Main::on_data_textChanged() QString s = ui->data->toPlainText(); while (s.size()) { - QRegExp r("(@|\\$)?\"(.*)\"(.*)"); + QRegExp r("(@|\\$)?\"([^\"]*)\"(.*)"); QRegExp h("(@|\\$)?(0x)?(([a-fA-F0-9])+)(.*)"); if (r.exactMatch(s)) { diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 602fa837e..7be4d2465 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -371,7 +371,7 @@ PastTransactions Client::transactions(TransactionFilter const& _f) const // Handle pending transactions differently as they're not on the block chain. if (_f.latest() == 0) { - for (unsigned i = m_postMine.pending().size(); i--;) + for (unsigned i = m_postMine.pending().size(); i-- && ret.size() != m;) if (_f.matches(m_postMine, i)) { if (s) @@ -391,7 +391,7 @@ PastTransactions Client::transactions(TransactionFilter const& _f) const try { State st(m_stateDB, m_bc, h); - for (unsigned i = st.pending().size(); i--;) + for (unsigned i = st.pending().size(); i-- && ret.size() != m;) if (_f.matches(st, i)) { if (s) diff --git a/liblll/Assembly.cpp b/liblll/Assembly.cpp index f4d700f92..6f5678539 100644 --- a/liblll/Assembly.cpp +++ b/liblll/Assembly.cpp @@ -74,12 +74,14 @@ unsigned Assembly::bytesRequired() const void Assembly::append(Assembly const& _a) { + auto newDeposit = m_deposit + _a.deposit(); for (AssemblyItem i: _a.m_items) { if (i.type() == Tag || i.type() == PushTag) i.m_data += m_usedTags; append(i); } + m_deposit = newDeposit; m_usedTags += _a.m_usedTags; for (auto const& i: _a.m_data) m_data.insert(i); diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index 70973aab4..47c83e635 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -151,6 +151,9 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) case 5: us = "SEQ"; break; + case 6: + us = "CALLDATALOAD"; + break; default:; } diff --git a/liblll/CompilerState.cpp b/liblll/CompilerState.cpp index e1d710110..380d5a66f 100644 --- a/liblll/CompilerState.cpp +++ b/liblll/CompilerState.cpp @@ -45,18 +45,20 @@ void CompilerState::populateStandard() { static const string s = "{" "(def 'gav 0x51ba59315b3a95761d0863b05ccc7a7f54703d99)" - "(def 'namereg 0x2d0aceee7e5ab874e22ccf8d1a649f59106d74e8)" - "(def 'config 0xccdeac59d35627b7de09332e819d5159e7bb7250)" + "(def 'config 0x661005d2720d855f1d9976f88bb10c1a3398c77f)" + "(def 'namereg 0x50441127ea5b9dfd835a9aba4e1dc9c1257b58ca)" "(def 'gavcoin 0x5620133321fcac7f15a5c570016f6cb6dc263f9d)" - "(def 'sendgavcoin (to value) { [0]:to [32]:value (call (- (gas) 21) gavcoin 0 0 64 0 0) })" - "(def 'regname (name) { [0]:name (call (- (gas) 21) namereg 0 0 32 0 0) })" - "(def 'send (to value) (call (- (gas) 21) to value 0 0 0 0))" + "(def 'allgas (- (gas) 21))" + "(def 'sendgavcoin (to value) { [0]'send [32]:to [64]:value (call allgas gavcoin 0 0 96 0 0) })" + "(def 'regname (name) { [0]'register [32]name (call allgas namereg 0 0 64 0 0) })" + "(def 'regcoins (name) { [0]'register [32]name (call allgas namereg 0 0 64 0 0) })" + "(def 'send (to value) (call allgas to value 0 0 0 0))" "(def 'send (gaslimit to value) (call gaslimit to value 0 0 0 0))" "(def 'msg (gaslimit to value data datasize outsize) { (set x outsize) (set y (alloc @32)) (call gaslimit to value data datasize @0 @32) @0 })" "(def 'msg (gaslimit to value data datasize) { (call gaslimit to value data datasize 0 32) @0 })" "(def 'msg (gaslimit to value data) { [0]:data (msg gaslimit to value 0 32) })" - "(def 'msg (to value data) { [0]:data (msg (- gas 21) to value 0 32) })" - "(def 'msg (to data) { [0]:data (msg (- gas 21) to 0 0 32) })" + "(def 'msg (to value data) { [0]:data (msg allgas to value 0 32) })" + "(def 'msg (to data) { [0]:data (msg allgas to 0 0 32) })" "(def 'create (value code) { [0]:(msize) (create value @0 (lll code @0)) })" "(def 'create (code) { [0]:(msize) (create 0 @0 (lll code @0)) })" "(def 'sha3 (val) { [0]:val (sha3 0 32) })" diff --git a/liblll/CompilerState.h b/liblll/CompilerState.h index 5dcde6147..a0b3bf46e 100644 --- a/liblll/CompilerState.h +++ b/liblll/CompilerState.h @@ -41,7 +41,7 @@ struct CompilerState CodeFragment const& getDef(std::string const& _s); void populateStandard(); - unsigned stackSize = 64; + unsigned stackSize = 128; std::map> vars; ///< maps name to stack offset & size. std::map defs; std::map args; diff --git a/liblll/Parser.cpp b/liblll/Parser.cpp index 53580898c..314e6cf78 100644 --- a/liblll/Parser.cpp +++ b/liblll/Parser.cpp @@ -56,6 +56,7 @@ void eth::debugOutAST(ostream& _out, sp::utree const& _this) case 3: _out << "[ "; debugOutAST(_out, _this.front()); _out << " ] "; debugOutAST(_out, _this.back()); break; case 4: _out << "[[ "; debugOutAST(_out, _this.front()); _out << " ]] "; debugOutAST(_out, _this.back()); break; case 5: _out << "{ "; for (auto const& i: _this) { debugOutAST(_out, i); _out << " "; } _out << "}"; break; + case 6: _out << "$ "; debugOutAST(_out, _this.front()); break; default:; } @@ -80,8 +81,8 @@ void eth::parseTreeLLL(string const& _s, sp::utree& o_out) qi::rule element; qi::rule str = '"' > qi::lexeme[+(~qi::char_(std::string("\"") + '\0'))] > '"'; - qi::rule strsh = '\'' > qi::lexeme[+(~qi::char_(std::string(" ;@()[]{}:") + '\0'))]; - qi::rule symbol = qi::lexeme[+(~qi::char_(std::string(" @[]{}:();\"\x01-\x1f\x7f") + '\0'))]; + qi::rule strsh = '\'' > qi::lexeme[+(~qi::char_(std::string(" ;$@()[]{}:\n\t") + '\0'))]; + qi::rule symbol = qi::lexeme[+(~qi::char_(std::string(" $@[]{}:();\"\x01-\x1f\x7f") + '\0'))]; qi::rule intstr = qi::lexeme[ qi::no_case["0x"][qi::_val = "0x"] >> *qi::char_("0-9a-fA-F")[qi::_val += qi::_1]] | qi::lexeme[+qi::char_("0-9")[qi::_val += qi::_1]]; qi::rule integer = intstr; qi::rule multiplier = qi::lit("wei")[qi::_val = 1] | qi::lit("szabo")[qi::_val = szabo] | qi::lit("finney")[qi::_val = finney] | qi::lit("ether")[qi::_val = ether]; @@ -92,10 +93,11 @@ void eth::parseTreeLLL(string const& _s, sp::utree& o_out) qi::rule sload = qi::lit("@@") > element; qi::rule mstore = '[' > element > ']' > -qi::lit(":") > element; qi::rule sstore = qi::lit("[[") > element > qi::lit("]]") > -qi::lit(":") > element; + qi::rule calldataload = qi::lit("$") > element; qi::rule list = '(' > *element > ')'; auto x = [](int a) { return [=](sp::utree& n, typename qi::rule::context_type& c) { (boost::fusion::at_c<0>(c.attributes) = n).tag(a); }; }; - qi::rule extra = sload[x(2)] | mload[x(1)] | sstore[x(4)] | mstore[x(3)] | seq[x(5)]; + qi::rule extra = sload[x(2)] | mload[x(1)] | sstore[x(4)] | mstore[x(3)] | seq[x(5)] | calldataload[x(6)]; element = atom | list | extra; string s; @@ -120,7 +122,8 @@ void eth::parseTreeLLL(string const& _s, sp::utree& o_out) } auto ret = s.cbegin(); qi::phrase_parse(ret, s.cend(), element, space, qi::skip_flag::dont_postskip, o_out); - if (ret != s.cend()) - throw std::exception(); + for (auto i = ret; i != s.cend(); ++i) + if (!isspace(*i)) + throw std::exception(); } diff --git a/stdserv.js b/stdserv.js index d3a1fb212..188ab781a 100644 --- a/stdserv.js +++ b/stdserv.js @@ -1,44 +1,48 @@ env.note('Creating Config...') -var configCode = eth.lll("{ +var configCode = eth.lll(" +{ [[69]] (caller) - (returnlll - (when (= (caller) @@69) + (returnlll { + (when (&& (= (calldatasize) 64) (= (caller) @@69)) (for {} (< @i (calldatasize)) [i](+ @i 64) [[ (calldataload @i) ]] (calldataload (+ @i 32)) ) ) - ) -}") + (return @@ $0) + }) +} +") env.note('Config code: ' + configCode.unbin()) var config = "0x9ef0f0d81e040012600b0c1abdef7c48f720f88a"; eth.create(eth.key, '0', configCode, 10000, eth.gasPrice, function(a) { config = a; }) env.note('Config at address ' + config) -var nameRegCode = eth.lll("{ +var nameRegCode = eth.lll(" +{ [[(address)]] 'NameReg [['NameReg]] (address) [[" + config + "]] 'Config [['Config]] " + config + " [[69]] (caller) - (returnlll - (if (calldatasize) - { - (when @@(calldataload 0) (stop)) - (when @@(caller) [[@@(caller)]] 0) - [[(calldataload 0)]] (caller) - [[(caller)]] (calldataload 0) - } - { - (when (= (caller) @@69) (suicide (caller))) - (when @@(caller) { - [[@@(caller)]] 0 - [[(caller)]] 0 - }) - } - ) - ) -}"); + (returnlll { + (when (= $0 'register) { + (when @@ $32 (stop)) + (when @@(caller) [[@@(caller)]] 0) + [[$32]] (caller) + [[(caller)]] $32 + (stop) + }) + (when (&& (= $0 'unregister) @@(caller)) { + [[@@(caller)]] 0 + [[(caller)]] 0 + (stop) + }) + (when (&& (= $0 'kill) (= (caller) @@69)) (suicide (caller))) + (return @@ $0) + }) +} +"); env.note('NameReg code: ' + nameRegCode.unbin()) var nameReg = "0x3face8f2b3ef580265f0f67a57ce0fb78b135613"; @@ -50,22 +54,89 @@ env.note('NameReg at address ' + nameReg) env.note('Register NameReg...') eth.transact(eth.key, '0', config, "0".pad(32) + nameReg.pad(32), 10000, eth.gasPrice); -var gavCoinCode = eth.lll("{ - [[ (caller) ]]: 0x1000000 - (call (- (gas) 100) " + nameReg + " 0 0 (lit 0 'GavCoin) 0 0) - (returnlll { - (when (!= (calldatasize) 64) (stop)) - [fromBal] @@(caller) - [toBal]: @@(calldataload 0) - [value]: (calldataload 32) - (when (< @fromBal @value) (stop)) - [[ (caller) ]]: (- @fromBal @value) - [[ (calldataload 0) ]]: (+ @toBal @value) - }) -}"); +var coinsCode = eth.lll(" +{ +[0]'register [32]'Coins +(msg allgas " + nameReg + " 0 0 64) +(returnlll { + (def 'name $0) + (def 'address (caller)) + (when (|| (& 0xffffffffffffffffffffffffff name) @@name) (stop)) + (set 'n (+ @@0 1)) + [[0]] @n + [[@n]] name + [[name]] address +}) +} +"); + +var coins; +env.note('Create Coins...') +eth.create(eth.key, '0', coinsCode, 10000, eth.gasPrice, function(a) { coins = a; }) + +env.note('Coins at address ' + coins) +env.note('Register Coins...') +eth.transact(eth.key, '0', config, "1".pad(32) + coins.pad(32), 10000, eth.gasPrice); + +var gavCoinCode = eth.lll(" +{ +[[ (caller) ]] 0x1000000 +[[ 0x69 ]] (caller) +[[ 0x42 ]] (number) + +[0]'register [32]'GavCoin +(msg allgas " + nameReg + " 0 0 64) +(msg " + coins + " 'GAV) + +(returnlll { + (when (&& (= $0 'kill) (= (caller) @@0x69)) (suicide (caller))) + (when (= $0 'balance) (return @@$32)) + (when (= $0 'approved) (return @@ @(sha3 (^ (if (= (calldatasize) 64) (caller) $64) $32))) ) + + (when (= $0 'approve) { + [[@(sha3 (^ (caller) $32))]] $32 + (stop) + }) + + (when (= $0 'send) { + (set 'fromVar (if (= (calldatasize) 96) + (caller) + { + (when (! @@ @(sha3 (^ $96 $32)) ) (stop)) + $96 + } + )) + (def 'to $32) + (def 'value $64) + (def 'from (get 'fromVar)) + (set 'fromBal @@from) + (when (< @fromBal value) (stop)) + [[ from ]]: (- @fromBal value) + [[ to ]]: (+ @@to value) + (stop) + }) + + (set 'n @@0x42) + (when (&& (|| (= $0 'mine) (! (calldatasize))) (> (number) @n)) { + [[(coinbase)]] (+ @@(coinbase) 1024) + [[0x42]] (+ @n 1) + }) + + (return @@ $0) +}) +} +"); + +var gavCoin; env.note('Create GavCoin...') -eth.create(eth.key, '0', gavCoinCode, 10000, eth.gasPrice); +eth.create(eth.key, '0', gavCoinCode, 10000, eth.gasPrice, function(a) { gavCoin = a; }); + +env.note('Register GavCoin...') +eth.transact(eth.key, '0', config, "2".pad(32) + gavCoin.pad(32), 10000, eth.gasPrice); + +env.note('Register my name...') +eth.transact(eth.key, '0', nameReg, "register".pad(32) + "Gav".pad(32), 10000, eth.gasPrice); env.note('All done.')