Browse Source

Merge remote-tracking branch 'ethereum/develop' into HEAD

Conflicts:
	libsolidity/Compiler.cpp
	test/solidityCompiler.cpp
cl-refactor
Christian 10 years ago
parent
commit
b7352c470b
  1. 91
      alethzero/MainWin.cpp
  2. 2
      alethzero/MainWin.h
  3. 2
      cmake/EthDependenciesDeprecated.cmake
  4. 31
      docker/Dockerfile
  5. 20
      libdevcore/FixedHash.h
  6. 3
      libdevcrypto/Common.h
  7. 1
      libdevcrypto/SHA3.cpp
  8. 5
      libdevcrypto/SHA3.h
  9. 2
      libethcore/BlockInfo.cpp
  10. 18
      libethereum/BlockChain.cpp
  11. 12
      libethereum/BlockChain.h
  12. 22
      libethereum/BlockDetails.h
  13. 42
      libethereum/Client.cpp
  14. 42
      libethereum/Executive.cpp
  15. 2
      libethereum/ExtVM.h
  16. 57
      libethereum/MessageFilter.cpp
  17. 34
      libethereum/MessageFilter.h
  18. 11
      libethereum/State.cpp
  19. 32
      libethereum/State.h
  20. 30
      libethereum/Transaction.cpp
  21. 58
      libethereum/Transaction.h
  22. 70
      libethereum/TransactionReceipt.h
  23. 20
      libevm/ExtVMFace.h
  24. 3
      libevm/VM.h
  25. 40
      libp2p/Host.cpp
  26. 4
      libp2p/Host.h
  27. 8
      libsolidity/Parser.cpp
  28. 83
      libweb3jsonrpc/WebThreeStubServer.cpp
  29. 4
      libweb3jsonrpc/WebThreeStubServer.h
  30. 7
      libweb3jsonrpc/abstractwebthreestubserver.h
  31. 1
      libweb3jsonrpc/spec.json
  32. 32
      neth/main.cpp
  33. 14
      test/crypto.cpp
  34. 96
      test/jsonrpc.cpp
  35. 10
      test/solidityParser.cpp
  36. 7
      test/state.cpp
  37. 38
      test/vm.cpp

91
alethzero/MainWin.cpp

@ -871,18 +871,18 @@ void Main::refreshPending()
ui->transactionQueue->clear(); ui->transactionQueue->clear();
for (Transaction const& t: ethereum()->pending()) for (Transaction const& t: ethereum()->pending())
{ {
QString s = t.receiveAddress ? QString s = t.receiveAddress() ?
QString("%2 %5> %3: %1 [%4]") QString("%2 %5> %3: %1 [%4]")
.arg(formatBalance(t.value).c_str()) .arg(formatBalance(t.value()).c_str())
.arg(render(t.safeSender())) .arg(render(t.safeSender()))
.arg(render(t.receiveAddress)) .arg(render(t.receiveAddress()))
.arg((unsigned)t.nonce) .arg((unsigned)t.nonce())
.arg(ethereum()->codeAt(t.receiveAddress).size() ? '*' : '-') : .arg(ethereum()->codeAt(t.receiveAddress()).size() ? '*' : '-') :
QString("%2 +> %3: %1 [%4]") QString("%2 +> %3: %1 [%4]")
.arg(formatBalance(t.value).c_str()) .arg(formatBalance(t.value()).c_str())
.arg(render(t.safeSender())) .arg(render(t.safeSender()))
.arg(render(right160(sha3(rlpList(t.safeSender(), t.nonce))))) .arg(render(right160(sha3(rlpList(t.safeSender(), t.nonce())))))
.arg((unsigned)t.nonce); .arg((unsigned)t.nonce());
ui->transactionQueue->addItem(s); ui->transactionQueue->addItem(s);
} }
} }
@ -949,7 +949,7 @@ static bool blockMatch(string const& _f, dev::eth::BlockDetails const& _b, h256
static bool transactionMatch(string const& _f, Transaction const& _t) static bool transactionMatch(string const& _f, Transaction const& _t)
{ {
string info = toHex(_t.receiveAddress.ref()) + " " + toHex(_t.sha3(true).ref()) + " " + toHex(_t.sha3(false).ref()) + " " + toHex(_t.sender().ref()); string info = toHex(_t.receiveAddress().ref()) + " " + toHex(_t.sha3(true).ref()) + " " + toHex(_t.sha3(false).ref()) + " " + toHex(_t.sender().ref());
if (info.find(_f) != string::npos) if (info.find(_f) != string::npos)
return true; return true;
return false; return false;
@ -989,18 +989,18 @@ void Main::refreshBlockChain()
Transaction t(i.data()); Transaction t(i.data());
if (bm || transactionMatch(filter, t)) if (bm || transactionMatch(filter, t))
{ {
QString s = t.receiveAddress ? QString s = t.receiveAddress() ?
QString(" %2 %5> %3: %1 [%4]") QString(" %2 %5> %3: %1 [%4]")
.arg(formatBalance(t.value).c_str()) .arg(formatBalance(t.value()).c_str())
.arg(render(t.safeSender())) .arg(render(t.safeSender()))
.arg(render(t.receiveAddress)) .arg(render(t.receiveAddress()))
.arg((unsigned)t.nonce) .arg((unsigned)t.nonce())
.arg(ethereum()->codeAt(t.receiveAddress).size() ? '*' : '-') : .arg(ethereum()->codeAt(t.receiveAddress()).size() ? '*' : '-') :
QString(" %2 +> %3: %1 [%4]") QString(" %2 +> %3: %1 [%4]")
.arg(formatBalance(t.value).c_str()) .arg(formatBalance(t.value()).c_str())
.arg(render(t.safeSender())) .arg(render(t.safeSender()))
.arg(render(right160(sha3(rlpList(t.safeSender(), t.nonce))))) .arg(render(right160(sha3(rlpList(t.safeSender(), t.nonce())))))
.arg((unsigned)t.nonce); .arg((unsigned)t.nonce());
QListWidgetItem* txItem = new QListWidgetItem(s, ui->blocks); QListWidgetItem* txItem = new QListWidgetItem(s, ui->blocks);
auto hba = QByteArray((char const*)h.data(), h.size); auto hba = QByteArray((char const*)h.data(), h.size);
txItem->setData(Qt::UserRole, hba); txItem->setData(Qt::UserRole, hba);
@ -1147,26 +1147,26 @@ void Main::on_transactionQueue_currentItemChanged()
{ {
Transaction tx(ethereum()->pending()[i]); Transaction tx(ethereum()->pending()[i]);
auto ss = tx.safeSender(); auto ss = tx.safeSender();
h256 th = sha3(rlpList(ss, tx.nonce)); h256 th = sha3(rlpList(ss, tx.nonce()));
s << "<h3>" << th << "</h3>"; s << "<h3>" << th << "</h3>";
s << "From: <b>" << pretty(ss).toStdString() << "</b> " << ss; s << "From: <b>" << pretty(ss).toStdString() << "</b> " << ss;
if (tx.isCreation()) if (tx.isCreation())
s << "<br/>Creates: <b>" << pretty(right160(th)).toStdString() << "</b> " << right160(th); s << "<br/>Creates: <b>" << pretty(right160(th)).toStdString() << "</b> " << right160(th);
else else
s << "<br/>To: <b>" << pretty(tx.receiveAddress).toStdString() << "</b> " << tx.receiveAddress; s << "<br/>To: <b>" << pretty(tx.receiveAddress()).toStdString() << "</b> " << tx.receiveAddress();
s << "<br/>Value: <b>" << formatBalance(tx.value) << "</b>"; s << "<br/>Value: <b>" << formatBalance(tx.value()) << "</b>";
s << "&nbsp;&emsp;&nbsp;#<b>" << tx.nonce << "</b>"; s << "&nbsp;&emsp;&nbsp;#<b>" << tx.nonce() << "</b>";
s << "<br/>Gas price: <b>" << formatBalance(tx.gasPrice) << "</b>"; s << "<br/>Gas price: <b>" << formatBalance(tx.gasPrice()) << "</b>";
s << "<br/>Gas: <b>" << tx.gas << "</b>"; s << "<br/>Gas: <b>" << tx.gas() << "</b>";
if (tx.isCreation()) if (tx.isCreation())
{ {
if (tx.data.size()) if (tx.data().size())
s << "<h4>Code</h4>" << disassemble(tx.data); s << "<h4>Code</h4>" << disassemble(tx.data());
} }
else else
{ {
if (tx.data.size()) if (tx.data().size())
s << dev::memDump(tx.data, 16, true); s << dev::memDump(tx.data(), 16, true);
} }
s << "<hr/>"; s << "<hr/>";
@ -1254,31 +1254,31 @@ void Main::on_blocks_currentItemChanged()
unsigned txi = item->data(Qt::UserRole + 1).toInt(); unsigned txi = item->data(Qt::UserRole + 1).toInt();
Transaction tx(block[1][txi].data()); Transaction tx(block[1][txi].data());
auto ss = tx.safeSender(); auto ss = tx.safeSender();
h256 th = sha3(rlpList(ss, tx.nonce)); h256 th = sha3(rlpList(ss, tx.nonce()));
s << "<h3>" << th << "</h3>"; s << "<h3>" << th << "</h3>";
s << "<h4>" << h << "[<b>" << txi << "</b>]</h4>"; s << "<h4>" << h << "[<b>" << txi << "</b>]</h4>";
s << "<br/>From: <b>" << pretty(ss).toHtmlEscaped().toStdString() << "</b> " << ss; s << "<br/>From: <b>" << pretty(ss).toHtmlEscaped().toStdString() << "</b> " << ss;
if (tx.isCreation()) if (tx.isCreation())
s << "<br/>Creates: <b>" << pretty(right160(th)).toHtmlEscaped().toStdString() << "</b> " << right160(th); s << "<br/>Creates: <b>" << pretty(right160(th)).toHtmlEscaped().toStdString() << "</b> " << right160(th);
else else
s << "<br/>To: <b>" << pretty(tx.receiveAddress).toHtmlEscaped().toStdString() << "</b> " << tx.receiveAddress; s << "<br/>To: <b>" << pretty(tx.receiveAddress()).toHtmlEscaped().toStdString() << "</b> " << tx.receiveAddress();
s << "<br/>Value: <b>" << formatBalance(tx.value) << "</b>"; s << "<br/>Value: <b>" << formatBalance(tx.value()) << "</b>";
s << "&nbsp;&emsp;&nbsp;#<b>" << tx.nonce << "</b>"; s << "&nbsp;&emsp;&nbsp;#<b>" << tx.nonce() << "</b>";
s << "<br/>Gas price: <b>" << formatBalance(tx.gasPrice) << "</b>"; s << "<br/>Gas price: <b>" << formatBalance(tx.gasPrice()) << "</b>";
s << "<br/>Gas: <b>" << tx.gas << "</b>"; s << "<br/>Gas: <b>" << tx.gas() << "</b>";
s << "<br/>V: <b>" << hex << nouppercase << (int)tx.vrs.v << "</b>"; s << "<br/>V: <b>" << hex << nouppercase << (int)tx.signature().v << "</b>";
s << "<br/>R: <b>" << hex << nouppercase << tx.vrs.r << "</b>"; s << "<br/>R: <b>" << hex << nouppercase << tx.signature().r << "</b>";
s << "<br/>S: <b>" << hex << nouppercase << tx.vrs.s << "</b>"; s << "<br/>S: <b>" << hex << nouppercase << tx.signature().s << "</b>";
s << "<br/>Msg: <b>" << tx.sha3(false) << "</b>"; s << "<br/>Msg: <b>" << tx.sha3(false) << "</b>";
if (tx.isCreation()) if (tx.isCreation())
{ {
if (tx.data.size()) if (tx.data().size())
s << "<h4>Code</h4>" << disassemble(tx.data); s << "<h4>Code</h4>" << disassemble(tx.data());
} }
else else
{ {
if (tx.data.size()) if (tx.data().size())
s << dev::memDump(tx.data, 16, true); s << dev::memDump(tx.data(), 16, true);
} }
s << renderDiff(ethereum()->diff(txi, h)); s << renderDiff(ethereum()->diff(txi, h));
ui->debugCurrent->setEnabled(true); ui->debugCurrent->setEnabled(true);
@ -1808,14 +1808,9 @@ void Main::on_debug_clicked()
Secret s = i.secret(); Secret s = i.secret();
m_executiveState = ethereum()->postState(); m_executiveState = ethereum()->postState();
m_currentExecution = unique_ptr<Executive>(new Executive(m_executiveState)); m_currentExecution = unique_ptr<Executive>(new Executive(m_executiveState));
Transaction t; Transaction t = isCreation() ?
t.nonce = m_executiveState.transactionsFrom(dev::toAddress(s)); Transaction(value(), gasPrice(), ui->gas->value(), m_data, m_executiveState.transactionsFrom(dev::toAddress(s)), s) :
t.value = value(); Transaction(value(), gasPrice(), ui->gas->value(), fromString(ui->destination->currentText()), m_data, m_executiveState.transactionsFrom(dev::toAddress(s)), s);
t.gasPrice = gasPrice();
t.gas = ui->gas->value();
t.data = m_data;
t.receiveAddress = isCreation() ? Address() : fromString(ui->destination->currentText());
t.sign(s);
auto r = t.rlp(); auto r = t.rlp();
populateDebugger(&r); populateDebugger(&r);
m_currentExecution.reset(); m_currentExecution.reset();

2
alethzero/MainWin.h

@ -255,7 +255,7 @@ private:
QString m_logHistory; QString m_logHistory;
bool m_logChanged = true; bool m_logChanged = true;
std::unique_ptr<WebThreeStubServer> m_server;
QWebThreeConnector m_qwebConnector; QWebThreeConnector m_qwebConnector;
std::unique_ptr<WebThreeStubServer> m_server;
QWebThree* m_qweb = nullptr; QWebThree* m_qweb = nullptr;
}; };

2
cmake/EthDependenciesDeprecated.cmake

@ -128,6 +128,7 @@ else()
find_path( JSONRPC_ID jsonrpc/rpc.h find_path( JSONRPC_ID jsonrpc/rpc.h
/usr/include /usr/include
/usr/local/include /usr/local/include
../libjson-rpc-cpp/src
) )
if ( JSONRPC_ID ) if ( JSONRPC_ID )
message(STATUS "Found jsonrpc headers") message(STATUS "Found jsonrpc headers")
@ -137,6 +138,7 @@ else()
/usr/local/lib /usr/local/lib
/opt/local/lib /opt/local/lib
/usr/lib/*/ /usr/lib/*/
../libjson-rpc-cpp/build/out
) )
if ( JSONRPC_LS ) if ( JSONRPC_LS )
message(STATUS "Found jsonrpc library: ${JSONRPC_LS}") message(STATUS "Found jsonrpc library: ${JSONRPC_LS}")

31
docker/Dockerfile

@ -4,17 +4,30 @@ ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update RUN apt-get update
RUN apt-get upgrade -y RUN apt-get upgrade -y
RUN apt-get install -qy wget # Ethereum dependencies
RUN apt-get install -qy build-essential g++-4.8 automake libtool unzip git cmake RUN apt-get install -qy build-essential g++-4.8 git cmake libboost-all-dev libcurl4-openssl-dev wget
RUN apt-get install -qy libncurses5-dev libgmp-dev libgmp3-dev libboost-all-dev libleveldb-dev yasm libminiupnpc-dev RUN apt-get install -qy automake unzip libgmp-dev libtool libleveldb-dev yasm libminiupnpc-dev libreadline-dev scons
RUN apt-get install -qy qtbase5-dev qt5-default qtdeclarative5-dev libqt5webkit5-dev
RUN mkdir /cryptopp562 # NCurses based GUI (not optional though for a succesful compilation, see https://github.com/ethereum/cpp-ethereum/issues/452 )
RUN cd /cryptopp562 && wget http://www.cryptopp.com/cryptopp562.zip && unzip cryptopp562.zip RUN apt-get install -qy libncurses5-dev
RUN cd /cryptopp562 && make -j $(cat /proc/cpuinfo | grep processor | wc -l) && make install
# Qt-based GUI
# RUN apt-get install -qy qtbase5-dev qt5-default qtdeclarative5-dev libqt5webkit5-dev
# Cryptopp
RUN git clone --depth=1 https://github.com/mmoss/cryptopp.git
RUN cd cryptopp && scons --shared --prefix=/usr
# JSONRPC (version 0.2.1, see https://github.com/ethereum/cpp-ethereum/issues/453 )
RUN apt-get install -qy libjsoncpp-dev libargtable2-dev
RUN git clone --depth=1 --branch=0.2.1 https://github.com/cinemast/libjson-rpc-cpp.git
RUN mkdir -p libjson-rpc-cpp/build
RUN cd libjson-rpc-cpp/build && cmake .. && make && make install
# Build Ethereum (HEADLESS)
RUN git clone --depth=1 https://github.com/ethereum/cpp-ethereum RUN git clone --depth=1 https://github.com/ethereum/cpp-ethereum
RUN mkdir cpp-ethereum/build RUN mkdir -p cpp-ethereum/build
RUN cd cpp-ethereum/build && cmake .. -DCMAKE_BUILD_TYPE=Release && make -j $(cat /proc/cpuinfo | grep processor | wc -l) && make install RUN cd cpp-ethereum/build && cmake .. -DCMAKE_BUILD_TYPE=Release -DHEADLESS=1 && make -j $(cat /proc/cpuinfo | grep processor | wc -l) && make install
RUN ldconfig
ENTRYPOINT ["/usr/local/bin/eth"] ENTRYPOINT ["/usr/local/bin/eth"]

20
libdevcore/FixedHash.h

@ -158,21 +158,30 @@ public:
return ret; return ret;
} }
template <unsigned P, unsigned M> inline FixedHash& shiftBloom(FixedHash<M> const& _h) { return (*this |= _h.template nbloom<P, N>()); } template <unsigned P, unsigned M> inline FixedHash& shiftBloom(FixedHash<M> const& _h)
{
return (*this |= _h.template nbloom<P, N>());
}
template <unsigned P, unsigned M> inline bool containsBloom(FixedHash<M> const& _h)
{
return contains(_h.template nbloom<P, N>());
}
template <unsigned P, unsigned M> inline FixedHash<M> nbloom() const template <unsigned P, unsigned M> inline FixedHash<M> nbloom() const
{ {
static const unsigned c_bloomBytes = (M + 7) / 8; static const unsigned c_bloomBits = M * 8;
unsigned mask = (1 << c_bloomBytes) - 1; unsigned mask = c_bloomBits - 1;
unsigned bloomBytes = (dev::toLog2(c_bloomBits) + 7) / 8;
FixedHash<M> ret; FixedHash<M> ret;
byte const* p = data(); byte const* p = data();
for (unsigned i = 0; i < P; ++i) for (unsigned i = 0; i < P; ++i)
{ {
unsigned index = 0; unsigned index = 0;
for (unsigned j = 0; j < c_bloomBytes; ++j, ++p) for (unsigned j = 0; j < bloomBytes; ++j, ++p)
index = (index << 8) | *p; index = (index << 8) | *p;
index &= mask; index &= mask;
ret[N - 1 - index / 8] |= (1 << (index % 8)); ret[M - 1 - index / 8] |= (1 << (index % 8));
} }
return ret; return ret;
} }
@ -231,6 +240,7 @@ using h520 = FixedHash<65>;
using h512 = FixedHash<64>; using h512 = FixedHash<64>;
using h256 = FixedHash<32>; using h256 = FixedHash<32>;
using h160 = FixedHash<20>; using h160 = FixedHash<20>;
using h512s = std::vector<h512>;
using h256s = std::vector<h256>; using h256s = std::vector<h256>;
using h160s = std::vector<h160>; using h160s = std::vector<h160>;
using h256Set = std::set<h256>; using h256Set = std::set<h256>;

3
libdevcrypto/Common.h

@ -50,6 +50,9 @@ using Address = h160;
/// A vector of Ethereum addresses. /// A vector of Ethereum addresses.
using Addresses = h160s; using Addresses = h160s;
/// A vector of Ethereum addresses.
using AddressSet = std::set<h160>;
/// A vector of secrets. /// A vector of secrets.
using Secrets = h256s; using Secrets = h256s;

1
libdevcrypto/SHA3.cpp

@ -30,6 +30,7 @@ namespace dev
{ {
h256 EmptySHA3 = sha3(bytesConstRef()); h256 EmptySHA3 = sha3(bytesConstRef());
h256 EmptyListSHA3 = sha3(RLPEmptyList);
std::string sha3(std::string const& _input, bool _hex) std::string sha3(std::string const& _input, bool _hex)
{ {

5
libdevcrypto/SHA3.h

@ -56,8 +56,13 @@ inline h256 sha3(bytes const& _input) { return sha3(bytesConstRef((bytes*)&_inpu
/// Calculate SHA3-256 hash of the given input (presented as a binary-filled string), returning as a 256-bit hash. /// Calculate SHA3-256 hash of the given input (presented as a binary-filled string), returning as a 256-bit hash.
inline h256 sha3(std::string const& _input) { return sha3(bytesConstRef(_input)); } inline h256 sha3(std::string const& _input) { return sha3(bytesConstRef(_input)); }
/// Calculate SHA3-256 hash of the given input (presented as a FixedHash), returns a 256-bit hash.
template<unsigned N> inline h256 sha3(FixedHash<N> const& _input) { return sha3(_input.ref()); }
extern h256 EmptySHA3; extern h256 EmptySHA3;
extern h256 EmptyListSHA3;
// Other crypto convenience routines // Other crypto convenience routines
bytes aesDecrypt(bytesConstRef _cipher, std::string const& _password, unsigned _rounds = 2000, bytesConstRef _salt = bytesConstRef()); bytes aesDecrypt(bytesConstRef _cipher, std::string const& _password, unsigned _rounds = 2000, bytesConstRef _salt = bytesConstRef());

2
libethcore/BlockInfo.cpp

@ -56,8 +56,6 @@ h256 BlockInfo::headerHashWithoutNonce() const
return sha3(s.out()); return sha3(s.out());
} }
auto static const c_sha3EmptyList = sha3(RLPEmptyList);
void BlockInfo::streamRLP(RLPStream& _s, bool _nonce) const void BlockInfo::streamRLP(RLPStream& _s, bool _nonce) const
{ {
_s.appendList(_nonce ? 15 : 14) _s.appendList(_nonce ? 15 : 14)

18
libethereum/BlockChain.cpp

@ -103,7 +103,7 @@ bytes BlockChain::createGenesisBlock()
block.appendList(15) block.appendList(15)
// TODO: maybe make logbloom correct? // TODO: maybe make logbloom correct?
<< h256() << EmptySHA3 << h160() << stateRoot << EmptyTrie << EmptyTrie << LogBloom() << c_genesisDifficulty << 0 << 0 << 1000000 << 0 << (unsigned)0 << string() << sha3(bytes(1, 42)); << h256() << EmptyListSHA3 << h160() << stateRoot << EmptyTrie << EmptyTrie << LogBloom() << c_genesisDifficulty << 0 << 0 << 1000000 << 0 << (unsigned)0 << string() << sha3(bytes(1, 42));
block.appendRaw(RLPEmptyList); block.appendRaw(RLPEmptyList);
block.appendRaw(RLPEmptyList); block.appendRaw(RLPEmptyList);
return block.out(); return block.out();
@ -309,10 +309,14 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db)
auto b = s.oldBloom(); auto b = s.oldBloom();
BlockBlooms bb; BlockBlooms bb;
BlockTraces bt; BlockTraces bt;
BlockLogBlooms blb;
BlockReceipts br;
for (unsigned i = 0; i < s.pending().size(); ++i) for (unsigned i = 0; i < s.pending().size(); ++i)
{ {
bt.traces.push_back(s.changesFromPending(i));
bb.blooms.push_back(s.changesFromPending(i).bloom()); bb.blooms.push_back(s.changesFromPending(i).bloom());
bt.traces.push_back(s.changesFromPending(i));
blb.blooms.push_back(s.receipt(i).bloom());
br.receipts.push_back(s.receipt(i));
} }
s.cleanup(true); s.cleanup(true);
td = pd.totalDifficulty + tdIncrease; td = pd.totalDifficulty + tdIncrease;
@ -334,11 +338,21 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db)
WriteGuard l(x_traces); WriteGuard l(x_traces);
m_traces[newHash] = bt; m_traces[newHash] = bt;
} }
{
WriteGuard l(x_logBlooms);
m_logBlooms[newHash] = blb;
}
{
WriteGuard l(x_receipts);
m_receipts[newHash] = br;
}
m_extrasDB->Put(m_writeOptions, toSlice(newHash), (ldb::Slice)dev::ref(m_details[newHash].rlp())); m_extrasDB->Put(m_writeOptions, toSlice(newHash), (ldb::Slice)dev::ref(m_details[newHash].rlp()));
m_extrasDB->Put(m_writeOptions, toSlice(bi.parentHash), (ldb::Slice)dev::ref(m_details[bi.parentHash].rlp())); m_extrasDB->Put(m_writeOptions, toSlice(bi.parentHash), (ldb::Slice)dev::ref(m_details[bi.parentHash].rlp()));
m_extrasDB->Put(m_writeOptions, toSlice(newHash, 1), (ldb::Slice)dev::ref(m_blooms[newHash].rlp())); m_extrasDB->Put(m_writeOptions, toSlice(newHash, 1), (ldb::Slice)dev::ref(m_blooms[newHash].rlp()));
m_extrasDB->Put(m_writeOptions, toSlice(newHash, 2), (ldb::Slice)dev::ref(m_traces[newHash].rlp())); m_extrasDB->Put(m_writeOptions, toSlice(newHash, 2), (ldb::Slice)dev::ref(m_traces[newHash].rlp()));
m_extrasDB->Put(m_writeOptions, toSlice(newHash, 3), (ldb::Slice)dev::ref(m_logBlooms[newHash].rlp()));
m_extrasDB->Put(m_writeOptions, toSlice(newHash, 4), (ldb::Slice)dev::ref(m_receipts[newHash].rlp()));
m_db->Put(m_writeOptions, toSlice(newHash), (ldb::Slice)ref(_block)); m_db->Put(m_writeOptions, toSlice(newHash), (ldb::Slice)ref(_block));
#if ETH_PARANOIA #if ETH_PARANOIA

12
libethereum/BlockChain.h

@ -105,6 +105,14 @@ public:
BlockTraces traces(h256 _hash) const { return queryExtras<BlockTraces, 2>(_hash, m_traces, x_traces, NullBlockTraces); } BlockTraces traces(h256 _hash) const { return queryExtras<BlockTraces, 2>(_hash, m_traces, x_traces, NullBlockTraces); }
BlockTraces traces() const { return traces(currentHash()); } BlockTraces traces() const { return traces(currentHash()); }
/// Get the transactions' log blooms of a block (or the most recent mined if none given). Thread-safe.
BlockLogBlooms logBlooms(h256 _hash) const { return queryExtras<BlockLogBlooms, 3>(_hash, m_logBlooms, x_logBlooms, NullBlockLogBlooms); }
BlockLogBlooms logBlooms() const { return logBlooms(currentHash()); }
/// Get the transactions' receipts of a block (or the most recent mined if none given). Thread-safe.
BlockReceipts receipts(h256 _hash) const { return queryExtras<BlockReceipts, 4>(_hash, m_receipts, x_receipts, NullBlockReceipts); }
BlockReceipts receipts() const { return receipts(currentHash()); }
/// Get a block (RLP format) for the given hash (or the most recent mined if none given). Thread-safe. /// Get a block (RLP format) for the given hash (or the most recent mined if none given). Thread-safe.
bytes block(h256 _hash) const; bytes block(h256 _hash) const;
bytes block() const { return block(currentHash()); } bytes block() const { return block(currentHash()); }
@ -185,6 +193,10 @@ private:
mutable BlockBloomsHash m_blooms; mutable BlockBloomsHash m_blooms;
mutable boost::shared_mutex x_traces; mutable boost::shared_mutex x_traces;
mutable BlockTracesHash m_traces; mutable BlockTracesHash m_traces;
mutable boost::shared_mutex x_logBlooms;
mutable BlockLogBloomsHash m_logBlooms;
mutable boost::shared_mutex x_receipts;
mutable BlockReceiptsHash m_receipts;
mutable boost::shared_mutex x_cache; mutable boost::shared_mutex x_cache;
mutable std::map<h256, bytes> m_cache; mutable std::map<h256, bytes> m_cache;

22
libethereum/BlockDetails.h

@ -29,6 +29,7 @@
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libdevcore/RLP.h> #include <libdevcore/RLP.h>
#include "Manifest.h" #include "Manifest.h"
#include "TransactionReceipt.h"
namespace ldb = leveldb; namespace ldb = leveldb;
namespace dev namespace dev
@ -71,14 +72,35 @@ struct BlockTraces
Manifests traces; Manifests traces;
}; };
struct BlockLogBlooms
{
BlockLogBlooms() {}
BlockLogBlooms(RLP const& _r) { blooms = _r.toVector<h512>(); }
bytes rlp() const { RLPStream s; s << blooms; return s.out(); }
h512s blooms;
};
struct BlockReceipts
{
BlockReceipts() {}
BlockReceipts(RLP const& _r) { for (auto const& i: _r) receipts.emplace_back(i.data()); }
bytes rlp() const { RLPStream s(receipts.size()); for (TransactionReceipt const& i: receipts) i.streamRLP(s); return s.out(); }
TransactionReceipts receipts;
};
typedef std::map<h256, BlockDetails> BlockDetailsHash; typedef std::map<h256, BlockDetails> BlockDetailsHash;
typedef std::map<h256, BlockBlooms> BlockBloomsHash; typedef std::map<h256, BlockBlooms> BlockBloomsHash;
typedef std::map<h256, BlockTraces> BlockTracesHash; typedef std::map<h256, BlockTraces> BlockTracesHash;
typedef std::map<h256, BlockLogBlooms> BlockLogBloomsHash;
typedef std::map<h256, BlockReceipts> BlockReceiptsHash;
static const BlockDetails NullBlockDetails; static const BlockDetails NullBlockDetails;
static const BlockBlooms NullBlockBlooms; static const BlockBlooms NullBlockBlooms;
static const BlockTraces NullBlockTraces; static const BlockTraces NullBlockTraces;
static const BlockLogBlooms NullBlockLogBlooms;
static const BlockReceipts NullBlockReceipts;
} }
} }

42
libethereum/Client.cpp

@ -316,19 +316,13 @@ void Client::transact(Secret _secret, u256 _value, Address _dest, bytes const& _
{ {
startWorking(); startWorking();
Transaction t; u256 n;
// cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret));
{ {
ReadGuard l(x_stateDB); ReadGuard l(x_stateDB);
t.nonce = m_postMine.transactionsFrom(toAddress(_secret)); n = m_postMine.transactionsFrom(toAddress(_secret));
} }
t.value = _value; Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret);
t.gasPrice = _gasPrice; // cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret));
t.gas = _gas;
t.type = Transaction::MessageCall;
t.receiveAddress = _dest;
t.data = _data;
t.sign(_secret);
cnote << "New transaction " << t; cnote << "New transaction " << t;
m_tq.attemptImport(t.rlp()); m_tq.attemptImport(t.rlp());
} }
@ -338,22 +332,16 @@ bytes Client::call(Secret _secret, u256 _value, Address _dest, bytes const& _dat
bytes out; bytes out;
try try
{ {
u256 n;
State temp; State temp;
Transaction t;
// cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret)); // cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret));
{ {
ReadGuard l(x_stateDB); ReadGuard l(x_stateDB);
temp = m_postMine; temp = m_postMine;
t.nonce = temp.transactionsFrom(toAddress(_secret)); n = temp.transactionsFrom(toAddress(_secret));
} }
t.value = _value; Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret);
t.gasPrice = _gasPrice; u256 gasUsed = temp.execute(t.data(), &out, false);
t.gas = _gas;
t.type = Transaction::ContractCreation;
t.receiveAddress = _dest;
t.data = _data;
t.sign(_secret);
u256 gasUsed = temp.execute(t.data, &out, false);
(void)gasUsed; // TODO: do something with gasused which it returns. (void)gasUsed; // TODO: do something with gasused which it returns.
} }
catch (...) catch (...)
@ -367,21 +355,15 @@ Address Client::transact(Secret _secret, u256 _endowment, bytes const& _init, u2
{ {
startWorking(); startWorking();
Transaction t; u256 n;
{ {
ReadGuard l(x_stateDB); ReadGuard l(x_stateDB);
t.nonce = m_postMine.transactionsFrom(toAddress(_secret)); n = m_postMine.transactionsFrom(toAddress(_secret));
} }
t.value = _endowment; Transaction t(_endowment, _gasPrice, _gas, _init, n, _secret);
t.gasPrice = _gasPrice;
t.gas = _gas;
t.type = Transaction::ContractCreation;
t.receiveAddress = Address();
t.data = _init;
t.sign(_secret);
cnote << "New transaction " << t; cnote << "New transaction " << t;
m_tq.attemptImport(t.rlp()); m_tq.attemptImport(t.rlp());
return right160(sha3(rlpList(t.sender(), t.nonce))); return right160(sha3(rlpList(t.sender(), t.nonce())));
} }
void Client::inject(bytesConstRef _rlp) void Client::inject(bytesConstRef _rlp)

42
libethereum/Executive.cpp

@ -40,7 +40,7 @@ Executive::~Executive()
u256 Executive::gasUsed() const u256 Executive::gasUsed() const
{ {
return m_t.gas - m_endGas; return m_t.gas() - m_endGas;
} }
bool Executive::setup(bytesConstRef _rlp) bool Executive::setup(bytesConstRef _rlp)
@ -52,29 +52,29 @@ bool Executive::setup(bytesConstRef _rlp)
// Avoid invalid transactions. // Avoid invalid transactions.
auto nonceReq = m_s.transactionsFrom(m_sender); auto nonceReq = m_s.transactionsFrom(m_sender);
if (m_t.nonce != nonceReq) if (m_t.nonce() != nonceReq)
{ {
clog(StateDetail) << "Invalid Nonce: Require" << nonceReq << " Got" << m_t.nonce; clog(StateDetail) << "Invalid Nonce: Require" << nonceReq << " Got" << m_t.nonce();
BOOST_THROW_EXCEPTION(InvalidNonce(nonceReq, m_t.nonce)); BOOST_THROW_EXCEPTION(InvalidNonce(nonceReq, m_t.nonce()));
} }
// Don't like transactions whose gas price is too low. NOTE: this won't stay here forever - it's just until we get a proper gas price discovery protocol going. // Don't like transactions whose gas price is too low. NOTE: this won't stay here forever - it's just until we get a proper gas price discovery protocol going.
if (m_t.gasPrice < m_s.m_currentBlock.minGasPrice) if (m_t.gasPrice() < m_s.m_currentBlock.minGasPrice)
{ {
clog(StateDetail) << "Offered gas-price is too low: Require >" << m_s.m_currentBlock.minGasPrice << " Got" << m_t.gasPrice; clog(StateDetail) << "Offered gas-price is too low: Require >" << m_s.m_currentBlock.minGasPrice << " Got" << m_t.gasPrice();
BOOST_THROW_EXCEPTION(GasPriceTooLow()); BOOST_THROW_EXCEPTION(GasPriceTooLow());
} }
// Check gas cost is enough. // Check gas cost is enough.
u256 gasCost = m_t.data.size() * c_txDataGas + c_txGas; u256 gasCost = m_t.data().size() * c_txDataGas + c_txGas;
if (m_t.gas < gasCost) if (m_t.gas() < gasCost)
{ {
clog(StateDetail) << "Not enough gas to pay for the transaction: Require >" << gasCost << " Got" << m_t.gas; clog(StateDetail) << "Not enough gas to pay for the transaction: Require >" << gasCost << " Got" << m_t.gas();
BOOST_THROW_EXCEPTION(OutOfGas()); BOOST_THROW_EXCEPTION(OutOfGas());
} }
u256 cost = m_t.value + m_t.gas * m_t.gasPrice; u256 cost = m_t.value() + m_t.gas() * m_t.gasPrice();
// Avoid unaffordable transactions. // Avoid unaffordable transactions.
if (m_s.balance(m_sender) < cost) if (m_s.balance(m_sender) < cost)
@ -84,9 +84,9 @@ bool Executive::setup(bytesConstRef _rlp)
} }
u256 startGasUsed = m_s.gasUsed(); u256 startGasUsed = m_s.gasUsed();
if (startGasUsed + m_t.gas > m_s.m_currentBlock.gasLimit) if (startGasUsed + m_t.gas() > m_s.m_currentBlock.gasLimit)
{ {
clog(StateDetail) << "Too much gas used in this block: Require <" << (m_s.m_currentBlock.gasLimit - startGasUsed) << " Got" << m_t.gas; clog(StateDetail) << "Too much gas used in this block: Require <" << (m_s.m_currentBlock.gasLimit - startGasUsed) << " Got" << m_t.gas();
BOOST_THROW_EXCEPTION(BlockGasLimitReached()); BOOST_THROW_EXCEPTION(BlockGasLimitReached());
} }
@ -94,21 +94,21 @@ bool Executive::setup(bytesConstRef _rlp)
m_s.noteSending(m_sender); m_s.noteSending(m_sender);
// Pay... // Pay...
clog(StateDetail) << "Paying" << formatBalance(cost) << "from sender (includes" << m_t.gas << "gas at" << formatBalance(m_t.gasPrice) << ")"; clog(StateDetail) << "Paying" << formatBalance(cost) << "from sender (includes" << m_t.gas() << "gas at" << formatBalance(m_t.gasPrice()) << ")";
m_s.subBalance(m_sender, cost); m_s.subBalance(m_sender, cost);
if (m_ms) if (m_ms)
{ {
m_ms->from = m_sender; m_ms->from = m_sender;
m_ms->to = m_t.receiveAddress; m_ms->to = m_t.receiveAddress();
m_ms->value = m_t.value; m_ms->value = m_t.value();
m_ms->input = m_t.data; m_ms->input = m_t.data();
} }
if (m_t.isCreation()) if (m_t.isCreation())
return create(m_sender, m_t.value, m_t.gasPrice, m_t.gas - gasCost, &m_t.data, m_sender); return create(m_sender, m_t.value(), m_t.gasPrice(), m_t.gas() - gasCost, &m_t.data(), m_sender);
else else
return call(m_t.receiveAddress, m_sender, m_t.value, m_t.gasPrice, bytesConstRef(&m_t.data), m_t.gas - gasCost, m_sender); return call(m_t.receiveAddress(), m_sender, m_t.value(), m_t.gasPrice(), bytesConstRef(&m_t.data()), m_t.gas() - gasCost, m_sender);
} }
bool Executive::call(Address _receiveAddress, Address _senderAddress, u256 _value, u256 _gasPrice, bytesConstRef _data, u256 _gas, Address _originAddress) bool Executive::call(Address _receiveAddress, Address _senderAddress, u256 _value, u256 _gasPrice, bytesConstRef _data, u256 _gas, Address _originAddress)
@ -177,7 +177,7 @@ bool Executive::go(OnOpFunc const& _onOp)
{ {
m_out = m_vm->go(*m_ext, _onOp); m_out = m_vm->go(*m_ext, _onOp);
if (m_ext) if (m_ext)
m_endGas += min((m_t.gas - m_endGas) / 2, m_ext->sub.refunds); m_endGas += min((m_t.gas() - m_endGas) / 2, m_ext->sub.refunds);
m_endGas = m_vm->gas(); m_endGas = m_vm->gas();
} }
catch (StepsDone const&) catch (StepsDone const&)
@ -234,9 +234,9 @@ void Executive::finalize(OnOpFunc const&)
m_s.m_cache[m_newAddress].setCode(m_out); m_s.m_cache[m_newAddress].setCode(m_out);
// cnote << "Refunding" << formatBalance(m_endGas * m_ext->gasPrice) << "to origin (=" << m_endGas << "*" << formatBalance(m_ext->gasPrice) << ")"; // cnote << "Refunding" << formatBalance(m_endGas * m_ext->gasPrice) << "to origin (=" << m_endGas << "*" << formatBalance(m_ext->gasPrice) << ")";
m_s.addBalance(m_sender, m_endGas * m_t.gasPrice); m_s.addBalance(m_sender, m_endGas * m_t.gasPrice());
u256 feesEarned = (m_t.gas - m_endGas) * m_t.gasPrice; u256 feesEarned = (m_t.gas() - m_endGas) * m_t.gasPrice();
// cnote << "Transferring" << formatBalance(gasSpent) << "to miner."; // cnote << "Transferring" << formatBalance(gasSpent) << "to miner.";
m_s.addBalance(m_s.m_currentBlock.coinbaseAddress, feesEarned); m_s.addBalance(m_s.m_currentBlock.coinbaseAddress, feesEarned);

2
libethereum/ExtVM.h

@ -102,7 +102,7 @@ public:
private: private:
State& m_s; ///< A reference to the base state. State& m_s; ///< A reference to the base state.
std::map<Address, Account> m_origCache; ///< The cache of the address states (i.e. the externalities) as-was prior to the execution. std::map<Address, Account> m_origCache; ///< The cache of the address states (i.e. the externalities) as-was prior to the execution.
Manifest* m_ms; Manifest* m_ms;
}; };

57
libethereum/MessageFilter.cpp

@ -79,7 +79,7 @@ bool MessageFilter::matches(State const& _s, unsigned _i) const
return false; return false;
Transaction t = _s.pending()[_i]; Transaction t = _s.pending()[_i];
if (!m_to.empty() && !m_to.count(t.receiveAddress)) if (!m_to.empty() && !m_to.count(t.receiveAddress()))
return false; return false;
if (!m_from.empty() && !m_from.count(t.sender())) if (!m_from.empty() && !m_from.count(t.sender()))
return false; return false;
@ -149,3 +149,58 @@ bool MessageFilter::matches(Manifest const& _m, vector<unsigned> _p, Address _o,
return ret; return ret;
} }
void LogFilter::streamRLP(RLPStream& _s) const
{
_s.appendList(6) << m_addresses << m_topics << m_earliest << m_latest << m_max << m_skip;
}
h256 LogFilter::sha3() const
{
RLPStream s;
streamRLP(s);
return dev::sha3(s.out());
}
bool LogFilter::matches(LogBloom _bloom) const
{
if (m_addresses.size())
{
for (auto i: m_addresses)
if (_bloom.containsBloom<3>(dev::sha3(i)))
goto OK1;
return false;
}
OK1:
if (m_topics.size())
{
for (auto i: m_topics)
if (_bloom.containsBloom<3>(dev::sha3(i)))
goto OK2;
return false;
}
OK2:
return true;
}
bool LogFilter::matches(State const& _s, unsigned _i) const
{
return matches(_s.receipt(_i)).size() > 0;
}
LogEntries LogFilter::matches(TransactionReceipt const& _m) const
{
LogEntries ret;
for (LogEntry const& e: _m.log())
{
if (!m_addresses.empty() && !m_addresses.count(e.address))
continue;
for (auto const& t: m_topics)
if (!e.topics.count(t))
continue;
ret.push_back(e);
}
return ret;
}

34
libethereum/MessageFilter.h

@ -25,6 +25,7 @@
#include <libdevcore/RLP.h> #include <libdevcore/RLP.h>
#include <libethcore/CommonEth.h> #include <libethcore/CommonEth.h>
#include "PastMessage.h" #include "PastMessage.h"
#include "TransactionReceipt.h"
namespace dev namespace dev
{ {
@ -72,5 +73,38 @@ private:
unsigned m_skip; unsigned m_skip;
}; };
class LogFilter
{
public:
LogFilter(int _earliest = 0, int _latest = -1, unsigned _max = 10, unsigned _skip = 0): m_earliest(_earliest), m_latest(_latest), m_max(_max), m_skip(_skip) {}
void streamRLP(RLPStream& _s) const;
h256 sha3() const;
int earliest() const { return m_earliest; }
int latest() const { return m_latest; }
unsigned max() const { return m_max; }
unsigned skip() const { return m_skip; }
bool matches(LogBloom _bloom) const;
bool matches(State const& _s, unsigned _i) const;
LogEntries matches(TransactionReceipt const& _r) const;
LogFilter address(Address _a) { m_addresses.insert(_a); return *this; }
LogFilter from(Address _a) { return topic(u256((u160)_a) + 1); }
LogFilter topic(h256 const& _t) { m_topics.insert(_t); return *this; }
LogFilter withMax(unsigned _m) { m_max = _m; return *this; }
LogFilter withSkip(unsigned _m) { m_skip = _m; return *this; }
LogFilter withEarliest(int _e) { m_earliest = _e; return *this; }
LogFilter withLatest(int _e) { m_latest = _e; return *this; }
private:
AddressSet m_addresses;
h256Set m_topics;
int m_earliest = 0;
int m_latest = -1;
unsigned m_max;
unsigned m_skip;
};
} }
} }

11
libethereum/State.cpp

@ -520,7 +520,7 @@ bool State::cull(TransactionQueue& _tq) const
try try
{ {
Transaction t(i.second); Transaction t(i.second);
if (t.nonce <= transactionsFrom(t.sender())) if (t.nonce() <= transactionsFrom(t.sender()))
{ {
_tq.drop(i.first); _tq.drop(i.first);
ret = true; ret = true;
@ -723,9 +723,7 @@ void State::cleanup(bool _fullCommit)
m_previousBlock = m_currentBlock; m_previousBlock = m_currentBlock;
} }
else else
{
m_db.rollback(); m_db.rollback();
}
resetCurrent(); resetCurrent();
} }
@ -793,7 +791,8 @@ h256 State::oldBloom() const
LogBloom State::logBloom() const LogBloom State::logBloom() const
{ {
LogBloom ret; LogBloom ret;
ret.shiftBloom<3>(sha3(m_currentBlock.coinbaseAddress.ref())); auto sa = sha3(m_currentBlock.coinbaseAddress.ref());
ret.shiftBloom<3>(sa);
for (TransactionReceipt const& i: m_receipts) for (TransactionReceipt const& i: m_receipts)
ret |= i.bloom(); ret |= i.bloom();
return ret; return ret;
@ -1155,10 +1154,10 @@ u256 State::execute(bytesConstRef _rlp, bytes* o_output, bool _commit)
paranoia("after execution commit.", true); paranoia("after execution commit.", true);
if (e.t().receiveAddress) if (e.t().receiveAddress())
{ {
EnforceRefs r(m_db, true); EnforceRefs r(m_db, true);
if (storageRoot(e.t().receiveAddress) && m_db.lookup(storageRoot(e.t().receiveAddress)).empty()) if (storageRoot(e.t().receiveAddress()) && m_db.lookup(storageRoot(e.t().receiveAddress())).empty())
{ {
cwarn << "TRIE immediately after execution; no node for receiveAddress"; cwarn << "TRIE immediately after execution; no node for receiveAddress";
BOOST_THROW_EXCEPTION(InvalidTrie()); BOOST_THROW_EXCEPTION(InvalidTrie());

32
libethereum/State.h

@ -35,6 +35,7 @@
#include "TransactionQueue.h" #include "TransactionQueue.h"
#include "Account.h" #include "Account.h"
#include "Transaction.h" #include "Transaction.h"
#include "TransactionReceipt.h"
#include "Executive.h" #include "Executive.h"
#include "AccountDiff.h" #include "AccountDiff.h"
@ -52,37 +53,6 @@ struct StateChat: public LogChannel { static const char* name() { return "-S-";
struct StateTrace: public LogChannel { static const char* name() { return "=S="; } static const int verbosity = 7; }; struct StateTrace: public LogChannel { static const char* name() { return "=S="; } static const int verbosity = 7; };
struct StateDetail: public LogChannel { static const char* name() { return "/S/"; } static const int verbosity = 14; }; struct StateDetail: public LogChannel { static const char* name() { return "/S/"; } static const int verbosity = 14; };
class TransactionReceipt
{
public:
TransactionReceipt(h256 _root, u256 _gasUsed, LogEntries const& _log, Manifest const& _ms): m_stateRoot(_root), m_gasUsed(_gasUsed), m_bloom(eth::bloom(_log)), m_log(_log), m_changes(_ms) {}
Manifest const& changes() const { return m_changes; }
h256 const& stateRoot() const { return m_stateRoot; }
u256 const& gasUsed() const { return m_gasUsed; }
LogBloom const& bloom() const { return m_bloom; }
LogEntries const& log() const { return m_log; }
void streamRLP(RLPStream& _s) const
{
_s.appendList(4) << m_stateRoot << m_gasUsed << m_bloom;
_s.appendList(m_log.size());
for (LogEntry const& l: m_log)
l.streamRLP(_s);
}
private:
h256 m_stateRoot;
u256 m_gasUsed;
LogBloom m_bloom;
LogEntries m_log;
Manifest m_changes; ///< TODO: PoC-7: KILL
};
using TransactionReceipts = std::vector<TransactionReceipt>;
struct PrecompiledAddress struct PrecompiledAddress
{ {
unsigned gas; unsigned gas;

30
libethereum/Transaction.cpp

@ -36,14 +36,14 @@ Transaction::Transaction(bytesConstRef _rlpData, bool _checkSender)
RLP rlp(_rlpData); RLP rlp(_rlpData);
try try
{ {
nonce = rlp[field = 0].toInt<u256>(); m_nonce = rlp[field = 0].toInt<u256>();
gasPrice = rlp[field = 1].toInt<u256>(); m_gasPrice = rlp[field = 1].toInt<u256>();
gas = rlp[field = 2].toInt<u256>(); m_gas = rlp[field = 2].toInt<u256>();
type = rlp[field = 3].isEmpty() ? ContractCreation : MessageCall; m_type = rlp[field = 3].isEmpty() ? ContractCreation : MessageCall;
receiveAddress = rlp[field = 3].toHash<Address>(); m_receiveAddress = rlp[field = 3].toHash<Address>();
value = rlp[field = 4].toInt<u256>(); m_value = rlp[field = 4].toInt<u256>();
data = rlp[field = 5].toBytes(); m_data = rlp[field = 5].toBytes();
vrs = SignatureStruct{ rlp[field = 7].toInt<u256>(), rlp[field = 8].toInt<u256>(), byte(rlp[field = 6].toInt<byte>() - 27) }; m_vrs = SignatureStruct{ rlp[field = 7].toInt<u256>(), rlp[field = 8].toInt<u256>(), byte(rlp[field = 6].toInt<byte>() - 27) };
if (_checkSender) if (_checkSender)
m_sender = sender(); m_sender = sender();
} }
@ -71,7 +71,7 @@ Address Transaction::sender() const
{ {
if (!m_sender) if (!m_sender)
{ {
auto p = recover(*(Signature const*)&vrs, sha3(false)); auto p = recover(*(Signature const*)&m_vrs, sha3(false));
if (!p) if (!p)
BOOST_THROW_EXCEPTION(InvalidSignature()); BOOST_THROW_EXCEPTION(InvalidSignature());
m_sender = right160(dev::sha3(bytesConstRef(p.data(), sizeof(p)))); m_sender = right160(dev::sha3(bytesConstRef(p.data(), sizeof(p))));
@ -82,18 +82,18 @@ Address Transaction::sender() const
void Transaction::sign(Secret _priv) void Transaction::sign(Secret _priv)
{ {
auto sig = dev::sign(_priv, sha3(false)); auto sig = dev::sign(_priv, sha3(false));
vrs = *(SignatureStruct const*)&sig; m_vrs = *(SignatureStruct const*)&sig;
} }
void Transaction::streamRLP(RLPStream& _s, bool _sig) const void Transaction::streamRLP(RLPStream& _s, bool _sig) const
{ {
_s.appendList((_sig ? 3 : 0) + 6); _s.appendList((_sig ? 3 : 0) + 6);
_s << nonce << gasPrice << gas; _s << m_nonce << m_gasPrice << m_gas;
if (type == MessageCall) if (m_type == MessageCall)
_s << receiveAddress; _s << m_receiveAddress;
else else
_s << ""; _s << "";
_s << value << data; _s << m_value << m_data;
if (_sig) if (_sig)
_s << (vrs.v + 27) << (u256)vrs.r << (u256)vrs.s; _s << (m_vrs.v + 27) << (u256)m_vrs.r << (u256)m_vrs.s;
} }

58
libethereum/Transaction.h

@ -30,47 +30,60 @@ namespace dev
namespace eth namespace eth
{ {
struct Transaction class Transaction
{ {
public:
enum Type enum Type
{ {
NullTransaction,
ContractCreation, ContractCreation,
MessageCall MessageCall
}; };
Transaction() {} Transaction() {}
Transaction(u256 _value, u256 _gasPrice, u256 _gas, Address const& _dest, bytes const& _data, u256 _nonce, Secret const& _secret): m_type(MessageCall), m_nonce(_nonce), m_value(_value), m_receiveAddress(_dest), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) { sign(_secret); }
Transaction(u256 _value, u256 _gasPrice, u256 _gas, bytes const& _data, u256 _nonce, Secret const& _secret): m_type(ContractCreation), m_nonce(_nonce), m_value(_value), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) { sign(_secret); }
Transaction(u256 _value, u256 _gasPrice, u256 _gas, Address const& _dest, bytes const& _data): m_type(MessageCall), m_value(_value), m_receiveAddress(_dest), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) {}
Transaction(u256 _value, u256 _gasPrice, u256 _gas, bytes const& _data): m_type(ContractCreation), m_value(_value), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) {}
Transaction(bytesConstRef _rlp, bool _checkSender = false); Transaction(bytesConstRef _rlp, bool _checkSender = false);
Transaction(bytes const& _rlp, bool _checkSender = false): Transaction(&_rlp, _checkSender) {} Transaction(bytes const& _rlp, bool _checkSender = false): Transaction(&_rlp, _checkSender) {}
bool operator==(Transaction const& _c) const { return type == _c.type && (type == ContractCreation || receiveAddress == _c.receiveAddress) && value == _c.value && data == _c.data; } bool operator==(Transaction const& _c) const { return m_type == _c.m_type && (m_type == ContractCreation || m_receiveAddress == _c.m_receiveAddress) && m_value == _c.m_value && m_data == _c.m_data; }
bool operator!=(Transaction const& _c) const { return !operator==(_c); } bool operator!=(Transaction const& _c) const { return !operator==(_c); }
Type type; ///< True if this is a contract-creation transaction. F Address safeSender() const noexcept; ///< Like sender() but will never throw. @returns a null Address if the signature is invalid.
u256 nonce; ///< The transaction-count of the sender.
u256 value; ///< The amount of ETH to be transferred by this transaction. Called 'endowment' for contract-creation transactions.
Address receiveAddress; ///< The receiving address of the transaction.
u256 gasPrice; ///< The base fee and thus the implied exchange rate of ETH to GAS.
u256 gas; ///< The total gas to convert, paid for from sender's account. Any unused gas gets refunded once the contract is ended.
bytes data; ///< The data associated with the transaction, or the initialiser if it's a creation transaction.
SignatureStruct vrs; ///< The signature of the transaction. Encodes the sender.
Address safeSender() const noexcept; ///< Like sender() but will never throw.
Address sender() const; ///< Determine the sender of the transaction from the signature (and hash). Address sender() const; ///< Determine the sender of the transaction from the signature (and hash).
void sign(Secret _priv); ///< Sign the transaction.
bool isCreation() const { return !receiveAddress; }
static h256 kFromMessage(h256 _msg, h256 _priv); bool isCreation() const { return m_type == ContractCreation; }
void streamRLP(RLPStream& _s, bool _sig = true) const; void streamRLP(RLPStream& _s, bool _sig = true) const;
bytes rlp(bool _sig = true) const { RLPStream s; streamRLP(s, _sig); return s.out(); } bytes rlp(bool _sig = true) const { RLPStream s; streamRLP(s, _sig); return s.out(); }
std::string rlpString(bool _sig = true) const { return asString(rlp(_sig)); } std::string rlpString(bool _sig = true) const { return asString(rlp(_sig)); }
h256 sha3(bool _sig = true) const { RLPStream s; streamRLP(s, _sig); return dev::sha3(s.out()); } h256 sha3(bool _sig = true) const { RLPStream s; streamRLP(s, _sig); return dev::sha3(s.out()); }
bytes sha3Bytes(bool _sig = true) const { RLPStream s; streamRLP(s, _sig); return dev::sha3Bytes(s.out()); } bytes sha3Bytes(bool _sig = true) const { RLPStream s; streamRLP(s, _sig); return dev::sha3Bytes(s.out()); }
Type type() const { return m_type; }
u256 nonce() const { return m_nonce; }
u256 value() const { return m_value; }
Address receiveAddress() const { return m_receiveAddress; }
u256 gasPrice() const { return m_gasPrice; }
u256 gas() const { return m_gas; }
bytes const& data() const { return m_data; }
SignatureStruct const& signature() const { return m_vrs; }
private: private:
void sign(Secret _priv); ///< Sign the transaction.
Type m_type = NullTransaction; ///< True if this is a contract-creation transaction. F
u256 m_nonce; ///< The transaction-count of the sender.
u256 m_value; ///< The amount of ETH to be transferred by this transaction. Called 'endowment' for contract-creation transactions.
Address m_receiveAddress; ///< The receiving address of the transaction.
u256 m_gasPrice; ///< The base fee and thus the implied exchange rate of ETH to GAS.
u256 m_gas; ///< The total gas to convert, paid for from sender's account. Any unused gas gets refunded once the contract is ended.
bytes m_data; ///< The data associated with the transaction, or the initialiser if it's a creation transaction.
SignatureStruct m_vrs; ///< The signature of the transaction. Encodes the sender.
mutable Address m_sender; mutable Address m_sender;
}; };
@ -79,19 +92,18 @@ using Transactions = std::vector<Transaction>;
inline std::ostream& operator<<(std::ostream& _out, Transaction const& _t) inline std::ostream& operator<<(std::ostream& _out, Transaction const& _t)
{ {
_out << "{"; _out << "{";
if (_t.receiveAddress) if (_t.receiveAddress())
_out << _t.receiveAddress.abridged(); _out << _t.receiveAddress().abridged();
else else
_out << "[CREATE]"; _out << "[CREATE]";
_out << "/" << _t.nonce << "$" << _t.value << "+" << _t.gas << "@" << _t.gasPrice; _out << "/" << _t.nonce() << "$" << _t.value() << "+" << _t.gas() << "@" << _t.gasPrice();
Address s;
try try
{ {
_out << "<-" << _t.sender().abridged(); _out << "<-" << _t.sender().abridged();
} }
catch (...) {} catch (...) {}
_out << " #" << _t.data.size() << "}"; _out << " #" << _t.data().size() << "}";
return _out; return _out;
} }

70
libethereum/TransactionReceipt.h

@ -0,0 +1,70 @@
/*
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 TransactionReceipt.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#pragma once
#include <array>
#include <map>
#include <libdevcore/Common.h>
#include <libdevcore/RLP.h>
#include <libevm/ExtVMFace.h>
#include "Manifest.h"
namespace dev
{
namespace eth
{
class TransactionReceipt
{
public:
TransactionReceipt(bytesConstRef _rlp) { RLP r(_rlp); m_stateRoot = (h256)r[0]; m_gasUsed = (u256)r[1]; m_bloom = (LogBloom)r[2]; for (auto const& i: r[3]) m_log.emplace_back(i); }
TransactionReceipt(h256 _root, u256 _gasUsed, LogEntries const& _log, Manifest const& _ms): m_stateRoot(_root), m_gasUsed(_gasUsed), m_bloom(eth::bloom(_log)), m_log(_log), m_changes(_ms) {}
Manifest const& changes() const { return m_changes; }
h256 const& stateRoot() const { return m_stateRoot; }
u256 const& gasUsed() const { return m_gasUsed; }
LogBloom const& bloom() const { return m_bloom; }
LogEntries const& log() const { return m_log; }
void streamRLP(RLPStream& _s) const
{
_s.appendList(4) << m_stateRoot << m_gasUsed << m_bloom;
_s.appendList(m_log.size());
for (LogEntry const& l: m_log)
l.streamRLP(_s);
}
private:
h256 m_stateRoot;
u256 m_gasUsed;
LogBloom m_bloom;
LogEntries m_log;
Manifest m_changes; ///< TODO: PoC-7: KILL
};
using TransactionReceipts = std::vector<TransactionReceipt>;
}
}

20
libevm/ExtVMFace.h

@ -36,27 +36,35 @@ namespace dev
namespace eth namespace eth
{ {
template <class T> inline std::set<T> toSet(std::vector<T> const& _ts)
{
std::set<T> ret;
for (auto const& t: _ts)
ret.insert(t);
return ret;
}
using LogBloom = h512; using LogBloom = h512;
struct LogEntry struct LogEntry
{ {
LogEntry() {} LogEntry() {}
LogEntry(RLP const& _r) { from = (Address)_r[0]; topics = (h256s)_r[1]; data = (bytes)_r[2]; } LogEntry(RLP const& _r) { address = (Address)_r[0]; topics = (h256Set)_r[1]; data = (bytes)_r[2]; }
LogEntry(Address const& _f, h256s&& _ts, bytes&& _d): from(_f), topics(std::move(_ts)), data(std::move(_d)) {} LogEntry(Address const& _address, h256s const& _ts, bytes&& _d): address(_address), topics(toSet(_ts)), data(std::move(_d)) {}
void streamRLP(RLPStream& _s) const { _s.appendList(3) << from << topics << data; } void streamRLP(RLPStream& _s) const { _s.appendList(3) << address << topics << data; }
LogBloom bloom() const LogBloom bloom() const
{ {
LogBloom ret; LogBloom ret;
ret.shiftBloom<3, 32>(sha3(from.ref())); ret.shiftBloom<3, 32>(sha3(address.ref()));
for (auto t: topics) for (auto t: topics)
ret.shiftBloom<3, 32>(sha3(t.ref())); ret.shiftBloom<3, 32>(sha3(t.ref()));
return ret; return ret;
} }
Address from; Address address;
h256s topics; h256Set topics;
bytes data; bytes data;
}; };

3
libevm/VM.h

@ -104,7 +104,7 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
{ {
int in = _ext.code[i] - (unsigned)Instruction::PUSH1 + 1; int in = _ext.code[i] - (unsigned)Instruction::PUSH1 + 1;
u256 p = 0; u256 p = 0;
for (; in--; i++) for (i++; in--; i++)
p = (p << 8) | _ext.getCode(i); p = (p << 8) | _ext.getCode(i);
if ((_ext.getCode(i) == (byte)Instruction::JUMP || _ext.getCode(i) == (byte)Instruction::JUMPI) && !(_ext.getCode(p) == (byte)Instruction::JUMP || _ext.getCode(p) == (byte)Instruction::JUMPI)) if ((_ext.getCode(i) == (byte)Instruction::JUMP || _ext.getCode(i) == (byte)Instruction::JUMPI) && !(_ext.getCode(p) == (byte)Instruction::JUMP || _ext.getCode(p) == (byte)Instruction::JUMPI))
if (p >= _ext.code.size()) if (p >= _ext.code.size())
@ -112,6 +112,7 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
else else
implicit.insert(p); implicit.insert(p);
else {} else {}
i--;
} }
for (unsigned i = 0; i < _ext.code.size(); i += instructionInfo((Instruction)_ext.getCode(i)).additional + 1) for (unsigned i = 0; i < _ext.code.size(); i += instructionInfo((Instruction)_ext.getCode(i)).additional + 1)
if (implicit.count(i)) if (implicit.count(i))

40
libp2p/Host.cpp

@ -62,8 +62,8 @@ Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bool
m_clientVersion(_clientVersion), m_clientVersion(_clientVersion),
m_netPrefs(_n), m_netPrefs(_n),
m_ioService(new ba::io_service), m_ioService(new ba::io_service),
m_acceptor(*m_ioService), m_acceptor(new bi::tcp::acceptor(*m_ioService)),
m_socket(*m_ioService), m_socket(new bi::tcp::socket(*m_ioService)),
m_key(KeyPair::create()) m_key(KeyPair::create())
{ {
populateAddresses(); populateAddresses();
@ -91,11 +91,11 @@ void Host::start()
bi::tcp::endpoint endpoint(bi::tcp::v4(), i ? 0 : m_netPrefs.listenPort); bi::tcp::endpoint endpoint(bi::tcp::v4(), i ? 0 : m_netPrefs.listenPort);
try try
{ {
m_acceptor.open(endpoint.protocol()); m_acceptor->open(endpoint.protocol());
m_acceptor.set_option(ba::socket_base::reuse_address(true)); m_acceptor->set_option(ba::socket_base::reuse_address(true));
m_acceptor.bind(endpoint); m_acceptor->bind(endpoint);
m_acceptor.listen(); m_acceptor->listen();
m_listenPort = i ? m_acceptor.local_endpoint().port() : m_netPrefs.listenPort; m_listenPort = i ? m_acceptor->local_endpoint().port() : m_netPrefs.listenPort;
break; break;
} }
catch (...) catch (...)
@ -105,7 +105,7 @@ void Host::start()
cwarn << "Couldn't start accepting connections on host. Something very wrong with network?\n" << boost::current_exception_diagnostic_information(); cwarn << "Couldn't start accepting connections on host. Something very wrong with network?\n" << boost::current_exception_diagnostic_information();
return; return;
} }
m_acceptor.close(); m_acceptor->close();
continue; continue;
} }
} }
@ -118,20 +118,24 @@ void Host::start()
void Host::stop() void Host::stop()
{ {
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!m_ioService)
return;
for (auto const& h: m_capabilities) for (auto const& h: m_capabilities)
h.second->onStopping(); h.second->onStopping();
stopWorking(); stopWorking();
if (m_acceptor.is_open()) if (m_acceptor->is_open())
{ {
if (m_accepting) if (m_accepting)
m_acceptor.cancel(); m_acceptor->cancel();
m_acceptor.close(); m_acceptor->close();
m_accepting = false; m_accepting = false;
} }
if (m_socket.is_open()) if (m_socket->is_open())
m_socket.close(); m_socket->close();
disconnectPeers(); disconnectPeers();
if (!!m_ioService) if (!!m_ioService)
@ -147,6 +151,8 @@ void Host::quit()
// such tasks may involve socket reads from Capabilities that maintain references // such tasks may involve socket reads from Capabilities that maintain references
// to resources we're about to free. // to resources we're about to free.
stop(); stop();
m_acceptor.reset();
m_socket.reset();
m_ioService.reset(); m_ioService.reset();
// m_acceptor & m_socket are DANGEROUS now. // m_acceptor & m_socket are DANGEROUS now.
} }
@ -463,18 +469,18 @@ void Host::ensureAccepting()
{ {
clog(NetConnect) << "Listening on local port " << m_listenPort << " (public: " << m_public << ")"; clog(NetConnect) << "Listening on local port " << m_listenPort << " (public: " << m_public << ")";
m_accepting = true; m_accepting = true;
m_acceptor.async_accept(m_socket, [=](boost::system::error_code ec) m_acceptor->async_accept(*m_socket, [=](boost::system::error_code ec)
{ {
if (!ec) if (!ec)
{ {
try try
{ {
try { try {
clog(NetConnect) << "Accepted connection from " << m_socket.remote_endpoint(); clog(NetConnect) << "Accepted connection from " << m_socket->remote_endpoint();
} catch (...){} } catch (...){}
bi::address remoteAddress = m_socket.remote_endpoint().address(); bi::address remoteAddress = m_socket->remote_endpoint().address();
// Port defaults to 0 - we let the hello tell us which port the peer listens to // Port defaults to 0 - we let the hello tell us which port the peer listens to
auto p = std::make_shared<Session>(this, std::move(m_socket), bi::tcp::endpoint(remoteAddress, 0)); auto p = std::make_shared<Session>(this, std::move(*m_socket), bi::tcp::endpoint(remoteAddress, 0));
p->start(); p->start();
} }
catch (Exception const& _e) catch (Exception const& _e)

4
libp2p/Host.h

@ -214,8 +214,8 @@ private:
int m_listenPort = NetworkStopped; ///< What port are we listening on? int m_listenPort = NetworkStopped; ///< What port are we listening on?
std::unique_ptr<ba::io_service> m_ioService; ///< IOService for network stuff. std::unique_ptr<ba::io_service> m_ioService; ///< IOService for network stuff.
bi::tcp::acceptor m_acceptor; ///< Listening acceptor. std::unique_ptr<bi::tcp::acceptor> m_acceptor; ///< Listening acceptor.
bi::tcp::socket m_socket; ///< Listening socket. std::unique_ptr<bi::tcp::socket> m_socket; ///< Listening socket.
UPnP* m_upnp = nullptr; ///< UPnP helper. UPnP* m_upnp = nullptr; ///< UPnP helper.
bi::tcp::endpoint m_public; ///< Our public listening endpoint. bi::tcp::endpoint m_public; ///< Our public listening endpoint.

8
libsolidity/Parser.cpp

@ -290,10 +290,10 @@ ASTPointer<Statement> Parser::parseStatement()
// We have a variable definition if we get a keyword that specifies a type name, or // We have a variable definition if we get a keyword that specifies a type name, or
// in the case of a user-defined type, we have two identifiers following each other. // in the case of a user-defined type, we have two identifiers following each other.
if (m_scanner->getCurrentToken() == Token::MAPPING || if (m_scanner->getCurrentToken() == Token::MAPPING ||
m_scanner->getCurrentToken() == Token::VAR || m_scanner->getCurrentToken() == Token::VAR ||
Token::isElementaryTypeName(m_scanner->getCurrentToken()) || ((Token::isElementaryTypeName(m_scanner->getCurrentToken()) ||
(m_scanner->getCurrentToken() == Token::IDENTIFIER && m_scanner->getCurrentToken() == Token::IDENTIFIER) &&
m_scanner->peekNextToken() == Token::IDENTIFIER)) m_scanner->peekNextToken() == Token::IDENTIFIER))
statement = parseVariableDefinition(); statement = parseVariableDefinition();
else // "ordinary" expression statement else // "ordinary" expression statement
statement = parseExpressionStatement(); statement = parseExpressionStatement();

83
libweb3jsonrpc/WebThreeStubServer.cpp

@ -87,13 +87,31 @@ static Json::Value toJson(dev::eth::Transaction const& _t)
{ {
Json::Value res; Json::Value res;
res["hash"] = toJS(_t.sha3()); res["hash"] = toJS(_t.sha3());
res["input"] = jsFromBinary(_t.data); res["input"] = jsFromBinary(_t.data());
res["to"] = toJS(_t.receiveAddress); res["to"] = toJS(_t.receiveAddress());
res["from"] = toJS(_t.sender()); res["from"] = toJS(_t.sender());
res["gas"] = (int)_t.gas; res["gas"] = (int)_t.gas();
res["gasPrice"] = toJS(_t.gasPrice); res["gasPrice"] = toJS(_t.gasPrice());
res["nonce"] = toJS(_t.nonce); res["nonce"] = toJS(_t.nonce());
res["value"] = toJS(_t.value); res["value"] = toJS(_t.value());
return res;
}
static Json::Value toJson(dev::eth::LogEntry const& _e)
{
Json::Value res;
res["data"] = jsFromBinary(_e.data);
res["address"] = toJS(_e.address);
for (auto const& t: _e.topics)
res["topics"].append(toJS(t));
return res;
}
/*static*/ Json::Value toJson(dev::eth::LogEntries const& _es) // commented to avoid warning. Uncomment once in use @ poC-7.
{
Json::Value res;
for (dev::eth::LogEntry const& e: _es)
res.append(toJson(e));
return res; return res;
} }
@ -123,9 +141,9 @@ static dev::eth::MessageFilter toMessageFilter(Json::Value const& _json)
{ {
if (_json["to"].isArray()) if (_json["to"].isArray())
for (auto i : _json["to"]) for (auto i : _json["to"])
filter.from(jsToAddress(i.asString())); filter.to(jsToAddress(i.asString()));
else else
filter.from(jsToAddress(_json["to"].asString())); filter.to(jsToAddress(_json["to"].asString()));
} }
if (!_json["altered"].empty()) if (!_json["altered"].empty())
{ {
@ -143,6 +161,48 @@ static dev::eth::MessageFilter toMessageFilter(Json::Value const& _json)
return filter; return filter;
} }
/*static*/ dev::eth::LogFilter toLogFilter(Json::Value const& _json) // commented to avoid warning. Uncomment once in use @ PoC-7.
{
dev::eth::LogFilter filter;
if (!_json.isObject() || _json.empty())
return filter;
if (!_json["earliest"].empty())
filter.withEarliest(_json["earliest"].asInt());
if (!_json["latest"].empty())
filter.withLatest(_json["lastest"].asInt());
if (!_json["max"].empty())
filter.withMax(_json["max"].asInt());
if (!_json["skip"].empty())
filter.withSkip(_json["skip"].asInt());
if (!_json["from"].empty())
{
if (_json["from"].isArray())
for (auto i : _json["from"])
filter.from(jsToAddress(i.asString()));
else
filter.from(jsToAddress(_json["from"].asString()));
}
if (!_json["address"].empty())
{
if (_json["address"].isArray())
for (auto i : _json["address"])
filter.address(jsToAddress(i.asString()));
else
filter.from(jsToAddress(_json["address"].asString()));
}
if (!_json["topics"].empty())
{
if (_json["topics"].isArray())
for (auto i: _json["topics"])
if (i.isString())
filter.topic(jsToU256(i.asString()));
else if(_json["topics"].isString())
filter.topic(jsToU256(_json["topics"].asString()));
}
return filter;
}
static shh::Message toMessage(Json::Value const& _json) static shh::Message toMessage(Json::Value const& _json)
{ {
shh::Message ret; shh::Message ret;
@ -252,13 +312,6 @@ std::shared_ptr<dev::shh::Interface> WebThreeStubServer::face() const
return m_web3.whisper(); return m_web3.whisper();
} }
std::string WebThreeStubServer::account()
{
if (!m_accounts.empty())
return toJS(m_accounts.begin()->first);
return "";
}
Json::Value WebThreeStubServer::accounts() Json::Value WebThreeStubServer::accounts()
{ {
Json::Value ret(Json::arrayValue); Json::Value ret(Json::arrayValue);

4
libweb3jsonrpc/WebThreeStubServer.h

@ -56,13 +56,14 @@ class Interface;
* @brief JSON-RPC api implementation * @brief JSON-RPC api implementation
* @todo filters should work on unsigned instead of int * @todo filters should work on unsigned instead of int
* unsigned are not supported in json-rpc-cpp and there are bugs with double in json-rpc-cpp version 0.2.1 * unsigned are not supported in json-rpc-cpp and there are bugs with double in json-rpc-cpp version 0.2.1
* @todo split these up according to subprotocol (eth, shh, db, p2p, web3) and make it /very/ clear about how to add other subprotocols.
* @todo modularise everything so additional subprotocols don't need to change this file.
*/ */
class WebThreeStubServer: public AbstractWebThreeStubServer class WebThreeStubServer: public AbstractWebThreeStubServer
{ {
public: public:
WebThreeStubServer(jsonrpc::AbstractServerConnector* _conn, dev::WebThreeDirect& _web3, std::vector<dev::KeyPair> const& _accounts); WebThreeStubServer(jsonrpc::AbstractServerConnector* _conn, dev::WebThreeDirect& _web3, std::vector<dev::KeyPair> const& _accounts);
virtual std::string account();
virtual Json::Value accounts(); virtual Json::Value accounts();
virtual std::string addToGroup(std::string const& _group, std::string const& _who); virtual std::string addToGroup(std::string const& _group, std::string const& _who);
virtual std::string balanceAt(std::string const& _address); virtual std::string balanceAt(std::string const& _address);
@ -109,6 +110,7 @@ public:
void setAccounts(std::vector<dev::KeyPair> const& _accounts); void setAccounts(std::vector<dev::KeyPair> const& _accounts);
void setIdentities(std::vector<dev::KeyPair> const& _ids); void setIdentities(std::vector<dev::KeyPair> const& _ids);
std::map<dev::Public, dev::Secret> const& ids() const { return m_ids; } std::map<dev::Public, dev::Secret> const& ids() const { return m_ids; }
private: private:
dev::eth::Interface* client() const; dev::eth::Interface* client() const;
std::shared_ptr<dev::shh::Interface> face() const; std::shared_ptr<dev::shh::Interface> face() const;

7
libweb3jsonrpc/abstractwebthreestubserver.h

@ -13,7 +13,6 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
AbstractWebThreeStubServer(jsonrpc::AbstractServerConnector* conn) : AbstractWebThreeStubServer(jsonrpc::AbstractServerConnector* conn) :
jsonrpc::AbstractServer<AbstractWebThreeStubServer>(conn) jsonrpc::AbstractServer<AbstractWebThreeStubServer>(conn)
{ {
this->bindAndAddMethod(new jsonrpc::Procedure("account", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::accountI);
this->bindAndAddMethod(new jsonrpc::Procedure("accounts", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::accountsI); this->bindAndAddMethod(new jsonrpc::Procedure("accounts", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::accountsI);
this->bindAndAddMethod(new jsonrpc::Procedure("addToGroup", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::addToGroupI); this->bindAndAddMethod(new jsonrpc::Procedure("addToGroup", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::addToGroupI);
this->bindAndAddMethod(new jsonrpc::Procedure("balanceAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::balanceAtI); this->bindAndAddMethod(new jsonrpc::Procedure("balanceAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::balanceAtI);
@ -59,11 +58,6 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
} }
inline virtual void accountI(const Json::Value& request, Json::Value& response)
{
response = this->account();
}
inline virtual void accountsI(const Json::Value& request, Json::Value& response) inline virtual void accountsI(const Json::Value& request, Json::Value& response)
{ {
response = this->accounts(); response = this->accounts();
@ -275,7 +269,6 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
} }
virtual std::string account() = 0;
virtual Json::Value accounts() = 0; virtual Json::Value accounts() = 0;
virtual std::string addToGroup(const std::string& param1, const std::string& param2) = 0; virtual std::string addToGroup(const std::string& param1, const std::string& param2) = 0;
virtual std::string balanceAt(const std::string& param1) = 0; virtual std::string balanceAt(const std::string& param1) = 0;

1
libweb3jsonrpc/spec.json

@ -6,7 +6,6 @@
{ "method": "mining", "params": [], "order": [], "returns" : false }, { "method": "mining", "params": [], "order": [], "returns" : false },
{ "method": "setMining", "params": [false], "order" : [], "returns" : true }, { "method": "setMining", "params": [false], "order" : [], "returns" : true },
{ "method": "gasPrice", "params": [], "order": [], "returns" : "" }, { "method": "gasPrice", "params": [], "order": [], "returns" : "" },
{ "method": "account", "params": [], "order": [], "returns" : "" },
{ "method": "accounts", "params": [], "order": [], "returns" : [] }, { "method": "accounts", "params": [], "order": [], "returns" : [] },
{ "method": "peerCount", "params": [], "order": [], "returns" : 0 }, { "method": "peerCount", "params": [], "order": [], "returns" : 0 },
{ "method": "defaultBlock", "params": [], "order": [], "returns" : 0}, { "method": "defaultBlock", "params": [], "order": [], "returns" : 0},

32
neth/main.cpp

@ -843,18 +843,18 @@ int main(int argc, char** argv)
for (auto const& i: RLP(b)[1]) for (auto const& i: RLP(b)[1])
{ {
Transaction t(i[0].data()); Transaction t(i[0].data());
auto s = t.receiveAddress ? auto s = t.receiveAddress() ?
boost::format(" %1% %2%> %3%: %4% [%5%]") % boost::format(" %1% %2%> %3%: %4% [%5%]") %
toString(t.safeSender()) % toString(t.safeSender()) %
(c.codeAt(t.receiveAddress, 0).size() ? '*' : '-') % (c.codeAt(t.receiveAddress(), 0).size() ? '*' : '-') %
toString(t.receiveAddress) % toString(t.receiveAddress()) %
toString(formatBalance(t.value)) % toString(formatBalance(t.value())) %
toString((unsigned)t.nonce) : toString((unsigned)t.nonce()) :
boost::format(" %1% +> %2%: %3% [%4%]") % boost::format(" %1% +> %2%: %3% [%4%]") %
toString(t.safeSender()) % toString(t.safeSender()) %
toString(right160(sha3(rlpList(t.safeSender(), t.nonce)))) % toString(right160(sha3(rlpList(t.safeSender(), t.nonce())))) %
toString(formatBalance(t.value)) % toString(formatBalance(t.value())) %
toString((unsigned)t.nonce); toString((unsigned)t.nonce());
mvwaddnstr(blockswin, y++, x, s.str().c_str(), qwidth - 2); mvwaddnstr(blockswin, y++, x, s.str().c_str(), qwidth - 2);
if (y > qheight - 2) if (y > qheight - 2)
break; break;
@ -868,18 +868,18 @@ int main(int argc, char** argv)
y = 1; y = 1;
for (Transaction const& t: c.pending()) for (Transaction const& t: c.pending())
{ {
auto s = t.receiveAddress ? auto s = t.receiveAddress() ?
boost::format("%1% %2%> %3%: %4% [%5%]") % boost::format("%1% %2%> %3%: %4% [%5%]") %
toString(t.safeSender()) % toString(t.safeSender()) %
(c.codeAt(t.receiveAddress, 0).size() ? '*' : '-') % (c.codeAt(t.receiveAddress(), 0).size() ? '*' : '-') %
toString(t.receiveAddress) % toString(t.receiveAddress()) %
toString(formatBalance(t.value)) % toString(formatBalance(t.value())) %
toString((unsigned)t.nonce) : toString((unsigned)t.nonce()) :
boost::format("%1% +> %2%: %3% [%4%]") % boost::format("%1% +> %2%: %3% [%4%]") %
toString(t.safeSender()) % toString(t.safeSender()) %
toString(right160(sha3(rlpList(t.safeSender(), t.nonce)))) % toString(right160(sha3(rlpList(t.safeSender(), t.nonce())))) %
toString(formatBalance(t.value)) % toString(formatBalance(t.value())) %
toString((unsigned)t.nonce); toString((unsigned)t.nonce());
mvwaddnstr(pendingwin, y++, x, s.str().c_str(), qwidth); mvwaddnstr(pendingwin, y++, x, s.str().c_str(), qwidth);
if (y > height * 1 / 5 - 4) if (y > height * 1 / 5 - 4)
break; break;

14
test/crypto.cpp

@ -339,16 +339,11 @@ BOOST_AUTO_TEST_CASE(eth_keypairs)
BOOST_REQUIRE(p.pub() == Public(fromHex("97466f2b32bc3bb76d4741ae51cd1d8578b48d3f1e68da206d47321aec267ce78549b514e4453d74ef11b0cd5e4e4c364effddac8b51bcfc8de80682f952896f"))); BOOST_REQUIRE(p.pub() == Public(fromHex("97466f2b32bc3bb76d4741ae51cd1d8578b48d3f1e68da206d47321aec267ce78549b514e4453d74ef11b0cd5e4e4c364effddac8b51bcfc8de80682f952896f")));
BOOST_REQUIRE(p.address() == Address(fromHex("8a40bfaa73256b60764c1bf40675a99083efb075"))); BOOST_REQUIRE(p.address() == Address(fromHex("8a40bfaa73256b60764c1bf40675a99083efb075")));
{ {
eth::Transaction t; eth::Transaction t(1000, 0, 0, h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b")), bytes(), 0, p.secret());
t.nonce = 0;
t.type = eth::Transaction::MessageCall;
t.receiveAddress = h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b"));
t.value = 1000;
auto rlp = t.rlp(false); auto rlp = t.rlp(false);
cnote << RLP(rlp); cnote << RLP(rlp);
cnote << toHex(rlp); cnote << toHex(rlp);
cnote << t.sha3(false); cnote << t.sha3(false);
t.sign(p.secret());
rlp = t.rlp(true); rlp = t.rlp(true);
cnote << RLP(rlp); cnote << RLP(rlp);
cnote << toHex(rlp); cnote << toHex(rlp);
@ -368,16 +363,11 @@ int cryptoTest()
assert(p.pub() == Public(fromHex("97466f2b32bc3bb76d4741ae51cd1d8578b48d3f1e68da206d47321aec267ce78549b514e4453d74ef11b0cd5e4e4c364effddac8b51bcfc8de80682f952896f"))); assert(p.pub() == Public(fromHex("97466f2b32bc3bb76d4741ae51cd1d8578b48d3f1e68da206d47321aec267ce78549b514e4453d74ef11b0cd5e4e4c364effddac8b51bcfc8de80682f952896f")));
assert(p.address() == Address(fromHex("8a40bfaa73256b60764c1bf40675a99083efb075"))); assert(p.address() == Address(fromHex("8a40bfaa73256b60764c1bf40675a99083efb075")));
{ {
eth::Transaction t; eth::Transaction t(1000, 0, 0, h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b")), bytes(), 0, p.secret());
t.nonce = 0;
t.type = eth::Transaction::MessageCall;
t.receiveAddress = h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b"));
t.value = 1000;
auto rlp = t.rlp(false); auto rlp = t.rlp(false);
cnote << RLP(rlp); cnote << RLP(rlp);
cnote << toHex(rlp); cnote << toHex(rlp);
cnote << t.sha3(false); cnote << t.sha3(false);
t.sign(p.secret());
rlp = t.rlp(true); rlp = t.rlp(true);
cnote << RLP(rlp); cnote << RLP(rlp);
cnote << toHex(rlp); cnote << toHex(rlp);

96
test/jsonrpc.cpp

@ -43,44 +43,39 @@ using namespace dev;
using namespace dev::eth; using namespace dev::eth;
namespace js = json_spirit; namespace js = json_spirit;
namespace jsonrpc_tests WebThreeDirect *web3;
{
string name = "Ethereum(++) tests";
string dbPath;
auto s = set<string>{"eth", "shh"};
dev::p2p::NetworkPreferences np(30303, std::string(), false);
dev::WebThreeDirect web3(name, dbPath, true, s, np);
unique_ptr<WebThreeStubServer> jsonrpcServer; unique_ptr<WebThreeStubServer> jsonrpcServer;
unique_ptr<WebThreeStubClient> jsonrpcClient; unique_ptr<WebThreeStubClient> jsonrpcClient;
struct JsonrpcFixture { struct Setup
JsonrpcFixture() {
Setup()
{ {
cnote << "setup jsonrpc"; static bool setup = false;
if (setup)
return;
setup = true;
web3.setIdealPeerCount(5); dev::p2p::NetworkPreferences nprefs(30303, std::string(), false);
web3.ethereum()->setForceMining(true); web3 = new WebThreeDirect("Ethereum(++) tests", "", true, {"eth", "shh"}, nprefs);
jsonrpcServer = unique_ptr<WebThreeStubServer>(new WebThreeStubServer(new jsonrpc::CorsHttpServer(8080), web3, {}));
web3->setIdealPeerCount(5);
web3->ethereum()->setForceMining(true);
jsonrpcServer = unique_ptr<WebThreeStubServer>(new WebThreeStubServer(new jsonrpc::CorsHttpServer(8080), *web3, {}));
jsonrpcServer->setIdentities({}); jsonrpcServer->setIdentities({});
jsonrpcServer->StartListening(); jsonrpcServer->StartListening();
jsonrpcClient = unique_ptr<WebThreeStubClient>(new WebThreeStubClient(new jsonrpc::HttpClient("http://localhost:8080"))); jsonrpcClient = unique_ptr<WebThreeStubClient>(new WebThreeStubClient(new jsonrpc::HttpClient("http://localhost:8080")));
} }
~JsonrpcFixture()
{
cnote << "teardown jsonrpc";
}
}; };
BOOST_GLOBAL_FIXTURE(JsonrpcFixture) BOOST_FIXTURE_TEST_SUITE(environment, Setup)
BOOST_AUTO_TEST_CASE(jsonrpc_defaultBlock) BOOST_AUTO_TEST_CASE(jsonrpc_defaultBlock)
{ {
cnote << "Testing jsonrpc defaultBlock..."; cnote << "Testing jsonrpc defaultBlock...";
int defaultBlock = jsonrpcClient->defaultBlock(); int defaultBlock = jsonrpcClient->defaultBlock();
BOOST_CHECK_EQUAL(defaultBlock, web3.ethereum()->getDefault()); BOOST_CHECK_EQUAL(defaultBlock, web3->ethereum()->getDefault());
} }
BOOST_AUTO_TEST_CASE(jsonrpc_gasPrice) BOOST_AUTO_TEST_CASE(jsonrpc_gasPrice)
@ -94,26 +89,26 @@ BOOST_AUTO_TEST_CASE(jsonrpc_isListening)
{ {
cnote << "Testing jsonrpc isListening..."; cnote << "Testing jsonrpc isListening...";
web3.startNetwork(); web3->startNetwork();
bool listeningOn = jsonrpcClient->listening(); bool listeningOn = jsonrpcClient->listening();
BOOST_CHECK_EQUAL(listeningOn, web3.isNetworkStarted()); BOOST_CHECK_EQUAL(listeningOn, web3->isNetworkStarted());
web3.stopNetwork(); web3->stopNetwork();
bool listeningOff = jsonrpcClient->listening(); bool listeningOff = jsonrpcClient->listening();
BOOST_CHECK_EQUAL(listeningOff, web3.isNetworkStarted()); BOOST_CHECK_EQUAL(listeningOff, web3->isNetworkStarted());
} }
BOOST_AUTO_TEST_CASE(jsonrpc_isMining) BOOST_AUTO_TEST_CASE(jsonrpc_isMining)
{ {
cnote << "Testing jsonrpc isMining..."; cnote << "Testing jsonrpc isMining...";
web3.ethereum()->startMining(); web3->ethereum()->startMining();
bool miningOn = jsonrpcClient->mining(); bool miningOn = jsonrpcClient->mining();
BOOST_CHECK_EQUAL(miningOn, web3.ethereum()->isMining()); BOOST_CHECK_EQUAL(miningOn, web3->ethereum()->isMining());
web3.ethereum()->stopMining(); web3->ethereum()->stopMining();
bool miningOff = jsonrpcClient->mining(); bool miningOff = jsonrpcClient->mining();
BOOST_CHECK_EQUAL(miningOff, web3.ethereum()->isMining()); BOOST_CHECK_EQUAL(miningOff, web3->ethereum()->isMining());
} }
BOOST_AUTO_TEST_CASE(jsonrpc_accounts) BOOST_AUTO_TEST_CASE(jsonrpc_accounts)
@ -139,18 +134,18 @@ BOOST_AUTO_TEST_CASE(jsonrpc_number)
{ {
cnote << "Testing jsonrpc number2..."; cnote << "Testing jsonrpc number2...";
int number = jsonrpcClient->number(); int number = jsonrpcClient->number();
BOOST_CHECK_EQUAL(number, web3.ethereum()->number() + 1); BOOST_CHECK_EQUAL(number, web3->ethereum()->number() + 1);
dev::eth::mine(*(web3.ethereum()), 1); dev::eth::mine(*(web3->ethereum()), 1);
int numberAfter = jsonrpcClient->number(); int numberAfter = jsonrpcClient->number();
BOOST_CHECK_EQUAL(number + 1, numberAfter); BOOST_CHECK_EQUAL(number + 1, numberAfter);
BOOST_CHECK_EQUAL(numberAfter, web3.ethereum()->number() + 1); BOOST_CHECK_EQUAL(numberAfter, web3->ethereum()->number() + 1);
} }
BOOST_AUTO_TEST_CASE(jsonrpc_peerCount) BOOST_AUTO_TEST_CASE(jsonrpc_peerCount)
{ {
cnote << "Testing jsonrpc peerCount..."; cnote << "Testing jsonrpc peerCount...";
int peerCount = jsonrpcClient->peerCount(); int peerCount = jsonrpcClient->peerCount();
BOOST_CHECK_EQUAL(web3.peerCount(), peerCount); BOOST_CHECK_EQUAL(web3->peerCount(), peerCount);
} }
BOOST_AUTO_TEST_CASE(jsonrpc_setListening) BOOST_AUTO_TEST_CASE(jsonrpc_setListening)
@ -158,10 +153,10 @@ BOOST_AUTO_TEST_CASE(jsonrpc_setListening)
cnote << "Testing jsonrpc setListening..."; cnote << "Testing jsonrpc setListening...";
jsonrpcClient->setListening(true); jsonrpcClient->setListening(true);
BOOST_CHECK_EQUAL(web3.isNetworkStarted(), true); BOOST_CHECK_EQUAL(web3->isNetworkStarted(), true);
jsonrpcClient->setListening(false); jsonrpcClient->setListening(false);
BOOST_CHECK_EQUAL(web3.isNetworkStarted(), false); BOOST_CHECK_EQUAL(web3->isNetworkStarted(), false);
} }
BOOST_AUTO_TEST_CASE(jsonrpc_setMining) BOOST_AUTO_TEST_CASE(jsonrpc_setMining)
@ -169,10 +164,10 @@ BOOST_AUTO_TEST_CASE(jsonrpc_setMining)
cnote << "Testing jsonrpc setMining..."; cnote << "Testing jsonrpc setMining...";
jsonrpcClient->setMining(true); jsonrpcClient->setMining(true);
BOOST_CHECK_EQUAL(web3.ethereum()->isMining(), true); BOOST_CHECK_EQUAL(web3->ethereum()->isMining(), true);
jsonrpcClient->setMining(false); jsonrpcClient->setMining(false);
BOOST_CHECK_EQUAL(web3.ethereum()->isMining(), false); BOOST_CHECK_EQUAL(web3->ethereum()->isMining(), false);
} }
BOOST_AUTO_TEST_CASE(jsonrpc_stateAt) BOOST_AUTO_TEST_CASE(jsonrpc_stateAt)
@ -181,36 +176,36 @@ BOOST_AUTO_TEST_CASE(jsonrpc_stateAt)
dev::KeyPair key = KeyPair::create(); dev::KeyPair key = KeyPair::create();
auto address = key.address(); auto address = key.address();
string stateAt = jsonrpcClient->stateAt(toJS(address), "0"); string stateAt = jsonrpcClient->stateAt(toJS(address), "0");
BOOST_CHECK_EQUAL(toJS(web3.ethereum()->stateAt(address, jsToU256("0"), 0)), stateAt); BOOST_CHECK_EQUAL(toJS(web3->ethereum()->stateAt(address, jsToU256("0"), 0)), stateAt);
} }
BOOST_AUTO_TEST_CASE(jsonrpc_transact) BOOST_AUTO_TEST_CASE(jsonrpc_transact)
{ {
cnote << "Testing jsonrpc transact..."; cnote << "Testing jsonrpc transact...";
string coinbase = jsonrpcClient->coinbase(); string coinbase = jsonrpcClient->coinbase();
BOOST_CHECK_EQUAL(jsToAddress(coinbase), web3.ethereum()->address()); BOOST_CHECK_EQUAL(jsToAddress(coinbase), web3->ethereum()->address());
dev::KeyPair key = KeyPair::create(); dev::KeyPair key = KeyPair::create();
auto address = key.address(); auto address = key.address();
auto receiver = KeyPair::create(); auto receiver = KeyPair::create();
web3.ethereum()->setAddress(address); web3->ethereum()->setAddress(address);
coinbase = jsonrpcClient->coinbase(); coinbase = jsonrpcClient->coinbase();
BOOST_CHECK_EQUAL(jsToAddress(coinbase), web3.ethereum()->address()); BOOST_CHECK_EQUAL(jsToAddress(coinbase), web3->ethereum()->address());
BOOST_CHECK_EQUAL(jsToAddress(coinbase), address); BOOST_CHECK_EQUAL(jsToAddress(coinbase), address);
jsonrpcServer->setAccounts({key}); jsonrpcServer->setAccounts({key});
auto balance = web3.ethereum()->balanceAt(address, 0); auto balance = web3->ethereum()->balanceAt(address, 0);
string balanceString = jsonrpcClient->balanceAt(toJS(address)); string balanceString = jsonrpcClient->balanceAt(toJS(address));
double countAt = jsonrpcClient->countAt(toJS(address)); double countAt = jsonrpcClient->countAt(toJS(address));
BOOST_CHECK_EQUAL(countAt, (double)(uint64_t)web3.ethereum()->countAt(address)); BOOST_CHECK_EQUAL(countAt, (double)(uint64_t)web3->ethereum()->countAt(address));
BOOST_CHECK_EQUAL(countAt, 0); BOOST_CHECK_EQUAL(countAt, 0);
BOOST_CHECK_EQUAL(toJS(balance), balanceString); BOOST_CHECK_EQUAL(toJS(balance), balanceString);
BOOST_CHECK_EQUAL(jsToDecimal(balanceString), "0"); BOOST_CHECK_EQUAL(jsToDecimal(balanceString), "0");
dev::eth::mine(*(web3.ethereum()), 1); dev::eth::mine(*(web3->ethereum()), 1);
balance = web3.ethereum()->balanceAt(address, 0); balance = web3->ethereum()->balanceAt(address, 0);
balanceString = jsonrpcClient->balanceAt(toJS(address)); balanceString = jsonrpcClient->balanceAt(toJS(address));
BOOST_CHECK_EQUAL(toJS(balance), balanceString); BOOST_CHECK_EQUAL(toJS(balance), balanceString);
@ -230,21 +225,20 @@ BOOST_AUTO_TEST_CASE(jsonrpc_transact)
jsonrpcClient->transact(t); jsonrpcClient->transact(t);
jsonrpcServer->setAccounts({}); jsonrpcServer->setAccounts({});
dev::eth::mine(*(web3.ethereum()), 1); dev::eth::mine(*(web3->ethereum()), 1);
countAt = jsonrpcClient->countAt(toJS(address)); countAt = jsonrpcClient->countAt(toJS(address));
auto balance2 = web3.ethereum()->balanceAt(receiver.address()); auto balance2 = web3->ethereum()->balanceAt(receiver.address());
string balanceString2 = jsonrpcClient->balanceAt(toJS(receiver.address())); string balanceString2 = jsonrpcClient->balanceAt(toJS(receiver.address()));
BOOST_CHECK_EQUAL(countAt, (double)(uint64_t)web3.ethereum()->countAt(address)); BOOST_CHECK_EQUAL(countAt, (double)(uint64_t)web3->ethereum()->countAt(address));
BOOST_CHECK_EQUAL(countAt, 1); BOOST_CHECK_EQUAL(countAt, 1);
BOOST_CHECK_EQUAL(toJS(balance2), balanceString2); BOOST_CHECK_EQUAL(toJS(balance2), balanceString2);
BOOST_CHECK_EQUAL(jsToDecimal(balanceString2), "750000000000000000"); BOOST_CHECK_EQUAL(jsToDecimal(balanceString2), "750000000000000000");
BOOST_CHECK_EQUAL(txAmount, balance2); BOOST_CHECK_EQUAL(txAmount, balance2);
} }
} BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
#endif #endif

10
test/solidityParser.cpp

@ -211,7 +211,15 @@ BOOST_AUTO_TEST_CASE(else_if_statement)
BOOST_CHECK_NO_THROW(parseText(text)); BOOST_CHECK_NO_THROW(parseText(text));
} }
BOOST_AUTO_TEST_CASE(statement_starting_with_type_conversion)
{
char const* text = "contract test {\n"
" function fun() {\n"
" uint64(2);\n"
" }\n"
"}\n";
BOOST_CHECK_NO_THROW(parseText(text));
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

7
test/state.cpp

@ -65,12 +65,7 @@ int stateTest()
// Inject a transaction to transfer funds from miner to me. // Inject a transaction to transfer funds from miner to me.
bytes tx; bytes tx;
{ {
Transaction t; Transaction t(1000, 0, 0, me.address(), bytes(), s.transactionsFrom(myMiner.address()), myMiner.secret());
t.nonce = s.transactionsFrom(myMiner.address());
t.value = 1000; // 1e3 wei.
t.type = eth::Transaction::MessageCall;
t.receiveAddress = me.address();
t.sign(myMiner.secret());
assert(t.sender() == myMiner.address()); assert(t.sender() == myMiner.address());
tx = t.rlp(); tx = t.rlp();
} }

38
test/vm.cpp

@ -36,11 +36,7 @@ FakeExtVM::FakeExtVM(eth::BlockInfo const& _previousBlock, eth::BlockInfo const&
h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFunc const&) h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFunc const&)
{ {
Transaction t; Transaction t(_endowment, gasPrice, *_gas, _init.toBytes());
t.value = _endowment;
t.gasPrice = gasPrice;
t.gas = *_gas;
t.data = _init.toBytes();
m_s.noteSending(myAddress); m_s.noteSending(myAddress);
m_ms.internal.resize(m_ms.internal.size() + 1); m_ms.internal.resize(m_ms.internal.size() + 1);
@ -55,7 +51,6 @@ h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFun
get<3>(addresses[ret]) = m_s.code(ret); get<3>(addresses[ret]) = m_s.code(ret);
} }
t.type = eth::Transaction::ContractCreation;
callcreates.push_back(t); callcreates.push_back(t);
return ret; return ret;
} }
@ -64,13 +59,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data,
{ {
u256 contractgas = 0xffff; u256 contractgas = 0xffff;
Transaction t; Transaction t(_value, gasPrice, *_gas, _receiveAddress, _data.toVector());
t.value = _value;
t.gasPrice = gasPrice;
t.gas = *_gas;
t.data = _data.toVector();
t.type = eth::Transaction::MessageCall;
t.receiveAddress = _receiveAddress;
callcreates.push_back(t); callcreates.push_back(t);
string codeOf_CodeAddress = _codeAddressOverride ? toHex(get<3>(addresses[_codeAddressOverride])) : toHex(get<3>(addresses[_receiveAddress]) ); string codeOf_CodeAddress = _codeAddressOverride ? toHex(get<3>(addresses[_codeAddressOverride])) : toHex(get<3>(addresses[_receiveAddress]) );
@ -386,10 +375,10 @@ mArray FakeExtVM::exportCallCreates()
for (Transaction const& tx: callcreates) for (Transaction const& tx: callcreates)
{ {
mObject o; mObject o;
o["destination"] = tx.type == Transaction::ContractCreation ? "" : toString(tx.receiveAddress); o["destination"] = tx.type() == Transaction::ContractCreation ? "" : toString(tx.receiveAddress());
push(o, "gasLimit", tx.gas); push(o, "gasLimit", tx.gas());
push(o, "value", tx.value); push(o, "value", tx.value());
o["data"] = "0x" + toHex(tx.data); o["data"] = "0x" + toHex(tx.data());
ret.push_back(o); ret.push_back(o);
} }
return ret; return ret;
@ -404,19 +393,18 @@ void FakeExtVM::importCallCreates(mArray& _callcreates)
BOOST_REQUIRE(tx.count("value") > 0); BOOST_REQUIRE(tx.count("value") > 0);
BOOST_REQUIRE(tx.count("destination") > 0); BOOST_REQUIRE(tx.count("destination") > 0);
BOOST_REQUIRE(tx.count("gasLimit") > 0); BOOST_REQUIRE(tx.count("gasLimit") > 0);
Transaction t; bytes data;
t.type = tx["destination"].get_str().empty() ? Transaction::ContractCreation : Transaction::MessageCall;
t.receiveAddress = Address(tx["destination"].get_str());
t.value = toInt(tx["value"]);
t.gas = toInt(tx["gasLimit"]);
if (tx["data"].type() == str_type) if (tx["data"].type() == str_type)
if (tx["data"].get_str().find_first_of("0x") == 0) if (tx["data"].get_str().find_first_of("0x") == 0)
t.data = fromHex(tx["data"].get_str().substr(2)); data = fromHex(tx["data"].get_str().substr(2));
else else
t.data = fromHex(tx["data"].get_str()); data = fromHex(tx["data"].get_str());
else else
for (auto const& j: tx["data"].get_array()) for (auto const& j: tx["data"].get_array())
t.data.push_back(toByte(j)); data.push_back(toByte(j));
Transaction t = tx["destination"].get_str().empty() ?
Transaction(toInt(tx["value"]), 0, toInt(tx["gasLimit"]), data) :
Transaction(toInt(tx["value"]), 0, toInt(tx["gasLimit"]), Address(tx["destination"].get_str()), data);
callcreates.push_back(t); callcreates.push_back(t);
} }
} }

Loading…
Cancel
Save