diff --git a/alethzero/DappLoader.cpp b/alethzero/DappLoader.cpp
index 6ac1afbcb..7c754f8f5 100644
--- a/alethzero/DappLoader.cpp
+++ b/alethzero/DappLoader.cpp
@@ -82,7 +82,7 @@ DappLocation DappLoader::resolveAppUri(QString const& _uri)
}
string32 urlHintName = ZeroString32;
- QByteArray utf8 = QString("UrlHint").toUtf8();
+ QByteArray utf8 = QString("urlhint").toUtf8();
std::copy(utf8.data(), utf8.data() + utf8.size(), urlHintName.data());
Address urlHint = abiOut
(web3()->ethereum()->call(m_nameReg, abiIn("addr(bytes32)", urlHintName)).output);
diff --git a/libdevcore/Common.h b/libdevcore/Common.h
index 49491d4cc..b2d48da98 100644
--- a/libdevcore/Common.h
+++ b/libdevcore/Common.h
@@ -52,6 +52,8 @@ using byte = uint8_t;
#define DEV_QUOTED_HELPER(s) #s
#define DEV_QUOTED(s) DEV_QUOTED_HELPER(s)
+#define DEV_IGNORE_EXCEPTIONS(X) try { X; } catch (...) {}
+
namespace dev
{
diff --git a/libethcore/EthashAux.cpp b/libethcore/EthashAux.cpp
index 19a96f550..9cb4d9fad 100644
--- a/libethcore/EthashAux.cpp
+++ b/libethcore/EthashAux.cpp
@@ -40,8 +40,6 @@ using namespace chrono;
using namespace dev;
using namespace eth;
-#define ETH_IGNORE_EXCEPTIONS(X) try { X; } catch (...) {}
-
EthashAux* dev::eth::EthashAux::s_this = nullptr;
EthashAux::~EthashAux()
@@ -171,8 +169,8 @@ EthashAux::FullType EthashAux::full(h256 const& _seedHash, bytesRef _dest, bool
boost::filesystem::rename(oldMemoFile, memoFile);
}
- ETH_IGNORE_EXCEPTIONS(boost::filesystem::remove(oldMemoFile));
- ETH_IGNORE_EXCEPTIONS(boost::filesystem::remove(oldMemoFile + ".info"));
+ DEV_IGNORE_EXCEPTIONS(boost::filesystem::remove(oldMemoFile));
+ DEV_IGNORE_EXCEPTIONS(boost::filesystem::remove(oldMemoFile + ".info"));
ethash_params p = params(_seedHash);
assert(!_dest || _dest.size() >= p.full_size); // must be big enough.
diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp
index cb51bcb87..bab8f9555 100644
--- a/libethereum/Client.cpp
+++ b/libethereum/Client.cpp
@@ -646,7 +646,7 @@ void Client::tick()
m_bq.tick(m_bc);
m_lastTick = chrono::system_clock::now();
if (m_report.ticks == 15)
- cnote << activityReport();
+ clog(ClientTrace) << activityReport();
}
}
diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp
index 7c56bce4e..eba8dbc67 100644
--- a/libethereum/ClientBase.cpp
+++ b/libethereum/ClientBase.cpp
@@ -48,8 +48,11 @@ State ClientBase::asOf(BlockNumber _h) const
void ClientBase::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice)
{
prepareForTransaction();
-
- u256 n = postMine().transactionsFrom(toAddress(_secret));
+
+ auto a = toAddress(_secret);
+ u256 n = postMine().transactionsFrom(a);
+ cdebug << "submitTx: " << a << "postMine=" << n << "; tq=" << m_tq.maxNonce(a);
+ n = max(n, m_tq.maxNonce(a));
Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret);
m_tq.import(t.rlp());
diff --git a/libethereum/Transaction.h b/libethereum/Transaction.h
index 7276493c2..09102e0ba 100644
--- a/libethereum/Transaction.h
+++ b/libethereum/Transaction.h
@@ -221,19 +221,14 @@ using Transactions = std::vector;
/// Simple human-readable stream-shift operator.
inline std::ostream& operator<<(std::ostream& _out, Transaction const& _t)
{
- _out << "{";
+ _out << _t.sha3().abridged() << "{";
if (_t.receiveAddress())
_out << _t.receiveAddress().abridged();
else
_out << "[CREATE]";
- _out << "/" << _t.nonce() << "$" << _t.value() << "+" << _t.gas() << "@" << _t.gasPrice();
- try
- {
- _out << "<-" << _t.sender().abridged();
- }
- catch (...) {}
- _out << " #" << _t.data().size() << "}";
+ _out << "/" << _t.data().size() << "$" << _t.value() << "+" << _t.gas() << "@" << _t.gasPrice();
+ _out << "<-" << _t.safeSender().abridged() << " #" << _t.nonce() << "}";
return _out;
}
diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp
index 40eec1ac5..57429d32c 100644
--- a/libethereum/TransactionQueue.cpp
+++ b/libethereum/TransactionQueue.cpp
@@ -53,7 +53,7 @@ ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, ImportCallb
UpgradeGuard ul(l);
// If valid, append to blocks.
- m_current[h] = t;
+ insertCurrent_WITH_LOCK(make_pair(h, t));
m_known.insert(h);
if (_cb)
m_callbacks[h] = _cb;
@@ -74,13 +74,54 @@ ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, ImportCallb
return ImportResult::Success;
}
+u256 TransactionQueue::maxNonce(Address const& _a) const
+{
+ cdebug << "txQ::maxNonce" << _a;
+ ReadGuard l(m_lock);
+ u256 ret = 0;
+ auto r = m_senders.equal_range(_a);
+ for (auto it = r.first; it != r.second; ++it)
+ {
+ cdebug << it->first << "1+" << m_current.at(it->second).nonce();
+ DEV_IGNORE_EXCEPTIONS(ret = max(ret, m_current.at(it->second).nonce() + 1));
+ }
+ return ret;
+}
+
+void TransactionQueue::insertCurrent_WITH_LOCK(std::pair const& _p)
+{
+ cdebug << "txQ::insertCurrent" << _p.first << _p.second.sender() << _p.second.nonce();
+ m_senders.insert(make_pair(_p.second.sender(), _p.first));
+ m_current.insert(_p);
+}
+
+bool TransactionQueue::removeCurrent_WITH_LOCK(h256 const& _txHash)
+{
+ cdebug << "txQ::removeCurrent" << _txHash;
+ if (m_current.count(_txHash))
+ {
+ auto r = m_senders.equal_range(m_current[_txHash].sender());
+ for (auto it = r.first; it != r.second; ++it)
+ if (it->second == _txHash)
+ {
+ cdebug << "=> sender" << it->first;
+ m_senders.erase(it);
+ break;
+ }
+ cdebug << "=> nonce" << m_current[_txHash].nonce();
+ m_current.erase(_txHash);
+ return true;
+ }
+ return false;
+}
+
void TransactionQueue::setFuture(std::pair const& _t)
{
WriteGuard l(m_lock);
if (m_current.count(_t.first))
{
- m_current.erase(_t.first);
m_unknown.insert(make_pair(_t.second.sender(), _t));
+ m_current.erase(_t.first);
}
}
@@ -104,9 +145,7 @@ void TransactionQueue::drop(h256 const& _txHash)
m_dropped.insert(_txHash);
m_known.erase(_txHash);
- if (m_current.count(_txHash))
- m_current.erase(_txHash);
- else
+ if (!removeCurrent_WITH_LOCK(_txHash))
{
for (auto i = m_unknown.begin(); i != m_unknown.end(); ++i)
if (i->second.first == _txHash)
diff --git a/libethereum/TransactionQueue.h b/libethereum/TransactionQueue.h
index 3858949cc..16bc34641 100644
--- a/libethereum/TransactionQueue.h
+++ b/libethereum/TransactionQueue.h
@@ -56,6 +56,7 @@ public:
std::map transactions() const { ReadGuard l(m_lock); return m_current; }
std::pair items() const { ReadGuard l(m_lock); return std::make_pair(m_current.size(), m_unknown.size()); }
+ u256 maxNonce(Address const& _a) const;
void setFuture(std::pair const& _t);
void noteGood(std::pair const& _t);
@@ -64,12 +65,16 @@ public:
template Handler onReady(T const& _t) { return m_onReady.add(_t); }
private:
- mutable SharedMutex m_lock; ///< General lock.
+ void insertCurrent_WITH_LOCK(std::pair const& _p);
+ bool removeCurrent_WITH_LOCK(h256 const& _txHash);
+
+ mutable SharedMutex m_lock; ///< General lock.
std::set m_known; ///< Hashes of transactions in both sets.
std::map m_current; ///< Map of SHA3(tx) to tx.
std::multimap> m_unknown; ///< For transactions that have a future nonce; we map their sender address to the tx stuff, and insert once the sender has a valid TX.
std::map> m_callbacks; ///< Called once.
std::set m_dropped; ///< Transactions that have previously been dropped.
+ std::multimap m_senders; ///< Mapping from the sender address to the transaction hash; useful for determining the nonce of a given sender.
Signal m_onReady; ///< Called when a subsequent call to import transactions will return a non-empty container. Be nice and exit fast.
};
diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp
index 208351fc6..2a1427b16 100644
--- a/libweb3jsonrpc/WebThreeStubServerBase.cpp
+++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp
@@ -505,7 +505,7 @@ string WebThreeStubServerBase::eth_sendTransaction(Json::Value const& _json)
if (!t.gasPrice)
t.gasPrice = 10 * dev::eth::szabo; // TODO: should be determined by user somehow.
if (!t.gas)
- t.gas = min(client()->gasLimitRemaining(), client()->balanceAt(t.from) / t.gasPrice);
+ t.gas = min(client()->gasLimitRemaining() / 5, client()->balanceAt(t.from) / t.gasPrice);
if (m_accounts->isRealAccount(t.from))
authenticate(t, false);
@@ -534,7 +534,7 @@ string WebThreeStubServerBase::eth_signTransaction(Json::Value const& _json)
if (!t.gasPrice)
t.gasPrice = 10 * dev::eth::szabo; // TODO: should be determined by user somehow.
if (!t.gas)
- t.gas = min(client()->gasLimitRemaining(), client()->balanceAt(t.from) / t.gasPrice);
+ t.gas = min(client()->gasLimitRemaining() / 5, client()->balanceAt(t.from) / t.gasPrice);
if (m_accounts->isRealAccount(t.from))
authenticate(t, false);
diff --git a/mix/qml/js/NetworkDeployment.js b/mix/qml/js/NetworkDeployment.js
index fa85ddc54..9bbed2415 100644
--- a/mix/qml/js/NetworkDeployment.js
+++ b/mix/qml/js/NetworkDeployment.js
@@ -219,7 +219,9 @@ function finalizeDeployment(deploymentId, addresses) {
function checkEthPath(dappUrl, callBack)
{
if (dappUrl.length === 1)
- registerContentHash(deploymentDialog.eth, callBack); // we directly create a dapp under the root registrar.
+ reserve(deploymentDialog.eth, function() {
+ registerContentHash(deploymentDialog.eth, callBack); // we directly create a dapp under the root registrar.
+ });
else
{
// the first owned registrar must have been created to follow the path.
@@ -310,7 +312,7 @@ function checkRegistration(dappUrl, addr, callBack)
requests.push({
jsonrpc: "2.0",
method: "eth_sendTransaction",
- params: [ { "from": deploymentDialog.currentAccount, "gas": 20000, "code": "0x600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317815561058990819061003990396000f3007c010000000000000000000000000000000000000000000000000000000060003504630198489281146100a757806302571be3146100d957806321f8a721146100e35780632dff6941146100ed5780633b3b57de1461010d5780635a3a05bd1461013d5780635fd4b08a1461017057806389a69c0e1461017c578063b5c645bd146101b0578063be99a9801461022c578063c3d014d614610264578063d93e75731461029857005b73ffffffffffffffffffffffffffffffffffffffff600435166000908152600160205260409020548060005260206000f35b6000808052602081f35b6000808052602081f35b600435600090815260026020819052604090912001548060005260206000f35b600435600090815260026020908152604082205473ffffffffffffffffffffffffffffffffffffffff1680835291f35b600435600090815260026020908152604082206001015473ffffffffffffffffffffffffffffffffffffffff1680835291f35b60008060005260206000f35b6000546102c89060043590602435903373ffffffffffffffffffffffffffffffffffffffff908116911614610451576104b1565b600435600090815260026020819052604090912080546001820154919092015473ffffffffffffffffffffffffffffffffffffffff9283169291909116908273ffffffffffffffffffffffffffffffffffffffff166000528173ffffffffffffffffffffffffffffffffffffffff166020528060405260606000f35b6000546102ce906004359060243590604435903373ffffffffffffffffffffffffffffffffffffffff9081169116146104b557610584565b6000546102d49060043590602435903373ffffffffffffffffffffffffffffffffffffffff9081169116146102e05761031d565b6000546102da90600435903373ffffffffffffffffffffffffffffffffffffffff9081169116146103215761044e565b60006000f35b60006000f35b60006000f35b60006000f35b600082815260026020819052604080832090910183905583917fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc91a25b5050565b60008181526002602090815260408083205473ffffffffffffffffffffffffffffffffffffffff1683526001909152902054811461035e576103de565b6000818152600260205260408082205473ffffffffffffffffffffffffffffffffffffffff169183917ff63780e752c6a54a94fc52715dbc5518a3b4c3c2833d301a204226548a2a85459190a360008181526002602090815260408083205473ffffffffffffffffffffffffffffffffffffffff16835260019091528120555b600081815260026020819052604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081168255600182018054909116905590910182905582917fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc91a25b50565b60008281526002602052604080822060010180547fffffffffffffffffffffffff0000000000000000000000000000000000000000168417905583917fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc91a25b5050565b600083815260026020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016831790558061051c57827fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc60006040a2610583565b73ffffffffffffffffffffffffffffffffffffffff8216837ff63780e752c6a54a94fc52715dbc5518a3b4c3c2833d301a204226548a2a854560006040a373ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604090208390555b5b50505056" } ],
+ params: [ { "from": deploymentDialog.currentAccount, "gas": 20000, "code": "0x600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317815561058990819061003990396000f3007c010000000000000000000000000000000000000000000000000000000060003504630198489281146100a757806302571be3146100d957806321f8a721146100e35780632dff6941146100ed5780633b3b57de1461010d5780635a3a05bd1461013d5780635fd4b08a1461017057806389a69c0e1461017c578063b5c645bd146101b0578063be99a9801461022c578063c3d014d614610264578063d93e75731461029857005b73ffffffffffffffffffffffffffffffffffffffff600435166000908152600160205260409020548060005260206000f35b6000808052602081f35b6000808052602081f35b600435600090815260026020819052604090912001548060005260206000f35b600435600090815260026020908152604082205473ffffffffffffffffffffffffffffffffffffffff1680835291f35b600435600090815260026020908152604082206001015473ffffffffffffffffffffffffffffffffffffffff1680835291f35b60008060005260206000f35b6000546102c89060043590602435903373ffffffffffffffffffffffffffffffffffffffff90811691161461052557610585565b600435600090815260026020819052604090912080546001820154919092015473ffffffffffffffffffffffffffffffffffffffff9283169291909116908273ffffffffffffffffffffffffffffffffffffffff166000528173ffffffffffffffffffffffffffffffffffffffff166020528060405260606000f35b6000546102ce906004359060243590604435903373ffffffffffffffffffffffffffffffffffffffff9081169116146102e0576103af565b6000546102d49060043590602435903373ffffffffffffffffffffffffffffffffffffffff9081169116146103b4576103f1565b6000546102da90600435903373ffffffffffffffffffffffffffffffffffffffff9081169116146103f557610522565b60006000f35b60006000f35b60006000f35b60006000f35b600083815260026020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016831790558061034757827fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc60006040a26103ae565b73ffffffffffffffffffffffffffffffffffffffff8216837ff63780e752c6a54a94fc52715dbc5518a3b4c3c2833d301a204226548a2a854560006040a373ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604090208390555b5b505050565b600082815260026020819052604080832090910183905583917fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc91a25b5050565b60008181526002602090815260408083205473ffffffffffffffffffffffffffffffffffffffff16835260019091529020548114610432576104b2565b6000818152600260205260408082205473ffffffffffffffffffffffffffffffffffffffff169183917ff63780e752c6a54a94fc52715dbc5518a3b4c3c2833d301a204226548a2a85459190a360008181526002602090815260408083205473ffffffffffffffffffffffffffffffffffffffff16835260019091528120555b600081815260026020819052604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081168255600182018054909116905590910182905582917fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc91a25b50565b60008281526002602052604080822060010180547fffffffffffffffffffffffff0000000000000000000000000000000000000000168417905583917fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc91a25b505056" } ],
id: jsonRpcRequestId++
});
@@ -353,6 +355,26 @@ function trCountIncrementTimeOut()
deploymentError(error);
}
+function reserve(registrar, callBack)
+{
+ var txt = qsTr("Making reservation in the root registrar...");
+ deploymentStepChanged(txt);
+ console.log(txt);
+ var requests = [];
+ var paramTitle = clientModel.encodeStringParam(projectModel.projectTitle);
+ requests.push({
+ //reserve()
+ jsonrpc: "2.0",
+ method: "eth_sendTransaction",
+ params: [ { "from": deploymentDialog.currentAccount, "gas": "0xfffff", "to": '0x' + registrar, "data": "0x432ced04" + paramTitle } ],
+ id: jsonRpcRequestId++
+ });
+ rpcCall(requests, function (httpRequest, response) {
+ callBack();
+ });
+}
+
+
function registerContentHash(registrar, callBack)
{
var txt = qsTr("Finalizing Dapp registration ...");
@@ -398,7 +420,7 @@ function registerToUrlHint()
function urlHintAddress(callBack)
{
var requests = [];
- var urlHint = clientModel.encodeStringParam("UrlHint");
+ var urlHint = clientModel.encodeStringParam("urlhint");
requests.push({
//registrar: get UrlHint addr
jsonrpc: "2.0",
diff --git a/mix/qml/js/TransactionHelper.js b/mix/qml/js/TransactionHelper.js
index f0b4991fc..be057917c 100644
--- a/mix/qml/js/TransactionHelper.js
+++ b/mix/qml/js/TransactionHelper.js
@@ -17,6 +17,7 @@ function rpcCall(requests, callBack)
{
var jsonRpcUrl = "http://localhost:8080";
var rpcRequest = JSON.stringify(requests);
+ console.log(rpcRequest);
var httpRequest = new XMLHttpRequest();
httpRequest.open("POST", jsonRpcUrl, true);
httpRequest.setRequestHeader("Content-type", "application/json");
@@ -31,7 +32,10 @@ function rpcCall(requests, callBack)
deploymentError(errorText);
}
else
+ {
+ console.log(httpRequest.responseText);
callBack(httpRequest.status, httpRequest.responseText)
+ }
}
}
httpRequest.send(rpcRequest);