Browse Source

Merge branch 'p2p' into whisper

cl-refactor
subtly 10 years ago
parent
commit
92669aa47d
  1. 17
      CMakeLists.txt
  2. 16
      CodingStandards.txt
  3. 55
      alethzero/DappLoader.cpp
  4. 7
      alethzero/DappLoader.h
  5. 6
      alethzero/Main.ui
  6. 23
      alethzero/MainWin.cpp
  7. 1
      alethzero/MainWin.h
  8. 2
      alethzero/Transact.cpp
  9. 280
      eth/main.cpp
  10. 4
      evmjit/libevmjit/ExecutionEngine.cpp
  11. 18
      exp/CMakeLists.txt
  12. 29
      exp/main.cpp
  13. 1
      libdevcore/CMakeLists.txt
  14. 2
      libdevcore/Common.cpp
  15. 28
      libdevcore/CommonData.h
  16. 6
      libdevcore/CommonIO.cpp
  17. 2
      libdevcore/CommonIO.h
  18. 2
      libdevcore/Log.cpp
  19. 2
      libdevcore/RLP.cpp
  20. 5
      libdevcore/RLP.h
  21. 1
      libdevcore/RangeMask.h
  22. 4
      libdevcore/TransientDirectory.cpp
  23. 4
      libdevcore/TransientDirectory.h
  24. 12
      libdevcore/Worker.cpp
  25. 6
      libdevcrypto/Common.cpp
  26. 6
      libdevcrypto/TrieDB.h
  27. 2
      libethash/util.h
  28. 30
      libethcore/BlockInfo.cpp
  29. 4
      libethcore/BlockInfo.h
  30. 17
      libethcore/CommonJS.cpp
  31. 3
      libethcore/CommonJS.h
  32. 38
      libethcore/Ethasher.cpp
  33. 2
      libethcore/Ethasher.h
  34. 1
      libethcore/Exceptions.h
  35. 1
      libethcore/Params.cpp
  36. 3
      libethcore/Params.h
  37. 117
      libethcore/ProofOfWork.cpp
  38. 6
      libethcore/ProofOfWork.h
  39. 83
      libethereum/BlockChain.cpp
  40. 36
      libethereum/BlockChain.h
  41. 8
      libethereum/BlockQueue.cpp
  42. 7
      libethereum/CMakeLists.txt
  43. 13
      libethereum/Client.cpp
  44. 3
      libethereum/Client.h
  45. 44
      libethereum/ClientBase.cpp
  46. 14
      libethereum/ClientBase.h
  47. 5
      libethereum/EthereumHost.cpp
  48. 4
      libethereum/EthereumPeer.cpp
  49. 13
      libethereum/Executive.cpp
  50. 2
      libethereum/Executive.h
  51. 33
      libethereum/Interface.h
  52. 30
      libethereum/State.cpp
  53. 5
      libethereum/State.h
  54. 16
      libethereum/Transaction.cpp
  55. 48
      libethereum/Transaction.h
  56. 8
      libethereum/TransactionQueue.cpp
  57. 3
      libethereum/TransactionQueue.h
  58. 2
      libevm/VM.cpp
  59. 2
      libjsqrc/ethereumjs/.bowerrc
  60. 1
      libjsqrc/ethereumjs/.gitignore
  61. 1
      libjsqrc/ethereumjs/.travis.yml
  62. 8
      libjsqrc/ethereumjs/README.md
  63. 4
      libjsqrc/ethereumjs/bower.json
  64. 57
      libjsqrc/ethereumjs/dist/ethereum.js.map
  65. 1
      libjsqrc/ethereumjs/dist/ethereum.min.js
  66. 1879
      libjsqrc/ethereumjs/dist/web3-light.js
  67. 69
      libjsqrc/ethereumjs/dist/web3-light.js.map
  68. 1
      libjsqrc/ethereumjs/dist/web3-light.min.js
  69. 5548
      libjsqrc/ethereumjs/dist/web3.js
  70. 69
      libjsqrc/ethereumjs/dist/web3.js.map
  71. 2
      libjsqrc/ethereumjs/dist/web3.min.js
  72. 4
      libjsqrc/ethereumjs/example/balance.html
  73. 153
      libjsqrc/ethereumjs/example/coin.html
  74. 3
      libjsqrc/ethereumjs/example/contract.html
  75. 3
      libjsqrc/ethereumjs/example/contract_with_array.html
  76. 3
      libjsqrc/ethereumjs/example/event.html
  77. 3
      libjsqrc/ethereumjs/example/event_inc.html
  78. 3
      libjsqrc/ethereumjs/example/natspec_contract.html
  79. 34
      libjsqrc/ethereumjs/gulpfile.js
  80. 9
      libjsqrc/ethereumjs/index.js
  81. 3
      libjsqrc/ethereumjs/karma.conf.js
  82. 20
      libjsqrc/ethereumjs/lib/solidity/formatters.js
  83. 4
      libjsqrc/ethereumjs/lib/utils/browser-bn.js
  84. 9
      libjsqrc/ethereumjs/lib/utils/browser-xhr.js
  85. 4
      libjsqrc/ethereumjs/lib/utils/config.js
  86. 68
      libjsqrc/ethereumjs/lib/utils/utils.js
  87. 3
      libjsqrc/ethereumjs/lib/version.json
  88. 288
      libjsqrc/ethereumjs/lib/web3.js
  89. 47
      libjsqrc/ethereumjs/lib/web3/contract.js
  90. 38
      libjsqrc/ethereumjs/lib/web3/db.js
  91. 38
      libjsqrc/ethereumjs/lib/web3/errors.js
  92. 242
      libjsqrc/ethereumjs/lib/web3/eth.js
  93. 4
      libjsqrc/ethereumjs/lib/web3/event.js
  94. 165
      libjsqrc/ethereumjs/lib/web3/filter.js
  95. 92
      libjsqrc/ethereumjs/lib/web3/formatters.js
  96. 56
      libjsqrc/ethereumjs/lib/web3/httpprovider.js
  97. 66
      libjsqrc/ethereumjs/lib/web3/jsonrpc.js
  98. 159
      libjsqrc/ethereumjs/lib/web3/method.js
  99. 13
      libjsqrc/ethereumjs/lib/web3/net.js
  100. 104
      libjsqrc/ethereumjs/lib/web3/property.js

17
CMakeLists.txt

@ -15,7 +15,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
# Normally, set(...CACHE...) creates cache variables, but does not modify them.
function(createDefaultCacheConfig)
set(VMTRACE OFF CACHE BOOL "VM tracing and run-time checks (useful for cross-implementation VM debugging)")
set(PARANOIA OFF CACHE BOOL "Additional run-time checks")
set(PARANOID OFF CACHE BOOL "Additional run-time checks")
set(JSONRPC ON CACHE BOOL "Build with jsonprc. default on")
set(FATDB OFF CACHE BOOL "Build with ability to list entries in the Trie. Doubles DB size, slows everything down, but good for looking at state diffs and trie contents.")
set(USENPM OFF CACHE BOOL "Use npm to recompile ethereum.js if it was changed")
@ -35,7 +35,7 @@ endfunction()
# propagates CMake configuration options to the compiler
function(configureProject)
if (PARANOIA)
if (PARANOID)
add_definitions(-DETH_PARANOIA)
endif ()
@ -89,7 +89,7 @@ function(createBuildInfo)
set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/int")
endif ()
if (PARANOIA)
if (PARANOID)
set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/PARA")
endif ()
@ -123,9 +123,9 @@ cmake_policy(SET CMP0015 NEW)
# Clear invalid option
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
if (PARANOIA)
if (PARANOID)
message("Paranoia requires debug - disabling for release build.")
set(PARANOIA OFF)
set(PARANOID OFF)
endif ()
if (VMTRACE)
message("VM Tracing requires debug - disabling for release build.")
@ -151,10 +151,10 @@ if (HEADLESS)
set(BUNDLE "minimal")
endif ()
if (PARANOIA)
set(PARANOIA ON)
if (PARANOID)
set(PARANOID ON)
else ()
set(PARANOIA OFF)
set(PARANOID OFF)
endif ()
if (VMTRACE)
set(VMTRACE ON)
@ -282,7 +282,6 @@ message("--------------------------------------------------------------- feature
message("-- Chromium support ${ETH_HAVE_WEBENGINE}")
message("-- VMTRACE VM execution tracing ${VMTRACE}")
message("-- PROFILING Profiling support ${PROFILING}")
message("-- PARANOIA Additional (SLOW) database checking ${PARANOIA}")
message("-- FATDB Full database exploring ${FATDB}")
message("-- JSONRPC JSON-RPC support ${JSONRPC}")
message("-- USENPM Javascript source building ${USENPM}")

16
CodingStandards.txt

@ -113,26 +113,33 @@ d. Favour declarations close to use; don't habitually declare at top of scope al
e. Always pass non-trivial parameters with a const& suffix.
f. If a function returns multiple values, use std::tuple (std::pair acceptable). Prefer not using */& arguments, except where efficiency requires.
g. Never use a macro where adequate non-preprocessor C++ can be written.
h. Prefer "using NewType = OldType" to "typedef OldType NewType".
i. Make use of auto whenever type is clear or unimportant:
h. Make use of auto whenever type is clear or unimportant:
- Always avoid doubly-stating the type.
- Use to avoid vast and unimportant type declarations.
i. Don't pass bools: prefer enumerations instead.
j. Prefer enum class to straight enum.
(WRONG)
const double d = 0;
int i, j;
char *s;
float meanAndSigma(std::vector<float> _v, float* _sigma);
float meanAndSigma(std::vector<float> _v, float* _sigma, bool _approximate);
Derived* x(dynamic_cast<Derived*>(base));
for (map<ComplexTypeOne, ComplexTypeTwo>::iterator i = l.begin(); i != l.end(); ++l) {}
(CORRECT)
enum class Accuracy
{
Approximate,
Exact
};
double const d = 0;
int i;
int j;
char* s;
std::tuple<float, float> meanAndSigma(std::vector<float> const& _v);
std::tuple<float, float> meanAndSigma(std::vector<float> const& _v, Accuracy _a);
auto x = dynamic_cast<Derived*>(base);
for (auto i = x.begin(); i != x.end(); ++i) {}
@ -192,7 +199,6 @@ c. Where there are exceptions to this (due to excessive use and clear meaning),
d. In general expressions should be roughly as important/semantically meaningful as the space they occupy.
11. Commenting
a. Comments should be doxygen-compilable, using @notation rather than \notation.

55
alethzero/DappLoader.cpp

@ -25,6 +25,7 @@
#include <QStringList>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QMimeDatabase>
#include <libdevcore/Common.h>
#include <libdevcore/RLP.h>
#include <libdevcrypto/CryptoPP.h>
@ -96,13 +97,31 @@ DappLocation DappLoader::resolveAppUri(QString const& _uri)
void DappLoader::downloadComplete(QNetworkReply* _reply)
{
QUrl requestUrl = _reply->request().url();
if (m_pageUrls.count(requestUrl) != 0)
{
//inject web3 js
QByteArray content = "<script>\n";
content.append(web3Content());
content.append("</script>\n");
content.append(_reply->readAll());
QString contentType = _reply->header(QNetworkRequest::ContentTypeHeader).toString();
if (contentType.isEmpty())
{
QMimeDatabase db;
contentType = db.mimeTypeForUrl(requestUrl).name();
}
pageReady(content, contentType, requestUrl);
return;
}
try
{
//try to interpret as rlp
QByteArray data = _reply->readAll();
_reply->deleteLater();
h256 expected = m_uriHashes[_reply->request().url()];
h256 expected = m_uriHashes[requestUrl];
bytes package(reinterpret_cast<unsigned char const*>(data.constData()), reinterpret_cast<unsigned char const*>(data.constData() + data.size()));
Secp256k1 dec;
dec.decrypt(expected, package);
@ -144,15 +163,7 @@ void DappLoader::loadDapp(RLP const& _rlp)
if (entry->path == "/deployment.js")
{
//inject web3 code
QString code;
code += contentsOfQResource(":/js/bignumber.min.js");
code += "\n";
code += contentsOfQResource(":/js/webthree.js");
code += "\n";
code += contentsOfQResource(":/js/setup.js");
code += "\n";
QByteArray res = code.toLatin1();
bytes b(res.data(), res.data() + res.size());
bytes b(web3Content().data(), web3Content().data() + web3Content().size());
b.insert(b.end(), content.begin(), content.end());
dapp.content[hash] = b;
}
@ -165,6 +176,22 @@ void DappLoader::loadDapp(RLP const& _rlp)
emit dappReady(dapp);
}
QByteArray const& DappLoader::web3Content()
{
if (m_web3Js.isEmpty())
{
QString code;
code += contentsOfQResource(":/js/bignumber.min.js");
code += "\n";
code += contentsOfQResource(":/js/webthree.js");
code += "\n";
code += contentsOfQResource(":/js/setup.js");
code += "\n";
m_web3Js = code.toLatin1();
}
return m_web3Js;
}
Manifest DappLoader::loadManifest(std::string const& _manifest)
{
/// https://github.com/ethereum/go-ethereum/wiki/URL-Scheme
@ -216,3 +243,11 @@ void DappLoader::loadDapp(QString const& _uri)
m_net.get(request);
}
void DappLoader::loadPage(QString const& _uri)
{
QUrl uri(_uri);
QNetworkRequest request(uri);
m_pageUrls.insert(uri);
m_net.get(request);
}

7
alethzero/DappLoader.h

@ -73,9 +73,13 @@ public:
///Load a new DApp. Resolves a name with a name reg contract. Asynchronous. dappReady is emitted once everything is read, dappError othervise
///@param _uri Eth name path
void loadDapp(QString const& _uri);
///Load a regular html page
///@param _uri Page Uri
void loadPage(QString const& _uri);
signals:
void dappReady(Dapp& _dapp);
void pageReady(QByteArray const& _content, QString const& _mimeType, QUrl const& _uri);
void dappError();
private slots:
@ -86,9 +90,12 @@ private:
DappLocation resolveAppUri(QString const& _uri);
void loadDapp(dev::RLP const& _rlp);
Manifest loadManifest(std::string const& _manifest);
QByteArray const& web3Content();
dev::WebThreeDirect* m_web3;
QNetworkAccessManager m_net;
std::map<QUrl, dev::h256> m_uriHashes;
std::set<QUrl> m_pageUrls;
QByteArray m_web3Js;
};

6
alethzero/Main.ui

@ -570,7 +570,7 @@
<item>
<widget class="QListWidget" name="ourAccounts">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
<enum>Qt::WheelFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
@ -637,7 +637,7 @@
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
<enum>Qt::WheelFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
@ -715,7 +715,7 @@
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
<enum>Qt::WheelFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>

23
alethzero/MainWin.cpp

@ -183,13 +183,6 @@ Main::Main(QWidget *parent) :
m_webPage = webPage;
connect(webPage, &WebPage::consoleMessage, [this](QString const& _msg) { Main::addConsoleMessage(_msg, QString()); });
ui->webView->setPage(m_webPage);
connect(ui->webView, &QWebEngineView::loadFinished, [this]()
{
auto f = ui->webView->page();
f->runJavaScript(contentsOfQResource(":/js/bignumber.min.js"));
f->runJavaScript(contentsOfQResource(":/js/webthree.js"));
f->runJavaScript(contentsOfQResource(":/js/setup.js"));
});
connect(ui->webView, &QWebEngineView::titleChanged, [=]()
{
@ -199,6 +192,7 @@ Main::Main(QWidget *parent) :
m_dappHost.reset(new DappHost(8081));
m_dappLoader = new DappLoader(this, web3());
connect(m_dappLoader, &DappLoader::dappReady, this, &Main::dappLoaded);
connect(m_dappLoader, &DappLoader::pageReady, this, &Main::pageLoaded);
// ui->webView->page()->settings()->setAttribute(QWebEngineSettings::DeveloperExtrasEnabled, true);
// QWebEngineInspector* inspector = new QWebEngineInspector();
// inspector->setPage(page);
@ -918,6 +912,7 @@ void Main::on_urlEdit_returnPressed()
{
//try do resolve dapp url
m_dappLoader->loadDapp(s);
return;
}
catch (...)
{
@ -931,8 +926,7 @@ void Main::on_urlEdit_returnPressed()
else
url.setScheme("http");
else {}
qDebug() << url.toString();
ui->webView->page()->setUrl(url);
m_dappLoader->loadPage(url.toString());
}
void Main::on_nameReg_textChanged()
@ -1156,7 +1150,7 @@ void Main::refreshBlockChain()
auto b = bc.block(h);
for (auto const& i: RLP(b)[1])
{
Transaction t(i.data(), CheckSignature::Sender);
Transaction t(i.data(), CheckTransaction::Everything);
QString s = t.receiveAddress() ?
QString(" %2 %5> %3: %1 [%4]")
.arg(formatBalance(t.value()).c_str())
@ -1536,7 +1530,7 @@ void Main::on_blocks_currentItemChanged()
else
{
unsigned txi = item->data(Qt::UserRole + 1).toInt();
Transaction tx(block[1][txi].data(), CheckSignature::Sender);
Transaction tx(block[1][txi].data(), CheckTransaction::Everything);
auto ss = tx.safeSender();
h256 th = sha3(rlpList(ss, tx.nonce()));
TransactionReceipt receipt = ethereum()->blockChain().receipts(h).receipts[txi];
@ -1597,7 +1591,7 @@ void Main::on_debugCurrent_triggered()
State s(ethereum()->state(txi, h));
Executive e(s, ethereum()->blockChain());
Debugger dw(this, this);
dw.populate(e, Transaction(t, CheckSignature::Sender));
dw.populate(e, Transaction(t, CheckTransaction::Everything));
dw.exec();
}
}
@ -2016,3 +2010,8 @@ void Main::dappLoaded(Dapp& _dapp)
QUrl url = m_dappHost->hostDapp(std::move(_dapp));
ui->webView->page()->setUrl(url);
}
void Main::pageLoaded(QByteArray const& _content, QString const& _mimeType, QUrl const& _uri)
{
ui->webView->page()->setContent(_content, _mimeType, _uri);
}

1
alethzero/MainWin.h

@ -179,6 +179,7 @@ private slots:
// Dapps
void dappLoaded(Dapp& _dapp); //qt does not support rvalue refs for signals
void pageLoaded(QByteArray const& _content, QString const& _mimeType, QUrl const& _uri);
signals:
void poll();

2
alethzero/Transact.cpp

@ -306,7 +306,7 @@ void Transact::rejigData()
htmlInfo += "<h4>Hex</h4>" + QString(Div(Mono)) + QString::fromStdString(toHex(m_data)) + "</div>";
// Determine the minimum amount of gas we need to play...
qint64 baseGas = (qint64)Interface::txGas(m_data, 0);
qint64 baseGas = (qint64)Transaction::gasRequired(m_data, 0);
qint64 gasNeeded = 0;
if (b < value() + baseGas * gasPrice())

280
eth/main.cpp

@ -44,6 +44,7 @@
#include <libweb3jsonrpc/WebThreeStubServer.h>
#include <jsonrpccpp/server/connectors/httpserver.h>
#endif
#include <libethcore/Ethasher.h>
#include "BuildInfo.h"
using namespace std;
using namespace dev;
@ -112,10 +113,16 @@ void help()
<< " -c,--client-name <name> Add a name to your client's version string (default: blank)." << endl
<< " -d,--db-path <path> Load database from path (default: ~/.ethereum " << endl
<< " <APPDATA>/Etherum or Library/Application Support/Ethereum)." << endl
<< " -D,--create-dag <this/next/number> Create the DAG in preparation for mining on given block and exit." << endl
<< " -e,--ether-price <n> Set the ether price in the reference unit e.g. ¢ (Default: 30.679)." << endl
<< " -E,--export <file> Export file as a concatenated series of blocks and exit." << endl
<< " --from <n> Export only from block n; n may be a decimal, a '0x' prefixed hash, or 'latest'." << endl
<< " --to <n> Export only to block n (inclusive); n may be a decimal, a '0x' prefixed hash, or 'latest'." << endl
<< " --only <n> Equivalent to --export-from n --export-to n." << endl
<< " -f,--force-mining Mine even when there are no transaction to mine (Default: off)" << endl
<< " -h,--help Show this help message and exit." << endl
<< " -i,--interactive Enter interactive mode (default: non-interactive)." << endl
<< " -I,--import <file> Import file as a concatenated series of blocks and exit." << endl
#if ETH_JSONRPC
<< " -j,--json-rpc Enable JSON-RPC server (default: off)." << endl
<< " --json-rpc-port Specify JSON-RPC server port (implies '-j', default: " << SensibleHttpPort << ")." << endl
@ -198,41 +205,87 @@ enum class NodeMode
Full
};
void doInitDAG(unsigned _n)
{
BlockInfo bi;
bi.number = _n;
cout << "Initializing DAG for epoch beginning #" << (bi.number / 30000 * 30000) << " (seedhash " << bi.seedHash().abridged() << "). This will take a while." << endl;
Ethasher::get()->full(bi);
exit(0);
}
enum class OperationMode
{
Node,
Import,
Export,
DAGInit
};
enum class Format
{
Binary,
Hex,
Human
};
int main(int argc, char** argv)
{
string listenIP;
unsigned short listenPort = 30303;
string publicIP;
string remoteHost;
unsigned short remotePort = 30303;
// Init defaults
Defaults::get();
/// Operating mode.
OperationMode mode = OperationMode::Node;
string dbPath;
unsigned mining = ~(unsigned)0;
NodeMode mode = NodeMode::Full;
unsigned peers = 5;
int miners = -1;
/// File name for import/export.
string filename;
/// Hashes/numbers for export range.
string exportFrom = "1";
string exportTo = "latest";
Format exportFormat = Format::Binary;
/// DAG initialisation param.
unsigned initDAG = 0;
/// General params for Node operation
NodeMode nodeMode = NodeMode::Full;
bool interactive = false;
#if ETH_JSONRPC
int jsonrpc = -1;
#endif
bool bootstrap = false;
bool upnp = true;
bool forceMining = false;
WithExisting killChain = WithExisting::Trust;
bool jit = false;
/// Networking params.
string clientName;
string listenIP;
unsigned short listenPort = 30303;
string publicIP;
string remoteHost;
unsigned short remotePort = 30303;
unsigned peers = 5;
bool bootstrap = false;
/// Mining params
unsigned mining = ~(unsigned)0;
int miners = -1;
bool forceMining = false;
bool turboMining = false;
KeyPair us = KeyPair::create();
Address coinbase = us.address();
/// Structured logging params
bool structuredLogging = false;
string structuredLoggingFormat = "%Y-%m-%dT%H:%M:%S";
string clientName;
/// Transaction params
TransactionPriority priority = TransactionPriority::Medium;
double etherPrice = 30.679;
double blockFees = 15.0;
// Init defaults
Defaults::get();
// Our address.
KeyPair us = KeyPair::create();
Address coinbase = us.address();
string configFile = getDataDir() + "/config.rlp";
bytes b = contents(configFile);
if (b.size())
@ -241,12 +294,6 @@ int main(int argc, char** argv)
us = KeyPair(config[0].toHash<Secret>());
coinbase = config[1].toHash<Address>();
}
else
{
RLPStream config(2);
config << us.secret() << coinbase;
writeFile(configFile, config.out());
}
for (int i = 1; i < argc; ++i)
{
@ -261,6 +308,37 @@ int main(int argc, char** argv)
remoteHost = argv[++i];
else if ((arg == "-p" || arg == "--port") && i + 1 < argc)
remotePort = (short)atoi(argv[++i]);
else if ((arg == "-I" || arg == "--import") && i + 1 < argc)
{
mode = OperationMode::Import;
filename = argv[++i];
}
else if ((arg == "-E" || arg == "--export") && i + 1 < argc)
{
mode = OperationMode::Export;
filename = argv[++i];
}
else if (arg == "--format" && i + 1 < argc)
{
string m = argv[++i];
if (m == "binary")
exportFormat = Format::Binary;
else if (m == "hex")
exportFormat = Format::Hex;
else if (m == "human")
exportFormat = Format::Human;
else
{
cerr << "Bad " << arg << " option: " << m << endl;
return -1;
}
}
else if (arg == "--to" && i + 1 < argc)
exportTo = argv[++i];
else if (arg == "--from" && i + 1 < argc)
exportFrom = argv[++i];
else if (arg == "--only" && i + 1 < argc)
exportTo = exportFrom = argv[++i];
else if ((arg == "-n" || arg == "--upnp") && i + 1 < argc)
{
string m = argv[++i];
@ -270,7 +348,7 @@ int main(int argc, char** argv)
upnp = false;
else
{
cerr << "Invalid -n/--upnp option: " << m << endl;
cerr << "Bad " << arg << " option: " << m << endl;
return -1;
}
}
@ -287,14 +365,13 @@ int main(int argc, char** argv)
}
catch (BadHexCharacter& _e)
{
cwarn << "invalid hex character, coinbase rejected";
cwarn << boost::diagnostic_information(_e);
break;
cerr << "Bad hex in " << arg << " option: " << argv[i] << endl;
return -1;
}
catch (...)
{
cwarn << "coinbase rejected";
break;
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
else if ((arg == "-s" || arg == "--secret") && i + 1 < argc)
us = KeyPair(h256(fromHex(argv[++i])));
@ -304,6 +381,25 @@ int main(int argc, char** argv)
structuredLogging = true;
else if ((arg == "-d" || arg == "--path" || arg == "--db-path") && i + 1 < argc)
dbPath = argv[++i];
else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc)
{
string m = boost::to_lower_copy(string(argv[++i]));
mode = OperationMode::DAGInit;
if (m == "next")
initDAG = PendingBlock;
else if (m == "this")
initDAG = LatestBlock;
else
try
{
initDAG = stol(m);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << m << endl;
return -1;
}
}
else if ((arg == "-B" || arg == "--block-fees") && i + 1 < argc)
{
try
@ -312,7 +408,7 @@ int main(int argc, char** argv)
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[++i] << endl;
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
}
@ -324,7 +420,7 @@ int main(int argc, char** argv)
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[++i] << endl;
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
}
@ -370,6 +466,8 @@ int main(int argc, char** argv)
bootstrap = true;
else if (arg == "-f" || arg == "--force-mining")
forceMining = true;
else if (arg == "-T" || arg == "--turbo-mining")
turboMining = true;
else if (arg == "-i" || arg == "--interactive")
interactive = true;
#if ETH_JSONRPC
@ -388,9 +486,9 @@ int main(int argc, char** argv)
{
string m = argv[++i];
if (m == "full")
mode = NodeMode::Full;
nodeMode = NodeMode::Full;
else if (m == "peer")
mode = NodeMode::PeerServer;
nodeMode = NodeMode::PeerServer;
else
{
cerr << "Unknown mode: " << m << endl;
@ -417,11 +515,20 @@ int main(int argc, char** argv)
}
}
{
RLPStream config(2);
config << us.secret() << coinbase;
writeFile(configFile, config.out());
}
// Two codepaths is necessary since named block require database, but numbered
// blocks are superuseful to have when database is already open in another process.
if (mode == OperationMode::DAGInit && !(initDAG == LatestBlock || initDAG == PendingBlock))
doInitDAG(initDAG);
if (!clientName.empty())
clientName += "/";
cout << credits();
StructuredLogger::get().initialize(structuredLogging, structuredLoggingFormat);
VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter);
auto netPrefs = publicIP.empty() ? NetworkPreferences(listenIP ,listenPort, upnp) : NetworkPreferences(publicIP, listenIP ,listenPort, upnp);
@ -431,19 +538,101 @@ int main(int argc, char** argv)
clientImplString,
dbPath,
killChain,
mode == NodeMode::Full ? set<string>{"eth", "shh"} : set<string>(),
nodeMode == NodeMode::Full ? set<string>{"eth", "shh"} : set<string>(),
netPrefs,
&nodesState,
miners
);
if (mode == OperationMode::DAGInit)
doInitDAG(web3.ethereum()->blockChain().number() + (initDAG == PendingBlock ? 30000 : 0));
auto toNumber = [&](string const& s) -> unsigned {
if (s == "latest")
return web3.ethereum()->number();
if (s.size() == 64 || (s.size() == 66 && s.substr(0, 2) == "0x"))
return web3.ethereum()->blockChain().number(h256(s));
try {
return stol(s);
}
catch (...)
{
cerr << "Bad block number/hash option: " << s << endl;
exit(-1);
}
};
if (mode == OperationMode::Export)
{
ofstream fout(filename, std::ofstream::binary);
ostream& out = (filename.empty() || filename == "--") ? cout : fout;
unsigned last = toNumber(exportTo);
for (unsigned i = toNumber(exportFrom); i <= last; ++i)
{
bytes block = web3.ethereum()->blockChain().block(web3.ethereum()->blockChain().numberHash(i));
switch (exportFormat)
{
case Format::Binary: out.write((char const*)block.data(), block.size()); break;
case Format::Hex: out << toHex(block) << endl; break;
case Format::Human: out << RLP(block) << endl; break;
default:;
}
}
return 0;
}
if (mode == OperationMode::Import)
{
ifstream fin(filename, std::ifstream::binary);
istream& in = (filename.empty() || filename == "--") ? cin : fin;
unsigned alreadyHave = 0;
unsigned good = 0;
unsigned futureTime = 0;
unsigned unknownParent = 0;
unsigned bad = 0;
while (in.peek() != -1)
{
bytes block(8);
in.read((char*)block.data(), 8);
block.resize(RLP(block, RLP::LaisezFaire).actualSize());
in.read((char*)block.data() + 8, block.size() - 8);
try
{
web3.ethereum()->injectBlock(block);
good++;
}
catch (AlreadyHaveBlock const&)
{
alreadyHave++;
}
catch (UnknownParent const&)
{
unknownParent++;
}
catch (FutureTime const&)
{
futureTime++;
}
catch (...)
{
bad++;
}
}
cout << (good + bad + futureTime + unknownParent + alreadyHave) << " total: " << good << " ok, " << alreadyHave << " got, " << futureTime << " future, " << unknownParent << " unknown parent, " << bad << " malformed." << endl;
return 0;
}
cout << credits();
web3.setIdealPeerCount(peers);
std::shared_ptr<eth::BasicGasPricer> gasPricer = make_shared<eth::BasicGasPricer>(u256(double(ether / 1000) / etherPrice), u256(blockFees * 1000));
eth::Client* c = mode == NodeMode::Full ? web3.ethereum() : nullptr;
eth::Client* c = nodeMode == NodeMode::Full ? web3.ethereum() : nullptr;
StructuredLogger::starting(clientImplString, dev::Version);
if (c)
{
c->setGasPricer(gasPricer);
c->setForceMining(forceMining);
c->setTurboMining(turboMining);
c->setAddress(coinbase);
}
@ -511,10 +700,9 @@ int main(int argc, char** argv)
}
else if (cmd == "connect")
{
string addr;
unsigned port;
iss >> addr >> port;
web3.addNode(p2p::NodeId(), addr + ":" + toString(port ? port : p2p::c_defaultIPPort));
string addrPort;
iss >> addrPort;
web3.addNode(p2p::NodeId(), addrPort);
}
else if (cmd == "netstop")
{
@ -654,7 +842,7 @@ int main(int argc, char** argv)
cnote << ssbd.str();
int ssize = sechex.length();
int size = hexAddr.length();
u256 minGas = (u256)Client::txGas(data, 0);
u256 minGas = (u256)Transaction::gasRequired(data, 0);
if (size < 40)
{
if (size > 0)
@ -733,7 +921,7 @@ int main(int argc, char** argv)
auto h = bc.currentHash();
auto blockData = bc.block(h);
BlockInfo info(blockData);
u256 minGas = (u256)Client::txGas(bytes(), 0);
u256 minGas = (u256)Transaction::gasRequired(bytes(), 0);
try
{
Address dest = h160(fromHex(hexAddr, WhenError::Throw));
@ -798,7 +986,7 @@ int main(int argc, char** argv)
cnote << "Init:";
cnote << ssc.str();
}
u256 minGas = (u256)Client::txGas(init, 0);
u256 minGas = (u256)Transaction::gasRequired(init, 0);
if (!init.size())
cwarn << "Contract creation aborted, no init code.";
else if (endowment < 0)

4
evmjit/libevmjit/ExecutionEngine.cpp

@ -88,10 +88,10 @@ void parseOptions()
//cl::ParseEnvironmentOptions("evmjit", "EVMJIT", "Ethereum EVM JIT Compiler");
// FIXME: LLVM workaround:
// Manually select instruction scheduler other than "source".
// Manually select instruction scheduler. Confirmed bad schedulers: source, list-burr, list-hybrid.
// "source" scheduler has a bug: http://llvm.org/bugs/show_bug.cgi?id=22304
auto envLine = std::getenv("EVMJIT");
auto commandLine = std::string{"evmjit "} + (envLine ? envLine : "") + " -pre-RA-sched=list-burr\0";
auto commandLine = std::string{"evmjit "} + (envLine ? envLine : "") + " -pre-RA-sched=list-ilp\0";
static const auto c_maxArgs = 20;
char const* argv[c_maxArgs] = {nullptr, };
auto arg = std::strtok(&*commandLine.begin(), " ");

18
exp/CMakeLists.txt

@ -10,8 +10,26 @@ set(EXECUTABLE exp)
add_executable(${EXECUTABLE} ${SRC_LIST})
target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARIES})
if (READLINE_FOUND)
target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARIES})
endif()
if (JSONRPC)
target_link_libraries(${EXECUTABLE} web3jsonrpc)
endif()
target_link_libraries(${EXECUTABLE} webthree)
target_link_libraries(${EXECUTABLE} ethereum)
target_link_libraries(${EXECUTABLE} p2p)
target_link_libraries(${EXECUTABLE} ethash-cl)
target_link_libraries(${EXECUTABLE} ethash)
target_link_libraries(${EXECUTABLE} OpenCL)
install( TARGETS ${EXECUTABLE} DESTINATION bin)

29
exp/main.cpp

@ -19,18 +19,25 @@
* @date 2014
* Ethereum client.
*/
#define __CL_ENABLE_EXCEPTIONS
#define CL_USE_DEPRECATED_OPENCL_2_0_APIS
#include "libethash-cl/cl.hpp"
#include <functional>
#include <libethereum/AccountDiff.h>
#include <libdevcore/RangeMask.h>
#include <libdevcore/Log.h>
#include <libdevcore/Common.h>
#include <libdevcore/CommonData.h>
#include <libdevcore/RLP.h>
#include <libdevcrypto/TrieDB.h>
#include <libdevcore/TransientDirectory.h>
#include <libdevcore/CommonIO.h>
#include <libdevcrypto/TrieDB.h>
#include <libp2p/All.h>
#include <libethereum/DownloadMan.h>
#include <libethcore/Ethasher.h>
#include <libethcore/ProofOfWork.h>
#include <libethereum/All.h>
#include <libethereum/AccountDiff.h>
#include <libethereum/DownloadMan.h>
#include <liblll/All.h>
#include <libwhisper/WhisperPeer.h>
#include <libwhisper/WhisperHost.h>
@ -101,6 +108,22 @@ int main()
#else
int main()
{
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
if (platforms.empty())
{
cdebug << "No OpenCL platforms found.";
return false;
}
EthashCL ecl;
BlockInfo genesis = CanonBlockChain::genesis();
TransientDirectory td;
std::pair<MineInfo, Ethash::Proof> r;
while (!r.first.completed)
r = ecl.mine(genesis, 1000);
EthashCL::assignResult(r.second, genesis);
assert(EthashCPU::verify(genesis));
return 0;
}
#endif

1
libdevcore/CMakeLists.txt

@ -28,6 +28,7 @@ endif()
target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES})
# transitive dependencies for windows executables

2
libdevcore/Common.cpp

@ -27,7 +27,7 @@ using namespace dev;
namespace dev
{
char const* Version = "0.9.5";
char const* Version = "0.9.6";
}

28
libdevcore/CommonData.h

@ -236,6 +236,34 @@ inline std::vector<_T>& operator+=(std::vector<typename std::enable_if<!std::is_
return _a;
}
/// Insert the contents of a container into a set
template <class T, class U> std::set<T>& operator+=(std::set<T>& _a, U const& _b)
{
for (auto const& i: _b)
_a.insert(i);
return _a;
}
/// Concatenate the contents of a container onto a vector
template <class T, class U> std::vector<T>& operator+=(std::vector<T>& _a, U const& _b)
{
for (auto const& i: _b)
_a.push_back(i);
return _a;
}
/// Insert the contents of a container into a set
template <class T, class U> std::set<T> operator+(std::set<T> _a, U const& _b)
{
return _a += _b;
}
/// Concatenate the contents of a container onto a vector
template <class T, class U> std::vector<T> operator+(std::vector<T> _a, U const& _b)
{
return _a += _b;
}
/// Concatenate two vectors of elements.
template <class _T>
inline std::vector<_T> operator+(std::vector<_T> const& _a, std::vector<_T> const& _b)

6
libdevcore/CommonIO.cpp

@ -58,7 +58,7 @@ string dev::memDump(bytes const& _bytes, unsigned _width, bool _html)
}
// Don't forget to delete[] later.
bytesRef dev::contentsNew(std::string const& _file)
bytesRef dev::contentsNew(std::string const& _file, bytesRef _dest)
{
std::ifstream is(_file, std::ifstream::binary);
if (!is)
@ -68,8 +68,10 @@ bytesRef dev::contentsNew(std::string const& _file)
streamoff length = is.tellg();
if (length == 0) // return early, MSVC does not like reading 0 bytes
return bytesRef();
if (!_dest.empty() && _dest.size() != (unsigned)length)
return bytesRef();
is.seekg (0, is.beg);
bytesRef ret(new byte[length], length);
bytesRef ret = _dest.empty() ? bytesRef(new byte[length], length) : _dest;
is.read((char*)ret.data(), length);
is.close();
return ret;

2
libdevcore/CommonIO.h

@ -46,7 +46,7 @@ namespace dev
bytes contents(std::string const& _file);
std::string contentsString(std::string const& _file);
/// Retrieve and returns the allocated contents of the given file. If the file doesn't exist or isn't readable, returns nullptr. Don't forget to delete [] when finished.
bytesRef contentsNew(std::string const& _file);
bytesRef contentsNew(std::string const& _file, bytesRef _dest = bytesRef());
/// Write the given binary data into the given file, replacing the file if it pre-exists.
void writeFile(std::string const& _file, bytesConstRef _data);

2
libdevcore/Log.cpp

@ -43,7 +43,7 @@ void dev::simpleDebugOut(std::string const& _s, char const*)
static Mutex s_lock;
Guard l(s_lock);
cout << _s << endl << flush;
cerr << _s << endl << flush;
// helpful to use OutputDebugString on windows
#ifdef _WIN32

2
libdevcore/RLP.cpp

@ -107,7 +107,7 @@ unsigned RLP::actualSize() const
if (isSingleByte())
return 1;
if (isData() || isList())
return payload().data() - m_data.data() + length();
return payloadOffset() + length();
return 0;
}

5
libdevcore/RLP.h

@ -290,7 +290,7 @@ public:
RLPs toList() const;
/// @returns the data payload. Valid for all types.
bytesConstRef payload() const { return isSingleByte() ? m_data.cropped(0, 1) : m_data.cropped(1 + lengthSize()); }
bytesConstRef payload() const { return m_data.cropped(payloadOffset()); }
/// @returns the theoretical size of this item.
/// @note Under normal circumstances, is equivalent to m_data.size() - use that unless you know it won't work.
@ -309,6 +309,9 @@ private:
/// @returns the size in bytes of the payload, as given by the RLP as opposed to as inferred from m_data.
unsigned length() const;
/// @returns the number of bytes into the data that the payload starts.
unsigned payloadOffset() const { return isSingleByte() ? 0 : (1 + lengthSize()); }
/// @returns the number of data items.
unsigned items() const;

1
libdevcore/RangeMask.h

@ -25,6 +25,7 @@
#include <utility>
#include <vector>
#include <iostream>
#include <assert.h>
namespace dev
{

4
libtestutils/TransientDirectory.cpp → libdevcore/TransientDirectory.cpp

@ -20,11 +20,11 @@
*/
#include <boost/filesystem.hpp>
#include <libdevcore/Exceptions.h>
#include "Exceptions.h"
#include "TransientDirectory.h"
#include "CommonIO.h"
using namespace std;
using namespace dev;
using namespace dev::test;
TransientDirectory::TransientDirectory():
TransientDirectory((boost::filesystem::temp_directory_path() / "eth_transient" / toString(FixedHash<4>::random())).string())

4
libtestutils/TransientDirectory.h → libdevcore/TransientDirectory.h

@ -22,12 +22,9 @@
#pragma once
#include <string>
#include "Common.h"
namespace dev
{
namespace test
{
/**
* @brief temporary directory implementation
@ -48,4 +45,3 @@ private:
};
}
}

12
libdevcore/Worker.cpp

@ -29,11 +29,11 @@ using namespace dev;
void Worker::startWorking()
{
cdebug << "startWorking for thread" << m_name;
cnote << "startWorking for thread" << m_name;
Guard l(x_work);
if (m_work)
return;
cdebug << "Spawning" << m_name;
cnote << "Spawning" << m_name;
m_stop = false;
m_work.reset(new thread([&]()
{
@ -45,21 +45,21 @@ void Worker::startWorking()
this_thread::sleep_for(chrono::milliseconds(m_idleWaitMs));
doWork();
}
cdebug << "Finishing up worker thread";
cnote << "Finishing up worker thread";
doneWorking();
}));
}
void Worker::stopWorking()
{
cdebug << "stopWorking for thread" << m_name;
cnote << "stopWorking for thread" << m_name;
Guard l(x_work);
if (!m_work)
return;
cdebug << "Stopping" << m_name;
cnote << "Stopping" << m_name;
m_stop = true;
m_work->join();
m_work.reset();
cdebug << "Stopped" << m_name;
cnote << "Stopped" << m_name;
}

6
libdevcrypto/Common.cpp

@ -37,9 +37,9 @@ static Secp256k1 s_secp256k1;
bool dev::SignatureStruct::isValid() const
{
if (this->v > 1 ||
this->r >= h256("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141") ||
this->s >= h256("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"))
if (v > 1 ||
r >= h256("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141") ||
s >= h256("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"))
return false;
return true;
}

6
libdevcrypto/TrieDB.h

@ -161,9 +161,15 @@ public:
}
}
std::string at(bytes const& _key) const { return at(&_key); }
std::string at(bytesConstRef _key) const;
void insert(bytes const& _key, bytes const& _value) { insert(&_key, &_value); }
void insert(bytesConstRef _key, bytes const& _value) { insert(_key, &_value); }
void insert(bytes const& _key, bytesConstRef _value) { insert(&_key, _value); }
void insert(bytesConstRef _key, bytesConstRef _value);
void remove(bytes const& _key) { remove(&_key); }
void remove(bytesConstRef _key);
bool contains(bytes const& _key) { return contains(&_key); }
bool contains(bytesConstRef _key) { return !at(_key).empty(); }
class iterator

2
libethash/util.h

@ -29,7 +29,7 @@ extern "C" {
#ifdef _MSC_VER
void debugf(const char *str, ...);
#else
#define debugf printf
#define debugf(...) fprintf(stderr, __VA_ARGS__)
#endif
static inline uint32_t min_u32(uint32_t a, uint32_t b)

30
libethcore/BlockInfo.cpp

@ -40,7 +40,7 @@ BlockInfo::BlockInfo(bytesConstRef _block, Strictness _s, h256 const& _h)
populate(_block, _s, _h);
}
void BlockInfo::setEmpty()
void BlockInfo::clear()
{
parentHash = h256();
sha3Uncles = EmptyListSHA3;
@ -105,8 +105,9 @@ h256 BlockInfo::headerHash(bytesConstRef _block)
void BlockInfo::populateFromHeader(RLP const& _header, Strictness _s, h256 const& _h)
{
// m_hash = dev::sha3(_header.data());
m_hash = _h;
if (_h)
assert(_h == dev::sha3(_header.data()));
m_seedHash = h256();
int field = 0;
@ -172,13 +173,21 @@ void BlockInfo::populate(bytesConstRef _block, Strictness _s, h256 const& _h)
BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("block uncles need to be a list") << BadFieldError(2, root[2].data().toString()));
}
template <class T, class U> h256 trieRootOver(unsigned _itemCount, T const& _getKey, U const& _getValue)
{
MemoryDB db;
GenericTrieDB<MemoryDB> t(&db);
t.init();
for (unsigned i = 0; i < _itemCount; ++i)
t.insert(_getKey(i), _getValue(i));
return t.root();
}
void BlockInfo::verifyInternals(bytesConstRef _block) const
{
RLP root(_block);
u256 mgp = (u256)-1;
OverlayDB db;
/*OverlayDB db;
GenericTrieDB<OverlayDB> t(&db);
t.init();
unsigned i = 0;
@ -186,12 +195,13 @@ void BlockInfo::verifyInternals(bytesConstRef _block) const
{
bytes k = rlp(i);
t.insert(&k, tr.data());
u256 gasprice = tr[1].toInt<u256>();
mgp = min(mgp, gasprice); // the minimum gas price is not used for anything //TODO delete?
++i;
}
if (transactionsRoot != t.root())
BOOST_THROW_EXCEPTION(InvalidTransactionsHash() << HashMismatchError(t.root(), transactionsRoot));
if (transactionsRoot != t.root())*/
auto txList = root[1];
auto expectedRoot = trieRootOver(txList.itemCount(), [&](unsigned i){ return rlp(i); }, [&](unsigned i){ return txList[i].data(); });
if (transactionsRoot != expectedRoot)
BOOST_THROW_EXCEPTION(InvalidTransactionsHash() << HashMismatchError(expectedRoot, transactionsRoot));
if (sha3Uncles != sha3(root[2].data()))
BOOST_THROW_EXCEPTION(InvalidUnclesHash());
@ -199,7 +209,7 @@ void BlockInfo::verifyInternals(bytesConstRef _block) const
void BlockInfo::populateFromParent(BlockInfo const& _parent)
{
m_hash = m_seedHash = h256();
noteDirty();
stateRoot = _parent.stateRoot;
parentHash = _parent.hash();
number = _parent.number + 1;

4
libethcore/BlockInfo.h

@ -116,9 +116,9 @@ public:
}
bool operator!=(BlockInfo const& _cmp) const { return !operator==(_cmp); }
void setEmpty();
void clear();
void noteDirty() const { m_hash = m_seedHash= h256(); }
void noteDirty() const { m_hash = m_seedHash = h256(); }
void populateFromHeader(RLP const& _header, Strictness _s = IgnoreNonce, h256 const& _h = h256());
void populate(bytesConstRef _block, Strictness _s = IgnoreNonce, h256 const& _h = h256());

17
libethcore/CommonJS.cpp

@ -65,5 +65,22 @@ std::string prettyU256(u256 _n, bool _abridged)
return s.str();
}
namespace eth
{
BlockNumber jsToBlockNumber(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);
}
}
}

3
libethcore/CommonJS.h

@ -67,5 +67,8 @@ struct TransactionSkeleton
u256 gasPrice;
};
/// Convert to a block number, a bit like jsToInt, except that it correctly recognises "pending" and "latest".
BlockNumber jsToBlockNumber(std::string const& _js);
}
}

38
libethcore/Ethasher.cpp

@ -123,6 +123,44 @@ ethash_params Ethasher::params(BlockInfo const& _header)
return params((unsigned)_header.number);
}
void Ethasher::readFull(BlockInfo const& _header, void* _dest)
{
if (!m_fulls.count(_header.seedHash()))
{
// @memoryleak @bug place it on a pile for deletion - perhaps use shared_ptr.
/* if (!m_fulls.empty())
{
delete [] m_fulls.begin()->second.data();
m_fulls.erase(m_fulls.begin());
}*/
try {
boost::filesystem::create_directories(getDataDir("ethash"));
} catch (...) {}
auto info = rlpList(c_ethashRevision, _header.seedHash());
std::string oldMemoFile = getDataDir("ethash") + "/full";
std::string memoFile = getDataDir("ethash") + "/full-R" + toString(c_ethashRevision) + "-" + toHex(_header.seedHash().ref().cropped(0, 8));
if (boost::filesystem::exists(oldMemoFile) && contents(oldMemoFile + ".info") == info)
{
// memofile valid - rename.
boost::filesystem::rename(oldMemoFile, memoFile);
}
IGNORE_EXCEPTIONS(boost::filesystem::remove(oldMemoFile));
IGNORE_EXCEPTIONS(boost::filesystem::remove(oldMemoFile + ".info"));
ethash_params p = params((unsigned)_header.number);
bytesRef r = contentsNew(memoFile, bytesRef((byte*)_dest, p.full_size));
if (!r)
{
auto c = light(_header);
ethash_prep_full(_dest, &p, c);
writeFile(memoFile, bytesConstRef((byte*)_dest, p.full_size));
}
}
}
ethash_params Ethasher::params(unsigned _n)
{
ethash_params p;

2
libethcore/Ethasher.h

@ -56,6 +56,8 @@ public:
static ethash_params params(BlockInfo const& _header);
static ethash_params params(unsigned _n);
void readFull(BlockInfo const& _header, void* _dest);
struct Result
{
h256 value;

1
libethcore/Exceptions.h

@ -38,6 +38,7 @@ using errinfo_difficulty = boost::error_info<struct tag_difficulty, u256>;
using BadFieldError = boost::tuple<errinfo_field, errinfo_data>;
struct DatabaseAlreadyOpen: virtual dev::Exception {};
struct OutOfGasBase: virtual dev::Exception {};
struct NotEnoughAvailableSpace: virtual dev::Exception {};
struct NotEnoughCash: virtual dev::Exception {};
struct GasPriceTooLow: virtual dev::Exception {};

1
libethcore/Params.cpp

@ -46,7 +46,6 @@ u256 const c_sha3WordGas = 6;
u256 const c_sloadGas = 50;
u256 const c_sstoreSetGas = 20000;
u256 const c_sstoreResetGas = 5000;
u256 const c_sstoreClearGas = 5000;
u256 const c_sstoreRefundGas = 15000;
u256 const c_jumpdestGas = 1;
u256 const c_logGas = 375;

3
libethcore/Params.h

@ -48,8 +48,7 @@ extern u256 const c_sha3WordGas; ///< Once per word of the SHA3 operation's da
extern u256 const c_copyGas; ///< Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added.
extern u256 const c_sloadGas; ///< Once per SLOAD operation.
extern u256 const c_sstoreSetGas; ///< Once per SSTORE operation if the zeroness changes from zero.
extern u256 const c_sstoreResetGas; ///< Once per SSTORE operation if the zeroness doesn't change.
extern u256 const c_sstoreClearGas; ///< Once per SSTORE operation if the zeroness changes to zero.
extern u256 const c_sstoreResetGas; ///< Once per SSTORE operation if the zeroness does not change from zero. NOTE: when c_sstoreSetGas does not apply.
extern u256 const c_sstoreRefundGas; ///< Refunded gas, once per SSTORE operation if the zeroness changes to zero.
extern u256 const c_jumpdestGas; ///< Once per JUMPDEST operation.
extern u256 const c_logGas; ///< Per LOG* operation.

117
libethcore/ProofOfWork.cpp

@ -33,32 +33,6 @@
#include <libdevcore/Common.h>
#if ETH_ETHASHCL
#include <libethash-cl/ethash_cl_miner.h>
#define ETHASH_REVISION REVISION
#define ETHASH_DATASET_BYTES_INIT DATASET_BYTES_INIT
#define ETHASH_DATASET_BYTES_GROWTH DATASET_BYTES_GROWTH
#define ETHASH_CACHE_BYTES_INIT CACHE_BYTES_INIT
#define ETHASH_CACHE_BYTES_GROWTH CACHE_BYTES_GROWTH
#define ETHASH_DAGSIZE_BYTES_INIT DAGSIZE_BYTES_INIT
#define ETHASH_DAG_GROWTH DAG_GROWTH
#define ETHASH_EPOCH_LENGTH EPOCH_LENGTH
#define ETHASH_MIX_BYTES MIX_BYTES
#define ETHASH_HASH_BYTES HASH_BYTES
#define ETHASH_DATASET_PARENTS DATASET_PARENTS
#define ETHASH_CACHE_ROUNDS CACHE_ROUNDS
#define ETHASH_ACCESSES ACCESSES
#undef REVISION
#undef DATASET_BYTES_INIT
#undef DATASET_BYTES_GROWTH
#undef CACHE_BYTES_INIT
#undef CACHE_BYTES_GROWTH
#undef DAGSIZE_BYTES_INIT
#undef DAG_GROWTH
#undef EPOCH_LENGTH
#undef MIX_BYTES
#undef HASH_BYTES
#undef DATASET_PARENTS
#undef CACHE_ROUNDS
#undef ACCESSES
#endif
#include "BlockInfo.h"
#include "Ethasher.h"
@ -131,16 +105,16 @@ std::pair<MineInfo, EthashCPU::Proof> EthashCPU::mine(BlockInfo const& _header,
#if ETH_ETHASHCL
/*
struct ethash_cl_search_hook
{
// reports progress, return true to abort
virtual bool found(uint64_t const* nonces, uint32_t count) = 0;
virtual bool searched(uint64_t start_nonce, uint32_t count) = 0;
};
class ethash_cl_miner
{
public:
struct search_hook
{
// reports progress, return true to abort
virtual bool found(uint64_t const* nonces, uint32_t count) = 0;
virtual bool searched(uint64_t start_nonce, uint32_t count) = 0;
};
ethash_cl_miner();
bool init(ethash_params const& params, const uint8_t seed[32], unsigned workgroup_size = 64);
@ -150,58 +124,63 @@ public:
};
*/
struct EthashCLHook: public ethash_cl_search_hook
struct EthashCLHook: public ethash_cl_miner::search_hook
{
virtual bool found(uint64_t const* _nonces, uint32_t _count)
void abort()
{
if (m_aborted)
return;
m_abort = true;
for (unsigned timeout = 0; timeout < 100 && !m_aborted; ++timeout)
std::this_thread::sleep_for(chrono::milliseconds(30));
if (!m_aborted)
cwarn << "Couldn't abort. Abandoning OpenCL process.";
m_aborted = m_abort = false;
m_found.clear();
}
vector<Nonce> fetchFound() { vector<Nonce> ret; Guard l(x_all); std::swap(ret, m_found); return ret; }
uint64_t fetchTotal() { Guard l(x_all); auto ret = m_total; m_total = 0; return ret; }
protected:
virtual bool found(uint64_t const* _nonces, uint32_t _count) override
{
Guard l(x_all);
for (unsigned i = 0; i < _count; ++i)
found.push_back((Nonce)(u64)_nonces[i]);
if (abort)
{
aborted = true;
return true;
}
return false;
m_found.push_back((Nonce)(u64)_nonces[i]);
m_aborted = true;
return true;
}
virtual bool searched(uint64_t _startNonce, uint32_t _count)
virtual bool searched(uint64_t _startNonce, uint32_t _count) override
{
Guard l(x_all);
total += _count;
last = _startNonce + _count;
if (abort)
m_total += _count;
m_last = _startNonce + _count;
if (m_abort)
{
aborted = true;
m_aborted = true;
return true;
}
return false;
}
vector<Nonce> fetchFound() { vector<Nonce> ret; Guard l(x_all); std::swap(ret, found); return ret; }
uint64_t fetchTotal() { Guard l(x_all); auto ret = total; total = 0; return ret; }
private:
Mutex x_all;
vector<Nonce> found;
uint64_t total;
uint64_t last;
bool abort = false;
bool aborted = false;
vector<Nonce> m_found;
uint64_t m_total;
uint64_t m_last;
bool m_abort = false;
bool m_aborted = true;
};
EthashCL::EthashCL():
m_miner(new ethash_cl_miner),
m_hook(new EthashCLHook)
{
}
EthashCL::~EthashCL()
{
m_hook->abort = true;
for (unsigned timeout = 0; timeout < 100 && !m_hook->aborted; ++timeout)
std::this_thread::sleep_for(chrono::milliseconds(30));
if (!m_hook->aborted)
cwarn << "Couldn't abort. Abandoning OpenCL process.";
}
bool EthashCL::verify(BlockInfo const& _header)
@ -211,13 +190,16 @@ bool EthashCL::verify(BlockInfo const& _header)
std::pair<MineInfo, Ethash::Proof> EthashCL::mine(BlockInfo const& _header, unsigned _msTimeout, bool, bool)
{
if (m_lastHeader.seedHash() != _header.seedHash())
if (!m_lastHeader || m_lastHeader.seedHash() != _header.seedHash())
{
m_miner->init(Ethasher::params(_header), _header.seedHash().data());
// TODO: reinit probably won't work when seed changes.
if (m_miner)
m_hook->abort();
m_miner.reset(new ethash_cl_miner);
m_miner->init(Ethasher::params(_header), [&](void* d){ Ethasher::get()->readFull(_header, d); });
}
if (m_lastHeader != _header)
{
m_hook->abort();
static std::random_device s_eng;
uint64_t tryNonce = (uint64_t)(u64)(m_last = Nonce::random(s_eng));
m_miner->search(_header.headerHash(WithoutNonce).data(), tryNonce, *m_hook);
@ -228,10 +210,11 @@ std::pair<MineInfo, Ethash::Proof> EthashCL::mine(BlockInfo const& _header, unsi
auto found = m_hook->fetchFound();
if (!found.empty())
{
h256 mixHash; // ?????
return std::make_pair(MineInfo{0.0, 1e99, 0, true}, EthashCL::Proof((Nonce)(u64)found[0], mixHash));
Nonce n = (Nonce)(u64)found[0];
auto result = Ethasher::eval(_header, n);
return std::make_pair(MineInfo(true), EthashCL::Proof{n, result.mixHash});
}
return std::make_pair(MineInfo{0.0, 1e99, 0, false}, EthashCL::Proof());
return std::make_pair(MineInfo(false), EthashCL::Proof());
}
#endif

6
libethcore/ProofOfWork.h

@ -42,6 +42,8 @@ namespace eth
struct MineInfo
{
MineInfo() = default;
MineInfo(bool _completed): completed(_completed) {}
void combine(MineInfo const& _m) { requirement = std::max(requirement, _m.requirement); best = std::min(best, _m.best); hashes += _m.hashes; completed = completed || _m.completed; }
double requirement = 0;
double best = 1e99;
@ -67,6 +69,8 @@ protected:
};
#if ETH_ETHASHCL
class EthashCLHook;
class EthashCL
{
public:
@ -88,7 +92,7 @@ protected:
BlockInfo m_lastHeader;
Nonce m_mined;
std::unique_ptr<ethash_cl_miner> m_miner;
std::unique_ptr<ethash_cl_search_hook> m_hook;
std::unique_ptr<EthashCLHook> m_hook;
};
using Ethash = EthashCL;

83
libethereum/BlockChain.cpp

@ -68,20 +68,6 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, BlockChain const& _bc)
return _out;
}
ldb::Slice dev::eth::oldToSlice(h256 const& _h, unsigned _sub)
{
#if ALL_COMPILERS_ARE_CPP11_COMPLIANT
static thread_local h256 h = _h ^ sha3(h256(u256(_sub)));
return ldb::Slice((char const*)&h, 32);
#else
static boost::thread_specific_ptr<h256> t_h;
if (!t_h.get())
t_h.reset(new h256);
*t_h = _h ^ sha3(h256(u256(_sub)));
return ldb::Slice((char const*)t_h.get(), 32);
#endif
}
ldb::Slice dev::eth::toSlice(h256 const& _h, unsigned _sub)
{
#if ALL_COMPILERS_ARE_CPP11_COMPLIANT
@ -254,7 +240,7 @@ void BlockChain::rebuild(std::string const& _path, std::function<void(unsigned,
return;
}
lastHash = bi.hash();
import(b, s.db(), true);
import(b, s.db(), Aversion::ImportOldBlocks);
}
catch (...)
{
@ -348,7 +334,7 @@ tuple<h256s, h256s, bool> BlockChain::sync(BlockQueue& _bq, OverlayDB const& _st
return make_tuple(fresh, dead, _bq.doneDrain(badBlocks));
}
pair<h256s, h256> BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, bool _force) noexcept
pair<h256s, h256> BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, Aversion _force) noexcept
{
try
{
@ -361,7 +347,7 @@ pair<h256s, h256> BlockChain::attemptImport(bytes const& _block, OverlayDB const
}
}
pair<h256s, h256> BlockChain::import(bytes const& _block, OverlayDB const& _db, bool _force)
pair<h256s, h256> BlockChain::import(bytes const& _block, OverlayDB const& _db, Aversion _force)
{
//@tidy This is a behemoth of a method - could do to be split into a few smaller ones.
@ -398,19 +384,18 @@ pair<h256s, h256> BlockChain::import(bytes const& _block, OverlayDB const& _db,
throw;
}
#endif
auto newHash = BlockInfo::headerHash(_block);
// Check block doesn't already exist first!
if (isKnown(newHash) && !_force)
if (isKnown(bi.hash()) && _force == Aversion::AvoidOldBlocks)
{
clog(BlockChainNote) << newHash << ": Not new.";
clog(BlockChainNote) << bi.hash() << ": Not new.";
BOOST_THROW_EXCEPTION(AlreadyHaveBlock());
}
// Work out its number as the parent's number + 1
if (!isKnown(bi.parentHash))
{
clog(BlockChainNote) << newHash << ": Unknown parent " << bi.parentHash;
clog(BlockChainNote) << bi.hash() << ": Unknown parent " << bi.parentHash;
// We don't know the parent (yet) - discard for now. It'll get resent to us if we find out about its ancestry later on.
BOOST_THROW_EXCEPTION(UnknownParent());
}
@ -427,12 +412,12 @@ pair<h256s, h256> BlockChain::import(bytes const& _block, OverlayDB const& _db,
// Check it's not crazy
if (bi.timestamp > (u256)time(0))
{
clog(BlockChainNote) << newHash << ": Future time " << bi.timestamp << " (now at " << time(0) << ")";
clog(BlockChainNote) << bi.hash() << ": Future time " << bi.timestamp << " (now at " << time(0) << ")";
// Block has a timestamp in the future. This is no good.
BOOST_THROW_EXCEPTION(FutureTime());
}
clog(BlockChainNote) << "Attempting import of " << newHash.abridged() << "...";
clog(BlockChainNote) << "Attempting import of " << bi.hash().abridged() << "...";
#if ETH_TIMED_IMPORTS
preliminaryChecks = t.elapsed();
@ -477,16 +462,16 @@ pair<h256s, h256> BlockChain::import(bytes const& _block, OverlayDB const& _db,
details(bi.parentHash);
WriteGuard l(x_details);
m_details[newHash] = BlockDetails((unsigned)pd.number + 1, td, bi.parentHash, {});
m_details[bi.parentHash].children.push_back(newHash);
m_details[bi.hash()] = BlockDetails((unsigned)pd.number + 1, td, bi.parentHash, {});
m_details[bi.parentHash].children.push_back(bi.hash());
}
{
WriteGuard l(x_logBlooms);
m_logBlooms[newHash] = blb;
m_logBlooms[bi.hash()] = blb;
}
{
WriteGuard l(x_receipts);
m_receipts[newHash] = br;
m_receipts[bi.hash()] = br;
}
#if ETH_TIMED_IMPORTS
@ -498,11 +483,11 @@ pair<h256s, h256> BlockChain::import(bytes const& _block, OverlayDB const& _db,
ReadGuard l2(x_details);
ReadGuard l4(x_receipts);
ReadGuard l5(x_logBlooms);
m_blocksDB->Put(m_writeOptions, toSlice(newHash), (ldb::Slice)ref(_block));
m_extrasDB->Put(m_writeOptions, toSlice(newHash, ExtraDetails), (ldb::Slice)dev::ref(m_details[newHash].rlp()));
m_blocksDB->Put(m_writeOptions, toSlice(bi.hash()), (ldb::Slice)ref(_block));
m_extrasDB->Put(m_writeOptions, toSlice(bi.hash(), ExtraDetails), (ldb::Slice)dev::ref(m_details[bi.hash()].rlp()));
m_extrasDB->Put(m_writeOptions, toSlice(bi.parentHash, ExtraDetails), (ldb::Slice)dev::ref(m_details[bi.parentHash].rlp()));
m_extrasDB->Put(m_writeOptions, toSlice(newHash, ExtraLogBlooms), (ldb::Slice)dev::ref(m_logBlooms[newHash].rlp()));
m_extrasDB->Put(m_writeOptions, toSlice(newHash, ExtraReceipts), (ldb::Slice)dev::ref(m_receipts[newHash].rlp()));
m_extrasDB->Put(m_writeOptions, toSlice(bi.hash(), ExtraLogBlooms), (ldb::Slice)dev::ref(m_logBlooms[bi.hash()].rlp()));
m_extrasDB->Put(m_writeOptions, toSlice(bi.hash(), ExtraReceipts), (ldb::Slice)dev::ref(m_receipts[bi.hash()].rlp()));
}
#if ETH_TIMED_IMPORTS
@ -549,13 +534,13 @@ pair<h256s, h256> BlockChain::import(bytes const& _block, OverlayDB const& _db,
if (td > details(last).totalDifficulty)
{
unsigned commonIndex;
tie(route, common, commonIndex) = treeRoute(last, newHash);
tie(route, common, commonIndex) = treeRoute(last, bi.hash());
{
WriteGuard l(x_lastBlockHash);
m_lastBlockHash = newHash;
m_lastBlockHash = bi.hash();
}
m_extrasDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&newHash, 32));
m_extrasDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&(bi.hash()), 32));
// Most of the time these two will be equal - only when we're doing a chain revert will they not be
if (common != last)
@ -988,41 +973,11 @@ bytes BlockChain::block(h256 const& _hash) const
return bytes();
}
WriteGuard l(x_blocks);
m_blocks[_hash].resize(d.size());
memcpy(m_blocks[_hash].data(), d.data(), d.size());
noteUsed(_hash);
return m_blocks[_hash];
}
bytes BlockChain::oldBlock(h256 const& _hash) const
{
if (_hash == m_genesisHash)
return m_genesisBlock;
{
ReadGuard l(x_blocks);
auto it = m_blocks.find(_hash);
if (it != m_blocks.end())
return it->second;
}
string d;
m_blocksDB->Get(m_readOptions, oldToSlice(_hash), &d);
if (!d.size())
{
cwarn << "Couldn't find requested block:" << _hash.abridged();
return bytes();
}
WriteGuard l(x_blocks);
m_blocks[_hash].resize(d.size());
memcpy(m_blocks[_hash].data(), d.data(), d.size());
noteUsed(_hash);
return m_blocks[_hash];
}

36
libethereum/BlockChain.h

@ -64,7 +64,6 @@ struct BlockChainWarn: public LogChannel { static const char* name() { return "=
std::map<Address, Account> const& genesisState();
ldb::Slice toSlice(h256 const& _h, unsigned _sub = 0);
ldb::Slice oldToSlice(h256 const& _h, unsigned _sub = 0);
using BlocksHash = std::map<h256, bytes>;
using TransactionHashes = h256s;
@ -81,10 +80,15 @@ enum {
using ProgressCallback = std::function<void(unsigned, unsigned)>;
enum class Aversion
{
AvoidOldBlocks,
ImportOldBlocks
};
/**
* @brief Implements the blockchain database. All data this gives is disk-backed.
* @threadsafe
* @todo Make not memory hog (should actually act as a cache and deallocate old entries).
*/
class BlockChain
{
@ -104,11 +108,11 @@ public:
/// Attempt to import the given block directly into the CanonBlockChain and sync with the state DB.
/// @returns the block hashes of any blocks that came into/went out of the canonical block chain.
std::pair<h256s, h256> attemptImport(bytes const& _block, OverlayDB const& _stateDB, bool _force = false) noexcept;
std::pair<h256s, h256> attemptImport(bytes const& _block, OverlayDB const& _stateDB, Aversion _force = Aversion::AvoidOldBlocks) noexcept;
/// Import block into disk-backed DB
/// @returns the block hashes of any blocks that came into/went out of the canonical block chain.
std::pair<h256s, h256> import(bytes const& _block, OverlayDB const& _stateDB, bool _force = false);
std::pair<h256s, h256> import(bytes const& _block, OverlayDB const& _stateDB, Aversion _force = Aversion::AvoidOldBlocks);
/// Returns true if the given block is known (though not necessarily a part of the canon chain).
bool isKnown(h256 const& _hash) const;
@ -274,30 +278,6 @@ private:
return ret.first->second;
}
template<class T, unsigned N> T oldQueryExtras(h256 const& _h, std::map<h256, T>& _m, boost::shared_mutex& _x, T const& _n, ldb::DB* _extrasDB = nullptr) const
{
{
ReadGuard l(_x);
auto it = _m.find(_h);
if (it != _m.end())
return it->second;
}
std::string s;
(_extrasDB ? _extrasDB : m_extrasDB)->Get(m_readOptions, oldToSlice(_h, N), &s);
if (s.empty())
{
// cout << "Not found in DB: " << _h << endl;
return _n;
}
noteUsed(_h, N);
WriteGuard l(_x);
auto ret = _m.insert(std::make_pair(_h, T(RLP(s))));
return ret.first->second;
}
void checkConsistency();
/// The caches of the disk DB and their locks.

8
libethereum/BlockQueue.cpp

@ -107,14 +107,6 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc)
}
}
namespace dev {
template <class T, class U> std::set<T>& operator+=(std::set<T>& _a, U const& _b)
{
for (auto const& i: _b)
_a.insert(i);
return _a;
} }
bool BlockQueue::doneDrain(h256s const& _bad)
{
WriteGuard l(m_lock);

7
libethereum/CMakeLists.txt

@ -25,19 +25,18 @@ else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARIES})
target_link_libraries(${EXECUTABLE} evm)
target_link_libraries(${EXECUTABLE} lll)
target_link_libraries(${EXECUTABLE} whisper)
target_link_libraries(${EXECUTABLE} p2p)
target_link_libraries(${EXECUTABLE} devcrypto)
target_link_libraries(${EXECUTABLE} ethcore)
target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARIES})
target_link_libraries(${EXECUTABLE} secp256k1)
if (ETHASHCL)
target_link_libraries(${EXECUTABLE} ethash-cl)
target_link_libraries(${EXECUTABLE} OpenCL)
endif ()
if (CMAKE_COMPILER_IS_MINGW)

13
libethereum/Client.cpp

@ -94,7 +94,7 @@ void BasicGasPricer::update(BlockChain const& _bc)
for (unsigned i = 0; i < r[1].size(); ++i)
{
auto gu = brs.receipts[i].gasUsed();
dist[Transaction(r[1][i].data(), CheckSignature::None).gasPrice()] += (unsigned)brs.receipts[i].gasUsed();
dist[Transaction(r[1][i].data(), CheckTransaction::None).gasPrice()] += (unsigned)brs.receipts[i].gasUsed();
total += (unsigned)gu;
}
}
@ -334,6 +334,7 @@ void Client::setMiningThreads(unsigned _threads)
{
stopMining();
#if ETH_ETHASHCL
(void)_threads;
unsigned t = 1;
#else
auto t = _threads ? _threads : thread::hardware_concurrency();
@ -397,7 +398,7 @@ void Client::setupState(State& _s)
_s.commitToMine(m_bc);
}
ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256 _value, u256 _gasPrice)
ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256 _value, u256 _gasPrice, Address const& _from)
{
ExecutionResult ret;
try
@ -407,10 +408,10 @@ ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256
{
ReadGuard l(x_stateDB);
temp = m_postMine;
temp.addBalance(Address(), _value + _gasPrice * _gas);
temp.addBalance(_from, _value + _gasPrice * _gas);
}
Executive e(temp, LastHashes(), 0);
if (!e.call(_dest, _dest, Address(), _value, _gasPrice, &_data, _gas, Address()))
if (!e.call(_dest, _dest, _from, _value, _gasPrice, &_data, _gas, _from))
e.go();
ret = e.executionResult();
}
@ -511,7 +512,7 @@ void Client::doWork()
clog(ClientNote) << "Dead block:" << h.abridged();
for (auto const& t: m_bc.transactions(h))
{
clog(ClientNote) << "Resubmitting transaction " << Transaction(t, CheckSignature::None);
clog(ClientNote) << "Resubmitting transaction " << Transaction(t, CheckTransaction::None);
m_tq.import(t);
}
}
@ -519,7 +520,7 @@ void Client::doWork()
// remove transactions from m_tq nicely rather than relying on out of date nonce later on.
for (auto const& h: fresh)
{
clog(ClientChat) << "Mined block:" << h.abridged();
clog(ClientChat) << "Live block:" << h.abridged();
for (auto const& th: m_bc.transactionHashes(h))
{
clog(ClientNote) << "Safely dropping transaction " << th;

3
libethereum/Client.h

@ -159,7 +159,7 @@ public:
using Interface::call; // to remove warning about hiding virtual function
/// 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);
ExecutionResult call(Address _dest, bytes const& _data = bytes(), u256 _gas = 125000, u256 _value = 0, u256 _gasPrice = 1 * ether, Address const& _from = Address());
/// Get the remaining gas limit in this block.
virtual u256 gasLimitRemaining() const { return m_postMine.gasLimitRemaining(); }
@ -229,6 +229,7 @@ public:
protected:
/// InterfaceStub methods
virtual BlockChain& bc() override { return m_bc; }
virtual BlockChain const& bc() const override { return m_bc; }
/// Returns the state object for the full block (i.e. the terminal state) for index _h.

44
libethereum/ClientBase.cpp

@ -65,14 +65,17 @@ Address ClientBase::submitTransaction(Secret _secret, u256 _endowment, bytes con
}
// TODO: remove try/catch, allow exceptions
ExecutionResult ClientBase::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber)
ExecutionResult ClientBase::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff)
{
ExecutionResult ret;
try
{
State temp = asOf(_blockNumber);
u256 n = temp.transactionsFrom(toAddress(_secret));
Address a = toAddress(_secret);
u256 n = temp.transactionsFrom(a);
Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret);
if (_ff == FudgeFactor::Lenient)
temp.addBalance(a, (u256)(t.gas() * t.gasPrice() + t.value()));
ret = temp.execute(bc().lastHashes(), t, Permanence::Reverted);
}
catch (...)
@ -82,16 +85,19 @@ ExecutionResult ClientBase::call(Secret _secret, u256 _value, Address _dest, byt
return ret;
}
ExecutionResult ClientBase::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber)
ExecutionResult ClientBase::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff)
{
ExecutionResult ret;
try
{
State temp = asOf(_blockNumber);
u256 n = temp.transactionsFrom(toAddress(_secret));
Address a = toAddress(_secret);
u256 n = temp.transactionsFrom(a);
// cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret));
Transaction t(_value, _gasPrice, _gas, _data, n, _secret);
if (_ff == FudgeFactor::Lenient)
temp.addBalance(a, (u256)(t.gasRequired() * t.gasPrice() + t.value()));
ret = temp.execute(bc().lastHashes(), t, Permanence::Reverted);
}
catch (...)
@ -101,6 +107,11 @@ ExecutionResult ClientBase::create(Secret _secret, u256 _value, bytes const& _da
return ret;
}
void ClientBase::injectBlock(bytes const& _block)
{
bc().import(_block, preMine().db());
}
u256 ClientBase::balanceAt(Address _a, BlockNumber _block) const
{
return asOf(_block).balance(_a);
@ -285,11 +296,6 @@ LocalisedLogEntries ClientBase::checkWatch(unsigned _watchId)
return ret;
}
h256 ClientBase::hashFromNumber(unsigned _number) const
{
return bc().numberHash(_number);
}
BlockInfo ClientBase::blockInfo(h256 _hash) const
{
return BlockInfo(bc().block(_hash));
@ -302,7 +308,7 @@ BlockDetails ClientBase::blockDetails(h256 _hash) const
Transaction ClientBase::transaction(h256 _transactionHash) const
{
return Transaction(bc().transaction(_transactionHash), CheckSignature::Range);
return Transaction(bc().transaction(_transactionHash), CheckTransaction::Cheap);
}
Transaction ClientBase::transaction(h256 _blockHash, unsigned _i) const
@ -310,7 +316,7 @@ Transaction ClientBase::transaction(h256 _blockHash, unsigned _i) const
auto bl = bc().block(_blockHash);
RLP b(bl);
if (_i < b[1].itemCount())
return Transaction(b[1][_i].data(), CheckSignature::Range);
return Transaction(b[1][_i].data(), CheckTransaction::Cheap);
else
return Transaction();
}
@ -321,7 +327,7 @@ Transactions ClientBase::transactions(h256 _blockHash) const
RLP b(bl);
Transactions res;
for (unsigned i = 0; i < b[1].itemCount(); i++)
res.emplace_back(b[1][i].data(), CheckSignature::Range);
res.emplace_back(b[1][i].data(), CheckTransaction::Cheap);
return res;
}
@ -369,6 +375,11 @@ Transactions ClientBase::pending() const
return postMine().pending();
}
h256s ClientBase::pendingHashes() const
{
return h256s() + postMine().pendingHashes();
}
StateDiff ClientBase::diff(unsigned _txi, h256 _block) const
{
@ -399,3 +410,12 @@ Address ClientBase::address() const
{
return preMine().address();
}
h256 ClientBase::hashFromNumber(BlockNumber _number) const
{
if (_number == PendingBlock)
return h256();
if (_number == LatestBlock)
return bc().currentHash();
return bc().numberHash(_number);
}

14
libethereum/ClientBase.h

@ -63,7 +63,7 @@ struct WatchChannel: public LogChannel { static const char* name() { return "(o)
#define cwatch dev::LogOutputStream<dev::eth::WatchChannel, true>()
struct WorkInChannel: public LogChannel { static const char* name() { return ">W>"; } static const int verbosity = 16; };
struct WorkOutChannel: public LogChannel { static const char* name() { return "<W<"; } static const int verbosity = 16; };
struct WorkChannel: public LogChannel { static const char* name() { return "-W-"; } static const int verbosity = 16; };
struct WorkChannel: public LogChannel { static const char* name() { return "-W-"; } static const int verbosity = 21; };
#define cwork dev::LogOutputStream<dev::eth::WorkChannel, true>()
#define cworkin dev::LogOutputStream<dev::eth::WorkInChannel, true>()
#define cworkout dev::LogOutputStream<dev::eth::WorkOutChannel, true>()
@ -82,9 +82,10 @@ public:
virtual Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = 10 * szabo) 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, BlockNumber _blockNumber = PendingBlock) override;
virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock, FudgeFactor _ff = FudgeFactor::Strict) 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 create. Nothing is recorded into the state.
virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock, FudgeFactor _ff = FudgeFactor::Strict) override;
using Interface::balanceAt;
using Interface::countAt;
@ -108,8 +109,7 @@ public:
virtual LocalisedLogEntries peekWatch(unsigned _watchId) const override;
virtual LocalisedLogEntries checkWatch(unsigned _watchId) override;
// TODO: switch all the _blockHash arguments to also accept _blockNumber
virtual h256 hashFromNumber(unsigned _number) const override;
virtual h256 hashFromNumber(BlockNumber _number) const override;
virtual eth::BlockInfo blockInfo(h256 _hash) const override;
virtual eth::BlockDetails blockDetails(h256 _hash) const override;
virtual eth::Transaction transaction(h256 _transactionHash) const override;
@ -122,6 +122,9 @@ public:
virtual unsigned uncleCount(h256 _blockHash) const override;
virtual unsigned number() const override;
virtual eth::Transactions pending() const override;
virtual h256s pendingHashes() const override;
void injectBlock(bytes const& _block);
using Interface::diff;
virtual StateDiff diff(unsigned _txi, h256 _block) const override;
@ -153,6 +156,7 @@ public:
protected:
/// The interface that must be implemented in any class deriving this.
/// {
virtual BlockChain& bc() = 0;
virtual BlockChain const& bc() const = 0;
virtual State asOf(h256 const& _h) const = 0;
virtual State preMine() const = 0;

5
libethereum/EthereumHost.cpp

@ -191,6 +191,8 @@ void EthereumHost::maintainTransactions()
for (auto const& p: randomSelection(25, [&](EthereumPeer* p) { return p->m_requireTransactions || (unsent && !p->m_knownTransactions.count(i.first)); }))
peerTransactions[p].push_back(i.first);
}
for (auto const& t: ts)
m_transactionsSent.insert(t.first);
for (auto p: peerSessions())
if (auto ep = p.first->cap<EthereumPeer>())
{
@ -198,11 +200,10 @@ void EthereumHost::maintainTransactions()
unsigned n = 0;
for (auto const& h: peerTransactions[ep])
{
ep->m_knownTransactions.insert(h);
b += ts[h].rlp();
++n;
}
for (auto const& t: ts)
m_transactionsSent.insert(t.first);
ep->clearKnownTransactions();

4
libethereum/EthereumPeer.cpp

@ -334,7 +334,7 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
case GetTransactionsPacket: break; // DEPRECATED.
case TransactionsPacket:
{
clogS(NetMessageSummary) << "Transactions (" << dec << _r.itemCount() << "entries)";
clogS(NetAllDetail) << "Transactions (" << dec << _r.itemCount() << "entries)";
Guard l(x_knownTransactions);
for (unsigned i = 0; i < _r.itemCount(); ++i)
{
@ -348,11 +348,11 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
break;
case ImportResult::AlreadyKnown:
// if we already had the transaction, then don't bother sending it on.
host()->m_transactionsSent.insert(h);
addRating(0);
break;
case ImportResult::Success:
addRating(100);
host()->m_transactionsSent.insert(h);
break;
default:;
}

13
libethereum/Executive.cpp

@ -31,8 +31,6 @@ using namespace std;
using namespace dev;
using namespace dev::eth;
#define ETH_VMTRACE 1
Executive::Executive(State& _s, BlockChain const& _bc, unsigned _level):
m_s(_s),
m_lastHashes(_bc.lastHashes((unsigned)_s.info().number - 1)),
@ -69,12 +67,11 @@ void Executive::initialize(Transaction const& _transaction)
}
// Check gas cost is enough.
m_gasRequired = Interface::txGas(m_t.data());
if (m_t.gas() < m_gasRequired)
if (!m_t.checkPayment())
{
clog(StateDetail) << "Not enough gas to pay for the transaction: Require >" << m_gasRequired << " Got" << m_t.gas();
clog(StateDetail) << "Not enough gas to pay for the transaction: Require >" << m_t.gasRequired() << " Got" << m_t.gas();
m_excepted = TransactionException::OutOfGas;
BOOST_THROW_EXCEPTION(OutOfGas() << RequirementError((bigint)m_gasRequired, (bigint)m_t.gas()));
BOOST_THROW_EXCEPTION(OutOfGasBase() << RequirementError(m_t.gasRequired(), (bigint)m_t.gas()));
}
// Avoid invalid transactions.
@ -119,9 +116,9 @@ bool Executive::execute()
m_s.subBalance(m_t.sender(), m_gasCost);
if (m_t.isCreation())
return create(m_t.sender(), m_t.value(), m_t.gasPrice(), m_t.gas() - (u256)m_gasRequired, &m_t.data(), m_t.sender());
return create(m_t.sender(), m_t.value(), m_t.gasPrice(), m_t.gas() - (u256)m_t.gasRequired(), &m_t.data(), m_t.sender());
else
return call(m_t.receiveAddress(), m_t.receiveAddress(), m_t.sender(), m_t.value(), m_t.gasPrice(), bytesConstRef(&m_t.data()), m_t.gas() - (u256)m_gasRequired, m_t.sender());
return call(m_t.receiveAddress(), m_t.receiveAddress(), m_t.sender(), m_t.value(), m_t.gasPrice(), bytesConstRef(&m_t.data()), m_t.gas() - (u256)m_t.gasRequired(), m_t.sender());
}
bool Executive::call(Address _receiveAddress, Address _codeAddress, Address _senderAddress, u256 _value, u256 _gasPrice, bytesConstRef _data, u256 _gas, Address _originAddress)

2
libethereum/Executive.h

@ -71,7 +71,7 @@ public:
void operator=(Executive) = delete;
/// Initializes the executive for evaluating a transaction. You must call finalize() at some point following this.
void initialize(bytesConstRef _transaction) { initialize(Transaction(_transaction, CheckSignature::None)); }
void initialize(bytesConstRef _transaction) { initialize(Transaction(_transaction, CheckTransaction::None)); }
void initialize(Transaction const& _transaction);
/// Finalise a transaction previously set up with initialize().
/// @warning Only valid after initialize() and execute(), and possibly go().

33
libethereum/Interface.h

@ -46,6 +46,12 @@ enum class Reaping
Manual
};
enum class FudgeFactor
{
Strict,
Lenient
};
/**
* @brief Main API hub for interfacing with Ethereum.
*/
@ -71,13 +77,13 @@ 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, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) = 0;
ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo) { return call(_secret, _value, _dest, _data, _gas, _gasPrice, m_default); }
virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) = 0;
ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, FudgeFactor _ff = FudgeFactor::Strict) { return call(_secret, _value, _dest, _data, _gas, _gasPrice, m_default, _ff); }
/// 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, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) = 0;
ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo) { return create(_secret, _value, _data, _gas, _gasPrice, m_default); }
virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) = 0;
ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, FudgeFactor _ff = FudgeFactor::Strict) { return create(_secret, _value, _data, _gas, _gasPrice, m_default, _ff); }
// [STATE-QUERY API]
@ -112,10 +118,11 @@ public:
// [BLOCK QUERY API]
virtual h256 hashFromNumber(unsigned _number) const = 0;
virtual Transaction transaction(h256 _transactionHash) const = 0;
virtual h256 hashFromNumber(BlockNumber _number) const = 0;
virtual BlockInfo blockInfo(h256 _hash) const = 0;
virtual BlockDetails blockDetails(h256 _hash) const = 0;
virtual Transaction transaction(h256 _transactionHash) const = 0;
virtual Transaction transaction(h256 _blockHash, unsigned _i) const = 0;
virtual BlockInfo uncle(h256 _blockHash, unsigned _i) const = 0;
virtual UncleHashes uncleHashes(h256 _blockHash) const = 0;
@ -124,6 +131,16 @@ public:
virtual Transactions transactions(h256 _blockHash) const = 0;
virtual TransactionHashes transactionHashes(h256 _blockHash) const = 0;
BlockInfo blockInfo(BlockNumber _block) const { return blockInfo(hashFromNumber(_block)); }
BlockDetails blockDetails(BlockNumber _block) const { return blockDetails(hashFromNumber(_block)); }
Transaction transaction(BlockNumber _block, unsigned _i) const { if (_block == PendingBlock) { auto p = pending(); return _i < p.size() ? p[_i] : Transaction(); } return transaction(hashFromNumber(_block)); }
unsigned transactionCount(BlockNumber _block) const { if (_block == PendingBlock) { auto p = pending(); return p.size(); } return transactionCount(hashFromNumber(_block)); }
Transactions transactions(BlockNumber _block) const { if (_block == PendingBlock) return pending(); return transactions(hashFromNumber(_block)); }
TransactionHashes transactionHashes(BlockNumber _block) const { if (_block == PendingBlock) return pendingHashes(); return transactionHashes(hashFromNumber(_block)); }
BlockInfo uncle(BlockNumber _block, unsigned _i) const { return uncle(hashFromNumber(_block), _i); }
UncleHashes uncleHashes(BlockNumber _block) const { return uncleHashes(hashFromNumber(_block)); }
unsigned uncleCount(BlockNumber _block) const { return uncleCount(hashFromNumber(_block)); }
// [EXTRA API]:
/// @returns The height of the chain.
@ -132,6 +149,7 @@ public:
/// Get a map containing each of the pending transactions.
/// @TODO: Remove in favour of transactions().
virtual Transactions pending() const = 0;
virtual h256s pendingHashes() const = 0;
/// Differences between transactions.
StateDiff diff(unsigned _txi) const { return diff(_txi, m_default); }
@ -143,9 +161,6 @@ public:
virtual Addresses addresses() const { return addresses(m_default); }
virtual Addresses addresses(BlockNumber _block) const = 0;
/// Get the fee associated for a transaction with the given data.
template <class T> 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; }
/// Get the remaining gas limit in this block.
virtual u256 gasLimitRemaining() const = 0;

30
libethereum/State.cpp

@ -99,7 +99,7 @@ State::State(OverlayDB const& _db, BaseState _bs, Address _coinbaseAddress):
m_previousBlock = CanonBlockChain::genesis();
}
else
m_previousBlock.setEmpty();
m_previousBlock.clear();
resetCurrent();
@ -190,6 +190,8 @@ State& State::operator=(State const& _s)
m_blockReward = _s.m_blockReward;
m_lastTx = _s.m_lastTx;
paranoia("after state cloning (assignment op)", true);
m_committedToMine = false;
return *this;
}
@ -276,8 +278,8 @@ bool State::sync(BlockChain const& _bc, h256 _block, BlockInfo const& _bi)
{
bool ret = false;
// BLOCK
BlockInfo bi = _bi;
if (!bi)
BlockInfo bi = _bi ? _bi : _bc.info(_block);
/* if (!bi)
while (1)
{
try
@ -299,7 +301,7 @@ bool State::sync(BlockChain const& _bc, h256 _block, BlockInfo const& _bi)
cerr << "ERROR: Corrupt block-chain! Delete your block-chain DB and restart." << endl;
cerr << _e.what() << endl;
}
}
}*/
if (bi == m_currentBlock)
{
// We mined the last block.
@ -364,7 +366,7 @@ u256 State::enactOn(bytesConstRef _block, BlockInfo const& _bi, BlockChain const
#endif
// Check family:
BlockInfo biParent(_bc.block(_bi.parentHash));
BlockInfo biParent = _bc.info(_bi.parentHash);
_bi.verifyParent(biParent);
#if ETH_TIMED_ENACTMENTS
@ -374,7 +376,7 @@ u256 State::enactOn(bytesConstRef _block, BlockInfo const& _bi, BlockChain const
BlockInfo biGrandParent;
if (biParent.number)
biGrandParent.populate(_bc.block(biParent.parentHash));
biGrandParent = _bc.info(biParent.parentHash);
#if ETH_TIMED_ENACTMENTS
populateGrand = t.elapsed();
@ -434,6 +436,8 @@ void State::resetCurrent()
m_lastTx = m_db;
m_state.setRoot(m_previousBlock.stateRoot);
m_committedToMine = false;
paranoia("begin resetCurrent", true);
}
@ -539,6 +543,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
// m_currentBlock is assumed to be prepopulated and reset.
BlockInfo bi(_block, _checkNonce ? CheckEverything : IgnoreNonce);
#if !ETH_RELEASE
assert(m_previousBlock.hash() == bi.parentHash);
assert(m_currentBlock.parentHash == bi.parentHash);
@ -551,6 +556,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
// Populate m_currentBlock with the correct values.
m_currentBlock = bi;
m_currentBlock.verifyInternals(_block);
m_currentBlock.noteDirty();
// cnote << "playback begins:" << m_state.root();
// cnote << m_state;
@ -574,7 +580,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
k << i;
transactionsTrie.insert(&k.out(), tr.data());
execute(lh, Transaction(tr.data(), CheckSignature::Sender));
execute(lh, Transaction(tr.data(), CheckTransaction::Everything));
RLPStream receiptrlp;
m_receipts.back().streamRLP(receiptrlp);
@ -646,6 +652,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
tdIncrease += uncle.difficulty;
rewarded.push_back(uncle);
}
applyRewards(rewarded);
// Commit all cached state changes to the state trie.
@ -687,6 +694,9 @@ void State::cleanup(bool _fullCommit)
paranoia("immediately after database commit", true);
m_previousBlock = m_currentBlock;
m_currentBlock.populateFromParent(m_previousBlock);
cdebug << "finalising enactment. current -> previous, hash is" << m_previousBlock.hash().abridged();
}
else
m_db.rollback();
@ -696,7 +706,7 @@ void State::cleanup(bool _fullCommit)
void State::uncommitToMine()
{
if (m_currentBlock.sha3Uncles)
if (m_committedToMine)
{
m_cache.clear();
if (!m_transactions.size())
@ -705,7 +715,7 @@ void State::uncommitToMine()
m_state.setRoot(m_receipts.back().stateRoot());
m_db = m_lastTx;
paranoia("Uncommited to mine", true);
m_currentBlock.sha3Uncles = h256();
m_committedToMine = false;
}
}
@ -842,6 +852,8 @@ void State::commitToMine(BlockChain const& _bc)
m_currentBlock.gasUsed = gasUsed();
m_currentBlock.stateRoot = m_state.root();
m_currentBlock.parentHash = m_previousBlock.hash();
m_committedToMine = true;
}
MineInfo State::mine(unsigned _msTimeout, bool _turbo)

5
libethereum/State.h

@ -138,6 +138,7 @@ public:
static OverlayDB openDB(std::string _path, WithExisting _we = WithExisting::Trust);
static OverlayDB openDB(WithExisting _we = WithExisting::Trust) { return openDB(std::string(), _we); }
OverlayDB const& db() const { return m_db; }
OverlayDB& db() { return m_db; }
/// @returns the set containing all addresses currently in use in Ethereum.
/// @throws InterfaceNotSupported if compiled without ETH_FATDB.
@ -274,6 +275,9 @@ public:
/// Get the list of pending transactions.
Transactions const& pending() const { return m_transactions; }
/// Get the list of hashes of pending transactions.
h256Set const& pendingHashes() const { return m_transactionSet; }
/// Get the transaction receipt for the transaction of the given index.
TransactionReceipt const& receipt(unsigned _i) const { return m_receipts[_i]; }
@ -360,6 +364,7 @@ private:
BlockInfo m_previousBlock; ///< The previous block's information.
BlockInfo m_currentBlock; ///< The current block's information.
bytes m_currentBytes; ///< The current block.
bool m_committedToMine = false; ///< Have we committed to mine on the present m_currentBlock?
bytes m_currentTxs; ///< The RLP-encoded block of transactions.
bytes m_currentUncles; ///< The RLP-encoded block of uncles.

16
libethereum/Transaction.cpp

@ -25,6 +25,7 @@
#include <libdevcrypto/Common.h>
#include <libethcore/Exceptions.h>
#include <libevm/VMFace.h>
#include "Interface.h"
#include "Transaction.h"
using namespace std;
using namespace dev;
@ -53,7 +54,7 @@ TransactionException dev::eth::toTransactionException(VMException const& _e)
return TransactionException::Unknown;
}
Transaction::Transaction(bytesConstRef _rlpData, CheckSignature _checkSig)
Transaction::Transaction(bytesConstRef _rlpData, CheckTransaction _checkSig)
{
int field = 0;
RLP rlp(_rlpData);
@ -81,9 +82,9 @@ Transaction::Transaction(bytesConstRef _rlpData, CheckSignature _checkSig)
BOOST_THROW_EXCEPTION(BadRLP() << errinfo_comment("to many fields in the transaction RLP"));
m_vrs = SignatureStruct{ r, s, v };
if (_checkSig >= CheckSignature::Range && !m_vrs.isValid())
if (_checkSig >= CheckTransaction::Cheap && !m_vrs.isValid())
BOOST_THROW_EXCEPTION(InvalidSignature());
if (_checkSig == CheckSignature::Sender)
if (_checkSig == CheckTransaction::Everything)
m_sender = sender();
}
catch (Exception& _e)
@ -91,6 +92,8 @@ Transaction::Transaction(bytesConstRef _rlpData, CheckSignature _checkSig)
_e << errinfo_name("invalid transaction format") << BadFieldError(field, toHex(rlp[field].data().toBytes()));
throw;
}
if (_checkSig >= CheckTransaction::Cheap && !checkPayment())
BOOST_THROW_EXCEPTION(OutOfGasBase() << RequirementError(gasRequired(), (bigint)gas()));
}
Address const& Transaction::safeSender() const noexcept
@ -118,6 +121,13 @@ Address const& Transaction::sender() const
return m_sender;
}
bigint Transaction::gasRequired() const
{
if (!m_gasRequired)
m_gasRequired = Transaction::gasRequired(m_data);
return m_gasRequired;
}
void Transaction::sign(Secret _priv)
{
auto sig = dev::sign(_priv, sha3(WithoutSignature));

48
libethereum/Transaction.h

@ -24,7 +24,7 @@
#include <libdevcore/RLP.h>
#include <libdevcrypto/SHA3.h>
#include <libethcore/Common.h>
#include <libethcore/Params.h>
namespace dev
{
namespace eth
@ -37,11 +37,11 @@ enum IncludeSignature
WithSignature = 1, ///< Do include a signature.
};
enum class CheckSignature
enum class CheckTransaction
{
None,
Range,
Sender
Cheap,
Everything
};
enum class TransactionException
@ -119,10 +119,10 @@ public:
Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, bytes const& _data): m_type(ContractCreation), m_value(_value), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) {}
/// Constructs a transaction from the given RLP.
explicit Transaction(bytesConstRef _rlp, CheckSignature _checkSig);
explicit Transaction(bytesConstRef _rlp, CheckTransaction _checkSig);
/// Constructs a transaction from the given RLP.
explicit Transaction(bytes const& _rlp, CheckSignature _checkSig): Transaction(&_rlp, _checkSig) {}
explicit Transaction(bytes const& _rlp, CheckTransaction _checkSig): Transaction(&_rlp, _checkSig) {}
/// Checks equality of transactions.
@ -178,27 +178,37 @@ public:
/// @returns the signature of the transaction. Encodes the sender.
SignatureStruct const& signature() const { return m_vrs; }
/// @returns true if the transaction contains enough gas for the basic payment.
bool checkPayment() const { return m_gas >= gasRequired(); }
/// @returns the gas required to run this transaction.
bigint gasRequired() const;
/// Get the fee associated for a transaction with the given data.
template <class T> static bigint gasRequired(T const& _data, u256 _gas = 0) { bigint ret = c_txGas + _gas; for (auto i: _data) ret += i ? c_txDataNonZeroGas : c_txDataZeroGas; return ret; }
private:
/// Type of transaction.
enum Type
{
NullTransaction, ///< Null transaction.
ContractCreation, ///< Transaction to create contracts - receiveAddress() is ignored.
MessageCall ///< Transaction to invoke a message call - receiveAddress() is used.
NullTransaction, ///< Null transaction.
ContractCreation, ///< Transaction to create contracts - receiveAddress() is ignored.
MessageCall ///< Transaction to invoke a message call - receiveAddress() is used.
};
void sign(Secret _priv); ///< Sign the transaction.
void sign(Secret _priv); ///< Sign the transaction.
Type m_type = NullTransaction; ///< Is this a contract-creation transaction or a message-call transaction?
u256 m_nonce; ///< The transaction-count of the sender.
u256 m_value; ///< The amount of ETH to be transferred by this transaction. Called 'endowment' for contract-creation transactions.
Address m_receiveAddress; ///< The receiving address of the transaction.
u256 m_gasPrice; ///< The base fee and thus the implied exchange rate of ETH to GAS.
u256 m_gas; ///< The total gas to convert, paid for from sender's account. Any unused gas gets refunded once the contract is ended.
bytes m_data; ///< The data associated with the transaction, or the initialiser if it's a creation transaction.
SignatureStruct m_vrs; ///< The signature of the transaction. Encodes the sender.
Type m_type = NullTransaction; ///< Is this a contract-creation transaction or a message-call transaction?
u256 m_nonce; ///< The transaction-count of the sender.
u256 m_value; ///< The amount of ETH to be transferred by this transaction. Called 'endowment' for contract-creation transactions.
Address m_receiveAddress; ///< The receiving address of the transaction.
u256 m_gasPrice; ///< The base fee and thus the implied exchange rate of ETH to GAS.
u256 m_gas; ///< The total gas to convert, paid for from sender's account. Any unused gas gets refunded once the contract is ended.
bytes m_data; ///< The data associated with the transaction, or the initialiser if it's a creation transaction.
SignatureStruct m_vrs; ///< The signature of the transaction. Encodes the sender.
mutable Address m_sender; ///< Cached sender, determined from signature.
mutable Address m_sender; ///< Cached sender, determined from signature.
mutable bigint m_gasRequired = 0; ///< Memoised amount required for the transaction to run.
};
/// Nice name for vector of Transaction.

8
libethereum/TransactionQueue.cpp

@ -44,21 +44,23 @@ ImportResult TransactionQueue::import(bytesConstRef _transactionRLP)
// Check validity of _transactionRLP as a transaction. To do this we just deserialise and attempt to determine the sender.
// If it doesn't work, the signature is bad.
// The transaction's nonce may yet be invalid (or, it could be "valid" but we may be missing a marginally older transaction).
Transaction t(_transactionRLP, CheckSignature::Sender);
Transaction t(_transactionRLP, CheckTransaction::Everything);
UpgradeGuard ul(l);
// If valid, append to blocks.
m_current[h] = t;
m_known.insert(h);
ctxq << "Queued vaguely legit-looking transaction" << h.abridged();
}
catch (Exception const& _e)
{
cwarn << "Ignoring invalid transaction: " << diagnostic_information(_e);
ctxq << "Ignoring invalid transaction: " << diagnostic_information(_e);
return ImportResult::Malformed;
}
catch (std::exception const& _e)
{
cwarn << "Ignoring invalid transaction: " << _e.what();
ctxq << "Ignoring invalid transaction: " << _e.what();
return ImportResult::Malformed;
}

3
libethereum/TransactionQueue.h

@ -24,6 +24,7 @@
#include <boost/thread.hpp>
#include <libdevcore/Common.h>
#include <libdevcore/Guards.h>
#include <libdevcore/Log.h>
#include "libethcore/Common.h"
#include "Transaction.h"
@ -34,6 +35,8 @@ namespace eth
class BlockChain;
struct TransactionQueueChannel: public LogChannel { static const char* name() { return "->Q"; } static const int verbosity = 4; };
#define ctxq dev::LogOutputStream<dev::eth::TransactionQueueChannel, true>()
/**
* @brief A queue of Transactions, each stored as RLP.

2
libevm/VM.cpp

@ -108,7 +108,7 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps)
runGas = c_sstoreSetGas;
else if (_ext.store(m_stack.back()) && !m_stack[m_stack.size() - 2])
{
runGas = c_sstoreClearGas;
runGas = c_sstoreResetGas;
_ext.sub.refunds += c_sstoreRefundGas;
}
else

2
libjsqrc/ethereumjs/.bowerrc

@ -1,5 +1,5 @@
{
"directory": "example/js/",
"directory": "bower",
"cwd": "./",
"analytics": false
}

1
libjsqrc/ethereumjs/.gitignore

@ -17,3 +17,4 @@ example/js
node_modules
bower_components
npm-debug.log
/bower

1
libjsqrc/ethereumjs/.travis.yml

@ -14,4 +14,5 @@ after_script:
- npm run-script build
- npm run-script karma
- npm run-script test-coveralls
- cd test/node && npm install && node app.js

8
libjsqrc/ethereumjs/README.md

@ -1,9 +1,11 @@
# Ethereum JavaScript API
[![Join the chat at https://gitter.im/ethereum/ethereum.js](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ethereum/ethereum.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
This is the Ethereum compatible [JavaScript API](https://github.com/ethereum/wiki/wiki/JavaScript-API)
which implements the [Generic JSON RPC](https://github.com/ethereum/wiki/wiki/JSON-RPC) spec. It's available on npm as a node module, for bower and component as an embeddable js and as a meteor.js package.
[![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![dependency status][dep-image]][dep-url] [![dev dependency status][dep-dev-image]][dep-dev-url][![Coverage Status][coveralls-image]][coveralls-url]
[![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![dependency status][dep-image]][dep-url] [![dev dependency status][dep-dev-image]][dep-dev-url][![Coverage Status][coveralls-image]][coveralls-url][![Stories in Ready][waffle-image]][waffle-url]
<!-- [![browser support](https://ci.testling.com/ethereum/ethereum.js.png)](https://ci.testling.com/ethereum/ethereum.js) -->
@ -36,7 +38,7 @@ Component
## Usage
Require the library (not required for the meteor package):
var web3 = require('web3');
var web3 = require('ethereum.js');
Set a provider (QtSyncProvider, HttpProvider)
@ -110,4 +112,6 @@ eth -j
[dep-dev-url]: https://david-dm.org/ethereum/ethereum.js#info=devDependencies
[coveralls-image]: https://coveralls.io/repos/ethereum/ethereum.js/badge.svg?branch=master
[coveralls-url]: https://coveralls.io/r/ethereum/ethereum.js?branch=master
[waffle-image]: https://badge.waffle.io/ethereum/ethereum.js.svg?label=ready&title=Ready
[waffle-url]: http://waffle.io/ethereum/ethereum.js

4
libjsqrc/ethereumjs/bower.json

@ -1,7 +1,7 @@
{
"name": "ethereum.js",
"name": "web3",
"namespace": "ethereum",
"version": "0.1.2",
"version": "0.2.5",
"description": "Ethereum Compatible JavaScript API",
"main": [
"./dist/ethereum.js",

57
libjsqrc/ethereumjs/dist/ethereum.js.map

File diff suppressed because one or more lines are too long

1
libjsqrc/ethereumjs/dist/ethereum.min.js

File diff suppressed because one or more lines are too long

1879
libjsqrc/ethereumjs/dist/ethereum.js → libjsqrc/ethereumjs/dist/web3-light.js

File diff suppressed because it is too large

69
libjsqrc/ethereumjs/dist/web3-light.js.map

File diff suppressed because one or more lines are too long

1
libjsqrc/ethereumjs/dist/web3-light.min.js

File diff suppressed because one or more lines are too long

5548
libjsqrc/ethereumjs/dist/web3.js

File diff suppressed because it is too large

69
libjsqrc/ethereumjs/dist/web3.js.map

File diff suppressed because one or more lines are too long

2
libjsqrc/ethereumjs/dist/web3.min.js

File diff suppressed because one or more lines are too long

4
libjsqrc/ethereumjs/example/balance.html

@ -2,8 +2,8 @@
<html>
<head>
<script type="text/javascript" src="js/bignumber.js/bignumber.min.js"></script>
<script type="text/javascript" src="../dist/ethereum.js"></script>
<script type="text/javascript" src="../node_modules/bignumber.js/bignumber.min.js"></script>
<script type="text/javascript" src="../dist/web3-light.js"></script>
<script type="text/javascript">
var web3 = require('web3');

153
libjsqrc/ethereumjs/example/coin.html

@ -0,0 +1,153 @@
<!doctype>
<html>
<title>JevCoin</title>
<head>
<script type="text/javascript" src="../dist/web3.js"></script>
</head>
<body>
<h1>JevCoin <code id="contract_addr"></code></h1>
<div>
<strong>Balance</strong>
<span id="balance"></strong>
</div>
<div>
<span>Address:</span>
<input type="text" id="address" style="width:200px">
<span>Amount:</span>
<input type="text" id="amount" style="width:200px">
<button onclick="transact()">Send</button>
<span id="message"></span>
</div>
<hr>
<table width="100%" id="table">
<tr><td style="width:40%;">Address</td><td>Balance</td></tr>
<tbody id="table_body"></tbody>
</table>
</body>
<script type="text/javascript">
var web3 = require('web3');
var eth = web3.eth;
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8080'));
var desc = [{
"name": "balance(address)",
"type": "function",
"inputs": [{
"name": "who",
"type": "address"
}],
"constant": true,
"outputs": [{
"name": "value",
"type": "uint256"
}]
}, {
"name": "send(address,uint256)",
"type": "function",
"inputs": [{
"name": "to",
"type": "address"
}, {
"name": "value",
"type": "uint256"
}],
"outputs": []
}, {
"name":"Changed",
"type":"event",
"inputs": [
{"name":"from","type":"address","indexed":true},
{"name":"amount","type":"uint256","indexed":true},
],
}];
var address = localStorage.getItem("address");
// deploy if not exist
if(address === null) {
var code = "0x60056013565b61014f8061003a6000396000f35b620f42406000600033600160a060020a0316815260200190815260200160002081905550560060e060020a600035048063d0679d3414610020578063e3d670d71461003457005b61002e600435602435610049565b60006000f35b61003f600435610129565b8060005260206000f35b806000600033600160a060020a03168152602001908152602001600020541061007157610076565b610125565b806000600033600160a060020a03168152602001908152602001600020908154039081905550806000600084600160a060020a031681526020019081526020016000209081540190819055508033600160a060020a03167fb52dda022b6c1a1f40905a85f257f689aa5d69d850e49cf939d688fbe5af594660006000a38082600160a060020a03167fb52dda022b6c1a1f40905a85f257f689aa5d69d850e49cf939d688fbe5af594660006000a35b5050565b60006000600083600160a060020a0316815260200190815260200160002054905091905056";
address = web3.eth.transact({from: eth.coinbase, data: code, gas: "1000000"});
localStorage.setItem("address", address);
}
document.querySelector("#contract_addr").innerHTML = address;
var Contract = web3.eth.contract(desc);
contract = new Contract(address);
contract.Changed({from: eth.accounts[0]}).changed(function() {
refresh();
});
function refresh() {
document.querySelector("#balance").innerHTML = contract.balance(eth.coinbase);
var table = document.querySelector("#table_body");
table.innerHTML = ""; // clear
/*var storage = eth.getStorage(address);*/
/*table.innerHTML = "";*/
/*for( var item in storage ) {*/
/*table.innerHTML += "<tr><td>"+item+"</td><td>"+web3.toDecimal(storage[item])+"</td></tr>";*/
/*}*/
}
function transact() {
var to = document.querySelector("#address");
if( to.value.length == 0 ) {
to = "0x4205b06c2cfa0e30359edcab94543266cb6fa1d3";
} else {
if (to.value.substr(0,2) != "0x")
to.value = "0x"+to.value;
}
var value = document.querySelector("#amount");
var amount = parseInt( value.value );
console.log("transact: ", to.value, " => ", amount)
contract.sendTransaction({from: eth.accounts[0]}).send( to.value, amount );
to.value = "";
value.value = "";
var message = document.querySelector("#message")
message.innerHTML = "Submitted";
setTimeout(function() {
message.innerHTML = "";
}, 1000);
}
refresh();
</script>
</html>
<!--
contract JevCoin {
function JevCoin()
{
balances[msg.sender] = 1000000;
}
event Changed(address indexed from, uint indexed amount);
function send(address to, uint value)
{
if( balances[msg.sender] < value ) return;
balances[msg.sender] -= value;
balances[to] += value;
Changed(msg.sender, value);
Changed(to, value);
}
function balance(address who) constant returns(uint t)
{
t = balances[who];
}
mapping(address => uint256) balances;
}
-!>

3
libjsqrc/ethereumjs/example/contract.html

@ -2,8 +2,7 @@
<html>
<head>
<script type="text/javascript" src="js/bignumber.js/bignumber.min.js"></script>
<script type="text/javascript" src="../dist/ethereum.js"></script>
<script type="text/javascript" src="../dist/web3"></script>
<script type="text/javascript">
var web3 = require('web3');

3
libjsqrc/ethereumjs/example/contract_with_array.html

@ -2,8 +2,7 @@
<html>
<head>
<script type="text/javascript" src="js/bignumber.js/bignumber.min.js"></script>
<script type="text/javascript" src="../dist/ethereum.js"></script>
<script type="text/javascript" src="../dist/web3.js"></script>
<script type="text/javascript">
var web3 = require('web3');

3
libjsqrc/ethereumjs/example/event.html

@ -1,8 +1,7 @@
<!doctype>
<html>
<head>
<script type="text/javascript" src="js/bignumber.js/bignumber.min.js"></script>
<script type="text/javascript" src="../dist/ethereum.js"></script>
<script type="text/javascript" src="../dist/web3.js"></script>
<script type="text/javascript">
var web3 = require('web3');
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8080'));

3
libjsqrc/ethereumjs/example/event_inc.html

@ -1,8 +1,7 @@
<!doctype>
<html>
<head>
<script type="text/javascript" src="js/bignumber.js/bignumber.min.js"></script>
<script type="text/javascript" src="../dist/ethereum.js"></script>
<script type="text/javascript" src="../dist/web3.js"></script>
<script type="text/javascript">
var web3 = require('web3');
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8080'));

3
libjsqrc/ethereumjs/example/natspec_contract.html

@ -2,8 +2,7 @@
<html>
<head>
<script type="text/javascript" src="js/bignumber.js/bignumber.min.js"></script>
<script type="text/javascript" src="../dist/ethereum.js"></script>
<script type="text/javascript" src="../dist/web3.js"></script>
<script type="text/javascript">
var web3 = require('web3');

34
libjsqrc/ethereumjs/gulpfile.js

@ -2,7 +2,7 @@
'use strict';
var version = require('./version.json');
var version = require('./lib/version.json');
var path = require('path');
var del = require('del');
@ -19,19 +19,23 @@ var replace = require('gulp-replace');
var DEST = './dist/';
var src = 'index';
var dst = 'ethereum';
var dst = 'web3';
var lightDst = 'web3-light';
var browserifyOptions = {
debug: true,
insert_global_vars: false, // jshint ignore:line
detectGlobals: false,
bundleExternal: false
bundleExternal: true
};
gulp.task('versionReplace', function(){
gulp.src(['./package.json'])
.pipe(replace(/\"version\"\: \"(.{5})\"/, '"version": "'+ version.version + '"'))
.pipe(gulp.dest('./'));
gulp.src(['./bower.json'])
.pipe(replace(/\"version\"\: \"(.{5})\"/, '"version": "'+ version.version + '"'))
.pipe(gulp.dest('./'));
gulp.src(['./package.js'])
.pipe(replace(/version\: \'(.{5})\'/, "version: '"+ version.version + "'"))
.pipe(gulp.dest('./'));
@ -54,10 +58,27 @@ gulp.task('lint', function(){
.pipe(jshint.reporter('default'));
});
gulp.task('build', ['clean'], function () {
gulp.task('buildLight', ['clean'], function () {
return browserify(browserifyOptions)
.require('./' + src + '.js', {expose: 'web3'})
.ignore('bignumber.js')
.require('./lib/utils/browser-bn.js', {expose: 'bignumber.js'}) // fake bignumber.js
.add('./' + src + '.js')
.bundle()
.pipe(exorcist(path.join( DEST, lightDst + '.js.map')))
.pipe(source(lightDst + '.js'))
.pipe(gulp.dest( DEST ))
.pipe(streamify(uglify()))
.pipe(rename(lightDst + '.min.js'))
.pipe(gulp.dest( DEST ));
});
gulp.task('buildStandalone', ['clean'], function () {
return browserify(browserifyOptions)
.require('./' + src + '.js', {expose: 'web3'})
.require('bignumber.js') // expose it to dapp users
.add('./' + src + '.js')
.ignore('crypto')
.bundle()
.pipe(exorcist(path.join( DEST, dst + '.js.map')))
.pipe(source(dst + '.js'))
@ -71,8 +92,9 @@ gulp.task('watch', function() {
gulp.watch(['./lib/*.js'], ['lint', 'build']);
});
gulp.task('dev', ['versionReplace','bower', 'lint', 'build']);
gulp.task('default', ['dev']);
gulp.task('light', ['versionReplace','bower', 'lint', 'buildLight']);
gulp.task('standalone', ['versionReplace','bower', 'lint', 'buildStandalone']);
gulp.task('default', ['light', 'standalone']);
gulp.task('version', ['versionReplace']);

9
libjsqrc/ethereumjs/index.js

@ -1,7 +1,14 @@
var web3 = require('./lib/web3');
// dont override global variable
if (typeof web3 !== 'undefined') {
var web3;
}
web3 = require('./lib/web3');
web3.providers.HttpProvider = require('./lib/web3/httpprovider');
web3.providers.QtSyncProvider = require('./lib/web3/qtsync');
web3.eth.contract = require('./lib/web3/contract');
web3.abi = require('./lib/solidity/abi');
module.exports = web3;

3
libjsqrc/ethereumjs/karma.conf.js

@ -22,8 +22,7 @@ module.exports = function (config) {
// list of files / patterns to load in the browser
files: [
'node_modules/bignumber.js/bignumber.js',
'test/*.js',
'test/*.js'
],

20
libjsqrc/ethereumjs/lib/solidity/formatters.js

@ -20,26 +20,10 @@
* @date 2015
*/
if (process.env.NODE_ENV !== 'build') {
var BigNumber = require('bignumber.js'); // jshint ignore:line
}
var BigNumber = require('bignumber.js');
var utils = require('../utils/utils');
var c = require('../utils/config');
/**
* Should be called to pad string to expected length
*
* @method padLeft
* @param {String} string to be padded
* @param {Number} characters that result string should have
* @param {String} sign, by default 0
* @returns {String} right aligned string
*/
var padLeft = function (string, chars, sign) {
return new Array(chars - string.length + 1).join(sign ? sign : "0") + string;
};
/**
* Formats input value to byte representation of int
* If value is negative, return it's two's complement
@ -52,7 +36,7 @@ var padLeft = function (string, chars, sign) {
var formatInputInt = function (value) {
var padding = c.ETH_PADDING * 2;
BigNumber.config(c.ETH_BIGNUMBER_ROUNDING_MODE);
return padLeft(utils.toTwosComplement(value).round().toString(16), padding);
return utils.padLeft(utils.toTwosComplement(value).round().toString(16), padding);
};
/**

4
libjsqrc/ethereumjs/lib/utils/browser-bn.js

@ -0,0 +1,4 @@
'use strict';
module.exports = BigNumber; // jshint ignore:line

9
libjsqrc/ethereumjs/lib/utils/browser-xhr.js

@ -0,0 +1,9 @@
'use strict';
// go env doesn't have and need XMLHttpRequest
if (typeof XMLHttpRequest === 'undefined') {
exports.XMLHttpRequest = {};
} else {
exports.XMLHttpRequest = XMLHttpRequest; // jshint ignore:line
}

4
libjsqrc/ethereumjs/lib/utils/config.js

@ -34,9 +34,7 @@
*/
/// required to define ETH_BIGNUMBER_ROUNDING_MODE
if (process.env.NODE_ENV !== 'build') {
var BigNumber = require('bignumber.js'); // jshint ignore:line
}
var BigNumber = require('bignumber.js');
var ETH_UNITS = [
'wei',

68
libjsqrc/ethereumjs/lib/utils/utils.js

@ -33,9 +33,7 @@
* @constructor
*/
if (process.env.NODE_ENV !== 'build') {
var BigNumber = require('bignumber.js'); // jshint ignore:line
}
var BigNumber = require('bignumber.js');
var unitMap = {
'wei': '1',
@ -56,6 +54,18 @@ var unitMap = {
'tether': '1000000000000000000000000000000'
};
/**
* Should be called to pad string to expected length
*
* @method padLeft
* @param {String} string to be padded
* @param {Number} characters that result string should have
* @param {String} sign, by default 0
* @returns {String} right aligned string
*/
var padLeft = function (string, chars, sign) {
return new Array(chars - string.length + 1).join(sign ? sign : "0") + string;
};
/** Finds first index of array element matching pattern
*
@ -214,13 +224,13 @@ var fromDecimal = function (value) {
var toHex = function (val) {
/*jshint maxcomplexity:7 */
if(isBoolean(val))
return val;
if (isBoolean(val))
return fromDecimal(+val);
if(isBigNumber(val))
if (isBigNumber(val))
return fromDecimal(val);
if(isObject(val))
if (isObject(val))
return fromAscii(JSON.stringify(val));
// if its a negative number, pass it through fromDecimal
@ -345,13 +355,27 @@ var toTwosComplement = function (number) {
* @param {String} address the given HEX adress
* @return {Boolean}
*/
var isAddress = function(address) {
if (!isString(address)) {
return false;
var isAddress = function (address) {
return /^0x[0-9a-f]{40}$/.test(address);
};
/**
* Transforms given string to valid 20 bytes-length addres with 0x prefix
*
* @method toAddress
* @param {String} address
* @return {String} formatted address
*/
var toAddress = function (address) {
if (isAddress(address)) {
return address;
}
return ((address.indexOf('0x') === 0 && address.length === 42) ||
(address.indexOf('0x') === -1 && address.length === 40));
if (/^[0-9a-f]{40}$/.test(address)) {
return '0x' + address;
}
return '0x' + padLeft(toHex(address).substr(2), 40);
};
/**
@ -422,7 +446,23 @@ var isArray = function (object) {
return object instanceof Array;
};
/**
* Returns true if given string is valid json object
*
* @method isJson
* @param {String}
* @return {Boolean}
*/
var isJson = function (str) {
try {
return !!JSON.parse(str);
} catch (e) {
return false;
}
};
module.exports = {
padLeft: padLeft,
findIndex: findIndex,
toHex: toHex,
toDecimal: toDecimal,
@ -437,12 +477,14 @@ module.exports = {
fromWei: fromWei,
toBigNumber: toBigNumber,
toTwosComplement: toTwosComplement,
toAddress: toAddress,
isBigNumber: isBigNumber,
isAddress: isAddress,
isFunction: isFunction,
isString: isString,
isObject: isObject,
isBoolean: isBoolean,
isArray: isArray
isArray: isArray,
isJson: isJson
};

3
libjsqrc/ethereumjs/lib/version.json

@ -0,0 +1,3 @@
{
"version": "0.2.5"
}

288
libjsqrc/ethereumjs/lib/web3.js

@ -24,79 +24,55 @@
* @date 2014
*/
var version = require('../version.json');
var version = require('./version.json');
var net = require('./web3/net');
var eth = require('./web3/eth');
var db = require('./web3/db');
var shh = require('./web3/shh');
var watches = require('./web3/watches');
var filter = require('./web3/filter');
var Filter = require('./web3/filter');
var utils = require('./utils/utils');
var formatters = require('./solidity/formatters');
var requestManager = require('./web3/requestmanager');
var formatters = require('./web3/formatters');
var RequestManager = require('./web3/requestmanager');
var c = require('./utils/config');
var Method = require('./web3/method');
var Property = require('./web3/property');
/// @returns an array of objects describing web3 api methods
var web3Methods = [
{ name: 'sha3', call: 'web3_sha3', inputFormatter: utils.toHex },
new Method({
name: 'sha3',
call: 'web3_sha3',
params: 1
})
];
var web3Properties = [
{ name: 'version.client', getter: 'web3_clientVersion' },
{ name: 'version.network', getter: 'net_version' }
new Property({
name: 'version.client',
getter: 'web3_clientVersion'
}),
new Property({
name: 'version.network',
getter: 'net_version',
inputFormatter: utils.toDecimal
}),
new Property({
name: 'version.ethereum',
getter: 'eth_version',
inputFormatter: utils.toDecimal
}),
new Property({
name: 'version.whisper',
getter: 'shh_version',
inputFormatter: utils.toDecimal
})
];
/// creates methods in a given object based on method description on input
/// setups api calls for these methods
var setupMethods = function (obj, methods) {
methods.forEach(function (method) {
// allow for object methods 'myObject.method'
var objectMethods = method.name.split('.'),
callFunction = function () {
/*jshint maxcomplexity:8 */
var callback = null,
args = Array.prototype.slice.call(arguments),
call = typeof method.call === 'function' ? method.call(args) : method.call;
// get the callback if one is available
if(typeof args[args.length-1] === 'function'){
callback = args[args.length-1];
Array.prototype.pop.call(args);
}
// add the defaultBlock if not given
if(method.addDefaultblock) {
if(args.length !== method.addDefaultblock)
Array.prototype.push.call(args, (isFinite(c.ETH_DEFAULTBLOCK) ? utils.fromDecimal(c.ETH_DEFAULTBLOCK) : c.ETH_DEFAULTBLOCK));
else
args[args.length-1] = isFinite(args[args.length-1]) ? utils.fromDecimal(args[args.length-1]) : args[args.length-1];
}
// show deprecated warning
if(method.newMethod)
console.warn('This method is deprecated please use web3.'+ method.newMethod +'() instead.');
return web3.manager.send({
method: call,
params: args,
outputFormatter: method.outputFormatter,
inputFormatter: method.inputFormatter,
addDefaultblock: method.addDefaultblock
}, callback);
};
if(objectMethods.length > 1) {
if(!obj[objectMethods[0]])
obj[objectMethods[0]] = {};
obj[objectMethods[0]][objectMethods[1]] = callFunction;
} else {
obj[objectMethods[0]] = callFunction;
}
method.attachToObject(obj);
});
};
@ -104,173 +80,53 @@ var setupMethods = function (obj, methods) {
/// setups api calls for these properties
var setupProperties = function (obj, properties) {
properties.forEach(function (property) {
var objectProperties = property.name.split('.'),
proto = {};
proto.get = function () {
// show deprecated warning
if(property.newProperty)
console.warn('This property is deprecated please use web3.'+ property.newProperty +' instead.');
return web3.manager.send({
method: property.getter,
outputFormatter: property.outputFormatter
});
};
if (property.setter) {
proto.set = function (val) {
// show deprecated warning
if(property.newProperty)
console.warn('This property is deprecated please use web3.'+ property.newProperty +' instead.');
return web3.manager.send({
method: property.setter,
params: [val],
inputFormatter: property.inputFormatter
});
};
}
proto.enumerable = !property.newProperty;
if(objectProperties.length > 1) {
if(!obj[objectProperties[0]])
obj[objectProperties[0]] = {};
Object.defineProperty(obj[objectProperties[0]], objectProperties[1], proto);
} else
Object.defineProperty(obj, property.name, proto);
property.attachToObject(obj);
});
};
/// setups web3 object, and it's in-browser executed methods
var web3 = {};
web3.providers = {};
web3.version = {};
web3.version.api = version.version;
web3.eth = {};
/*jshint maxparams:4 */
var startPolling = function (method, id, callback, uninstall) {
web3.manager.startPolling({
method: method,
params: [id]
}, id, callback, uninstall);
};
/*jshint maxparams:3 */
web3.eth.filter = function (fil, eventParams, options, formatter) {
var stopPolling = function (id) {
web3.manager.stopPolling(id);
};
// if its event, treat it differently
// TODO: simplify and remove
if (fil._isEvent) {
return fil(eventParams, options);
}
var ethWatch = {
startPolling: startPolling.bind(null, 'eth_getFilterChanges'),
stopPolling: stopPolling
// what outputLogFormatter? that's wrong
//return new Filter(fil, watches.eth(), formatters.outputLogFormatter);
return new Filter(fil, watches.eth(), formatter || formatters.outputLogFormatter);
};
/*jshint maxparams:3 */
var shhWatch = {
startPolling: startPolling.bind(null, 'shh_getFilterChanges'),
stopPolling: stopPolling
web3.shh = {};
web3.shh.filter = function (fil) {
return new Filter(fil, watches.shh(), formatters.outputPostFormatter);
};
/// setups web3 object, and it's in-browser executed methods
var web3 = {
version: {
api: version.version
},
manager: requestManager(),
providers: {},
setProvider: function (provider) {
web3.manager.setProvider(provider);
},
/// Should be called to reset state of web3 object
/// Resets everything except manager
reset: function () {
web3.manager.reset();
},
/// @returns hex string of the input
toHex: utils.toHex,
/// @returns ascii string representation of hex value prefixed with 0x
toAscii: utils.toAscii,
/// @returns hex representation (prefixed by 0x) of ascii string
fromAscii: utils.fromAscii,
/// @returns decimal representaton of hex value prefixed by 0x
toDecimal: utils.toDecimal,
/// @returns hex representation (prefixed by 0x) of decimal value
fromDecimal: utils.fromDecimal,
/// @returns a BigNumber object
toBigNumber: utils.toBigNumber,
toWei: utils.toWei,
fromWei: utils.fromWei,
isAddress: utils.isAddress,
// provide network information
net: {
// peerCount:
},
/// eth object prototype
eth: {
// DEPRECATED
contractFromAbi: function (abi) {
console.warn('Initiating a contract like this is deprecated please use var MyContract = eth.contract(abi); new MyContract(address); instead.');
return function(addr) {
// Default to address of Config. TODO: rremove prior to genesis.
addr = addr || '0xc6d9d2cd449a754c494264e1809c50e34d64562b';
var ret = web3.eth.contract(addr, abi);
ret.address = addr;
return ret;
};
},
/// @param filter may be a string, object or event
/// @param eventParams is optional, this is an object with optional event eventParams params
/// @param options is optional, this is an object with optional event options ('max'...)
/*jshint maxparams:4 */
filter: function (fil, eventParams, options) {
// if its event, treat it differently
if (fil._isEvent)
return fil(eventParams, options);
return filter(fil, ethWatch, formatters.outputLogFormatter);
},
// DEPRECATED
watch: function (fil, eventParams, options) {
console.warn('eth.watch() is deprecated please use eth.filter() instead.');
return this.filter(fil, eventParams, options);
}
/*jshint maxparams:3 */
},
/// db object prototype
db: {},
/// shh object prototype
shh: {
/// @param filter may be a string, object or event
filter: function (fil) {
return filter(fil, shhWatch, formatters.outputPostFormatter);
},
// DEPRECATED
watch: function (fil) {
console.warn('shh.watch() is deprecated please use shh.filter() instead.');
return this.filter(fil);
}
}
web3.net = {};
web3.db = {};
web3.setProvider = function (provider) {
RequestManager.getInstance().setProvider(provider);
};
web3.reset = function () {
RequestManager.getInstance().reset();
};
web3.toHex = utils.toHex;
web3.toAscii = utils.toAscii;
web3.fromAscii = utils.fromAscii;
web3.toDecimal = utils.toDecimal;
web3.fromDecimal = utils.fromDecimal;
web3.toBigNumber = utils.toBigNumber;
web3.toWei = utils.toWei;
web3.fromWei = utils.fromWei;
web3.isAddress = utils.isAddress;
// ADD defaultblock
Object.defineProperty(web3.eth, 'defaultBlock', {
@ -291,10 +147,8 @@ setupMethods(web3.net, net.methods);
setupProperties(web3.net, net.properties);
setupMethods(web3.eth, eth.methods);
setupProperties(web3.eth, eth.properties);
setupMethods(web3.db, db.methods());
setupMethods(web3.shh, shh.methods());
setupMethods(ethWatch, watches.eth());
setupMethods(shhWatch, watches.shh());
setupMethods(web3.db, db.methods);
setupMethods(web3.shh, shh.methods);
module.exports = web3;

47
libjsqrc/ethereumjs/lib/web3/contract.js

@ -26,15 +26,6 @@ var utils = require('../utils/utils');
var eventImpl = require('./event');
var signature = require('./signature');
var exportNatspecGlobals = function (vars) {
// it's used byt natspec.js
// TODO: figure out better way to solve this
web3._currentContractAbi = vars.abi;
web3._currentContractAddress = vars.address;
web3._currentContractMethodName = vars.method;
web3._currentContractMethodParams = vars.params;
};
var addFunctionRelatedPropertiesToContract = function (contract) {
contract.call = function (options) {
@ -43,28 +34,11 @@ var addFunctionRelatedPropertiesToContract = function (contract) {
return contract;
};
contract.sendTransaction = function (options) {
contract._isTransaction = true;
contract._options = options;
return contract;
};
// DEPRECATED
contract.transact = function (options) {
console.warn('myContract.transact() is deprecated please use myContract.sendTransaction() instead.');
return contract.sendTransaction(options);
};
contract._options = {};
['gas', 'gasPrice', 'value', 'from'].forEach(function(p) {
contract[p] = function (v) {
contract._options[p] = v;
return contract;
};
});
};
var addFunctionsToContract = function (contract, desc, address) {
@ -96,13 +70,6 @@ var addFunctionsToContract = function (contract, desc, address) {
if (isTransaction) {
exportNatspecGlobals({
abi: desc,
address: address,
method: method.name,
params: params
});
// transactions do not have any output, cause we do not know, when they will be processed
web3.eth.sendTransaction(options);
return;
@ -159,7 +126,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
@ -203,17 +170,7 @@ var addEventsToContract = function (contract, desc, address) {
var contract = function (abi) {
// return prototype
if(abi instanceof Array && arguments.length === 1) {
return Contract.bind(null, abi);
// deprecated: auto initiate contract
} else {
console.warn('Initiating a contract like this is deprecated please use var MyContract = eth.contract(abi); new MyContract(address); instead.');
return new Contract(arguments[1], arguments[0]);
}
return Contract.bind(null, abi);
};
function Contract(abi, address) {

38
libjsqrc/ethereumjs/lib/web3/db.js

@ -20,16 +20,36 @@
* @date 2015
*/
var Method = require('./method');
/// @returns an array of objects describing web3.db api methods
var methods = function () {
return [
{ name: 'putString', call: 'db_putString'},
{ name: 'getString', call: 'db_getString'},
{ name: 'putHex', call: 'db_putHex'},
{ name: 'getHex', call: 'db_getHex'}
];
};
var putString = new Method({
name: 'putString',
call: 'db_putString',
params: 3
});
var getString = new Method({
name: 'getString',
call: 'db_getString',
params: 2
});
var putHex = new Method({
name: 'putHex',
call: 'db_putHex',
params: 3
});
var getHex = new Method({
name: 'getHex',
call: 'db_getHex',
params: 2
});
var methods = [
putString, getString, putHex, getHex
];
module.exports = {
methods: methods

38
libjsqrc/ethereumjs/lib/web3/errors.js

@ -0,0 +1,38 @@
/*
This file is part of ethereum.js.
ethereum.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ethereum.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file errors.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
var utils = require('../utils/utils');
module.exports = {
InvalidNumberOfParams: new Error('Invalid number of input parameters'),
InvalidProvider: new Error('Providor not set or invalid'),
InvalidResponse: function(result){
var message = 'Invalid JSON RPC response';
if(utils.isObject(result) && result.error && result.error.message) {
message = result.error.message;
}
return new Error(message);
}
};

242
libjsqrc/ethereumjs/lib/web3/eth.js

@ -14,10 +14,10 @@
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file eth.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
* Fabian Vogelsteller <fabian@ethdev.com>
/**
* @file eth.js
* @author Marek Kotewicz <marek@ethdev.com>
* @author Fabian Vogelsteller <fabian@ethdev.com>
* @date 2015
*/
@ -35,10 +35,11 @@
* {
* name: 'getBlock',
* call: blockCall,
* params: 2,
* outputFormatter: formatters.outputBlockFormatter,
* inputFormatter: [ // can be a formatter funciton or an array of functions. Where each item in the array will be used for one parameter
* utils.toHex, // formats paramter 1
* function(param){ if(!param) return false; } // formats paramter 2
* function(param){ return !!param; } // formats paramter 2
* ]
* },
*
@ -46,10 +47,12 @@
* @constructor
*/
"use strict";
var formatters = require('./formatters');
var utils = require('../utils/utils');
var Method = require('./method');
var Property = require('./property');
var blockCall = function (args) {
return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? "eth_getBlockByHash" : "eth_getBlockByNumber";
@ -72,75 +75,178 @@ var uncleCountCall = function (args) {
};
/// @returns an array of objects describing web3.eth api methods
var getBalance = new Method({
name: 'getBalance',
call: 'eth_getBalance',
params: 2,
inputFormatter: [utils.toAddress, formatters.inputDefaultBlockNumberFormatter],
outputFormatter: formatters.outputBigNumberFormatter
});
var getStorageAt = new Method({
name: 'getStorageAt',
call: 'eth_getStorageAt',
params: 3,
inputFormatter: [null, utils.toHex, formatters.inputDefaultBlockNumberFormatter]
});
var getCode = new Method({
name: 'getCode',
call: 'eth_getCode',
params: 2,
inputFormatter: [utils.toAddress, formatters.inputDefaultBlockNumberFormatter]
});
var getBlock = new Method({
name: 'getBlock',
call: blockCall,
params: 2,
inputFormatter: [formatters.inputBlockNumberFormatter, function (val) { return !!val; }],
outputFormatter: formatters.outputBlockFormatter
});
var getUncle = new Method({
name: 'getUncle',
call: uncleCall,
params: 3,
inputFormatter: [formatters.inputBlockNumberFormatter, utils.toHex, function (val) { return !!val; }],
outputFormatter: formatters.outputBlockFormatter,
});
var getCompilers = new Method({
name: 'getCompilers',
call: 'eth_getCompilers',
params: 0
});
var getBlockTransactionCount = new Method({
name: 'getBlockTransactionCount',
call: getBlockTransactionCountCall,
params: 1,
inputFormatter: [formatters.inputBlockNumberFormatter],
outputFormatter: utils.toDecimal
});
var getBlockUncleCount = new Method({
name: 'getBlockUncleCount',
call: uncleCountCall,
params: 1,
inputFormatter: [formatters.inputBlockNumberFormatter],
outputFormatter: utils.toDecimal
});
var getTransaction = new Method({
name: 'getTransaction',
call: 'eth_getTransactionByHash',
params: 1,
outputFormatter: formatters.outputTransactionFormatter
});
var getTransactionFromBlock = new Method({
name: 'getTransactionFromBlock',
call: transactionFromBlockCall,
params: 2,
inputFormatter: [utils.toHex, utils.toHex],
outputFormatter: formatters.outputTransactionFormatter
});
var getTransactionCount = new Method({
name: 'getTransactionCount',
call: 'eth_getTransactionCount',
params: 2,
inputFormatter: [null, formatters.inputDefaultBlockNumberFormatter],
outputFormatter: utils.toDecimal
});
var sendTransaction = new Method({
name: 'sendTransaction',
call: 'eth_sendTransaction',
params: 1,
inputFormatter: [formatters.inputTransactionFormatter]
});
var call = new Method({
name: 'call',
call: 'eth_call',
params: 2,
inputFormatter: [formatters.inputTransactionFormatter, formatters.inputDefaultBlockNumberFormatter]
});
var compileSolidity = new Method({
name: 'compile.solidity',
call: 'eth_compileSolidity',
params: 1
});
var compileLLL = new Method({
name: 'compile.lll',
call: 'eth_compileLLL',
params: 1
});
var compileSerpent = new Method({
name: 'compile.serpent',
call: 'eth_compileSerpent',
params: 1
});
var flush = new Method({
name: 'flush',
call: 'eth_flush',
params: 0
});
var methods = [
{ name: 'getBalance', call: 'eth_getBalance', addDefaultblock: 2,
outputFormatter: formatters.convertToBigNumber},
{ name: 'getStorageAt', call: 'eth_getStorageAt', addDefaultblock: 3,
inputFormatter: utils.toHex},
{ name: 'getCode', call: 'eth_getCode', addDefaultblock: 2},
{ name: 'getBlock', call: blockCall,
outputFormatter: formatters.outputBlockFormatter,
inputFormatter: [utils.toHex, function(param){ return (!param) ? false : true; }]},
{ name: 'getUncle', call: uncleCall,
outputFormatter: formatters.outputBlockFormatter,
inputFormatter: [utils.toHex, utils.toHex, function(param){ return (!param) ? false : true; }]},
{ name: 'getCompilers', call: 'eth_getCompilers' },
{ name: 'getBlockTransactionCount', call: getBlockTransactionCountCall,
outputFormatter: utils.toDecimal,
inputFormatter: utils.toHex },
{ name: 'getBlockUncleCount', call: uncleCountCall,
outputFormatter: utils.toDecimal,
inputFormatter: utils.toHex },
{ name: 'getTransaction', call: 'eth_getTransactionByHash',
outputFormatter: formatters.outputTransactionFormatter },
{ name: 'getTransactionFromBlock', call: transactionFromBlockCall,
outputFormatter: formatters.outputTransactionFormatter,
inputFormatter: utils.toHex },
{ name: 'getTransactionCount', call: 'eth_getTransactionCount', addDefaultblock: 2,
outputFormatter: utils.toDecimal},
{ name: 'sendTransaction', call: 'eth_sendTransaction',
inputFormatter: formatters.inputTransactionFormatter },
{ name: 'call', call: 'eth_call', addDefaultblock: 2,
inputFormatter: formatters.inputCallFormatter },
{ name: 'compile.solidity', call: 'eth_compileSolidity' },
{ name: 'compile.lll', call: 'eth_compileLLL', inputFormatter: utils.toHex },
{ name: 'compile.serpent', call: 'eth_compileSerpent', inputFormatter: utils.toHex },
{ name: 'flush', call: 'eth_flush' },
// deprecated methods
{ 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: blockCall, newMethod: 'eth.getBlock' },
{ name: 'transaction', call: transactionFromBlockCall, newMethod: 'eth.getTransaction' },
{ name: 'uncle', call: uncleCall, 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: getBlockTransactionCountCall, newMethod: 'eth.getBlockTransactionCount' },
{ name: 'uncleCount', call: uncleCountCall, newMethod: 'eth.getBlockUncleCount' },
{ name: 'logs', call: 'eth_logs' }
getBalance,
getStorageAt,
getCode,
getBlock,
getUncle,
getCompilers,
getBlockTransactionCount,
getBlockUncleCount,
getTransaction,
getTransactionFromBlock,
getTransactionCount,
call,
sendTransaction,
compileSolidity,
compileLLL,
compileSerpent,
flush
];
/// @returns an array of objects describing web3.eth api properties
var properties = [
{ name: 'coinbase', getter: 'eth_coinbase'},
{ name: 'mining', getter: 'eth_mining'},
{ name: 'gasPrice', getter: 'eth_gasPrice', outputFormatter: formatters.convertToBigNumber},
{ name: 'accounts', getter: 'eth_accounts' },
{ name: 'blockNumber', getter: 'eth_blockNumber', outputFormatter: utils.toDecimal},
// deprecated properties
{ 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'}
new Property({
name: 'coinbase',
getter: 'eth_coinbase'
}),
new Property({
name: 'mining',
getter: 'eth_mining'
}),
new Property({
name: 'gasPrice',
getter: 'eth_gasPrice',
outputFormatter: formatters.inputNumberFormatter
}),
new Property({
name: 'accounts',
getter: 'eth_accounts'
}),
new Property({
name: 'blockNumber',
getter: 'eth_blockNumber',
outputFormatter: utils.toDecimal
})
];
module.exports = {
methods: methods,
properties: properties

4
libjsqrc/ethereumjs/lib/web3/event.js

@ -57,7 +57,7 @@ var indexedParamsToTopics = function (event, indexed) {
return abi.formatInput(inputs, [v]);
});
}
return abi.formatInput(inputs, [value]);
return '0x' + abi.formatInput(inputs, [value]);
});
};
@ -101,10 +101,10 @@ var outputParser = function (event) {
args: {}
};
output.topics = output.topic; // fallback for go-ethereum
if (!output.topics) {
return result;
}
output.data = output.data || '';
var indexedOutputs = filterInputs(event.inputs, true);
var indexedData = "0x" + output.topics.slice(1, output.topics.length).map(function (topics) { return topics.slice(2); }).join("");

165
libjsqrc/ethereumjs/lib/web3/filter.js

@ -24,148 +24,87 @@
* @date 2014
*/
var RequestManager = require('./requestmanager');
var formatters = require('./formatters');
var utils = require('../utils/utils');
/// Should be called to check if filter implementation is valid
/// @returns true if it is, otherwise false
var implementationIsValid = function (i) {
return !!i &&
typeof i.newFilter === 'function' &&
typeof i.getLogs === 'function' &&
typeof i.uninstallFilter === 'function' &&
typeof i.startPolling === 'function' &&
typeof i.stopPolling === 'function';
};
/// This method should be called on options object, to verify deprecated properties && lazy load dynamic ones
/// @param should be string or object
/// @returns options string or object
var getOptions = function (options) {
/*jshint maxcomplexity:9 */
if (typeof options === 'string') {
if (utils.isString(options)) {
return options;
}
options = options || {};
if (options.topic) {
console.warn('"topic" is deprecated, is "topics" instead');
options.topics = options.topic;
}
if (options.earliest) {
console.warn('"earliest" is deprecated, is "fromBlock" instead');
options.fromBlock = options.earliest;
}
if (options.latest) {
console.warn('"latest" is deprecated, is "toBlock" instead');
options.toBlock = options.latest;
}
// make sure topics, get converted to hex
if(options.topics instanceof Array) {
options.topics = options.topics.map(function(topic){
return utils.toHex(topic);
});
}
var asBlockNumber = function(n) {
if (n == null)
return null;
if (n == 'latest' || n == 'pending')
return n;
return utils.toHex(n);
};
options.topics = options.topics || [];
options.topics = options.topics.map(function(topic){
return utils.toHex(topic);
});
// evaluate lazy properties
// lazy load
return {
fromBlock: asBlockNumber(options.fromBlock),
toBlock: asBlockNumber(options.toBlock),
topics: options.topics,
to: options.to,
address: options.address,
topics: options.topics
fromBlock: formatters.inputBlockNumberFormatter(options.fromBlock),
toBlock: formatters.inputBlockNumberFormatter(options.toBlock)
};
};
/// Should be used when we want to watch something
/// it's using inner polling mechanism and is notified about changes
/// @param options are filter options
/// @param implementation, an abstract polling implementation
/// @param formatter (optional), callback function which formats output before 'real' callback
var filter = function(options, implementation, formatter) {
if (!implementationIsValid(implementation)) {
console.error('filter implemenation is invalid');
return;
}
var Filter = function (options, methods, formatter) {
var implementation = {};
methods.forEach(function (method) {
method.attachToObject(implementation);
});
this.options = getOptions(options);
this.implementation = implementation;
this.callbacks = [];
this.formatter = formatter;
this.filterId = this.implementation.newFilter(this.options);
};
options = getOptions(options);
var callbacks = [];
var filterId = implementation.newFilter(options);
Filter.prototype.watch = function (callback) {
this.callbacks.push(callback);
var self = this;
var onMessage = function (error, messages) {
if (error) {
return self.callbacks.forEach(function (callback) {
callback(error);
});
}
// call the callbacks
var onMessages = function (messages) {
messages.forEach(function (message) {
message = formatter ? formatter(message) : message;
callbacks.forEach(function (callback) {
callback(message);
message = self.formatter ? self.formatter(message) : message;
self.callbacks.forEach(function (callback) {
callback(null, message);
});
});
};
implementation.startPolling(filterId, onMessages, implementation.uninstallFilter);
var watch = function(callback) {
callbacks.push(callback);
};
var stopWatching = function() {
implementation.stopPolling(filterId);
implementation.uninstallFilter(filterId);
callbacks = [];
};
var get = function () {
var results = implementation.getLogs(filterId);
RequestManager.getInstance().startPolling({
method: this.implementation.poll.call,
params: [this.filterId],
}, this.filterId, onMessage, this.stopWatching.bind(this));
};
return utils.isArray(results) ? results.map(function(message){
return formatter ? formatter(message) : message;
}) : results;
};
Filter.prototype.stopWatching = function () {
RequestManager.getInstance().stopPolling(this.filterId);
this.implementation.uninstallFilter(this.filterId);
this.callbacks = [];
};
return {
watch: watch,
stopWatching: stopWatching,
get: get,
// DEPRECATED methods
changed: function(){
console.warn('watch().changed() is deprecated please use filter().watch() instead.');
return watch.apply(this, arguments);
},
arrived: function(){
console.warn('watch().arrived() is deprecated please use filter().watch() instead.');
return watch.apply(this, arguments);
},
happened: function(){
console.warn('watch().happened() is deprecated please use filter().watch() instead.');
return watch.apply(this, arguments);
},
uninstall: function(){
console.warn('watch().uninstall() is deprecated please use filter().stopWatching() instead.');
return stopWatching.apply(this, arguments);
},
messages: function(){
console.warn('watch().messages() is deprecated please use filter().get() instead.');
return get.apply(this, arguments);
},
logs: function(){
console.warn('watch().logs() is deprecated please use filter().get() instead.');
return get.apply(this, arguments);
}
};
Filter.prototype.get = function () {
var logs = this.implementation.getLogs(this.filterId);
var self = this;
return logs.map(function (log) {
return self.formatter ? self.formatter(log) : log;
});
};
module.exports = filter;
module.exports = Filter;

92
libjsqrc/ethereumjs/lib/web3/formatters.js

@ -14,24 +14,45 @@
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file formatters.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
* Fabian Vogelsteller <fabian@ethdev.com>
/**
* @file formatters.js
* @author Marek Kotewicz <marek@ethdev.com>
* @author Fabian Vogelsteller <fabian@ethdev.com>
* @date 2015
*/
var utils = require('../utils/utils');
var config = require('../utils/config');
/**
* Should the input to a big number
* Should the format output to a big number
*
* @method convertToBigNumber
* @method outputBigNumberFormatter
* @param {String|Number|BigNumber}
* @returns {BigNumber} object
*/
var convertToBigNumber = function (value) {
return utils.toBigNumber(value);
var outputBigNumberFormatter = function (number) {
return utils.toBigNumber(number);
};
var isPredefinedBlockNumber = function (blockNumber) {
return blockNumber === 'latest' || blockNumber === 'pending' || blockNumber === 'earliest';
};
var inputDefaultBlockNumberFormatter = function (blockNumber) {
if (blockNumber === undefined) {
return config.ETH_DEFAULTBLOCK;
}
return inputBlockNumberFormatter(blockNumber);
};
var inputBlockNumberFormatter = function (blockNumber) {
if (blockNumber === undefined) {
return undefined;
} else if (isPredefinedBlockNumber(blockNumber)) {
return blockNumber;
}
return utils.toHex(blockNumber);
};
/**
@ -49,7 +70,9 @@ var inputTransactionFormatter = function (options){
delete options.code;
}
['gasPrice', 'gas', 'value'].forEach(function(key){
['gasPrice', 'gas', 'value'].filter(function (key) {
return options[key] !== undefined;
}).forEach(function(key){
options[key] = utils.fromDecimal(options[key]);
});
@ -64,31 +87,14 @@ var inputTransactionFormatter = function (options){
* @returns {Object} transaction
*/
var outputTransactionFormatter = function (tx){
tx.blockNumber = utils.toDecimal(tx.blockNumber);
tx.transactionIndex = utils.toDecimal(tx.transactionIndex);
tx.gas = utils.toDecimal(tx.gas);
tx.gasPrice = utils.toBigNumber(tx.gasPrice);
tx.value = utils.toBigNumber(tx.value);
return tx;
};
/**
* Formats the input of a call and converts all values to HEX
*
* @method inputCallFormatter
* @param {Object} transaction options
* @returns object
*/
var inputCallFormatter = function (options){
// make code -> data
if (options.code) {
options.data = options.code;
delete options.code;
}
return options;
};
/**
* Formats the output of a block to its proper values
*
@ -96,7 +102,7 @@ var inputCallFormatter = function (options){
* @param {Object} block object
* @returns {Object} block object
*/
var outputBlockFormatter = function(block){
var outputBlockFormatter = function(block) {
// transform to number
block.gasLimit = utils.toDecimal(block.gasLimit);
@ -109,7 +115,7 @@ var outputBlockFormatter = function(block){
block.difficulty = utils.toBigNumber(block.difficulty);
block.totalDifficulty = utils.toBigNumber(block.totalDifficulty);
if(block.transactions instanceof Array) {
if (utils.isArray(block.transactions)) {
block.transactions.forEach(function(item){
if(!utils.isString(item))
return outputTransactionFormatter(item);
@ -126,7 +132,11 @@ var outputBlockFormatter = function(block){
* @param {Object} log object
* @returns {Object} log
*/
var outputLogFormatter = function(log){
var outputLogFormatter = function(log) {
if (log === null) { // 'pending' && 'latest' filters are nulls
return null;
}
log.blockNumber = utils.toDecimal(log.blockNumber);
log.transactionIndex = utils.toDecimal(log.transactionIndex);
log.logIndex = utils.toDecimal(log.logIndex);
@ -134,7 +144,6 @@ var outputLogFormatter = function(log){
return log;
};
/**
* Formats the input of a whisper post and converts all values to HEX
*
@ -142,15 +151,15 @@ var outputLogFormatter = function(log){
* @param {Object} transaction object
* @returns {Object}
*/
var inputPostFormatter = function(post){
var inputPostFormatter = function(post) {
post.payload = utils.toHex(post.payload);
post.ttl = utils.fromDecimal(post.ttl);
post.priority = utils.fromDecimal(post.priority);
if(!(post.topics instanceof Array))
if(!utils.isArray(post.topics)) {
post.topics = [post.topics];
}
// format the following options
post.topics = post.topics.map(function(topic){
@ -176,10 +185,8 @@ var outputPostFormatter = function(post){
post.payloadRaw = post.payload;
post.payload = utils.toAscii(post.payload);
if(post.payload.indexOf('{') === 0 || post.payload.indexOf('[') === 0) {
try {
post.payload = JSON.parse(post.payload);
} catch (e) { }
if (utils.isJson(post.payload)) {
post.payload = JSON.parse(post.payload);
}
// format the following options
@ -191,13 +198,14 @@ var outputPostFormatter = function(post){
};
module.exports = {
convertToBigNumber: convertToBigNumber,
inputDefaultBlockNumberFormatter: inputDefaultBlockNumberFormatter,
inputBlockNumberFormatter: inputBlockNumberFormatter,
inputTransactionFormatter: inputTransactionFormatter,
inputPostFormatter: inputPostFormatter,
outputBigNumberFormatter: outputBigNumberFormatter,
outputTransactionFormatter: outputTransactionFormatter,
inputCallFormatter: inputCallFormatter,
outputBlockFormatter: outputBlockFormatter,
outputLogFormatter: outputLogFormatter,
inputPostFormatter: inputPostFormatter,
outputPostFormatter: outputPostFormatter
};

56
libjsqrc/ethereumjs/lib/web3/httpprovider.js

@ -22,47 +22,39 @@
* @date 2014
*/
if (process.env.NODE_ENV !== 'build') {
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line
}
"use strict";
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line
var HttpProvider = function (host) {
this.name = 'HTTP';
this.handlers = [];
this.host = host || 'http://localhost:8080';
};
HttpProvider.prototype.send = function (payload, callback) {
HttpProvider.prototype.send = function (payload) {
var request = new XMLHttpRequest();
// ASYNC
if(typeof callback === 'function') {
request.onreadystatechange = function() {
if(request.readyState === 4) {
var result = '';
try {
result = JSON.parse(request.responseText);
} catch(error) {
result = error;
}
callback(result, request.status);
}
};
request.open('POST', this.host, true);
request.send(JSON.stringify(payload));
// SYNC
} else {
request.open('POST', this.host, false);
request.send(JSON.stringify(payload));
request.open('POST', this.host, false);
request.send(JSON.stringify(payload));
// check request.status
if(request.status !== 200)
return;
return JSON.parse(request.responseText);
// check request.status
// TODO: throw an error here! it cannot silently fail!!!
//if (request.status !== 200) {
//return;
//}
return JSON.parse(request.responseText);
};
}
HttpProvider.prototype.sendAsync = function (payload, callback) {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState === 4) {
// TODO: handle the error properly here!!!
callback(null, JSON.parse(request.responseText));
}
};
request.open('POST', this.host, true);
request.send(JSON.stringify(payload));
};
module.exports = HttpProvider;

66
libjsqrc/ethereumjs/lib/web3/jsonrpc.js

@ -20,13 +20,33 @@
* @date 2015
*/
var messageId = 1;
var Jsonrpc = function () {
// singleton pattern
if (arguments.callee._singletonInstance) {
return arguments.callee._singletonInstance;
}
arguments.callee._singletonInstance = this;
/// Should be called to valid json create payload object
/// @param method of jsonrpc call, required
/// @param params, an array of method params, optional
/// @returns valid jsonrpc payload object
var toPayload = function (method, params) {
this.messageId = 1;
};
/**
* @return {Jsonrpc} singleton
*/
Jsonrpc.getInstance = function () {
var instance = new Jsonrpc();
return instance;
};
/**
* Should be called to valid json create payload object
*
* @method toPayload
* @param {Function} method of jsonrpc call, required
* @param {Array} params, an array of method params, optional
* @returns {Object} valid jsonrpc payload object
*/
Jsonrpc.prototype.toPayload = function (method, params) {
if (!method)
console.error('jsonrpc method should be specified!');
@ -34,13 +54,18 @@ var toPayload = function (method, params) {
jsonrpc: '2.0',
method: method,
params: params || [],
id: messageId++
id: this.messageId++
};
};
/// Should be called to check if jsonrpc response is valid
/// @returns true if response is valid, otherwise false
var isValidResponse = function (response) {
/**
* Should be called to check if jsonrpc response is valid
*
* @method isValidResponse
* @param {Object}
* @returns {Boolean} true if response is valid, otherwise false
*/
Jsonrpc.prototype.isValidResponse = function (response) {
return !!response &&
!response.error &&
response.jsonrpc === '2.0' &&
@ -48,18 +73,19 @@ var isValidResponse = function (response) {
response.result !== undefined; // only undefined is not valid json object
};
/// Should be called to create batch payload object
/// @param messages, an array of objects with method (required) and params (optional) fields
var toBatchPayload = function (messages) {
/**
* Should be called to create batch payload object
*
* @method toBatchPayload
* @param {Array} messages, an array of objects with method (required) and params (optional) fields
* @returns {Array} batch payload
*/
Jsonrpc.prototype.toBatchPayload = function (messages) {
var self = this;
return messages.map(function (message) {
return toPayload(message.method, message.params);
return self.toPayload(message.method, message.params);
});
};
module.exports = {
toPayload: toPayload,
isValidResponse: isValidResponse,
toBatchPayload: toBatchPayload
};
module.exports = Jsonrpc;

159
libjsqrc/ethereumjs/lib/web3/method.js

@ -0,0 +1,159 @@
/*
This file is part of ethereum.js.
ethereum.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ethereum.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file method.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
var RequestManager = require('./requestmanager');
var utils = require('../utils/utils');
var errors = require('./errors');
var Method = function (options) {
this.name = options.name;
this.call = options.call;
this.params = options.params || 0;
this.inputFormatter = options.inputFormatter;
this.outputFormatter = options.outputFormatter;
};
/**
* Should be used to determine name of the jsonrpc method based on arguments
*
* @method getCall
* @param {Array} arguments
* @return {String} name of jsonrpc method
*/
Method.prototype.getCall = function (args) {
return utils.isFunction(this.call) ? this.call(args) : this.call;
};
/**
* Should be used to extract callback from array of arguments. Modifies input param
*
* @method extractCallback
* @param {Array} arguments
* @return {Function|Null} callback, if exists
*/
Method.prototype.extractCallback = function (args) {
if (utils.isFunction(args[args.length - 1])) {
return args.pop(); // modify the args array!
}
return null;
};
/**
* Should be called to check if the number of arguments is correct
*
* @method validateArgs
* @param {Array} arguments
* @throws {Error} if it is not
*/
Method.prototype.validateArgs = function (args) {
if (args.length !== this.params) {
throw errors.InvalidNumberOfParams;
}
};
/**
* Should be called to format input args of method
*
* @method formatInput
* @param {Array}
* @return {Array}
*/
Method.prototype.formatInput = function (args) {
if (!this.inputFormatter) {
return args;
}
return this.inputFormatter.map(function (formatter, index) {
return formatter ? formatter(args[index]) : args[index];
});
};
/**
* Should be called to format output(result) of method
*
* @method formatOutput
* @param {Object}
* @return {Object}
*/
Method.prototype.formatOutput = function (result) {
return this.outputFormatter && result !== null ? this.outputFormatter(result) : result;
};
/**
* Should attach function to method
*
* @method attachToObject
* @param {Object}
* @param {Function}
*/
Method.prototype.attachToObject = function (obj) {
var func = this.send.bind(this);
func.call = this.call; // that's ugly. filter.js uses it
var name = this.name.split('.');
if (name.length > 1) {
obj[name[0]] = obj[name[0]] || {};
obj[name[0]][name[1]] = func;
} else {
obj[name[0]] = func;
}
};
/**
* Should create payload from given input args
*
* @method toPayload
* @param {Array} args
* @return {Object}
*/
Method.prototype.toPayload = function (args) {
var call = this.getCall(args);
var callback = this.extractCallback(args);
var params = this.formatInput(args);
this.validateArgs(params);
return {
method: call,
params: params,
callback: callback
};
};
/**
* Should send request to the API
*
* @method send
* @param list of params
* @return result
*/
Method.prototype.send = function () {
var payload = this.toPayload(Array.prototype.slice.call(arguments));
if (payload.callback) {
var self = this;
return RequestManager.getInstance().sendAsync(payload, function (err, result) {
payload.callback(null, self.formatOutput(result));
});
}
return this.formatOutput(RequestManager.getInstance().send(payload));
};
module.exports = Method;

13
libjsqrc/ethereumjs/lib/web3/net.js

@ -21,16 +21,23 @@
*/
var utils = require('../utils/utils');
var Property = require('./property');
/// @returns an array of objects describing web3.eth api methods
var methods = [
// { name: 'getBalance', call: 'eth_balanceAt', outputFormatter: formatters.convertToBigNumber},
];
/// @returns an array of objects describing web3.eth api properties
var properties = [
{ name: 'listening', getter: 'net_listening'},
{ name: 'peerCount', getter: 'net_peerCount', outputFormatter: utils.toDecimal },
new Property({
name: 'listening',
getter: 'net_listening'
}),
new Property({
name: 'peerCount',
getter: 'net_peerCount',
outputFormatter: utils.toDecimal
})
];

104
libjsqrc/ethereumjs/lib/web3/property.js

@ -0,0 +1,104 @@
/*
This file is part of ethereum.js.
ethereum.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ethereum.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file property.js
* @author Fabian Vogelsteller <fabian@frozeman.de>
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
var RequestManager = require('./requestmanager');
var Property = function (options) {
this.name = options.name;
this.getter = options.getter;
this.setter = options.setter;
this.outputFormatter = options.outputFormatter;
this.inputFormatter = options.inputFormatter;
};
/**
* Should be called to format input args of method
*
* @method formatInput
* @param {Array}
* @return {Array}
*/
Property.prototype.formatInput = function (arg) {
return this.inputFormatter ? this.inputFormatter(arg) : arg;
};
/**
* Should be called to format output(result) of method
*
* @method formatOutput
* @param {Object}
* @return {Object}
*/
Property.prototype.formatOutput = function (result) {
return this.outputFormatter && result !== null ? this.outputFormatter(result) : result;
};
/**
* Should attach function to method
*
* @method attachToObject
* @param {Object}
* @param {Function}
*/
Property.prototype.attachToObject = function (obj) {
var proto = {
get: this.get.bind(this),
set: this.set.bind(this)
};
var name = this.name.split('.');
if (name.length > 1) {
obj[name[0]] = obj[name[0]] || {};
Object.defineProperty(obj[name[0]], name[1], proto);
} else {
Object.defineProperty(obj, name[0], proto);
}
};
/**
* Should be used to get value of the property
*
* @method get
* @return {Object} value of the property
*/
Property.prototype.get = function () {
return this.formatOutput(RequestManager.getInstance().send({
method: this.getter
}));
};
/**
* Should be used to set value of the property
*
* @method set
* @param {Object} new value of the property
*/
Property.prototype.set = function (value) {
return RequestManager.getInstance().send({
method: this.setter,
params: [this.formatInput(value)]
});
};
module.exports = Property;

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save