diff --git a/src/LedgerTiming.cpp b/src/LedgerTiming.cpp new file mode 100644 index 000000000..1425f85ac --- /dev/null +++ b/src/LedgerTiming.cpp @@ -0,0 +1,61 @@ + +#include "LedgerTiming.h" + + +// 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 + 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 (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 + } + + 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 +} + +// 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) + 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; +} diff --git a/src/LedgerTiming.h b/src/LedgerTiming.h index d7e623844..543144328 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 diff --git a/src/Transaction.cpp b/src/Transaction.cpp index 1cc4e8e30..95d4d2772 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)); @@ -565,11 +568,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);