diff --git a/src/cpp/ripple/LedgerConsensus.cpp b/src/cpp/ripple/LedgerConsensus.cpp index 8cba7d23e1..784ee068f7 100644 --- a/src/cpp/ripple/LedgerConsensus.cpp +++ b/src/cpp/ripple/LedgerConsensus.cpp @@ -373,7 +373,7 @@ void LedgerConsensus::checkLCL() uint256 netLgr = mPrevLedgerHash; int netLgrCount = 0; - uint256 favoredLedger = (mState == lcsPRE_CLOSE) ? uint256() : mPrevLedgerHash; // Don't get stuck one ledger back + uint256 favoredLedger = mPrevLedgerHash; // Don't get stuck one ledger back or jump one forward boost::unordered_map vals = theApp->getValidations().getCurrentValidations(favoredLedger); @@ -397,7 +397,7 @@ void LedgerConsensus::checkLCL() default: status = "unknown"; } - cLog(lsWARNING) << "View of consensus changed during consensus (" << netLgrCount << ") status=" + cLog(lsWARNING) << "View of consensus changed during " << status << " (" << netLgrCount << ") status=" << status << ", " << (mHaveCorrectLCL ? "CorrectLCL" : "IncorrectLCL"); cLog(lsWARNING) << mPrevLedgerHash << " to " << netLgr; @@ -966,8 +966,8 @@ void LedgerConsensus::addDisputedTransaction(const uint256& txID, const std::vec txn->setVote(pit.first, cit->second->hasItem(txID)); } - if (!ourVote && theApp->isNewFlag(txID, SF_RELAYED)) - { // We voted no and a trusted peer voted yes, so relay + if (theApp->isNewFlag(txID, SF_RELAYED)) + { ripple::TMTransaction msg; msg.set_rawtransaction(&(tx.front()), tx.size()); msg.set_status(ripple::tsNEW); diff --git a/src/cpp/ripple/Log.cpp b/src/cpp/ripple/Log.cpp index 3758149c08..a9b9cfdba3 100644 --- a/src/cpp/ripple/Log.cpp +++ b/src/cpp/ripple/Log.cpp @@ -208,7 +208,7 @@ namespace websocketpp void websocketLog(websocketpp::log::alevel::value v, const std::string& entry) { - if (v == websocketpp::log::alevel::DEVEL) + if ((v == websocketpp::log::alevel::DEVEL) || (v == websocketpp::log::alevel::DEBUG_CLOSE)) { if (websocketPartition.doLog(lsTRACE)) Log(lsDEBUG, websocketPartition) << entry; diff --git a/src/js/remote.js b/src/js/remote.js index 8507c4a3f5..72a9f6b627 100644 --- a/src/js/remote.js +++ b/src/js/remote.js @@ -1082,7 +1082,8 @@ Remote.prototype.account_seq = function (account, advance) { { seq = account_info.seq; - if (advance) account_info.seq += 1; + if (advance === "ADVANCE") account_info.seq += 1; + if (advance === "REWIND") account_info.seq -= 1; // console.log("cached: %s current=%d next=%d", account, seq, account_info.seq); } diff --git a/src/js/transaction.js b/src/js/transaction.js index 77b8841d4e..61eb541a1e 100644 --- a/src/js/transaction.js +++ b/src/js/transaction.js @@ -312,32 +312,59 @@ Transaction.prototype.submit = function (callback) { if (self.remote.local_sequence && !self.tx_json.Sequence) { self.tx_json.Sequence = this.remote.account_seq(self.tx_json.Account, 'ADVANCE'); // console.log("Sequence: %s", self.tx_json.Sequence); - } - if (self.remote.local_sequence && !self.tx_json.Sequence) { - // Look in the last closed ledger. - this.remote.account_seq_cache(self.tx_json.Account, false) - .on('success_account_seq_cache', function () { - // Try again. - self.submit(); - }) - .on('error_account_seq_cache', function (message) { - // XXX Maybe be smarter about this. Don't want to trust an untrusted server for this seq number. + if (!self.tx_json.Sequence) { + // Look in the last closed ledger. + this.remote.account_seq_cache(self.tx_json.Account, false) + .on('success_account_seq_cache', function () { + // Try again. + self.submit(); + }) + .on('error_account_seq_cache', function (message) { + // XXX Maybe be smarter about this. Don't want to trust an untrusted server for this seq number. - // Look in the current ledger. - self.remote.account_seq_cache(self.tx_json.Account, 'CURRENT') - .on('success_account_seq_cache', function () { - // Try again. - self.submit(); - }) - .on('error_account_seq_cache', function (message) { - // Forward errors. - self.emit('error', message); - }) - .request(); - }) - .request(); - return this; + // Look in the current ledger. + self.remote.account_seq_cache(self.tx_json.Account, 'CURRENT') + .on('success_account_seq_cache', function () { + // Try again. + self.submit(); + }) + .on('error_account_seq_cache', function (message) { + // Forward errors. + self.emit('error', message); + }) + .request(); + }) + .request(); + return this; + } + + // If the transaction fails we want to either undo incrementing the sequence + // or submit a noop transaction to consume the sequence remotely. + this.on('success', function (res) { + if (!res || "string" !== typeof res.engine_result) return; + + switch (res.engine_result.slice(0, 3)) { + // Synchronous local error + case 'tej': + self.remote.account_seq(self.tx_json.Account, 'REWIND'); + break; + // XXX: What do we do in case of ter? + case 'tel': + case 'tem': + case 'tef': + // XXX Once we have a transaction submission manager class, we can + // check if there are any other transactions pending. If there are, + // we should submit a dummy transaction to ensure those + // transactions are still valid. + //var noop = self.remote.transaction().account_set(self.tx_json.Account); + //noop.submit(); + + // XXX Hotfix. This only works if no other transactions are pending. + self.remote.account_seq(self.tx_json.Account, 'REWIND'); + break; + } + }); } // Prepare request @@ -345,8 +372,12 @@ Transaction.prototype.submit = function (callback) { var request = this.remote.request_submit(); // Forward successes and errors. - request.on('success', function (message) { self.emit('success', message); }); - request.on('error', function (message) { self.emit('error', message); }); + request.on('success', function (message) { + self.emit('success', message); + }); + request.on('error', function (message) { + self.emit('error', message); + }); if (!this._secret && !this.tx_json.Signature) { this.emit('error', {