diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index 967bc6b56..d5e81a4f5 100644
--- a/alethzero/MainWin.cpp
+++ b/alethzero/MainWin.cpp
@@ -145,7 +145,7 @@ Main::Main(QWidget *parent) :
cerr << "Block Hash: " << CanonBlockChain::genesis().hash << endl;
cerr << "Block RLP: " << RLP(block) << endl;
cerr << "Block Hex: " << toHex(block) << endl;
- cerr << "Network protocol version: " << c_protocolVersion << endl;
+ cerr << "eth Network protocol version: " << eth::c_protocolVersion << endl;
cerr << "Client database version: " << c_databaseVersion << endl;
ui->configDock->close();
@@ -162,7 +162,7 @@ Main::Main(QWidget *parent) :
QSettings s("ethereum", "alethzero");
m_networkConfig = s.value("peers").toByteArray();
bytesConstRef network((byte*)m_networkConfig.data(), m_networkConfig.size());
- m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/AlethZero", false, {"eth", "shh"}, p2p::NetworkPreferences(), network));
+ m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir(), false, {"eth", "shh"}, p2p::NetworkPreferences(), network));
m_httpConnector.reset(new jsonrpc::HttpServer(8080));
m_server.reset(new OurWebThreeStubServer(*m_httpConnector, *web3(), keysAsVector(m_myKeys), this));
@@ -312,7 +312,7 @@ void Main::installBalancesWatch()
Address coinsAddr = getCurrencies();
// TODO: Update for new currencies reg.
- for (unsigned i = 0; i < ethereum()->stateAt(coinsAddr, 0); ++i)
+ for (unsigned i = 0; i < ethereum()->stateAt(coinsAddr, PendingBlock); ++i)
altCoins.push_back(right160(ethereum()->stateAt(coinsAddr, i + 1)));
for (auto i: m_myKeys)
for (auto c: altCoins)
@@ -583,7 +583,7 @@ Address Main::fromString(QString const& _n) const
{
try
{
- return Address(fromHex(_n.toStdString(), ThrowType::Throw));
+ return Address(fromHex(_n.toStdString(), WhenError::Throw));
}
catch (BadHexCharacter& _e)
{
@@ -616,10 +616,10 @@ QString Main::lookup(QString const& _a) const
h256 ret;
// TODO: fix with the new DNSreg contract
-// if (h160 dnsReg = (u160)ethereum()->stateAt(c_config, 4, 0))
+// if (h160 dnsReg = (u160)ethereum()->stateAt(c_config, 4, PendingBlock))
// ret = ethereum()->stateAt(dnsReg, n);
/* if (!ret)
- if (h160 nameReg = (u160)ethereum()->stateAt(c_config, 0, 0))
+ if (h160 nameReg = (u160)ethereum()->stateAt(c_config, 0, PendingBlock))
ret = ethereum()->stateAt(nameReg, n2);
*/
if (ret && !((u256)ret >> 32))
@@ -937,7 +937,7 @@ void Main::refreshBalances()
u256 totalBalance = 0;
/* map
> altCoins;
Address coinsAddr = getCurrencies();
- for (unsigned i = 0; i < ethereum()->stateAt(coinsAddr, 0); ++i)
+ for (unsigned i = 0; i < ethereum()->stateAt(coinsAddr, PendingBlock); ++i)
{
auto n = ethereum()->stateAt(coinsAddr, i + 1);
auto addr = right160(ethereum()->stateAt(coinsAddr, n));
@@ -1059,7 +1059,7 @@ void Main::refreshBlockCount()
{
cwatch << "refreshBlockCount()";
auto d = ethereum()->blockChain().details();
- ui->blockCount->setText(QString("%4 #%1 PV%2 D%3 H%5").arg(d.number).arg(c_protocolVersion).arg(c_databaseVersion).arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet").arg(c_ethashVersion));
+ ui->blockCount->setText(QString("%4 #%1 PV%2 D%3 H%5").arg(d.number).arg(eth::c_protocolVersion).arg(c_databaseVersion).arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet").arg(c_ethashVersion));
}
void Main::on_turboMining_triggered()
@@ -1357,7 +1357,7 @@ void Main::on_transactionQueue_currentItemChanged()
auto r = receipt.rlp();
s << "Receipt: " << toString(RLP(r)) << "
";
s << "Receipt-Hex: " Span(Mono) << toHex(receipt.rlp()) << "
";
- s << renderDiff(ethereum()->diff(i, 0));
+ s << renderDiff(ethereum()->diff(i, PendingBlock));
// s << "Pre: " << fs.rootHash() << "
";
// s << "Post: " << ts.rootHash() << "";
}
@@ -1388,7 +1388,7 @@ void Main::on_inject_triggered()
QString s = QInputDialog::getText(this, "Inject Transaction", "Enter transaction dump in hex");
try
{
- bytes b = fromHex(s.toStdString(), ThrowType::Throw);
+ bytes b = fromHex(s.toStdString(), WhenError::Throw);
ethereum()->inject(&b);
}
catch (BadHexCharacter& _e)
@@ -1550,7 +1550,7 @@ void Main::on_debugCurrent_triggered()
unsigned txi = item->data(Qt::UserRole + 1).toInt();
bytes t = ethereum()->blockChain().transaction(h, txi);
State s(ethereum()->state(txi, h));
- Executive e(s, ethereum()->blockChain(), 0);
+ Executive e(s, ethereum()->blockChain(), PendingBlock);
Debugger dw(this, this);
dw.populate(e, Transaction(t, CheckSignature::Sender));
dw.exec();
diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp
index 2c77895ff..7248ee4a6 100644
--- a/alethzero/Transact.cpp
+++ b/alethzero/Transact.cpp
@@ -25,6 +25,7 @@
#include "Transact.h"
#include
+#include
#include
#include
#include
@@ -135,7 +136,39 @@ void Transact::updateFee()
ui->total->setPalette(p);
}
-string Transact::getFunctionHashes(dev::solidity::CompilerStack const& _compiler, string const& _contractName)
+void Transact::on_destination_currentTextChanged(QString)
+{
+ if (ui->destination->currentText().size() && ui->destination->currentText() != "(Create Contract)")
+ if (Address a = m_context->fromString(ui->destination->currentText()))
+ ui->calculatedName->setText(m_context->render(a));
+ else
+ ui->calculatedName->setText("Unknown Address");
+ else
+ ui->calculatedName->setText("Create Contract");
+ rejigData();
+// updateFee();
+}
+
+static std::string toString(TransactionException _te)
+{
+ switch (_te)
+ {
+ case TransactionException::Unknown: return "Unknown error";
+ case TransactionException::InvalidSignature: return "Permanent Abort: Invalid transaction signature";
+ case TransactionException::InvalidNonce: return "Transient Abort: Invalid transaction nonce";
+ case TransactionException::NotEnoughCash: return "Transient Abort: Not enough cash to pay for transaction";
+ case TransactionException::OutOfGasBase: return "Permanent Abort: Not enough gas to consider transaction";
+ case TransactionException::BlockGasLimitReached: return "Transient Abort: Gas limit of block reached";
+ case TransactionException::BadInstruction: return "VM Error: Attempt to execute invalid instruction";
+ case TransactionException::BadJumpDestination: return "VM Error: Attempt to jump to invalid destination";
+ case TransactionException::OutOfGas: return "VM Error: Out of gas";
+ case TransactionException::OutOfStack: return "VM Error: VM stack limit reached during execution";
+ case TransactionException::StackUnderflow: return "VM Error: Stack underflow";
+ default:; return std::string();
+ }
+}
+
+static string getFunctionHashes(dev::solidity::CompilerStack const& _compiler, string const& _contractName)
{
string ret = "";
auto const& contract = _compiler.getContractDefinition(_contractName);
@@ -150,186 +183,256 @@ string Transact::getFunctionHashes(dev::solidity::CompilerStack const& _compiler
return ret;
}
-void Transact::on_destination_currentTextChanged(QString)
-{
- if (ui->destination->currentText().size() && ui->destination->currentText() != "(Create Contract)")
- if (Address a = m_context->fromString(ui->destination->currentText()))
- ui->calculatedName->setText(m_context->render(a));
- else
- ui->calculatedName->setText("Unknown Address");
- else
- ui->calculatedName->setText("Create Contract");
- rejigData();
-// updateFee();
-}
-
-void Transact::rejigData()
+static tuple, bytes, string> userInputToCode(string const& _user, bool _opt)
{
- if (isCreation())
+ string lll;
+ string solidity;
+ bytes data;
+ vector errors;
+ if (_user.find_first_not_of("1234567890abcdefABCDEF\n\t ") == string::npos && _user.size() % 2 == 0)
{
- string src = ui->data->toPlainText().toStdString();
- vector errors;
- QString lll;
- QString solidity;
- if (src.find_first_not_of("1234567890abcdefABCDEF") == string::npos && src.size() % 2 == 0)
- m_data = fromHex(src);
- else if (sourceIsSolidity(src))
+ std::string u = _user;
+ boost::replace_all_copy(u, "\n", "");
+ boost::replace_all_copy(u, "\t", "");
+ boost::replace_all_copy(u, " ", "");
+ data = fromHex(u);
+ }
+ else if (sourceIsSolidity(_user))
+ {
+ dev::solidity::CompilerStack compiler(true);
+ try
{
- dev::solidity::CompilerStack compiler(true);
- try
- {
// compiler.addSources(dev::solidity::StandardSources);
- m_data = compiler.compile(src, ui->optimize->isChecked());
- solidity = "Solidity
";
- solidity += "var " + QString::fromStdString(compiler.defaultContractName()) + " = web3.eth.contractFromAbi(" + QString::fromStdString(compiler.getInterface()).replace(QRegExp("\\s"), "").toHtmlEscaped() + ");
";
- solidity += "" + QString::fromStdString(compiler.getSolidityInterface()).toHtmlEscaped() + "
";
- solidity += "" + QString::fromStdString(getFunctionHashes(compiler)).toHtmlEscaped() + "
";
- }
- catch (dev::Exception const& exception)
- {
- ostringstream error;
- solidity::SourceReferenceFormatter::printExceptionInformation(error, exception, "Error", compiler);
- solidity = "Solidity
" + QString::fromStdString(error.str()).toHtmlEscaped() + "
";
- }
- catch (...)
- {
- solidity = "Solidity
Uncaught exception.
";
- }
+ data = compiler.compile(_user, _opt);
+ solidity = "Solidity
";
+ solidity += "var " + compiler.defaultContractName() + " = web3.eth.contract(" + QString::fromStdString(compiler.getInterface()).replace(QRegExp("\\s"), "").toHtmlEscaped().toStdString() + ");
";
+ solidity += "" + QString::fromStdString(compiler.getSolidityInterface()).toHtmlEscaped().toStdString() + "
";
+ solidity += "" + QString::fromStdString(getFunctionHashes(compiler, "")).toHtmlEscaped().toStdString() + "
";
}
+ catch (dev::Exception const& exception)
+ {
+ ostringstream error;
+ solidity::SourceReferenceFormatter::printExceptionInformation(error, exception, "Error", compiler);
+ errors.push_back("Solidity: " + error.str());
+ }
+ catch (...)
+ {
+ errors.push_back("Solidity: Uncaught exception");
+ }
+ }
#ifndef _MSC_VER
- else if (sourceIsSerpent(src))
+ else if (sourceIsSerpent(_user))
+ {
+ try
{
- try
- {
- m_data = dev::asBytes(::compile(src));
- for (auto& i: errors)
- i = "(LLL " + i + ")";
- }
- catch (string const& err)
- {
- errors.push_back("Serpent " + err);
- }
+ data = dev::asBytes(::compile(_user));
}
+ catch (string const& err)
+ {
+ errors.push_back("Serpent " + err);
+ }
+ }
#endif
+ else
+ {
+ data = compileLLL(_user, _opt, &errors);
+ if (errors.empty())
+ {
+ auto asmcode = compileLLLToAsm(_user, _opt);
+ lll = "LLL
" + QString::fromStdString(asmcode).toHtmlEscaped().toStdString() + "
";
+ }
+ }
+ return make_tuple(errors, data, lll + solidity);
+}
+
+string Transact::natspecNotice(Address _to, bytes const& _data)
+{
+ if (ethereum()->codeAt(_to, PendingBlock).size())
+ {
+ string userNotice = m_natSpecDB->getUserNotice(ethereum()->postState().codeHash(_to), _data);
+ if (userNotice.empty())
+ return "Destination contract unknown.";
else
{
- m_data = compileLLL(src, ui->optimize->isChecked(), &errors);
- if (errors.empty())
- {
- auto asmcode = compileLLLToAsm(src, false);
- lll = "Pre
" + QString::fromStdString(asmcode).toHtmlEscaped() + "
";
- if (ui->optimize->isChecked())
- {
- asmcode = compileLLLToAsm(src, true);
- lll = "Opt
" + QString::fromStdString(asmcode).toHtmlEscaped() + "
" + lll;
- }
- }
+ NatspecExpressionEvaluator evaluator;
+ return evaluator.evalExpression(QString::fromStdString(userNotice)).toStdString();
}
- QString errs;
+ }
+ else
+ return "Destination not a contract.";
+}
+
+void Transact::rejigData()
+{
+ if (!ethereum())
+ return;
+
+ // Determine how much balance we have to play with...
+ auto s = findSecret(value() + ethereum()->gasLimitRemaining() * gasPrice());
+ auto b = ethereum()->balanceAt(KeyPair(s).address(), PendingBlock);
+
+ m_allGood = true;
+ QString htmlInfo;
+
+ auto bail = [&](QString he) {
+ m_allGood = false;
+ ui->send->setEnabled(false);
+ ui->code->setHtml(he + htmlInfo);
+ };
+
+ // Determine m_info.
+ if (isCreation())
+ {
+ string info;
+ vector errors;
+ tie(errors, m_data, info) = userInputToCode(ui->data->toPlainText().toStdString(), ui->optimize->isChecked());
if (errors.size())
{
- errs = "Errors
";
+ // Errors determining transaction data (i.e. init code). Bail.
+ QString htmlErrors;
for (auto const& i: errors)
- errs.append("" + QString::fromStdString(i).toHtmlEscaped() + "
");
+ htmlErrors.append("ERROR " + QString::fromStdString(i).toHtmlEscaped() + "
");
+ bail(htmlErrors);
+ return;
}
- ui->code->setHtml(errs + lll + solidity + "Code
" + QString::fromStdString(disassemble(m_data)).toHtmlEscaped() + "Hex
" Div(Mono) + QString::fromStdString(toHex(m_data)) + "");
- ui->gas->setMinimum((qint64)Interface::txGas(m_data, 0));
- if (!ui->gas->isEnabled())
- ui->gas->setValue(m_backupGas);
- ui->gas->setEnabled(true);
- if (ui->gas->value() == ui->gas->minimum() && !src.empty())
- ui->gas->setValue((int)(m_ethereum->postState().gasLimitRemaining() / 10));
+ htmlInfo = QString::fromStdString(info) + "Code
" + QString::fromStdString(disassemble(m_data)).toHtmlEscaped();
}
else
{
m_data = parseData(ui->data->toPlainText().toStdString());
- auto to = m_context->fromString(ui->destination->currentText());
- QString natspec;
- if (ethereum()->codeAt(to, 0).size())
- {
- string userNotice = m_natSpecDB->getUserNotice(ethereum()->postState().codeHash(to), m_data);
- if (userNotice.empty())
- natspec = "Destination contract unknown.";
- else
- {
- NatspecExpressionEvaluator evaluator;
- natspec = evaluator.evalExpression(QString::fromStdString(userNotice));
- }
- ui->gas->setMinimum((qint64)Interface::txGas(m_data, 1));
- if (!ui->gas->isEnabled())
- ui->gas->setValue(m_backupGas);
- ui->gas->setEnabled(true);
- }
- else
- {
- natspec += "Destination not a contract.";
- if (ui->gas->isEnabled())
- m_backupGas = ui->gas->value();
- ui->gas->setValue((qint64)Interface::txGas(m_data));
- ui->gas->setEnabled(false);
- }
- ui->code->setHtml("NatSpec
" + natspec + "Dump
" + QString::fromStdString(dev::memDump(m_data, 8, true)) + "Hex
" + Div(Mono) + QString::fromStdString(toHex(m_data)) + "");
+ htmlInfo = "Dump
" + QString::fromStdString(dev::memDump(m_data, 8, true));
+ }
+
+ htmlInfo += "Hex
" + QString(Div(Mono)) + QString::fromStdString(toHex(m_data)) + "";
+
+ // Determine the minimum amount of gas we need to play...
+ qint64 baseGas = (qint64)Interface::txGas(m_data, 0);
+ qint64 gasNeeded = 0;
+
+ if (b < value() + baseGas * gasPrice())
+ {
+ // Not enough - bail.
+ bail("ERROR No single account contains enough for paying even the basic amount of gas required.
");
+ return;
+ }
+ else
+ gasNeeded = min((qint64)ethereum()->gasLimitRemaining(), (qint64)((b - value()) / gasPrice()));
+
+ // Dry-run execution to determine gas requirement and any execution errors
+ Address to;
+ ExecutionResult er;
+ if (isCreation())
+ er = ethereum()->create(s, value(), m_data, gasNeeded, gasPrice());
+ else
+ {
+ to = m_context->fromString(ui->destination->currentText());
+ er = ethereum()->call(s, value(), to, m_data, ethereum()->gasLimitRemaining(), gasPrice());
+ }
+ gasNeeded = (qint64)er.gasUsed;
+ htmlInfo = QString("INFO Gas required: %1 total = %2 base, %3 exec
").arg(gasNeeded).arg(baseGas).arg(gasNeeded - baseGas) + htmlInfo;
+
+ if (er.excepted != TransactionException::None)
+ {
+ bail("ERROR " + QString::fromStdString(toString(er.excepted)) + "
");
+ return;
+ }
+ if (er.codeDeposit == CodeDeposit::Failed)
+ {
+ bail("ERROR Code deposit failed due to insufficient gas
");
+ return;
+ }
+
+ // Add Natspec information
+ if (!isCreation())
+ htmlInfo = "INFO " + QString::fromStdString(natspecNotice(to, m_data)).toHtmlEscaped() + "
" + htmlInfo;
+
+ // Update gas
+ if (ui->gas->value() == ui->gas->minimum())
+ {
+ ui->gas->setMinimum(gasNeeded);
+ ui->gas->setValue(gasNeeded);
}
+ else
+ ui->gas->setMinimum(gasNeeded);
+
updateFee();
+
+ ui->code->setHtml(htmlInfo);
+ ui->send->setEnabled(m_allGood);
}
-void Transact::on_send_clicked()
+Secret Transact::findSecret(u256 _totalReq) const
{
- u256 totalReq = value() + fee();
+ if (!ethereum())
+ return Secret();
+
+ Secret best;
+ u256 bestBalance = 0;
for (auto const& i: m_myKeys)
- if (ethereum()->balanceAt(i.address(), 0) >= totalReq)
- {
- Secret s = i.secret();
- if (isCreation())
+ {
+ auto b = ethereum()->balanceAt(i.address(), PendingBlock);
+ if (b >= _totalReq)
+ return i.secret();
+ if (b > bestBalance)
+ bestBalance = b, best = i.secret();
+ }
+ return best;
+}
+
+void Transact::on_send_clicked()
+{
+ Secret s = findSecret(value() + fee());
+ auto b = ethereum()->balanceAt(KeyPair(s).address(), PendingBlock);
+ if (!s || b < value() + fee())
+ {
+ QMessageBox::critical(this, "Transaction Failed", "Couldn't make transaction: no single account contains at least the required amount.");
+ return;
+ }
+
+ if (isCreation())
+ {
+ // If execution is a contract creation, add Natspec to
+ // a local Natspec LEVELDB
+ ethereum()->submitTransaction(s, value(), m_data, ui->gas->value(), gasPrice());
+ string src = ui->data->toPlainText().toStdString();
+ if (sourceIsSolidity(src))
+ try
{
- // If execution is a contract creation, add Natspec to
- // a local Natspec LEVELDB
- ethereum()->submitTransaction(s, value(), m_data, ui->gas->value(), gasPrice());
- string src = ui->data->toPlainText().toStdString();
- if (sourceIsSolidity(src))
- try
- {
- dev::solidity::CompilerStack compiler(true);
- m_data = compiler.compile(src, ui->optimize->isChecked());
- for (string const& s: compiler.getContractNames())
- {
- h256 contractHash = compiler.getContractCodeHash(s);
- m_natSpecDB->add(contractHash, compiler.getMetadata(s, dev::solidity::DocumentationType::NatspecUser));
- }
- }
- catch (...)
- {
- }
- close();
- return;
+ dev::solidity::CompilerStack compiler(true);
+ m_data = compiler.compile(src, ui->optimize->isChecked());
+ for (string const& s: compiler.getContractNames())
+ {
+ h256 contractHash = compiler.getContractCodeHash(s);
+ m_natSpecDB->add(contractHash, compiler.getMetadata(s, dev::solidity::DocumentationType::NatspecUser));
+ }
}
- else
- ethereum()->submitTransaction(s, value(), m_context->fromString(ui->destination->currentText()), m_data, ui->gas->value(), gasPrice());
- return;
- }
- QMessageBox::critical(this, "Transaction Failed", "Couldn't make transaction: no single account contains at least the required amount.");
+ catch (...) {}
+ }
+ else
+ ethereum()->submitTransaction(s, value(), m_context->fromString(ui->destination->currentText()), m_data, ui->gas->value(), gasPrice());
+ close();
}
void Transact::on_debug_clicked()
{
+ Secret s = findSecret(value() + fee());
+ auto b = ethereum()->balanceAt(KeyPair(s).address(), PendingBlock);
+ if (!s || b < value() + fee())
+ {
+ QMessageBox::critical(this, "Transaction Failed", "Couldn't make transaction: no single account contains at least the required amount.");
+ return;
+ }
+
try
{
- u256 totalReq = value() + fee();
- for (auto i: m_myKeys)
- if (ethereum()->balanceAt(i.address()) >= totalReq)
- {
- State st(ethereum()->postState());
- Secret s = i.secret();
- Transaction t = isCreation() ?
- Transaction(value(), gasPrice(), ui->gas->value(), m_data, st.transactionsFrom(dev::toAddress(s)), s) :
- Transaction(value(), gasPrice(), ui->gas->value(), m_context->fromString(ui->destination->currentText()), m_data, st.transactionsFrom(dev::toAddress(s)), s);
- Debugger dw(m_context, this);
- Executive e(st, ethereum()->blockChain(), 0);
- dw.populate(e, t);
- dw.exec();
- return;
- }
- QMessageBox::critical(this, "Transaction Failed", "Couldn't make transaction: no single account contains at least the required amount.");
+ State st(ethereum()->postState());
+ Transaction t = isCreation() ?
+ Transaction(value(), gasPrice(), ui->gas->value(), m_data, st.transactionsFrom(dev::toAddress(s)), s) :
+ Transaction(value(), gasPrice(), ui->gas->value(), m_context->fromString(ui->destination->currentText()), m_data, st.transactionsFrom(dev::toAddress(s)), s);
+ Debugger dw(m_context, this);
+ Executive e(st, ethereum()->blockChain(), 0);
+ dw.populate(e, t);
+ dw.exec();
}
catch (dev::Exception const& _e)
{
diff --git a/alethzero/Transact.h b/alethzero/Transact.h
index 8ef4f41e0..71bc393b2 100644
--- a/alethzero/Transact.h
+++ b/alethzero/Transact.h
@@ -57,7 +57,7 @@ private slots:
void on_cancel_clicked() { close(); }
private:
- dev::eth::Client* ethereum() { return m_ethereum; }
+ dev::eth::Client* ethereum() const { return m_ethereum; }
void rejigData();
void updateDestination();
@@ -68,15 +68,17 @@ private:
dev::u256 value() const;
dev::u256 gasPrice() const;
- std::string getFunctionHashes(dev::solidity::CompilerStack const& _compiler, std::string const& _contractName = std::string());
+ std::string natspecNotice(dev::Address _to, dev::bytes const& _data);
+ dev::Secret findSecret(dev::u256 _totalReq) const;
- Ui::Transact* ui;
+ Ui::Transact* ui = nullptr;
- unsigned m_backupGas;
+ unsigned m_backupGas = 0;
dev::bytes m_data;
QList m_myKeys;
- dev::eth::Client* m_ethereum;
- Context* m_context;
- NatSpecFace* m_natSpecDB;
+ dev::eth::Client* m_ethereum = nullptr;
+ Context* m_context = nullptr;
+ NatSpecFace* m_natSpecDB = nullptr;
+ bool m_allGood = false;
};
diff --git a/eth/main.cpp b/eth/main.cpp
index 81e910716..eda6e12ae 100644
--- a/eth/main.cpp
+++ b/eth/main.cpp
@@ -103,7 +103,7 @@ void interactiveHelp()
void help()
{
cout
- << "Usage eth [OPTIONS] " << endl
+ << "Usage eth [OPTIONS]" << endl
<< "Options:" << endl
<< " -a,--address Set the coinbase (mining payout) address to addr (default: auto)." << endl
<< " -b,--bootstrap Connect to the default Ethereum peerserver." << endl
@@ -119,6 +119,7 @@ void help()
<< " -j,--json-rpc Enable JSON-RPC server (default: off)." << endl
<< " --json-rpc-port Specify JSON-RPC server port (implies '-j', default: 8080)." << endl
#endif
+ << " -K,--kill-blockchain First kill the blockchain." << endl
<< " -l,--listen Listen on the given port for incoming connected (default: 30303)." << endl
<< " -L,--local-networking Use peers whose addresses are local." << endl
<< " -m,--mining Enable mining, optionally for a specified number of blocks (Default: off)" << endl
@@ -159,7 +160,7 @@ string credits(bool _interactive = false)
void version()
{
cout << "eth version " << dev::Version << endl;
- cout << "Network protocol version: " << dev::eth::c_protocolVersion << endl;
+ cout << "eth network protocol version: " << dev::eth::c_protocolVersion << endl;
cout << "Client database version: " << dev::eth::c_databaseVersion << endl;
cout << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl;
exit(0);
@@ -214,6 +215,7 @@ int main(int argc, char** argv)
bool upnp = true;
bool useLocal = false;
bool forceMining = false;
+ bool killChain = false;
bool jit = false;
bool structuredLogging = false;
string structuredLoggingFormat = "%Y-%m-%dT%H:%M:%S";
@@ -270,13 +272,14 @@ int main(int argc, char** argv)
}
else if (arg == "-L" || arg == "--local-networking")
useLocal = true;
+ else if (arg == "-K" || arg == "--kill-blockchain")
+ killChain = true;
else if ((arg == "-c" || arg == "--client-name") && i + 1 < argc)
clientName = argv[++i];
else if ((arg == "-a" || arg == "--address" || arg == "--coinbase-address") && i + 1 < argc)
- {
try
{
- coinbase = h160(fromHex(argv[++i], ThrowType::Throw));
+ coinbase = h160(fromHex(argv[++i], WhenError::Throw));
}
catch (BadHexCharacter& _e)
{
@@ -289,7 +292,6 @@ int main(int argc, char** argv)
cwarn << "coinbase rejected";
break;
}
- }
else if ((arg == "-s" || arg == "--secret") && i + 1 < argc)
us = KeyPair(h256(fromHex(argv[++i])));
else if (arg == "--structured-logging-format" && i + 1 < argc)
@@ -300,20 +302,24 @@ int main(int argc, char** argv)
dbPath = argv[++i];
else if ((arg == "-B" || arg == "--block-fees") && i + 1 < argc)
{
- try {
+ try
+ {
blockFees = stof(argv[++i]);
}
- catch (...) {
+ catch (...)
+ {
cerr << "Bad " << arg << " option: " << argv[++i] << endl;
return -1;
}
}
else if ((arg == "-e" || arg == "--ether-price") && i + 1 < argc)
{
- try {
+ try
+ {
etherPrice = stof(argv[++i]);
}
- catch (...) {
+ catch (...)
+ {
cerr << "Bad " << arg << " option: " << argv[++i] << endl;
return -1;
}
@@ -401,7 +407,10 @@ int main(int argc, char** argv)
else if (arg == "-V" || arg == "--version")
version();
else
- remoteHost = argv[i];
+ {
+ cerr << "Invalid argument: " << arg << endl;
+ exit(-1);
+ }
}
if (!clientName.empty())
@@ -417,7 +426,7 @@ int main(int argc, char** argv)
dev::WebThreeDirect web3(
clientImplString,
dbPath,
- false,
+ killChain,
mode == NodeMode::Full ? set{"eth", "shh"} : set(),
netPrefs,
&nodesState,
@@ -434,7 +443,8 @@ int main(int argc, char** argv)
c->setAddress(coinbase);
}
- cout << "Address: " << endl << toHex(us.address().asArray()) << endl;
+ cout << "Transaction Signer: " << us.address() << endl;
+ cout << "Mining Benefactor: " << coinbase << endl;
web3.startNetwork();
if (bootstrap)
@@ -680,7 +690,7 @@ int main(int argc, char** argv)
auto acs =c->addresses();
string ss;
for (auto const& i: acs)
- if ( c->codeAt(i, 0).size())
+ if ( c->codeAt(i, PendingBlock).size())
{
ss = toString(i) + " : " + toString( c->balanceAt(i)) + " [" + toString((unsigned) c->countAt(i)) + "]";
cout << ss << endl;
@@ -691,7 +701,7 @@ int main(int argc, char** argv)
auto acs =c->addresses();
string ss;
for (auto const& i: acs)
- if ( c->codeAt(i, 0).empty())
+ if ( c->codeAt(i, PendingBlock).empty())
{
ss = toString(i) + " : " + toString( c->balanceAt(i)) + " [" + toString((unsigned) c->countAt(i)) + "]";
cout << ss << endl;
@@ -720,7 +730,7 @@ int main(int argc, char** argv)
u256 minGas = (u256)Client::txGas(bytes(), 0);
try
{
- Address dest = h160(fromHex(hexAddr, ThrowType::Throw));
+ Address dest = h160(fromHex(hexAddr, WhenError::Throw));
c->submitTransaction(us.secret(), amount, dest, bytes(), minGas);
}
catch (BadHexCharacter& _e)
@@ -764,7 +774,7 @@ int main(int argc, char** argv)
stringstream ssc;
try
{
- init = fromHex(sinit, ThrowType::Throw);
+ init = fromHex(sinit, WhenError::Throw);
}
catch (BadHexCharacter& _e)
{
@@ -883,10 +893,10 @@ int main(int argc, char** argv)
try
{
- auto storage =c->storageAt(h, 0);
+ auto storage =c->storageAt(h, PendingBlock);
for (auto const& i: storage)
s << "@" << showbase << hex << i.first << " " << showbase << hex << i.second << endl;
- s << endl << disassemble( c->codeAt(h, 0)) << endl;
+ s << endl << disassemble( c->codeAt(h, PendingBlock)) << endl;
string outFile = getDataDir() + "/" + rechex + ".evm";
ofstream ofs;
@@ -925,7 +935,7 @@ int main(int argc, char** argv)
{
try
{
- coinbase = h160(fromHex(hexAddr, ThrowType::Throw));
+ coinbase = h160(fromHex(hexAddr, WhenError::Throw));
}
catch (BadHexCharacter& _e)
{
diff --git a/evmjit/libevmjit/Arith256.cpp b/evmjit/libevmjit/Arith256.cpp
index f24626750..e88fda432 100644
--- a/evmjit/libevmjit/Arith256.cpp
+++ b/evmjit/libevmjit/Arith256.cpp
@@ -371,17 +371,18 @@ llvm::Value* Arith256::mul(llvm::Value* _arg1, llvm::Value* _arg2)
std::pair Arith256::div(llvm::Value* _arg1, llvm::Value* _arg2)
{
- if (auto c1 = llvm::dyn_cast(_arg1))
- {
- if (auto c2 = llvm::dyn_cast(_arg2))
- {
- if (!c2->getValue())
- return std::make_pair(Constant::get(0), Constant::get(0));
- auto div = Constant::get(c1->getValue().udiv(c2->getValue()));
- auto mod = Constant::get(c1->getValue().urem(c2->getValue()));
- return std::make_pair(div, mod);
- }
- }
+ // FIXME: Disabled because of llvm::APInt::urem bug
+// if (auto c1 = llvm::dyn_cast(_arg1))
+// {
+// if (auto c2 = llvm::dyn_cast(_arg2))
+// {
+// if (!c2->getValue())
+// return std::make_pair(Constant::get(0), Constant::get(0));
+// auto div = Constant::get(c1->getValue().udiv(c2->getValue()));
+// auto mod = Constant::get(c1->getValue().urem(c2->getValue()));
+// return std::make_pair(div, mod);
+// }
+// }
auto r = createCall(getDivFunc(Type::Word), {_arg1, _arg2});
auto div = m_builder.CreateExtractValue(r, 0, "div");
@@ -391,17 +392,18 @@ std::pair Arith256::div(llvm::Value* _arg1, llvm::Va
std::pair Arith256::sdiv(llvm::Value* _x, llvm::Value* _y)
{
- if (auto c1 = llvm::dyn_cast(_x))
- {
- if (auto c2 = llvm::dyn_cast(_y))
- {
- if (!c2->getValue())
- return std::make_pair(Constant::get(0), Constant::get(0));
- auto div = Constant::get(c1->getValue().sdiv(c2->getValue()));
- auto mod = Constant::get(c1->getValue().srem(c2->getValue()));
- return std::make_pair(div, mod);
- }
- }
+ // FIXME: Disabled because of llvm::APInt::urem bug
+// if (auto c1 = llvm::dyn_cast(_x))
+// {
+// if (auto c2 = llvm::dyn_cast(_y))
+// {
+// if (!c2->getValue())
+// return std::make_pair(Constant::get(0), Constant::get(0));
+// auto div = Constant::get(c1->getValue().sdiv(c2->getValue()));
+// auto mod = Constant::get(c1->getValue().srem(c2->getValue()));
+// return std::make_pair(div, mod);
+// }
+// }
auto xIsNeg = m_builder.CreateICmpSLT(_x, Constant::get(0));
auto xNeg = m_builder.CreateSub(Constant::get(0), _x);
diff --git a/libdevcore/CommonData.cpp b/libdevcore/CommonData.cpp
index 17e393cbe..6cad29952 100644
--- a/libdevcore/CommonData.cpp
+++ b/libdevcore/CommonData.cpp
@@ -78,7 +78,7 @@ int dev::fromHex(char _i)
BOOST_THROW_EXCEPTION(BadHexCharacter() << errinfo_invalidSymbol(_i));
}
-bytes dev::fromHex(std::string const& _s, ThrowType _throw)
+bytes dev::fromHex(std::string const& _s, WhenError _throw)
{
unsigned s = (_s[0] == '0' && _s[1] == 'x') ? 2 : 0;
std::vector ret;
@@ -96,7 +96,7 @@ bytes dev::fromHex(std::string const& _s, ThrowType _throw)
#ifndef BOOST_NO_EXCEPTIONS
cwarn << boost::current_exception_diagnostic_information();
#endif
- if (_throw == ThrowType::Throw)
+ if (_throw == WhenError::Throw)
throw;
}
for (unsigned i = s; i < _s.size(); i += 2)
@@ -109,7 +109,7 @@ bytes dev::fromHex(std::string const& _s, ThrowType _throw)
#ifndef BOOST_NO_EXCEPTIONS
cwarn << boost::current_exception_diagnostic_information();
#endif
- if (_throw == ThrowType::Throw)
+ if (_throw == WhenError::Throw)
throw;
}
return ret;
diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h
index 2c9fd30ef..1c7a4cd61 100644
--- a/libdevcore/CommonData.h
+++ b/libdevcore/CommonData.h
@@ -35,9 +35,9 @@ namespace dev
// String conversion functions, mainly to/from hex/nibble/byte representations.
-enum class ThrowType
+enum class WhenError
{
- NoThrow = 0,
+ DontThrow = 0,
Throw = 1,
};
@@ -59,8 +59,8 @@ int fromHex(char _i);
/// Converts a (printable) ASCII hex string into the corresponding byte stream.
/// @example fromHex("41626261") == asBytes("Abba")
-/// If _throw = ThrowType::NoThrow, it replaces bad hex characters with 0's, otherwise it will throw an exception.
-bytes fromHex(std::string const& _s, ThrowType _throw = ThrowType::NoThrow);
+/// If _throw = ThrowType::DontThrow, it replaces bad hex characters with 0's, otherwise it will throw an exception.
+bytes fromHex(std::string const& _s, WhenError _throw = WhenError::DontThrow);
#if 0
std::string toBase58(bytesConstRef _data);
diff --git a/libdevcrypto/FileSystem.cpp b/libdevcrypto/FileSystem.cpp
index 81b23e886..ed054553d 100644
--- a/libdevcrypto/FileSystem.cpp
+++ b/libdevcrypto/FileSystem.cpp
@@ -32,12 +32,15 @@
using namespace std;
using namespace dev;
-std::string dev::getDataDir()
+std::string dev::getDataDir(std::string _prefix)
{
+ if (_prefix.empty())
+ _prefix = "ethereum";
#ifdef _WIN32
+ _prefix[0] = toupper(_prefix[0]);
char path[1024] = "";
if (SHGetSpecialFolderPathA(NULL, path, CSIDL_APPDATA, true))
- return (boost::filesystem::path(path) / "Ethereum").string();
+ return (boost::filesystem::path(path) / _prefix).string();
else
{
#ifndef _MSC_VER // todo?
@@ -57,7 +60,7 @@ std::string dev::getDataDir()
// This eventually needs to be put in proper wrapper (to support sandboxing)
return (dataDirPath / "Library/Application Support/Ethereum").string();
#else
- return (dataDirPath / ".ethereum").string();
+ return (dataDirPath / ("." + _prefix)).string();
#endif
#endif
}
diff --git a/libdevcrypto/FileSystem.h b/libdevcrypto/FileSystem.h
index 281e60e24..6c8160a58 100644
--- a/libdevcrypto/FileSystem.h
+++ b/libdevcrypto/FileSystem.h
@@ -30,6 +30,6 @@ namespace dev
{
/// @returns the path for user data.
-std::string getDataDir();
+std::string getDataDir(std::string _prefix = "ethereum");
}
diff --git a/libethcore/Common.h b/libethcore/Common.h
index aabb59d25..51322dcb2 100644
--- a/libethcore/Common.h
+++ b/libethcore/Common.h
@@ -71,5 +71,16 @@ static const u256 wei = exp10<0>();
using Nonce = h64;
+using BlockNumber = unsigned;
+
+static const BlockNumber LatestBlock = (BlockNumber)-2;
+static const BlockNumber PendingBlock = (BlockNumber)-1;
+
+enum class RelativeBlock: BlockNumber
+{
+ Latest = LatestBlock,
+ Pending = PendingBlock
+};
+
}
}
diff --git a/libethcore/Ethasher.cpp b/libethcore/Ethasher.cpp
index 80c263673..44a555fde 100644
--- a/libethcore/Ethasher.cpp
+++ b/libethcore/Ethasher.cpp
@@ -71,10 +71,10 @@ bytesConstRef Ethasher::full(BlockInfo const& _header)
m_fulls.erase(m_fulls.begin());
}
try {
- boost::filesystem::create_directories(getDataDir() + "/ethashcache");
+ boost::filesystem::create_directories(getDataDir("ethash"));
} catch (...) {}
- std::string memoFile = getDataDir() + "/ethashcache/full";
+ std::string memoFile = getDataDir("ethash") + "/full";
auto info = rlpList(c_ethashRevision, _header.seedHash());
if (boost::filesystem::exists(memoFile) && contents(memoFile + ".info") != info)
boost::filesystem::remove(memoFile);
diff --git a/libethcore/Exceptions.h b/libethcore/Exceptions.h
index f9eab7c8d..df6a08817 100644
--- a/libethcore/Exceptions.h
+++ b/libethcore/Exceptions.h
@@ -59,7 +59,6 @@ struct InvalidGasUsed: virtual dev::Exception {};
class InvalidTransactionsHash: virtual public dev::Exception {};
struct InvalidTransaction: virtual dev::Exception {};
struct InvalidDifficulty: virtual dev::Exception {};
-struct InvalidSeedHash: virtual dev::Exception {};
class InvalidGasLimit: virtual public dev::Exception {};
struct InvalidTransactionGasUsed: virtual dev::Exception {};
struct InvalidTransactionsStateRoot: virtual dev::Exception {};
diff --git a/libethcore/Params.cpp b/libethcore/Params.cpp
index d58888ab7..d70443fd9 100644
--- a/libethcore/Params.cpp
+++ b/libethcore/Params.cpp
@@ -37,6 +37,7 @@ u256 const c_gasLimitBoundDivisor = 1024;
u256 const c_minimumDifficulty = 131072;
u256 const c_difficultyBoundDivisor = 2048;
u256 const c_durationLimit = 8;
+u256 const c_stackLimit = 1024;
u256 const c_tierStepGas[] = {0, 2, 3, 5, 8, 10, 20, 0};
u256 const c_expGas = 10;
u256 const c_expByteGas = 10;
diff --git a/libethcore/Params.h b/libethcore/Params.h
index cab1852fa..7520e49f1 100644
--- a/libethcore/Params.h
+++ b/libethcore/Params.h
@@ -38,6 +38,7 @@ extern u256 const c_gasLimitBoundDivisor;
extern u256 const c_minimumDifficulty;
extern u256 const c_difficultyBoundDivisor;
extern u256 const c_durationLimit;
+extern u256 const c_stackLimit;
extern u256 const c_tierStepGas[8]; ///< Once per operation, for a selection of them.
extern u256 const c_expGas; ///< Once per EXP instuction.
diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp
index fb29ffb6a..883b7f615 100644
--- a/libethereum/Client.cpp
+++ b/libethereum/Client.cpp
@@ -40,7 +40,7 @@ VersionChecker::VersionChecker(string const& _dbPath):
{
auto protocolContents = contents(m_path + "/protocol");
auto databaseContents = contents(m_path + "/database");
- m_ok = RLP(protocolContents).toInt(RLP::LaisezFaire) == c_protocolVersion && RLP(databaseContents).toInt(RLP::LaisezFaire) == c_databaseVersion;
+ m_ok = RLP(protocolContents).toInt(RLP::LaisezFaire) == eth::c_protocolVersion && RLP(databaseContents).toInt(RLP::LaisezFaire) == c_databaseVersion;
}
void VersionChecker::setOk()
@@ -55,7 +55,7 @@ void VersionChecker::setOk()
{
cwarn << "Unhandled exception! Failed to create directory: " << m_path << "\n" << boost::current_exception_diagnostic_information();
}
- writeFile(m_path + "/protocol", rlp(c_protocolVersion));
+ writeFile(m_path + "/protocol", rlp(eth::c_protocolVersion));
writeFile(m_path + "/database", rlp(c_databaseVersion));
}
}
@@ -357,11 +357,11 @@ LocalisedLogEntries Client::checkWatch(unsigned _watchId)
return ret;
}
-void Client::appendFromNewPending(TransactionReceipt const& _receipt, h256Set& io_changed, h256 _sha3)
+void Client::appendFromNewPending(TransactionReceipt const& _receipt, h256Set& io_changed, h256 _transactionHash)
{
Guard l(m_filterLock);
for (pair& i: m_filters)
- if ((unsigned)i.second.filter.latest() > m_bc.number())
+ if (i.second.filter.envelops(RelativeBlock::Pending, m_bc.number() + 1))
{
// acceptable number.
auto m = i.second.filter.matches(_receipt);
@@ -369,7 +369,7 @@ void Client::appendFromNewPending(TransactionReceipt const& _receipt, h256Set& i
{
// filter catches them
for (LogEntry const& l: m)
- i.second.changes.push_back(LocalisedLogEntry(l, m_bc.number() + 1, _sha3));
+ i.second.changes.push_back(LocalisedLogEntry(l, m_bc.number() + 1, _transactionHash));
io_changed.insert(i.first);
}
}
@@ -383,7 +383,7 @@ void Client::appendFromNewBlock(h256 const& _block, h256Set& io_changed)
Guard l(m_filterLock);
for (pair& i: m_filters)
- if ((unsigned)i.second.filter.latest() >= d.number && (unsigned)i.second.filter.earliest() <= d.number && i.second.filter.matches(d.logBloom))
+ if (i.second.filter.envelops(RelativeBlock::Latest, d.number) && i.second.filter.matches(d.logBloom))
// acceptable number & looks like block may contain a matching log entry.
for (size_t j = 0; j < br.receipts.size(); j++)
{
@@ -391,10 +391,10 @@ void Client::appendFromNewBlock(h256 const& _block, h256Set& io_changed)
auto m = i.second.filter.matches(tr);
if (m.size())
{
- auto sha3 = transaction(d.hash, j).sha3();
+ auto transactionHash = transaction(d.hash, j).sha3();
// filter catches them
for (LogEntry const& l: m)
- i.second.changes.push_back(LocalisedLogEntry(l, (unsigned)d.number, sha3));
+ i.second.changes.push_back(LocalisedLogEntry(l, (unsigned)d.number, transactionHash));
io_changed.insert(i.first);
}
}
@@ -491,7 +491,7 @@ void Client::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes
m_tq.attemptImport(t.rlp());
}
-ExecutionResult Client::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, int _blockNumber)
+ExecutionResult Client::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber)
{
ExecutionResult ret;
try
@@ -514,7 +514,7 @@ ExecutionResult Client::call(Secret _secret, u256 _value, Address _dest, bytes c
return ret;
}
-ExecutionResult Client::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, int _blockNumber)
+ExecutionResult Client::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber)
{
ExecutionResult ret;
try
@@ -739,12 +739,12 @@ unsigned Client::numberOf(int _n) const
return m_bc.details().number + max(-(int)m_bc.details().number, 1 + _n);
}
-State Client::asOf(int _h) const
+State Client::asOf(unsigned _h) const
{
ReadGuard l(x_stateDB);
- if (_h == 0)
+ if (_h == PendingBlock)
return m_postMine;
- else if (_h == -1)
+ else if (_h == LatestBlock)
return m_preMine;
else
return State(m_stateDB, m_bc, m_bc.numberHash(numberOf(_h)));
@@ -768,7 +768,7 @@ eth::State Client::state(unsigned _txi) const
return m_postMine.fromPending(_txi);
}
-StateDiff Client::diff(unsigned _txi, int _block) const
+StateDiff Client::diff(unsigned _txi, BlockNumber _block) const
{
State st = asOf(_block);
return st.fromPending(_txi).diff(st.fromPending(_txi + 1));
@@ -780,7 +780,7 @@ StateDiff Client::diff(unsigned _txi, h256 _block) const
return st.fromPending(_txi).diff(st.fromPending(_txi + 1));
}
-std::vector Client::addresses(int _block) const
+std::vector Client::addresses(BlockNumber _block) const
{
vector ret;
for (auto const& i: asOf(_block).addresses())
@@ -788,27 +788,27 @@ std::vector Client::addresses(int _block) const
return ret;
}
-u256 Client::balanceAt(Address _a, int _block) const
+u256 Client::balanceAt(Address _a, BlockNumber _block) const
{
return asOf(_block).balance(_a);
}
-std::map Client::storageAt(Address _a, int _block) const
+std::map Client::storageAt(Address _a, BlockNumber _block) const
{
return asOf(_block).storage(_a);
}
-u256 Client::countAt(Address _a, int _block) const
+u256 Client::countAt(Address _a, BlockNumber _block) const
{
return asOf(_block).transactionsFrom(_a);
}
-u256 Client::stateAt(Address _a, u256 _l, int _block) const
+u256 Client::stateAt(Address _a, u256 _l, BlockNumber _block) const
{
return asOf(_block).storage(_a, _l);
}
-bytes Client::codeAt(Address _a, int _block) const
+bytes Client::codeAt(Address _a, BlockNumber _block) const
{
return asOf(_block).code(_a);
}
diff --git a/libethereum/Client.h b/libethereum/Client.h
index 426c78ca7..f34eea5bf 100644
--- a/libethereum/Client.h
+++ b/libethereum/Client.h
@@ -225,11 +225,11 @@ public:
virtual void flushTransactions() override;
/// Makes the given call. Nothing is recorded into the state.
- virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, int _blockNumber = 0) override;
+ virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock) override;
/// Does the given creation. Nothing is recorded into the state.
/// @returns the pair of the Address of the created contract together with its code.
- virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, int _blockNumber = 0) override;
+ virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock) override;
/// Makes the given call. Nothing is recorded into the state. This cheats by creating a null address and endowing it with a lot of ETH.
ExecutionResult call(Address _dest, bytes const& _data = bytes(), u256 _gas = 125000, u256 _value = 0, u256 _gasPrice = 1 * ether);
@@ -244,11 +244,11 @@ public:
using Interface::codeAt;
using Interface::storageAt;
- virtual u256 balanceAt(Address _a, int _block) const;
- virtual u256 countAt(Address _a, int _block) const;
- virtual u256 stateAt(Address _a, u256 _l, int _block) const;
- virtual bytes codeAt(Address _a, int _block) const;
- virtual std::map storageAt(Address _a, int _block) const;
+ virtual u256 balanceAt(Address _a, BlockNumber _block) const;
+ virtual u256 countAt(Address _a, BlockNumber _block) const;
+ virtual u256 stateAt(Address _a, u256 _l, BlockNumber _block) const;
+ virtual bytes codeAt(Address _a, BlockNumber _block) const;
+ virtual std::map storageAt(Address _a, BlockNumber _block) const;
virtual unsigned installWatch(LogFilter const& _filter, Reaping _r = Reaping::Automatic) override;
virtual unsigned installWatch(h256 _filterId, Reaping _r = Reaping::Automatic) override;
@@ -282,11 +282,11 @@ public:
/// Differences between transactions.
using Interface::diff;
virtual StateDiff diff(unsigned _txi, h256 _block) const;
- virtual StateDiff diff(unsigned _txi, int _block) const;
+ virtual StateDiff diff(unsigned _txi, BlockNumber _block) const;
/// Get a list of all active addresses.
using Interface::addresses;
- virtual std::vector addresses(int _block) const;
+ virtual std::vector addresses(BlockNumber _block) const;
/// Get the remaining gas limit in this block.
virtual u256 gasLimitRemaining() const { return m_postMine.gasLimitRemaining(); }
@@ -383,7 +383,8 @@ private:
/// Return the actual block number of the block with the given int-number (positive is the same, INT_MIN is genesis block, < 0 is negative age, thus -1 is most recently mined, 0 is pending.
unsigned numberOf(int _b) const;
- State asOf(int _h) const;
+ /// Returns the state object for the full block (i.e. the terminal state) for index _h.
+ /// Works properly with LatestBlock and PendingBlock.
State asOf(unsigned _h) const;
VersionChecker m_vc; ///< Dummy object to check & update the protocol version.
diff --git a/libethereum/EthereumPeer.cpp b/libethereum/EthereumPeer.cpp
index a6211505f..f318a1757 100644
--- a/libethereum/EthereumPeer.cpp
+++ b/libethereum/EthereumPeer.cpp
@@ -48,6 +48,7 @@ EthereumPeer::EthereumPeer(Session* _s, HostCapabilityFace* _h, unsigned _i):
EthereumPeer::~EthereumPeer()
{
+ clogS(NetMessageSummary) << "Aborting Sync :-(";
abortSync();
}
diff --git a/libethereum/Interface.h b/libethereum/Interface.h
index dfbd47704..68eb4b094 100644
--- a/libethereum/Interface.h
+++ b/libethereum/Interface.h
@@ -73,16 +73,16 @@ public:
virtual void flushTransactions() = 0;
/// Makes the given call. Nothing is recorded into the state.
- virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, int _blockNumber = 0) = 0;
+ virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = 0) = 0;
/// Does the given creation. Nothing is recorded into the state.
/// @returns the pair of the Address of the created contract together with its code.
- virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, int _blockNumber = 0) = 0;
+ virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = 0) = 0;
// [STATE-QUERY API]
int getDefault() const { return m_default; }
- void setDefault(int _block) { m_default = _block; }
+ void setDefault(BlockNumber _block) { m_default = _block; }
u256 balanceAt(Address _a) const { return balanceAt(_a, m_default); }
u256 countAt(Address _a) const { return countAt(_a, m_default); }
@@ -90,11 +90,11 @@ public:
bytes codeAt(Address _a) const { return codeAt(_a, m_default); }
std::map storageAt(Address _a) const { return storageAt(_a, m_default); }
- virtual u256 balanceAt(Address _a, int _block) const = 0;
- virtual u256 countAt(Address _a, int _block) const = 0;
- virtual u256 stateAt(Address _a, u256 _l, int _block) const = 0;
- virtual bytes codeAt(Address _a, int _block) const = 0;
- virtual std::map storageAt(Address _a, int _block) const = 0;
+ virtual u256 balanceAt(Address _a, BlockNumber _block) const = 0;
+ virtual u256 countAt(Address _a, BlockNumber _block) const = 0;
+ virtual u256 stateAt(Address _a, u256 _l, BlockNumber _block) const = 0;
+ virtual bytes codeAt(Address _a, BlockNumber _block) const = 0;
+ virtual std::map storageAt(Address _a, BlockNumber _block) const = 0;
// [LOGS API]
@@ -135,11 +135,11 @@ public:
/// Differences between transactions.
StateDiff diff(unsigned _txi) const { return diff(_txi, m_default); }
virtual StateDiff diff(unsigned _txi, h256 _block) const = 0;
- virtual StateDiff diff(unsigned _txi, int _block) const = 0;
+ virtual StateDiff diff(unsigned _txi, BlockNumber _block) const = 0;
/// Get a list of all active addresses.
virtual Addresses addresses() const { return addresses(m_default); }
- virtual Addresses addresses(int _block) const = 0;
+ virtual Addresses addresses(BlockNumber _block) const = 0;
/// Get the fee associated for a transaction with the given data.
template static bigint txGas(T const& _data, u256 _gas = 0) { bigint ret = c_txGas + _gas; for (auto i: _data) ret += i ? c_txDataNonZeroGas : c_txDataZeroGas; return ret; }
@@ -177,7 +177,7 @@ public:
virtual MineProgress miningProgress() const = 0;
protected:
- int m_default = -1;
+ int m_default = PendingBlock;
};
class Watch;
diff --git a/libethereum/LogFilter.cpp b/libethereum/LogFilter.cpp
index 45716a949..ab9848d59 100644
--- a/libethereum/LogFilter.cpp
+++ b/libethereum/LogFilter.cpp
@@ -46,6 +46,33 @@ h256 LogFilter::sha3() const
return dev::sha3(s.out());
}
+static bool isNoLater(RelativeBlock _logBlockRelation, u256 _logBlockNumber, unsigned _latest)
+{
+ if (_latest == PendingBlock)
+ return true;
+ else if (_latest == LatestBlock)
+ return _logBlockRelation == RelativeBlock::Latest;
+ else
+ return _logBlockNumber <= _latest;
+}
+
+static bool isNoEarlier(RelativeBlock _logBlockRelation, u256 _logBlockNumber, unsigned _earliest)
+{
+ if (_earliest == PendingBlock)
+ return _logBlockRelation == RelativeBlock::Pending;
+ else if (_earliest == LatestBlock)
+ return true;
+ else
+ return _logBlockNumber >= _earliest;
+}
+
+bool LogFilter::envelops(RelativeBlock _logBlockRelation, u256 _logBlockNumber) const
+{
+ return
+ isNoLater(_logBlockRelation, _logBlockNumber, m_latest) &&
+ isNoEarlier(_logBlockRelation, _logBlockNumber, m_earliest);
+}
+
bool LogFilter::matches(LogBloom _bloom) const
{
if (m_addresses.size())
diff --git a/libethereum/LogFilter.h b/libethereum/LogFilter.h
index a28bfe806..304fab317 100644
--- a/libethereum/LogFilter.h
+++ b/libethereum/LogFilter.h
@@ -45,14 +45,15 @@ class State;
class LogFilter
{
public:
- LogFilter(int _earliest = 0, int _latest = -1): m_earliest(_earliest), m_latest(_latest) {}
+ LogFilter(unsigned _earliest = 0, unsigned _latest = PendingBlock): m_earliest(_earliest), m_latest(_latest) {}
void streamRLP(RLPStream& _s) const;
h256 sha3() const;
- int earliest() const { return m_earliest; }
- int latest() const { return m_latest; }
+ unsigned earliest() const { return m_earliest; }
+ unsigned latest() const { return m_latest; }
+ bool envelops(RelativeBlock _logBlockRelation, u256 _logBlockNumber) const;
std::vector bloomPossibilities() const;
bool matches(LogBloom _bloom) const;
bool matches(State const& _s, unsigned _i) const;
@@ -68,8 +69,8 @@ public:
private:
AddressSet m_addresses;
std::array m_topics;
- int m_earliest = 0;
- int m_latest = -1;
+ unsigned m_earliest = 0;
+ unsigned m_latest = LatestBlock;
};
}
diff --git a/libethereum/State.cpp b/libethereum/State.cpp
index 0d2b3a93e..c5732116d 100644
--- a/libethereum/State.cpp
+++ b/libethereum/State.cpp
@@ -1040,7 +1040,7 @@ LastHashes State::getLastHashes(BlockChain const& _bc, unsigned _n) const
{
LastHashes ret;
ret.resize(256);
- if (c_protocolVersion > 49)
+ if (eth::c_protocolVersion > 49)
{
ret[0] = _bc.numberHash(_n);
for (unsigned i = 1; i < 256; ++i)
diff --git a/libethereum/Transaction.cpp b/libethereum/Transaction.cpp
index 3a092bf25..31a7f74a9 100644
--- a/libethereum/Transaction.cpp
+++ b/libethereum/Transaction.cpp
@@ -46,6 +46,8 @@ TransactionException dev::eth::toTransactionException(VMException const& _e)
return TransactionException::BadJumpDestination;
if (!!dynamic_cast(&_e))
return TransactionException::OutOfGas;
+ if (!!dynamic_cast(&_e))
+ return TransactionException::OutOfStack;
if (!!dynamic_cast(&_e))
return TransactionException::StackUnderflow;
return TransactionException::Unknown;
diff --git a/libethereum/Transaction.h b/libethereum/Transaction.h
index 85543a3fc..561ec6269 100644
--- a/libethereum/Transaction.h
+++ b/libethereum/Transaction.h
@@ -56,6 +56,7 @@ enum class TransactionException
BadInstruction,
BadJumpDestination,
OutOfGas, ///< Ran out of gas executing code of the transaction.
+ OutOfStack, ///< Ran out of stack executing code of the transaction.
StackUnderflow
};
@@ -66,7 +67,7 @@ enum class CodeDeposit
Success
};
-class VMException;
+struct VMException;
TransactionException toTransactionException(VMException const& _e);
diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h
index 79b97a252..48fbd0b01 100644
--- a/libevm/ExtVMFace.h
+++ b/libevm/ExtVMFace.h
@@ -63,10 +63,10 @@ using LogEntries = std::vector;
struct LocalisedLogEntry: public LogEntry
{
LocalisedLogEntry() {}
- LocalisedLogEntry(LogEntry const& _le, unsigned _number, h256 _sha3 = {}): LogEntry(_le), number(_number), sha3(_sha3) {}
+ LocalisedLogEntry(LogEntry const& _le, unsigned _number, h256 _transactionHash = h256()): LogEntry(_le), number(_number), transactionHash(_transactionHash) {}
unsigned number = 0;
- h256 sha3;
+ h256 transactionHash;
};
using LocalisedLogEntries = std::vector;
diff --git a/libevm/VM.cpp b/libevm/VM.cpp
index 6f6e08d4c..2c1627db9 100644
--- a/libevm/VM.cpp
+++ b/libevm/VM.cpp
@@ -36,6 +36,7 @@ struct InstructionMetric
{
int gasPriceTier;
int args;
+ int ret;
};
static array metrics()
@@ -46,12 +47,15 @@ static array metrics()
InstructionInfo inst = instructionInfo((Instruction)i);
s_ret[i].gasPriceTier = inst.gasPriceTier;
s_ret[i].args = inst.args;
+ s_ret[i].ret = inst.ret;
}
return s_ret;
}
bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps)
{
+ m_stack.reserve((unsigned)c_stackLimit);
+
static const array c_metrics = metrics();
auto memNeed = [](u256 _offset, dev::u256 _size) { return _size ? (bigint)_offset + _size : (bigint)0; };
@@ -89,7 +93,7 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps)
// should work, but just seems to result in immediate errorless exit on initial execution. yeah. weird.
//m_onFail = std::function(onOperation);
- require(metric.args);
+ require(metric.args, metric.ret);
auto onOperation = [&]()
{
diff --git a/libevm/VM.h b/libevm/VM.h
index 3efb3b119..b14a117df 100644
--- a/libevm/VM.h
+++ b/libevm/VM.h
@@ -56,7 +56,7 @@ public:
virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final;
- void require(u256 _n) { if (m_stack.size() < _n) { if (m_onFail) m_onFail(); BOOST_THROW_EXCEPTION(StackUnderflow() << RequirementError((bigint)_n, (bigint)m_stack.size())); } }
+ void require(u256 _n, u256 _d) { if (m_stack.size() < _n) { if (m_onFail) m_onFail(); BOOST_THROW_EXCEPTION(StackUnderflow() << RequirementError((bigint)_n, (bigint)m_stack.size())); } if (m_stack.size() - _n + _d >= c_stackLimit) { if (m_onFail) m_onFail(); BOOST_THROW_EXCEPTION(OutOfStack() << RequirementError((bigint)(_d - _n), (bigint)m_stack.size())); } }
void requireMem(unsigned _n) { if (m_temp.size() < _n) { m_temp.resize(_n); } }
u256 curPC() const { return m_curPC; }
diff --git a/libevm/VMFace.h b/libevm/VMFace.h
index 7b99b5bfd..d2689d13e 100644
--- a/libevm/VMFace.h
+++ b/libevm/VMFace.h
@@ -31,6 +31,7 @@ struct BreakPointHit: virtual VMException {};
struct BadInstruction: virtual VMException {};
struct BadJumpDestination: virtual VMException {};
struct OutOfGas: virtual VMException {};
+struct OutOfStack: virtual VMException {};
struct StackUnderflow: virtual VMException {};
/// EVM Virtual Machine interface
diff --git a/libjsqrc/ethereumjs/dist/ethereum.js b/libjsqrc/ethereumjs/dist/ethereum.js
index 4ae476ca5..8d00981c0 100644
--- a/libjsqrc/ethereumjs/dist/ethereum.js
+++ b/libjsqrc/ethereumjs/dist/ethereum.js
@@ -1527,7 +1527,7 @@ var addEventsToContract = function (contract, desc, address) {
var parser = eventImpl.outputParser(e);
return parser(data);
};
- return web3.eth.filter(o, undefined, undefined, outputFormatter);
+ return web3.eth.filter(o, undefined, undefined, outputFormatter);
};
// this property should be used by eth.filter to check if object is an event
@@ -2005,16 +2005,6 @@ var getOptions = function (options) {
options.toBlock = options.latest;
}
- if (options.skip) {
- console.warn('"skip" is deprecated, is "offset" instead');
- options.offset = options.skip;
- }
-
- if (options.max) {
- console.warn('"max" is deprecated, is "limit" instead');
- options.limit = options.max;
- }
-
// make sure topics, get converted to hex
if(options.topics instanceof Array) {
options.topics = options.topics.map(function(topic){
@@ -2022,13 +2012,18 @@ var getOptions = function (options) {
});
}
+ var asBlockNumber = function(n) {
+ if (n == null)
+ return null;
+ if (n == 'latest' || n == 'pending')
+ return n;
+ return utils.toHex(n);
+ };
// evaluate lazy properties
return {
- fromBlock: utils.toHex(options.fromBlock),
- toBlock: utils.toHex(options.toBlock),
- limit: utils.toHex(options.limit),
- offset: utils.toHex(options.offset),
+ fromBlock: asBlockNumber(options.fromBlock),
+ toBlock: asBlockNumber(options.toBlock),
to: options.to,
address: options.address,
topics: options.topics
@@ -2053,9 +2048,9 @@ var filter = function(options, implementation, formatter) {
// call the callbacks
var onMessages = function (messages) {
messages.forEach(function (message) {
- message = formatter ? formatter(message) : message;
+ message = formatter ? formatter(message) : message;
callbacks.forEach(function (callback) {
- callback(message);
+ callback(message);
});
});
};
@@ -2855,4 +2850,4 @@ module.exports = web3;
},{"./lib/solidity/abi":1,"./lib/web3":6,"./lib/web3/contract":7,"./lib/web3/httpprovider":13,"./lib/web3/qtsync":16}]},{},["web3"])
-//# sourceMappingURL=ethereum.js.map
+//# sourceMappingURL=ethereum.js.map
\ No newline at end of file
diff --git a/libjsqrc/ethereumjs/dist/ethereum.js.map b/libjsqrc/ethereumjs/dist/ethereum.js.map
index a36e9ed17..44144743f 100644
--- a/libjsqrc/ethereumjs/dist/ethereum.js.map
+++ b/libjsqrc/ethereumjs/dist/ethereum.js.map
@@ -26,7 +26,7 @@
"index.js"
],
"names": [],
- "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChcA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5SA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3MA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjDA;AACA;AACA;;ACFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA",
+ "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChcA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5SA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3MA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjDA;AACA;AACA;;ACFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA",
"file": "generated.js",
"sourceRoot": "",
"sourcesContent": [
@@ -37,11 +37,11 @@
"/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file config.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\n/**\n * Utils\n * \n * @module utils\n */\n\n/**\n * Utility functions\n * \n * @class [utils] config\n * @constructor\n */\n\n/// required to define ETH_BIGNUMBER_ROUNDING_MODE\nif (\"build\" !== 'build') {/*\n var BigNumber = require('bignumber.js'); // jshint ignore:line\n*/}\n\nvar ETH_UNITS = [ \n 'wei', \n 'Kwei', \n 'Mwei', \n 'Gwei', \n 'szabo', \n 'finney', \n 'ether', \n 'grand', \n 'Mether', \n 'Gether', \n 'Tether', \n 'Pether', \n 'Eether', \n 'Zether', \n 'Yether', \n 'Nether', \n 'Dether', \n 'Vether', \n 'Uether' \n];\n\nmodule.exports = {\n ETH_PADDING: 32,\n ETH_SIGNATURE_LENGTH: 4,\n ETH_UNITS: ETH_UNITS,\n ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN },\n ETH_POLLING_TIMEOUT: 1000,\n ETH_DEFAULTBLOCK: 'latest'\n};\n\n",
"/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file utils.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\n/**\n * Utils\n * \n * @module utils\n */\n\n/**\n * Utility functions\n * \n * @class [utils] utils\n * @constructor\n */\n\nif (\"build\" !== 'build') {/*\n var BigNumber = require('bignumber.js'); // jshint ignore:line\n*/}\n\nvar unitMap = {\n 'wei': '1',\n 'kwei': '1000',\n 'ada': '1000',\n 'mwei': '1000000',\n 'babbage': '1000000',\n 'gwei': '1000000000',\n 'shannon': '1000000000',\n 'szabo': '1000000000000',\n 'finney': '1000000000000000',\n 'ether': '1000000000000000000',\n 'kether': '1000000000000000000000',\n 'grand': '1000000000000000000000',\n 'einstein': '1000000000000000000000',\n 'mether': '1000000000000000000000000',\n 'gether': '1000000000000000000000000000',\n 'tether': '1000000000000000000000000000000'\n};\n\n\n/** Finds first index of array element matching pattern\n *\n * @method findIndex\n * @param {Array}\n * @param {Function} pattern\n * @returns {Number} index of element\n */\nvar findIndex = function (array, callback) {\n var end = false;\n var i = 0;\n for (; i < array.length && !end; i++) {\n end = callback(array[i]);\n }\n return end ? i - 1 : -1;\n};\n\n/** \n * Should be called to get sting from it's hex representation\n *\n * @method toAscii\n * @param {String} string in hex\n * @returns {String} ascii string representation of hex value\n */\nvar toAscii = function(hex) {\n// Find termination\n var str = \"\";\n var i = 0, l = hex.length;\n if (hex.substring(0, 2) === '0x') {\n i = 2;\n }\n for (; i < l; i+=2) {\n var code = parseInt(hex.substr(i, 2), 16);\n if (code === 0) {\n break;\n }\n\n str += String.fromCharCode(code);\n }\n\n return str;\n};\n \n/**\n * Shold be called to get hex representation (prefixed by 0x) of ascii string \n *\n * @method fromAscii\n * @param {String} string\n * @returns {String} hex representation of input string\n */\nvar toHexNative = function(str) {\n var hex = \"\";\n for(var i = 0; i < str.length; i++) {\n var n = str.charCodeAt(i).toString(16);\n hex += n.length < 2 ? '0' + n : n;\n }\n\n return hex;\n};\n\n/**\n * Shold be called to get hex representation (prefixed by 0x) of ascii string \n *\n * @method fromAscii\n * @param {String} string\n * @param {Number} optional padding\n * @returns {String} hex representation of input string\n */\nvar fromAscii = function(str, pad) {\n pad = pad === undefined ? 0 : pad;\n var hex = toHexNative(str);\n while (hex.length < pad*2)\n hex += \"00\";\n return \"0x\" + hex;\n};\n\n/**\n * Should be called to get display name of contract function\n * \n * @method extractDisplayName\n * @param {String} name of function/event\n * @returns {String} display name for function/event eg. multiply(uint256) -> multiply\n */\nvar extractDisplayName = function (name) {\n var length = name.indexOf('('); \n return length !== -1 ? name.substr(0, length) : name;\n};\n\n/// @returns overloaded part of function/event name\nvar extractTypeName = function (name) {\n /// TODO: make it invulnerable\n var length = name.indexOf('(');\n return length !== -1 ? name.substr(length + 1, name.length - 1 - (length + 1)).replace(' ', '') : \"\";\n};\n\n/**\n * Filters all functions from input abi\n *\n * @method filterFunctions\n * @param {Array} abi\n * @returns {Array} abi array with filtered objects of type 'function'\n */\nvar filterFunctions = function (json) {\n return json.filter(function (current) {\n return current.type === 'function'; \n }); \n};\n\n/**\n * Filters all events from input abi\n *\n * @method filterEvents\n * @param {Array} abi\n * @returns {Array} abi array with filtered objects of type 'event'\n */\nvar filterEvents = function (json) {\n return json.filter(function (current) {\n return current.type === 'event';\n });\n};\n\n/**\n * Converts value to it's decimal representation in string\n *\n * @method toDecimal\n * @param {String|Number|BigNumber}\n * @return {String}\n */\nvar toDecimal = function (value) {\n return toBigNumber(value).toNumber();\n};\n\n/**\n * Converts value to it's hex representation\n *\n * @method fromDecimal\n * @param {String|Number|BigNumber}\n * @return {String}\n */\nvar fromDecimal = function (value) {\n var number = toBigNumber(value);\n var result = number.toString(16);\n\n return number.lessThan(0) ? '-0x' + result.substr(1) : '0x' + result;\n};\n\n/**\n * Auto converts any given value into it's hex representation.\n *\n * And even stringifys objects before.\n *\n * @method toHex\n * @param {String|Number|BigNumber|Object}\n * @return {String}\n */\nvar toHex = function (val) {\n /*jshint maxcomplexity:7 */\n\n if(isBoolean(val))\n return val;\n\n if(isBigNumber(val))\n return fromDecimal(val);\n\n if(isObject(val))\n return fromAscii(JSON.stringify(val));\n\n // if its a negative number, pass it through fromDecimal\n if (isString(val)) {\n if (val.indexOf('-0x') === 0)\n return fromDecimal(val);\n else if (!isFinite(val))\n return fromAscii(val);\n }\n\n return fromDecimal(val);\n};\n\n/**\n * Returns value of unit in Wei\n *\n * @method getValueOfUnit\n * @param {String} unit the unit to convert to, default ether\n * @returns {BigNumber} value of the unit (in Wei)\n * @throws error if the unit is not correct:w\n */\nvar getValueOfUnit = function (unit) {\n unit = unit ? unit.toLowerCase() : 'ether';\n var unitValue = unitMap[unit];\n if (unitValue === undefined) {\n throw new Error('This unit doesn\\'t exists, please use the one of the following units' + JSON.stringify(unitMap, null, 2));\n }\n return new BigNumber(unitValue, 10);\n};\n\n/**\n * Takes a number of wei and converts it to any other ether unit.\n *\n * Possible units are:\n * - kwei/ada\n * - mwei/babbage\n * - gwei/shannon\n * - szabo\n * - finney\n * - ether\n * - kether/grand/einstein\n * - mether\n * - gether\n * - tether\n *\n * @method fromWei\n * @param {Number|String} number can be a number, number string or a HEX of a decimal\n * @param {String} unit the unit to convert to, default ether\n * @return {String|Object} When given a BigNumber object it returns one as well, otherwise a number\n*/\nvar fromWei = function(number, unit) {\n var returnValue = toBigNumber(number).dividedBy(getValueOfUnit(unit));\n\n return isBigNumber(number) ? returnValue : returnValue.toString(10); \n};\n\n/**\n * Takes a number of a unit and converts it to wei.\n *\n * Possible units are:\n * - kwei/ada\n * - mwei/babbage\n * - gwei/shannon\n * - szabo\n * - finney\n * - ether\n * - kether/grand/einstein\n * - mether\n * - gether\n * - tether\n *\n * @method toWei\n * @param {Number|String|BigNumber} number can be a number, number string or a HEX of a decimal\n * @param {String} unit the unit to convert from, default ether\n * @return {String|Object} When given a BigNumber object it returns one as well, otherwise a number\n*/\nvar toWei = function(number, unit) {\n var returnValue = toBigNumber(number).times(getValueOfUnit(unit));\n\n return isBigNumber(number) ? returnValue : returnValue.toString(10); \n};\n\n/**\n * Takes an input and transforms it into an bignumber\n *\n * @method toBigNumber\n * @param {Number|String|BigNumber} a number, string, HEX string or BigNumber\n * @return {BigNumber} BigNumber\n*/\nvar toBigNumber = function(number) {\n /*jshint maxcomplexity:5 */\n number = number || 0;\n if (isBigNumber(number))\n return number;\n\n if (isString(number) && (number.indexOf('0x') === 0 || number.indexOf('-0x') === 0)) {\n return new BigNumber(number.replace('0x',''), 16);\n }\n \n return new BigNumber(number.toString(10), 10);\n};\n\n/**\n * Takes and input transforms it into bignumber and if it is negative value, into two's complement\n *\n * @method toTwosComplement\n * @param {Number|String|BigNumber}\n * @return {BigNumber}\n */\nvar toTwosComplement = function (number) {\n var bigNumber = toBigNumber(number);\n if (bigNumber.lessThan(0)) {\n return new BigNumber(\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\", 16).plus(bigNumber).plus(1);\n }\n return bigNumber;\n};\n\n/**\n * Checks if the given string has proper length\n *\n * @method isAddress\n * @param {String} address the given HEX adress\n * @return {Boolean}\n*/\nvar isAddress = function(address) {\n if (!isString(address)) {\n return false;\n }\n\n return ((address.indexOf('0x') === 0 && address.length === 42) ||\n (address.indexOf('0x') === -1 && address.length === 40));\n};\n\n/**\n * Returns true if object is BigNumber, otherwise false\n *\n * @method isBigNumber\n * @param {Object}\n * @return {Boolean} \n */\nvar isBigNumber = function (object) {\n return object instanceof BigNumber ||\n (object && object.constructor && object.constructor.name === 'BigNumber');\n};\n\n/**\n * Returns true if object is string, otherwise false\n * \n * @method isString\n * @param {Object}\n * @return {Boolean}\n */\nvar isString = function (object) {\n return typeof object === 'string' ||\n (object && object.constructor && object.constructor.name === 'String');\n};\n\n/**\n * Returns true if object is function, otherwise false\n *\n * @method isFunction\n * @param {Object}\n * @return {Boolean}\n */\nvar isFunction = function (object) {\n return typeof object === 'function';\n};\n\n/**\n * Returns true if object is Objet, otherwise false\n *\n * @method isObject\n * @param {Object}\n * @return {Boolean}\n */\nvar isObject = function (object) {\n return typeof object === 'object';\n};\n\n/**\n * Returns true if object is boolean, otherwise false\n *\n * @method isBoolean\n * @param {Object}\n * @return {Boolean}\n */\nvar isBoolean = function (object) {\n return typeof object === 'boolean';\n};\n\n/**\n * Returns true if object is array, otherwise false\n *\n * @method isArray\n * @param {Object}\n * @return {Boolean}\n */\nvar isArray = function (object) {\n return object instanceof Array; \n};\n\nmodule.exports = {\n findIndex: findIndex,\n toHex: toHex,\n toDecimal: toDecimal,\n fromDecimal: fromDecimal,\n toAscii: toAscii,\n fromAscii: fromAscii,\n extractDisplayName: extractDisplayName,\n extractTypeName: extractTypeName,\n filterFunctions: filterFunctions,\n filterEvents: filterEvents,\n toWei: toWei,\n fromWei: fromWei,\n toBigNumber: toBigNumber,\n toTwosComplement: toTwosComplement,\n isBigNumber: isBigNumber,\n isAddress: isAddress,\n isFunction: isFunction,\n isString: isString,\n isObject: isObject,\n isBoolean: isBoolean,\n isArray: isArray\n};\n\n",
"/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file web3.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Fabian Vogelsteller \n * Gav Wood \n * @date 2014\n */\n\nvar version = require('../version.json');\nvar net = require('./web3/net');\nvar eth = require('./web3/eth');\nvar db = require('./web3/db');\nvar shh = require('./web3/shh');\nvar watches = require('./web3/watches');\nvar filter = require('./web3/filter');\nvar utils = require('./utils/utils');\nvar formatters = require('./solidity/formatters');\nvar requestManager = require('./web3/requestmanager');\nvar c = require('./utils/config');\n\n/// @returns an array of objects describing web3 api methods\nvar web3Methods = [\n { name: 'sha3', call: 'web3_sha3', inputFormatter: utils.toHex },\n];\nvar web3Properties = [\n { name: 'version.client', getter: 'web3_clientVersion' },\n { name: 'version.network', getter: 'net_version' }\n];\n\n\n/// creates methods in a given object based on method description on input\n/// setups api calls for these methods\nvar setupMethods = function (obj, methods) {\n methods.forEach(function (method) {\n // allow for object methods 'myObject.method'\n var objectMethods = method.name.split('.'),\n callFunction = function () {\n /*jshint maxcomplexity:8 */\n \n var callback = null,\n args = Array.prototype.slice.call(arguments),\n call = typeof method.call === 'function' ? method.call(args) : method.call;\n\n // get the callback if one is available\n if(typeof args[args.length-1] === 'function'){\n callback = args[args.length-1];\n Array.prototype.pop.call(args);\n }\n\n // add the defaultBlock if not given\n if(method.addDefaultblock) {\n if(args.length !== method.addDefaultblock)\n Array.prototype.push.call(args, (isFinite(c.ETH_DEFAULTBLOCK) ? utils.fromDecimal(c.ETH_DEFAULTBLOCK) : c.ETH_DEFAULTBLOCK));\n else\n args[args.length-1] = isFinite(args[args.length-1]) ? utils.fromDecimal(args[args.length-1]) : args[args.length-1];\n }\n\n // show deprecated warning\n if(method.newMethod)\n console.warn('This method is deprecated please use web3.'+ method.newMethod +'() instead.');\n\n return web3.manager.send({\n method: call,\n params: args,\n outputFormatter: method.outputFormatter,\n inputFormatter: method.inputFormatter,\n addDefaultblock: method.addDefaultblock\n }, callback);\n };\n\n if(objectMethods.length > 1) {\n if(!obj[objectMethods[0]])\n obj[objectMethods[0]] = {};\n\n obj[objectMethods[0]][objectMethods[1]] = callFunction;\n \n } else {\n\n obj[objectMethods[0]] = callFunction;\n }\n\n });\n};\n\n/// creates properties in a given object based on properties description on input\n/// setups api calls for these properties\nvar setupProperties = function (obj, properties) {\n properties.forEach(function (property) {\n var objectProperties = property.name.split('.'),\n proto = {};\n\n proto.get = function () {\n\n // show deprecated warning\n if(property.newProperty)\n console.warn('This property is deprecated please use web3.'+ property.newProperty +' instead.');\n\n\n return web3.manager.send({\n method: property.getter,\n outputFormatter: property.outputFormatter\n });\n };\n\n if (property.setter) {\n proto.set = function (val) {\n\n // show deprecated warning\n if(property.newProperty)\n console.warn('This property is deprecated please use web3.'+ property.newProperty +' instead.');\n\n return web3.manager.send({\n method: property.setter,\n params: [val],\n inputFormatter: property.inputFormatter\n });\n };\n }\n\n proto.enumerable = !property.newProperty;\n\n if(objectProperties.length > 1) {\n if(!obj[objectProperties[0]])\n obj[objectProperties[0]] = {};\n\n Object.defineProperty(obj[objectProperties[0]], objectProperties[1], proto); \n } else\n Object.defineProperty(obj, property.name, proto);\n\n });\n};\n\n/*jshint maxparams:4 */\nvar startPolling = function (method, id, callback, uninstall) {\n web3.manager.startPolling({\n method: method, \n params: [id]\n }, id, callback, uninstall); \n};\n/*jshint maxparams:3 */\n\nvar stopPolling = function (id) {\n web3.manager.stopPolling(id);\n};\n\nvar ethWatch = {\n startPolling: startPolling.bind(null, 'eth_getFilterChanges'), \n stopPolling: stopPolling\n};\n\nvar shhWatch = {\n startPolling: startPolling.bind(null, 'shh_getFilterChanges'), \n stopPolling: stopPolling\n};\n\n/// setups web3 object, and it's in-browser executed methods\nvar web3 = {\n\n version: {\n api: version.version\n },\n\n manager: requestManager(),\n providers: {},\n\n setProvider: function (provider) {\n web3.manager.setProvider(provider);\n },\n \n /// Should be called to reset state of web3 object\n /// Resets everything except manager\n reset: function () {\n web3.manager.reset(); \n },\n\n /// @returns hex string of the input\n toHex: utils.toHex,\n\n /// @returns ascii string representation of hex value prefixed with 0x\n toAscii: utils.toAscii,\n\n /// @returns hex representation (prefixed by 0x) of ascii string\n fromAscii: utils.fromAscii,\n\n /// @returns decimal representaton of hex value prefixed by 0x\n toDecimal: utils.toDecimal,\n\n /// @returns hex representation (prefixed by 0x) of decimal value\n fromDecimal: utils.fromDecimal,\n\n /// @returns a BigNumber object\n toBigNumber: utils.toBigNumber,\n\n toWei: utils.toWei,\n fromWei: utils.fromWei,\n isAddress: utils.isAddress,\n\n // provide network information\n net: {\n // peerCount: \n },\n\n\n /// eth object prototype\n eth: {\n // DEPRECATED\n contractFromAbi: function (abi) {\n console.warn('Initiating a contract like this is deprecated please use var MyContract = eth.contract(abi); new MyContract(address); instead.');\n\n return function(addr) {\n // Default to address of Config. TODO: rremove prior to genesis.\n addr = addr || '0xc6d9d2cd449a754c494264e1809c50e34d64562b';\n var ret = web3.eth.contract(addr, abi);\n ret.address = addr;\n return ret;\n };\n },\n\n /// @param filter may be a string, object or event\n /// @param eventParams is optional, this is an object with optional event eventParams params\n /// @param options is optional, this is an object with optional event options ('max'...)\n /*jshint maxparams:4 */\n filter: function (fil, eventParams, options) {\n\n // if its event, treat it differently\n if (fil._isEvent)\n return fil(eventParams, options);\n\n return filter(fil, ethWatch, formatters.outputLogFormatter);\n },\n // DEPRECATED\n watch: function (fil, eventParams, options) {\n console.warn('eth.watch() is deprecated please use eth.filter() instead.');\n return this.filter(fil, eventParams, options);\n }\n /*jshint maxparams:3 */\n },\n\n /// db object prototype\n db: {},\n\n /// shh object prototype\n shh: {\n /// @param filter may be a string, object or event\n filter: function (fil) {\n return filter(fil, shhWatch, formatters.outputPostFormatter);\n },\n // DEPRECATED\n watch: function (fil) {\n console.warn('shh.watch() is deprecated please use shh.filter() instead.');\n return this.filter(fil);\n }\n }\n};\n\n\n// ADD defaultblock\nObject.defineProperty(web3.eth, 'defaultBlock', {\n get: function () {\n return c.ETH_DEFAULTBLOCK;\n },\n set: function (val) {\n c.ETH_DEFAULTBLOCK = val;\n return c.ETH_DEFAULTBLOCK;\n }\n});\n\n\n/// setups all api methods\nsetupMethods(web3, web3Methods);\nsetupProperties(web3, web3Properties);\nsetupMethods(web3.net, net.methods);\nsetupProperties(web3.net, net.properties);\nsetupMethods(web3.eth, eth.methods);\nsetupProperties(web3.eth, eth.properties);\nsetupMethods(web3.db, db.methods());\nsetupMethods(web3.shh, shh.methods());\nsetupMethods(ethWatch, watches.eth());\nsetupMethods(shhWatch, watches.shh());\n\nmodule.exports = web3;\n\n",
- "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file contract.js\n * @authors:\n * Marek Kotewicz \n * @date 2014\n */\n\nvar web3 = require('../web3'); \nvar abi = require('../solidity/abi');\nvar utils = require('../utils/utils');\nvar eventImpl = require('./event');\nvar signature = require('./signature');\n\nvar exportNatspecGlobals = function (vars) {\n // it's used byt natspec.js\n // TODO: figure out better way to solve this\n web3._currentContractAbi = vars.abi;\n web3._currentContractAddress = vars.address;\n web3._currentContractMethodName = vars.method;\n web3._currentContractMethodParams = vars.params;\n};\n\nvar addFunctionRelatedPropertiesToContract = function (contract) {\n \n contract.call = function (options) {\n contract._isTransaction = false;\n contract._options = options;\n return contract;\n };\n\n\n contract.sendTransaction = function (options) {\n contract._isTransaction = true;\n contract._options = options;\n return contract;\n };\n // DEPRECATED\n contract.transact = function (options) {\n\n console.warn('myContract.transact() is deprecated please use myContract.sendTransaction() instead.');\n\n return contract.sendTransaction(options);\n };\n\n contract._options = {};\n ['gas', 'gasPrice', 'value', 'from'].forEach(function(p) {\n contract[p] = function (v) {\n contract._options[p] = v;\n return contract;\n };\n });\n\n};\n\nvar addFunctionsToContract = function (contract, desc, address) {\n var inputParser = abi.inputParser(desc);\n var outputParser = abi.outputParser(desc);\n\n // create contract functions\n utils.filterFunctions(desc).forEach(function (method) {\n\n var displayName = utils.extractDisplayName(method.name);\n var typeName = utils.extractTypeName(method.name);\n\n var impl = function () {\n /*jshint maxcomplexity:7 */\n var params = Array.prototype.slice.call(arguments);\n var sign = signature.functionSignatureFromAscii(method.name);\n var parsed = inputParser[displayName][typeName].apply(null, params);\n\n var options = contract._options || {};\n options.to = address;\n options.data = sign + parsed;\n \n var isTransaction = contract._isTransaction === true || (contract._isTransaction !== false && !method.constant);\n var collapse = options.collapse !== false;\n \n // reset\n contract._options = {};\n contract._isTransaction = null;\n\n if (isTransaction) {\n \n exportNatspecGlobals({\n abi: desc,\n address: address,\n method: method.name,\n params: params\n });\n\n // transactions do not have any output, cause we do not know, when they will be processed\n web3.eth.sendTransaction(options);\n return;\n }\n \n var output = web3.eth.call(options);\n var ret = outputParser[displayName][typeName](output);\n if (collapse)\n {\n if (ret.length === 1)\n ret = ret[0];\n else if (ret.length === 0)\n ret = null;\n }\n return ret;\n };\n\n if (contract[displayName] === undefined) {\n contract[displayName] = impl;\n }\n\n contract[displayName][typeName] = impl;\n });\n};\n\nvar addEventRelatedPropertiesToContract = function (contract, desc, address) {\n contract.address = address;\n contract._onWatchEventResult = function (data) {\n var matchingEvent = event.getMatchingEvent(utils.filterEvents(desc));\n var parser = eventImpl.outputParser(matchingEvent);\n return parser(data);\n };\n \n Object.defineProperty(contract, 'topics', {\n get: function() {\n return utils.filterEvents(desc).map(function (e) {\n return signature.eventSignatureFromAscii(e.name);\n });\n }\n });\n\n};\n\nvar addEventsToContract = function (contract, desc, address) {\n // create contract events\n utils.filterEvents(desc).forEach(function (e) {\n\n var impl = function () {\n var params = Array.prototype.slice.call(arguments);\n var sign = signature.eventSignatureFromAscii(e.name);\n var event = eventImpl.inputParser(address, sign, e);\n var o = event.apply(null, params);\n var outputFormatter = function (data) {\n var parser = eventImpl.outputParser(e);\n return parser(data);\n };\n return web3.eth.filter(o, undefined, undefined, outputFormatter);\n };\n \n // this property should be used by eth.filter to check if object is an event\n impl._isEvent = true;\n\n var displayName = utils.extractDisplayName(e.name);\n var typeName = utils.extractTypeName(e.name);\n\n if (contract[displayName] === undefined) {\n contract[displayName] = impl;\n }\n\n contract[displayName][typeName] = impl;\n\n });\n};\n\n\n/**\n * This method should be called when we want to call / transact some solidity method from javascript\n * it returns an object which has same methods available as solidity contract description\n * usage example: \n *\n * var abi = [{\n * name: 'myMethod',\n * inputs: [{ name: 'a', type: 'string' }],\n * outputs: [{name: 'd', type: 'string' }]\n * }]; // contract abi\n *\n * var MyContract = web3.eth.contract(abi); // creation of contract prototype\n *\n * var contractInstance = new MyContract('0x0123123121');\n *\n * contractInstance.myMethod('this is test string param for call'); // myMethod call (implicit, default)\n * contractInstance.call().myMethod('this is test string param for call'); // myMethod call (explicit)\n * contractInstance.sendTransaction().myMethod('this is test string param for transact'); // myMethod sendTransaction\n *\n * @param abi - abi json description of the contract, which is being created\n * @returns contract object\n */\nvar contract = function (abi) {\n\n // return prototype\n if(abi instanceof Array && arguments.length === 1) {\n return Contract.bind(null, abi);\n\n // deprecated: auto initiate contract\n } else {\n\n console.warn('Initiating a contract like this is deprecated please use var MyContract = eth.contract(abi); new MyContract(address); instead.');\n\n return new Contract(arguments[1], arguments[0]);\n }\n\n};\n\nfunction Contract(abi, address) {\n\n // workaround for invalid assumption that method.name is the full anonymous prototype of the method.\n // it's not. it's just the name. the rest of the code assumes it's actually the anonymous\n // prototype, so we make it so as a workaround.\n // TODO: we may not want to modify input params, maybe use copy instead?\n abi.forEach(function (method) {\n if (method.name.indexOf('(') === -1) {\n var displayName = method.name;\n var typeName = method.inputs.map(function(i){return i.type; }).join();\n method.name = displayName + '(' + typeName + ')';\n }\n });\n\n var result = {};\n addFunctionRelatedPropertiesToContract(result);\n addFunctionsToContract(result, abi, address);\n addEventRelatedPropertiesToContract(result, abi, address);\n addEventsToContract(result, abi, address);\n\n return result;\n}\n\nmodule.exports = contract;\n\n",
+ "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file contract.js\n * @authors:\n * Marek Kotewicz \n * @date 2014\n */\n\nvar web3 = require('../web3'); \nvar abi = require('../solidity/abi');\nvar utils = require('../utils/utils');\nvar eventImpl = require('./event');\nvar signature = require('./signature');\n\nvar exportNatspecGlobals = function (vars) {\n // it's used byt natspec.js\n // TODO: figure out better way to solve this\n web3._currentContractAbi = vars.abi;\n web3._currentContractAddress = vars.address;\n web3._currentContractMethodName = vars.method;\n web3._currentContractMethodParams = vars.params;\n};\n\nvar addFunctionRelatedPropertiesToContract = function (contract) {\n \n contract.call = function (options) {\n contract._isTransaction = false;\n contract._options = options;\n return contract;\n };\n\n\n contract.sendTransaction = function (options) {\n contract._isTransaction = true;\n contract._options = options;\n return contract;\n };\n // DEPRECATED\n contract.transact = function (options) {\n\n console.warn('myContract.transact() is deprecated please use myContract.sendTransaction() instead.');\n\n return contract.sendTransaction(options);\n };\n\n contract._options = {};\n ['gas', 'gasPrice', 'value', 'from'].forEach(function(p) {\n contract[p] = function (v) {\n contract._options[p] = v;\n return contract;\n };\n });\n\n};\n\nvar addFunctionsToContract = function (contract, desc, address) {\n var inputParser = abi.inputParser(desc);\n var outputParser = abi.outputParser(desc);\n\n // create contract functions\n utils.filterFunctions(desc).forEach(function (method) {\n\n var displayName = utils.extractDisplayName(method.name);\n var typeName = utils.extractTypeName(method.name);\n\n var impl = function () {\n /*jshint maxcomplexity:7 */\n var params = Array.prototype.slice.call(arguments);\n var sign = signature.functionSignatureFromAscii(method.name);\n var parsed = inputParser[displayName][typeName].apply(null, params);\n\n var options = contract._options || {};\n options.to = address;\n options.data = sign + parsed;\n \n var isTransaction = contract._isTransaction === true || (contract._isTransaction !== false && !method.constant);\n var collapse = options.collapse !== false;\n \n // reset\n contract._options = {};\n contract._isTransaction = null;\n\n if (isTransaction) {\n \n exportNatspecGlobals({\n abi: desc,\n address: address,\n method: method.name,\n params: params\n });\n\n // transactions do not have any output, cause we do not know, when they will be processed\n web3.eth.sendTransaction(options);\n return;\n }\n \n var output = web3.eth.call(options);\n var ret = outputParser[displayName][typeName](output);\n if (collapse)\n {\n if (ret.length === 1)\n ret = ret[0];\n else if (ret.length === 0)\n ret = null;\n }\n return ret;\n };\n\n if (contract[displayName] === undefined) {\n contract[displayName] = impl;\n }\n\n contract[displayName][typeName] = impl;\n });\n};\n\nvar addEventRelatedPropertiesToContract = function (contract, desc, address) {\n contract.address = address;\n contract._onWatchEventResult = function (data) {\n var matchingEvent = event.getMatchingEvent(utils.filterEvents(desc));\n var parser = eventImpl.outputParser(matchingEvent);\n return parser(data);\n };\n \n Object.defineProperty(contract, 'topics', {\n get: function() {\n return utils.filterEvents(desc).map(function (e) {\n return signature.eventSignatureFromAscii(e.name);\n });\n }\n });\n\n};\n\nvar addEventsToContract = function (contract, desc, address) {\n // create contract events\n utils.filterEvents(desc).forEach(function (e) {\n\n var impl = function () {\n var params = Array.prototype.slice.call(arguments);\n var sign = signature.eventSignatureFromAscii(e.name);\n var event = eventImpl.inputParser(address, sign, e);\n var o = event.apply(null, params);\n var outputFormatter = function (data) {\n var parser = eventImpl.outputParser(e);\n return parser(data);\n };\n\t\t\treturn web3.eth.filter(o, undefined, undefined, outputFormatter);\n };\n \n // this property should be used by eth.filter to check if object is an event\n impl._isEvent = true;\n\n var displayName = utils.extractDisplayName(e.name);\n var typeName = utils.extractTypeName(e.name);\n\n if (contract[displayName] === undefined) {\n contract[displayName] = impl;\n }\n\n contract[displayName][typeName] = impl;\n\n });\n};\n\n\n/**\n * This method should be called when we want to call / transact some solidity method from javascript\n * it returns an object which has same methods available as solidity contract description\n * usage example: \n *\n * var abi = [{\n * name: 'myMethod',\n * inputs: [{ name: 'a', type: 'string' }],\n * outputs: [{name: 'd', type: 'string' }]\n * }]; // contract abi\n *\n * var MyContract = web3.eth.contract(abi); // creation of contract prototype\n *\n * var contractInstance = new MyContract('0x0123123121');\n *\n * contractInstance.myMethod('this is test string param for call'); // myMethod call (implicit, default)\n * contractInstance.call().myMethod('this is test string param for call'); // myMethod call (explicit)\n * contractInstance.sendTransaction().myMethod('this is test string param for transact'); // myMethod sendTransaction\n *\n * @param abi - abi json description of the contract, which is being created\n * @returns contract object\n */\nvar contract = function (abi) {\n\n // return prototype\n if(abi instanceof Array && arguments.length === 1) {\n return Contract.bind(null, abi);\n\n // deprecated: auto initiate contract\n } else {\n\n console.warn('Initiating a contract like this is deprecated please use var MyContract = eth.contract(abi); new MyContract(address); instead.');\n\n return new Contract(arguments[1], arguments[0]);\n }\n\n};\n\nfunction Contract(abi, address) {\n\n // workaround for invalid assumption that method.name is the full anonymous prototype of the method.\n // it's not. it's just the name. the rest of the code assumes it's actually the anonymous\n // prototype, so we make it so as a workaround.\n // TODO: we may not want to modify input params, maybe use copy instead?\n abi.forEach(function (method) {\n if (method.name.indexOf('(') === -1) {\n var displayName = method.name;\n var typeName = method.inputs.map(function(i){return i.type; }).join();\n method.name = displayName + '(' + typeName + ')';\n }\n });\n\n var result = {};\n addFunctionRelatedPropertiesToContract(result);\n addFunctionsToContract(result, abi, address);\n addEventRelatedPropertiesToContract(result, abi, address);\n addEventsToContract(result, abi, address);\n\n return result;\n}\n\nmodule.exports = contract;\n\n",
"/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file db.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\n\n/// @returns an array of objects describing web3.db api methods\nvar methods = function () {\n return [\n { name: 'putString', call: 'db_putString'},\n { name: 'getString', call: 'db_getString'},\n { name: 'putHex', call: 'db_putHex'},\n { name: 'getHex', call: 'db_getHex'}\n ];\n};\n\nmodule.exports = {\n methods: methods\n};\n",
- "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file eth.js\n * @authors:\n * Marek Kotewicz \n * Fabian Vogelsteller \n * @date 2015\n */\n\n/**\n * Web3\n * \n * @module web3\n */\n\n/**\n * Eth methods and properties\n *\n * An example method object can look as follows:\n *\n * {\n * name: 'getBlock',\n * call: blockCall,\n * outputFormatter: formatters.outputBlockFormatter,\n * inputFormatter: [ // can be a formatter funciton or an array of functions. Where each item in the array will be used for one parameter\n * utils.toHex, // formats paramter 1\n * function(param){ if(!param) return false; } // formats paramter 2\n * ]\n * },\n *\n * @class [web3] eth\n * @constructor\n */\n\n\nvar formatters = require('./formatters');\nvar utils = require('../utils/utils');\n\n\nvar blockCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? \"eth_getBlockByHash\" : \"eth_getBlockByNumber\";\n};\n\nvar transactionFromBlockCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getTransactionByBlockHashAndIndex' : 'eth_getTransactionByBlockNumberAndIndex';\n};\n\nvar uncleCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getUncleByBlockHashAndIndex' : 'eth_getUncleByBlockNumberAndIndex';\n};\n\nvar getBlockTransactionCountCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getBlockTransactionCountByHash' : 'eth_getBlockTransactionCountByNumber';\n};\n\nvar uncleCountCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getUncleCountByBlockHash' : 'eth_getUncleCountByBlockNumber';\n};\n\n/// @returns an array of objects describing web3.eth api methods\nvar methods = [\n { name: 'getBalance', call: 'eth_getBalance', addDefaultblock: 2,\n outputFormatter: formatters.convertToBigNumber},\n { name: 'getStorage', call: 'eth_getStorage', addDefaultblock: 2},\n { name: 'getStorageAt', call: 'eth_getStorageAt', addDefaultblock: 3,\n inputFormatter: utils.toHex},\n { name: 'getData', call: 'eth_getData', addDefaultblock: 2},\n { name: 'getBlock', call: blockCall,\n outputFormatter: formatters.outputBlockFormatter,\n inputFormatter: [utils.toHex, function(param){ return (!param) ? false : true; }]},\n { name: 'getUncle', call: uncleCall,\n outputFormatter: formatters.outputBlockFormatter,\n inputFormatter: [utils.toHex, utils.toHex, function(param){ return (!param) ? false : true; }]},\n { name: 'getCompilers', call: 'eth_getCompilers' },\n { name: 'getBlockTransactionCount', call: getBlockTransactionCountCall,\n outputFormatter: utils.toDecimal,\n inputFormatter: utils.toHex },\n { name: 'getBlockUncleCount', call: uncleCountCall,\n outputFormatter: utils.toDecimal,\n inputFormatter: utils.toHex },\n { name: 'getTransaction', call: 'eth_getTransactionByHash',\n outputFormatter: formatters.outputTransactionFormatter },\n { name: 'getTransactionFromBlock', call: transactionFromBlockCall,\n outputFormatter: formatters.outputTransactionFormatter,\n inputFormatter: utils.toHex },\n { name: 'getTransactionCount', call: 'eth_getTransactionCount', addDefaultblock: 2,\n outputFormatter: utils.toDecimal},\n { name: 'sendTransaction', call: 'eth_sendTransaction',\n inputFormatter: formatters.inputTransactionFormatter },\n { name: 'call', call: 'eth_call', addDefaultblock: 2,\n inputFormatter: formatters.inputCallFormatter },\n { name: 'compile.solidity', call: 'eth_compileSolidity' },\n { name: 'compile.lll', call: 'eth_compileLLL', inputFormatter: utils.toHex },\n { name: 'compile.serpent', call: 'eth_compileSerpent', inputFormatter: utils.toHex },\n { name: 'flush', call: 'eth_flush' },\n\n // deprecated methods\n { name: 'balanceAt', call: 'eth_balanceAt', newMethod: 'eth.getBalance' },\n { name: 'stateAt', call: 'eth_stateAt', newMethod: 'eth.getStorageAt' },\n { name: 'storageAt', call: 'eth_storageAt', newMethod: 'eth.getStorage' },\n { name: 'countAt', call: 'eth_countAt', newMethod: 'eth.getTransactionCount' },\n { name: 'codeAt', call: 'eth_codeAt', newMethod: 'eth.getData' },\n { name: 'transact', call: 'eth_transact', newMethod: 'eth.sendTransaction' },\n { name: 'block', call: blockCall, newMethod: 'eth.getBlock' },\n { name: 'transaction', call: transactionFromBlockCall, newMethod: 'eth.getTransaction' },\n { name: 'uncle', call: uncleCall, newMethod: 'eth.getUncle' },\n { name: 'compilers', call: 'eth_compilers', newMethod: 'eth.getCompilers' },\n { name: 'solidity', call: 'eth_solidity', newMethod: 'eth.compile.solidity' },\n { name: 'lll', call: 'eth_lll', newMethod: 'eth.compile.lll' },\n { name: 'serpent', call: 'eth_serpent', newMethod: 'eth.compile.serpent' },\n { name: 'transactionCount', call: getBlockTransactionCountCall, newMethod: 'eth.getBlockTransactionCount' },\n { name: 'uncleCount', call: uncleCountCall, newMethod: 'eth.getBlockUncleCount' },\n { name: 'logs', call: 'eth_logs' }\n];\n\n/// @returns an array of objects describing web3.eth api properties\nvar properties = [\n { name: 'coinbase', getter: 'eth_coinbase'},\n { name: 'mining', getter: 'eth_mining'},\n { name: 'gasPrice', getter: 'eth_gasPrice', outputFormatter: formatters.convertToBigNumber},\n { name: 'accounts', getter: 'eth_accounts' },\n { name: 'blockNumber', getter: 'eth_blockNumber', outputFormatter: utils.toDecimal},\n\n // deprecated properties\n { name: 'listening', getter: 'net_listening', setter: 'eth_setListening', newProperty: 'net.listening'},\n { name: 'peerCount', getter: 'net_peerCount', newProperty: 'net.peerCount'},\n { name: 'number', getter: 'eth_number', newProperty: 'eth.blockNumber'}\n];\n\n\nmodule.exports = {\n methods: methods,\n properties: properties\n};\n\n",
+ "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file eth.js\n * @authors:\n * Marek Kotewicz \n * Fabian Vogelsteller \n * @date 2015\n */\n\n/**\n * Web3\n * \n * @module web3\n */\n\n/**\n * Eth methods and properties\n *\n * An example method object can look as follows:\n *\n * {\n * name: 'getBlock',\n * call: blockCall,\n * outputFormatter: formatters.outputBlockFormatter,\n * inputFormatter: [ // can be a formatter funciton or an array of functions. Where each item in the array will be used for one parameter\n * utils.toHex, // formats paramter 1\n * function(param){ if(!param) return false; } // formats paramter 2\n * ]\n * },\n *\n * @class [web3] eth\n * @constructor\n */\n\n\nvar formatters = require('./formatters');\nvar utils = require('../utils/utils');\n\n\nvar blockCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? \"eth_getBlockByHash\" : \"eth_getBlockByNumber\";\n};\n\nvar transactionFromBlockCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getTransactionByBlockHashAndIndex' : 'eth_getTransactionByBlockNumberAndIndex';\n};\n\nvar uncleCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getUncleByBlockHashAndIndex' : 'eth_getUncleByBlockNumberAndIndex';\n};\n\nvar getBlockTransactionCountCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getBlockTransactionCountByHash' : 'eth_getBlockTransactionCountByNumber';\n};\n\nvar uncleCountCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getUncleCountByBlockHash' : 'eth_getUncleCountByBlockNumber';\n};\n\n/// @returns an array of objects describing web3.eth api methods\nvar methods = [\n { name: 'getBalance', call: 'eth_getBalance', addDefaultblock: 2,\n outputFormatter: formatters.convertToBigNumber},\n { name: 'getStorageAt', call: 'eth_getStorageAt', addDefaultblock: 3,\n inputFormatter: utils.toHex},\n\t{ name: 'getCode', call: 'eth_getCode', addDefaultblock: 2},\n { name: 'getBlock', call: blockCall,\n outputFormatter: formatters.outputBlockFormatter,\n inputFormatter: [utils.toHex, function(param){ return (!param) ? false : true; }]},\n { name: 'getUncle', call: uncleCall,\n outputFormatter: formatters.outputBlockFormatter,\n inputFormatter: [utils.toHex, utils.toHex, function(param){ return (!param) ? false : true; }]},\n { name: 'getCompilers', call: 'eth_getCompilers' },\n { name: 'getBlockTransactionCount', call: getBlockTransactionCountCall,\n outputFormatter: utils.toDecimal,\n inputFormatter: utils.toHex },\n { name: 'getBlockUncleCount', call: uncleCountCall,\n outputFormatter: utils.toDecimal,\n inputFormatter: utils.toHex },\n { name: 'getTransaction', call: 'eth_getTransactionByHash',\n outputFormatter: formatters.outputTransactionFormatter },\n { name: 'getTransactionFromBlock', call: transactionFromBlockCall,\n outputFormatter: formatters.outputTransactionFormatter,\n inputFormatter: utils.toHex },\n { name: 'getTransactionCount', call: 'eth_getTransactionCount', addDefaultblock: 2,\n outputFormatter: utils.toDecimal},\n { name: 'sendTransaction', call: 'eth_sendTransaction',\n inputFormatter: formatters.inputTransactionFormatter },\n { name: 'call', call: 'eth_call', addDefaultblock: 2,\n inputFormatter: formatters.inputCallFormatter },\n { name: 'compile.solidity', call: 'eth_compileSolidity' },\n { name: 'compile.lll', call: 'eth_compileLLL', inputFormatter: utils.toHex },\n { name: 'compile.serpent', call: 'eth_compileSerpent', inputFormatter: utils.toHex },\n { name: 'flush', call: 'eth_flush' },\n\n // deprecated methods\n { name: 'balanceAt', call: 'eth_balanceAt', newMethod: 'eth.getBalance' },\n { name: 'stateAt', call: 'eth_stateAt', newMethod: 'eth.getStorageAt' },\n { name: 'storageAt', call: 'eth_storageAt', newMethod: 'eth.getStorage' },\n { name: 'countAt', call: 'eth_countAt', newMethod: 'eth.getTransactionCount' },\n\t{ name: 'codeAt', call: 'eth_codeAt', newMethod: 'eth.getCode' },\n { name: 'transact', call: 'eth_transact', newMethod: 'eth.sendTransaction' },\n { name: 'block', call: blockCall, newMethod: 'eth.getBlock' },\n { name: 'transaction', call: transactionFromBlockCall, newMethod: 'eth.getTransaction' },\n { name: 'uncle', call: uncleCall, newMethod: 'eth.getUncle' },\n { name: 'compilers', call: 'eth_compilers', newMethod: 'eth.getCompilers' },\n { name: 'solidity', call: 'eth_solidity', newMethod: 'eth.compile.solidity' },\n { name: 'lll', call: 'eth_lll', newMethod: 'eth.compile.lll' },\n { name: 'serpent', call: 'eth_serpent', newMethod: 'eth.compile.serpent' },\n { name: 'transactionCount', call: getBlockTransactionCountCall, newMethod: 'eth.getBlockTransactionCount' },\n { name: 'uncleCount', call: uncleCountCall, newMethod: 'eth.getBlockUncleCount' },\n { name: 'logs', call: 'eth_logs' }\n];\n\n/// @returns an array of objects describing web3.eth api properties\nvar properties = [\n { name: 'coinbase', getter: 'eth_coinbase'},\n { name: 'mining', getter: 'eth_mining'},\n { name: 'gasPrice', getter: 'eth_gasPrice', outputFormatter: formatters.convertToBigNumber},\n { name: 'accounts', getter: 'eth_accounts' },\n { name: 'blockNumber', getter: 'eth_blockNumber', outputFormatter: utils.toDecimal},\n\n // deprecated properties\n { name: 'listening', getter: 'net_listening', setter: 'eth_setListening', newProperty: 'net.listening'},\n { name: 'peerCount', getter: 'net_peerCount', newProperty: 'net.peerCount'},\n { name: 'number', getter: 'eth_number', newProperty: 'eth.blockNumber'}\n];\n\n\nmodule.exports = {\n methods: methods,\n properties: properties\n};\n\n",
"/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file event.js\n * @authors:\n * Marek Kotewicz \n * @date 2014\n */\n\nvar abi = require('../solidity/abi');\nvar utils = require('../utils/utils');\nvar signature = require('./signature');\n\n/// filter inputs array && returns only indexed (or not) inputs\n/// @param inputs array\n/// @param bool if result should be an array of indexed params on not\n/// @returns array of (not?) indexed params\nvar filterInputs = function (inputs, indexed) {\n return inputs.filter(function (current) {\n return current.indexed === indexed;\n });\n};\n\nvar inputWithName = function (inputs, name) {\n var index = utils.findIndex(inputs, function (input) {\n return input.name === name;\n });\n \n if (index === -1) {\n console.error('indexed param with name ' + name + ' not found');\n return undefined;\n }\n return inputs[index];\n};\n\nvar indexedParamsToTopics = function (event, indexed) {\n // sort keys?\n return Object.keys(indexed).map(function (key) {\n var inputs = [inputWithName(filterInputs(event.inputs, true), key)];\n\n var value = indexed[key];\n if (value instanceof Array) {\n return value.map(function (v) {\n return abi.formatInput(inputs, [v]);\n }); \n }\n return abi.formatInput(inputs, [value]);\n });\n};\n\nvar inputParser = function (address, sign, event) {\n \n // valid options are 'earliest', 'latest', 'offset' and 'max', as defined for 'eth.filter'\n return function (indexed, options) {\n var o = options || {};\n o.address = address;\n o.topics = [];\n o.topics.push(sign);\n if (indexed) {\n o.topics = o.topics.concat(indexedParamsToTopics(event, indexed));\n }\n return o;\n };\n};\n\nvar getArgumentsObject = function (inputs, indexed, notIndexed) {\n var indexedCopy = indexed.slice();\n var notIndexedCopy = notIndexed.slice();\n return inputs.reduce(function (acc, current) {\n var value;\n if (current.indexed)\n value = indexedCopy.splice(0, 1)[0];\n else\n value = notIndexedCopy.splice(0, 1)[0];\n\n acc[current.name] = value;\n return acc;\n }, {}); \n};\n \nvar outputParser = function (event) {\n \n return function (output) {\n var result = {\n event: utils.extractDisplayName(event.name),\n number: output.number,\n hash: output.hash,\n args: {}\n };\n\n output.topics = output.topic; // fallback for go-ethereum\n if (!output.topics) {\n return result;\n }\n \n var indexedOutputs = filterInputs(event.inputs, true);\n var indexedData = \"0x\" + output.topics.slice(1, output.topics.length).map(function (topics) { return topics.slice(2); }).join(\"\");\n var indexedRes = abi.formatOutput(indexedOutputs, indexedData);\n\n var notIndexedOutputs = filterInputs(event.inputs, false);\n var notIndexedRes = abi.formatOutput(notIndexedOutputs, output.data);\n\n result.args = getArgumentsObject(event.inputs, indexedRes, notIndexedRes);\n\n return result;\n };\n};\n\nvar getMatchingEvent = function (events, payload) {\n for (var i = 0; i < events.length; i++) {\n var sign = signature.eventSignatureFromAscii(events[i].name); \n if (sign === payload.topics[0]) {\n return events[i];\n }\n }\n return undefined;\n};\n\n\nmodule.exports = {\n inputParser: inputParser,\n outputParser: outputParser,\n getMatchingEvent: getMatchingEvent\n};\n\n",
- "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file filter.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Fabian Vogelsteller \n * Gav Wood \n * @date 2014\n */\n\nvar utils = require('../utils/utils');\n\n/// Should be called to check if filter implementation is valid\n/// @returns true if it is, otherwise false\nvar implementationIsValid = function (i) {\n return !!i && \n typeof i.newFilter === 'function' && \n typeof i.getLogs === 'function' && \n typeof i.uninstallFilter === 'function' &&\n typeof i.startPolling === 'function' &&\n typeof i.stopPolling === 'function';\n};\n\n/// This method should be called on options object, to verify deprecated properties && lazy load dynamic ones\n/// @param should be string or object\n/// @returns options string or object\nvar getOptions = function (options) {\n /*jshint maxcomplexity:9 */\n\n if (typeof options === 'string') {\n return options;\n } \n\n options = options || {};\n\n if (options.topic) {\n console.warn('\"topic\" is deprecated, is \"topics\" instead');\n options.topics = options.topic;\n }\n\n if (options.earliest) {\n console.warn('\"earliest\" is deprecated, is \"fromBlock\" instead');\n options.fromBlock = options.earliest;\n }\n\n if (options.latest) {\n console.warn('\"latest\" is deprecated, is \"toBlock\" instead');\n options.toBlock = options.latest;\n }\n\n if (options.skip) {\n console.warn('\"skip\" is deprecated, is \"offset\" instead');\n options.offset = options.skip;\n }\n\n if (options.max) {\n console.warn('\"max\" is deprecated, is \"limit\" instead');\n options.limit = options.max;\n }\n\n // make sure topics, get converted to hex\n if(options.topics instanceof Array) {\n options.topics = options.topics.map(function(topic){\n return utils.toHex(topic);\n });\n }\n\n\n // evaluate lazy properties\n return {\n fromBlock: utils.toHex(options.fromBlock),\n toBlock: utils.toHex(options.toBlock),\n limit: utils.toHex(options.limit),\n offset: utils.toHex(options.offset),\n to: options.to,\n address: options.address,\n topics: options.topics\n };\n};\n\n/// Should be used when we want to watch something\n/// it's using inner polling mechanism and is notified about changes\n/// @param options are filter options\n/// @param implementation, an abstract polling implementation\n/// @param formatter (optional), callback function which formats output before 'real' callback \nvar filter = function(options, implementation, formatter) {\n if (!implementationIsValid(implementation)) {\n console.error('filter implemenation is invalid');\n return;\n }\n\n options = getOptions(options);\n var callbacks = [];\n var filterId = implementation.newFilter(options);\n\n // call the callbacks\n var onMessages = function (messages) {\n messages.forEach(function (message) {\n message = formatter ? formatter(message) : message;\n callbacks.forEach(function (callback) {\n callback(message);\n });\n });\n };\n\n implementation.startPolling(filterId, onMessages, implementation.uninstallFilter);\n\n var watch = function(callback) {\n callbacks.push(callback);\n };\n\n var stopWatching = function() {\n implementation.stopPolling(filterId);\n implementation.uninstallFilter(filterId);\n callbacks = [];\n };\n\n var get = function () {\n var results = implementation.getLogs(filterId);\n\n return utils.isArray(results) ? results.map(function(message){\n return formatter ? formatter(message) : message;\n }) : results;\n };\n \n return {\n watch: watch,\n stopWatching: stopWatching,\n get: get,\n\n // DEPRECATED methods\n changed: function(){\n console.warn('watch().changed() is deprecated please use filter().watch() instead.');\n return watch.apply(this, arguments);\n },\n arrived: function(){\n console.warn('watch().arrived() is deprecated please use filter().watch() instead.');\n return watch.apply(this, arguments);\n },\n happened: function(){\n console.warn('watch().happened() is deprecated please use filter().watch() instead.');\n return watch.apply(this, arguments);\n },\n uninstall: function(){\n console.warn('watch().uninstall() is deprecated please use filter().stopWatching() instead.');\n return stopWatching.apply(this, arguments);\n },\n messages: function(){\n console.warn('watch().messages() is deprecated please use filter().get() instead.');\n return get.apply(this, arguments);\n },\n logs: function(){\n console.warn('watch().logs() is deprecated please use filter().get() instead.');\n return get.apply(this, arguments);\n }\n };\n};\n\nmodule.exports = filter;\n\n",
+ "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file filter.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Fabian Vogelsteller \n * Gav Wood \n * @date 2014\n */\n\nvar utils = require('../utils/utils');\n\n/// Should be called to check if filter implementation is valid\n/// @returns true if it is, otherwise false\nvar implementationIsValid = function (i) {\n return !!i && \n typeof i.newFilter === 'function' && \n typeof i.getLogs === 'function' && \n typeof i.uninstallFilter === 'function' &&\n typeof i.startPolling === 'function' &&\n typeof i.stopPolling === 'function';\n};\n\n/// This method should be called on options object, to verify deprecated properties && lazy load dynamic ones\n/// @param should be string or object\n/// @returns options string or object\nvar getOptions = function (options) {\n /*jshint maxcomplexity:9 */\n\n if (typeof options === 'string') {\n return options;\n } \n\n options = options || {};\n\n if (options.topic) {\n console.warn('\"topic\" is deprecated, is \"topics\" instead');\n options.topics = options.topic;\n }\n\n if (options.earliest) {\n console.warn('\"earliest\" is deprecated, is \"fromBlock\" instead');\n options.fromBlock = options.earliest;\n }\n\n if (options.latest) {\n console.warn('\"latest\" is deprecated, is \"toBlock\" instead');\n options.toBlock = options.latest;\n }\n\n // make sure topics, get converted to hex\n if(options.topics instanceof Array) {\n options.topics = options.topics.map(function(topic){\n return utils.toHex(topic);\n });\n }\n\n\tvar asBlockNumber = function(n) {\n\t\tif (n == null)\n\t\t\treturn null;\n\t\tif (n == 'latest' || n == 'pending')\n\t\t\treturn n;\n\t\treturn utils.toHex(n);\n\t};\n\n // evaluate lazy properties\n return {\n\t\tfromBlock: asBlockNumber(options.fromBlock),\n\t\ttoBlock: asBlockNumber(options.toBlock),\n to: options.to,\n address: options.address,\n topics: options.topics\n };\n};\n\n/// Should be used when we want to watch something\n/// it's using inner polling mechanism and is notified about changes\n/// @param options are filter options\n/// @param implementation, an abstract polling implementation\n/// @param formatter (optional), callback function which formats output before 'real' callback \nvar filter = function(options, implementation, formatter) {\n if (!implementationIsValid(implementation)) {\n console.error('filter implemenation is invalid');\n return;\n }\n\n options = getOptions(options);\n var callbacks = [];\n var filterId = implementation.newFilter(options);\n\n // call the callbacks\n var onMessages = function (messages) {\n messages.forEach(function (message) {\n\t\t\tmessage = formatter ? formatter(message) : message;\n callbacks.forEach(function (callback) {\n\t\t\t\tcallback(message);\n });\n });\n };\n\n implementation.startPolling(filterId, onMessages, implementation.uninstallFilter);\n\n var watch = function(callback) {\n callbacks.push(callback);\n };\n\n var stopWatching = function() {\n implementation.stopPolling(filterId);\n implementation.uninstallFilter(filterId);\n callbacks = [];\n };\n\n var get = function () {\n var results = implementation.getLogs(filterId);\n\n return utils.isArray(results) ? results.map(function(message){\n return formatter ? formatter(message) : message;\n }) : results;\n };\n \n return {\n watch: watch,\n stopWatching: stopWatching,\n get: get,\n\n // DEPRECATED methods\n changed: function(){\n console.warn('watch().changed() is deprecated please use filter().watch() instead.');\n return watch.apply(this, arguments);\n },\n arrived: function(){\n console.warn('watch().arrived() is deprecated please use filter().watch() instead.');\n return watch.apply(this, arguments);\n },\n happened: function(){\n console.warn('watch().happened() is deprecated please use filter().watch() instead.');\n return watch.apply(this, arguments);\n },\n uninstall: function(){\n console.warn('watch().uninstall() is deprecated please use filter().stopWatching() instead.');\n return stopWatching.apply(this, arguments);\n },\n messages: function(){\n console.warn('watch().messages() is deprecated please use filter().get() instead.');\n return get.apply(this, arguments);\n },\n logs: function(){\n console.warn('watch().logs() is deprecated please use filter().get() instead.');\n return get.apply(this, arguments);\n }\n };\n};\n\nmodule.exports = filter;\n\n",
"/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file formatters.js\n * @authors:\n * Marek Kotewicz \n * Fabian Vogelsteller \n * @date 2015\n */\n\nvar utils = require('../utils/utils');\n\n/**\n * Should the input to a big number\n *\n * @method convertToBigNumber\n * @param {String|Number|BigNumber}\n * @returns {BigNumber} object\n */\nvar convertToBigNumber = function (value) {\n return utils.toBigNumber(value);\n};\n\n/**\n * Formats the input of a transaction and converts all values to HEX\n *\n * @method inputTransactionFormatter\n * @param {Object} transaction options\n * @returns object\n*/\nvar inputTransactionFormatter = function (options){\n\n // make code -> data\n if (options.code) {\n options.data = options.code;\n delete options.code;\n }\n\n ['gasPrice', 'gas', 'value'].forEach(function(key){\n options[key] = utils.fromDecimal(options[key]);\n });\n\n return options;\n};\n\n/**\n * Formats the output of a transaction to its proper values\n * \n * @method outputTransactionFormatter\n * @param {Object} transaction\n * @returns {Object} transaction\n*/\nvar outputTransactionFormatter = function (tx){\n tx.gas = utils.toDecimal(tx.gas);\n tx.gasPrice = utils.toBigNumber(tx.gasPrice);\n tx.value = utils.toBigNumber(tx.value);\n return tx;\n};\n\n/**\n * Formats the input of a call and converts all values to HEX\n *\n * @method inputCallFormatter\n * @param {Object} transaction options\n * @returns object\n*/\nvar inputCallFormatter = function (options){\n\n // make code -> data\n if (options.code) {\n options.data = options.code;\n delete options.code;\n }\n\n return options;\n};\n\n\n/**\n * Formats the output of a block to its proper values\n *\n * @method outputBlockFormatter\n * @param {Object} block object \n * @returns {Object} block object\n*/\nvar outputBlockFormatter = function(block){\n\n // transform to number\n block.gasLimit = utils.toDecimal(block.gasLimit);\n block.gasUsed = utils.toDecimal(block.gasUsed);\n block.size = utils.toDecimal(block.size);\n block.timestamp = utils.toDecimal(block.timestamp);\n block.number = utils.toDecimal(block.number);\n\n block.minGasPrice = utils.toBigNumber(block.minGasPrice);\n block.difficulty = utils.toBigNumber(block.difficulty);\n block.totalDifficulty = utils.toBigNumber(block.totalDifficulty);\n\n if(block.transactions instanceof Array) {\n block.transactions.forEach(function(item){\n if(!utils.isString(item))\n return outputTransactionFormatter(item);\n });\n }\n\n return block;\n};\n\n/**\n * Formats the output of a log\n * \n * @method outputLogFormatter\n * @param {Object} log object\n * @returns {Object} log\n*/\nvar outputLogFormatter = function(log){\n log.blockNumber = utils.toDecimal(log.blockNumber);\n log.transactionIndex = utils.toDecimal(log.transactionIndex);\n log.logIndex = utils.toDecimal(log.logIndex);\n\n return log;\n};\n\n\n/**\n * Formats the input of a whisper post and converts all values to HEX\n *\n * @method inputPostFormatter\n * @param {Object} transaction object\n * @returns {Object}\n*/\nvar inputPostFormatter = function(post){\n\n post.payload = utils.toHex(post.payload);\n post.ttl = utils.fromDecimal(post.ttl);\n post.priority = utils.fromDecimal(post.priority);\n\n if(!(post.topics instanceof Array))\n post.topics = [post.topics];\n\n\n // format the following options\n post.topics = post.topics.map(function(topic){\n return utils.fromAscii(topic);\n });\n\n return post;\n};\n\n/**\n * Formats the output of a received post message\n *\n * @method outputPostFormatter\n * @param {Object}\n * @returns {Object}\n */\nvar outputPostFormatter = function(post){\n\n post.expiry = utils.toDecimal(post.expiry);\n post.sent = utils.toDecimal(post.sent);\n post.ttl = utils.toDecimal(post.ttl);\n post.workProved = utils.toDecimal(post.workProved);\n post.payloadRaw = post.payload;\n post.payload = utils.toAscii(post.payload);\n\n if(post.payload.indexOf('{') === 0 || post.payload.indexOf('[') === 0) {\n try {\n post.payload = JSON.parse(post.payload);\n } catch (e) { }\n }\n\n // format the following options\n post.topics = post.topics.map(function(topic){\n return utils.toAscii(topic);\n });\n\n return post;\n};\n\nmodule.exports = {\n convertToBigNumber: convertToBigNumber,\n inputTransactionFormatter: inputTransactionFormatter,\n outputTransactionFormatter: outputTransactionFormatter,\n inputCallFormatter: inputCallFormatter,\n outputBlockFormatter: outputBlockFormatter,\n outputLogFormatter: outputLogFormatter,\n inputPostFormatter: inputPostFormatter,\n outputPostFormatter: outputPostFormatter\n};\n\n",
"/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file httpprovider.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \n * Fabian Vogelsteller \n * @date 2014\n */\n\nif (\"build\" !== 'build') {/*\n var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line\n*/}\n\nvar HttpProvider = function (host) {\n this.name = 'HTTP';\n this.handlers = [];\n this.host = host || 'http://localhost:8080';\n};\n\nHttpProvider.prototype.send = function (payload, callback) {\n var request = new XMLHttpRequest();\n\n // ASYNC\n if(typeof callback === 'function') {\n request.onreadystatechange = function() {\n if(request.readyState === 4) {\n var result = '';\n try {\n result = JSON.parse(request.responseText);\n } catch(error) {\n result = error;\n }\n callback(result, request.status);\n }\n };\n\n request.open('POST', this.host, true);\n request.send(JSON.stringify(payload));\n\n // SYNC\n } else {\n request.open('POST', this.host, false);\n request.send(JSON.stringify(payload));\n\n // check request.status\n if(request.status !== 200)\n return;\n return JSON.parse(request.responseText);\n \n }\n};\n\nmodule.exports = HttpProvider;\n\n",
"/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file jsonrpc.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\nvar messageId = 1;\n\n/// Should be called to valid json create payload object\n/// @param method of jsonrpc call, required\n/// @param params, an array of method params, optional\n/// @returns valid jsonrpc payload object\nvar toPayload = function (method, params) {\n if (!method)\n console.error('jsonrpc method should be specified!');\n\n return {\n jsonrpc: '2.0',\n method: method,\n params: params || [],\n id: messageId++\n }; \n};\n\n/// Should be called to check if jsonrpc response is valid\n/// @returns true if response is valid, otherwise false \nvar isValidResponse = function (response) {\n return !!response &&\n !response.error &&\n response.jsonrpc === '2.0' &&\n typeof response.id === 'number' &&\n response.result !== undefined; // only undefined is not valid json object\n};\n\n/// Should be called to create batch payload object\n/// @param messages, an array of objects with method (required) and params (optional) fields\nvar toBatchPayload = function (messages) {\n return messages.map(function (message) {\n return toPayload(message.method, message.params);\n }); \n};\n\nmodule.exports = {\n toPayload: toPayload,\n isValidResponse: isValidResponse,\n toBatchPayload: toBatchPayload\n};\n\n\n",
diff --git a/libjsqrc/ethereumjs/dist/ethereum.min.js b/libjsqrc/ethereumjs/dist/ethereum.min.js
index e0cb5a491..4aab986d6 100644
--- a/libjsqrc/ethereumjs/dist/ethereum.min.js
+++ b/libjsqrc/ethereumjs/dist/ethereum.min.js
@@ -1 +1 @@
-require=function t(e,n,r){function o(a,u){if(!n[a]){if(!e[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;ay;y++)g.push(d(e.slice(0,s))),e=e.slice(s);n.push(g)}else o.prefixedType("bytes")(t[c].type)?(l=l.slice(s),n.push(d(e.slice(0,s))),e=e.slice(s)):(n.push(d(e.slice(0,s))),e=e.slice(s))}),n},d=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),i=function(){var e=Array.prototype.slice.call(arguments);return l(t.inputs,e)};void 0===e[r]&&(e[r]=i),e[r][o]=i}),e},h=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),i=function(e){return m(t.outputs,e)};void 0===e[r]&&(e[r]=i),e[r][o]=i}),e};e.exports={inputParser:d,outputParser:h,formatInput:l,formatOutput:m}},{"../utils/config":4,"../utils/utils":5,"./formatters":2,"./types":3}],2:[function(t,e){var n=t("../utils/utils"),r=t("../utils/config"),o=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},i=function(t){var e=2*r.ETH_PADDING;return BigNumber.config(r.ETH_BIGNUMBER_ROUNDING_MODE),o(n.toTwosComplement(t).round().toString(16),e)},a=function(t){return n.fromAscii(t,r.ETH_PADDING).substr(2)},u=function(t){return"000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0")},s=function(t){return i(new BigNumber(t).times(new BigNumber(2).pow(128)))},c=function(t){return"1"===new BigNumber(t.substr(0,1),16).toString(2).substr(0,1)},l=function(t){return t=t||"0",c(t)?new BigNumber(t,16).minus(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new BigNumber(t,16)},f=function(t){return t=t||"0",new BigNumber(t,16)},p=function(t){return l(t).dividedBy(new BigNumber(2).pow(128))},m=function(t){return f(t).dividedBy(new BigNumber(2).pow(128))},d=function(t){return"0x"+t},h=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t?!0:!1},g=function(t){return n.toAscii(t)},y=function(t){return"0x"+t.slice(t.length-40,t.length)};e.exports={formatInputInt:i,formatInputString:a,formatInputBool:u,formatInputReal:s,formatOutputInt:l,formatOutputUInt:f,formatOutputReal:p,formatOutputUReal:m,formatOutputHash:d,formatOutputBool:h,formatOutputString:g,formatOutputAddress:y}},{"../utils/config":4,"../utils/utils":5}],3:[function(t,e){var n=t("./formatters"),r=function(t){return function(e){return 0===e.indexOf(t)}},o=function(t){return function(e){return t===e}},i=function(){return[{type:r("uint"),format:n.formatInputInt},{type:r("int"),format:n.formatInputInt},{type:r("bytes"),format:n.formatInputString},{type:r("real"),format:n.formatInputReal},{type:r("ureal"),format:n.formatInputReal},{type:o("address"),format:n.formatInputInt},{type:o("bool"),format:n.formatInputBool}]},a=function(){return[{type:r("uint"),format:n.formatOutputUInt},{type:r("int"),format:n.formatOutputInt},{type:r("bytes"),format:n.formatOutputString},{type:r("real"),format:n.formatOutputReal},{type:r("ureal"),format:n.formatOutputUReal},{type:o("address"),format:n.formatOutputAddress},{type:o("bool"),format:n.formatOutputBool}]};e.exports={prefixedType:r,namedType:o,inputTypes:i,outputTypes:a}},{"./formatters":2}],4:[function(t,e){var n=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:n,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:BigNumber.ROUND_DOWN},ETH_POLLING_TIMEOUT:1e3,ETH_DEFAULTBLOCK:"latest"}},{}],5:[function(t,e){var n={wei:"1",kwei:"1000",ada:"1000",mwei:"1000000",babbage:"1000000",gwei:"1000000000",shannon:"1000000000",szabo:"1000000000000",finney:"1000000000000000",ether:"1000000000000000000",kether:"1000000000000000000000",grand:"1000000000000000000000",einstein:"1000000000000000000000",mether:"1000000000000000000000000",gether:"1000000000000000000000000000",tether:"1000000000000000000000000000000"},r=function(t,e){for(var n=!1,r=0;rn;n+=2){var o=parseInt(t.substr(n,2),16);if(0===o)break;e+=String.fromCharCode(o)}return e},i=function(t){for(var e="",n=0;n1?(t[n[0]]||(t[n[0]]={}),t[n[0]][n[1]]=r):t[n[0]]=r})},g=function(t,e){e.forEach(function(e){var n=e.name.split("."),r={};r.get=function(){return e.newProperty&&console.warn("This property is deprecated please use web3."+e.newProperty+" instead."),x.manager.send({method:e.getter,outputFormatter:e.outputFormatter})},e.setter&&(r.set=function(t){return e.newProperty&&console.warn("This property is deprecated please use web3."+e.newProperty+" instead."),x.manager.send({method:e.setter,params:[t],inputFormatter:e.inputFormatter})}),r.enumerable=!e.newProperty,n.length>1?(t[n[0]]||(t[n[0]]={}),Object.defineProperty(t[n[0]],n[1],r)):Object.defineProperty(t,e.name,r)})},y=function(t,e,n,r){x.manager.startPolling({method:t,params:[e]},e,n,r)},b=function(t){x.manager.stopPolling(t)},v={startPolling:y.bind(null,"eth_getFilterChanges"),stopPolling:b},w={startPolling:y.bind(null,"shh_getFilterChanges"),stopPolling:b},x={version:{api:n.version},manager:f(),providers:{},setProvider:function(t){x.manager.setProvider(t)},reset:function(){x.manager.reset()},toHex:c.toHex,toAscii:c.toAscii,fromAscii:c.fromAscii,toDecimal:c.toDecimal,fromDecimal:c.fromDecimal,toBigNumber:c.toBigNumber,toWei:c.toWei,fromWei:c.fromWei,isAddress:c.isAddress,net:{},eth:{contractFromAbi:function(t){return console.warn("Initiating a contract like this is deprecated please use var MyContract = eth.contract(abi); new MyContract(address); instead."),function(e){e=e||"0xc6d9d2cd449a754c494264e1809c50e34d64562b";var n=x.eth.contract(e,t);return n.address=e,n}},filter:function(t,e,n){return t._isEvent?t(e,n):s(t,v,l.outputLogFormatter)},watch:function(t,e,n){return console.warn("eth.watch() is deprecated please use eth.filter() instead."),this.filter(t,e,n)}},db:{},shh:{filter:function(t){return s(t,w,l.outputPostFormatter)},watch:function(t){return console.warn("shh.watch() is deprecated please use shh.filter() instead."),this.filter(t)}}};Object.defineProperty(x.eth,"defaultBlock",{get:function(){return p.ETH_DEFAULTBLOCK},set:function(t){return p.ETH_DEFAULTBLOCK=t,p.ETH_DEFAULTBLOCK}}),h(x,m),g(x,d),h(x.net,r.methods),g(x.net,r.properties),h(x.eth,o.methods),g(x.eth,o.properties),h(x.db,i.methods()),h(x.shh,a.methods()),h(v,u.eth()),h(w,u.shh()),e.exports=x},{"../version.json":21,"./solidity/formatters":2,"./utils/config":4,"./utils/utils":5,"./web3/db":8,"./web3/eth":9,"./web3/filter":11,"./web3/net":15,"./web3/requestmanager":17,"./web3/shh":18,"./web3/watches":20}],7:[function(t,e){function n(t,e){t.forEach(function(t){if(-1===t.name.indexOf("(")){var e=t.name,n=t.inputs.map(function(t){return t.type}).join();t.name=e+"("+n+")"}});var n={};return c(n),l(n,t,e),f(n,t,e),p(n,t,e),n}var r=t("../web3"),o=t("../solidity/abi"),i=t("../utils/utils"),a=t("./event"),u=t("./signature"),s=function(t){r._currentContractAbi=t.abi,r._currentContractAddress=t.address,r._currentContractMethodName=t.method,r._currentContractMethodParams=t.params},c=function(t){t.call=function(e){return t._isTransaction=!1,t._options=e,t},t.sendTransaction=function(e){return t._isTransaction=!0,t._options=e,t},t.transact=function(e){return console.warn("myContract.transact() is deprecated please use myContract.sendTransaction() instead."),t.sendTransaction(e)},t._options={},["gas","gasPrice","value","from"].forEach(function(e){t[e]=function(n){return t._options[e]=n,t}})},l=function(t,e,n){var a=o.inputParser(e),c=o.outputParser(e);i.filterFunctions(e).forEach(function(o){var l=i.extractDisplayName(o.name),f=i.extractTypeName(o.name),p=function(){var i=Array.prototype.slice.call(arguments),p=u.functionSignatureFromAscii(o.name),m=a[l][f].apply(null,i),d=t._options||{};d.to=n,d.data=p+m;var h=t._isTransaction===!0||t._isTransaction!==!1&&!o.constant,g=d.collapse!==!1;if(t._options={},t._isTransaction=null,h)return s({abi:e,address:n,method:o.name,params:i}),void r.eth.sendTransaction(d);var y=r.eth.call(d),b=c[l][f](y);return g&&(1===b.length?b=b[0]:0===b.length&&(b=null)),b};void 0===t[l]&&(t[l]=p),t[l][f]=p})},f=function(t,e,n){t.address=n,t._onWatchEventResult=function(t){var n=event.getMatchingEvent(i.filterEvents(e)),r=a.outputParser(n);return r(t)},Object.defineProperty(t,"topics",{get:function(){return i.filterEvents(e).map(function(t){return u.eventSignatureFromAscii(t.name)})}})},p=function(t,e,n){i.filterEvents(e).forEach(function(e){var o=function(){var t=Array.prototype.slice.call(arguments),o=u.eventSignatureFromAscii(e.name),i=a.inputParser(n,o,e),s=i.apply(null,t),c=function(t){var n=a.outputParser(e);return n(t)};return r.eth.filter(s,void 0,void 0,c)};o._isEvent=!0;var s=i.extractDisplayName(e.name),c=i.extractTypeName(e.name);void 0===t[s]&&(t[s]=o),t[s][c]=o})},m=function(t){return t instanceof Array&&1===arguments.length?n.bind(null,t):(console.warn("Initiating a contract like this is deprecated please use var MyContract = eth.contract(abi); new MyContract(address); instead."),new n(arguments[1],arguments[0]))};e.exports=m},{"../solidity/abi":1,"../utils/utils":5,"../web3":6,"./event":10,"./signature":19}],8:[function(t,e){var n=function(){return[{name:"putString",call:"db_putString"},{name:"getString",call:"db_getString"},{name:"putHex",call:"db_putHex"},{name:"getHex",call:"db_getHex"}]};e.exports={methods:n}},{}],9:[function(t,e){var n=t("./formatters"),r=t("../utils/utils"),o=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getBlockByHash":"eth_getBlockByNumber"},i=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getTransactionByBlockHashAndIndex":"eth_getTransactionByBlockNumberAndIndex"},a=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getUncleByBlockHashAndIndex":"eth_getUncleByBlockNumberAndIndex"},u=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getBlockTransactionCountByHash":"eth_getBlockTransactionCountByNumber"},s=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getUncleCountByBlockHash":"eth_getUncleCountByBlockNumber"},c=[{name:"getBalance",call:"eth_getBalance",addDefaultblock:2,outputFormatter:n.convertToBigNumber},{name:"getStorage",call:"eth_getStorage",addDefaultblock:2},{name:"getStorageAt",call:"eth_getStorageAt",addDefaultblock:3,inputFormatter:r.toHex},{name:"getData",call:"eth_getData",addDefaultblock:2},{name:"getBlock",call:o,outputFormatter:n.outputBlockFormatter,inputFormatter:[r.toHex,function(t){return t?!0:!1}]},{name:"getUncle",call:a,outputFormatter:n.outputBlockFormatter,inputFormatter:[r.toHex,r.toHex,function(t){return t?!0:!1}]},{name:"getCompilers",call:"eth_getCompilers"},{name:"getBlockTransactionCount",call:u,outputFormatter:r.toDecimal,inputFormatter:r.toHex},{name:"getBlockUncleCount",call:s,outputFormatter:r.toDecimal,inputFormatter:r.toHex},{name:"getTransaction",call:"eth_getTransactionByHash",outputFormatter:n.outputTransactionFormatter},{name:"getTransactionFromBlock",call:i,outputFormatter:n.outputTransactionFormatter,inputFormatter:r.toHex},{name:"getTransactionCount",call:"eth_getTransactionCount",addDefaultblock:2,outputFormatter:r.toDecimal},{name:"sendTransaction",call:"eth_sendTransaction",inputFormatter:n.inputTransactionFormatter},{name:"call",call:"eth_call",addDefaultblock:2,inputFormatter:n.inputCallFormatter},{name:"compile.solidity",call:"eth_compileSolidity"},{name:"compile.lll",call:"eth_compileLLL",inputFormatter:r.toHex},{name:"compile.serpent",call:"eth_compileSerpent",inputFormatter:r.toHex},{name:"flush",call:"eth_flush"},{name:"balanceAt",call:"eth_balanceAt",newMethod:"eth.getBalance"},{name:"stateAt",call:"eth_stateAt",newMethod:"eth.getStorageAt"},{name:"storageAt",call:"eth_storageAt",newMethod:"eth.getStorage"},{name:"countAt",call:"eth_countAt",newMethod:"eth.getTransactionCount"},{name:"codeAt",call:"eth_codeAt",newMethod:"eth.getData"},{name:"transact",call:"eth_transact",newMethod:"eth.sendTransaction"},{name:"block",call:o,newMethod:"eth.getBlock"},{name:"transaction",call:i,newMethod:"eth.getTransaction"},{name:"uncle",call:a,newMethod:"eth.getUncle"},{name:"compilers",call:"eth_compilers",newMethod:"eth.getCompilers"},{name:"solidity",call:"eth_solidity",newMethod:"eth.compile.solidity"},{name:"lll",call:"eth_lll",newMethod:"eth.compile.lll"},{name:"serpent",call:"eth_serpent",newMethod:"eth.compile.serpent"},{name:"transactionCount",call:u,newMethod:"eth.getBlockTransactionCount"},{name:"uncleCount",call:s,newMethod:"eth.getBlockUncleCount"},{name:"logs",call:"eth_logs"}],l=[{name:"coinbase",getter:"eth_coinbase"},{name:"mining",getter:"eth_mining"},{name:"gasPrice",getter:"eth_gasPrice",outputFormatter:n.convertToBigNumber},{name:"accounts",getter:"eth_accounts"},{name:"blockNumber",getter:"eth_blockNumber",outputFormatter:r.toDecimal},{name:"listening",getter:"net_listening",setter:"eth_setListening",newProperty:"net.listening"},{name:"peerCount",getter:"net_peerCount",newProperty:"net.peerCount"},{name:"number",getter:"eth_number",newProperty:"eth.blockNumber"}];e.exports={methods:c,properties:l}},{"../utils/utils":5,"./formatters":12}],10:[function(t,e){var n=t("../solidity/abi"),r=t("../utils/utils"),o=t("./signature"),i=function(t,e){return t.filter(function(t){return t.indexed===e})},a=function(t,e){var n=r.findIndex(t,function(t){return t.name===e});return-1===n?void console.error("indexed param with name "+e+" not found"):t[n]},u=function(t,e){return Object.keys(e).map(function(r){var o=[a(i(t.inputs,!0),r)],u=e[r];return u instanceof Array?u.map(function(t){return n.formatInput(o,[t])}):n.formatInput(o,[u])})},s=function(t,e,n){return function(r,o){var i=o||{};return i.address=t,i.topics=[],i.topics.push(e),r&&(i.topics=i.topics.concat(u(n,r))),i}},c=function(t,e,n){var r=e.slice(),o=n.slice();return t.reduce(function(t,e){var n;return n=e.indexed?r.splice(0,1)[0]:o.splice(0,1)[0],t[e.name]=n,t},{})},l=function(t){return function(e){var o={event:r.extractDisplayName(t.name),number:e.number,hash:e.hash,args:{}};if(e.topics=e.topic,!e.topics)return o;var a=i(t.inputs,!0),u="0x"+e.topics.slice(1,e.topics.length).map(function(t){return t.slice(2)}).join(""),s=n.formatOutput(a,u),l=i(t.inputs,!1),f=n.formatOutput(l,e.data);return o.args=c(t.inputs,s,f),o}},f=function(t,e){for(var n=0;ny;y++)g.push(d(e.slice(0,s))),e=e.slice(s);n.push(g)}else o.prefixedType("bytes")(t[c].type)?(l=l.slice(s),n.push(d(e.slice(0,s))),e=e.slice(s)):(n.push(d(e.slice(0,s))),e=e.slice(s))}),n},d=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),i=function(){var e=Array.prototype.slice.call(arguments);return l(t.inputs,e)};void 0===e[r]&&(e[r]=i),e[r][o]=i}),e},h=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),i=function(e){return m(t.outputs,e)};void 0===e[r]&&(e[r]=i),e[r][o]=i}),e};e.exports={inputParser:d,outputParser:h,formatInput:l,formatOutput:m}},{"../utils/config":4,"../utils/utils":5,"./formatters":2,"./types":3}],2:[function(t,e){var n=t("../utils/utils"),r=t("../utils/config"),o=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},i=function(t){var e=2*r.ETH_PADDING;return BigNumber.config(r.ETH_BIGNUMBER_ROUNDING_MODE),o(n.toTwosComplement(t).round().toString(16),e)},a=function(t){return n.fromAscii(t,r.ETH_PADDING).substr(2)},u=function(t){return"000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0")},s=function(t){return i(new BigNumber(t).times(new BigNumber(2).pow(128)))},c=function(t){return"1"===new BigNumber(t.substr(0,1),16).toString(2).substr(0,1)},l=function(t){return t=t||"0",c(t)?new BigNumber(t,16).minus(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new BigNumber(t,16)},f=function(t){return t=t||"0",new BigNumber(t,16)},p=function(t){return l(t).dividedBy(new BigNumber(2).pow(128))},m=function(t){return f(t).dividedBy(new BigNumber(2).pow(128))},d=function(t){return"0x"+t},h=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t?!0:!1},g=function(t){return n.toAscii(t)},y=function(t){return"0x"+t.slice(t.length-40,t.length)};e.exports={formatInputInt:i,formatInputString:a,formatInputBool:u,formatInputReal:s,formatOutputInt:l,formatOutputUInt:f,formatOutputReal:p,formatOutputUReal:m,formatOutputHash:d,formatOutputBool:h,formatOutputString:g,formatOutputAddress:y}},{"../utils/config":4,"../utils/utils":5}],3:[function(t,e){var n=t("./formatters"),r=function(t){return function(e){return 0===e.indexOf(t)}},o=function(t){return function(e){return t===e}},i=function(){return[{type:r("uint"),format:n.formatInputInt},{type:r("int"),format:n.formatInputInt},{type:r("bytes"),format:n.formatInputString},{type:r("real"),format:n.formatInputReal},{type:r("ureal"),format:n.formatInputReal},{type:o("address"),format:n.formatInputInt},{type:o("bool"),format:n.formatInputBool}]},a=function(){return[{type:r("uint"),format:n.formatOutputUInt},{type:r("int"),format:n.formatOutputInt},{type:r("bytes"),format:n.formatOutputString},{type:r("real"),format:n.formatOutputReal},{type:r("ureal"),format:n.formatOutputUReal},{type:o("address"),format:n.formatOutputAddress},{type:o("bool"),format:n.formatOutputBool}]};e.exports={prefixedType:r,namedType:o,inputTypes:i,outputTypes:a}},{"./formatters":2}],4:[function(t,e){var n=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:n,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:BigNumber.ROUND_DOWN},ETH_POLLING_TIMEOUT:1e3,ETH_DEFAULTBLOCK:"latest"}},{}],5:[function(t,e){var n={wei:"1",kwei:"1000",ada:"1000",mwei:"1000000",babbage:"1000000",gwei:"1000000000",shannon:"1000000000",szabo:"1000000000000",finney:"1000000000000000",ether:"1000000000000000000",kether:"1000000000000000000000",grand:"1000000000000000000000",einstein:"1000000000000000000000",mether:"1000000000000000000000000",gether:"1000000000000000000000000000",tether:"1000000000000000000000000000000"},r=function(t,e){for(var n=!1,r=0;rn;n+=2){var o=parseInt(t.substr(n,2),16);if(0===o)break;e+=String.fromCharCode(o)}return e},i=function(t){for(var e="",n=0;n1?(t[n[0]]||(t[n[0]]={}),t[n[0]][n[1]]=r):t[n[0]]=r})},g=function(t,e){e.forEach(function(e){var n=e.name.split("."),r={};r.get=function(){return e.newProperty&&console.warn("This property is deprecated please use web3."+e.newProperty+" instead."),_.manager.send({method:e.getter,outputFormatter:e.outputFormatter})},e.setter&&(r.set=function(t){return e.newProperty&&console.warn("This property is deprecated please use web3."+e.newProperty+" instead."),_.manager.send({method:e.setter,params:[t],inputFormatter:e.inputFormatter})}),r.enumerable=!e.newProperty,n.length>1?(t[n[0]]||(t[n[0]]={}),Object.defineProperty(t[n[0]],n[1],r)):Object.defineProperty(t,e.name,r)})},y=function(t,e,n,r){_.manager.startPolling({method:t,params:[e]},e,n,r)},b=function(t){_.manager.stopPolling(t)},v={startPolling:y.bind(null,"eth_getFilterChanges"),stopPolling:b},w={startPolling:y.bind(null,"shh_getFilterChanges"),stopPolling:b},_={version:{api:n.version},manager:f(),providers:{},setProvider:function(t){_.manager.setProvider(t)},reset:function(){_.manager.reset()},toHex:c.toHex,toAscii:c.toAscii,fromAscii:c.fromAscii,toDecimal:c.toDecimal,fromDecimal:c.fromDecimal,toBigNumber:c.toBigNumber,toWei:c.toWei,fromWei:c.fromWei,isAddress:c.isAddress,net:{},eth:{contractFromAbi:function(t){return console.warn("Initiating a contract like this is deprecated please use var MyContract = eth.contract(abi); new MyContract(address); instead."),function(e){e=e||"0xc6d9d2cd449a754c494264e1809c50e34d64562b";var n=_.eth.contract(e,t);return n.address=e,n}},filter:function(t,e,n){return t._isEvent?t(e,n):s(t,v,l.outputLogFormatter)},watch:function(t,e,n){return console.warn("eth.watch() is deprecated please use eth.filter() instead."),this.filter(t,e,n)}},db:{},shh:{filter:function(t){return s(t,w,l.outputPostFormatter)},watch:function(t){return console.warn("shh.watch() is deprecated please use shh.filter() instead."),this.filter(t)}}};Object.defineProperty(_.eth,"defaultBlock",{get:function(){return p.ETH_DEFAULTBLOCK},set:function(t){return p.ETH_DEFAULTBLOCK=t,p.ETH_DEFAULTBLOCK}}),h(_,m),g(_,d),h(_.net,r.methods),g(_.net,r.properties),h(_.eth,o.methods),g(_.eth,o.properties),h(_.db,i.methods()),h(_.shh,a.methods()),h(v,u.eth()),h(w,u.shh()),e.exports=_},{"../version.json":21,"./solidity/formatters":2,"./utils/config":4,"./utils/utils":5,"./web3/db":8,"./web3/eth":9,"./web3/filter":11,"./web3/net":15,"./web3/requestmanager":17,"./web3/shh":18,"./web3/watches":20}],7:[function(t,e){function n(t,e){t.forEach(function(t){if(-1===t.name.indexOf("(")){var e=t.name,n=t.inputs.map(function(t){return t.type}).join();t.name=e+"("+n+")"}});var n={};return c(n),l(n,t,e),f(n,t,e),p(n,t,e),n}var r=t("../web3"),o=t("../solidity/abi"),i=t("../utils/utils"),a=t("./event"),u=t("./signature"),s=function(t){r._currentContractAbi=t.abi,r._currentContractAddress=t.address,r._currentContractMethodName=t.method,r._currentContractMethodParams=t.params},c=function(t){t.call=function(e){return t._isTransaction=!1,t._options=e,t},t.sendTransaction=function(e){return t._isTransaction=!0,t._options=e,t},t.transact=function(e){return console.warn("myContract.transact() is deprecated please use myContract.sendTransaction() instead."),t.sendTransaction(e)},t._options={},["gas","gasPrice","value","from"].forEach(function(e){t[e]=function(n){return t._options[e]=n,t}})},l=function(t,e,n){var a=o.inputParser(e),c=o.outputParser(e);i.filterFunctions(e).forEach(function(o){var l=i.extractDisplayName(o.name),f=i.extractTypeName(o.name),p=function(){var i=Array.prototype.slice.call(arguments),p=u.functionSignatureFromAscii(o.name),m=a[l][f].apply(null,i),d=t._options||{};d.to=n,d.data=p+m;var h=t._isTransaction===!0||t._isTransaction!==!1&&!o.constant,g=d.collapse!==!1;if(t._options={},t._isTransaction=null,h)return s({abi:e,address:n,method:o.name,params:i}),void r.eth.sendTransaction(d);var y=r.eth.call(d),b=c[l][f](y);return g&&(1===b.length?b=b[0]:0===b.length&&(b=null)),b};void 0===t[l]&&(t[l]=p),t[l][f]=p})},f=function(t,e,n){t.address=n,t._onWatchEventResult=function(t){var n=event.getMatchingEvent(i.filterEvents(e)),r=a.outputParser(n);return r(t)},Object.defineProperty(t,"topics",{get:function(){return i.filterEvents(e).map(function(t){return u.eventSignatureFromAscii(t.name)})}})},p=function(t,e,n){i.filterEvents(e).forEach(function(e){var o=function(){var t=Array.prototype.slice.call(arguments),o=u.eventSignatureFromAscii(e.name),i=a.inputParser(n,o,e),s=i.apply(null,t),c=function(t){var n=a.outputParser(e);return n(t)};return r.eth.filter(s,void 0,void 0,c)};o._isEvent=!0;var s=i.extractDisplayName(e.name),c=i.extractTypeName(e.name);void 0===t[s]&&(t[s]=o),t[s][c]=o})},m=function(t){return t instanceof Array&&1===arguments.length?n.bind(null,t):(console.warn("Initiating a contract like this is deprecated please use var MyContract = eth.contract(abi); new MyContract(address); instead."),new n(arguments[1],arguments[0]))};e.exports=m},{"../solidity/abi":1,"../utils/utils":5,"../web3":6,"./event":10,"./signature":19}],8:[function(t,e){var n=function(){return[{name:"putString",call:"db_putString"},{name:"getString",call:"db_getString"},{name:"putHex",call:"db_putHex"},{name:"getHex",call:"db_getHex"}]};e.exports={methods:n}},{}],9:[function(t,e){var n=t("./formatters"),r=t("../utils/utils"),o=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getBlockByHash":"eth_getBlockByNumber"},i=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getTransactionByBlockHashAndIndex":"eth_getTransactionByBlockNumberAndIndex"},a=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getUncleByBlockHashAndIndex":"eth_getUncleByBlockNumberAndIndex"},u=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getBlockTransactionCountByHash":"eth_getBlockTransactionCountByNumber"},s=function(t){return r.isString(t[0])&&0===t[0].indexOf("0x")?"eth_getUncleCountByBlockHash":"eth_getUncleCountByBlockNumber"},c=[{name:"getBalance",call:"eth_getBalance",addDefaultblock:2,outputFormatter:n.convertToBigNumber},{name:"getStorageAt",call:"eth_getStorageAt",addDefaultblock:3,inputFormatter:r.toHex},{name:"getCode",call:"eth_getCode",addDefaultblock:2},{name:"getBlock",call:o,outputFormatter:n.outputBlockFormatter,inputFormatter:[r.toHex,function(t){return t?!0:!1}]},{name:"getUncle",call:a,outputFormatter:n.outputBlockFormatter,inputFormatter:[r.toHex,r.toHex,function(t){return t?!0:!1}]},{name:"getCompilers",call:"eth_getCompilers"},{name:"getBlockTransactionCount",call:u,outputFormatter:r.toDecimal,inputFormatter:r.toHex},{name:"getBlockUncleCount",call:s,outputFormatter:r.toDecimal,inputFormatter:r.toHex},{name:"getTransaction",call:"eth_getTransactionByHash",outputFormatter:n.outputTransactionFormatter},{name:"getTransactionFromBlock",call:i,outputFormatter:n.outputTransactionFormatter,inputFormatter:r.toHex},{name:"getTransactionCount",call:"eth_getTransactionCount",addDefaultblock:2,outputFormatter:r.toDecimal},{name:"sendTransaction",call:"eth_sendTransaction",inputFormatter:n.inputTransactionFormatter},{name:"call",call:"eth_call",addDefaultblock:2,inputFormatter:n.inputCallFormatter},{name:"compile.solidity",call:"eth_compileSolidity"},{name:"compile.lll",call:"eth_compileLLL",inputFormatter:r.toHex},{name:"compile.serpent",call:"eth_compileSerpent",inputFormatter:r.toHex},{name:"flush",call:"eth_flush"},{name:"balanceAt",call:"eth_balanceAt",newMethod:"eth.getBalance"},{name:"stateAt",call:"eth_stateAt",newMethod:"eth.getStorageAt"},{name:"storageAt",call:"eth_storageAt",newMethod:"eth.getStorage"},{name:"countAt",call:"eth_countAt",newMethod:"eth.getTransactionCount"},{name:"codeAt",call:"eth_codeAt",newMethod:"eth.getCode"},{name:"transact",call:"eth_transact",newMethod:"eth.sendTransaction"},{name:"block",call:o,newMethod:"eth.getBlock"},{name:"transaction",call:i,newMethod:"eth.getTransaction"},{name:"uncle",call:a,newMethod:"eth.getUncle"},{name:"compilers",call:"eth_compilers",newMethod:"eth.getCompilers"},{name:"solidity",call:"eth_solidity",newMethod:"eth.compile.solidity"},{name:"lll",call:"eth_lll",newMethod:"eth.compile.lll"},{name:"serpent",call:"eth_serpent",newMethod:"eth.compile.serpent"},{name:"transactionCount",call:u,newMethod:"eth.getBlockTransactionCount"},{name:"uncleCount",call:s,newMethod:"eth.getBlockUncleCount"},{name:"logs",call:"eth_logs"}],l=[{name:"coinbase",getter:"eth_coinbase"},{name:"mining",getter:"eth_mining"},{name:"gasPrice",getter:"eth_gasPrice",outputFormatter:n.convertToBigNumber},{name:"accounts",getter:"eth_accounts"},{name:"blockNumber",getter:"eth_blockNumber",outputFormatter:r.toDecimal},{name:"listening",getter:"net_listening",setter:"eth_setListening",newProperty:"net.listening"},{name:"peerCount",getter:"net_peerCount",newProperty:"net.peerCount"},{name:"number",getter:"eth_number",newProperty:"eth.blockNumber"}];e.exports={methods:c,properties:l}},{"../utils/utils":5,"./formatters":12}],10:[function(t,e){var n=t("../solidity/abi"),r=t("../utils/utils"),o=t("./signature"),i=function(t,e){return t.filter(function(t){return t.indexed===e})},a=function(t,e){var n=r.findIndex(t,function(t){return t.name===e});return-1===n?void console.error("indexed param with name "+e+" not found"):t[n]},u=function(t,e){return Object.keys(e).map(function(r){var o=[a(i(t.inputs,!0),r)],u=e[r];return u instanceof Array?u.map(function(t){return n.formatInput(o,[t])}):n.formatInput(o,[u])})},s=function(t,e,n){return function(r,o){var i=o||{};return i.address=t,i.topics=[],i.topics.push(e),r&&(i.topics=i.topics.concat(u(n,r))),i}},c=function(t,e,n){var r=e.slice(),o=n.slice();return t.reduce(function(t,e){var n;return n=e.indexed?r.splice(0,1)[0]:o.splice(0,1)[0],t[e.name]=n,t},{})},l=function(t){return function(e){var o={event:r.extractDisplayName(t.name),number:e.number,hash:e.hash,args:{}};if(e.topics=e.topic,!e.topics)return o;var a=i(t.inputs,!0),u="0x"+e.topics.slice(1,e.topics.length).map(function(t){return t.slice(2)}).join(""),s=n.formatOutput(a,u),l=i(t.inputs,!1),f=n.formatOutput(l,e.data);return o.args=c(t.inputs,s,f),o}},f=function(t,e){for(var n=0;n31].*", Class C "192.168.*"
diff --git a/libp2p/Common.h b/libp2p/Common.h
index ddf5f78b8..66b3f08e8 100644
--- a/libp2p/Common.h
+++ b/libp2p/Common.h
@@ -48,6 +48,9 @@ class RLPStream;
namespace p2p
{
+/// Peer network protocol version.
+extern const unsigned c_protocolVersion;
+
using NodeId = h512;
bool isPrivateAddress(bi::address const& _addressToCheck);
diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp
index 78a8232fd..13ea87ba6 100644
--- a/libp2p/Host.cpp
+++ b/libp2p/Host.cpp
@@ -42,6 +42,12 @@ using namespace std;
using namespace dev;
using namespace dev::p2p;
+/// Interval at which Host::run will call keepAlivePeers to ping peers.
+std::chrono::seconds const c_keepAliveInterval = std::chrono::seconds(30);
+
+/// Disconnect timeout after failure to respond to keepAlivePeers ping.
+std::chrono::milliseconds const c_keepAliveTimeOut = std::chrono::milliseconds(1000);
+
HostNodeTableHandler::HostNodeTableHandler(Host& _host): m_host(_host) {}
void HostNodeTableHandler::processEvent(NodeId const& _n, NodeTableEventType const& _e)
@@ -170,11 +176,6 @@ void Host::doneWorking()
m_sessions.clear();
}
-unsigned Host::protocolVersion() const
-{
- return 3;
-}
-
void Host::startPeerSession(Public const& _id, RLP const& _rlp, RLPXFrameIO* _io, bi::tcp::endpoint _endpoint)
{
shared_ptr p;
@@ -205,7 +206,7 @@ void Host::startPeerSession(Public const& _id, RLP const& _rlp, RLPXFrameIO* _io
// create session so disconnects are managed
auto ps = make_shared(this, _io, p, PeerSessionInfo({_id, clientVersion, _endpoint.address().to_string(), listenPort, chrono::steady_clock::duration(), _rlp[2].toSet(), 0, map()}));
- if (protocolVersion != this->protocolVersion())
+ if (protocolVersion != dev::p2p::c_protocolVersion)
{
ps->disconnect(IncompatibleProtocol);
return;
@@ -260,7 +261,7 @@ void Host::onNodeTableEvent(NodeId const& _n, NodeTableEventType const& _e)
p->required = n.required;
m_peers[_n] = p;
- clog(NetNote) << "p2p.host.peers.events.peersAdded " << _n << p->endpoint.tcp.address() << p->endpoint.udp.address();
+ clog(NetNote) << "p2p.host.peers.events.peersAdded " << _n << "udp:" << p->endpoint.udp.address() << "tcp:" << p->endpoint.tcp.address();
}
p->endpoint.tcp = n.endpoint.tcp;
}
@@ -474,6 +475,7 @@ void Host::connect(std::shared_ptr const& _p)
clog(NetConnect) << "Connection refused to node" << _p->id.abridged() << "@" << _p->peerEndpoint() << "(" << ec.message() << ")";
_p->m_lastDisconnect = TCPError;
_p->m_lastAttempted = std::chrono::system_clock::now();
+ _p->m_failedAttempts++;
}
else
{
@@ -609,8 +611,7 @@ void Host::startedWorking()
else
clog(NetNote) << "p2p.start.notice id:" << id().abridged() << "Listen port is invalid or unavailable. Node Table using default port (30303).";
- // TODO: add m_tcpPublic endpoint; sort out endpoint stuff for nodetable
- m_nodeTable.reset(new NodeTable(m_ioService, m_alias, m_listenPort > 0 ? m_listenPort : 30303));
+ m_nodeTable.reset(new NodeTable(m_ioService, m_alias, bi::address::from_string(listenAddress()), listenPort() > 0 ? listenPort() : 30303));
m_nodeTable->setEventHandler(new HostNodeTableHandler(*this));
restoreNetwork(&m_restoreNetwork);
@@ -674,7 +675,7 @@ bytes Host::saveNetwork() const
// TODO: alpha: Figure out why it ever shares these ports.//p.address.port() >= 30300 && p.address.port() <= 30305 &&
// TODO: alpha: if/how to save private addresses
// Only save peers which have connected within 2 days, with properly-advertised port and public IP address
- if (chrono::system_clock::now() - p.m_lastConnected < chrono::seconds(3600 * 48) && p.peerEndpoint().port() > 0 && p.peerEndpoint().port() < /*49152*/32768 && p.id != id() && !isPrivateAddress(p.peerEndpoint().address()))
+ if (chrono::system_clock::now() - p.m_lastConnected < chrono::seconds(3600 * 48) && p.peerEndpoint().port() > 0 && p.peerEndpoint().port() < /*49152*/32768 && p.id != id() && !isPrivateAddress(p.endpoint.udp.address()) && !isPrivateAddress(p.endpoint.tcp.address()))
{
network.appendList(10);
if (p.peerEndpoint().address().is_v4())
@@ -708,7 +709,7 @@ bytes Host::saveNetwork() const
}
RLPStream ret(3);
- ret << 1 << m_alias.secret();
+ ret << dev::p2p::c_protocolVersion << m_alias.secret();
ret.appendList(count).appendRaw(network.out(), count);
return ret.out();
}
@@ -721,7 +722,7 @@ void Host::restoreNetwork(bytesConstRef _b)
RecursiveGuard l(x_sessions);
RLP r(_b);
- if (r.itemCount() > 0 && r[0].isInt() && r[0].toInt() == 1)
+ if (r.itemCount() > 0 && r[0].isInt() && r[0].toInt() == dev::p2p::c_protocolVersion)
{
// r[0] = version
// r[1] = key
@@ -741,6 +742,13 @@ void Host::restoreNetwork(bytesConstRef _b)
tcp = bi::tcp::endpoint(bi::address_v6(i[0].toArray()), i[1].toInt());
udp = bi::udp::endpoint(bi::address_v6(i[0].toArray()), i[1].toInt());
}
+
+ // skip private addresses
+ // todo: to support private addresseses entries must be stored
+ // and managed externally by host rather than nodetable.
+ if (isPrivateAddress(tcp.address()) || isPrivateAddress(udp.address()))
+ continue;
+
auto id = (NodeId)i[2];
if (i.itemCount() == 3)
m_nodeTable->addNode(id, udp, tcp);
diff --git a/libp2p/Host.h b/libp2p/Host.h
index ff27807a7..0feda364f 100644
--- a/libp2p/Host.h
+++ b/libp2p/Host.h
@@ -94,18 +94,9 @@ public:
/// Will block on network process events.
virtual ~Host();
- /// Interval at which Host::run will call keepAlivePeers to ping peers.
- std::chrono::seconds const c_keepAliveInterval = std::chrono::seconds(30);
-
- /// Disconnect timeout after failure to respond to keepAlivePeers ping.
- std::chrono::milliseconds const c_keepAliveTimeOut = std::chrono::milliseconds(1000);
-
/// Default host for current version of client.
static std::string pocHost();
- /// Basic peer network protocol version.
- unsigned protocolVersion() const;
-
/// Register a peer-capability; all new peer connections will have this capability.
template std::shared_ptr registerCapability(T* _t) { _t->m_host = this; auto ret = std::shared_ptr(_t); m_capabilities[std::make_pair(T::staticName(), T::staticVersion())] = ret; return ret; }
diff --git a/libp2p/NodeTable.cpp b/libp2p/NodeTable.cpp
index ccfbeaba4..0d6dda214 100644
--- a/libp2p/NodeTable.cpp
+++ b/libp2p/NodeTable.cpp
@@ -27,11 +27,11 @@ using namespace dev::p2p;
NodeEntry::NodeEntry(Node _src, Public _pubk, NodeIPEndpoint _gw): Node(_pubk, _gw), distance(NodeTable::distance(_src.id,_pubk)) {}
NodeEntry::NodeEntry(Node _src, Public _pubk, bi::udp::endpoint _udp): Node(_pubk, NodeIPEndpoint(_udp)), distance(NodeTable::distance(_src.id,_pubk)) {}
-NodeTable::NodeTable(ba::io_service& _io, KeyPair _alias, uint16_t _udp):
- m_node(Node(_alias.pub(), bi::udp::endpoint())),
+NodeTable::NodeTable(ba::io_service& _io, KeyPair _alias, bi::address const& _udpAddress, uint16_t _udp):
+ m_node(Node(_alias.pub(), bi::udp::endpoint(_udpAddress, _udp))),
m_secret(_alias.sec()),
m_io(_io),
- m_socket(new NodeSocket(m_io, *this, _udp)),
+ m_socket(new NodeSocket(m_io, *this, m_node.endpoint.udp)),
m_socketPointer(m_socket.get()),
m_bucketRefreshTimer(m_io),
m_evictionCheckTimer(m_io)
@@ -70,6 +70,20 @@ shared_ptr NodeTable::addNode(Public const& _pubk, bi::udp::endpoint
shared_ptr NodeTable::addNode(Node const& _node)
{
+ if (_node.endpoint.udp.address().to_string() == "0.0.0.0" || _node.endpoint.tcp.address().to_string() == "0.0.0.0")
+ {
+ string ptype;
+ if (_node.endpoint.udp.address().to_string() != "0.0.0.0")
+ ptype = "TCP";
+ else if (_node.endpoint.tcp.address().to_string() != "0.0.0.0")
+ ptype = "UDP";
+ else
+ ptype = "TCP,UDP";
+
+ clog(NodeTableWarn) << "addNode Failed. Invalid" << ptype << "address 0.0.0.0 for" << _node.id.abridged();
+ return move(shared_ptr());
+ }
+
// ping address if nodeid is empty
if (!_node.id)
{
@@ -326,7 +340,7 @@ void NodeTable::noteActiveNode(Public const& _pubk, bi::udp::endpoint const& _en
s.nodes.push_back(node);
s.touch();
- if (!removed)
+ if (!removed && m_nodeEventHandler)
m_nodeEventHandler->appendEvent(node->id, NodeEntryAdded);
}
}
@@ -335,7 +349,7 @@ void NodeTable::noteActiveNode(Public const& _pubk, bi::udp::endpoint const& _en
s.nodes.push_back(node);
s.touch();
- if (!removed)
+ if (!removed && m_nodeEventHandler)
m_nodeEventHandler->appendEvent(node->id, NodeEntryAdded);
}
}
@@ -463,6 +477,13 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes
case PingNode::type:
{
PingNode in = PingNode::fromBytesConstRef(_from, rlpBytes);
+ if (in.version != dev::p2p::c_protocolVersion)
+ {
+ if (auto n = nodeEntry(nodeid))
+ dropNode(n);
+ return;
+ }
+
addNode(nodeid, _from, bi::tcp::endpoint(bi::address::from_string(in.ipAddress), in.port));
Pong p(_from);
diff --git a/libp2p/NodeTable.h b/libp2p/NodeTable.h
index a97326501..58fa722c1 100644
--- a/libp2p/NodeTable.h
+++ b/libp2p/NodeTable.h
@@ -135,7 +135,8 @@ class NodeTable: UDPSocketEvents, public std::enable_shared_from_this
using EvictionTimeout = std::pair, NodeId>; ///< First NodeId may be evicted and replaced with second NodeId.
public:
- NodeTable(ba::io_service& _io, KeyPair _alias, uint16_t _udpPort = 30303);
+ /// Constructor requiring host for I/O, credentials, and IP Address and port to listen on.
+ NodeTable(ba::io_service& _io, KeyPair _alias, bi::address const& _udpAddress, uint16_t _udpPort = 30303);
~NodeTable();
/// Returns distance based on xor metric two node ids. Used by NodeEntry and NodeTable.
@@ -315,7 +316,7 @@ struct PingNode: RLPXDatagram
static const uint8_t type = 1;
- unsigned version = 1;
+ unsigned version = dev::p2p::c_protocolVersion;
std::string ipAddress;
unsigned port;
unsigned expiration;
diff --git a/libp2p/RLPxHandshake.cpp b/libp2p/RLPxHandshake.cpp
index b6df5f8e0..1e42995ee 100644
--- a/libp2p/RLPxHandshake.cpp
+++ b/libp2p/RLPxHandshake.cpp
@@ -139,7 +139,7 @@ void RLPXHandshake::error()
void RLPXHandshake::transition(boost::system::error_code _ech)
{
- if (_ech || m_nextState == Error)
+ if (_ech || m_nextState == Error || m_cancel)
return error();
auto self(shared_from_this());
@@ -172,7 +172,7 @@ void RLPXHandshake::transition(boost::system::error_code _ech)
// 5 arguments, HelloPacket
RLPStream s;
s.append((unsigned)0).appendList(5)
- << m_host->protocolVersion()
+ << dev::p2p::c_protocolVersion
<< m_host->m_clientVersion
<< m_host->caps()
<< m_host->listenPort()
@@ -259,4 +259,14 @@ void RLPXHandshake::transition(boost::system::error_code _ech)
}
});
}
+
+ m_idleTimer.expires_from_now(c_timeout);
+ m_idleTimer.async_wait([this, self](boost::system::error_code const& _ec)
+ {
+ if (!_ec)
+ {
+ clog(NetWarn) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Timeout)";
+ cancel();
+ }
+ });
}
diff --git a/libp2p/RLPxHandshake.h b/libp2p/RLPxHandshake.h
index aac8f4b5a..5e51aa4f8 100644
--- a/libp2p/RLPxHandshake.h
+++ b/libp2p/RLPxHandshake.h
@@ -62,17 +62,18 @@ class RLPXHandshake: public std::enable_shared_from_this
public:
/// Setup incoming connection.
- RLPXHandshake(Host* _host, std::shared_ptr const& _socket): m_host(_host), m_originated(false), m_socket(_socket) { crypto::Nonce::get().ref().copyTo(m_nonce.ref()); }
+ RLPXHandshake(Host* _host, std::shared_ptr const& _socket): m_host(_host), m_originated(false), m_socket(_socket), m_idleTimer(m_socket->ref().get_io_service()) { crypto::Nonce::get().ref().copyTo(m_nonce.ref()); }
/// Setup outbound connection.
- RLPXHandshake(Host* _host, std::shared_ptr const& _socket, NodeId _remote): m_host(_host), m_remote(_remote), m_originated(true), m_socket(_socket) { crypto::Nonce::get().ref().copyTo(m_nonce.ref()); }
+ RLPXHandshake(Host* _host, std::shared_ptr const& _socket, NodeId _remote): m_host(_host), m_remote(_remote), m_originated(true), m_socket(_socket), m_idleTimer(m_socket->ref().get_io_service()) { crypto::Nonce::get().ref().copyTo(m_nonce.ref()); }
~RLPXHandshake() {}
/// Start handshake.
void start() { transition(); }
- void cancel() { m_nextState = Error; }
+ /// Cancels handshake preventing
+ void cancel() { m_cancel = true; }
protected:
/// Write Auth message to socket and transitions to AckAuth.
@@ -93,7 +94,11 @@ protected:
/// Performs transition for m_nextState.
void transition(boost::system::error_code _ech = boost::system::error_code());
+ /// Timeout for remote to respond to transition events. Enforced by m_idleTimer and refreshed by transition().
+ boost::posix_time::milliseconds const c_timeout = boost::posix_time::milliseconds(1000);
+
State m_nextState = New; ///< Current or expected state of transition.
+ bool m_cancel = false; ///< Will be set to true if connection was canceled.
Host* m_host; ///< Host which provides m_alias, protocolVersion(), m_clientVersion, caps(), and TCP listenPort().
@@ -119,7 +124,8 @@ protected:
/// Passed onto Host which will take ownership.
RLPXFrameIO* m_io = nullptr;
- std::shared_ptr m_socket; ///< Socket.
+ std::shared_ptr m_socket; ///< Socket.
+ boost::asio::deadline_timer m_idleTimer; ///< Timer which enforces c_timeout.
};
}
diff --git a/libp2p/Session.cpp b/libp2p/Session.cpp
index 2c6530a2d..d7bfca34e 100644
--- a/libp2p/Session.cpp
+++ b/libp2p/Session.cpp
@@ -51,6 +51,7 @@ Session::Session(Host* _s, RLPXFrameIO* _io, std::shared_ptr const& _n, Pe
Session::~Session()
{
+ clogS(NetMessageSummary) << "Closing Peer Session :-(";
m_peer->m_lastConnected = m_peer->m_lastAttempted - chrono::seconds(1);
// Read-chain finished for one reason or another.
diff --git a/libp2p/UDP.h b/libp2p/UDP.h
index 3c3399acb..091f3cc2a 100644
--- a/libp2p/UDP.h
+++ b/libp2p/UDP.h
@@ -113,6 +113,10 @@ public:
enum { maxDatagramSize = MaxDatagramSize };
static_assert(maxDatagramSize < 65507, "UDP datagrams cannot be larger than 65507 bytes");
+ /// Create socket for specific endpoint.
+ UDPSocket(ba::io_service& _io, UDPSocketEvents& _host, bi::udp::endpoint _endpoint): m_host(_host), m_endpoint(_endpoint), m_socket(_io) { m_started.store(false); m_closed.store(true); };
+
+ /// Create socket which listens to all ports.
UDPSocket(ba::io_service& _io, UDPSocketEvents& _host, unsigned _port): m_host(_host), m_endpoint(bi::udp::v4(), _port), m_socket(_io) { m_started.store(false); m_closed.store(true); };
virtual ~UDPSocket() { disconnect(); }
diff --git a/libsolidity/ArrayUtils.cpp b/libsolidity/ArrayUtils.cpp
index 2596e4afa..bbf7f985a 100644
--- a/libsolidity/ArrayUtils.cpp
+++ b/libsolidity/ArrayUtils.cpp
@@ -52,15 +52,21 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
// TODO unroll loop for small sizes
bool sourceIsStorage = _sourceType.getLocation() == ArrayType::Location::Storage;
+ bool directCopy = sourceIsStorage && sourceBaseType->isValueType() && *sourceBaseType == *targetBaseType;
+ bool haveByteOffsetSource = !directCopy && sourceIsStorage && sourceBaseType->getStorageBytes() <= 16;
+ bool haveByteOffsetTarget = !directCopy && targetBaseType->getStorageBytes() <= 16;
+ unsigned byteOffsetSize = (haveByteOffsetSource ? 1 : 0) + (haveByteOffsetTarget ? 1 : 0);
// stack: source_ref [source_byte_off] [source_length] target_ref target_byte_off
// store target_ref
- m_context << eth::Instruction::POP; //@todo
+ // arrays always start at zero byte offset, pop offset
+ m_context << eth::Instruction::POP;
for (unsigned i = _sourceType.getSizeOnStack(); i > 0; --i)
m_context << eth::swapInstruction(i);
// stack: target_ref source_ref [source_byte_off] [source_length]
if (sourceIsStorage)
- m_context << eth::Instruction::POP; //@todo
+ // arrays always start at zero byte offset, pop offset
+ m_context << eth::Instruction::POP;
// stack: target_ref source_ref [source_length]
// retrieve source length
if (_sourceType.getLocation() != ArrayType::Location::CallData || !_sourceType.isDynamicallySized())
@@ -81,7 +87,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
m_context
<< eth::Instruction::POP << eth::Instruction::POP
<< eth::Instruction::POP << eth::Instruction::POP;
- m_context << u256(0); //@todo
+ m_context << u256(0);
return;
}
// compute hashes (data positions)
@@ -97,8 +103,8 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
// stack: target_ref target_data_end source_length target_data_pos source_ref
// skip copying if source length is zero
m_context << eth::Instruction::DUP3 << eth::Instruction::ISZERO;
- eth::AssemblyItem copyLoopEnd = m_context.newTag();
- m_context.appendConditionalJumpTo(copyLoopEnd);
+ eth::AssemblyItem copyLoopEndWithoutByteOffset = m_context.newTag();
+ m_context.appendConditionalJumpTo(copyLoopEndWithoutByteOffset);
if (_sourceType.getLocation() == ArrayType::Location::Storage && _sourceType.isDynamicallySized())
CompilerUtils(m_context).computeHashStatic();
@@ -107,18 +113,24 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
convertLengthToSize(_sourceType);
m_context << eth::Instruction::DUP3 << eth::Instruction::ADD;
// stack: target_ref target_data_end source_data_pos target_data_pos source_data_end
+ if (haveByteOffsetTarget)
+ m_context << u256(0);
+ if (haveByteOffsetSource)
+ m_context << u256(0);
+ // stack: target_ref target_data_end source_data_pos target_data_pos source_data_end [target_byte_offset] [source_byte_offset]
eth::AssemblyItem copyLoopStart = m_context.newTag();
m_context << copyLoopStart;
// check for loop condition
m_context
- << eth::Instruction::DUP3 << eth::Instruction::DUP2
+ << eth::dupInstruction(3 + byteOffsetSize) << eth::dupInstruction(2 + byteOffsetSize)
<< eth::Instruction::GT << eth::Instruction::ISZERO;
+ eth::AssemblyItem copyLoopEnd = m_context.newTag();
m_context.appendConditionalJumpTo(copyLoopEnd);
- // stack: target_ref target_data_end source_data_pos target_data_pos source_data_end
+ // stack: target_ref target_data_end source_data_pos target_data_pos source_data_end [target_byte_offset] [source_byte_offset]
// copy
if (sourceBaseType->getCategory() == Type::Category::Array)
{
- //@todo
+ solAssert(byteOffsetSize == 0, "Byte offset for array as base type.");
m_context << eth::Instruction::DUP3;
if (sourceIsStorage)
m_context << u256(0);
@@ -129,36 +141,80 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
);
m_context << eth::Instruction::POP << eth::Instruction::POP;
}
+ else if (directCopy)
+ {
+ solAssert(byteOffsetSize == 0, "Byte offset for direct copy.");
+ m_context
+ << eth::Instruction::DUP3 << eth::Instruction::SLOAD
+ << eth::Instruction::DUP3 << eth::Instruction::SSTORE;
+ }
else
{
- m_context << eth::Instruction::DUP3;
+ // Note that we have to copy each element on its own in case conversion is involved.
+ // We might copy too much if there is padding at the last element, but this way end
+ // checking is easier.
+ // stack: target_ref target_data_end source_data_pos target_data_pos source_data_end [target_byte_offset] [source_byte_offset]
+ m_context << eth::dupInstruction(3 + byteOffsetSize);
if (_sourceType.getLocation() == ArrayType::Location::Storage)
{
- m_context << u256(0);
+ if (haveByteOffsetSource)
+ m_context << eth::Instruction::DUP2;
+ else
+ m_context << u256(0);
StorageItem(m_context, *sourceBaseType).retrieveValue(SourceLocation(), true);
}
else if (sourceBaseType->isValueType())
CompilerUtils(m_context).loadFromMemoryDynamic(*sourceBaseType, true, true, false);
else
solAssert(false, "Copying of unknown type requested: " + sourceBaseType->toString());
- solAssert(2 + sourceBaseType->getSizeOnStack() <= 16, "Stack too deep.");
- m_context << eth::dupInstruction(2 + sourceBaseType->getSizeOnStack()) << u256(0);
+ // stack: target_ref target_data_end source_data_pos target_data_pos source_data_end [target_byte_offset] [source_byte_offset] ...
+ solAssert(2 + byteOffsetSize + sourceBaseType->getSizeOnStack() <= 16, "Stack too deep.");
+ // fetch target storage reference
+ m_context << eth::dupInstruction(2 + byteOffsetSize + sourceBaseType->getSizeOnStack());
+ if (haveByteOffsetTarget)
+ m_context << eth::dupInstruction(1 + byteOffsetSize + sourceBaseType->getSizeOnStack());
+ else
+ m_context << u256(0);
StorageItem(m_context, *targetBaseType).storeValue(*sourceBaseType, SourceLocation(), true);
}
+ // stack: target_ref target_data_end source_data_pos target_data_pos source_data_end [target_byte_offset] [source_byte_offset]
// increment source
- m_context
- << eth::Instruction::SWAP2
- << (sourceIsStorage ? sourceBaseType->getStorageSize() : sourceBaseType->getCalldataEncodedSize())
- << eth::Instruction::ADD
- << eth::Instruction::SWAP2;
+ if (haveByteOffsetSource)
+ incrementByteOffset(sourceBaseType->getStorageBytes(), 1, haveByteOffsetTarget ? 5 : 4);
+ else
+ m_context
+ << eth::swapInstruction(2 + byteOffsetSize)
+ << (sourceIsStorage ? sourceBaseType->getStorageSize() : sourceBaseType->getCalldataEncodedSize())
+ << eth::Instruction::ADD
+ << eth::swapInstruction(2 + byteOffsetSize);
// increment target
- m_context
- << eth::Instruction::SWAP1
- << targetBaseType->getStorageSize()
- << eth::Instruction::ADD
- << eth::Instruction::SWAP1;
+ if (haveByteOffsetTarget)
+ incrementByteOffset(targetBaseType->getStorageBytes(), byteOffsetSize, byteOffsetSize + 2);
+ else
+ m_context
+ << eth::swapInstruction(1 + byteOffsetSize)
+ << targetBaseType->getStorageSize()
+ << eth::Instruction::ADD
+ << eth::swapInstruction(1 + byteOffsetSize);
m_context.appendJumpTo(copyLoopStart);
m_context << copyLoopEnd;
+ if (haveByteOffsetTarget)
+ {
+ // clear elements that might be left over in the current slot in target
+ // stack: target_ref target_data_end source_data_pos target_data_pos source_data_end target_byte_offset [source_byte_offset]
+ m_context << eth::dupInstruction(byteOffsetSize) << eth::Instruction::ISZERO;
+ eth::AssemblyItem copyCleanupLoopEnd = m_context.appendConditionalJump();
+ m_context << eth::dupInstruction(2 + byteOffsetSize) << eth::dupInstruction(1 + byteOffsetSize);
+ StorageItem(m_context, *targetBaseType).setToZero(SourceLocation(), true);
+ incrementByteOffset(targetBaseType->getStorageBytes(), byteOffsetSize, byteOffsetSize + 2);
+ m_context.appendJumpTo(copyLoopEnd);
+
+ m_context << copyCleanupLoopEnd;
+ m_context << eth::Instruction::POP; // might pop the source, but then target is popped next
+ }
+ if (haveByteOffsetSource)
+ m_context << eth::Instruction::POP;
+ m_context << copyLoopEndWithoutByteOffset;
// zero-out leftovers in target
// stack: target_ref target_data_end source_data_pos target_data_pos_updated source_data_end
@@ -166,41 +222,61 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
// stack: target_ref target_data_end target_data_pos_updated
clearStorageLoop(*targetBaseType);
m_context << eth::Instruction::POP;
- m_context << u256(0); //@todo
+ m_context << u256(0);
}
void ArrayUtils::clearArray(ArrayType const& _type) const
{
unsigned stackHeightStart = m_context.getStackHeight();
solAssert(_type.getLocation() == ArrayType::Location::Storage, "");
- if (_type.isDynamicallySized())
+ if (_type.getBaseType()->getStorageBytes() < 32)
{
- m_context << eth::Instruction::POP; // remove byte offset
- clearDynamicArray(_type);
+ solAssert(_type.getBaseType()->isValueType(), "Invalid storage size for non-value type.");
+ solAssert(_type.getBaseType()->getStorageSize() <= 1, "Invalid storage size for type.");
}
+ if (_type.getBaseType()->isValueType())
+ solAssert(_type.getBaseType()->getStorageSize() <= 1, "Invalid size for value type.");
+
+ m_context << eth::Instruction::POP; // remove byte offset
+ if (_type.isDynamicallySized())
+ clearDynamicArray(_type);
else if (_type.getLength() == 0 || _type.getBaseType()->getCategory() == Type::Category::Mapping)
- m_context << eth::Instruction::POP << eth::Instruction::POP;
- else if (_type.getLength() < 5) // unroll loop for small arrays @todo choose a good value
+ m_context << eth::Instruction::POP;
+ else if (_type.getBaseType()->isValueType() && _type.getStorageSize() <= 5)
+ {
+ // unroll loop for small arrays @todo choose a good value
+ // Note that we loop over storage slots here, not elements.
+ for (unsigned i = 1; i < _type.getStorageSize(); ++i)
+ m_context
+ << u256(0) << eth::Instruction::DUP2 << eth::Instruction::SSTORE
+ << u256(1) << eth::Instruction::ADD;
+ m_context << u256(0) << eth::Instruction::SWAP1 << eth::Instruction::SSTORE;
+ }
+ else if (!_type.getBaseType()->isValueType() && _type.getLength() <= 4)
{
- solAssert(!_type.isByteArray(), "");
+ // unroll loop for small arrays @todo choose a good value
+ solAssert(_type.getBaseType()->getStorageBytes() >= 32, "Invalid storage size.");
for (unsigned i = 1; i < _type.getLength(); ++i)
{
+ m_context << u256(0);
StorageItem(m_context, *_type.getBaseType()).setToZero(SourceLocation(), false);
- m_context << eth::Instruction::SWAP1;
- m_context << u256(_type.getBaseType()->getStorageSize()) << eth::Instruction::ADD;
- m_context << eth::Instruction::SWAP1;
+ m_context
+ << eth::Instruction::POP
+ << u256(_type.getBaseType()->getStorageSize()) << eth::Instruction::ADD;
}
+ m_context << u256(0);
StorageItem(m_context, *_type.getBaseType()).setToZero(SourceLocation(), true);
}
else
{
- solAssert(!_type.isByteArray(), "");
- m_context << eth::Instruction::SWAP1;
m_context << eth::Instruction::DUP1 << _type.getLength();
convertLengthToSize(_type);
m_context << eth::Instruction::ADD << eth::Instruction::SWAP1;
- clearStorageLoop(*_type.getBaseType());
- m_context << eth::Instruction::POP << eth::Instruction::POP;
+ if (_type.getBaseType()->getStorageBytes() < 32)
+ clearStorageLoop(IntegerType(256));
+ else
+ clearStorageLoop(*_type.getBaseType());
+ m_context << eth::Instruction::POP;
}
solAssert(m_context.getStackHeight() == stackHeightStart - 2, "");
}
@@ -224,7 +300,7 @@ void ArrayUtils::clearDynamicArray(ArrayType const& _type) const
m_context << eth::Instruction::SWAP1 << eth::Instruction::DUP2 << eth::Instruction::ADD
<< eth::Instruction::SWAP1;
// stack: data_pos_end data_pos
- if (_type.isByteArray())
+ if (_type.isByteArray() || _type.getBaseType()->getStorageBytes() < 32)
clearStorageLoop(IntegerType(256));
else
clearStorageLoop(*_type.getBaseType());
@@ -237,6 +313,8 @@ void ArrayUtils::resizeDynamicArray(const ArrayType& _type) const
{
solAssert(_type.getLocation() == ArrayType::Location::Storage, "");
solAssert(_type.isDynamicallySized(), "");
+ if (!_type.isByteArray() && _type.getBaseType()->getStorageBytes() < 32)
+ solAssert(_type.getBaseType()->isValueType(), "Invalid storage size for non-value type.");
unsigned stackHeightStart = m_context.getStackHeight();
eth::AssemblyItem resizeEnd = m_context.newTag();
@@ -266,7 +344,7 @@ void ArrayUtils::resizeDynamicArray(const ArrayType& _type) const
// stack: ref new_length data_pos new_size delete_end
m_context << eth::Instruction::SWAP2 << eth::Instruction::ADD;
// stack: ref new_length delete_end delete_start
- if (_type.isByteArray())
+ if (_type.isByteArray() || _type.getBaseType()->getStorageBytes() < 32)
clearStorageLoop(IntegerType(256));
else
clearStorageLoop(*_type.getBaseType());
@@ -294,7 +372,7 @@ void ArrayUtils::clearStorageLoop(Type const& _type) const
eth::AssemblyItem zeroLoopEnd = m_context.newTag();
m_context.appendConditionalJumpTo(zeroLoopEnd);
// delete
- m_context << u256(0); //@todo
+ m_context << u256(0);
StorageItem(m_context, _type).setToZero(SourceLocation(), false);
m_context << eth::Instruction::POP;
// increment
@@ -313,7 +391,20 @@ void ArrayUtils::convertLengthToSize(ArrayType const& _arrayType, bool _pad) con
if (_arrayType.isByteArray())
m_context << u256(31) << eth::Instruction::ADD
<< u256(32) << eth::Instruction::SWAP1 << eth::Instruction::DIV;
- else if (_arrayType.getBaseType()->getStorageSize() > 1)
+ else if (_arrayType.getBaseType()->getStorageSize() <= 1)
+ {
+ unsigned baseBytes = _arrayType.getBaseType()->getStorageBytes();
+ if (baseBytes == 0)
+ m_context << eth::Instruction::POP << u256(1);
+ else if (baseBytes <= 16)
+ {
+ unsigned itemsPerSlot = 32 / baseBytes;
+ m_context
+ << u256(itemsPerSlot - 1) << eth::Instruction::ADD
+ << u256(itemsPerSlot) << eth::Instruction::SWAP1 << eth::Instruction::DIV;
+ }
+ }
+ else
m_context << _arrayType.getBaseType()->getStorageSize() << eth::Instruction::MUL;
}
else
@@ -349,3 +440,39 @@ void ArrayUtils::retrieveLength(ArrayType const& _arrayType) const
}
}
+void ArrayUtils::incrementByteOffset(unsigned _byteSize, unsigned _byteOffsetPosition, unsigned _storageOffsetPosition) const
+{
+ solAssert(_byteSize < 32, "");
+ solAssert(_byteSize != 0, "");
+ // We do the following, but avoiding jumps:
+ // byteOffset += byteSize
+ // if (byteOffset + byteSize > 32)
+ // {
+ // storageOffset++;
+ // byteOffset = 0;
+ // }
+ if (_byteOffsetPosition > 1)
+ m_context << eth::swapInstruction(_byteOffsetPosition - 1);
+ m_context << u256(_byteSize) << eth::Instruction::ADD;
+ if (_byteOffsetPosition > 1)
+ m_context << eth::swapInstruction(_byteOffsetPosition - 1);
+ // compute, X := (byteOffset + byteSize - 1) / 32, should be 1 iff byteOffset + bytesize > 32
+ m_context
+ << u256(32) << eth::dupInstruction(1 + _byteOffsetPosition) << u256(_byteSize - 1)
+ << eth::Instruction::ADD << eth::Instruction::DIV;
+ // increment storage offset if X == 1 (just add X to it)
+ // stack: X
+ m_context
+ << eth::swapInstruction(_storageOffsetPosition) << eth::dupInstruction(_storageOffsetPosition + 1)
+ << eth::Instruction::ADD << eth::swapInstruction(_storageOffsetPosition);
+ // stack: X
+ // set source_byte_offset to zero if X == 1 (using source_byte_offset *= 1 - X)
+ m_context << u256(1) << eth::Instruction::SUB;
+ // stack: 1 - X
+ if (_byteOffsetPosition == 1)
+ m_context << eth::Instruction::MUL;
+ else
+ m_context
+ << eth::dupInstruction(_byteOffsetPosition + 1) << eth::Instruction::MUL
+ << eth::swapInstruction(_byteOffsetPosition) << eth::Instruction::POP;
+}
diff --git a/libsolidity/ArrayUtils.h b/libsolidity/ArrayUtils.h
index c7b05b6d3..22c0646a5 100644
--- a/libsolidity/ArrayUtils.h
+++ b/libsolidity/ArrayUtils.h
@@ -72,6 +72,12 @@ public:
void retrieveLength(ArrayType const& _arrayType) const;
private:
+ /// Adds the given number of bytes to a storage byte offset counter and also increments
+ /// the storage offset if adding this number again would increase the counter over 32.
+ /// @param byteOffsetPosition the stack offset of the storage byte offset
+ /// @param storageOffsetPosition the stack offset of the storage slot offset
+ void incrementByteOffset(unsigned _byteSize, unsigned _byteOffsetPosition, unsigned _storageOffsetPosition) const;
+
CompilerContext& m_context;
};
diff --git a/libsolidity/Compiler.cpp b/libsolidity/Compiler.cpp
index db61cc4a1..8e2634499 100644
--- a/libsolidity/Compiler.cpp
+++ b/libsolidity/Compiler.cpp
@@ -20,12 +20,12 @@
* Solidity compiler.
*/
+#include
#include
#include
#include
#include
#include
-#include
#include
#include
@@ -274,19 +274,8 @@ void Compiler::appendReturnValuePacker(TypePointers const& _typeParameters)
void Compiler::registerStateVariables(ContractDefinition const& _contract)
{
- vector variables;
- for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.getLinearizedBaseContracts()))
- for (ASTPointer const& variable: contract->getStateVariables())
- if (!variable->isConstant())
- variables.push_back(variable.get());
- TypePointers types;
- for (auto variable: variables)
- types.push_back(variable->getType());
- StorageOffsets offsets;
- offsets.computeOffsets(types);
- for (size_t index = 0; index < variables.size(); ++index)
- if (auto const* offset = offsets.getOffset(index))
- m_context.addStateVariable(*variables[index], offset->first, offset->second);
+ for (auto const& var: ContractType(_contract).getStateVariables())
+ m_context.addStateVariable(*get<0>(var), get<1>(var), get<2>(var));
}
void Compiler::initializeStateVariables(ContractDefinition const& _contract)
diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp
index 61b17f663..da762147a 100644
--- a/libsolidity/ExpressionCompiler.cpp
+++ b/libsolidity/ExpressionCompiler.cpp
@@ -753,7 +753,6 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
}
else if (baseType.getCategory() == Type::Category::Array)
{
- // stack layout: [storage_byte_offset] []
ArrayType const& arrayType = dynamic_cast(baseType);
solAssert(_indexAccess.getIndexExpression(), "Index expression expected.");
ArrayType::Location location = arrayType.getLocation();
@@ -762,6 +761,11 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
location == ArrayType::Location::Memory ? eth::Instruction::MLOAD :
eth::Instruction::CALLDATALOAD;
+ // remove storage byte offset
+ if (location == ArrayType::Location::Storage)
+ m_context << eth::Instruction::POP;
+
+ // stack layout: []
_indexAccess.getIndexExpression()->accept(*this);
// retrieve length
if (!arrayType.isDynamicallySized())
@@ -769,11 +773,9 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
else if (location == ArrayType::Location::CallData)
// length is stored on the stack
m_context << eth::Instruction::SWAP1;
- else if (location == ArrayType::Location::Storage)
- m_context << eth::Instruction::DUP3 << load;
else
m_context << eth::Instruction::DUP2 << load;
- // stack: [storage_byte_offset]
+ // stack:
// check out-of-bounds access
m_context << eth::Instruction::DUP2 << eth::Instruction::LT;
eth::AssemblyItem legalAccess = m_context.appendConditionalJump();
@@ -781,23 +783,22 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
m_context << eth::Instruction::STOP;
m_context << legalAccess;
- // stack: [storage_byte_offset]
+ // stack:
if (arrayType.isByteArray())
- // byte array is packed differently, especially in storage
switch (location)
{
case ArrayType::Location::Storage:
// byte array index storage lvalue on stack (goal):
// [ =
- m_context << u256(32) << eth::Instruction::SWAP3;
+ m_context << u256(32) << eth::Instruction::SWAP2;
CompilerUtils(m_context).computeHashStatic();
- // stack: 32 storage_byte_offset index data_ref
+ // stack: 32 index data_ref
m_context
- << eth::Instruction::DUP4 << eth::Instruction::DUP3
+ << eth::Instruction::DUP3 << eth::Instruction::DUP3
<< eth::Instruction::DIV << eth::Instruction::ADD
- // stack: 32 storage_byte_offset index (data_ref + index / 32)
- << eth::Instruction::SWAP3 << eth::Instruction::SWAP2
- << eth::Instruction::POP << eth::Instruction::MOD;
+ // stack: 32 index (data_ref + index / 32)
+ << eth::Instruction::SWAP2 << eth::Instruction::SWAP1
+ << eth::Instruction::MOD;
setLValue(_indexAccess);
break;
case ArrayType::Location::CallData:
@@ -811,36 +812,51 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
}
else
{
- // stack: [storage_byte_offset]
- if (location == ArrayType::Location::Storage)
- //@todo use byte offset, remove it for now
- m_context << eth::Instruction::SWAP1 << eth::Instruction::POP;
- u256 elementSize =
- location == ArrayType::Location::Storage ?
- arrayType.getBaseType()->getStorageSize() :
- arrayType.getBaseType()->getCalldataEncodedSize();
- solAssert(elementSize != 0, "Invalid element size.");
- if (elementSize > 1)
- m_context << elementSize << eth::Instruction::MUL;
+ // stack:
+ m_context << eth::Instruction::SWAP1;
if (arrayType.isDynamicallySized())
{
if (location == ArrayType::Location::Storage)
- {
- m_context << eth::Instruction::SWAP1;
CompilerUtils(m_context).computeHashStatic();
- }
else if (location == ArrayType::Location::Memory)
m_context << u256(32) << eth::Instruction::ADD;
}
- m_context << eth::Instruction::ADD;
+ // stack:
switch (location)
{
case ArrayType::Location::CallData:
+ m_context
+ << eth::Instruction::SWAP1 << arrayType.getBaseType()->getCalldataEncodedSize()
+ << eth::Instruction::MUL << eth::Instruction::ADD;
if (arrayType.getBaseType()->isValueType())
CompilerUtils(m_context).loadFromMemoryDynamic(*arrayType.getBaseType(), true, true, false);
break;
case ArrayType::Location::Storage:
- m_context << u256(0); // @todo
+ m_context << eth::Instruction::SWAP1;
+ if (arrayType.getBaseType()->getStorageBytes() <= 16)
+ {
+ // stack:
+ // goal:
+ // ][ = <(index % itemsPerSlot) * byteSize>
+ unsigned byteSize = arrayType.getBaseType()->getStorageBytes();
+ solAssert(byteSize != 0, "");
+ unsigned itemsPerSlot = 32 / byteSize;
+ m_context << u256(itemsPerSlot) << eth::Instruction::SWAP2;
+ // stack: itemsPerSlot index data_ref
+ m_context
+ << eth::Instruction::DUP3 << eth::Instruction::DUP3
+ << eth::Instruction::DIV << eth::Instruction::ADD
+ // stack: itemsPerSlot index (data_ref + index / itemsPerSlot)
+ << eth::Instruction::SWAP2 << eth::Instruction::SWAP1
+ << eth::Instruction::MOD
+ << u256(byteSize) << eth::Instruction::MUL;
+ }
+ else
+ {
+ if (arrayType.getBaseType()->getStorageSize() != 1)
+ m_context << arrayType.getBaseType()->getStorageSize() << eth::Instruction::MUL;
+ m_context << eth::Instruction::ADD << u256(0);
+ }
setLValueToStorageItem(_indexAccess);
break;
case ArrayType::Location::Memory:
diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp
index 4b5dddacd..016f0b236 100644
--- a/libsolidity/Types.cpp
+++ b/libsolidity/Types.cpp
@@ -20,14 +20,14 @@
* Solidity data types
*/
+#include
+#include
+#include
#include
#include
#include
-#include
#include
-#include
-
using namespace std;
namespace dev
@@ -184,6 +184,8 @@ TypePointer Type::fromArrayTypeName(TypeName& _baseTypeName, Expression* _length
TypePointer baseType = _baseTypeName.toType();
if (!baseType)
BOOST_THROW_EXCEPTION(_baseTypeName.createTypeError("Invalid type name."));
+ if (baseType->getStorageBytes() == 0)
+ BOOST_THROW_EXCEPTION(_baseTypeName.createTypeError("Illegal base type of storage size zero for array."));
if (_length)
{
if (!_length->getType())
@@ -700,13 +702,21 @@ u256 ArrayType::getStorageSize() const
{
if (isDynamicallySized())
return 1;
- else
+
+ bigint size;
+ unsigned baseBytes = getBaseType()->getStorageBytes();
+ if (baseBytes == 0)
+ size = 1;
+ else if (baseBytes < 32)
{
- bigint size = bigint(getLength()) * getBaseType()->getStorageSize();
- if (size >= bigint(1) << 256)
- BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Array too large for storage."));
- return max(1, u256(size));
+ unsigned itemsPerSlot = 32 / baseBytes;
+ size = (bigint(getLength()) + (itemsPerSlot - 1)) / itemsPerSlot;
}
+ else
+ size = bigint(getLength()) * getBaseType()->getStorageSize();
+ if (size >= bigint(1) << 256)
+ BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Array too large for storage."));
+ return max(1, u256(size));
}
unsigned ArrayType::getSizeOnStack() const
@@ -806,6 +816,26 @@ u256 ContractType::getFunctionIdentifier(string const& _functionName) const
return Invalid256;
}
+vector> ContractType::getStateVariables() const
+{
+ vector variables;
+ for (ContractDefinition const* contract: boost::adaptors::reverse(m_contract.getLinearizedBaseContracts()))
+ for (ASTPointer const& variable: contract->getStateVariables())
+ if (!variable->isConstant())
+ variables.push_back(variable.get());
+ TypePointers types;
+ for (auto variable: variables)
+ types.push_back(variable->getType());
+ StorageOffsets offsets;
+ offsets.computeOffsets(types);
+
+ vector> variablesAndOffsets;
+ for (size_t index = 0; index < variables.size(); ++index)
+ if (auto const* offset = offsets.getOffset(index))
+ variablesAndOffsets.push_back(make_tuple(variables[index], offset->first, offset->second));
+ return variablesAndOffsets;
+}
+
TypePointer StructType::unaryOperatorResult(Token::Value _operator) const
{
return _operator == Token::Delete ? make_shared() : TypePointer();
diff --git a/libsolidity/Types.h b/libsolidity/Types.h
index e7601fde8..c90aabda1 100644
--- a/libsolidity/Types.h
+++ b/libsolidity/Types.h
@@ -335,13 +335,22 @@ public:
/// Constructor for a byte array ("bytes")
explicit ArrayType(Location _location):
- m_location(_location), m_isByteArray(true), m_baseType(std::make_shared(8)) {}
+ m_location(_location),
+ m_isByteArray(true),
+ m_baseType(std::make_shared(8))
+ {}
/// Constructor for a dynamically sized array type ("type[]")
ArrayType(Location _location, const TypePointer &_baseType):
- m_location(_location), m_baseType(_baseType) {}
+ m_location(_location),
+ m_baseType(_baseType)
+ {}
/// Constructor for a fixed-size array type ("type[20]")
ArrayType(Location _location, const TypePointer &_baseType, u256 const& _length):
- m_location(_location), m_baseType(_baseType), m_hasDynamicLength(false), m_length(_length) {}
+ m_location(_location),
+ m_baseType(_baseType),
+ m_hasDynamicLength(false),
+ m_length(_length)
+ {}
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
virtual TypePointer unaryOperatorResult(Token::Value _operator) const override;
@@ -403,6 +412,10 @@ public:
/// not exist.
u256 getFunctionIdentifier(std::string const& _functionName) const;
+ /// @returns a list of all state variables (including inherited) of the contract and their
+ /// offsets in storage.
+ std::vector> getStateVariables() const;
+
private:
ContractDefinition const& m_contract;
/// If true, it is the "super" type of the current contract, i.e. it contains only inherited
diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp
index 76b422a18..9e4ffe174 100644
--- a/libweb3jsonrpc/WebThreeStubServerBase.cpp
+++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp
@@ -112,18 +112,20 @@ static Json::Value toJson(dev::eth::TransactionSkeleton const& _t)
static Json::Value toJson(dev::eth::LocalisedLogEntry const& _e)
{
Json::Value res;
-
- res["data"] = toJS(_e.data);
- res["address"] = toJS(_e.address);
- res["topics"] = Json::Value(Json::arrayValue);
- for (auto const& t: _e.topics)
- res["topics"].append(toJS(t));
- res["number"] = _e.number;
- res["hash"] = toJS(_e.sha3);
+ if (_e.transactionHash)
+ {
+ res["data"] = toJS(_e.data);
+ res["address"] = toJS(_e.address);
+ res["topics"] = Json::Value(Json::arrayValue);
+ for (auto const& t: _e.topics)
+ res["topics"].append(toJS(t));
+ res["number"] = _e.number;
+ res["hash"] = toJS(_e.transactionHash);
+ }
return res;
}
-static Json::Value toJson(dev::eth::LocalisedLogEntries const& _es) // commented to avoid warning. Uncomment once in use @ poC-7.
+static Json::Value toJson(dev::eth::LocalisedLogEntries const& _es)
{
Json::Value res(Json::arrayValue);
for (dev::eth::LocalisedLogEntry const& e: _es)
@@ -139,6 +141,18 @@ static Json::Value toJson(map const& _storage)
return res;
}
+static unsigned toBlockNumber(std::string const& _js)
+{
+ if (_js == "latest")
+ return LatestBlock;
+ else if (_js == "earliest")
+ return 0;
+ else if (_js == "pending")
+ return PendingBlock;
+ else
+ return (unsigned)jsToInt(_js);
+}
+
static dev::eth::LogFilter toLogFilter(Json::Value const& _json) // commented to avoid warning. Uncomment once in use @ PoC-7.
{
dev::eth::LogFilter filter;
@@ -147,9 +161,9 @@ static dev::eth::LogFilter toLogFilter(Json::Value const& _json) // commented to
// check only !empty. it should throw exceptions if input params are incorrect
if (!_json["fromBlock"].empty())
- filter.withEarliest(jsToInt(_json["fromBlock"].asString()));
+ filter.withEarliest(toBlockNumber(_json["fromBlock"].asString()));
if (!_json["toBlock"].empty())
- filter.withLatest(jsToInt(_json["toBlock"].asString()));
+ filter.withLatest(toBlockNumber(_json["toBlock"].asString()));
if (!_json["address"].empty())
{
if (_json["address"].isArray())
@@ -227,15 +241,6 @@ static Json::Value toJson(h256 const& _h, shh::Envelope const& _e, shh::Message
return res;
}
-static int toBlockNumber(string const& _string)
-{
- if (_string.compare("latest") == 0)
- return -1;
- if (_string.compare("pending") == 0)
- return 0;
- return jsToInt(_string);
-}
-
WebThreeStubServerBase::WebThreeStubServerBase(AbstractServerConnector& _conn, vector const& _accounts):
AbstractWebThreeStubServer(_conn), m_accounts(make_shared(bind(&WebThreeStubServerBase::client, this)))
{
@@ -476,7 +481,7 @@ string WebThreeStubServerBase::eth_call(Json::Value const& _json, string const&
t.gasPrice = 10 * dev::eth::szabo;
if (!t.gas)
t.gas = min(client()->gasLimitRemaining(), client()->balanceAt(t.from) / t.gasPrice);
- ret = toJS(client()->call(m_accounts->secretKey(t.from), t.value, t.to, t.data, t.gas, t.gasPrice, number));
+ ret = toJS(client()->call(m_accounts->secretKey(t.from), t.value, t.to, t.data, t.gas, t.gasPrice, number).output);
return ret;
}
diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp
index f61269005..fd7b2263d 100644
--- a/mix/MixClient.cpp
+++ b/mix/MixClient.cpp
@@ -283,7 +283,7 @@ void MixClient::flushTransactions()
{
}
-dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, int _blockNumber)
+dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber)
{
u256 n;
State temp;
@@ -299,7 +299,7 @@ dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _
return lastExecution().result;
}
-dev::eth::ExecutionResult MixClient::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, int _blockNumber)
+dev::eth::ExecutionResult MixClient::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber)
{
u256 n;
State temp;
@@ -315,27 +315,27 @@ dev::eth::ExecutionResult MixClient::create(Secret _secret, u256 _value, bytes c
return lastExecution().result;
}
-u256 MixClient::balanceAt(Address _a, int _block) const
+u256 MixClient::balanceAt(Address _a, BlockNumber _block) const
{
return asOf(_block).balance(_a);
}
-u256 MixClient::countAt(Address _a, int _block) const
+u256 MixClient::countAt(Address _a, BlockNumber _block) const
{
return asOf(_block).transactionsFrom(_a);
}
-u256 MixClient::stateAt(Address _a, u256 _l, int _block) const
+u256 MixClient::stateAt(Address _a, u256 _l, BlockNumber _block) const
{
return asOf(_block).storage(_a, _l);
}
-bytes MixClient::codeAt(Address _a, int _block) const
+bytes MixClient::codeAt(Address _a, BlockNumber _block) const
{
return asOf(_block).code(_a);
}
-std::map MixClient::storageAt(Address _a, int _block) const
+std::map MixClient::storageAt(Address _a, BlockNumber _block) const
{
return asOf(_block).storage(_a);
}
@@ -567,13 +567,13 @@ eth::StateDiff MixClient::diff(unsigned _txi, h256 _block) const
return st.fromPending(_txi).diff(st.fromPending(_txi + 1));
}
-eth::StateDiff MixClient::diff(unsigned _txi, int _block) const
+eth::StateDiff MixClient::diff(unsigned _txi, BlockNumber _block) const
{
State st = asOf(_block);
return st.fromPending(_txi).diff(st.fromPending(_txi + 1));
}
-Addresses MixClient::addresses(int _block) const
+Addresses MixClient::addresses(BlockNumber _block) const
{
Addresses ret;
for (auto const& i: asOf(_block).addresses())
diff --git a/mix/MixClient.h b/mix/MixClient.h
index 37b2bb5d2..e1085a20e 100644
--- a/mix/MixClient.h
+++ b/mix/MixClient.h
@@ -25,6 +25,7 @@
#include
#include
+#include
#include
#include
#include "MachineStates.h"
@@ -52,13 +53,13 @@ public:
Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) override;
void inject(bytesConstRef _rlp) override;
void flushTransactions() override;
- dev::eth::ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, int _blockNumber) override;
- dev::eth::ExecutionResult create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, int _blockNumber) override;
- u256 balanceAt(Address _a, int _block) const override;
- u256 countAt(Address _a, int _block) const override;
- u256 stateAt(Address _a, u256 _l, int _block) const override;
- bytes codeAt(Address _a, int _block) const override;
- std::map storageAt(Address _a, int _block) const override;
+ dev::eth::ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber) override;
+ dev::eth::ExecutionResult create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber) override;
+ u256 balanceAt(Address _a, eth::BlockNumber _block) const override;
+ u256 countAt(Address _a, eth::BlockNumber _block) const override;
+ u256 stateAt(Address _a, u256 _l, eth::BlockNumber _block) const override;
+ bytes codeAt(Address _a, eth::BlockNumber _block) const override;
+ std::map storageAt(Address _a, eth::BlockNumber _block) const override;
eth::LocalisedLogEntries logs(unsigned _watchId) const override;
eth::LocalisedLogEntries logs(eth::LogFilter const& _filter) const override;
unsigned installWatch(eth::LogFilter const& _filter, eth::Reaping _r = eth::Reaping::Automatic) override;
@@ -79,8 +80,8 @@ public:
unsigned number() const override;
eth::Transactions pending() const override;
eth::StateDiff diff(unsigned _txi, h256 _block) const override;
- eth::StateDiff diff(unsigned _txi, int _block) const override;
- Addresses addresses(int _block) const override;
+ eth::StateDiff diff(unsigned _txi, eth::BlockNumber _block) const override;
+ Addresses addresses(eth::BlockNumber _block) const override;
u256 gasLimitRemaining() const override;
void setAddress(Address _us) override;
Address address() const override;
diff --git a/neth/main.cpp b/neth/main.cpp
index 2ce9872ca..4888f784d 100644
--- a/neth/main.cpp
+++ b/neth/main.cpp
@@ -65,7 +65,7 @@ bool isFalse(std::string const& _m)
void help()
{
cout
- << "Usage neth [OPTIONS] " << endl
+ << "Usage neth [OPTIONS]" << endl
<< "Options:" << endl
<< " -a,--address Set the coinbase (mining payout) address to addr (default: auto)." << endl
<< " -c,--client-name Add a name to your client's version string (default: blank)." << endl
@@ -122,7 +122,7 @@ string credits()
std::ostringstream ccout;
ccout
<< "NEthereum (++) " << dev::Version << endl
- << " Code by Gav Wood & , (c) 2013, 2014." << endl
+ << " Code by Gav Wood & caktux, (c) 2013, 2014, 2015." << endl
<< " Based on a design by Vitalik Buterin." << endl << endl;
ccout << "Type 'netstart 30303' to start networking" << endl;
@@ -134,7 +134,7 @@ string credits()
void version()
{
cout << "neth version " << dev::Version << endl;
- cout << "Network protocol version: " << dev::eth::c_protocolVersion << endl;
+ cout << "eth network protocol version: " << dev::eth::c_protocolVersion << endl;
cout << "Client database version: " << dev::eth::c_databaseVersion << endl;
cout << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl;
exit(0);
@@ -373,7 +373,7 @@ int main(int argc, char** argv)
{
try
{
- coinbase = h160(fromHex(argv[++i], ThrowType::Throw));
+ coinbase = h160(fromHex(argv[++i], WhenError::Throw));
}
catch (BadHexCharacter& _e)
{
@@ -428,7 +428,10 @@ int main(int argc, char** argv)
else if (arg == "-V" || arg == "--version")
version();
else
- remoteHost = argv[i];
+ {
+ cerr << "Invalid argument: " << arg << endl;
+ exit(-1);
+ }
}
if (!clientName.empty())
@@ -734,8 +737,8 @@ int main(int argc, char** argv)
{
try
{
- Secret secret = h256(fromHex(sechex, ThrowType::Throw));
- Address dest = h160(fromHex(fields[0], ThrowType::Throw));
+ Secret secret = h256(fromHex(sechex, WhenError::Throw));
+ Address dest = h160(fromHex(fields[0], WhenError::Throw));
c->submitTransaction(secret, amount, dest, data, gas, gasPrice);
}
catch (BadHexCharacter& _e)
@@ -786,7 +789,7 @@ int main(int argc, char** argv)
u256 minGas = (u256)Client::txGas(bytes(), 0);
try
{
- Address dest = h160(fromHex(fields[0], ThrowType::Throw));
+ Address dest = h160(fromHex(fields[0], WhenError::Throw));
c->submitTransaction(us.secret(), amount, dest, bytes(), minGas);
}
catch (BadHexCharacter& _e)
@@ -852,7 +855,7 @@ int main(int argc, char** argv)
stringstream ssc;
try
{
- init = fromHex(sinit, ThrowType::Throw);
+ init = fromHex(sinit, WhenError::Throw);
}
catch (BadHexCharacter& _e)
{
@@ -954,7 +957,7 @@ int main(int argc, char** argv)
auto s = t.receiveAddress() ?
boost::format(" %1% %2%> %3%: %4% [%5%]") %
toString(t.safeSender()) %
- (c->codeAt(t.receiveAddress(), 0).size() ? '*' : '-') %
+ (c->codeAt(t.receiveAddress(), PendingBlock).size() ? '*' : '-') %
toString(t.receiveAddress()) %
toString(formatBalance(t.value())) %
toString((unsigned)t.nonce()) :
@@ -979,7 +982,7 @@ int main(int argc, char** argv)
auto s = t.receiveAddress() ?
boost::format("%1% %2%> %3%: %4% [%5%]") %
toString(t.safeSender()) %
- (c->codeAt(t.receiveAddress(), 0).size() ? '*' : '-') %
+ (c->codeAt(t.receiveAddress(), PendingBlock).size() ? '*' : '-') %
toString(t.receiveAddress()) %
toString(formatBalance(t.value())) %
toString((unsigned)t.nonce()) :
@@ -999,25 +1002,25 @@ int main(int argc, char** argv)
int cc = 1;
auto acs = c->addresses();
for (auto const& i: acs)
- if (c->codeAt(i, 0).size())
+ if (c->codeAt(i, PendingBlock).size())
{
auto s = boost::format("%1%%2% : %3% [%4%]") %
toString(i) %
pretty(i, c->postState()) %
toString(formatBalance(c->balanceAt(i))) %
- toString((unsigned)c->countAt(i, 0));
+ toString((unsigned)c->countAt(i, PendingBlock));
mvwaddnstr(contractswin, cc++, x, s.str().c_str(), qwidth);
if (cc > qheight - 2)
break;
}
for (auto const& i: acs)
- if (c->codeAt(i, 0).empty())
+ if (c->codeAt(i, PendingBlock).empty())
{
auto s = boost::format("%1%%2% : %3% [%4%]") %
toString(i) %
pretty(i, c->postState()) %
toString(formatBalance(c->balanceAt(i))) %
- toString((unsigned)c->countAt(i, 0));
+ toString((unsigned)c->countAt(i, PendingBlock));
mvwaddnstr(addswin, y++, x, s.str().c_str(), width / 2 - 4);
if (y > height * 3 / 5 - 4)
break;
diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp
index 0bd27a5fc..ea6ada603 100644
--- a/test/SolidityEndToEndTest.cpp
+++ b/test/SolidityEndToEndTest.cpp
@@ -3088,6 +3088,123 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_storage_static_dynamic)
BOOST_CHECK(callContractFunction("test()") == encodeArgs(9, 4));
}
+BOOST_AUTO_TEST_CASE(array_copy_different_packing)
+{
+ char const* sourceCode = R"(
+ contract c {
+ bytes8[] data1; // 4 per slot
+ bytes10[] data2; // 3 per slot
+ function test() returns (bytes10 a, bytes10 b, bytes10 c, bytes10 d, bytes10 e) {
+ data1.length = 9;
+ for (uint i = 0; i < data1.length; ++i)
+ data1[i] = bytes8(i);
+ data2 = data1;
+ a = data2[1];
+ b = data2[2];
+ c = data2[3];
+ d = data2[4];
+ e = data2[5];
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callContractFunction("test()") == encodeArgs(
+ asString(fromHex("0000000000000001")),
+ asString(fromHex("0000000000000002")),
+ asString(fromHex("0000000000000003")),
+ asString(fromHex("0000000000000004")),
+ asString(fromHex("0000000000000005"))
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(array_copy_target_simple)
+{
+ char const* sourceCode = R"(
+ contract c {
+ bytes8[9] data1; // 4 per slot
+ bytes17[10] data2; // 1 per slot, no offset counter
+ function test() returns (bytes17 a, bytes17 b, bytes17 c, bytes17 d, bytes17 e) {
+ for (uint i = 0; i < data1.length; ++i)
+ data1[i] = bytes8(i);
+ data2[8] = data2[9] = 2;
+ data2 = data1;
+ a = data2[1];
+ b = data2[2];
+ c = data2[3];
+ d = data2[4];
+ e = data2[9];
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callContractFunction("test()") == encodeArgs(
+ asString(fromHex("0000000000000001")),
+ asString(fromHex("0000000000000002")),
+ asString(fromHex("0000000000000003")),
+ asString(fromHex("0000000000000004")),
+ asString(fromHex("0000000000000000"))
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(array_copy_target_leftover)
+{
+ // test that leftover elements in the last slot of target are correctly cleared during assignment
+ char const* sourceCode = R"(
+ contract c {
+ byte[10] data1;
+ bytes2[32] data2;
+ function test() returns (uint check, uint res1, uint res2) {
+ uint i;
+ for (i = 0; i < data2.length; ++i)
+ data2[i] = 0xffff;
+ check = uint(data2[31]) * 0x10000 | uint(data2[14]);
+ for (i = 0; i < data1.length; ++i)
+ data1[i] = byte(uint8(1 + i));
+ data2 = data1;
+ for (i = 0; i < 16; ++i)
+ res1 |= uint(data2[i]) * 0x10000**i;
+ for (i = 0; i < 16; ++i)
+ res2 |= uint(data2[16 + i]) * 0x10000**i;
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callContractFunction("test()") == encodeArgs(
+ u256("0xffffffff"),
+ asString(fromHex("0000000000000000""000000000a000900""0800070006000500""0400030002000100")),
+ asString(fromHex("0000000000000000""0000000000000000""0000000000000000""0000000000000000"))
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(array_copy_target_leftover2)
+{
+ // since the copy always copies whole slots, we have to make sure that the source size maxes
+ // out a whole slot and at the same time there are still elements left in the target at that point
+ char const* sourceCode = R"(
+ contract c {
+ bytes8[4] data1; // fits into one slot
+ bytes10[6] data2; // 4 elements need two slots
+ function test() returns (bytes10 r1, bytes10 r2, bytes10 r3) {
+ data1[0] = 1;
+ data1[1] = 2;
+ data1[2] = 3;
+ data1[3] = 4;
+ for (uint i = 0; i < data2.length; ++i)
+ data2[i] = bytes10(0xffff00 | (1 + i));
+ data2 = data1;
+ r1 = data2[3];
+ r2 = data2[4];
+ r3 = data2[5];
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callContractFunction("test()") == encodeArgs(
+ asString(fromHex("0000000000000004")),
+ asString(fromHex("0000000000000000")),
+ asString(fromHex("0000000000000000"))
+ ));
+}
BOOST_AUTO_TEST_CASE(array_copy_storage_storage_struct)
{
char const* sourceCode = R"(
@@ -3214,7 +3331,7 @@ BOOST_AUTO_TEST_CASE(array_copy_nested_array)
char const* sourceCode = R"(
contract c {
uint[4][] a;
- uint[5][] b;
+ uint[10][] b;
uint[][] c;
function test(uint[2][] d) external returns (uint) {
a = d;
@@ -3480,6 +3597,30 @@ BOOST_AUTO_TEST_CASE(packed_storage_structs_delete)
BOOST_CHECK(m_state.storage(m_contractAddress).empty());
}
+BOOST_AUTO_TEST_CASE(packed_storage_structs_with_bytes0)
+{
+ char const* sourceCode = R"(
+ contract C {
+ struct str { uint8 a; bytes0 b; uint8 c; }
+ uint8 a;
+ bytes0 x;
+ uint8 b;
+ str data;
+ function test() returns (bool) {
+ a = 2;
+ b = 3;
+ data.a = 4;
+ data.c = 5;
+ delete x;
+ delete data.b;
+ return a == 2 && b == 3 && data.a == 4 && data.c == 5;
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callContractFunction("test()") == encodeArgs(true));
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/SolidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp
index b83709d83..591cf053a 100644
--- a/test/SolidityNameAndTypeResolution.cpp
+++ b/test/SolidityNameAndTypeResolution.cpp
@@ -1446,6 +1446,16 @@ BOOST_AUTO_TEST_CASE(local_const_variable)
BOOST_CHECK_THROW(parseTextAndResolveNames(text), ParserError);
}
+BOOST_AUTO_TEST_CASE(bytes0_array)
+{
+ char const* text = R"(
+ contract Foo {
+ bytes0[] illegalArray;
+ }
+ )";
+ BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/SolidityTypes.cpp b/test/SolidityTypes.cpp
index 8defd1d89..6b6306479 100644
--- a/test/SolidityTypes.cpp
+++ b/test/SolidityTypes.cpp
@@ -75,6 +75,17 @@ BOOST_AUTO_TEST_CASE(storage_layout_mapping)
BOOST_CHECK(*members.getMemberStorageOffset("final") == make_pair(u256(3), unsigned(0)));
}
+BOOST_AUTO_TEST_CASE(storage_layout_arrays)
+{
+ BOOST_CHECK(ArrayType(ArrayType::Location::Storage, make_shared(1), 32).getStorageSize() == 1);
+ BOOST_CHECK(ArrayType(ArrayType::Location::Storage, make_shared(1), 33).getStorageSize() == 2);
+ BOOST_CHECK(ArrayType(ArrayType::Location::Storage, make_shared(2), 31).getStorageSize() == 2);
+ BOOST_CHECK(ArrayType(ArrayType::Location::Storage, make_shared(7), 8).getStorageSize() == 2);
+ BOOST_CHECK(ArrayType(ArrayType::Location::Storage, make_shared(7), 9).getStorageSize() == 3);
+ BOOST_CHECK(ArrayType(ArrayType::Location::Storage, make_shared(31), 9).getStorageSize() == 9);
+ BOOST_CHECK(ArrayType(ArrayType::Location::Storage, make_shared(32), 9).getStorageSize() == 9);
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp
index 128318b8c..b29c5dc3a 100644
--- a/test/TestHelper.cpp
+++ b/test/TestHelper.cpp
@@ -240,7 +240,7 @@ byte toByte(json_spirit::mValue const& _v)
bytes importByteArray(std::string const& _str)
{
- return fromHex(_str.substr(0, 2) == "0x" ? _str.substr(2) : _str, ThrowType::Throw);
+ return fromHex(_str.substr(0, 2) == "0x" ? _str.substr(2) : _str, WhenError::Throw);
}
bytes importData(json_spirit::mObject& _o)
diff --git a/test/net.cpp b/test/net.cpp
index 3a69a627b..23ad0fb4a 100644
--- a/test/net.cpp
+++ b/test/net.cpp
@@ -53,7 +53,7 @@ protected:
struct TestNodeTable: public NodeTable
{
/// Constructor
- TestNodeTable(ba::io_service& _io, KeyPair _alias, uint16_t _port = 30300): NodeTable(_io, _alias, _port) {}
+ TestNodeTable(ba::io_service& _io, KeyPair _alias, bi::address const& _addr, uint16_t _port = 30300): NodeTable(_io, _alias, _addr, _port) {}
static std::vector> createTestNodes(unsigned _count)
{
@@ -89,7 +89,16 @@ struct TestNodeTable: public NodeTable
bi::address ourIp = bi::address::from_string("127.0.0.1");
for (auto& n: _testNodes)
if (_count--)
+ {
+ // manually add node for test
+ {
+ Guard ln(x_nodes);
+ shared_ptr node(new NodeEntry(m_node, n.first.pub(), NodeIPEndpoint(bi::udp::endpoint(ourIp, n.second), bi::tcp::endpoint(ourIp, n.second))));
+ node->pending = false;
+ m_nodes[node->id] = node;
+ }
noteActiveNode(n.first.pub(), bi::udp::endpoint(ourIp, n.second));
+ }
else
break;
}
@@ -106,10 +115,10 @@ struct TestNodeTable: public NodeTable
*/
struct TestNodeTableHost: public TestHost
{
- TestNodeTableHost(unsigned _count = 8): m_alias(KeyPair::create()), nodeTable(new TestNodeTable(m_io, m_alias)), testNodes(TestNodeTable::createTestNodes(_count)) {};
+ TestNodeTableHost(unsigned _count = 8): m_alias(KeyPair::create()), nodeTable(new TestNodeTable(m_io, m_alias, bi::address::from_string("127.0.0.1"))), testNodes(TestNodeTable::createTestNodes(_count)) {};
~TestNodeTableHost() { m_io.stop(); stopWorking(); }
- void setup() { for (auto n: testNodes) nodeTables.push_back(make_shared(m_io,n.first,n.second)); }
+ void setup() { for (auto n: testNodes) nodeTables.push_back(make_shared(m_io,n.first, bi::address::from_string("127.0.0.1"),n.second)); }
void pingAll() { for (auto& t: nodeTables) t->pingTestNodes(testNodes); }
diff --git a/test/peer.cpp b/test/peer.cpp
index 14712d4f1..bfb4680d3 100644
--- a/test/peer.cpp
+++ b/test/peer.cpp
@@ -35,8 +35,8 @@ BOOST_AUTO_TEST_CASE(host)
auto oldLogVerbosity = g_logVerbosity;
g_logVerbosity = 10;
- NetworkPreferences host1prefs(30301, "127.0.0.1", true, true);
- NetworkPreferences host2prefs(30302, "127.0.0.1", true, true);
+ NetworkPreferences host1prefs(30301, "127.0.0.1", false, true);
+ NetworkPreferences host2prefs(30302, "127.0.0.1", false, true);
Host host1("Test", host1prefs);
host1.start();
@@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE(save_nodes)
std::list hosts;
for (auto i:{0,1,2,3,4,5})
{
- Host* h = new Host("Test", NetworkPreferences(30300 + i, "127.0.0.1", true, true));
+ Host* h = new Host("Test", NetworkPreferences(30300 + i, "127.0.0.1", false, true));
h->setIdealPeerCount(10);
// starting host is required so listenport is available
h->start();
@@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(save_nodes)
RLP r(firstHostNetwork);
BOOST_REQUIRE(r.itemCount() == 3);
- BOOST_REQUIRE(r[0].toInt() == 1);
+ BOOST_REQUIRE(r[0].toInt() == dev::p2p::c_protocolVersion);
BOOST_REQUIRE_EQUAL(r[1].toBytes().size(), 32); // secret
BOOST_REQUIRE_EQUAL(r[2].itemCount(), 5);
}
diff --git a/third/MainWin.cpp b/third/MainWin.cpp
index a1074cddb..b03723131 100644
--- a/third/MainWin.cpp
+++ b/third/MainWin.cpp
@@ -212,13 +212,13 @@ void Main::installWatches()
void Main::installNameRegWatch()
{
ethereum()->uninstallWatch(m_nameRegFilter);
- m_nameRegFilter = installWatch(dev::eth::LogFilter().address(u160(ethereum()->stateAt(c_config, 0))), [=](LocalisedLogEntries const&){ onNameRegChange(); });
+ m_nameRegFilter = installWatch(dev::eth::LogFilter().address(u160(ethereum()->stateAt(c_config, PendingBlock))), [=](LocalisedLogEntries const&){ onNameRegChange(); });
}
void Main::installCurrenciesWatch()
{
ethereum()->uninstallWatch(m_currenciesFilter);
- m_currenciesFilter = installWatch(dev::eth::LogFilter().address(u160(ethereum()->stateAt(c_config, 1))), [=](LocalisedLogEntries const&){ onCurrenciesChange(); });
+ m_currenciesFilter = installWatch(dev::eth::LogFilter().address(u160(ethereum()->stateAt(c_config, LatestBlock))), [=](LocalisedLogEntries const&){ onCurrenciesChange(); });
}
void Main::installBalancesWatch()
@@ -226,8 +226,8 @@ void Main::installBalancesWatch()
dev::eth::LogFilter tf;
vector altCoins;
- Address coinsAddr = right160(ethereum()->stateAt(c_config, 1));
- for (unsigned i = 0; i < ethereum()->stateAt(coinsAddr, 0); ++i)
+ Address coinsAddr = right160(ethereum()->stateAt(c_config, LatestBlock));
+ for (unsigned i = 0; i < ethereum()->stateAt(coinsAddr, PendingBlock); ++i)
altCoins.push_back(right160(ethereum()->stateAt(coinsAddr, i + 1)));
for (auto i: m_myKeys)
for (auto c: altCoins)
@@ -294,7 +294,7 @@ QString Main::pretty(dev::Address _a) const
{
h256 n;
- if (h160 nameReg = (u160)ethereum()->stateAt(c_config, 0))
+ if (h160 nameReg = (u160)ethereum()->stateAt(c_config, PendingBlock))
n = ethereum()->stateAt(nameReg, (u160)(_a));
return fromRaw(n);
@@ -321,7 +321,7 @@ Address Main::fromString(QString const& _a) const
memset(n.data() + sn.size(), 0, 32 - sn.size());
if (_a.size())
{
- if (h160 nameReg = (u160)ethereum()->stateAt(c_config, 0))
+ if (h160 nameReg = (u160)ethereum()->stateAt(c_config, PendingBlock))
if (h256 a = ethereum()->stateAt(nameReg, n))
return right160(a);
}
@@ -350,10 +350,10 @@ QString Main::lookup(QString const& _a) const
*/
h256 ret;
- if (h160 dnsReg = (u160)ethereum()->stateAt(c_config, 4, 0))
+ if (h160 dnsReg = (u160)ethereum()->stateAt(c_config, 4, PendingBlock))
ret = ethereum()->stateAt(dnsReg, n);
/* if (!ret)
- if (h160 nameReg = (u160)ethereum()->stateAt(c_config, 0, 0))
+ if (h160 nameReg = (u160)ethereum()->stateAt(c_config, 0, PendingBlock))
ret = ethereum()->stateAt(nameReg, n2);
*/
if (ret && !((u256)ret >> 32))
@@ -476,8 +476,8 @@ void Main::refreshBalances()
ui->ourAccounts->clear();
u256 totalBalance = 0;
map> altCoins;
- Address coinsAddr = right160(ethereum()->stateAt(c_config, 1));
- for (unsigned i = 0; i < ethereum()->stateAt(coinsAddr, 0); ++i)
+ Address coinsAddr = right160(ethereum()->stateAt(c_config, LatestBlock));
+ for (unsigned i = 0; i < ethereum()->stateAt(coinsAddr, PendingBlock); ++i)
altCoins[right160(ethereum()->stateAt(coinsAddr, ethereum()->stateAt(coinsAddr, i + 1)))] = make_pair(fromRaw(ethereum()->stateAt(coinsAddr, i + 1)), 0);
for (auto i: m_myKeys)
{
]