From 1d16e1556fc4ffe0c57c1781fc77aa3ac236f64a Mon Sep 17 00:00:00 2001
From: Gav Wood
Date: Tue, 4 Nov 2014 18:11:06 +0000
Subject: [PATCH 1/3] Ready for move to log entries in JS API.
---
libdevcore/FixedHash.h | 5 ++
libdevcrypto/Common.h | 3 +
libdevcrypto/SHA3.h | 3 +
libethereum/MessageFilter.cpp | 55 ++++++++++++++++
libethereum/MessageFilter.h | 34 ++++++++++
libethereum/State.cpp | 3 +-
libevm/ExtVMFace.h | 20 ++++--
libweb3jsonrpc/WebThreeStubServer.cpp | 71 ++++++++++++++++++---
libweb3jsonrpc/WebThreeStubServer.h | 4 +-
libweb3jsonrpc/abstractwebthreestubserver.h | 7 --
libweb3jsonrpc/spec.json | 1 -
11 files changed, 181 insertions(+), 25 deletions(-)
diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h
index 02d199f62..2353a100c 100644
--- a/libdevcore/FixedHash.h
+++ b/libdevcore/FixedHash.h
@@ -163,6 +163,11 @@ public:
return (*this |= _h.template nbloom
());
}
+ template inline bool containsBloom(FixedHash const& _h)
+ {
+ return contains(_h.template nbloom());
+ }
+
template inline FixedHash nbloom() const
{
static const unsigned c_bloomBits = M * 8;
diff --git a/libdevcrypto/Common.h b/libdevcrypto/Common.h
index 7f2a8192e..4b4d34d87 100644
--- a/libdevcrypto/Common.h
+++ b/libdevcrypto/Common.h
@@ -50,6 +50,9 @@ using Address = h160;
/// A vector of Ethereum addresses.
using Addresses = h160s;
+/// A vector of Ethereum addresses.
+using AddressSet = std::set;
+
/// A vector of secrets.
using Secrets = h256s;
diff --git a/libdevcrypto/SHA3.h b/libdevcrypto/SHA3.h
index 1575ab29c..7aa4db246 100644
--- a/libdevcrypto/SHA3.h
+++ b/libdevcrypto/SHA3.h
@@ -56,6 +56,9 @@ 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.
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 inline h256 sha3(FixedHash const& _input) { return sha3(_input.ref()); }
+
extern h256 EmptySHA3;
extern h256 EmptyListSHA3;
diff --git a/libethereum/MessageFilter.cpp b/libethereum/MessageFilter.cpp
index fc6af1308..88f1a24f9 100644
--- a/libethereum/MessageFilter.cpp
+++ b/libethereum/MessageFilter.cpp
@@ -149,3 +149,58 @@ bool MessageFilter::matches(Manifest const& _m, vector _p, Address _o,
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;
+}
diff --git a/libethereum/MessageFilter.h b/libethereum/MessageFilter.h
index 83cbb7237..5602d7a17 100644
--- a/libethereum/MessageFilter.h
+++ b/libethereum/MessageFilter.h
@@ -25,6 +25,7 @@
#include
#include
#include "PastMessage.h"
+#include "TransactionReceipt.h"
namespace dev
{
@@ -72,5 +73,38 @@ private:
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;
+};
+
}
}
diff --git a/libethereum/State.cpp b/libethereum/State.cpp
index 51f5901c5..cd1a7f541 100644
--- a/libethereum/State.cpp
+++ b/libethereum/State.cpp
@@ -791,7 +791,8 @@ h256 State::oldBloom() const
LogBloom State::logBloom() const
{
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)
ret |= i.bloom();
return ret;
diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h
index 1b1ae7455..9f662087c 100644
--- a/libevm/ExtVMFace.h
+++ b/libevm/ExtVMFace.h
@@ -36,27 +36,35 @@ namespace dev
namespace eth
{
+template inline std::set toSet(std::vector const& _ts)
+{
+ std::set ret;
+ for (auto const& t: _ts)
+ ret.insert(t);
+ return ret;
+}
+
using LogBloom = h512;
struct LogEntry
{
LogEntry() {}
- LogEntry(RLP const& _r) { from = (Address)_r[0]; topics = (h256s)_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(RLP const& _r) { address = (Address)_r[0]; topics = (h256Set)_r[1]; data = (bytes)_r[2]; }
+ 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 ret;
- ret.shiftBloom<3, 32>(sha3(from.ref()));
+ ret.shiftBloom<3, 32>(sha3(address.ref()));
for (auto t: topics)
ret.shiftBloom<3, 32>(sha3(t.ref()));
return ret;
}
- Address from;
- h256s topics;
+ Address address;
+ h256Set topics;
bytes data;
};
diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp
index e7eb62e04..4ac048ee9 100644
--- a/libweb3jsonrpc/WebThreeStubServer.cpp
+++ b/libweb3jsonrpc/WebThreeStubServer.cpp
@@ -97,6 +97,24 @@ static Json::Value toJson(dev::eth::Transaction const& _t)
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)
+{
+ Json::Value res;
+ for (dev::eth::LogEntry const& e: _es)
+ res.append(toJson(e));
+ return res;
+}
+
static dev::eth::MessageFilter toMessageFilter(Json::Value const& _json)
{
dev::eth::MessageFilter filter;
@@ -123,9 +141,9 @@ static dev::eth::MessageFilter toMessageFilter(Json::Value const& _json)
{
if (_json["to"].isArray())
for (auto i : _json["to"])
- filter.from(jsToAddress(i.asString()));
+ filter.to(jsToAddress(i.asString()));
else
- filter.from(jsToAddress(_json["to"].asString()));
+ filter.to(jsToAddress(_json["to"].asString()));
}
if (!_json["altered"].empty())
{
@@ -143,6 +161,48 @@ static dev::eth::MessageFilter toMessageFilter(Json::Value const& _json)
return filter;
}
+static dev::eth::LogFilter toLogFilter(Json::Value const& _json)
+{
+ 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)
{
shh::Message ret;
@@ -252,13 +312,6 @@ std::shared_ptr WebThreeStubServer::face() const
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 ret(Json::arrayValue);
diff --git a/libweb3jsonrpc/WebThreeStubServer.h b/libweb3jsonrpc/WebThreeStubServer.h
index b18faf95a..33163b75e 100644
--- a/libweb3jsonrpc/WebThreeStubServer.h
+++ b/libweb3jsonrpc/WebThreeStubServer.h
@@ -56,13 +56,14 @@ class Interface;
* @brief JSON-RPC api implementation
* @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
+ * @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
{
public:
WebThreeStubServer(jsonrpc::AbstractServerConnector* _conn, dev::WebThreeDirect& _web3, std::vector const& _accounts);
- virtual std::string account();
virtual Json::Value accounts();
virtual std::string addToGroup(std::string const& _group, std::string const& _who);
virtual std::string balanceAt(std::string const& _address);
@@ -109,6 +110,7 @@ public:
void setAccounts(std::vector const& _accounts);
void setIdentities(std::vector const& _ids);
std::map const& ids() const { return m_ids; }
+
private:
dev::eth::Interface* client() const;
std::shared_ptr face() const;
diff --git a/libweb3jsonrpc/abstractwebthreestubserver.h b/libweb3jsonrpc/abstractwebthreestubserver.h
index ac6893933..66b9ff77d 100644
--- a/libweb3jsonrpc/abstractwebthreestubserver.h
+++ b/libweb3jsonrpc/abstractwebthreestubserver.h
@@ -13,7 +13,6 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer(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("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);
@@ -59,11 +58,6 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServeraccount();
- }
-
inline virtual void accountsI(const Json::Value& request, Json::Value& response)
{
response = this->accounts();
@@ -275,7 +269,6 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer
Date: Wed, 5 Nov 2014 13:45:19 +0000
Subject: [PATCH 2/3] Classify Transaction.
---
alethzero/MainWin.cpp | 91 +++++++++++++--------------
libethereum/Client.cpp | 42 ++++---------
libethereum/Executive.cpp | 42 ++++++-------
libethereum/MessageFilter.cpp | 2 +-
libethereum/State.cpp | 6 +-
libethereum/Transaction.cpp | 30 ++++-----
libethereum/Transaction.h | 53 +++++++++-------
libweb3jsonrpc/WebThreeStubServer.cpp | 16 ++---
neth/main.cpp | 32 +++++-----
test/crypto.cpp | 14 +----
test/state.cpp | 7 +--
test/vm.cpp | 38 ++++-------
12 files changed, 167 insertions(+), 206 deletions(-)
diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index f413532b7..18270ff8c 100644
--- a/alethzero/MainWin.cpp
+++ b/alethzero/MainWin.cpp
@@ -868,18 +868,18 @@ void Main::refreshPending()
ui->transactionQueue->clear();
for (Transaction const& t: ethereum()->pending())
{
- QString s = t.receiveAddress ?
+ QString s = t.receiveAddress() ?
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.receiveAddress))
- .arg((unsigned)t.nonce)
- .arg(ethereum()->codeAt(t.receiveAddress).size() ? '*' : '-') :
+ .arg(render(t.receiveAddress()))
+ .arg((unsigned)t.nonce())
+ .arg(ethereum()->codeAt(t.receiveAddress()).size() ? '*' : '-') :
QString("%2 +> %3: %1 [%4]")
- .arg(formatBalance(t.value).c_str())
+ .arg(formatBalance(t.value()).c_str())
.arg(render(t.safeSender()))
- .arg(render(right160(sha3(rlpList(t.safeSender(), t.nonce)))))
- .arg((unsigned)t.nonce);
+ .arg(render(right160(sha3(rlpList(t.safeSender(), t.nonce())))))
+ .arg((unsigned)t.nonce());
ui->transactionQueue->addItem(s);
}
}
@@ -946,7 +946,7 @@ static bool blockMatch(string const& _f, dev::eth::BlockDetails const& _b, h256
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)
return true;
return false;
@@ -986,18 +986,18 @@ void Main::refreshBlockChain()
Transaction t(i.data());
if (bm || transactionMatch(filter, t))
{
- QString s = t.receiveAddress ?
+ QString s = t.receiveAddress() ?
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.receiveAddress))
- .arg((unsigned)t.nonce)
- .arg(ethereum()->codeAt(t.receiveAddress).size() ? '*' : '-') :
+ .arg(render(t.receiveAddress()))
+ .arg((unsigned)t.nonce())
+ .arg(ethereum()->codeAt(t.receiveAddress()).size() ? '*' : '-') :
QString(" %2 +> %3: %1 [%4]")
- .arg(formatBalance(t.value).c_str())
+ .arg(formatBalance(t.value()).c_str())
.arg(render(t.safeSender()))
- .arg(render(right160(sha3(rlpList(t.safeSender(), t.nonce)))))
- .arg((unsigned)t.nonce);
+ .arg(render(right160(sha3(rlpList(t.safeSender(), t.nonce())))))
+ .arg((unsigned)t.nonce());
QListWidgetItem* txItem = new QListWidgetItem(s, ui->blocks);
auto hba = QByteArray((char const*)h.data(), h.size);
txItem->setData(Qt::UserRole, hba);
@@ -1144,26 +1144,26 @@ void Main::on_transactionQueue_currentItemChanged()
{
Transaction tx(ethereum()->pending()[i]);
auto ss = tx.safeSender();
- h256 th = sha3(rlpList(ss, tx.nonce));
+ h256 th = sha3(rlpList(ss, tx.nonce()));
s << "" << th << "
";
s << "From: " << pretty(ss).toStdString() << " " << ss;
if (tx.isCreation())
s << "
Creates: " << pretty(right160(th)).toStdString() << " " << right160(th);
else
- s << "
To: " << pretty(tx.receiveAddress).toStdString() << " " << tx.receiveAddress;
- s << "
Value: " << formatBalance(tx.value) << "";
- s << " #" << tx.nonce << "";
- s << "
Gas price: " << formatBalance(tx.gasPrice) << "";
- s << "
Gas: " << tx.gas << "";
+ s << "
To: " << pretty(tx.receiveAddress()).toStdString() << " " << tx.receiveAddress();
+ s << "
Value: " << formatBalance(tx.value()) << "";
+ s << " #" << tx.nonce() << "";
+ s << "
Gas price: " << formatBalance(tx.gasPrice()) << "";
+ s << "
Gas: " << tx.gas() << "";
if (tx.isCreation())
{
- if (tx.data.size())
- s << "Code
" << disassemble(tx.data);
+ if (tx.data().size())
+ s << "Code
" << disassemble(tx.data());
}
else
{
- if (tx.data.size())
- s << dev::memDump(tx.data, 16, true);
+ if (tx.data().size())
+ s << dev::memDump(tx.data(), 16, true);
}
s << "
";
@@ -1251,31 +1251,31 @@ void Main::on_blocks_currentItemChanged()
unsigned txi = item->data(Qt::UserRole + 1).toInt();
Transaction tx(block[1][txi].data());
auto ss = tx.safeSender();
- h256 th = sha3(rlpList(ss, tx.nonce));
+ h256 th = sha3(rlpList(ss, tx.nonce()));
s << "" << th << "
";
s << "" << h << "[" << txi << "]
";
s << "
From: " << pretty(ss).toHtmlEscaped().toStdString() << " " << ss;
if (tx.isCreation())
s << "
Creates: " << pretty(right160(th)).toHtmlEscaped().toStdString() << " " << right160(th);
else
- s << "
To: " << pretty(tx.receiveAddress).toHtmlEscaped().toStdString() << " " << tx.receiveAddress;
- s << "
Value: " << formatBalance(tx.value) << "";
- s << " #" << tx.nonce << "";
- s << "
Gas price: " << formatBalance(tx.gasPrice) << "";
- s << "
Gas: " << tx.gas << "";
- s << "
V: " << hex << nouppercase << (int)tx.vrs.v << "";
- s << "
R: " << hex << nouppercase << tx.vrs.r << "";
- s << "
S: " << hex << nouppercase << tx.vrs.s << "";
+ s << "
To: " << pretty(tx.receiveAddress()).toHtmlEscaped().toStdString() << " " << tx.receiveAddress();
+ s << "
Value: " << formatBalance(tx.value()) << "";
+ s << " #" << tx.nonce() << "";
+ s << "
Gas price: " << formatBalance(tx.gasPrice()) << "";
+ s << "
Gas: " << tx.gas() << "";
+ s << "
V: " << hex << nouppercase << (int)tx.signature().v << "";
+ s << "
R: " << hex << nouppercase << tx.signature().r << "";
+ s << "
S: " << hex << nouppercase << tx.signature().s << "";
s << "
Msg: " << tx.sha3(false) << "";
if (tx.isCreation())
{
- if (tx.data.size())
- s << "Code
" << disassemble(tx.data);
+ if (tx.data().size())
+ s << "Code
" << disassemble(tx.data());
}
else
{
- if (tx.data.size())
- s << dev::memDump(tx.data, 16, true);
+ if (tx.data().size())
+ s << dev::memDump(tx.data(), 16, true);
}
s << renderDiff(ethereum()->diff(txi, h));
ui->debugCurrent->setEnabled(true);
@@ -1786,14 +1786,9 @@ void Main::on_debug_clicked()
Secret s = i.secret();
m_executiveState = ethereum()->postState();
m_currentExecution = unique_ptr(new Executive(m_executiveState));
- Transaction t;
- t.nonce = m_executiveState.transactionsFrom(dev::toAddress(s));
- t.value = value();
- t.gasPrice = gasPrice();
- t.gas = ui->gas->value();
- t.data = m_data;
- t.receiveAddress = isCreation() ? Address() : fromString(ui->destination->currentText());
- t.sign(s);
+ Transaction t = isCreation() ?
+ Transaction(value(), gasPrice(), ui->gas->value(), m_data, m_executiveState.transactionsFrom(dev::toAddress(s)), s) :
+ Transaction(value(), gasPrice(), ui->gas->value(), fromString(ui->destination->currentText()), m_data, m_executiveState.transactionsFrom(dev::toAddress(s)), s);
auto r = t.rlp();
populateDebugger(&r);
m_currentExecution.reset();
diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp
index 63e093b17..d87e9c33e 100644
--- a/libethereum/Client.cpp
+++ b/libethereum/Client.cpp
@@ -316,19 +316,13 @@ void Client::transact(Secret _secret, u256 _value, Address _dest, bytes const& _
{
startWorking();
- Transaction t;
-// cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret));
+ u256 n;
{
ReadGuard l(x_stateDB);
- t.nonce = m_postMine.transactionsFrom(toAddress(_secret));
+ n = m_postMine.transactionsFrom(toAddress(_secret));
}
- t.value = _value;
- t.gasPrice = _gasPrice;
- t.gas = _gas;
- t.type = Transaction::MessageCall;
- t.receiveAddress = _dest;
- t.data = _data;
- t.sign(_secret);
+ Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret);
+// cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret));
cnote << "New transaction " << t;
m_tq.attemptImport(t.rlp());
}
@@ -338,22 +332,16 @@ bytes Client::call(Secret _secret, u256 _value, Address _dest, bytes const& _dat
bytes out;
try
{
+ u256 n;
State temp;
- Transaction t;
// cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret));
{
ReadGuard l(x_stateDB);
temp = m_postMine;
- t.nonce = temp.transactionsFrom(toAddress(_secret));
+ n = temp.transactionsFrom(toAddress(_secret));
}
- t.value = _value;
- t.gasPrice = _gasPrice;
- t.gas = _gas;
- t.type = Transaction::ContractCreation;
- t.receiveAddress = _dest;
- t.data = _data;
- t.sign(_secret);
- u256 gasUsed = temp.execute(t.data, &out, false);
+ Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret);
+ u256 gasUsed = temp.execute(t.data(), &out, false);
(void)gasUsed; // TODO: do something with gasused which it returns.
}
catch (...)
@@ -367,21 +355,15 @@ Address Client::transact(Secret _secret, u256 _endowment, bytes const& _init, u2
{
startWorking();
- Transaction t;
+ u256 n;
{
ReadGuard l(x_stateDB);
- t.nonce = m_postMine.transactionsFrom(toAddress(_secret));
+ n = m_postMine.transactionsFrom(toAddress(_secret));
}
- t.value = _endowment;
- t.gasPrice = _gasPrice;
- t.gas = _gas;
- t.type = Transaction::ContractCreation;
- t.receiveAddress = Address();
- t.data = _init;
- t.sign(_secret);
+ Transaction t(_endowment, _gasPrice, _gas, _init, n, _secret);
cnote << "New transaction " << t;
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)
diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp
index 885ab5535..e14401972 100644
--- a/libethereum/Executive.cpp
+++ b/libethereum/Executive.cpp
@@ -40,7 +40,7 @@ Executive::~Executive()
u256 Executive::gasUsed() const
{
- return m_t.gas - m_endGas;
+ return m_t.gas() - m_endGas;
}
bool Executive::setup(bytesConstRef _rlp)
@@ -52,29 +52,29 @@ bool Executive::setup(bytesConstRef _rlp)
// Avoid invalid transactions.
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;
- BOOST_THROW_EXCEPTION(InvalidNonce(nonceReq, m_t.nonce));
+ clog(StateDetail) << "Invalid Nonce: Require" << nonceReq << " Got" << 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.
- 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());
}
// 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());
}
- 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.
if (m_s.balance(m_sender) < cost)
@@ -84,9 +84,9 @@ bool Executive::setup(bytesConstRef _rlp)
}
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());
}
@@ -94,21 +94,21 @@ bool Executive::setup(bytesConstRef _rlp)
m_s.noteSending(m_sender);
// 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);
if (m_ms)
{
m_ms->from = m_sender;
- m_ms->to = m_t.receiveAddress;
- m_ms->value = m_t.value;
- m_ms->input = m_t.data;
+ m_ms->to = m_t.receiveAddress();
+ m_ms->value = m_t.value();
+ m_ms->input = m_t.data();
}
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
- 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)
@@ -177,7 +177,7 @@ bool Executive::go(OnOpFunc const& _onOp)
{
m_out = m_vm->go(*m_ext, _onOp);
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();
}
catch (StepsDone const&)
@@ -234,9 +234,9 @@ void Executive::finalize(OnOpFunc const&)
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) << ")";
- 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.";
m_s.addBalance(m_s.m_currentBlock.coinbaseAddress, feesEarned);
diff --git a/libethereum/MessageFilter.cpp b/libethereum/MessageFilter.cpp
index 88f1a24f9..b04d213f9 100644
--- a/libethereum/MessageFilter.cpp
+++ b/libethereum/MessageFilter.cpp
@@ -79,7 +79,7 @@ bool MessageFilter::matches(State const& _s, unsigned _i) const
return false;
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;
if (!m_from.empty() && !m_from.count(t.sender()))
return false;
diff --git a/libethereum/State.cpp b/libethereum/State.cpp
index cd1a7f541..c059922d5 100644
--- a/libethereum/State.cpp
+++ b/libethereum/State.cpp
@@ -520,7 +520,7 @@ bool State::cull(TransactionQueue& _tq) const
try
{
Transaction t(i.second);
- if (t.nonce <= transactionsFrom(t.sender()))
+ if (t.nonce() <= transactionsFrom(t.sender()))
{
_tq.drop(i.first);
ret = true;
@@ -1154,10 +1154,10 @@ u256 State::execute(bytesConstRef _rlp, bytes* o_output, bool _commit)
paranoia("after execution commit.", true);
- if (e.t().receiveAddress)
+ if (e.t().receiveAddress())
{
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";
BOOST_THROW_EXCEPTION(InvalidTrie());
diff --git a/libethereum/Transaction.cpp b/libethereum/Transaction.cpp
index bdc8bf34d..c65421e04 100644
--- a/libethereum/Transaction.cpp
+++ b/libethereum/Transaction.cpp
@@ -36,14 +36,14 @@ Transaction::Transaction(bytesConstRef _rlpData, bool _checkSender)
RLP rlp(_rlpData);
try
{
- nonce = rlp[field = 0].toInt();
- gasPrice = rlp[field = 1].toInt();
- gas = rlp[field = 2].toInt();
- type = rlp[field = 3].isEmpty() ? ContractCreation : MessageCall;
- receiveAddress = rlp[field = 3].toHash();
- value = rlp[field = 4].toInt();
- data = rlp[field = 5].toBytes();
- vrs = SignatureStruct{ rlp[field = 7].toInt(), rlp[field = 8].toInt(), byte(rlp[field = 6].toInt() - 27) };
+ m_nonce = rlp[field = 0].toInt();
+ m_gasPrice = rlp[field = 1].toInt();
+ m_gas = rlp[field = 2].toInt();
+ m_type = rlp[field = 3].isEmpty() ? ContractCreation : MessageCall;
+ m_receiveAddress = rlp[field = 3].toHash();
+ m_value = rlp[field = 4].toInt();
+ m_data = rlp[field = 5].toBytes();
+ m_vrs = SignatureStruct{ rlp[field = 7].toInt(), rlp[field = 8].toInt(), byte(rlp[field = 6].toInt() - 27) };
if (_checkSender)
m_sender = sender();
}
@@ -71,7 +71,7 @@ Address Transaction::sender() const
{
if (!m_sender)
{
- auto p = recover(*(Signature const*)&vrs, sha3(false));
+ auto p = recover(*(Signature const*)&m_vrs, sha3(false));
if (!p)
BOOST_THROW_EXCEPTION(InvalidSignature());
m_sender = right160(dev::sha3(bytesConstRef(p.data(), sizeof(p))));
@@ -82,18 +82,18 @@ Address Transaction::sender() const
void Transaction::sign(Secret _priv)
{
auto sig = dev::sign(_priv, sha3(false));
- vrs = *(SignatureStruct const*)&sig;
+ m_vrs = *(SignatureStruct const*)&sig;
}
void Transaction::streamRLP(RLPStream& _s, bool _sig) const
{
_s.appendList((_sig ? 3 : 0) + 6);
- _s << nonce << gasPrice << gas;
- if (type == MessageCall)
- _s << receiveAddress;
+ _s << m_nonce << m_gasPrice << m_gas;
+ if (m_type == MessageCall)
+ _s << m_receiveAddress;
else
_s << "";
- _s << value << data;
+ _s << m_value << m_data;
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;
}
diff --git a/libethereum/Transaction.h b/libethereum/Transaction.h
index 2492e32bc..bb04bcab7 100644
--- a/libethereum/Transaction.h
+++ b/libethereum/Transaction.h
@@ -30,47 +30,59 @@ namespace dev
namespace eth
{
-struct Transaction
+class Transaction
{
+public:
enum Type
{
+ NullTransaction,
ContractCreation,
MessageCall
};
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(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); }
- Type type; ///< True if this is a contract-creation transaction. F
- 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).
void sign(Secret _priv); ///< Sign the transaction.
- bool isCreation() const { return !receiveAddress; }
-
- static h256 kFromMessage(h256 _msg, h256 _priv);
+ bool isCreation() const { return !m_receiveAddress; }
void streamRLP(RLPStream& _s, bool _sig = true) const;
+
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)); }
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()); }
+ 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:
+ 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;
};
@@ -79,19 +91,18 @@ using Transactions = std::vector;
inline std::ostream& operator<<(std::ostream& _out, Transaction const& _t)
{
_out << "{";
- if (_t.receiveAddress)
- _out << _t.receiveAddress.abridged();
+ if (_t.receiveAddress())
+ _out << _t.receiveAddress().abridged();
else
_out << "[CREATE]";
- _out << "/" << _t.nonce << "$" << _t.value << "+" << _t.gas << "@" << _t.gasPrice;
- Address s;
+ _out << "/" << _t.nonce() << "$" << _t.value() << "+" << _t.gas() << "@" << _t.gasPrice();
try
{
_out << "<-" << _t.sender().abridged();
}
catch (...) {}
- _out << " #" << _t.data.size() << "}";
+ _out << " #" << _t.data().size() << "}";
return _out;
}
diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp
index 4ac048ee9..89d45f4e0 100644
--- a/libweb3jsonrpc/WebThreeStubServer.cpp
+++ b/libweb3jsonrpc/WebThreeStubServer.cpp
@@ -87,13 +87,13 @@ static Json::Value toJson(dev::eth::Transaction const& _t)
{
Json::Value res;
res["hash"] = toJS(_t.sha3());
- res["input"] = jsFromBinary(_t.data);
- res["to"] = toJS(_t.receiveAddress);
+ res["input"] = jsFromBinary(_t.data());
+ res["to"] = toJS(_t.receiveAddress());
res["from"] = toJS(_t.sender());
- res["gas"] = (int)_t.gas;
- res["gasPrice"] = toJS(_t.gasPrice);
- res["nonce"] = toJS(_t.nonce);
- res["value"] = toJS(_t.value);
+ res["gas"] = (int)_t.gas();
+ res["gasPrice"] = toJS(_t.gasPrice());
+ res["nonce"] = toJS(_t.nonce());
+ res["value"] = toJS(_t.value());
return res;
}
@@ -107,7 +107,7 @@ static Json::Value toJson(dev::eth::LogEntry const& _e)
return res;
}
-static Json::Value toJson(dev::eth::LogEntries const& _es)
+/*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)
@@ -161,7 +161,7 @@ static dev::eth::MessageFilter toMessageFilter(Json::Value const& _json)
return filter;
}
-static dev::eth::LogFilter toLogFilter(Json::Value const& _json)
+/*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())
diff --git a/neth/main.cpp b/neth/main.cpp
index 4e3a0f40a..06e22f963 100644
--- a/neth/main.cpp
+++ b/neth/main.cpp
@@ -843,18 +843,18 @@ int main(int argc, char** argv)
for (auto const& i: RLP(b)[1])
{
Transaction t(i[0].data());
- auto s = t.receiveAddress ?
+ auto s = t.receiveAddress() ?
boost::format(" %1% %2%> %3%: %4% [%5%]") %
toString(t.safeSender()) %
- (c.codeAt(t.receiveAddress, 0).size() ? '*' : '-') %
- toString(t.receiveAddress) %
- toString(formatBalance(t.value)) %
- toString((unsigned)t.nonce) :
+ (c.codeAt(t.receiveAddress(), 0).size() ? '*' : '-') %
+ toString(t.receiveAddress()) %
+ toString(formatBalance(t.value())) %
+ toString((unsigned)t.nonce()) :
boost::format(" %1% +> %2%: %3% [%4%]") %
toString(t.safeSender()) %
- toString(right160(sha3(rlpList(t.safeSender(), t.nonce)))) %
- toString(formatBalance(t.value)) %
- toString((unsigned)t.nonce);
+ toString(right160(sha3(rlpList(t.safeSender(), t.nonce())))) %
+ toString(formatBalance(t.value())) %
+ toString((unsigned)t.nonce());
mvwaddnstr(blockswin, y++, x, s.str().c_str(), qwidth - 2);
if (y > qheight - 2)
break;
@@ -868,18 +868,18 @@ int main(int argc, char** argv)
y = 1;
for (Transaction const& t: c.pending())
{
- auto s = t.receiveAddress ?
+ auto s = t.receiveAddress() ?
boost::format("%1% %2%> %3%: %4% [%5%]") %
toString(t.safeSender()) %
- (c.codeAt(t.receiveAddress, 0).size() ? '*' : '-') %
- toString(t.receiveAddress) %
- toString(formatBalance(t.value)) %
- toString((unsigned)t.nonce) :
+ (c.codeAt(t.receiveAddress(), 0).size() ? '*' : '-') %
+ toString(t.receiveAddress()) %
+ toString(formatBalance(t.value())) %
+ toString((unsigned)t.nonce()) :
boost::format("%1% +> %2%: %3% [%4%]") %
toString(t.safeSender()) %
- toString(right160(sha3(rlpList(t.safeSender(), t.nonce)))) %
- toString(formatBalance(t.value)) %
- toString((unsigned)t.nonce);
+ toString(right160(sha3(rlpList(t.safeSender(), t.nonce())))) %
+ toString(formatBalance(t.value())) %
+ toString((unsigned)t.nonce());
mvwaddnstr(pendingwin, y++, x, s.str().c_str(), qwidth);
if (y > height * 1 / 5 - 4)
break;
diff --git a/test/crypto.cpp b/test/crypto.cpp
index 67286bfca..2f5314421 100644
--- a/test/crypto.cpp
+++ b/test/crypto.cpp
@@ -339,16 +339,11 @@ BOOST_AUTO_TEST_CASE(eth_keypairs)
BOOST_REQUIRE(p.pub() == Public(fromHex("97466f2b32bc3bb76d4741ae51cd1d8578b48d3f1e68da206d47321aec267ce78549b514e4453d74ef11b0cd5e4e4c364effddac8b51bcfc8de80682f952896f")));
BOOST_REQUIRE(p.address() == Address(fromHex("8a40bfaa73256b60764c1bf40675a99083efb075")));
{
- eth::Transaction t;
- t.nonce = 0;
- t.type = eth::Transaction::MessageCall;
- t.receiveAddress = h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b"));
- t.value = 1000;
+ eth::Transaction t(1000, 0, 0, h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b")), bytes(), 0, p.secret());
auto rlp = t.rlp(false);
cnote << RLP(rlp);
cnote << toHex(rlp);
cnote << t.sha3(false);
- t.sign(p.secret());
rlp = t.rlp(true);
cnote << RLP(rlp);
cnote << toHex(rlp);
@@ -368,16 +363,11 @@ int cryptoTest()
assert(p.pub() == Public(fromHex("97466f2b32bc3bb76d4741ae51cd1d8578b48d3f1e68da206d47321aec267ce78549b514e4453d74ef11b0cd5e4e4c364effddac8b51bcfc8de80682f952896f")));
assert(p.address() == Address(fromHex("8a40bfaa73256b60764c1bf40675a99083efb075")));
{
- eth::Transaction t;
- t.nonce = 0;
- t.type = eth::Transaction::MessageCall;
- t.receiveAddress = h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b"));
- t.value = 1000;
+ eth::Transaction t(1000, 0, 0, h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b")), bytes(), 0, p.secret());
auto rlp = t.rlp(false);
cnote << RLP(rlp);
cnote << toHex(rlp);
cnote << t.sha3(false);
- t.sign(p.secret());
rlp = t.rlp(true);
cnote << RLP(rlp);
cnote << toHex(rlp);
diff --git a/test/state.cpp b/test/state.cpp
index b0f279bac..921be5f95 100644
--- a/test/state.cpp
+++ b/test/state.cpp
@@ -65,12 +65,7 @@ int stateTest()
// Inject a transaction to transfer funds from miner to me.
bytes tx;
{
- Transaction t;
- t.nonce = s.transactionsFrom(myMiner.address());
- t.value = 1000; // 1e3 wei.
- t.type = eth::Transaction::MessageCall;
- t.receiveAddress = me.address();
- t.sign(myMiner.secret());
+ Transaction t(1000, 0, 0, me.address(), bytes(), s.transactionsFrom(myMiner.address()), myMiner.secret());
assert(t.sender() == myMiner.address());
tx = t.rlp();
}
diff --git a/test/vm.cpp b/test/vm.cpp
index 617cb95c7..8344c0c5f 100644
--- a/test/vm.cpp
+++ b/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&)
{
- Transaction t;
- t.value = _endowment;
- t.gasPrice = gasPrice;
- t.gas = *_gas;
- t.data = _init.toBytes();
+ Transaction t(_endowment, gasPrice, *_gas, _init.toBytes());
m_s.noteSending(myAddress);
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);
}
- t.type = eth::Transaction::ContractCreation;
callcreates.push_back(t);
return ret;
}
@@ -64,13 +59,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data,
{
u256 contractgas = 0xffff;
- Transaction t;
- t.value = _value;
- t.gasPrice = gasPrice;
- t.gas = *_gas;
- t.data = _data.toVector();
- t.type = eth::Transaction::MessageCall;
- t.receiveAddress = _receiveAddress;
+ Transaction t(_value, gasPrice, *_gas, _receiveAddress, _data.toVector());
callcreates.push_back(t);
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)
{
mObject o;
- o["destination"] = tx.type == Transaction::ContractCreation ? "" : toString(tx.receiveAddress);
- push(o, "gasLimit", tx.gas);
- push(o, "value", tx.value);
- o["data"] = "0x" + toHex(tx.data);
+ o["destination"] = tx.type() == Transaction::ContractCreation ? "" : toString(tx.receiveAddress());
+ push(o, "gasLimit", tx.gas());
+ push(o, "value", tx.value());
+ o["data"] = "0x" + toHex(tx.data());
ret.push_back(o);
}
return ret;
@@ -404,19 +393,18 @@ void FakeExtVM::importCallCreates(mArray& _callcreates)
BOOST_REQUIRE(tx.count("value") > 0);
BOOST_REQUIRE(tx.count("destination") > 0);
BOOST_REQUIRE(tx.count("gasLimit") > 0);
- Transaction t;
- 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"]);
+ bytes data;
if (tx["data"].type() == str_type)
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
- t.data = fromHex(tx["data"].get_str());
+ data = fromHex(tx["data"].get_str());
else
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);
}
}
From 3b6ffcbe8d091e607c19604e938a5574a870a816 Mon Sep 17 00:00:00 2001
From: Gav Wood
Date: Wed, 5 Nov 2014 14:10:10 +0000
Subject: [PATCH 3/3] Minor fixes to Transaction.
---
libethereum/Transaction.h | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/libethereum/Transaction.h b/libethereum/Transaction.h
index bb04bcab7..ba79f971c 100644
--- a/libethereum/Transaction.h
+++ b/libethereum/Transaction.h
@@ -51,11 +51,10 @@ public:
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); }
- Address safeSender() const noexcept; ///< Like sender() but will never throw.
+ Address safeSender() const noexcept; ///< Like sender() but will never throw. @returns a null Address if the signature is invalid.
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 !m_receiveAddress; }
+ bool isCreation() const { return m_type == ContractCreation; }
void streamRLP(RLPStream& _s, bool _sig = true) const;
@@ -74,6 +73,8 @@ public:
SignatureStruct const& signature() const { return m_vrs; }
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.