Browse Source

Merge branch 'develop' into discovery

cl-refactor
subtly 10 years ago
parent
commit
875965792d
  1. 2
      alethzero/Context.h
  2. 56
      alethzero/MainWin.cpp
  3. 2
      alethzero/MainWin.h
  4. 33
      alethzero/Transact.cpp
  5. 2
      alethzero/Transact.ui
  6. 49
      eth/main.cpp
  7. 28
      libdevcore/CommonData.h
  8. 1
      libdevcore/Exceptions.h
  9. 2
      libdevcore/Log.h
  10. 4
      libdevcrypto/Common.cpp
  11. 4
      libethash/CMakeLists.txt
  12. 0
      libethcore/ABI.cpp
  13. 8
      libethcore/ABI.h
  14. 55
      libethcore/ICAP.cpp
  15. 13
      libethcore/ICAP.h
  16. 19
      libethereum/BlockChain.cpp
  17. 2
      libethereum/BlockChain.h
  18. 60
      libethereum/Client.cpp
  19. 9
      libethereum/Client.h
  20. 4
      libethereum/ClientBase.cpp
  21. 3
      libethereum/ClientBase.h
  22. 6
      libethereum/Interface.h
  23. 6
      libethereum/Transaction.h
  24. 13
      libevmcore/AssemblyItem.h
  25. 176
      libevmcore/CommonSubexpressionEliminator.cpp
  26. 20
      libevmcore/CommonSubexpressionEliminator.h
  27. 24
      libevmcore/ExpressionClasses.cpp
  28. 10
      libevmcore/ExpressionClasses.h
  29. 15
      libp2p/Host.cpp
  30. 8
      libsolidity/AST.cpp
  31. 16
      libsolidity/ExpressionCompiler.cpp
  32. 40
      libsolidity/InterfaceHandler.cpp
  33. 51
      libsolidity/Types.cpp
  34. 47
      libsolidity/Types.h
  35. 1
      libtestutils/StateLoader.cpp
  36. 70
      libweb3jsonrpc/WebThreeStubServerBase.cpp
  37. 3
      libweb3jsonrpc/WebThreeStubServerBase.h
  38. 18
      libweb3jsonrpc/abstractwebthreestubserver.h
  39. 115
      libweb3jsonrpc/spec.json
  40. 24
      neth/main.cpp
  41. 68
      test/TestHelper.cpp
  42. 1
      test/TestHelper.h
  43. 4
      test/fuzzTesting/checkRandomStateTest.cpp
  44. 3
      test/fuzzTesting/checkRandomVMTest.cpp
  45. 4
      test/fuzzTesting/createRandomStateTest.cpp
  46. 7
      test/fuzzTesting/createRandomVMTest.cpp
  47. 386
      test/libethereum/BlockTestsFiller/bcGasPricerTestFiller.json
  48. 0
      test/libethereum/BlockTestsFiller/bcRPC_API_TestFiller.json
  49. 2
      test/libethereum/BlockTestsFiller/bcValidBlockTestFiller.json
  50. 4
      test/libethereum/StateTestsFiller/stTransactionTestFiller.json
  51. 169
      test/libethereum/TransactionTestsFiller/ttTransactionTestFiller.json
  52. 221
      test/libethereum/blockchain.cpp
  53. 140
      test/libethereum/gaspricer.cpp
  54. 2
      test/libethereum/state.cpp
  55. 2
      test/libethereum/transaction.cpp
  56. 50
      test/libevm/vm.cpp
  57. 4
      test/libevm/vm.h
  58. 30
      test/libsolidity/SolidityABIJSON.cpp
  59. 16
      test/libsolidity/SolidityOptimizer.cpp
  60. 4
      test/libweb3jsonrpc/jsonrpc.cpp
  61. 626
      test/webthreestubclient.h

2
alethzero/Context.h

@ -62,7 +62,7 @@ public:
virtual QString pretty(dev::Address _a) const = 0; virtual QString pretty(dev::Address _a) const = 0;
virtual QString prettyU256(dev::u256 _n) const = 0; virtual QString prettyU256(dev::u256 _n) const = 0;
virtual QString render(dev::Address _a) const = 0; virtual QString render(dev::Address _a) const = 0;
virtual dev::Address fromString(QString const& _a) const = 0; virtual std::pair<dev::Address, dev::bytes> fromString(QString const& _a) const = 0;
virtual std::string renderDiff(dev::eth::StateDiff const& _d) const = 0; virtual std::string renderDiff(dev::eth::StateDiff const& _d) const = 0;
}; };

56
alethzero/MainWin.cpp

@ -328,7 +328,8 @@ void Main::installWatches()
Address Main::getNameReg() const Address Main::getNameReg() const
{ {
return abiOut<Address>(ethereum()->call(c_newConfig, abiIn("lookup(uint256)", (u256)1)).output); return Address("c6d9d2cd449a754c494264e1809c50e34d64562b");
// return abiOut<Address>(ethereum()->call(c_newConfig, abiIn("lookup(uint256)", (u256)1)).output);
} }
Address Main::getCurrencies() const Address Main::getCurrencies() const
@ -514,66 +515,65 @@ QString Main::pretty(dev::Address _a) const
if (g_newNameReg) if (g_newNameReg)
{ {
QString s = QString::fromStdString(toString(abiOut<string32>(ethereum()->call(g_newNameReg, abiIn("nameOf(address)", _a)).output))); QString s = QString::fromStdString(toString(abiOut<string32>(ethereum()->call(g_newNameReg, abiIn("getName(address)", _a)).output)));
if (s.size()) if (s.size())
return s; return s;
} }
h256 n; return QString();
return fromRaw(n);
} }
QString Main::render(dev::Address _a) const QString Main::render(dev::Address _a) const
{ {
QString p = pretty(_a); QString p = pretty(_a);
if (!_a[0]) QString n;
p += QString(p.isEmpty() ? "" : " ") + QString::fromStdString(ICAP(_a).encoded()); try {
if (!p.isEmpty()) n = QString::fromStdString(ICAP(_a).encoded());
return p + " (" + QString::fromStdString(_a.abridged()) + ")"; }
return QString::fromStdString(_a.abridged()); catch (...) {
} n = QString::fromStdString(_a.abridged());
}
string32 fromString(string const& _s) return p.isEmpty() ? n : (p + " " + n);
{
string32 ret;
for (unsigned i = 0; i < 32 && i <= _s.size(); ++i)
ret[i] = i < _s.size() ? _s[i] : 0;
return ret;
} }
Address Main::fromString(QString const& _n) const pair<Address, bytes> Main::fromString(QString const& _n) const
{ {
if (_n == "(Create Contract)") if (_n == "(Create Contract)")
return Address(); return make_pair(Address(), bytes());
auto g_newNameReg = getNameReg(); auto g_newNameReg = getNameReg();
if (g_newNameReg) if (g_newNameReg)
{ {
Address a = abiOut<Address>(ethereum()->call(g_newNameReg, abiIn("addressOf(string32)", ::fromString(_n.toStdString()))).output); Address a = abiOut<Address>(ethereum()->call(g_newNameReg, abiIn("addr(bytes32)", ::toString32(_n.toStdString()))).output);
if (a) if (a)
return a; return make_pair(a, bytes());
} }
if (_n.size() == 40) if (_n.size() == 40)
{ {
try try
{ {
return Address(fromHex(_n.toStdString(), WhenError::Throw)); return make_pair(Address(fromHex(_n.toStdString(), WhenError::Throw)), bytes());
} }
catch (BadHexCharacter& _e) catch (BadHexCharacter& _e)
{ {
cwarn << "invalid hex character, address rejected"; cwarn << "invalid hex character, address rejected";
cwarn << boost::diagnostic_information(_e); cwarn << boost::diagnostic_information(_e);
return Address(); return make_pair(Address(), bytes());
} }
catch (...) catch (...)
{ {
cwarn << "address rejected"; cwarn << "address rejected";
return Address(); return make_pair(Address(), bytes());
} }
} }
else if (Address a = ICAP::decoded(_n.toStdString()).direct())
return a;
else else
return Address(); try {
return ICAP::decoded(_n.toStdString()).address([&](Address const& a, bytes const& b) -> bytes
{
return ethereum()->call(a, b).output;
}, g_newNameReg);
}
catch (...) {}
return make_pair(Address(), bytes());
} }
QString Main::lookup(QString const& _a) const QString Main::lookup(QString const& _a) const
@ -1371,7 +1371,7 @@ void Main::on_inject_triggered()
try try
{ {
bytes b = fromHex(s.toStdString(), WhenError::Throw); bytes b = fromHex(s.toStdString(), WhenError::Throw);
ethereum()->inject(&b); ethereum()->injectTransaction(b);
} }
catch (BadHexCharacter& _e) catch (BadHexCharacter& _e)
{ {

2
alethzero/MainWin.h

@ -83,7 +83,7 @@ public:
QString pretty(dev::Address _a) const override; QString pretty(dev::Address _a) const override;
QString prettyU256(dev::u256 _n) const override; QString prettyU256(dev::u256 _n) const override;
QString render(dev::Address _a) const override; QString render(dev::Address _a) const override;
dev::Address fromString(QString const& _a) const override; std::pair<dev::Address, dev::bytes> fromString(QString const& _a) const override;
std::string renderDiff(dev::eth::StateDiff const& _d) const override; std::string renderDiff(dev::eth::StateDiff const& _d) const override;
QList<dev::KeyPair> owned() const { return m_myIdentities + m_myKeys; } QList<dev::KeyPair> owned() const { return m_myIdentities + m_myKeys; }

33
alethzero/Transact.cpp

@ -30,10 +30,12 @@
#include <QMessageBox> #include <QMessageBox>
#include <liblll/Compiler.h> #include <liblll/Compiler.h>
#include <liblll/CodeFragment.h> #include <liblll/CodeFragment.h>
#if ETH_SOLIDITY || !ETH_TRUE
#include <libsolidity/CompilerStack.h> #include <libsolidity/CompilerStack.h>
#include <libsolidity/Scanner.h> #include <libsolidity/Scanner.h>
#include <libsolidity/AST.h> #include <libsolidity/AST.h>
#include <libsolidity/SourceReferenceFormatter.h> #include <libsolidity/SourceReferenceFormatter.h>
#endif
#include <libnatspec/NatspecExpressionEvaluator.h> #include <libnatspec/NatspecExpressionEvaluator.h>
#include <libethereum/Client.h> #include <libethereum/Client.h>
#include <libethereum/Utility.h> #include <libethereum/Utility.h>
@ -113,7 +115,7 @@ void Transact::updateDestination()
if (ui->destination->findText(s, Qt::MatchExactly | Qt::MatchCaseSensitive) == -1) if (ui->destination->findText(s, Qt::MatchExactly | Qt::MatchCaseSensitive) == -1)
ui->destination->addItem(s); ui->destination->addItem(s);
for (int i = 0; i < ui->destination->count(); ++i) for (int i = 0; i < ui->destination->count(); ++i)
if (ui->destination->itemText(i) != "(Create Contract)" && !m_context->fromString(ui->destination->itemText(i))) if (ui->destination->itemText(i) != "(Create Contract)" && !m_context->fromString(ui->destination->itemText(i)).first)
ui->destination->removeItem(i--); ui->destination->removeItem(i--);
} }
@ -139,10 +141,25 @@ void Transact::updateFee()
void Transact::on_destination_currentTextChanged(QString) void Transact::on_destination_currentTextChanged(QString)
{ {
if (ui->destination->currentText().size() && ui->destination->currentText() != "(Create Contract)") if (ui->destination->currentText().size() && ui->destination->currentText() != "(Create Contract)")
if (Address a = m_context->fromString(ui->destination->currentText())) {
ui->calculatedName->setText(m_context->render(a)); auto p = m_context->fromString(ui->destination->currentText());
if (p.first)
ui->calculatedName->setText(m_context->render(p.first));
else else
ui->calculatedName->setText("Unknown Address"); ui->calculatedName->setText("Unknown Address");
if (!p.second.empty())
{
m_data = p.second;
ui->data->setPlainText(QString::fromStdString("0x" + toHex(m_data)));
ui->data->setEnabled(false);
}
else if (!ui->data->isEnabled())
{
m_data.clear();
ui->data->setPlainText("");
ui->data->setEnabled(true);
}
}
else else
ui->calculatedName->setText("Create Contract"); ui->calculatedName->setText("Create Contract");
rejigData(); rejigData();
@ -199,7 +216,7 @@ static tuple<vector<string>, bytes, string> userInputToCode(string const& _user,
boost::replace_all_copy(u, " ", ""); boost::replace_all_copy(u, " ", "");
data = fromHex(u); data = fromHex(u);
} }
#if ETH_SOLIDITY #if ETH_SOLIDITY || !ETH_TRUE
else if (sourceIsSolidity(_user)) else if (sourceIsSolidity(_user))
{ {
dev::solidity::CompilerStack compiler(true); dev::solidity::CompilerStack compiler(true);
@ -329,7 +346,8 @@ void Transact::rejigData()
er = ethereum()->create(s, value(), m_data, gasNeeded, gasPrice()); er = ethereum()->create(s, value(), m_data, gasNeeded, gasPrice());
else else
{ {
to = m_context->fromString(ui->destination->currentText()); // TODO: cache like m_data.
to = m_context->fromString(ui->destination->currentText()).first;
er = ethereum()->call(s, value(), to, m_data, gasNeeded, gasPrice()); er = ethereum()->call(s, value(), to, m_data, gasNeeded, gasPrice());
} }
gasNeeded = (qint64)(er.gasUsed + er.gasRefunded); gasNeeded = (qint64)(er.gasUsed + er.gasRefunded);
@ -415,7 +433,8 @@ void Transact::on_send_clicked()
#endif #endif
} }
else else
ethereum()->submitTransaction(s, value(), m_context->fromString(ui->destination->currentText()), m_data, ui->gas->value(), gasPrice()); // TODO: cache like m_data.
ethereum()->submitTransaction(s, value(), m_context->fromString(ui->destination->currentText()).first, m_data, ui->gas->value(), gasPrice());
close(); close();
} }
@ -434,7 +453,7 @@ void Transact::on_debug_clicked()
State st(ethereum()->postState()); State st(ethereum()->postState());
Transaction t = isCreation() ? Transaction t = isCreation() ?
Transaction(value(), gasPrice(), ui->gas->value(), m_data, st.transactionsFrom(dev::toAddress(s)), s) : Transaction(value(), gasPrice(), ui->gas->value(), m_data, st.transactionsFrom(dev::toAddress(s)), s) :
Transaction(value(), gasPrice(), ui->gas->value(), m_context->fromString(ui->destination->currentText()), m_data, st.transactionsFrom(dev::toAddress(s)), s); Transaction(value(), gasPrice(), ui->gas->value(), m_context->fromString(ui->destination->currentText()).first, m_data, st.transactionsFrom(dev::toAddress(s)), s);
Debugger dw(m_context, this); Debugger dw(m_context, this);
Executive e(st, ethereum()->blockChain(), 0); Executive e(st, ethereum()->blockChain(), 0);
dw.populate(e, t); dw.populate(e, t);

2
alethzero/Transact.ui

@ -11,7 +11,7 @@
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Dialog</string> <string>Transact</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="2" column="1" colspan="2"> <item row="2" column="1" colspan="2">

49
eth/main.cpp

@ -1010,26 +1010,13 @@ int main(int argc, char** argv)
in.read((char*)block.data(), 8); in.read((char*)block.data(), 8);
block.resize(RLP(block, RLP::LaisezFaire).actualSize()); block.resize(RLP(block, RLP::LaisezFaire).actualSize());
in.read((char*)block.data() + 8, block.size() - 8); in.read((char*)block.data() + 8, block.size() - 8);
try switch (web3.ethereum()->injectBlock(block))
{
web3.ethereum()->injectBlock(block);
good++;
}
catch (AlreadyHaveBlock const&)
{
alreadyHave++;
}
catch (UnknownParent const&)
{
unknownParent++;
}
catch (FutureTime const&)
{
futureTime++;
}
catch (...)
{ {
bad++; case ImportResult::Success: good++; break;
case ImportResult::AlreadyKnown: alreadyHave++; break;
case ImportResult::UnknownParent: unknownParent++; break;
case ImportResult::FutureTime: futureTime++; break;
default: bad++; break;
} }
} }
cout << (good + bad + futureTime + unknownParent + alreadyHave) << " total: " << good << " ok, " << alreadyHave << " got, " << futureTime << " future, " << unknownParent << " unknown parent, " << bad << " malformed." << endl; cout << (good + bad + futureTime + unknownParent + alreadyHave) << " total: " << good << " ok, " << alreadyHave << " got, " << futureTime << " future, " << unknownParent << " unknown parent, " << bad << " malformed." << endl;
@ -1137,13 +1124,33 @@ int main(int argc, char** argv)
else if (c && cmd == "setblockfees") else if (c && cmd == "setblockfees")
{ {
iss >> blockFees; iss >> blockFees;
gasPricer->setRefBlockFees(u256(blockFees * 1000)); try
{
gasPricer->setRefBlockFees(u256(blockFees * 1000));
}
catch (Overflow const& _e)
{
cout << boost::diagnostic_information(_e);
}
cout << "Block fees: " << blockFees << endl; cout << "Block fees: " << blockFees << endl;
} }
else if (c && cmd == "setetherprice") else if (c && cmd == "setetherprice")
{ {
iss >> etherPrice; iss >> etherPrice;
gasPricer->setRefPrice(u256(double(ether / 1000) / etherPrice)); if (etherPrice == 0)
cout << "ether price cannot be set to zero" << endl;
else
{
try
{
gasPricer->setRefPrice(u256(double(ether / 1000) / etherPrice));
}
catch (Overflow const& _e)
{
cout << boost::diagnostic_information(_e);
}
}
cout << "ether Price: " << etherPrice << endl; cout << "ether Price: " << etherPrice << endl;
} }
else if (c && cmd == "setpriority") else if (c && cmd == "setpriority")

28
libdevcore/CommonData.h

@ -41,17 +41,22 @@ enum class WhenError
Throw = 1, Throw = 1,
}; };
enum class HexPrefix
{
DontAdd = 0,
Add = 1,
};
/// Convert a series of bytes to the corresponding string of hex duplets. /// Convert a series of bytes to the corresponding string of hex duplets.
/// @param _w specifies the width of the first of the elements. Defaults to two - enough to represent a byte. /// @param _w specifies the width of the first of the elements. Defaults to two - enough to represent a byte.
/// @example toHex("A\x69") == "4169" /// @example toHex("A\x69") == "4169"
template <class _T> template <class _T>
std::string toHex(_T const& _data, int _w = 2) std::string toHex(_T const& _data, int _w = 2, HexPrefix _prefix = HexPrefix::DontAdd)
{ {
std::ostringstream ret; std::ostringstream ret;
unsigned ii = 0; unsigned ii = 0;
for (auto i: _data) for (auto i: _data)
ret << std::hex << std::setfill('0') << std::setw(ii++ ? 2 : _w) << (int)(typename std::make_unsigned<decltype(i)>::type)i; ret << std::hex << std::setfill('0') << std::setw(ii++ ? 2 : _w) << (int)(typename std::make_unsigned<decltype(i)>::type)i;
return ret.str(); return (_prefix == HexPrefix::Add) ? "0x" + ret.str() : ret.str();
} }
/// Converts a (printable) ASCII hex character into the correspnding integer value. /// Converts a (printable) ASCII hex character into the correspnding integer value.
@ -128,9 +133,6 @@ inline std::string toBigEndianString(u160 _val) { std::string ret(20, '\0'); toB
inline bytes toBigEndian(u256 _val) { bytes ret(32); toBigEndian(_val, ret); return ret; } inline bytes toBigEndian(u256 _val) { bytes ret(32); toBigEndian(_val, ret); return ret; }
inline bytes toBigEndian(u160 _val) { bytes ret(20); toBigEndian(_val, ret); return ret; } inline bytes toBigEndian(u160 _val) { bytes ret(20); toBigEndian(_val, ret); return ret; }
/// Convenience function for conversion of a u256 to hex
inline std::string toHex(u256 val) { return toHex(toBigEndian(val)); }
/// Convenience function for toBigEndian. /// Convenience function for toBigEndian.
/// @returns a byte array just big enough to represent @a _val. /// @returns a byte array just big enough to represent @a _val.
template <class _T> template <class _T>
@ -150,15 +152,27 @@ inline bytes toCompactBigEndian(byte _val, unsigned _min = 0)
/// Convenience function for toBigEndian. /// Convenience function for toBigEndian.
/// @returns a string just big enough to represent @a _val. /// @returns a string just big enough to represent @a _val.
template <class _T> template <class _T>
inline std::string toCompactBigEndianString(_T _val) inline std::string toCompactBigEndianString(_T _val, unsigned _min = 0)
{ {
int i = 0; int i = 0;
for (_T v = _val; v; ++i, v >>= 8) {} for (_T v = _val; v; ++i, v >>= 8) {}
std::string ret(i, '\0'); std::string ret(std::max<unsigned>(_min, i), '\0');
toBigEndian(_val, ret); toBigEndian(_val, ret);
return ret; return ret;
} }
/// Convenience function for conversion of a u256 to hex
inline std::string toHex(u256 val, HexPrefix prefix = HexPrefix::DontAdd)
{
std::string str = toHex(toBigEndian(val));
return (prefix == HexPrefix::Add) ? "0x" + str : str;
}
inline std::string toCompactHex(u256 val, HexPrefix prefix = HexPrefix::DontAdd, unsigned _min = 0)
{
std::string str = toHex(toCompactBigEndian(val, _min));
return (prefix == HexPrefix::Add) ? "0x" + str : str;
}
// Algorithms for string and string-like collections. // Algorithms for string and string-like collections.

1
libdevcore/Exceptions.h

@ -51,6 +51,7 @@ struct NoUPnPDevice: virtual Exception {};
struct RootNotFound: virtual Exception {}; struct RootNotFound: virtual Exception {};
struct BadRoot: virtual Exception {}; struct BadRoot: virtual Exception {};
struct FileError: virtual Exception {}; struct FileError: virtual Exception {};
struct Overflow: virtual Exception {};
struct InterfaceNotSupported: virtual Exception { public: InterfaceNotSupported(std::string _f): Exception("Interface " + _f + " not supported.") {} }; struct InterfaceNotSupported: virtual Exception { public: InterfaceNotSupported(std::string _f): Exception("Interface " + _f + " not supported.") {} };
// error information to be added to exceptions // error information to be added to exceptions

2
libdevcore/Log.h

@ -181,7 +181,7 @@ protected:
bool m_autospacing = false; bool m_autospacing = false;
unsigned m_verbosity = 0; unsigned m_verbosity = 0;
std::stringstream m_sstr; ///< The accrued log entry. std::stringstream m_sstr; ///< The accrued log entry.
LogTag m_logTag; LogTag m_logTag = LogTag::None;
}; };
/// Logging class, iostream-like, that can be shifted to. /// Logging class, iostream-like, that can be shifted to.

4
libdevcrypto/Common.cpp

@ -40,8 +40,8 @@ bool dev::SignatureStruct::isValid() const
if (v > 1 || if (v > 1 ||
r >= h256("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141") || r >= h256("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141") ||
s >= h256("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141") || s >= h256("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141") ||
s < h256("0x01") || s < h256(1) ||
r < h256("0x01")) r < h256(1))
return false; return false;
return true; return true;
} }

4
libethash/CMakeLists.txt

@ -43,3 +43,7 @@ add_library(${LIBRARY} ${FILES})
if (CRYPTOPP_FOUND) if (CRYPTOPP_FOUND)
TARGET_LINK_LIBRARIES(${LIBRARY} ${CRYPTOPP_LIBRARIES}) TARGET_LINK_LIBRARIES(${LIBRARY} ${CRYPTOPP_LIBRARIES})
endif() endif()
if (NOT ETHASHCL)
install( TARGETS ${LIBRARY} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
endif ()

0
libethereum/ABI.cpp → libethcore/ABI.cpp

8
libethereum/ABI.h → libethcore/ABI.h

@ -31,6 +31,14 @@ namespace dev
namespace eth namespace eth
{ {
inline string32 toString32(std::string const& _s)
{
string32 ret;
for (unsigned i = 0; i < 32; ++i)
ret[i] = i < _s.size() ? _s[i] : 0;
return ret;
}
template <class T> struct ABISerialiser {}; template <class T> struct ABISerialiser {};
template <unsigned N> struct ABISerialiser<FixedHash<N>> { static bytes serialise(FixedHash<N> const& _t) { static_assert(N <= 32, "Cannot serialise hash > 32 bytes."); static_assert(N > 0, "Cannot serialise zero-length hash."); return bytes(32 - N, 0) + _t.asBytes(); } }; template <unsigned N> struct ABISerialiser<FixedHash<N>> { static bytes serialise(FixedHash<N> const& _t) { static_assert(N <= 32, "Cannot serialise hash > 32 bytes."); static_assert(N > 0, "Cannot serialise zero-length hash."); return bytes(32 - N, 0) + _t.asBytes(); } };
template <> struct ABISerialiser<u256> { static bytes serialise(u256 const& _t) { return h256(_t).asBytes(); } }; template <> struct ABISerialiser<u256> { static bytes serialise(u256 const& _t) { return h256(_t).asBytes(); } };

55
libethcore/ICAP.cpp

@ -21,9 +21,11 @@
#include "ICAP.h" #include "ICAP.h"
#include <boost/algorithm/string/case_conv.hpp> #include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string.hpp>
#include <libdevcore/Base64.h> #include <libdevcore/Base64.h>
#include <libdevcrypto/SHA3.h> #include <libdevcrypto/SHA3.h>
#include "Exceptions.h" #include "Exceptions.h"
#include "ABI.h"
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;
@ -80,13 +82,11 @@ ICAP ICAP::decoded(std::string const& _encoded)
{ {
ret.m_type = Indirect; ret.m_type = Indirect;
ret.m_asset = data.substr(0, 3); ret.m_asset = data.substr(0, 3);
if (ret.m_asset == "XET") if (ret.m_asset == "XET" || ret.m_asset == "ETH")
{ {
ret.m_institution = data.substr(3, 4); ret.m_institution = data.substr(3, 4);
ret.m_client = data.substr(7); ret.m_client = data.substr(7);
} }
else if (ret.m_asset == "ETH")
ret.m_client = data.substr(4);
else else
throw InvalidICAP(); throw InvalidICAP();
} }
@ -101,7 +101,7 @@ std::string ICAP::encoded() const
if (m_type == Direct) if (m_type == Direct)
{ {
if (!!m_direct[0]) if (!!m_direct[0])
return string(); throw InvalidICAP();
std::string d = toBase36<Address::size>(m_direct); std::string d = toBase36<Address::size>(m_direct);
while (d.size() < 30) while (d.size() < 30)
d = "0" + d; d = "0" + d;
@ -113,44 +113,45 @@ std::string ICAP::encoded() const
m_asset.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos || m_asset.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos ||
m_institution.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos || m_institution.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos ||
m_client.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos || m_client.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos ||
m_asset.size() != 3 m_asset.size() != 3 ||
(boost::to_upper_copy(m_asset) != "XET" && boost::to_upper_copy(m_asset) != "ETH") ||
m_institution.size() != 4 ||
m_client.size() != 9
) )
throw InvalidICAP(); throw InvalidICAP();
if (boost::to_upper_copy(m_asset) == "XET")
{
if (m_institution.size() != 4 || m_client.size() != 9)
throw InvalidICAP();
}
else if (boost::to_upper_copy(m_asset) == "ETH")
{
if (m_client.size() != 13)
throw InvalidICAP();
}
else
throw InvalidICAP();
return iban("XE", m_asset + m_institution + m_client); return iban("XE", m_asset + m_institution + m_client);
} }
else else
throw InvalidICAP(); throw InvalidICAP();
} }
Address ICAP::lookup(std::function<bytes(Address, bytes)> const& _call, Address const& _reg) const pair<Address, bytes> ICAP::lookup(std::function<bytes(Address, bytes)> const& _call, Address const& _reg) const
{ {
(void)_call; auto resolve = [&](string const& s)
(void)_reg; {
vector<string> ss;
boost::algorithm::split(ss, s, boost::is_any_of("/"));
Address r = _reg;
for (unsigned i = 0; i < ss.size() - 1; ++i)
r = abiOut<Address>(_call(r, abiIn("subRegistrar(bytes32)", toString32(ss[i]))));
return abiOut<Address>(_call(r, abiIn("addr(bytes32)", toString32(ss.back()))));
};
if (m_asset == "XET") if (m_asset == "XET")
{ {
// TODO Address a = resolve(m_institution);
throw InterfaceNotSupported("ICAP::lookup(), XET asset"); bytes d = abiIn("deposit(uint64)", fromBase36<8>(m_client));
return make_pair(a, d);
} }
else if (m_asset == "ETH") else if (m_asset == "ETH")
{ {
// TODO if (m_institution == "XREG")
// return resolve(m_institution + "/" + m_client).primary(); return make_pair(resolve(m_client), bytes());
throw InterfaceNotSupported("ICAP::lookup(), ETH asset"); else if (m_institution[0] != 'X')
return make_pair(resolve(m_institution + "/" + m_client), bytes());
else
throw InterfaceNotSupported("ICAP::lookup(), bad institution");
} }
else throw InterfaceNotSupported("ICAP::lookup(), bad asset");
throw InterfaceNotSupported("ICAP::lookup(), non XET asset");
} }
} }

13
libethcore/ICAP.h

@ -25,6 +25,7 @@
#include <string> #include <string>
#include <functional> #include <functional>
#include <boost/algorithm/string/case_conv.hpp>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/Exceptions.h> #include <libdevcore/Exceptions.h>
#include <libdevcore/FixedHash.h> #include <libdevcore/FixedHash.h>
@ -49,13 +50,13 @@ public:
/// Construct null ICAP object. /// Construct null ICAP object.
ICAP() = default; ICAP() = default;
/// Construct a direct ICAP object for given target address. Must have a zero first byte. /// Construct a direct ICAP object for given target address. Must have a zero first byte.
ICAP(Address const& _target): m_direct(_target) {} ICAP(Address const& _target): m_type(Direct), m_direct(_target) {}
/// Construct an indirect ICAP object for given target name. /// Construct an indirect ICAP object for given target name.
ICAP(std::string const& _target): m_client(_target), m_asset("ETH") {} ICAP(std::string const& _target): m_type(Indirect), m_client(boost::algorithm::to_upper_copy(_target)), m_asset("ETH") {}
/// Construct an indirect ICAP object for given client and institution names. /// Construct an indirect ICAP object for given client and institution names.
ICAP(std::string const& _client, std::string const& _inst): m_client(_client), m_institution(_inst), m_asset("XET") {} ICAP(std::string const& _client, std::string const& _inst): m_type(Indirect), m_client(boost::algorithm::to_upper_copy(_client)), m_institution(boost::algorithm::to_upper_copy(_inst)), m_asset("XET") {}
/// Construct an indirect ICAP object for given client, institution and asset names. You generally don't want to use this. /// Construct an indirect ICAP object for given client, institution and asset names. You generally don't want to use this.
ICAP(std::string const& _c, std::string const& _i, std::string const& _a): m_client(_c), m_institution(_i), m_asset(_a) {} ICAP(std::string const& _c, std::string const& _i, std::string const& _a): m_type(Indirect), m_client(boost::algorithm::to_upper_copy(_c)), m_institution(boost::algorithm::to_upper_copy(_i)), m_asset(boost::algorithm::to_upper_copy(_a)) {}
/// Type of ICAP address. /// Type of ICAP address.
enum Type enum Type
@ -88,10 +89,10 @@ public:
/// @returns client name. Only valid when type() == Indirect and asset() == "XET". /// @returns client name. Only valid when type() == Indirect and asset() == "XET".
std::string const& client() const { return m_type == Indirect && m_asset == "XET" ? m_client : EmptyString; } std::string const& client() const { return m_type == Indirect && m_asset == "XET" ? m_client : EmptyString; }
/// @returns target address. Always valid, but requires the Registry address and a function to make calls. /// @returns target address. Always valid, but requires the Registry address and a function to make calls.
Address address(std::function<bytes(Address, bytes)> const& _call, Address const& _reg) const { return m_type == Direct ? direct() : m_type == Indirect ? lookup(_call, _reg) : Address(); } std::pair<Address, bytes> address(std::function<bytes(Address, bytes)> const& _call, Address const& _reg) const { return m_type == Direct ? make_pair(direct(), bytes()) : m_type == Indirect ? lookup(_call, _reg) : make_pair(Address(), bytes()); }
/// @returns target address. Looks up through the given Registry and call function. Only valid when type() == Indirect. /// @returns target address. Looks up through the given Registry and call function. Only valid when type() == Indirect.
Address lookup(std::function<bytes(Address, bytes)> const& _call, Address const& _reg) const; std::pair<Address, bytes> lookup(std::function<bytes(Address, bytes)> const& _call, Address const& _reg) const;
private: private:
Type m_type = Invalid; Type m_type = Invalid;

19
libethereum/BlockChain.cpp

@ -336,16 +336,27 @@ tuple<h256s, h256s, bool> BlockChain::sync(BlockQueue& _bq, OverlayDB const& _st
return make_tuple(fresh, dead, _bq.doneDrain(badBlocks)); return make_tuple(fresh, dead, _bq.doneDrain(badBlocks));
} }
ImportRoute BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, ImportRequirements::value _ir) noexcept pair<ImportResult, ImportRoute> BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, ImportRequirements::value _ir) noexcept
{ {
try try
{ {
return import(_block, _stateDB, _ir); return make_pair(ImportResult::Success, import(_block, _stateDB, _ir));
}
catch (UnknownParent&)
{
return make_pair(ImportResult::UnknownParent, make_pair(h256s(), h256s()));
}
catch (AlreadyHaveBlock&)
{
return make_pair(ImportResult::AlreadyKnown, make_pair(h256s(), h256s()));
}
catch (FutureTime&)
{
return make_pair(ImportResult::FutureTime, make_pair(h256s(), h256s()));
} }
catch (...) catch (...)
{ {
cwarn << "Unexpected exception! Could not import block!" << boost::current_exception_diagnostic_information(); return make_pair(ImportResult::Malformed, make_pair(h256s(), h256s()));
return make_pair(h256s(), h256s());
} }
} }

2
libethereum/BlockChain.h

@ -105,7 +105,7 @@ public:
/// Attempt to import the given block directly into the CanonBlockChain and sync with the state DB. /// 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. /// @returns the block hashes of any blocks that came into/went out of the canonical block chain.
ImportRoute attemptImport(bytes const& _block, OverlayDB const& _stateDB, ImportRequirements::value _ir = ImportRequirements::Default) noexcept; std::pair<ImportResult, ImportRoute> attemptImport(bytes const& _block, OverlayDB const& _stateDB, ImportRequirements::value _ir = ImportRequirements::Default) noexcept;
/// Import block into disk-backed DB /// Import block into disk-backed DB
/// @returns the block hashes of any blocks that came into/went out of the canonical block chain. /// @returns the block hashes of any blocks that came into/went out of the canonical block chain.

60
libethereum/Client.cpp

@ -24,6 +24,7 @@
#include <chrono> #include <chrono>
#include <thread> #include <thread>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/math/distributions/normal.hpp>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libdevcore/StructuredLogger.h> #include <libdevcore/StructuredLogger.h>
#include <libp2p/Host.h> #include <libp2p/Host.h>
@ -81,8 +82,10 @@ void BasicGasPricer::update(BlockChain const& _bc)
h256 p = _bc.currentHash(); h256 p = _bc.currentHash();
m_gasPerBlock = _bc.info(p).gasLimit; m_gasPerBlock = _bc.info(p).gasLimit;
map<u256, unsigned> dist; map<u256, u256> dist;
unsigned total = 0; u256 total = 0;
// make gasPrice versus gasUsed distribution for the last 1000 blocks
while (c < 1000 && p) while (c < 1000 && p)
{ {
BlockInfo bi = _bc.info(p); BlockInfo bi = _bc.info(p);
@ -91,29 +94,53 @@ void BasicGasPricer::update(BlockChain const& _bc)
auto bb = _bc.block(p); auto bb = _bc.block(p);
RLP r(bb); RLP r(bb);
BlockReceipts brs(_bc.receipts(bi.hash())); BlockReceipts brs(_bc.receipts(bi.hash()));
for (unsigned i = 0; i < r[1].size(); ++i) size_t i = 0;
for (auto const& tr: r[1])
{ {
auto gu = brs.receipts[i].gasUsed(); Transaction tx(tr.data(), CheckTransaction::None);
dist[Transaction(r[1][i].data(), CheckTransaction::None).gasPrice()] += (unsigned)brs.receipts[i].gasUsed(); u256 gu = brs.receipts[i].gasUsed();
total += (unsigned)gu; dist[tx.gasPrice()] += gu;
total += gu;
i++;
} }
} }
p = bi.parentHash; p = bi.parentHash;
++c; ++c;
} }
// fill m_octiles with weighted gasPrices
if (total > 0) if (total > 0)
{ {
unsigned t = 0;
unsigned q = 1;
m_octiles[0] = dist.begin()->first; m_octiles[0] = dist.begin()->first;
// calc mean
u256 mean = 0;
for (auto const& i: dist) for (auto const& i: dist)
mean += i.first * i.second;
mean /= total;
// calc standard deviation
u256 sdSquared = 0;
for (auto const& i: dist)
sdSquared += i.second * (i.first - mean) * (i.first - mean);
sdSquared /= total;
if (sdSquared)
{
long double sd = sqrt(sdSquared.convert_to<long double>());
long double normalizedSd = sd / mean.convert_to<long double>();
// calc octiles normalized to gaussian distribution
boost::math::normal gauss(1.0, (normalizedSd > 0.01) ? normalizedSd : 0.01);
for (size_t i = 1; i < 8; i++)
m_octiles[i] = u256(mean.convert_to<long double>() * boost::math::quantile(gauss, i / 8.0));
m_octiles[8] = dist.rbegin()->first;
}
else
{ {
for (; t <= total * q / 8 && t + i.second > total * q / 8; ++q) for (size_t i = 0; i < 9; i++)
m_octiles[q] = i.first; m_octiles[i] = (i + 1) * mean / 5;
if (q > 7)
break;
} }
m_octiles[8] = dist.rbegin()->first;
} }
} }
@ -671,13 +698,6 @@ eth::State Client::state(unsigned _txi) const
return m_postMine.fromPending(_txi); return m_postMine.fromPending(_txi);
} }
void Client::inject(bytesConstRef _rlp)
{
startWorking();
m_tq.import(_rlp);
}
void Client::flushTransactions() void Client::flushTransactions()
{ {
doWork(); doWork();

9
libethereum/Client.h

@ -35,12 +35,12 @@
#include <libdevcore/Guards.h> #include <libdevcore/Guards.h>
#include <libdevcore/Worker.h> #include <libdevcore/Worker.h>
#include <libethcore/Params.h> #include <libethcore/Params.h>
#include <libethcore/ABI.h>
#include <libp2p/Common.h> #include <libp2p/Common.h>
#include "CanonBlockChain.h" #include "CanonBlockChain.h"
#include "TransactionQueue.h" #include "TransactionQueue.h"
#include "State.h" #include "State.h"
#include "CommonNet.h" #include "CommonNet.h"
#include "ABI.h"
#include "Farm.h" #include "Farm.h"
#include "ClientBase.h" #include "ClientBase.h"
@ -77,8 +77,8 @@ class BasicGasPricer: public GasPricer
public: public:
explicit BasicGasPricer(u256 _weiPerRef, u256 _refsPerBlock): m_weiPerRef(_weiPerRef), m_refsPerBlock(_refsPerBlock) {} explicit BasicGasPricer(u256 _weiPerRef, u256 _refsPerBlock): m_weiPerRef(_weiPerRef), m_refsPerBlock(_refsPerBlock) {}
void setRefPrice(u256 _weiPerRef) { m_weiPerRef = _weiPerRef; } void setRefPrice(u256 _weiPerRef) { if ((bigint)m_refsPerBlock * _weiPerRef > std::numeric_limits<u256>::max() ) BOOST_THROW_EXCEPTION(Overflow() << errinfo_comment("ether price * block fees is larger than 2**256-1, choose a smaller number.") ); else m_weiPerRef = _weiPerRef; }
void setRefBlockFees(u256 _refsPerBlock) { m_refsPerBlock = _refsPerBlock; } void setRefBlockFees(u256 _refsPerBlock) { if ((bigint)m_weiPerRef * _refsPerBlock > std::numeric_limits<u256>::max() ) BOOST_THROW_EXCEPTION(Overflow() << errinfo_comment("ether price * block fees is larger than 2**256-1, choose a smaller number.") ); else m_refsPerBlock = _refsPerBlock; }
u256 ask(State const&) const override { return m_weiPerRef * m_refsPerBlock / m_gasPerBlock; } u256 ask(State const&) const override { return m_weiPerRef * m_refsPerBlock / m_gasPerBlock; }
u256 bid(TransactionPriority _p = TransactionPriority::Medium) const override { return m_octiles[(int)_p] > 0 ? m_octiles[(int)_p] : (m_weiPerRef * m_refsPerBlock / m_gasPerBlock); } u256 bid(TransactionPriority _p = TransactionPriority::Medium) const override { return m_octiles[(int)_p] > 0 ? m_octiles[(int)_p] : (m_weiPerRef * m_refsPerBlock / m_gasPerBlock); }
@ -133,9 +133,6 @@ public:
/// Resets the gas pricer to some other object. /// Resets the gas pricer to some other object.
void setGasPricer(std::shared_ptr<GasPricer> _gp) { m_gp = _gp; } void setGasPricer(std::shared_ptr<GasPricer> _gp) { m_gp = _gp; }
/// Injects the RLP-encoded transaction given by the _rlp into the transaction queue directly.
virtual void inject(bytesConstRef _rlp);
/// Blocks until all pending transactions have been processed. /// Blocks until all pending transactions have been processed.
virtual void flushTransactions() override; virtual void flushTransactions() override;

4
libethereum/ClientBase.cpp

@ -114,9 +114,9 @@ ExecutionResult ClientBase::create(Secret _secret, u256 _value, bytes const& _da
return ret; return ret;
} }
void ClientBase::injectBlock(bytes const& _block) ImportResult ClientBase::injectBlock(bytes const& _block)
{ {
bc().import(_block, preMine().db()); return bc().attemptImport(_block, preMine().db()).first;
} }
u256 ClientBase::balanceAt(Address _a, BlockNumber _block) const u256 ClientBase::balanceAt(Address _a, BlockNumber _block) const

3
libethereum/ClientBase.h

@ -127,7 +127,8 @@ public:
virtual Transactions pending() const override; virtual Transactions pending() const override;
virtual h256s pendingHashes() const override; virtual h256s pendingHashes() const override;
void injectBlock(bytes const& _block); ImportResult injectTransaction(bytes const& _rlp) override { prepareForTransaction(); return m_tq.import(_rlp); }
ImportResult injectBlock(bytes const& _block);
using Interface::diff; using Interface::diff;
virtual StateDiff diff(unsigned _txi, h256 _block) const override; virtual StateDiff diff(unsigned _txi, h256 _block) const override;

6
libethereum/Interface.h

@ -85,6 +85,12 @@ public:
virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) = 0; 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); } 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); }
/// Injects the RLP-encoded transaction given by the _rlp into the transaction queue directly.
virtual ImportResult injectTransaction(bytes const& _rlp) = 0;
/// Injects the RLP-encoded block given by the _rlp into the block queue directly.
virtual ImportResult injectBlock(bytes const& _block) = 0;
// [STATE-QUERY API] // [STATE-QUERY API]
int getDefault() const { return m_default; } int getDefault() const { return m_default; }

6
libethereum/Transaction.h

@ -165,6 +165,12 @@ public:
/// @returns the receiving address of the message-call transaction (undefined for contract-creation transactions). /// @returns the receiving address of the message-call transaction (undefined for contract-creation transactions).
Address receiveAddress() const { return m_receiveAddress; } Address receiveAddress() const { return m_receiveAddress; }
/// Synonym for receiveAddress().
Address to() const { return m_receiveAddress; }
/// Synonym for safeSender().
Address from() const { return safeSender(); }
/// @returns the data associated with this (message-call) transaction. Synonym for initCode(). /// @returns the data associated with this (message-call) transaction. Synonym for initCode().
bytes const& data() const { return m_data; } bytes const& data() const { return m_data; }
/// @returns the initialisation code associated with this (contract-creation) transaction. Synonym for data(). /// @returns the initialisation code associated with this (contract-creation) transaction. Synonym for data().

13
libevmcore/AssemblyItem.h

@ -43,9 +43,16 @@ class AssemblyItem
public: public:
enum class JumpType { Ordinary, IntoFunction, OutOfFunction }; enum class JumpType { Ordinary, IntoFunction, OutOfFunction };
AssemblyItem(u256 _push): m_type(Push), m_data(_push) {} AssemblyItem(u256 _push, SourceLocation const& _location = SourceLocation()):
AssemblyItem(Instruction _i): m_type(Operation), m_data((byte)_i) {} AssemblyItem(Push, _push, _location) { }
AssemblyItem(AssemblyItemType _type, u256 _data = 0): m_type(_type), m_data(_data) {} AssemblyItem(Instruction _i, SourceLocation const& _location = SourceLocation()):
AssemblyItem(Operation, byte(_i), _location) { }
AssemblyItem(AssemblyItemType _type, u256 _data = 0, SourceLocation const& _location = SourceLocation()):
m_type(_type),
m_data(_data),
m_location(_location)
{
}
AssemblyItem tag() const { assertThrow(m_type == PushTag || m_type == Tag, Exception, ""); return AssemblyItem(Tag, m_data); } AssemblyItem tag() const { assertThrow(m_type == PushTag || m_type == Tag, Exception, ""); return AssemblyItem(Tag, m_data); }
AssemblyItem pushTag() const { assertThrow(m_type == PushTag || m_type == Tag, Exception, ""); return AssemblyItem(PushTag, m_data); } AssemblyItem pushTag() const { assertThrow(m_type == PushTag || m_type == Tag, Exception, ""); return AssemblyItem(PushTag, m_data); }

176
libevmcore/CommonSubexpressionEliminator.cpp

@ -41,9 +41,9 @@ vector<AssemblyItem> CommonSubexpressionEliminator::getOptimizedItems()
if (!m_stackElements.empty()) if (!m_stackElements.empty())
minHeight = min(minHeight, m_stackElements.begin()->first); minHeight = min(minHeight, m_stackElements.begin()->first);
for (int height = minHeight; height <= 0; ++height) for (int height = minHeight; height <= 0; ++height)
initialStackContents[height] = initialStackElement(height); initialStackContents[height] = initialStackElement(height, SourceLocation());
for (int height = minHeight; height <= m_stackHeight; ++height) for (int height = minHeight; height <= m_stackHeight; ++height)
targetStackContents[height] = stackElement(height); targetStackContents[height] = stackElement(height, SourceLocation());
// Debug info: // Debug info:
//stream(cout, initialStackContents, targetStackContents); //stream(cout, initialStackContents, targetStackContents);
@ -111,30 +111,46 @@ void CommonSubexpressionEliminator::feedItem(AssemblyItem const& _item, bool _co
if (SemanticInformation::isDupInstruction(_item)) if (SemanticInformation::isDupInstruction(_item))
setStackElement( setStackElement(
m_stackHeight + 1, m_stackHeight + 1,
stackElement(m_stackHeight - int(instruction) + int(Instruction::DUP1)) stackElement(
m_stackHeight - int(instruction) + int(Instruction::DUP1),
_item.getLocation()
)
); );
else if (SemanticInformation::isSwapInstruction(_item)) else if (SemanticInformation::isSwapInstruction(_item))
swapStackElements( swapStackElements(
m_stackHeight, m_stackHeight,
m_stackHeight - 1 - int(instruction) + int(Instruction::SWAP1) m_stackHeight - 1 - int(instruction) + int(Instruction::SWAP1),
_item.getLocation()
); );
else if (instruction != Instruction::POP) else if (instruction != Instruction::POP)
{ {
vector<Id> arguments(info.args); vector<Id> arguments(info.args);
for (int i = 0; i < info.args; ++i) for (int i = 0; i < info.args; ++i)
arguments[i] = stackElement(m_stackHeight - i); arguments[i] = stackElement(m_stackHeight - i, _item.getLocation());
if (_item.instruction() == Instruction::SSTORE) if (_item.instruction() == Instruction::SSTORE)
storeInStorage(arguments[0], arguments[1]); storeInStorage(arguments[0], arguments[1], _item.getLocation());
else if (_item.instruction() == Instruction::SLOAD) else if (_item.instruction() == Instruction::SLOAD)
setStackElement(m_stackHeight + _item.deposit(), loadFromStorage(arguments[0])); setStackElement(
m_stackHeight + _item.deposit(),
loadFromStorage(arguments[0], _item.getLocation())
);
else if (_item.instruction() == Instruction::MSTORE) else if (_item.instruction() == Instruction::MSTORE)
storeInMemory(arguments[0], arguments[1]); storeInMemory(arguments[0], arguments[1], _item.getLocation());
else if (_item.instruction() == Instruction::MLOAD) else if (_item.instruction() == Instruction::MLOAD)
setStackElement(m_stackHeight + _item.deposit(), loadFromMemory(arguments[0])); setStackElement(
m_stackHeight + _item.deposit(),
loadFromMemory(arguments[0], _item.getLocation())
);
else if (_item.instruction() == Instruction::SHA3) else if (_item.instruction() == Instruction::SHA3)
setStackElement(m_stackHeight + _item.deposit(), applySha3(arguments.at(0), arguments.at(1))); setStackElement(
m_stackHeight + _item.deposit(),
applySha3(arguments.at(0), arguments.at(1), _item.getLocation())
);
else else
setStackElement(m_stackHeight + _item.deposit(), m_expressionClasses.find(_item, arguments, _copyItem)); setStackElement(
m_stackHeight + _item.deposit(),
m_expressionClasses.find(_item, arguments, _copyItem)
);
} }
m_stackHeight += _item.deposit(); m_stackHeight += _item.deposit();
} }
@ -145,22 +161,27 @@ void CommonSubexpressionEliminator::optimizeBreakingItem()
if (!m_breakingItem || *m_breakingItem != AssemblyItem(Instruction::JUMPI)) if (!m_breakingItem || *m_breakingItem != AssemblyItem(Instruction::JUMPI))
return; return;
static AssemblyItem s_jump = Instruction::JUMP; SourceLocation const& location = m_breakingItem->getLocation();
AssemblyItem::JumpType jumpType = m_breakingItem->getJumpType();
Id condition = stackElement(m_stackHeight - 1); Id condition = stackElement(m_stackHeight - 1, location);
Id zero = m_expressionClasses.find(u256(0)); Id zero = m_expressionClasses.find(u256(0));
if (m_expressionClasses.knownToBeDifferent(condition, zero)) if (m_expressionClasses.knownToBeDifferent(condition, zero))
{ {
feedItem(Instruction::SWAP1, true); feedItem(AssemblyItem(Instruction::SWAP1, location), true);
feedItem(Instruction::POP, true); feedItem(AssemblyItem(Instruction::POP, location), true);
m_breakingItem = &s_jump;
AssemblyItem item(Instruction::JUMP, location);
item.setJumpType(jumpType);
m_breakingItem = m_expressionClasses.storeItem(item);
return; return;
} }
Id negatedCondition = m_expressionClasses.find(Instruction::ISZERO, {condition}); Id negatedCondition = m_expressionClasses.find(Instruction::ISZERO, {condition});
if (m_expressionClasses.knownToBeDifferent(negatedCondition, zero)) if (m_expressionClasses.knownToBeDifferent(negatedCondition, zero))
{ {
feedItem(Instruction::POP, true); AssemblyItem it(Instruction::POP, location);
feedItem(Instruction::POP, true); feedItem(it, true);
feedItem(it, true);
m_breakingItem = nullptr; m_breakingItem = nullptr;
} }
} }
@ -170,33 +191,43 @@ void CommonSubexpressionEliminator::setStackElement(int _stackHeight, Id _class)
m_stackElements[_stackHeight] = _class; m_stackElements[_stackHeight] = _class;
} }
void CommonSubexpressionEliminator::swapStackElements(int _stackHeightA, int _stackHeightB) void CommonSubexpressionEliminator::swapStackElements(
int _stackHeightA,
int _stackHeightB,
SourceLocation const& _location
)
{ {
assertThrow(_stackHeightA != _stackHeightB, OptimizerException, "Swap on same stack elements."); assertThrow(_stackHeightA != _stackHeightB, OptimizerException, "Swap on same stack elements.");
// ensure they are created // ensure they are created
stackElement(_stackHeightA); stackElement(_stackHeightA, _location);
stackElement(_stackHeightB); stackElement(_stackHeightB, _location);
swap(m_stackElements[_stackHeightA], m_stackElements[_stackHeightB]); swap(m_stackElements[_stackHeightA], m_stackElements[_stackHeightB]);
} }
ExpressionClasses::Id CommonSubexpressionEliminator::stackElement(int _stackHeight) ExpressionClasses::Id CommonSubexpressionEliminator::stackElement(
int _stackHeight,
SourceLocation const& _location
)
{ {
if (m_stackElements.count(_stackHeight)) if (m_stackElements.count(_stackHeight))
return m_stackElements.at(_stackHeight); return m_stackElements.at(_stackHeight);
// Stack element not found (not assigned yet), create new equivalence class. // Stack element not found (not assigned yet), create new equivalence class.
return m_stackElements[_stackHeight] = initialStackElement(_stackHeight); return m_stackElements[_stackHeight] = initialStackElement(_stackHeight, _location);
} }
ExpressionClasses::Id CommonSubexpressionEliminator::initialStackElement(int _stackHeight) ExpressionClasses::Id CommonSubexpressionEliminator::initialStackElement(
int _stackHeight,
SourceLocation const& _location
)
{ {
assertThrow(_stackHeight <= 0, OptimizerException, "Initial stack element of positive height requested."); assertThrow(_stackHeight <= 0, OptimizerException, "Initial stack element of positive height requested.");
assertThrow(_stackHeight > -16, StackTooDeepException, ""); assertThrow(_stackHeight > -16, StackTooDeepException, "");
// This is a special assembly item that refers to elements pre-existing on the initial stack. // This is a special assembly item that refers to elements pre-existing on the initial stack.
return m_expressionClasses.find(AssemblyItem(dupInstruction(1 - _stackHeight))); return m_expressionClasses.find(AssemblyItem(dupInstruction(1 - _stackHeight), _location));
} }
void CommonSubexpressionEliminator::storeInStorage(Id _slot, Id _value) void CommonSubexpressionEliminator::storeInStorage(Id _slot, Id _value, SourceLocation const& _location)
{ {
if (m_storageContent.count(_slot) && m_storageContent[_slot] == _value) if (m_storageContent.count(_slot) && m_storageContent[_slot] == _value)
// do not execute the storage if we know that the value is already there // do not execute the storage if we know that the value is already there
@ -210,22 +241,25 @@ void CommonSubexpressionEliminator::storeInStorage(Id _slot, Id _value)
if (m_expressionClasses.knownToBeDifferent(storageItem.first, _slot) || storageItem.second == _value) if (m_expressionClasses.knownToBeDifferent(storageItem.first, _slot) || storageItem.second == _value)
storageContents.insert(storageItem); storageContents.insert(storageItem);
m_storageContent = move(storageContents); m_storageContent = move(storageContents);
Id id = m_expressionClasses.find(Instruction::SSTORE, {_slot, _value}, true, m_sequenceNumber);
AssemblyItem item(Instruction::SSTORE, _location);
Id id = m_expressionClasses.find(item, {_slot, _value}, true, m_sequenceNumber);
m_storeOperations.push_back(StoreOperation(StoreOperation::Storage, _slot, m_sequenceNumber, id)); m_storeOperations.push_back(StoreOperation(StoreOperation::Storage, _slot, m_sequenceNumber, id));
m_storageContent[_slot] = _value; m_storageContent[_slot] = _value;
// increment a second time so that we get unique sequence numbers for writes // increment a second time so that we get unique sequence numbers for writes
m_sequenceNumber++; m_sequenceNumber++;
} }
ExpressionClasses::Id CommonSubexpressionEliminator::loadFromStorage(Id _slot) ExpressionClasses::Id CommonSubexpressionEliminator::loadFromStorage(Id _slot, SourceLocation const& _location)
{ {
if (m_storageContent.count(_slot)) if (m_storageContent.count(_slot))
return m_storageContent.at(_slot); return m_storageContent.at(_slot);
else
return m_storageContent[_slot] = m_expressionClasses.find(Instruction::SLOAD, {_slot}, true, m_sequenceNumber); AssemblyItem item(Instruction::SLOAD, _location);
return m_storageContent[_slot] = m_expressionClasses.find(item, {_slot}, true, m_sequenceNumber);
} }
void CommonSubexpressionEliminator::storeInMemory(Id _slot, Id _value) void CommonSubexpressionEliminator::storeInMemory(Id _slot, Id _value, SourceLocation const& _location)
{ {
if (m_memoryContent.count(_slot) && m_memoryContent[_slot] == _value) if (m_memoryContent.count(_slot) && m_memoryContent[_slot] == _value)
// do not execute the store if we know that the value is already there // do not execute the store if we know that the value is already there
@ -237,34 +271,45 @@ void CommonSubexpressionEliminator::storeInMemory(Id _slot, Id _value)
if (m_expressionClasses.knownToBeDifferentBy32(memoryItem.first, _slot)) if (m_expressionClasses.knownToBeDifferentBy32(memoryItem.first, _slot))
memoryContents.insert(memoryItem); memoryContents.insert(memoryItem);
m_memoryContent = move(memoryContents); m_memoryContent = move(memoryContents);
Id id = m_expressionClasses.find(Instruction::MSTORE, {_slot, _value}, true, m_sequenceNumber);
AssemblyItem item(Instruction::MSTORE, _location);
Id id = m_expressionClasses.find(item, {_slot, _value}, true, m_sequenceNumber);
m_storeOperations.push_back(StoreOperation(StoreOperation::Memory, _slot, m_sequenceNumber, id)); m_storeOperations.push_back(StoreOperation(StoreOperation::Memory, _slot, m_sequenceNumber, id));
m_memoryContent[_slot] = _value; m_memoryContent[_slot] = _value;
// increment a second time so that we get unique sequence numbers for writes // increment a second time so that we get unique sequence numbers for writes
m_sequenceNumber++; m_sequenceNumber++;
} }
ExpressionClasses::Id CommonSubexpressionEliminator::loadFromMemory(Id _slot) ExpressionClasses::Id CommonSubexpressionEliminator::loadFromMemory(Id _slot, SourceLocation const& _location)
{ {
if (m_memoryContent.count(_slot)) if (m_memoryContent.count(_slot))
return m_memoryContent.at(_slot); return m_memoryContent.at(_slot);
else
return m_memoryContent[_slot] = m_expressionClasses.find(Instruction::MLOAD, {_slot}, true, m_sequenceNumber); AssemblyItem item(Instruction::MLOAD, _location);
return m_memoryContent[_slot] = m_expressionClasses.find(item, {_slot}, true, m_sequenceNumber);
} }
CommonSubexpressionEliminator::Id CommonSubexpressionEliminator::applySha3(Id _start, Id _length) CommonSubexpressionEliminator::Id CommonSubexpressionEliminator::applySha3(
Id _start,
Id _length,
SourceLocation const& _location
)
{ {
AssemblyItem sha3Item(Instruction::SHA3, _location);
// Special logic if length is a short constant, otherwise we cannot tell. // Special logic if length is a short constant, otherwise we cannot tell.
u256 const* l = m_expressionClasses.knownConstant(_length); u256 const* l = m_expressionClasses.knownConstant(_length);
// unknown or too large length // unknown or too large length
if (!l || *l > 128) if (!l || *l > 128)
return m_expressionClasses.find(Instruction::SHA3, {_start, _length}, true, m_sequenceNumber); return m_expressionClasses.find(sha3Item, {_start, _length}, true, m_sequenceNumber);
vector<Id> arguments; vector<Id> arguments;
for (u256 i = 0; i < *l; i += 32) for (u256 i = 0; i < *l; i += 32)
{ {
Id slot = m_expressionClasses.find(Instruction::ADD, {_start, m_expressionClasses.find(i)}); Id slot = m_expressionClasses.find(
arguments.push_back(loadFromMemory(slot)); AssemblyItem(Instruction::ADD, _location),
{_start, m_expressionClasses.find(i)}
);
arguments.push_back(loadFromMemory(slot, _location));
} }
if (m_knownSha3Hashes.count(arguments)) if (m_knownSha3Hashes.count(arguments))
return m_knownSha3Hashes.at(arguments); return m_knownSha3Hashes.at(arguments);
@ -276,10 +321,10 @@ CommonSubexpressionEliminator::Id CommonSubexpressionEliminator::applySha3(Id _s
for (Id a: arguments) for (Id a: arguments)
data += toBigEndian(*m_expressionClasses.knownConstant(a)); data += toBigEndian(*m_expressionClasses.knownConstant(a));
data.resize(size_t(*l)); data.resize(size_t(*l));
v = m_expressionClasses.find(u256(sha3(data))); v = m_expressionClasses.find(AssemblyItem(u256(sha3(data)), _location));
} }
else else
v = m_expressionClasses.find(Instruction::SHA3, {_start, _length}, true, m_sequenceNumber); v = m_expressionClasses.find(sha3Item, {_start, _length}, true, m_sequenceNumber);
return m_knownSha3Hashes[arguments] = v; return m_knownSha3Hashes[arguments] = v;
} }
@ -333,12 +378,13 @@ AssemblyItems CSECodeGenerator::generateCode(
assertThrow(position != c_invalidPosition, OptimizerException, ""); assertThrow(position != c_invalidPosition, OptimizerException, "");
if (position == targetItem.first) if (position == targetItem.first)
continue; continue;
SourceLocation const& location = m_expressionClasses.representative(targetItem.second).item->getLocation();
if (position < targetItem.first) if (position < targetItem.first)
// it is already at its target, we need another copy // it is already at its target, we need another copy
appendDup(position); appendDup(position, location);
else else
appendOrRemoveSwap(position); appendOrRemoveSwap(position, location);
appendOrRemoveSwap(targetItem.first); appendOrRemoveSwap(targetItem.first, location);
} }
// remove surplus elements // remove surplus elements
@ -404,7 +450,8 @@ void CSECodeGenerator::addDependencies(Id _c)
case Instruction::SHA3: case Instruction::SHA3:
{ {
Id length = expr.arguments.at(1); Id length = expr.arguments.at(1);
Id offsetToStart = m_expressionClasses.find(Instruction::SUB, {slot, slotToLoadFrom}); AssemblyItem offsetInstr(Instruction::SUB, expr.item->getLocation());
Id offsetToStart = m_expressionClasses.find(offsetInstr, {slot, slotToLoadFrom});
u256 const* o = m_expressionClasses.knownConstant(offsetToStart); u256 const* o = m_expressionClasses.knownConstant(offsetToStart);
u256 const* l = m_expressionClasses.knownConstant(length); u256 const* l = m_expressionClasses.knownConstant(length);
if (l && *l == 0) if (l && *l == 0)
@ -462,6 +509,7 @@ int CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced)
for (Id arg: boost::adaptors::reverse(arguments)) for (Id arg: boost::adaptors::reverse(arguments))
generateClassElement(arg); generateClassElement(arg);
SourceLocation const& location = expr.item->getLocation();
// The arguments are somewhere on the stack now, so it remains to move them at the correct place. // The arguments are somewhere on the stack now, so it remains to move them at the correct place.
// This is quite difficult as sometimes, the values also have to removed in this process // This is quite difficult as sometimes, the values also have to removed in this process
// (if canBeRemoved() returns true) and the two arguments can be equal. For now, this is // (if canBeRemoved() returns true) and the two arguments can be equal. For now, this is
@ -469,42 +517,42 @@ int CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced)
if (arguments.size() == 1) if (arguments.size() == 1)
{ {
if (canBeRemoved(arguments[0], _c)) if (canBeRemoved(arguments[0], _c))
appendOrRemoveSwap(classElementPosition(arguments[0])); appendOrRemoveSwap(classElementPosition(arguments[0]), location);
else else
appendDup(classElementPosition(arguments[0])); appendDup(classElementPosition(arguments[0]), location);
} }
else if (arguments.size() == 2) else if (arguments.size() == 2)
{ {
if (canBeRemoved(arguments[1], _c)) if (canBeRemoved(arguments[1], _c))
{ {
appendOrRemoveSwap(classElementPosition(arguments[1])); appendOrRemoveSwap(classElementPosition(arguments[1]), location);
if (arguments[0] == arguments[1]) if (arguments[0] == arguments[1])
appendDup(m_stackHeight); appendDup(m_stackHeight, location);
else if (canBeRemoved(arguments[0], _c)) else if (canBeRemoved(arguments[0], _c))
{ {
appendOrRemoveSwap(m_stackHeight - 1); appendOrRemoveSwap(m_stackHeight - 1, location);
appendOrRemoveSwap(classElementPosition(arguments[0])); appendOrRemoveSwap(classElementPosition(arguments[0]), location);
} }
else else
appendDup(classElementPosition(arguments[0])); appendDup(classElementPosition(arguments[0]), location);
} }
else else
{ {
if (arguments[0] == arguments[1]) if (arguments[0] == arguments[1])
{ {
appendDup(classElementPosition(arguments[0])); appendDup(classElementPosition(arguments[0]), location);
appendDup(m_stackHeight); appendDup(m_stackHeight, location);
} }
else if (canBeRemoved(arguments[0], _c)) else if (canBeRemoved(arguments[0], _c))
{ {
appendOrRemoveSwap(classElementPosition(arguments[0])); appendOrRemoveSwap(classElementPosition(arguments[0]), location);
appendDup(classElementPosition(arguments[1])); appendDup(classElementPosition(arguments[1]), location);
appendOrRemoveSwap(m_stackHeight - 1); appendOrRemoveSwap(m_stackHeight - 1, location);
} }
else else
{ {
appendDup(classElementPosition(arguments[1])); appendDup(classElementPosition(arguments[1]), location);
appendDup(classElementPosition(arguments[0])); appendDup(classElementPosition(arguments[0]), location);
} }
} }
} }
@ -521,7 +569,7 @@ int CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced)
!m_generatedItems.empty() && !m_generatedItems.empty() &&
m_generatedItems.back() == AssemblyItem(Instruction::SWAP1)) m_generatedItems.back() == AssemblyItem(Instruction::SWAP1))
// this will not append a swap but remove the one that is already there // this will not append a swap but remove the one that is already there
appendOrRemoveSwap(m_stackHeight - 1); appendOrRemoveSwap(m_stackHeight - 1, location);
for (auto arg: arguments) for (auto arg: arguments)
if (canBeRemoved(arg, _c)) if (canBeRemoved(arg, _c))
m_classPositions[arg] = c_invalidPosition; m_classPositions[arg] = c_invalidPosition;
@ -582,17 +630,17 @@ bool CSECodeGenerator::removeStackTopIfPossible()
return true; return true;
} }
void CSECodeGenerator::appendDup(int _fromPosition) void CSECodeGenerator::appendDup(int _fromPosition, SourceLocation const& _location)
{ {
assertThrow(_fromPosition != c_invalidPosition, OptimizerException, ""); assertThrow(_fromPosition != c_invalidPosition, OptimizerException, "");
int instructionNum = 1 + m_stackHeight - _fromPosition; int instructionNum = 1 + m_stackHeight - _fromPosition;
assertThrow(instructionNum <= 16, StackTooDeepException, "Stack too deep."); assertThrow(instructionNum <= 16, StackTooDeepException, "Stack too deep.");
assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access."); assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access.");
appendItem(AssemblyItem(dupInstruction(instructionNum))); appendItem(AssemblyItem(dupInstruction(instructionNum), _location));
m_stack[m_stackHeight] = m_stack[_fromPosition]; m_stack[m_stackHeight] = m_stack[_fromPosition];
} }
void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition) void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition, SourceLocation const& _location)
{ {
assertThrow(_fromPosition != c_invalidPosition, OptimizerException, ""); assertThrow(_fromPosition != c_invalidPosition, OptimizerException, "");
if (_fromPosition == m_stackHeight) if (_fromPosition == m_stackHeight)
@ -600,7 +648,7 @@ void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition)
int instructionNum = m_stackHeight - _fromPosition; int instructionNum = m_stackHeight - _fromPosition;
assertThrow(instructionNum <= 16, StackTooDeepException, "Stack too deep."); assertThrow(instructionNum <= 16, StackTooDeepException, "Stack too deep.");
assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access."); assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access.");
appendItem(AssemblyItem(swapInstruction(instructionNum))); appendItem(AssemblyItem(swapInstruction(instructionNum), _location));
// The value of a class can be present in multiple locations on the stack. We only update the // The value of a class can be present in multiple locations on the stack. We only update the
// "canonical" one that is tracked by m_classPositions // "canonical" one that is tracked by m_classPositions
if (m_classPositions[m_stack[m_stackHeight]] == m_stackHeight) if (m_classPositions[m_stack[m_stackHeight]] == m_stackHeight)

20
libevmcore/CommonSubexpressionEliminator.h

@ -99,26 +99,26 @@ private:
/// Assigns a new equivalence class to the next sequence number of the given stack element. /// Assigns a new equivalence class to the next sequence number of the given stack element.
void setStackElement(int _stackHeight, Id _class); void setStackElement(int _stackHeight, Id _class);
/// Swaps the given stack elements in their next sequence number. /// Swaps the given stack elements in their next sequence number.
void swapStackElements(int _stackHeightA, int _stackHeightB); void swapStackElements(int _stackHeightA, int _stackHeightB, SourceLocation const& _location);
/// Retrieves the current equivalence class fo the given stack element (or generates a new /// Retrieves the current equivalence class fo the given stack element (or generates a new
/// one if it does not exist yet). /// one if it does not exist yet).
Id stackElement(int _stackHeight); Id stackElement(int _stackHeight, SourceLocation const& _location);
/// @returns the equivalence class id of the special initial stack element at the given height /// @returns the equivalence class id of the special initial stack element at the given height
/// (must not be positive). /// (must not be positive).
Id initialStackElement(int _stackHeight); Id initialStackElement(int _stackHeight, SourceLocation const& _location);
/// Increments the sequence number, deletes all storage information that might be overwritten /// Increments the sequence number, deletes all storage information that might be overwritten
/// and stores the new value at the given slot. /// and stores the new value at the given slot.
void storeInStorage(Id _slot, Id _value); void storeInStorage(Id _slot, Id _value, SourceLocation const& _location);
/// Retrieves the current value at the given slot in storage or creates a new special sload class. /// Retrieves the current value at the given slot in storage or creates a new special sload class.
Id loadFromStorage(Id _slot); Id loadFromStorage(Id _slot, SourceLocation const& _location);
/// Increments the sequence number, deletes all memory information that might be overwritten /// Increments the sequence number, deletes all memory information that might be overwritten
/// and stores the new value at the given slot. /// and stores the new value at the given slot.
void storeInMemory(Id _slot, Id _value); void storeInMemory(Id _slot, Id _value, SourceLocation const& _location);
/// Retrieves the current value at the given slot in memory or creates a new special mload class. /// Retrieves the current value at the given slot in memory or creates a new special mload class.
Id loadFromMemory(Id _slot); Id loadFromMemory(Id _slot, SourceLocation const& _location);
/// Finds or creates a new expression that applies the sha3 hash function to the contents in memory. /// Finds or creates a new expression that applies the sha3 hash function to the contents in memory.
Id applySha3(Id _start, Id _length); Id applySha3(Id _start, Id _length, SourceLocation const& _location);
/// Current stack height, can be negative. /// Current stack height, can be negative.
int m_stackHeight = 0; int m_stackHeight = 0;
@ -188,10 +188,10 @@ private:
bool removeStackTopIfPossible(); bool removeStackTopIfPossible();
/// Appends a dup instruction to m_generatedItems to retrieve the element at the given stack position. /// Appends a dup instruction to m_generatedItems to retrieve the element at the given stack position.
void appendDup(int _fromPosition); void appendDup(int _fromPosition, SourceLocation const& _location);
/// Appends a swap instruction to m_generatedItems to retrieve the element at the given stack position. /// Appends a swap instruction to m_generatedItems to retrieve the element at the given stack position.
/// @note this might also remove the last item if it exactly the same swap instruction. /// @note this might also remove the last item if it exactly the same swap instruction.
void appendOrRemoveSwap(int _fromPosition); void appendOrRemoveSwap(int _fromPosition, SourceLocation const& _location);
/// Appends the given assembly item. /// Appends the given assembly item.
void appendItem(AssemblyItem const& _item); void appendItem(AssemblyItem const& _item);

24
libevmcore/ExpressionClasses.cpp

@ -64,10 +64,7 @@ ExpressionClasses::Id ExpressionClasses::find(
return it->id; return it->id;
if (_copyItem) if (_copyItem)
{ exp.item = storeItem(_item);
m_spareAssemblyItem.push_back(make_shared<AssemblyItem>(_item));
exp.item = m_spareAssemblyItem.back().get();
}
ExpressionClasses::Id id = tryToSimplify(exp); ExpressionClasses::Id id = tryToSimplify(exp);
if (id < m_representatives.size()) if (id < m_representatives.size())
@ -115,6 +112,12 @@ u256 const* ExpressionClasses::knownConstant(Id _c)
return &constant.d(); return &constant.d();
} }
AssemblyItem const* ExpressionClasses::storeItem(AssemblyItem const& _item)
{
m_spareAssemblyItems.push_back(make_shared<AssemblyItem>(_item));
return m_spareAssemblyItems.back().get();
}
string ExpressionClasses::fullDAGToString(ExpressionClasses::Id _id) const string ExpressionClasses::fullDAGToString(ExpressionClasses::Id _id) const
{ {
Expression const& expr = representative(_id); Expression const& expr = representative(_id);
@ -292,7 +295,7 @@ ExpressionClasses::Id ExpressionClasses::tryToSimplify(Expression const& _expr,
//cout << "with rule " << rule.first.toString() << endl; //cout << "with rule " << rule.first.toString() << endl;
//ExpressionTemplate t(rule.second()); //ExpressionTemplate t(rule.second());
//cout << "to " << rule.second().toString() << endl; //cout << "to " << rule.second().toString() << endl;
return rebuildExpression(ExpressionTemplate(rule.second())); return rebuildExpression(ExpressionTemplate(rule.second(), _expr.item->getLocation()));
} }
} }
@ -350,6 +353,11 @@ bool Pattern::matches(Expression const& _expr, ExpressionClasses const& _classes
return true; return true;
} }
AssemblyItem Pattern::toAssemblyItem(SourceLocation const& _location) const
{
return AssemblyItem(m_type, m_data, _location);
}
string Pattern::toString() const string Pattern::toString() const
{ {
stringstream s; stringstream s;
@ -399,7 +407,7 @@ Pattern::Expression const& Pattern::matchGroupValue() const
} }
ExpressionTemplate::ExpressionTemplate(Pattern const& _pattern) ExpressionTemplate::ExpressionTemplate(Pattern const& _pattern, SourceLocation const& _location)
{ {
if (_pattern.matchGroup()) if (_pattern.matchGroup())
{ {
@ -409,10 +417,10 @@ ExpressionTemplate::ExpressionTemplate(Pattern const& _pattern)
else else
{ {
hasId = false; hasId = false;
item = _pattern.toAssemblyItem(); item = _pattern.toAssemblyItem(_location);
} }
for (auto const& arg: _pattern.arguments()) for (auto const& arg: _pattern.arguments())
arguments.push_back(ExpressionTemplate(arg)); arguments.push_back(ExpressionTemplate(arg, _location));
} }
string ExpressionTemplate::toString() const string ExpressionTemplate::toString() const

10
libevmcore/ExpressionClasses.h

@ -88,6 +88,10 @@ public:
/// and a nullptr otherwise. /// and a nullptr otherwise.
u256 const* knownConstant(Id _c); u256 const* knownConstant(Id _c);
/// Stores a copy of the given AssemblyItem and returns a pointer to the copy that is valid for
/// the lifetime of the ExpressionClasses object.
AssemblyItem const* storeItem(AssemblyItem const& _item);
std::string fullDAGToString(Id _id) const; std::string fullDAGToString(Id _id) const;
private: private:
@ -105,7 +109,7 @@ private:
std::vector<Expression> m_representatives; std::vector<Expression> m_representatives;
/// All expression ever encountered. /// All expression ever encountered.
std::set<Expression> m_expressions; std::set<Expression> m_expressions;
std::vector<std::shared_ptr<AssemblyItem>> m_spareAssemblyItem; std::vector<std::shared_ptr<AssemblyItem>> m_spareAssemblyItems;
}; };
/** /**
@ -134,7 +138,7 @@ public:
unsigned matchGroup() const { return m_matchGroup; } unsigned matchGroup() const { return m_matchGroup; }
bool matches(Expression const& _expr, ExpressionClasses const& _classes) const; bool matches(Expression const& _expr, ExpressionClasses const& _classes) const;
AssemblyItem toAssemblyItem() const { return AssemblyItem(m_type, m_data); } AssemblyItem toAssemblyItem(SourceLocation const& _location) const;
std::vector<Pattern> arguments() const { return m_arguments; } std::vector<Pattern> arguments() const { return m_arguments; }
/// @returns the id of the matched expression if this pattern is part of a match group. /// @returns the id of the matched expression if this pattern is part of a match group.
@ -163,7 +167,7 @@ struct ExpressionTemplate
{ {
using Expression = ExpressionClasses::Expression; using Expression = ExpressionClasses::Expression;
using Id = ExpressionClasses::Id; using Id = ExpressionClasses::Id;
explicit ExpressionTemplate(Pattern const& _pattern); explicit ExpressionTemplate(Pattern const& _pattern, SourceLocation const& _location);
std::string toString() const; std::string toString() const;
bool hasId = false; bool hasId = false;
/// Id of the matched expression, if available. /// Id of the matched expression, if available.

15
libp2p/Host.cpp

@ -226,6 +226,12 @@ void Host::startPeerSession(Public const& _id, RLP const& _rlp, RLPXFrameIO* _io
return; return;
} }
if (peerCount() > 2 * m_idealPeerCount)
{
ps->disconnect(TooManyPeers);
return;
}
// todo: mutex Session::m_capabilities and move for(:caps) out of mutex. // todo: mutex Session::m_capabilities and move for(:caps) out of mutex.
unsigned o = (unsigned)UserPacket; unsigned o = (unsigned)UserPacket;
for (auto const& i: caps) for (auto const& i: caps)
@ -335,6 +341,15 @@ void Host::runAcceptor()
auto socket = make_shared<RLPXSocket>(new bi::tcp::socket(m_ioService)); auto socket = make_shared<RLPXSocket>(new bi::tcp::socket(m_ioService));
m_tcp4Acceptor.async_accept(socket->ref(), [=](boost::system::error_code ec) m_tcp4Acceptor.async_accept(socket->ref(), [=](boost::system::error_code ec)
{ {
if (peerCount() > 2 * m_idealPeerCount)
{
clog(NetConnect) << "Dropping incoming connect due to maximum peer count (2 * ideal peer count): " << socket->remoteEndpoint();
socket->close();
if (ec.value() < 1)
runAcceptor();
return;
}
// if no error code // if no error code
bool success = false; bool success = false;
if (!ec) if (!ec)

8
libsolidity/AST.cpp

@ -817,8 +817,12 @@ void NewExpression::checkTypeRequirements(TypePointers const*)
BOOST_THROW_EXCEPTION(createTypeError("Trying to create an instance of an abstract contract.")); BOOST_THROW_EXCEPTION(createTypeError("Trying to create an instance of an abstract contract."));
shared_ptr<ContractType const> contractType = make_shared<ContractType>(*m_contract); shared_ptr<ContractType const> contractType = make_shared<ContractType>(*m_contract);
TypePointers const& parameterTypes = contractType->getConstructorType()->getParameterTypes(); TypePointers const& parameterTypes = contractType->getConstructorType()->getParameterTypes();
m_type = make_shared<FunctionType>(parameterTypes, TypePointers{contractType}, m_type = make_shared<FunctionType>(
FunctionType::Location::Creation); parameterTypes,
TypePointers{contractType},
strings(),
strings(),
FunctionType::Location::Creation);
} }
void MemberAccess::checkTypeRequirements(TypePointers const* _argumentTypes) void MemberAccess::checkTypeRequirements(TypePointers const* _argumentTypes)

16
libsolidity/ExpressionCompiler.cpp

@ -521,8 +521,20 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
arguments.front()->accept(*this); arguments.front()->accept(*this);
appendTypeConversion(*arguments.front()->getType(), appendTypeConversion(*arguments.front()->getType(),
*function.getParameterTypes().front(), true); *function.getParameterTypes().front(), true);
appendExternalFunctionCall(FunctionType(TypePointers{}, TypePointers{}, appendExternalFunctionCall(
Location::External, false, true, true), {}, true); FunctionType(
TypePointers{},
TypePointers{},
strings(),
strings(),
Location::External,
false,
true,
true
),
{},
true
);
break; break;
case Location::Suicide: case Location::Suicide:
arguments.front()->accept(*this); arguments.front()->accept(*this);

40
libsolidity/InterfaceHandler.cpp

@ -38,21 +38,23 @@ std::unique_ptr<std::string> InterfaceHandler::getDocumentation(ContractDefiniti
std::unique_ptr<std::string> InterfaceHandler::getABIInterface(ContractDefinition const& _contractDef) std::unique_ptr<std::string> InterfaceHandler::getABIInterface(ContractDefinition const& _contractDef)
{ {
Json::Value abi(Json::arrayValue); Json::Value abi(Json::arrayValue);
for (auto const& it: _contractDef.getInterfaceFunctions())
auto populateParameters = [](vector<string> const& _paramNames, vector<string> const& _paramTypes)
{ {
auto populateParameters = [](vector<string> const& _paramNames, vector<string> const& _paramTypes) Json::Value params(Json::arrayValue);
solAssert(_paramNames.size() == _paramTypes.size(), "Names and types vector size does not match");
for (unsigned i = 0; i < _paramNames.size(); ++i)
{ {
Json::Value params(Json::arrayValue); Json::Value param;
solAssert(_paramNames.size() == _paramTypes.size(), "Names and types vector size does not match"); param["name"] = _paramNames[i];
for (unsigned i = 0; i < _paramNames.size(); ++i) param["type"] = _paramTypes[i];
{ params.append(param);
Json::Value param; }
param["name"] = _paramNames[i]; return params;
param["type"] = _paramTypes[i]; };
params.append(param);
} for (auto it: _contractDef.getInterfaceFunctions())
return params; {
};
Json::Value method; Json::Value method;
method["type"] = "function"; method["type"] = "function";
@ -64,6 +66,18 @@ std::unique_ptr<std::string> InterfaceHandler::getABIInterface(ContractDefinitio
it.second->getReturnParameterTypeNames()); it.second->getReturnParameterTypeNames());
abi.append(method); abi.append(method);
} }
if (_contractDef.getConstructor())
{
Json::Value method;
method["type"] = "constructor";
auto externalFunction = FunctionType(*_contractDef.getConstructor()).externalFunctionType();
solAssert(!!externalFunction, "");
method["inputs"] = populateParameters(
externalFunction->getParameterNames(),
externalFunction->getParameterTypeNames()
);
abi.append(method);
}
for (auto const& it: _contractDef.getInterfaceEvents()) for (auto const& it: _contractDef.getInterfaceEvents())
{ {

51
libsolidity/Types.cpp

@ -1143,7 +1143,7 @@ FunctionTypePointer FunctionType::externalFunctionType() const
return FunctionTypePointer(); return FunctionTypePointer();
retParamTypes.push_back(type->externalType()); retParamTypes.push_back(type->externalType());
} }
return make_shared<FunctionType>(paramTypes, retParamTypes, m_location, m_arbitraryParameters); return make_shared<FunctionType>(paramTypes, retParamTypes, m_parameterNames, m_returnParameterNames, m_location, m_arbitraryParameters);
} }
MemberList const& FunctionType::getMembers() const MemberList const& FunctionType::getMembers() const
@ -1159,14 +1159,36 @@ MemberList const& FunctionType::getMembers() const
if (!m_members) if (!m_members)
{ {
MemberList::MemberMap members{ MemberList::MemberMap members{
{"value", make_shared<FunctionType>(parseElementaryTypeVector({"uint"}), {
TypePointers{copyAndSetGasOrValue(false, true)}, "value",
Location::SetValue, false, m_gasSet, m_valueSet)}}; make_shared<FunctionType>(
parseElementaryTypeVector({"uint"}),
TypePointers{copyAndSetGasOrValue(false, true)},
strings(),
strings(),
Location::SetValue,
false,
m_gasSet,
m_valueSet
)
}
};
if (m_location != Location::Creation) if (m_location != Location::Creation)
members.push_back(MemberList::Member("gas", make_shared<FunctionType>( members.push_back(
parseElementaryTypeVector({"uint"}), MemberList::Member(
TypePointers{copyAndSetGasOrValue(true, false)}, "gas",
Location::SetGas, false, m_gasSet, m_valueSet))); make_shared<FunctionType>(
parseElementaryTypeVector({"uint"}),
TypePointers{copyAndSetGasOrValue(true, false)},
strings(),
strings(),
Location::SetGas,
false,
m_gasSet,
m_valueSet
)
)
);
m_members.reset(new MemberList(members)); m_members.reset(new MemberList(members));
} }
return *m_members; return *m_members;
@ -1244,9 +1266,16 @@ TypePointers FunctionType::parseElementaryTypeVector(strings const& _types)
TypePointer FunctionType::copyAndSetGasOrValue(bool _setGas, bool _setValue) const TypePointer FunctionType::copyAndSetGasOrValue(bool _setGas, bool _setValue) const
{ {
return make_shared<FunctionType>(m_parameterTypes, m_returnParameterTypes, m_location, return make_shared<FunctionType>(
m_arbitraryParameters, m_parameterTypes,
m_gasSet || _setGas, m_valueSet || _setValue); m_returnParameterTypes,
m_parameterNames,
m_returnParameterNames,
m_location,
m_arbitraryParameters,
m_gasSet || _setGas,
m_valueSet || _setValue
);
} }
vector<string> const FunctionType::getParameterTypeNames() const vector<string> const FunctionType::getParameterTypeNames() const

47
libsolidity/Types.h

@ -564,24 +564,39 @@ public:
explicit FunctionType(FunctionDefinition const& _function, bool _isInternal = true); explicit FunctionType(FunctionDefinition const& _function, bool _isInternal = true);
explicit FunctionType(VariableDeclaration const& _varDecl); explicit FunctionType(VariableDeclaration const& _varDecl);
explicit FunctionType(EventDefinition const& _event); explicit FunctionType(EventDefinition const& _event);
FunctionType(strings const& _parameterTypes, strings const& _returnParameterTypes,
Location _location = Location::Internal, bool _arbitraryParameters = false):
FunctionType(parseElementaryTypeVector(_parameterTypes), parseElementaryTypeVector(_returnParameterTypes),
_location, _arbitraryParameters) {}
FunctionType( FunctionType(
TypePointers const& _parameterTypes, strings const& _parameterTypes,
TypePointers const& _returnParameterTypes, strings const& _returnParameterTypes,
Location _location = Location::Internal, Location _location = Location::Internal,
bool _arbitraryParameters = false, bool _arbitraryParameters = false
bool _gasSet = false, ): FunctionType(
bool _valueSet = false parseElementaryTypeVector(_parameterTypes),
parseElementaryTypeVector(_returnParameterTypes),
strings(),
strings(),
_location,
_arbitraryParameters
)
{
}
FunctionType(
TypePointers const& _parameterTypes,
TypePointers const& _returnParameterTypes,
strings _parameterNames = strings(),
strings _returnParameterNames = strings(),
Location _location = Location::Internal,
bool _arbitraryParameters = false,
bool _gasSet = false,
bool _valueSet = false
): ):
m_parameterTypes (_parameterTypes), m_parameterTypes (_parameterTypes),
m_returnParameterTypes (_returnParameterTypes), m_returnParameterTypes (_returnParameterTypes),
m_location (_location), m_parameterNames (_parameterNames),
m_arbitraryParameters (_arbitraryParameters), m_returnParameterNames (_returnParameterNames),
m_gasSet (_gasSet), m_location (_location),
m_valueSet (_valueSet) m_arbitraryParameters (_arbitraryParameters),
m_gasSet (_gasSet),
m_valueSet (_valueSet)
{} {}
TypePointers const& getParameterTypes() const { return m_parameterTypes; } TypePointers const& getParameterTypes() const { return m_parameterTypes; }

1
libtestutils/StateLoader.cpp

@ -54,5 +54,4 @@ StateLoader::StateLoader(Json::Value const& _json, std::string const& _dbPath):
} }
m_state.commit(); m_state.commit();
m_state.db().commit();
} }

70
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -141,6 +141,24 @@ static Json::Value toJson(dev::eth::TransactionSkeleton const& _t)
return res; return res;
} }
static Json::Value toJson(dev::eth::Transaction const& _t)
{
Json::Value res;
res["to"] = _t.isCreation() ? Json::Value() : toJS(_t.to());
res["from"] = toJS(_t.from());
res["gas"] = toJS(_t.gas());
res["gasPrice"] = toJS(_t.gasPrice());
res["value"] = toJS(_t.value());
res["data"] = toJS(_t.data(), 32);
res["nonce"] = toJS(_t.nonce());
res["hash"] = toJS(_t.sha3(WithSignature));
res["sighash"] = toJS(_t.sha3(WithoutSignature));
res["r"] = toJS(_t.signature().r);
res["s"] = toJS(_t.signature().s);
res["v"] = toJS(_t.signature().v);
return res;
}
static Json::Value toJson(dev::eth::LocalisedLogEntry const& _e) static Json::Value toJson(dev::eth::LocalisedLogEntry const& _e)
{ {
Json::Value res; Json::Value res;
@ -502,6 +520,58 @@ string WebThreeStubServerBase::eth_sendTransaction(Json::Value const& _json)
} }
} }
string WebThreeStubServerBase::eth_signTransaction(Json::Value const& _json)
{
try
{
string ret;
TransactionSkeleton t = toTransaction(_json);
if (!t.from)
t.from = m_accounts->getDefaultTransactAccount();
if (t.creation)
ret = toJS(right160(sha3(rlpList(t.from, client()->countAt(t.from)))));;
if (!t.gasPrice)
t.gasPrice = 10 * dev::eth::szabo; // TODO: should be determined by user somehow.
if (!t.gas)
t.gas = min<u256>(client()->gasLimitRemaining(), client()->balanceAt(t.from) / t.gasPrice);
if (m_accounts->isRealAccount(t.from))
authenticate(t, false);
else if (m_accounts->isProxyAccount(t.from))
authenticate(t, true);
return toJS((t.creation ? Transaction(t.value, t.gasPrice, t.gas, t.data) : Transaction(t.value, t.gasPrice, t.gas, t.to, t.data)).sha3(WithoutSignature));
}
catch (...)
{
BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
}
}
Json::Value WebThreeStubServerBase::eth_inspectTransaction(std::string const& _rlp)
{
try
{
return toJson(Transaction(jsToBytes(_rlp), CheckTransaction::Everything));
}
catch (...)
{
BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
}
}
bool WebThreeStubServerBase::eth_injectTransaction(std::string const& _rlp)
{
try
{
return client()->injectTransaction(jsToBytes(_rlp)) == ImportResult::Success;
}
catch (...)
{
BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
}
}
string WebThreeStubServerBase::eth_call(Json::Value const& _json, string const& _blockNumber) string WebThreeStubServerBase::eth_call(Json::Value const& _json, string const& _blockNumber)
{ {

3
libweb3jsonrpc/WebThreeStubServerBase.h

@ -117,6 +117,9 @@ public:
virtual std::string eth_register(std::string const& _address); virtual std::string eth_register(std::string const& _address);
virtual bool eth_unregister(std::string const& _accountId); virtual bool eth_unregister(std::string const& _accountId);
virtual Json::Value eth_fetchQueuedTransactions(std::string const& _accountId); virtual Json::Value eth_fetchQueuedTransactions(std::string const& _accountId);
virtual std::string eth_signTransaction(Json::Value const& _transaction);
virtual Json::Value eth_inspectTransaction(std::string const& _rlp);
virtual bool eth_injectTransaction(std::string const& _rlp);
virtual bool db_put(std::string const& _name, std::string const& _key, std::string const& _value); virtual bool db_put(std::string const& _name, std::string const& _key, std::string const& _value);
virtual std::string db_get(std::string const& _name, std::string const& _key); virtual std::string db_get(std::string const& _name, std::string const& _key);

18
libweb3jsonrpc/abstractwebthreestubserver.h

@ -57,6 +57,9 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
this->bindAndAddMethod(jsonrpc::Procedure("eth_register", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_registerI); this->bindAndAddMethod(jsonrpc::Procedure("eth_register", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_registerI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_unregister", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_unregisterI); this->bindAndAddMethod(jsonrpc::Procedure("eth_unregister", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_unregisterI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_fetchQueuedTransactions", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_fetchQueuedTransactionsI); this->bindAndAddMethod(jsonrpc::Procedure("eth_fetchQueuedTransactions", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_fetchQueuedTransactionsI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_signTransaction", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_signTransactionI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_inspectTransaction", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_inspectTransactionI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_injectTransaction", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_injectTransactionI);
this->bindAndAddMethod(jsonrpc::Procedure("db_put", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::db_putI); this->bindAndAddMethod(jsonrpc::Procedure("db_put", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::db_putI);
this->bindAndAddMethod(jsonrpc::Procedure("db_get", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::db_getI); this->bindAndAddMethod(jsonrpc::Procedure("db_get", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::db_getI);
this->bindAndAddMethod(jsonrpc::Procedure("shh_post", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::shh_postI); this->bindAndAddMethod(jsonrpc::Procedure("shh_post", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::shh_postI);
@ -264,6 +267,18 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
{ {
response = this->eth_fetchQueuedTransactions(request[0u].asString()); response = this->eth_fetchQueuedTransactions(request[0u].asString());
} }
inline virtual void eth_signTransactionI(const Json::Value &request, Json::Value &response)
{
response = this->eth_signTransaction(request[0u]);
}
inline virtual void eth_inspectTransactionI(const Json::Value &request, Json::Value &response)
{
response = this->eth_inspectTransaction(request[0u].asString());
}
inline virtual void eth_injectTransactionI(const Json::Value &request, Json::Value &response)
{
response = this->eth_injectTransaction(request[0u].asString());
}
inline virtual void db_putI(const Json::Value &request, Json::Value &response) inline virtual void db_putI(const Json::Value &request, Json::Value &response)
{ {
response = this->db_put(request[0u].asString(), request[1u].asString(), request[2u].asString()); response = this->db_put(request[0u].asString(), request[1u].asString(), request[2u].asString());
@ -354,6 +369,9 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
virtual std::string eth_register(const std::string& param1) = 0; virtual std::string eth_register(const std::string& param1) = 0;
virtual bool eth_unregister(const std::string& param1) = 0; virtual bool eth_unregister(const std::string& param1) = 0;
virtual Json::Value eth_fetchQueuedTransactions(const std::string& param1) = 0; virtual Json::Value eth_fetchQueuedTransactions(const std::string& param1) = 0;
virtual std::string eth_signTransaction(const Json::Value& param1) = 0;
virtual Json::Value eth_inspectTransaction(const std::string& param1) = 0;
virtual bool eth_injectTransaction(const std::string& param1) = 0;
virtual bool db_put(const std::string& param1, const std::string& param2, const std::string& param3) = 0; virtual bool db_put(const std::string& param1, const std::string& param2, const std::string& param3) = 0;
virtual std::string db_get(const std::string& param1, const std::string& param2) = 0; virtual std::string db_get(const std::string& param1, const std::string& param2) = 0;
virtual bool shh_post(const Json::Value& param1) = 0; virtual bool shh_post(const Json::Value& param1) = 0;

115
libweb3jsonrpc/spec.json

@ -1,63 +1,66 @@
[ [
{ "name": "web3_sha3", "params": [""], "order": [], "returns" : "" }, { "name": "web3_sha3", "params": [""], "order": [], "returns" : "" },
{ "name": "web3_clientVersion", "params": [], "order": [], "returns" : "" }, { "name": "web3_clientVersion", "params": [], "order": [], "returns" : "" },
{ "name": "net_version", "params": [], "order": [], "returns" : "" }, { "name": "net_version", "params": [], "order": [], "returns" : "" },
{ "name": "net_peerCount", "params": [], "order": [], "returns" : "" }, { "name": "net_peerCount", "params": [], "order": [], "returns" : "" },
{ "name": "net_listening", "params": [], "order": [], "returns" : false }, { "name": "net_listening", "params": [], "order": [], "returns" : false },
{ "name": "eth_protocolVersion", "params": [], "order": [], "returns" : "" }, { "name": "eth_protocolVersion", "params": [], "order": [], "returns" : "" },
{ "name": "eth_hashrate", "params": [], "order": [], "returns" : "" }, { "name": "eth_hashrate", "params": [], "order": [], "returns" : "" },
{ "name": "eth_coinbase", "params": [], "order": [], "returns" : "" }, { "name": "eth_coinbase", "params": [], "order": [], "returns" : "" },
{ "name": "eth_mining", "params": [], "order": [], "returns" : false }, { "name": "eth_mining", "params": [], "order": [], "returns" : false },
{ "name": "eth_gasPrice", "params": [], "order": [], "returns" : "" }, { "name": "eth_gasPrice", "params": [], "order": [], "returns" : "" },
{ "name": "eth_accounts", "params": [], "order": [], "returns" : [] }, { "name": "eth_accounts", "params": [], "order": [], "returns" : [] },
{ "name": "eth_blockNumber", "params": [], "order": [], "returns" : ""}, { "name": "eth_blockNumber", "params": [], "order": [], "returns" : ""},
{ "name": "eth_getBalance", "params": ["", ""], "order": [], "returns" : ""}, { "name": "eth_getBalance", "params": ["", ""], "order": [], "returns" : ""},
{ "name": "eth_getStorageAt", "params": ["", "", ""], "order": [], "returns": ""}, { "name": "eth_getStorageAt", "params": ["", "", ""], "order": [], "returns": ""},
{ "name": "eth_getTransactionCount", "params": ["", ""], "order": [], "returns" : ""}, { "name": "eth_getTransactionCount", "params": ["", ""], "order": [], "returns" : ""},
{ "name": "eth_getBlockTransactionCountByHash", "params": [""], "order": [], "returns" : ""}, { "name": "eth_getBlockTransactionCountByHash", "params": [""], "order": [], "returns" : ""},
{ "name": "eth_getBlockTransactionCountByNumber", "params": [""], "order": [], "returns" : ""}, { "name": "eth_getBlockTransactionCountByNumber", "params": [""], "order": [], "returns" : ""},
{ "name": "eth_getUncleCountByBlockHash", "params": [""], "order": [], "returns" : ""}, { "name": "eth_getUncleCountByBlockHash", "params": [""], "order": [], "returns" : ""},
{ "name": "eth_getUncleCountByBlockNumber", "params": [""], "order": [], "returns" : ""}, { "name": "eth_getUncleCountByBlockNumber", "params": [""], "order": [], "returns" : ""},
{ "name": "eth_getCode", "params": ["", ""], "order": [], "returns": ""}, { "name": "eth_getCode", "params": ["", ""], "order": [], "returns": ""},
{ "name": "eth_sendTransaction", "params": [{}], "order": [], "returns": ""}, { "name": "eth_sendTransaction", "params": [{}], "order": [], "returns": ""},
{ "name": "eth_call", "params": [{}, ""], "order": [], "returns": ""}, { "name": "eth_call", "params": [{}, ""], "order": [], "returns": ""},
{ "name": "eth_flush", "params": [], "order": [], "returns" : true}, { "name": "eth_flush", "params": [], "order": [], "returns" : true},
{ "name": "eth_getBlockByHash", "params": ["", false],"order": [], "returns": {}}, { "name": "eth_getBlockByHash", "params": ["", false],"order": [], "returns": {}},
{ "name": "eth_getBlockByNumber", "params": ["", false],"order": [], "returns": {}}, { "name": "eth_getBlockByNumber", "params": ["", false],"order": [], "returns": {}},
{ "name": "eth_getTransactionByHash", "params": [""], "order": [], "returns": {}}, { "name": "eth_getTransactionByHash", "params": [""], "order": [], "returns": {}},
{ "name": "eth_getTransactionByBlockHashAndIndex", "params": ["", ""], "order": [], "returns": {}}, { "name": "eth_getTransactionByBlockHashAndIndex", "params": ["", ""], "order": [], "returns": {}},
{ "name": "eth_getTransactionByBlockNumberAndIndex", "params": ["", ""], "order": [], "returns": {}}, { "name": "eth_getTransactionByBlockNumberAndIndex", "params": ["", ""], "order": [], "returns": {}},
{ "name": "eth_getUncleByBlockHashAndIndex", "params": ["", ""], "order": [], "returns": {}}, { "name": "eth_getUncleByBlockHashAndIndex", "params": ["", ""], "order": [], "returns": {}},
{ "name": "eth_getUncleByBlockNumberAndIndex", "params": ["", ""], "order": [], "returns": {}}, { "name": "eth_getUncleByBlockNumberAndIndex", "params": ["", ""], "order": [], "returns": {}},
{ "name": "eth_getCompilers", "params": [], "order": [], "returns": []}, { "name": "eth_getCompilers", "params": [], "order": [], "returns": []},
{ "name": "eth_compileLLL", "params": [""], "order": [], "returns": ""}, { "name": "eth_compileLLL", "params": [""], "order": [], "returns": ""},
{ "name": "eth_compileSerpent", "params": [""], "order": [], "returns": ""}, { "name": "eth_compileSerpent", "params": [""], "order": [], "returns": ""},
{ "name": "eth_compileSolidity", "params": [""], "order": [], "returns": ""}, { "name": "eth_compileSolidity", "params": [""], "order": [], "returns": ""},
{ "name": "eth_newFilter", "params": [{}], "order": [], "returns": ""}, { "name": "eth_newFilter", "params": [{}], "order": [], "returns": ""},
{ "name": "eth_newBlockFilter", "params": [""], "order": [], "returns": ""}, { "name": "eth_newBlockFilter", "params": [""], "order": [], "returns": ""},
{ "name": "eth_uninstallFilter", "params": [""], "order": [], "returns": true}, { "name": "eth_uninstallFilter", "params": [""], "order": [], "returns": true},
{ "name": "eth_getFilterChanges", "params": [""], "order": [], "returns": []}, { "name": "eth_getFilterChanges", "params": [""], "order": [], "returns": []},
{ "name": "eth_getFilterLogs", "params": [""], "order": [], "returns": []}, { "name": "eth_getFilterLogs", "params": [""], "order": [], "returns": []},
{ "name": "eth_getLogs", "params": [{}], "order": [], "returns": []}, { "name": "eth_getLogs", "params": [{}], "order": [], "returns": []},
{ "name": "eth_getWork", "params": [], "order": [], "returns": []}, { "name": "eth_getWork", "params": [], "order": [], "returns": []},
{ "name": "eth_submitWork", "params": ["", "", ""], "order": [], "returns": true}, { "name": "eth_submitWork", "params": ["", "", ""], "order": [], "returns": true},
{ "name": "eth_register", "params": [""], "order": [], "returns": ""}, { "name": "eth_register", "params": [""], "order": [], "returns": ""},
{ "name": "eth_unregister", "params": [""], "order": [], "returns": true}, { "name": "eth_unregister", "params": [""], "order": [], "returns": true},
{ "name": "eth_fetchQueuedTransactions", "params": [""], "order": [], "returns": []}, { "name": "eth_fetchQueuedTransactions", "params": [""], "order": [], "returns": []},
{ "name": "eth_signTransaction", "params": [{}], "order": [], "returns": ""},
{ "name": "eth_inspectTransaction", "params": [""], "order": [], "returns": {}},
{ "name": "eth_injectTransaction", "params": [""], "order": [], "returns": true},
{ "name": "db_put", "params": ["", "", ""], "order": [], "returns": true}, { "name": "db_put", "params": ["", "", ""], "order": [], "returns": true},
{ "name": "db_get", "params": ["", ""], "order": [], "returns": ""}, { "name": "db_get", "params": ["", ""], "order": [], "returns": ""},
{ "name": "shh_post", "params": [{}], "order": [], "returns": true}, { "name": "shh_post", "params": [{}], "order": [], "returns": true},
{ "name": "shh_newIdentity", "params": [], "order": [], "returns": ""}, { "name": "shh_newIdentity", "params": [], "order": [], "returns": ""},
{ "name": "shh_hasIdentity", "params": [""], "order": [], "returns": false}, { "name": "shh_hasIdentity", "params": [""], "order": [], "returns": false},
{ "name": "shh_newGroup", "params": ["", ""], "order": [], "returns": ""}, { "name": "shh_newGroup", "params": ["", ""], "order": [], "returns": ""},
{ "name": "shh_addToGroup", "params": ["", ""], "order": [], "returns": ""}, { "name": "shh_addToGroup", "params": ["", ""], "order": [], "returns": ""},
{ "name": "shh_newFilter", "params": [{}], "order": [], "returns": ""}, { "name": "shh_newFilter", "params": [{}], "order": [], "returns": ""},
{ "name": "shh_uninstallFilter", "params": [""], "order": [], "returns": true}, { "name": "shh_uninstallFilter", "params": [""], "order": [], "returns": true},
{ "name": "shh_getFilterChanges", "params": [""], "order": [], "returns": []}, { "name": "shh_getFilterChanges", "params": [""], "order": [], "returns": []},
{ "name": "shh_getMessages", "params": [""], "order": [], "returns": []} { "name": "shh_getMessages", "params": [""], "order": [], "returns": []}
] ]

24
neth/main.cpp

@ -718,13 +718,33 @@ int main(int argc, char** argv)
else if (c && cmd == "setblockfees") else if (c && cmd == "setblockfees")
{ {
iss >> blockFees; iss >> blockFees;
gasPricer->setRefBlockFees(u256(blockFees * 1000)); try
{
gasPricer->setRefBlockFees(u256(blockFees * 1000));
}
catch (Overflow const& _e)
{
cout << boost::diagnostic_information(_e);
}
cout << "Block fees: " << blockFees << endl; cout << "Block fees: " << blockFees << endl;
} }
else if (c && cmd == "setetherprice") else if (c && cmd == "setetherprice")
{ {
iss >> etherPrice; iss >> etherPrice;
gasPricer->setRefPrice(u256(double(ether / 1000) / etherPrice)); if (etherPrice == 0)
cout << "ether price cannot be set to zero" << endl;
else
{
try
{
gasPricer->setRefPrice(u256(double(ether / 1000) / etherPrice));
}
catch (Overflow const& _e)
{
cout << boost::diagnostic_information(_e);
}
}
cout << "ether Price: " << etherPrice << endl; cout << "ether Price: " << etherPrice << endl;
} }
else if (c && cmd == "setpriority") else if (c && cmd == "setpriority")

68
test/TestHelper.cpp

@ -137,7 +137,7 @@ json_spirit::mObject& ImportTest::makeAllFieldsHex(json_spirit::mObject& _o)
str = value.get_str(); str = value.get_str();
else continue; else continue;
_o[key] = (str.substr(0, 2) == "0x") ? str : "0x" + toHex(toCompactBigEndian(toInt(str), 1)); _o[key] = (str.substr(0, 2) == "0x") ? str : toCompactHex(toInt(str), HexPrefix::Add, 1);
} }
return _o; return _o;
} }
@ -327,7 +327,7 @@ void ImportTest::checkExpectedState(State const& _stateExpect, State const& _sta
void ImportTest::exportTest(bytes const& _output, State const& _statePost) void ImportTest::exportTest(bytes const& _output, State const& _statePost)
{ {
// export output // export output
m_TestObject["out"] = "0x" + toHex(_output); m_TestObject["out"] = toHex(_output, 2, HexPrefix::Add);
// export logs // export logs
m_TestObject["logs"] = exportLog(_statePost.pending().size() ? _statePost.log(0) : LogEntries()); m_TestObject["logs"] = exportLog(_statePost.pending().size() ? _statePost.log(0) : LogEntries());
@ -352,29 +352,60 @@ void ImportTest::exportTest(bytes const& _output, State const& _statePost)
m_TestObject["transaction"] = makeAllFieldsHex(m_TestObject["transaction"].get_obj()); m_TestObject["transaction"] = makeAllFieldsHex(m_TestObject["transaction"].get_obj());
} }
json_spirit::mObject fillJsonWithTransaction(Transaction _txn)
{
json_spirit::mObject txObject;
txObject["nonce"] = toCompactHex(_txn.nonce(), HexPrefix::Add, 1);
txObject["data"] = toHex(_txn.data(), 2, HexPrefix::Add);
txObject["gasLimit"] = toCompactHex(_txn.gas(), HexPrefix::Add, 1);
txObject["gasPrice"] = toCompactHex(_txn.gasPrice(), HexPrefix::Add, 1);
txObject["r"] = toCompactHex(_txn.signature().r, HexPrefix::Add, 1);
txObject["s"] = toCompactHex(_txn.signature().s, HexPrefix::Add, 1);
txObject["v"] = toCompactHex(_txn.signature().v + 27, HexPrefix::Add, 1);
txObject["to"] = _txn.isCreation() ? "" : toString(_txn.receiveAddress());
txObject["value"] = toCompactHex(_txn.value(), HexPrefix::Add, 1);
return txObject;
}
json_spirit::mObject fillJsonWithState(State _state) json_spirit::mObject fillJsonWithState(State _state)
{ {
// export pre state
json_spirit::mObject oState; json_spirit::mObject oState;
for (auto const& a: _state.addresses()) for (auto const& a: _state.addresses())
{ {
json_spirit::mObject o; json_spirit::mObject o;
o["balance"] = "0x" + toHex(toCompactBigEndian(_state.balance(a.first), 1)); o["balance"] = toCompactHex(_state.balance(a.first), HexPrefix::Add, 1);
o["nonce"] = "0x" + toHex(toCompactBigEndian(_state.transactionsFrom(a.first), 1)); o["nonce"] = toCompactHex(_state.transactionsFrom(a.first), HexPrefix::Add, 1);
{ {
json_spirit::mObject store; json_spirit::mObject store;
for (auto const& s: _state.storage(a.first)) for (auto const& s: _state.storage(a.first))
store["0x"+toHex(toCompactBigEndian(s.first))] = "0x"+toHex(toCompactBigEndian(s.second)); store[toCompactHex(s.first, HexPrefix::Add, 1)] = toCompactHex(s.second, HexPrefix::Add, 1);
o["storage"] = store; o["storage"] = store;
} }
o["code"] = "0x" + toHex(_state.code(a.first)); o["code"] = toHex(_state.code(a.first), 2, HexPrefix::Add);
oState[toString(a.first)] = o; oState[toString(a.first)] = o;
} }
return oState; return oState;
} }
json_spirit::mArray exportLog(eth::LogEntries _logs)
{
json_spirit::mArray ret;
if (_logs.size() == 0) return ret;
for (LogEntry const& l: _logs)
{
json_spirit::mObject o;
o["address"] = toString(l.address);
json_spirit::mArray topics;
for (auto const& t: l.topics)
topics.push_back(toString(t));
o["topics"] = topics;
o["data"] = toHex(l.data, 2, HexPrefix::Add);
o["bloom"] = toString(l.bloom());
ret.push_back(o);
}
return ret;
}
u256 toInt(json_spirit::mValue const& _v) u256 toInt(json_spirit::mValue const& _v)
{ {
switch (_v.type()) switch (_v.type())
@ -455,25 +486,6 @@ LogEntries importLog(json_spirit::mArray& _a)
return logEntries; return logEntries;
} }
json_spirit::mArray exportLog(eth::LogEntries _logs)
{
json_spirit::mArray ret;
if (_logs.size() == 0) return ret;
for (LogEntry const& l: _logs)
{
json_spirit::mObject o;
o["address"] = toString(l.address);
json_spirit::mArray topics;
for (auto const& t: l.topics)
topics.push_back(toString(t));
o["topics"] = topics;
o["data"] = "0x" + toHex(l.data);
o["bloom"] = toString(l.bloom());
ret.push_back(o);
}
return ret;
}
void checkOutput(bytes const& _output, json_spirit::mObject& _o) void checkOutput(bytes const& _output, json_spirit::mObject& _o)
{ {
int j = 0; int j = 0;

1
test/TestHelper.h

@ -161,6 +161,7 @@ void userDefinedTest(std::string testTypeFlag, std::function<void(json_spirit::m
RLPStream createRLPStreamFromTransactionFields(json_spirit::mObject& _tObj); RLPStream createRLPStreamFromTransactionFields(json_spirit::mObject& _tObj);
eth::LastHashes lastHashes(u256 _currentBlockNumber); eth::LastHashes lastHashes(u256 _currentBlockNumber);
json_spirit::mObject fillJsonWithState(eth::State _state); json_spirit::mObject fillJsonWithState(eth::State _state);
json_spirit::mObject fillJsonWithTransaction(eth::Transaction _txn);
template<typename mapType> template<typename mapType>
void checkAddresses(mapType& _expectedAddrs, mapType& _resultAddrs) void checkAddresses(mapType& _expectedAddrs, mapType& _resultAddrs)

4
test/fuzzTesting/checkRandomStateTest.cpp

@ -25,8 +25,8 @@
#include <libdevcore/Exceptions.h> #include <libdevcore/Exceptions.h>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libevm/VMFactory.h> #include <libevm/VMFactory.h>
#include "TestHelper.h" #include <test/libevm/vm.h>
#include "../libevm/vm.h" #include <test/TestHelper.h>
#pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wunused-parameter"
using namespace std; using namespace std;

3
test/fuzzTesting/checkRandomVMTest.cpp

@ -25,7 +25,8 @@
#include <libdevcore/Exceptions.h> #include <libdevcore/Exceptions.h>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libevm/VMFactory.h> #include <libevm/VMFactory.h>
#include "../libevm/vm.h" #include <test/libevm/vm.h>
#include <test/TestHelper.h>
#pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wunused-parameter"

4
test/fuzzTesting/createRandomStateTest.cpp

@ -35,8 +35,8 @@
#include <libdevcore/CommonData.h> #include <libdevcore/CommonData.h>
#include <libevmcore/Instruction.h> #include <libevmcore/Instruction.h>
#include <libevm/VMFactory.h> #include <libevm/VMFactory.h>
#include "../TestHelper.h" #include <test/libevm/vm.h>
#include "../libevm/vm.h" #include <test/TestHelper.h>
using namespace std; using namespace std;
using namespace json_spirit; using namespace json_spirit;

7
test/fuzzTesting/createRandomVMTest.cpp

@ -35,7 +35,8 @@
#include <libdevcore/CommonData.h> #include <libdevcore/CommonData.h>
#include <libevmcore/Instruction.h> #include <libevmcore/Instruction.h>
#include <libevm/VMFactory.h> #include <libevm/VMFactory.h>
#include "../libevm/vm.h" #include <test/libevm/vm.h>
#include <test/TestHelper.h>
using namespace std; using namespace std;
using namespace json_spirit; using namespace json_spirit;
@ -199,8 +200,8 @@ void doMyTests(json_spirit::mValue& _v)
{ {
o["post"] = mValue(fev.exportState()); o["post"] = mValue(fev.exportState());
o["callcreates"] = fev.exportCallCreates(); o["callcreates"] = fev.exportCallCreates();
o["out"] = "0x" + toHex(output); o["out"] = toHex(output, 2, HexPrefix::Add);
fev.push(o, "gas", gas); o["gas"] = toCompactHex(gas, HexPrefix::Add, 1);
o["logs"] = test::exportLog(fev.sub.logs); o["logs"] = test::exportLog(fev.sub.logs);
} }
} }

386
test/libethereum/BlockTestsFiller/bcGasPricerTestFiller.json

@ -0,0 +1,386 @@
{
"highGasUsage" : {
"genesisBlockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "131072",
"extraData" : "0x42",
"gasLimit" : "31415920",
"gasUsed" : "0",
"mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"nonce" : "0x0102030405060708",
"number" : "0",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a",
"timestamp" : "0x54c98c81",
"transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"expect" : {
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "10000000000"
}
},
"pre" : {
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "9000000000000000000000000000",
"nonce" : "0",
"code" : "",
"storage": {}
},
"aaaf5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "10000000000",
"nonce" : "0",
"code" : "0x60003551",
"storage": {}
}
},
"blocks" : [
{
"transactions" : [
{
"data" : "0xffffffffffff",
"gasLimit" : "850000",
"gasPrice" : "10000000000000",
"nonce" : "0",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "0xffffffffffff",
"gasLimit" : "850000",
"gasPrice" : "12000000000000",
"nonce" : "1",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "0xffffffffffff",
"gasLimit" : "850000",
"gasPrice" : "14000000000000",
"nonce" : "2",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "0xffffffffffff",
"gasLimit" : "850000",
"gasPrice" : "16000000000000",
"nonce" : "3",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "0xffffffffffff",
"gasLimit" : "850000",
"gasPrice" : "18000000000000",
"nonce" : "4",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "0xffffffffffff",
"gasLimit" : "850000",
"gasPrice" : "20000000000000",
"nonce" : "5",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "0xffffffffffff",
"gasLimit" : "850000",
"gasPrice" : "22000000000000",
"nonce" : "6",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "0xffffffffffff",
"gasLimit" : "850000",
"gasPrice" : "24000000000000",
"nonce" : "7",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "0xffffffffffff",
"gasLimit" : "850000",
"gasPrice" : "26000000000000",
"nonce" : "8",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "0xffffffffffff",
"gasLimit" : "850000",
"gasPrice" : "28000000000000",
"nonce" : "9",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "0xffffffffffff",
"gasLimit" : "850000",
"gasPrice" : "30000000000000",
"nonce" : "10",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10"
}
],
"uncleHeaders" : [
]
}
]
},
"notxs" : {
"genesisBlockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "131072",
"extraData" : "0x42",
"gasLimit" : "3141592",
"gasUsed" : "0",
"mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"nonce" : "0x0102030405060708",
"number" : "0",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a",
"timestamp" : "0x54c98c81",
"transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"expect" : {
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "10000000000"
}
},
"pre" : {
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "10000000000",
"nonce" : "0",
"code" : "",
"storage": {}
}
},
"blocks" : [
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
},
{
"transactions" : [
],
"uncleHeaders" : [
]
}
]
}
}

0
test/bcRPC_API_TestFiller.json → test/libethereum/BlockTestsFiller/bcRPC_API_TestFiller.json

2
test/libethereum/BlockTestsFiller/bcValidBlockTestFiller.json

@ -430,7 +430,7 @@
] ]
}, },
"DifferentExtraData1024" : { "ExtraData1024" : {
"genesisBlockHeader" : { "genesisBlockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1",

4
test/libethereum/StateTestsFiller/stTransactionTestFiller.json

@ -838,8 +838,8 @@
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
}, },
"expect" : { "expect" : {
"balance" : "0",
"0000000000000000000000000000000000000000" : { "0000000000000000000000000000000000000000" : {
"balance" : "0",
"storage" : { "storage" : {
"0x" : "0x0c", "0x" : "0x0c",
"0x01" : "0x0c", "0x01" : "0x0c",
@ -875,7 +875,7 @@
"c94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "c94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "10", "balance" : "10",
"//" : "gas = 19 going OOG, gas = 20 fine", "code" : "gas = 19 going OOG, gas = 20 fine",
"code" : "{(SSTORE 0 0)(SSTORE 1 0)(SSTORE 2 0)(SSTORE 3 0) (CALL 20000 0 1 0 0 0 0) }", "code" : "{(SSTORE 0 0)(SSTORE 1 0)(SSTORE 2 0)(SSTORE 3 0) (CALL 20000 0 1 0 0 0 0) }",
"nonce" : "0", "nonce" : "0",
"storage" : { "storage" : {

169
test/libethereum/TransactionTestsFiller/ttTransactionTestFiller.json

@ -227,6 +227,57 @@
} }
}, },
"DataTestZeroBytes" : {
"expect" : "valid",
"transaction" :
{
"data" : "0x000000000000000000000000000000000000000000000000000000000",
"gasLimit" : "25000",
"gasPrice" : "1",
"nonce" : "0",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10",
"v" : "27",
"r" : "0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353",
"s" : "secretkey 45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"s" : "0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804"
}
},
"DataTestLastZeroBytes" : {
"expect" : "valid",
"transaction" :
{
"data" : "0x010000000000000000000000000000000000000000000000000000000",
"gasLimit" : "25000",
"gasPrice" : "1",
"nonce" : "0",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10",
"v" : "27",
"r" : "0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353",
"s" : "secretkey 45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"s" : "0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804"
}
},
"DataTestFirstZeroBytes" : {
"expect" : "valid",
"transaction" :
{
"data" : "0x000000000000000000000000001000000000000000000000000000000",
"gasLimit" : "25000",
"gasPrice" : "1",
"nonce" : "0",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10",
"v" : "27",
"r" : "0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353",
"s" : "secretkey 45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"s" : "0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804"
}
},
"TransactionWithTooManyRLPElements" : { "TransactionWithTooManyRLPElements" : {
"expect" : "invalid", "expect" : "invalid",
"transaction" : "transaction" :
@ -303,7 +354,39 @@
"value" : "11", "value" : "11",
"v" : "27", "v" : "27",
"r" : "0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353", "r" : "0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353",
"s" : "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e" "s" : "0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140"
}
},
"TransactionWithSvalue0" : {
"expect" : "invalid",
"transaction" :
{
"data" : "",
"gasLimit" : "21000",
"gasPrice" : "1",
"nonce" : "0",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "11",
"v" : "27",
"r" : "0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353",
"s" : "0"
}
},
"TransactionWithSvalue1" : {
"expect" : "valid",
"transaction" :
{
"data" : "",
"gasLimit" : "21000",
"gasPrice" : "1",
"nonce" : "0",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "11",
"v" : "27",
"r" : "0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353",
"s" : "0x01"
} }
}, },
@ -319,7 +402,7 @@
"value" : "11", "value" : "11",
"v" : "27", "v" : "27",
"r" : "0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353", "r" : "0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353",
"s" : "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f" "s" : "0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"
} }
}, },
@ -387,6 +470,38 @@
} }
}, },
"TransactionWithRvalue0" : {
"expect" : "invalid",
"transaction" :
{
"data" : "",
"gasLimit" : "21000",
"gasPrice" : "1",
"nonce" : "0",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "11",
"v" : "27",
"r" : "0",
"s" : "0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804"
}
},
"TransactionWithRvalue1" : {
"expect" : "valid",
"transaction" :
{
"data" : "",
"gasLimit" : "21000",
"gasPrice" : "1",
"nonce" : "0",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "11",
"v" : "27",
"r" : "0x01",
"s" : "0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804"
}
},
"TransactionWithRvaluePrefixed00" : { "TransactionWithRvaluePrefixed00" : {
"expect" : "valid", "expect" : "valid",
"transaction" : "transaction" :
@ -403,6 +518,38 @@
} }
}, },
"TransactionWithRSvalue0" : {
"expect" : "invalid",
"transaction" :
{
"data" : "",
"gasLimit" : "21000",
"gasPrice" : "1",
"nonce" : "0",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "11",
"v" : "27",
"r" : "0",
"s" : "0"
}
},
"TransactionWithRSvalue1" : {
"expect" : "valid",
"transaction" :
{
"data" : "",
"gasLimit" : "21000",
"gasPrice" : "1",
"nonce" : "0",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "11",
"v" : "27",
"r" : "1",
"s" : "1"
}
},
"TransactionWithSvaluePrefixed00" : { "TransactionWithSvaluePrefixed00" : {
"expect" : "valid", "expect" : "valid",
"transaction" : "transaction" :
@ -419,7 +566,7 @@
} }
}, },
"TransactionWithHihghNonce" : { "TransactionWithHihghNonce256" : {
"expect" : "valid", "expect" : "valid",
"transaction" : "transaction" :
{ {
@ -435,6 +582,22 @@
} }
}, },
"TransactionWithHihghNonce32" : {
"expect" : "valid",
"transaction" :
{
"data" : "",
"gasLimit" : "21000",
"gasPrice" : "1",
"nonce" : "4294967296",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "0",
"v" : "27",
"r" : "0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353",
"s" : "0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804"
}
},
"TransactionWithNonceOverflow" : { "TransactionWithNonceOverflow" : {
"expect" : "invalid", "expect" : "invalid",
"transaction" : "transaction" :

221
test/libethereum/blockchain.cpp

@ -24,7 +24,7 @@
#include <libdevcrypto/FileSystem.h> #include <libdevcrypto/FileSystem.h>
#include <libdevcore/TransientDirectory.h> #include <libdevcore/TransientDirectory.h>
#include <libethereum/CanonBlockChain.h> #include <libethereum/CanonBlockChain.h>
#include "../TestHelper.h" #include <test/TestHelper.h>
using namespace std; using namespace std;
using namespace json_spirit; using namespace json_spirit;
@ -33,12 +33,16 @@ using namespace dev::eth;
namespace dev { namespace test { namespace dev { namespace test {
BlockInfo constructBlock(mObject& _o);
bytes createBlockRLPFromFields(mObject& _tObj); bytes createBlockRLPFromFields(mObject& _tObj);
RLPStream createFullBlockFromHeader(BlockInfo const& _bi, bytes const& _txs = RLPEmptyList, bytes const& _uncles = RLPEmptyList);
mArray writeTransactionsToJson(Transactions const& txs);
mObject writeBlockHeaderToJson(mObject& _o, BlockInfo const& _bi);
void overwriteBlockHeader(BlockInfo& _current_BlockHeader, mObject& _blObj); void overwriteBlockHeader(BlockInfo& _current_BlockHeader, mObject& _blObj);
BlockInfo constructBlock(mObject& _o); BlockInfo constructBlock(mObject& _o);
void updatePoW(BlockInfo& _bi); void updatePoW(BlockInfo& _bi);
void writeBlockHeaderToJson(mObject& _o, BlockInfo const& _bi); mArray importUncles(mObject const& blObj, vector<BlockInfo>& vBiUncles, vector<BlockInfo> const& vBiBlocks);
RLPStream createFullBlockFromHeader(BlockInfo const& _bi, bytes const& _txs = RLPEmptyList, bytes const& _uncles = RLPEmptyList);
void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
{ {
@ -54,8 +58,8 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
ImportTest importer(o["pre"].get_obj()); ImportTest importer(o["pre"].get_obj());
TransientDirectory td_stateDB; TransientDirectory td_stateDB;
TransientDirectory td_stateDB_tmp; TransientDirectory td_stateDB_tmp;
State state(OverlayDB(State::openDB(td_stateDB.path())), BaseState::Empty, biGenesisBlock.coinbaseAddress); State state(State::openDB(td_stateDB.path()), BaseState::Empty, biGenesisBlock.coinbaseAddress);
State stateTemp(OverlayDB(State::openDB(td_stateDB_tmp.path())), BaseState::Empty, biGenesisBlock.coinbaseAddress); State stateTemp(State::openDB(td_stateDB_tmp.path()), BaseState::Empty, biGenesisBlock.coinbaseAddress);
importer.importState(o["pre"].get_obj(), state); importer.importState(o["pre"].get_obj(), state);
o["pre"] = fillJsonWithState(state); o["pre"] = fillJsonWithState(state);
state.commit(); state.commit();
@ -77,7 +81,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
// create new "genesis" block // create new "genesis" block
RLPStream rlpGenesisBlock = createFullBlockFromHeader(biGenesisBlock); RLPStream rlpGenesisBlock = createFullBlockFromHeader(biGenesisBlock);
biGenesisBlock.verifyInternals(&rlpGenesisBlock.out()); biGenesisBlock.verifyInternals(&rlpGenesisBlock.out());
o["genesisRLP"] = "0x" + toHex(rlpGenesisBlock.out()); o["genesisRLP"] = toHex(rlpGenesisBlock.out(), 2, HexPrefix::Add);
// construct blockchain // construct blockchain
TransientDirectory td; TransientDirectory td;
@ -91,6 +95,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
vBiBlocks.push_back(biGenesisBlock); vBiBlocks.push_back(biGenesisBlock);
for (auto const& bl: o["blocks"].get_array()) for (auto const& bl: o["blocks"].get_array())
{ {
stateTemp = state;
mObject blObj = bl.get_obj(); mObject blObj = bl.get_obj();
// get txs // get txs
@ -105,74 +110,15 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
cnote << "failed importing transaction\n"; cnote << "failed importing transaction\n";
} }
// write uncle list //get uncles
BlockQueue uncleBlockQueue;
mArray aUncleList;
vector<BlockInfo> vBiUncles; vector<BlockInfo> vBiUncles;
mObject uncleHeaderObj_pre; blObj["uncleHeaders"] = importUncles(blObj, vBiUncles, vBiBlocks);
for (auto const& uHObj: blObj["uncleHeaders"].get_array()) BlockQueue uncleBlockQueue;
cnote << "import uncle in blockQueue";
for (size_t i = 0; i < vBiUncles.size(); i++)
{ {
mObject uncleHeaderObj = uHObj.get_obj(); RLPStream uncle = createFullBlockFromHeader(vBiUncles.at(i));
if (uncleHeaderObj.count("sameAsPreviousSibling"))
{
writeBlockHeaderToJson(uncleHeaderObj_pre, vBiUncles[vBiUncles.size()-1]);
aUncleList.push_back(uncleHeaderObj_pre);
vBiUncles.push_back(vBiUncles[vBiUncles.size()-1]);
continue;
}
if (uncleHeaderObj.count("sameAsBlock"))
{
writeBlockHeaderToJson(uncleHeaderObj_pre, vBiBlocks[(size_t)toInt(uncleHeaderObj["sameAsBlock"])]);
aUncleList.push_back(uncleHeaderObj_pre);
vBiUncles.push_back(vBiBlocks[(size_t)toInt(uncleHeaderObj["sameAsBlock"])]);
continue;
}
string overwrite = "false";
if (uncleHeaderObj.count("overwriteAndRedoPoW"))
{
overwrite = uncleHeaderObj["overwriteAndRedoPoW"].get_str();
uncleHeaderObj.erase("overwriteAndRedoPoW");
}
BlockInfo uncleBlockFromFields = constructBlock(uncleHeaderObj);
// make uncle header valid
uncleBlockFromFields.timestamp = (u256)time(0);
if (vBiBlocks.size() > 2)
{
if (uncleBlockFromFields.number - 1 < vBiBlocks.size())
uncleBlockFromFields.populateFromParent(vBiBlocks[(size_t)uncleBlockFromFields.number - 1]);
else
uncleBlockFromFields.populateFromParent(vBiBlocks[vBiBlocks.size() - 2]);
}
else
continue;
if (overwrite != "false")
{
uncleBlockFromFields.difficulty = overwrite == "difficulty" ? toInt(uncleHeaderObj["difficulty"]) : uncleBlockFromFields.difficulty;
uncleBlockFromFields.gasLimit = overwrite == "gasLimit" ? toInt(uncleHeaderObj["gasLimit"]) : uncleBlockFromFields.gasLimit;
uncleBlockFromFields.gasUsed = overwrite == "gasUsed" ? toInt(uncleHeaderObj["gasUsed"]) : uncleBlockFromFields.gasUsed;
uncleBlockFromFields.parentHash = overwrite == "parentHash" ? h256(uncleHeaderObj["parentHash"].get_str()) : uncleBlockFromFields.parentHash;
uncleBlockFromFields.stateRoot = overwrite == "stateRoot" ? h256(uncleHeaderObj["stateRoot"].get_str()) : uncleBlockFromFields.stateRoot;
if (overwrite == "timestamp")
{
uncleBlockFromFields.timestamp = toInt(uncleHeaderObj["timestamp"]);
uncleBlockFromFields.difficulty = uncleBlockFromFields.calculateDifficulty(vBiBlocks[(size_t)uncleBlockFromFields.number - 1]);
}
}
updatePoW(uncleBlockFromFields);
writeBlockHeaderToJson(uncleHeaderObj, uncleBlockFromFields);
aUncleList.push_back(uncleHeaderObj);
vBiUncles.push_back(uncleBlockFromFields);
cnote << "import uncle in blockQueue";
RLPStream uncle = createFullBlockFromHeader(uncleBlockFromFields);
try try
{ {
uncleBlockQueue.import(&uncle.out(), bc); uncleBlockQueue.import(&uncle.out(), bc);
@ -181,11 +127,8 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
{ {
cnote << "error in importing uncle! This produces an invalid block (May be by purpose for testing)."; cnote << "error in importing uncle! This produces an invalid block (May be by purpose for testing).";
} }
}
uncleHeaderObj_pre = uncleHeaderObj;
} //for blObj["uncleHeaders"].get_array()
blObj["uncleHeaders"] = aUncleList;
bc.sync(uncleBlockQueue, state.db(), 4); bc.sync(uncleBlockQueue, state.db(), 4);
state.commitToMine(bc); state.commitToMine(bc);
@ -206,33 +149,15 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
return; return;
} }
blObj["rlp"] = "0x" + toHex(state.blockData()); blObj["rlp"] = toHex(state.blockData(), 2, HexPrefix::Add);
// write valid txs //get valid transactions
mArray txArray;
Transactions txList; Transactions txList;
for (auto const& txi: txs.transactions()) for (auto const& txi: txs.transactions())
{
txList.push_back(txi.second); txList.push_back(txi.second);
mObject txObject; blObj["transactions"] = writeTransactionsToJson(txList);
txObject["nonce"] = toString(txi.second.nonce());
txObject["data"] = "0x" + toHex(txi.second.data());
txObject["gasLimit"] = toString(txi.second.gas());
txObject["gasPrice"] = toString(txi.second.gasPrice());
txObject["r"] = "0x" + toString(txi.second.signature().r);
txObject["s"] = "0x" + toString(txi.second.signature().s);
txObject["v"] = to_string(txi.second.signature().v + 27);
txObject["to"] = txi.second.isCreation() ? "" : toString(txi.second.receiveAddress());
txObject["value"] = toString(txi.second.value());
txObject = ImportTest::makeAllFieldsHex(txObject);
txArray.push_back(txObject);
}
blObj["transactions"] = txArray;
BlockInfo current_BlockHeader = state.info(); BlockInfo current_BlockHeader = state.info();
if (blObj.count("blockHeader")) if (blObj.count("blockHeader"))
overwriteBlockHeader(current_BlockHeader, blObj); overwriteBlockHeader(current_BlockHeader, blObj);
@ -263,7 +188,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
RLPStream block2 = createFullBlockFromHeader(current_BlockHeader, txStream.out(), uncleStream.out()); RLPStream block2 = createFullBlockFromHeader(current_BlockHeader, txStream.out(), uncleStream.out());
blObj["rlp"] = "0x" + toHex(block2.out()); blObj["rlp"] = toHex(block2.out(), 2, HexPrefix::Add);
if (sha3(RLP(state.blockData())[0].data()) != sha3(RLP(block2.out())[0].data())) if (sha3(RLP(state.blockData())[0].data()) != sha3(RLP(block2.out())[0].data()))
cnote << "block header mismatch\n"; cnote << "block header mismatch\n";
@ -483,6 +408,77 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
// helping functions // helping functions
mArray importUncles(mObject const& blObj, vector<BlockInfo>& vBiUncles, vector<BlockInfo> const& vBiBlocks)
{
// write uncle list
mArray aUncleList;
mObject uncleHeaderObj_pre;
for (auto const& uHObj: blObj.at("uncleHeaders").get_array())
{
mObject uncleHeaderObj = uHObj.get_obj();
if (uncleHeaderObj.count("sameAsPreviousSibling"))
{
writeBlockHeaderToJson(uncleHeaderObj_pre, vBiUncles[vBiUncles.size()-1]);
aUncleList.push_back(uncleHeaderObj_pre);
vBiUncles.push_back(vBiUncles[vBiUncles.size()-1]);
continue;
}
if (uncleHeaderObj.count("sameAsBlock"))
{
writeBlockHeaderToJson(uncleHeaderObj_pre, vBiBlocks[(size_t)toInt(uncleHeaderObj["sameAsBlock"])]);
aUncleList.push_back(uncleHeaderObj_pre);
vBiUncles.push_back(vBiBlocks[(size_t)toInt(uncleHeaderObj["sameAsBlock"])]);
continue;
}
string overwrite = "false";
if (uncleHeaderObj.count("overwriteAndRedoPoW"))
{
overwrite = uncleHeaderObj["overwriteAndRedoPoW"].get_str();
uncleHeaderObj.erase("overwriteAndRedoPoW");
}
BlockInfo uncleBlockFromFields = constructBlock(uncleHeaderObj);
// make uncle header valid
uncleBlockFromFields.timestamp = (u256)time(0);
if (vBiBlocks.size() > 2)
{
if (uncleBlockFromFields.number - 1 < vBiBlocks.size())
uncleBlockFromFields.populateFromParent(vBiBlocks[(size_t)uncleBlockFromFields.number - 1]);
else
uncleBlockFromFields.populateFromParent(vBiBlocks[vBiBlocks.size() - 2]);
}
else
continue;
if (overwrite != "false")
{
uncleBlockFromFields.difficulty = overwrite == "difficulty" ? toInt(uncleHeaderObj["difficulty"]) : uncleBlockFromFields.difficulty;
uncleBlockFromFields.gasLimit = overwrite == "gasLimit" ? toInt(uncleHeaderObj["gasLimit"]) : uncleBlockFromFields.gasLimit;
uncleBlockFromFields.gasUsed = overwrite == "gasUsed" ? toInt(uncleHeaderObj["gasUsed"]) : uncleBlockFromFields.gasUsed;
uncleBlockFromFields.parentHash = overwrite == "parentHash" ? h256(uncleHeaderObj["parentHash"].get_str()) : uncleBlockFromFields.parentHash;
uncleBlockFromFields.stateRoot = overwrite == "stateRoot" ? h256(uncleHeaderObj["stateRoot"].get_str()) : uncleBlockFromFields.stateRoot;
if (overwrite == "timestamp")
{
uncleBlockFromFields.timestamp = toInt(uncleHeaderObj["timestamp"]);
uncleBlockFromFields.difficulty = uncleBlockFromFields.calculateDifficulty(vBiBlocks[(size_t)uncleBlockFromFields.number - 1]);
}
}
updatePoW(uncleBlockFromFields);
writeBlockHeaderToJson(uncleHeaderObj, uncleBlockFromFields);
aUncleList.push_back(uncleHeaderObj);
vBiUncles.push_back(uncleBlockFromFields);
uncleHeaderObj_pre = uncleHeaderObj;
} //for blObj["uncleHeaders"].get_array()
return aUncleList;
}
bytes createBlockRLPFromFields(mObject& _tObj) bytes createBlockRLPFromFields(mObject& _tObj)
{ {
RLPStream rlpStream; RLPStream rlpStream;
@ -619,7 +615,18 @@ void updatePoW(BlockInfo& _bi)
_bi.noteDirty(); _bi.noteDirty();
} }
void writeBlockHeaderToJson(mObject& _o, BlockInfo const& _bi) mArray writeTransactionsToJson(Transactions const& txs)
{
mArray txArray;
for (auto const& txi: txs)
{
mObject txObject = fillJsonWithTransaction(txi);
txArray.push_back(txObject);
}
return txArray;
}
mObject writeBlockHeaderToJson(mObject& _o, BlockInfo const& _bi)
{ {
_o["parentHash"] = toString(_bi.parentHash); _o["parentHash"] = toString(_bi.parentHash);
_o["uncleHash"] = toString(_bi.sha3Uncles); _o["uncleHash"] = toString(_bi.sha3Uncles);
@ -628,15 +635,16 @@ void writeBlockHeaderToJson(mObject& _o, BlockInfo const& _bi)
_o["transactionsTrie"] = toString(_bi.transactionsRoot); _o["transactionsTrie"] = toString(_bi.transactionsRoot);
_o["receiptTrie"] = toString(_bi.receiptsRoot); _o["receiptTrie"] = toString(_bi.receiptsRoot);
_o["bloom"] = toString(_bi.logBloom); _o["bloom"] = toString(_bi.logBloom);
_o["difficulty"] = "0x" + toHex(toCompactBigEndian(_bi.difficulty, 1)); _o["difficulty"] = toCompactHex(_bi.difficulty, HexPrefix::Add, 1);
_o["number"] = "0x" + toHex(toCompactBigEndian(_bi.number, 1)); _o["number"] = toCompactHex(_bi.number, HexPrefix::Add, 1);
_o["gasLimit"] = "0x" + toHex(toCompactBigEndian(_bi.gasLimit, 1)); _o["gasLimit"] = toCompactHex(_bi.gasLimit, HexPrefix::Add, 1);
_o["gasUsed"] = "0x" + toHex(toCompactBigEndian(_bi.gasUsed, 1)); _o["gasUsed"] = toCompactHex(_bi.gasUsed, HexPrefix::Add, 1);
_o["timestamp"] = "0x" + toHex(toCompactBigEndian(_bi.timestamp, 1)); _o["timestamp"] = toCompactHex(_bi.timestamp, HexPrefix::Add, 1);
_o["extraData"] ="0x" + toHex(_bi.extraData); _o["extraData"] = toHex(_bi.extraData, 2, HexPrefix::Add);
_o["mixHash"] = toString(_bi.mixHash); _o["mixHash"] = toString(_bi.mixHash);
_o["nonce"] = toString(_bi.nonce); _o["nonce"] = toString(_bi.nonce);
_o["hash"] = toString(_bi.hash()); _o["hash"] = toString(_bi.hash());
return _o;
} }
RLPStream createFullBlockFromHeader(BlockInfo const& _bi, bytes const& _txs, bytes const& _uncles) RLPStream createFullBlockFromHeader(BlockInfo const& _bi, bytes const& _txs, bytes const& _uncles)
@ -691,6 +699,11 @@ BOOST_AUTO_TEST_CASE(bcUncleHeaderValiditiy)
dev::test::executeTests("bcUncleHeaderValiditiy", "/BlockTests",dev::test::getFolder(__FILE__) + "/BlockTestsFiller", dev::test::doBlockchainTests); dev::test::executeTests("bcUncleHeaderValiditiy", "/BlockTests",dev::test::getFolder(__FILE__) + "/BlockTestsFiller", dev::test::doBlockchainTests);
} }
BOOST_AUTO_TEST_CASE(bcGasPricerTest)
{
dev::test::executeTests("bcGasPricerTest", "/BlockTests",dev::test::getFolder(__FILE__) + "/BlockTestsFiller", dev::test::doBlockchainTests);
}
BOOST_AUTO_TEST_CASE(userDefinedFile) BOOST_AUTO_TEST_CASE(userDefinedFile)
{ {
dev::test::userDefinedTest("--singletest", dev::test::doBlockchainTests); dev::test::userDefinedTest("--singletest", dev::test::doBlockchainTests);

140
test/libethereum/gaspricer.cpp

@ -0,0 +1,140 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file gasPricer.cpp
* @author Christoph Jentzsch <cj@ethdev.com>
* @date 2015
*/
#include <libtestutils/BlockChainLoader.h>
#include <libethereum/State.h>
#include <libethereum/BlockChain.h>
#include <libethereum/Client.h>
#include <libdevcore/TransientDirectory.h>
#include "../TestHelper.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
namespace dev { namespace test {
void executeGasPricerTest(const string name, double _etherPrice, double _blockFee, const string bcTestPath, TransactionPriority _txPrio, u256 _expectedAsk, u256 _expectedBid)
{
cnote << name;
BasicGasPricer gp(u256(double(ether / 1000) / _etherPrice), u256(_blockFee * 1000));
Json::Value vJson = test::loadJsonFromFile(test::getTestPath() + bcTestPath);
test::BlockChainLoader bcLoader(vJson[name]);
BlockChain const& bc = bcLoader.bc();
gp.update(bc);
BOOST_CHECK_EQUAL(gp.ask(State()), _expectedAsk);
BOOST_CHECK_EQUAL(gp.bid(_txPrio), _expectedBid);
}
} }
BOOST_AUTO_TEST_SUITE(GasPricer)
BOOST_AUTO_TEST_CASE(trivialGasPricer)
{
cnote << "trivialGasPricer";
std::shared_ptr<dev::eth::GasPricer> gp(new TrivialGasPricer);
BOOST_CHECK_EQUAL(gp->ask(State()), 10 * szabo);
BOOST_CHECK_EQUAL(gp->bid(), 10 * szabo);
gp->update(BlockChain(bytes(), TransientDirectory().path(), WithExisting::Kill));
BOOST_CHECK_EQUAL(gp->ask(State()), 10 * szabo);
BOOST_CHECK_EQUAL(gp->bid(), 10 * szabo);
}
BOOST_AUTO_TEST_CASE(basicGasPricerNoUpdate)
{
cnote << "basicGasPricer";
BasicGasPricer gp(u256(double(ether / 1000) / 30.679), u256(15.0 * 1000));
BOOST_CHECK_EQUAL(gp.ask(State()), 155632494086);
BOOST_CHECK_EQUAL(gp.bid(), 155632494086);
gp.setRefPrice(u256(0));
BOOST_CHECK_EQUAL(gp.ask(State()), 0);
BOOST_CHECK_EQUAL(gp.bid(), 0);
gp.setRefPrice(u256(1));
gp.setRefBlockFees(u256(0));
BOOST_CHECK_EQUAL(gp.ask(State()), 0);
BOOST_CHECK_EQUAL(gp.bid(), 0);
gp.setRefPrice(u256("0x100000000000000000000000000000000"));
BOOST_CHECK_THROW(gp.setRefBlockFees(u256("0x100000000000000000000000000000000")), Overflow);
BOOST_CHECK_EQUAL(gp.ask(State()), 0);
BOOST_CHECK_EQUAL(gp.bid(), 0);
gp.setRefPrice(1);
gp.setRefBlockFees(u256("0x100000000000000000000000000000000"));
BOOST_CHECK_THROW(gp.setRefPrice(u256("0x100000000000000000000000000000000")), Overflow);
BOOST_CHECK_EQUAL(gp.ask(State()), u256("108315264019305646138446560671076"));
BOOST_CHECK_EQUAL(gp.bid(), u256("108315264019305646138446560671076"));
}
BOOST_AUTO_TEST_CASE(basicGasPricer_RPC_API_Test)
{
dev::test::executeGasPricerTest("RPC_API_Test", 30.679, 15.0, "/BlockTests/bcRPC_API_Test.json", TransactionPriority::Medium, 155632494086, 1);
}
BOOST_AUTO_TEST_CASE(basicGasPricer_bcValidBlockTest)
{
dev::test::executeGasPricerTest("SimpleTx", 30.679, 15.0, "/BlockTests/bcValidBlockTest.json", TransactionPriority::Medium, 155632494086, 10);
}
BOOST_AUTO_TEST_CASE(basicGasPricer_bcUncleTest)
{
dev::test::executeGasPricerTest("twoUncle", 30.679, 15.0, "/BlockTests/bcUncleTest.json", TransactionPriority::Medium, 155632494086, 1);
}
BOOST_AUTO_TEST_CASE(basicGasPricer_bcUncleHeaderValiditiy)
{
dev::test::executeGasPricerTest("correct", 30.679, 15.0, "/BlockTests/bcUncleHeaderValiditiy.json", TransactionPriority::Medium, 155632494086, 1);
}
BOOST_AUTO_TEST_CASE(basicGasPricer_notxs)
{
dev::test::executeGasPricerTest("notxs", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::Medium, 155632494086, 155632494086);
}
BOOST_AUTO_TEST_CASE(basicGasPricer_highGasUsage_LowestPrio)
{
dev::test::executeGasPricerTest("highGasUsage", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::Lowest, 15731292650, 10000000000000);
}
BOOST_AUTO_TEST_CASE(basicGasPricer_highGasUsage_LowPrio)
{
dev::test::executeGasPricerTest("highGasUsage", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::Low, 15731292650, 15734152261884);
}
BOOST_AUTO_TEST_CASE(basicGasPricer_highGasUsage_MediumPrio)
{
dev::test::executeGasPricerTest("highGasUsage", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::Medium, 15731292650, 20000000000000);
}
BOOST_AUTO_TEST_CASE(basicGasPricer_highGasUsage_HighPrio)
{
dev::test::executeGasPricerTest("highGasUsage", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::High, 15731292650, 24265847738115);
}
BOOST_AUTO_TEST_CASE(basicGasPricer_highGasUsage_HighestPrio)
{
dev::test::executeGasPricerTest("highGasUsage", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::Highest, 15731292650, 30000000000000);
}
BOOST_AUTO_TEST_SUITE_END()

2
test/libethereum/state.cpp

@ -30,7 +30,7 @@
#include <libethereum/ExtVM.h> #include <libethereum/ExtVM.h>
#include <libethereum/Defaults.h> #include <libethereum/Defaults.h>
#include <libevm/VM.h> #include <libevm/VM.h>
#include "../TestHelper.h" #include <test/TestHelper.h>
using namespace std; using namespace std;
using namespace json_spirit; using namespace json_spirit;

2
test/libethereum/transaction.cpp

@ -43,7 +43,7 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin)
//Construct Rlp of the given transaction //Construct Rlp of the given transaction
RLPStream rlpStream = createRLPStreamFromTransactionFields(tObj); RLPStream rlpStream = createRLPStreamFromTransactionFields(tObj);
o["rlp"] = "0x" + toHex(rlpStream.out()); o["rlp"] = toHex(rlpStream.out(), 2, HexPrefix::Add);
try try
{ {

50
test/libevm/vm.cpp

@ -83,25 +83,15 @@ void FakeExtVM::reset(u256 _myBalance, u256 _myNonce, map<u256, u256> const& _st
set(myAddress, _myBalance, _myNonce, _storage, get<3>(addresses[myAddress])); set(myAddress, _myBalance, _myNonce, _storage, get<3>(addresses[myAddress]));
} }
void FakeExtVM::push(mObject& o, string const& _n, u256 _v)
{
o[_n] = "0x" + toHex(toCompactBigEndian(_v));
}
void FakeExtVM::push(mArray& a, u256 _v)
{
a.push_back(toString(_v));
}
mObject FakeExtVM::exportEnv() mObject FakeExtVM::exportEnv()
{ {
mObject ret; mObject ret;
ret["previousHash"] = toString(currentBlock.parentHash); ret["previousHash"] = toString(currentBlock.parentHash);
push(ret, "currentDifficulty", currentBlock.difficulty); ret["currentDifficulty"] = toCompactHex(currentBlock.difficulty, HexPrefix::Add, 1);
push(ret, "currentTimestamp", currentBlock.timestamp); ret["currentTimestamp"] = toCompactHex(currentBlock.timestamp, HexPrefix::Add, 1);
ret["currentCoinbase"] = toString(currentBlock.coinbaseAddress); ret["currentCoinbase"] = toString(currentBlock.coinbaseAddress);
push(ret, "currentNumber", currentBlock.number); ret["currentNumber"] = toCompactHex(currentBlock.number, HexPrefix::Add, 1);
push(ret, "currentGasLimit", currentBlock.gasLimit); ret["currentGasLimit"] = toCompactHex(currentBlock.gasLimit, HexPrefix::Add, 1);
return ret; return ret;
} }
@ -130,17 +120,15 @@ mObject FakeExtVM::exportState()
for (auto const& a: addresses) for (auto const& a: addresses)
{ {
mObject o; mObject o;
push(o, "balance", get<0>(a.second)); o["balance"] = toCompactHex(get<0>(a.second), HexPrefix::Add, 1);
push(o, "nonce", get<1>(a.second)); o["nonce"] = toCompactHex(get<1>(a.second), HexPrefix::Add, 1);
{ {
mObject store; mObject store;
for (auto const& s: get<2>(a.second)) for (auto const& s: get<2>(a.second))
store["0x"+toHex(toCompactBigEndian(s.first))] = "0x"+toHex(toCompactBigEndian(s.second)); store[toCompactHex(s.first, HexPrefix::Add, 1)] = toCompactHex(s.second, HexPrefix::Add, 1);
o["storage"] = store; o["storage"] = store;
} }
o["code"] = "0x" + toHex(get<3>(a.second)); o["code"] = toHex(get<3>(a.second), 2, HexPrefix::Add);
ret[toString(a.first)] = o; ret[toString(a.first)] = o;
} }
return ret; return ret;
@ -173,11 +161,11 @@ mObject FakeExtVM::exportExec()
ret["address"] = toString(myAddress); ret["address"] = toString(myAddress);
ret["caller"] = toString(caller); ret["caller"] = toString(caller);
ret["origin"] = toString(origin); ret["origin"] = toString(origin);
push(ret, "value", value); ret["value"] = toCompactHex(value, HexPrefix::Add, 1);
push(ret, "gasPrice", gasPrice); ret["gasPrice"] = toCompactHex(gasPrice, HexPrefix::Add, 1);
push(ret, "gas", gas); ret["gas"] = toCompactHex(gas, HexPrefix::Add, 1);
ret["data"] = "0x" + toHex(data); ret["data"] = toHex(data, 2, HexPrefix::Add);
ret["code"] = "0x" + toHex(code); ret["code"] = toHex(code, 2, HexPrefix::Add);
return ret; return ret;
} }
@ -219,9 +207,9 @@ mArray FakeExtVM::exportCallCreates()
{ {
mObject o; mObject o;
o["destination"] = tx.isCreation() ? "" : toString(tx.receiveAddress()); o["destination"] = tx.isCreation() ? "" : toString(tx.receiveAddress());
push(o, "gasLimit", tx.gas()); o["gasLimit"] = toCompactHex(tx.gas(), HexPrefix::Add, 1);
push(o, "value", tx.value()); o["value"] = toCompactHex(tx.value(), HexPrefix::Add, 1);
o["data"] = "0x" + toHex(tx.data()); o["data"] = toHex(tx.data(), 2, HexPrefix::Add);
ret.push_back(o); ret.push_back(o);
} }
return ret; return ret;
@ -292,7 +280,7 @@ eth::OnOpFunc FakeExtVM::simpleTrace()
o_step.push_back(Pair("storage", storage)); o_step.push_back(Pair("storage", storage));
o_step.push_back(Pair("depth", to_string(ext.depth))); o_step.push_back(Pair("depth", to_string(ext.depth)));
o_step.push_back(Pair("gas", (string)vm.gas())); o_step.push_back(Pair("gas", (string)vm.gas()));
o_step.push_back(Pair("address", "0x" + toString(ext.myAddress ))); o_step.push_back(Pair("address", toString(ext.myAddress )));
o_step.push_back(Pair("step", steps )); o_step.push_back(Pair("step", steps ));
o_step.push_back(Pair("pc", (int)vm.curPC())); o_step.push_back(Pair("pc", (int)vm.curPC()));
o_step.push_back(Pair("opcode", instructionInfo(inst).name )); o_step.push_back(Pair("opcode", instructionInfo(inst).name ));
@ -400,8 +388,8 @@ void doVMTests(json_spirit::mValue& v, bool _fillin)
} }
o["callcreates"] = fev.exportCallCreates(); o["callcreates"] = fev.exportCallCreates();
o["out"] = "0x" + toHex(output); o["out"] = toHex(output, 2, HexPrefix::Add);
fev.push(o, "gas", gas); o["gas"] = toCompactHex(gas, HexPrefix::Add, 1);
o["logs"] = exportLog(fev.sub.logs); o["logs"] = exportLog(fev.sub.logs);
} }
} }

4
test/libevm/vm.h

@ -38,7 +38,7 @@ along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
#include <libethereum/Transaction.h> #include <libethereum/Transaction.h>
#include <libethereum/ExtVM.h> #include <libethereum/ExtVM.h>
#include <libethereum/State.h> #include <libethereum/State.h>
#include "../TestHelper.h" #include <test/TestHelper.h>
namespace dev { namespace test { namespace dev { namespace test {
@ -64,8 +64,6 @@ public:
void setContract(Address _myAddress, u256 _myBalance, u256 _myNonce, std::map<u256, u256> const& _storage, bytes const& _code); void setContract(Address _myAddress, u256 _myBalance, u256 _myNonce, std::map<u256, u256> const& _storage, bytes const& _code);
void set(Address _a, u256 _myBalance, u256 _myNonce, std::map<u256, u256> const& _storage, bytes const& _code); void set(Address _a, u256 _myBalance, u256 _myNonce, std::map<u256, u256> const& _storage, bytes const& _code);
void reset(u256 _myBalance, u256 _myNonce, std::map<u256, u256> const& _storage); void reset(u256 _myBalance, u256 _myNonce, std::map<u256, u256> const& _storage);
void push(json_spirit::mObject& o, std::string const& _n, u256 _v);
void push(json_spirit::mArray& a, u256 _v);
u256 doPosts(); u256 doPosts();
json_spirit::mObject exportEnv(); json_spirit::mObject exportEnv();
void importEnv(json_spirit::mObject& _o); void importEnv(json_spirit::mObject& _o);

30
test/libsolidity/SolidityABIJSON.cpp

@ -495,6 +495,36 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter)
checkInterface(sourceCode, interface); checkInterface(sourceCode, interface);
} }
BOOST_AUTO_TEST_CASE(constructor_abi)
{
char const* sourceCode = R"(
contract test {
function test(uint param1, test param2, bool param3) {}
}
)";
char const* interface = R"([
{
"inputs": [
{
"name": "param1",
"type": "uint256"
},
{
"name": "param2",
"type": "address"
},
{
"name": "param3",
"type": "bool"
}
],
"type": "constructor"
}
])";
checkInterface(sourceCode, interface);
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }

16
test/libsolidity/SolidityOptimizer.cpp

@ -22,6 +22,7 @@
#include <string> #include <string>
#include <tuple> #include <tuple>
#include <memory>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <test/libsolidity/solidityExecutionFramework.h> #include <test/libsolidity/solidityExecutionFramework.h>
@ -84,9 +85,20 @@ public:
AssemblyItems getCSE(AssemblyItems const& _input) AssemblyItems getCSE(AssemblyItems const& _input)
{ {
// add dummy locations to each item so that we can check that they are not deleted
AssemblyItems input = _input;
for (AssemblyItem& item: input)
item.setLocation(SourceLocation(1, 3, make_shared<string>("")));
eth::CommonSubexpressionEliminator cse; eth::CommonSubexpressionEliminator cse;
BOOST_REQUIRE(cse.feedItems(_input.begin(), _input.end()) == _input.end()); BOOST_REQUIRE(cse.feedItems(input.begin(), input.end()) == input.end());
return cse.getOptimizedItems(); AssemblyItems output = cse.getOptimizedItems();
for (AssemblyItem const& item: output)
{
BOOST_CHECK(item == Instruction::POP || !item.getLocation().isEmpty());
}
return output;
} }
void checkCSE(AssemblyItems const& _input, AssemblyItems const& _expectation) void checkCSE(AssemblyItems const& _input, AssemblyItems const& _expectation)

4
test/libweb3jsonrpc/jsonrpc.cpp

@ -35,7 +35,7 @@
#include <jsonrpccpp/client/connectors/httpclient.h> #include <jsonrpccpp/client/connectors/httpclient.h>
#include <set> #include <set>
#include "../JsonSpiritHeaders.h" #include "../JsonSpiritHeaders.h"
#include "../TestHelper.h" #include "<test/TestHelper.h>"
#include "webthreestubclient.h" #include "webthreestubclient.h"
BOOST_AUTO_TEST_SUITE(jsonrpc) BOOST_AUTO_TEST_SUITE(jsonrpc)
@ -75,7 +75,7 @@ struct Setup
string fromAscii(string _s) string fromAscii(string _s)
{ {
bytes b = asBytes(_s); bytes b = asBytes(_s);
return "0x" + toHex(b); return toHex(b, 2, HexPrefix::Add);
} }
BOOST_FIXTURE_TEST_SUITE(environment, Setup) BOOST_FIXTURE_TEST_SUITE(environment, Setup)

626
test/webthreestubclient.h

@ -0,0 +1,626 @@
/**
* This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY!
*/
#ifndef JSONRPC_CPP_STUB_WEBTHREESTUBCLIENT_H_
#define JSONRPC_CPP_STUB_WEBTHREESTUBCLIENT_H_
#include <jsonrpccpp/client.h>
class WebThreeStubClient : public jsonrpc::Client
{
public:
WebThreeStubClient(jsonrpc::IClientConnector &conn, jsonrpc::clientVersion_t type = jsonrpc::JSONRPC_CLIENT_V2) : jsonrpc::Client(conn, type) {}
std::string web3_sha3(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("web3_sha3",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string web3_clientVersion() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("web3_clientVersion",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string net_version() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("net_version",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string net_peerCount() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("net_peerCount",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool net_listening() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("net_listening",p);
if (result.isBool())
return result.asBool();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_protocolVersion() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("eth_protocolVersion",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_hashrate() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("eth_hashrate",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_coinbase() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("eth_coinbase",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool eth_mining() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("eth_mining",p);
if (result.isBool())
return result.asBool();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_gasPrice() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("eth_gasPrice",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_accounts() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("eth_accounts",p);
if (result.isArray())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_blockNumber() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("eth_blockNumber",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_getBalance(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
p.append(param2);
Json::Value result = this->CallMethod("eth_getBalance",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_getStorageAt(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
p.append(param2);
p.append(param3);
Json::Value result = this->CallMethod("eth_getStorageAt",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_getTransactionCount(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
p.append(param2);
Json::Value result = this->CallMethod("eth_getTransactionCount",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_getBlockTransactionCountByHash(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_getBlockTransactionCountByHash",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_getBlockTransactionCountByNumber(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_getBlockTransactionCountByNumber",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_getUncleCountByBlockHash(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_getUncleCountByBlockHash",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_getUncleCountByBlockNumber(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_getUncleCountByBlockNumber",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_getCode(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
p.append(param2);
Json::Value result = this->CallMethod("eth_getCode",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_sendTransaction(const Json::Value& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_sendTransaction",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_call(const Json::Value& param1, const std::string& param2) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
p.append(param2);
Json::Value result = this->CallMethod("eth_call",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool eth_flush() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("eth_flush",p);
if (result.isBool())
return result.asBool();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_getBlockByHash(const std::string& param1, bool param2) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
p.append(param2);
Json::Value result = this->CallMethod("eth_getBlockByHash",p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_getBlockByNumber(const std::string& param1, bool param2) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
p.append(param2);
Json::Value result = this->CallMethod("eth_getBlockByNumber",p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_getTransactionByHash(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_getTransactionByHash",p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_getTransactionByBlockHashAndIndex(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
p.append(param2);
Json::Value result = this->CallMethod("eth_getTransactionByBlockHashAndIndex",p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_getTransactionByBlockNumberAndIndex(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
p.append(param2);
Json::Value result = this->CallMethod("eth_getTransactionByBlockNumberAndIndex",p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_getUncleByBlockHashAndIndex(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
p.append(param2);
Json::Value result = this->CallMethod("eth_getUncleByBlockHashAndIndex",p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_getUncleByBlockNumberAndIndex(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
p.append(param2);
Json::Value result = this->CallMethod("eth_getUncleByBlockNumberAndIndex",p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_getCompilers() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("eth_getCompilers",p);
if (result.isArray())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_compileLLL(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_compileLLL",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_compileSerpent(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_compileSerpent",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_compileSolidity(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_compileSolidity",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_newFilter(const Json::Value& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_newFilter",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_newBlockFilter(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_newBlockFilter",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool eth_uninstallFilter(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_uninstallFilter",p);
if (result.isBool())
return result.asBool();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_getFilterChanges(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_getFilterChanges",p);
if (result.isArray())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_getFilterLogs(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_getFilterLogs",p);
if (result.isArray())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_getLogs(const Json::Value& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_getLogs",p);
if (result.isArray())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_getWork() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("eth_getWork",p);
if (result.isArray())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool eth_submitWork(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
p.append(param2);
p.append(param3);
Json::Value result = this->CallMethod("eth_submitWork",p);
if (result.isBool())
return result.asBool();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_register(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_register",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool eth_unregister(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_unregister",p);
if (result.isBool())
return result.asBool();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_fetchQueuedTransactions(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_fetchQueuedTransactions",p);
if (result.isArray())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string eth_signTransaction(const Json::Value& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_signTransaction",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value eth_inspectTransaction(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_inspectTransaction",p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool eth_injectTransaction(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_injectTransaction",p);
if (result.isBool())
return result.asBool();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool db_put(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
p.append(param2);
p.append(param3);
Json::Value result = this->CallMethod("db_put",p);
if (result.isBool())
return result.asBool();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string db_get(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
p.append(param2);
Json::Value result = this->CallMethod("db_get",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool shh_post(const Json::Value& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("shh_post",p);
if (result.isBool())
return result.asBool();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string shh_newIdentity() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("shh_newIdentity",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool shh_hasIdentity(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("shh_hasIdentity",p);
if (result.isBool())
return result.asBool();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string shh_newGroup(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
p.append(param2);
Json::Value result = this->CallMethod("shh_newGroup",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string shh_addToGroup(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
p.append(param2);
Json::Value result = this->CallMethod("shh_addToGroup",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
std::string shh_newFilter(const Json::Value& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("shh_newFilter",p);
if (result.isString())
return result.asString();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool shh_uninstallFilter(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("shh_uninstallFilter",p);
if (result.isBool())
return result.asBool();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value shh_getFilterChanges(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("shh_getFilterChanges",p);
if (result.isArray())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value shh_getMessages(const std::string& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("shh_getMessages",p);
if (result.isArray())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
};
#endif //JSONRPC_CPP_STUB_WEBTHREESTUBCLIENT_H_
Loading…
Cancel
Save