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.')