From fcebbef0f432b1a0dc395c8abde2a5a20a0b3f68 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 29 Jun 2012 02:01:24 -0700 Subject: [PATCH 1/4] Fix incorrect transactions states after SQL retrieval --- src/Transaction.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Transaction.cpp b/src/Transaction.cpp index 1cc4e8e304..fc157e01a0 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -565,11 +565,13 @@ Transaction::pointer Transaction::transactionFromSQL(const std::string& sql) TransStatus st(INVALID); switch (status[0]) { - case TXN_SQL_NEW: st = NEW; break; - case 'A': st = INCLUDED; break; - case 'C': st = CONFLICTED; break; - case 'D': st = COMMITTED; break; - case 'H': st = HELD; break; + case TXN_SQL_NEW: st = NEW; break; + case TXN_SQL_CONFLICT: st = CONFLICTED; break; + case TXN_SQL_HELD: st = HELD; break; + case TXN_SQL_VALIDATED: st = COMMITTED; break; + case TXN_SQL_INCLUDED: st = INCLUDED; break; + case TXN_SQL_UNKNOWN: break; + default: assert(false); } tr->setStatus(st); tr->setLedger(inLedger); From 3f3ea3c594b3bd8d6309a200301efb226cfadbce Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 29 Jun 2012 02:07:24 -0700 Subject: [PATCH 2/4] Fix the bug Jed reported. --- src/Transaction.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Transaction.cpp b/src/Transaction.cpp index fc157e01a0..95d4d27720 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -535,10 +535,13 @@ bool Transaction::save() Transaction::pointer Transaction::transactionFromSQL(const std::string& sql) { - Serializer rawTxn(2048); + Serializer rawTxn; std::string status; uint32 inLedger; + int txSize = 2048; + rawTxn.resize(txSize); + { ScopedLock sl(theApp->getTxnDB()->getDBLock()); Database* db = theApp->getTxnDB()->getDB(); @@ -548,15 +551,15 @@ Transaction::pointer Transaction::transactionFromSQL(const std::string& sql) db->getStr("Status", status); inLedger = db->getInt("LedgerSeq"); - int txSize = db->getBinary("RawTxn", &*rawTxn.begin(), rawTxn.capacity()); - if (txSize > rawTxn.size()) + txSize = db->getBinary("RawTxn", &*rawTxn.begin(), rawTxn.getLength()); + if (txSize > rawTxn.getLength()) { rawTxn.resize(txSize); - db->getBinary("RawTxn", &*rawTxn.begin(), rawTxn.capacity()); + db->getBinary("RawTxn", &*rawTxn.begin(), rawTxn.getLength()); } - else rawTxn.resize(txSize); db->endIterRows(); } + rawTxn.resize(txSize); SerializerIterator it(rawTxn); SerializedTransaction::pointer txn = boost::make_shared(boost::ref(it)); From 4a2871ff52b58772c5bb540388962b6fcb09fcb6 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 29 Jun 2012 03:50:37 -0700 Subject: [PATCH 3/4] Timing routines for continuous ledger close. --- src/LedgerTiming.cpp | 58 ++++++++++++++++++++++++++++++++++++++++++++ src/LedgerTiming.h | 44 ++++++++++++++++++++++----------- 2 files changed, 88 insertions(+), 14 deletions(-) create mode 100644 src/LedgerTiming.cpp diff --git a/src/LedgerTiming.cpp b/src/LedgerTiming.cpp new file mode 100644 index 0000000000..d50eb3d85a --- /dev/null +++ b/src/LedgerTiming.cpp @@ -0,0 +1,58 @@ + +#include "LedgerTiming.h" + + +// Returns the number of seconds the ledger was or should be open +int ContinuousLedgerTiming::shouldClose( // How many: + bool anyTransactions, + int previousProposers, // proposers there were in the last closing + int proposersClosed, // proposers who have currently closed their ledgers + int previousOpenSeconds, // seconds the previous ledger was open + int currentOpenSeconds) // seconds since the previous ledger closed +{ + if (!anyTransactions) + { // no transactions so far this interval + if (previousOpenSeconds > (LEDGER_IDLE_INTERVAL + 2)) // the last ledger was very slow to close + return previousOpenSeconds - 1; + return LEDGER_IDLE_INTERVAL; // normal idle + } + + if (previousOpenSeconds == LEDGER_IDLE_INTERVAL) // coming out of idle, close now + return currentOpenSeconds; + + // If the network is slow, try to synchronize close times + if (previousOpenSeconds > 8) + return (currentOpenSeconds - currentOpenSeconds % 4); + else if (previousOpenSeconds > 4) + return (currentOpenSeconds - currentOpenSeconds % 2); + + return currentOpenSeconds; // this ledger should close now +} + +bool ContinuousLedgerTiming::haveConsensus( + int previousProposers, // proposers in the last closing (not including us) + int currentProposers, // proposers in this closing so far (not including us) + int currentAgree, // proposers who agree with us + int currentClosed, // proposers who have currently closed their ledgers + int previousAgreeTime, // how long it took to agree on the last ledger + int currentAgreeTime) // how long we've been trying to agree +{ + if (currentProposers < (previousProposers * 3 / 4)) + { // Less than 3/4 of the validators are present, slow down + if (currentAgreeTime < (previousAgreeTime + 2)) + return false; + } + + // If 80% of current proposers (plus us) agree on a set, we have consensus + int agreeWeight = (currentAgree * 100 + 100) / (currentProposers + 1); + if (agreeWeight > 80) + return true; + + // If 50% of the nodes on your UNL (minus us) have closed, you should close + int closeWeight = (currentClosed * 100 - 100) / (currentProposers + 1); + if (closeWeight > 50) + return true; + + return false; +} + \ No newline at end of file diff --git a/src/LedgerTiming.h b/src/LedgerTiming.h index d7e623844d..5431443282 100644 --- a/src/LedgerTiming.h +++ b/src/LedgerTiming.h @@ -21,30 +21,46 @@ // Maximum converge time # define LEDGER_MAX_CONVERGE 20 +#define AV_PCT_STOP 85 #endif -#ifdef LEDGER_CLOSE_SLOW - -# define LEDGER_INTERVAL 1800 - -# define LEDGER_FORCE_CONVERGE 180 - -# define LEDGER_CONVERGE 240 -// Time a transaction must be unconflicted before we consider it protected -# define LEDGER_PROTECT 90 +// BEGIN LEDGER_CLOSE_CONTINUOUS -#endif +// The number of seconds a ledger may remain idle before closing +# define LEDGER_IDLE_INTERVAL 15 + +// How long we wait to transition from inactive to active +# define LEDGER_IDLE_SPIN_TIME 2 // Avalance tuning (percent of UNL voting yes for us to vote yes) -#define AV_MIN_CONSENSUS 50 -#define AV_AVG_CONSENSUS 60 +#define AV_MIN_CONSENSUS 55 +#define AV_AVG_CONSENSUS 65 #define AV_MAX_CONSENSUS 70 -// We consider consensus reached at this percent agreement -#define AV_PCT_STOP 90 + +class ContinuousLedgerTiming +{ +public: + + // Returns the number of seconds the ledger was or should be open + // Call when a consensus is reached and when any transaction is relayed to be added + static int shouldClose( + bool anyTransactions, + int previousProposers, int proposersClosed, + int previousOpenSeconds, int currentOpenSeconds); + + static bool haveConsensus( + int previousProposers, int currentProposers, + int currentAgree, int currentClosed, + int previousAgreeTime, int currentAgreeTime); + +}; + +// END LEDGER_CLOSE_CONTINUOUS + #endif From 8516f40a892ae583149ae616427221726c60814e Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 29 Jun 2012 03:54:43 -0700 Subject: [PATCH 4/4] Improve comments. --- src/LedgerTiming.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/LedgerTiming.cpp b/src/LedgerTiming.cpp index d50eb3d85a..1425f85ac3 100644 --- a/src/LedgerTiming.cpp +++ b/src/LedgerTiming.cpp @@ -2,7 +2,7 @@ #include "LedgerTiming.h" -// Returns the number of seconds the ledger was or should be open +// Returns the number of seconds the ledger should be be open. int ContinuousLedgerTiming::shouldClose( // How many: bool anyTransactions, int previousProposers, // proposers there were in the last closing @@ -12,6 +12,8 @@ int ContinuousLedgerTiming::shouldClose( // How many: { if (!anyTransactions) { // no transactions so far this interval + if (proposersClosed > (previousProposers / 4)) // did we miss a transaction? + return currentOpenSeconds; if (previousOpenSeconds > (LEDGER_IDLE_INTERVAL + 2)) // the last ledger was very slow to close return previousOpenSeconds - 1; return LEDGER_IDLE_INTERVAL; // normal idle @@ -29,6 +31,8 @@ int ContinuousLedgerTiming::shouldClose( // How many: return currentOpenSeconds; // this ledger should close now } +// Returns whether we have a consensus or not. If so, we expect all honest nodes +// to already have everything they need to accept a consensus. Our vote is 'locked in'. bool ContinuousLedgerTiming::haveConsensus( int previousProposers, // proposers in the last closing (not including us) int currentProposers, // proposers in this closing so far (not including us) @@ -55,4 +59,3 @@ bool ContinuousLedgerTiming::haveConsensus( return false; } - \ No newline at end of file