diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index fc34be318..01bd22d4f 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -372,7 +372,7 @@ void Main::on_destination_textChanged() void Main::on_data_textChanged() { string code = ui->data->toPlainText().toStdString(); - m_data = code[0] == '(' ? compileLisp(code, true) : assemble(code); + m_data = code[0] == '(' ? compileLisp(code, true) : assemble(code, true); ui->code->setPlainText(QString::fromStdString(disassemble(m_data))); updateFee(); } diff --git a/libethereum/Common.h b/libethereum/Common.h index bbb319d4e..12028d7a1 100644 --- a/libethereum/Common.h +++ b/libethereum/Common.h @@ -216,7 +216,7 @@ public: char buf[24]; if (strftime(buf, 24, "%X", localtime(&rawTime)) == 0) buf[0] = '\0'; // empty if case strftime fails - sstr << Id::name << " [ " << buf << " | " << *(t_logThreadName.m_name.get()) << (_term ? " ] " : ""); + sstr << Id::name() << " [ " << buf << " | " << *(t_logThreadName.m_name.get()) << (_term ? " ] " : ""); } } ~LogOutputStream() { if (Id::verbosity <= g_logVerbosity) g_logPost(sstr.str(), Id::name()); } diff --git a/libethereum/Instruction.cpp b/libethereum/Instruction.cpp index 3e4679495..fb34f9d6d 100644 --- a/libethereum/Instruction.cpp +++ b/libethereum/Instruction.cpp @@ -25,45 +25,60 @@ using namespace std; using namespace eth; -u256s eth::assemble(std::string const& _code) +u256s eth::assemble(std::string const& _code, bool _quiet) { u256s ret; + map known; + map req; char const* d = _code.data(); char const* e = _code.data() + _code.size(); while (d != e) { // skip to next token - for (; d != e && !isalnum(*d) && *d != '_'; ++d) {} + for (; d != e && !isalnum(*d) && *d != '_' && *d != ':'; ++d) {} if (d == e) break; char const* s = d; - for (; d != e && (isalnum(*d) || *d == '_'); ++d) {} + for (; d != e && (isalnum(*d) || *d == '_' || *d == ':'); ++d) {} string t = string(s, d - s); if (isdigit(t[0])) - ret.push_back(u256(t)); + try + { + ret.push_back(u256(t)); + } + catch (...) + { + cwarn << "Invalid numeric" << t; + } + else if (t.back() == ':') + known[t.substr(0, t.size() - 1)] = ret.size(); else { - boost::algorithm::to_upper(t); - auto it = c_instructions.find(t); + auto it = c_instructions.find(boost::algorithm::to_upper_copy(t)); if (it != c_instructions.end()) ret.push_back((u256)it->second); else - cwarn << "Unknown assembler token" << t; + { + req[ret.size()] = t; + ret.push_back(0); + } } } + for (auto i: req) + if (known.count(i.second)) + ret[i.first] = known[i.second]; + else + cwarn << "Unknown assembler token" << i.second << "at address" << i.first; + return ret; } -u256s eth::compileLisp(std::string const& _code, bool _quiet) +static bool compileLispFragment(char const*& d, char const* e, bool _quiet, unsigned _off, u256s& o_code, vector& o_locs) { - u256s ret; - vector> inStack; + bool exec = false; - - char const* d = _code.data(); - char const* e = _code.data() + _code.size(); while (d != e) { // skip to next token @@ -74,59 +89,105 @@ u256s eth::compileLisp(std::string const& _code, bool _quiet) switch (*d) { case '(': - inStack.push_back(make_pair(Instruction::STOP, 0)); + exec = true; ++d; break; case ')': - ++d; - if (inStack.size()) - ret.push_back(inStack.back().first); - inStack.pop_back(); - if (inStack.size()) - inStack.back().second++; - break; + if (exec) + { + ++d; + return true; + } + else + // unexpected - return false as we don't know what to do with it. + return false; default: { char const* s = d; - for (; d != e && isalnum(*d); ++d) {} + for (; d != e && (isalnum(*d) || *d == '_'); ++d) {} - string t = string(s, d - s); + string t(s, d - s); if (isdigit(t[0])) - if (inStack.size() && !inStack.back().second) + { + if (exec) { - if (!_quiet) - cwarn << "Cannot execute numeric" << t; + cwarn << "Cannot execute numeric" << t; } else { - ret.push_back(Instruction::PUSH); - ret.push_back(u256(t)); + o_code.push_back(Instruction::PUSH); + try + { + o_code.push_back(u256(t)); + } + catch (...) + { + cwarn << "Invalid numeric" << t; + } } + } else { boost::algorithm::to_upper(t); - auto it = c_instructions.find(t); - if (it != c_instructions.end()) + if (t == "IF") + { + + } + else { - if (inStack.size()) + auto it = c_instructions.find(t); + if (it != c_instructions.end()) { - if (!inStack.back().second) - inStack.back().first = it->second; + if (exec) + { + vector>> codes(1); + while (d != e && compileLispFragment(d, e, _quiet, o_code.size(), codes.back().first, codes.back().second)) + codes.push_back(pair>()); + for (auto it = codes.rbegin(); it != codes.rend(); ++it) + { + for (auto i: it->second) + it->first[i] += o_code.size(); + o_code.reserve(o_code.size() + it->first.size()); + for (auto i: it->first) + o_code.push_back(i); + } + o_code.push_back((u256)it->second); + } else - ret.push_back((u256)it->second); - inStack.back().second++; + { + o_code.push_back(Instruction::PUSH); + try + { + o_code.push_back((u256)it->second); + } + catch (...) + { + cwarn << "Invalid numeric" << t; + o_code.push_back(u256(t)); + } + } } else if (!_quiet) - cwarn << "Instruction outside parens" << t; + cwarn << "Unknown assembler token" << t; } - else if (!_quiet) - cwarn << "Unknown assembler token" << t; } + + if (!exec) + return true; } } } - return ret; + return false; +} +u256s eth::compileLisp(std::string const& _code, bool _quiet) +{ + char const* d = _code.data(); + char const* e = _code.data() + _code.size(); + u256s ret; + vector locs; + compileLispFragment(d, e, _quiet, 0, ret, locs); + return ret; } string eth::disassemble(u256s const& _mem) diff --git a/libethereum/Instruction.h b/libethereum/Instruction.h index 5de76323b..657153d05 100644 --- a/libethereum/Instruction.h +++ b/libethereum/Instruction.h @@ -143,7 +143,7 @@ static const std::map c_instructionInfo = { Instruction::IND, { "IND", 0, 0, 1 } }, { Instruction::EXTRO, { "EXTRO", 0, 2, 1 } }, { Instruction::BALANCE, { "BALANCE", 0, 1, 1 } }, - { Instruction::MKTX, { "MKTX", 0, 4, 0 } }, + { Instruction::MKTX, { "MKTX", 0, -3, 0 } }, { Instruction::SUICIDE, { "SUICIDE", 0, 1, 0} } }; @@ -202,7 +202,7 @@ static const std::map c_instructions = { "SUICIDE", Instruction::SUICIDE } }; -u256s assemble(std::string const& _code); +u256s assemble(std::string const& _code, bool _quiet = false); std::string disassemble(u256s const& _mem); u256s compileLisp(std::string const& _code, bool _quiet = false); diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 8badddcb6..6dd5e1c03 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -278,6 +278,10 @@ void State::resetCurrent() m_currentBlock.parentHash = m_previousBlock.hash; m_currentBlock.sha3Transactions = h256(); m_currentBlock.sha3Uncles = h256(); + + // Update timestamp according to clock. + m_currentBlock.timestamp = time(0); + m_state.setRoot(m_currentBlock.stateRoot); } @@ -489,9 +493,6 @@ void State::commitToMine(BlockChain const& _bc) MineInfo State::mine(uint _msTimeout) { - // Update timestamp according to clock. - m_currentBlock.timestamp = time(0); - // Update difficulty according to timestamp. m_currentBlock.difficulty = m_currentBlock.calculateDifficulty(m_previousBlock); @@ -927,7 +928,7 @@ void State::execute(Address _myAddress, Address _txSender, u256 _txValue, u256s stack.push_back((u160)m_currentBlock.coinbaseAddress); break; case Instruction::BLK_TIMESTAMP: - stack.push_back(m_currentBlock.timestamp); + stack.push_back(m_previousBlock.timestamp); break; case Instruction::BLK_NUMBER: stack.push_back(m_currentNumber); @@ -936,7 +937,7 @@ void State::execute(Address _myAddress, Address _txSender, u256 _txValue, u256s stack.push_back(m_currentBlock.difficulty); break; case Instruction::BLK_NONCE: - stack.push_back(m_currentBlock.nonce); + stack.push_back(m_previousBlock.nonce); break; case Instruction::BASEFEE: stack.push_back(m_fees.multiplier());