diff --git a/src/DBInit.cpp b/src/DBInit.cpp index 4f11e12ec3..c9c00ce7a6 100644 --- a/src/DBInit.cpp +++ b/src/DBInit.cpp @@ -43,7 +43,10 @@ const char *LedgerDBInit[] = { LedgerSeq BIGINT UNSIGNED, \ PrevHash CHARACTER(64), \ TotalCoins BIGINT UNSIGNED, \ - ClosingTime BIGINT UNSINGED, \ + ClosingTime BIGINT UNSIGNED, \ + PrevClosingTime BIGINT UNSIGNED, \ + CloseTimeRes BIGINT UNSIGNED, \ + CloseFlags, BIGINT UNSIGNED, \ AccountSetHash CHARACTER(64), \ TransSetHash CHARACTER(64) \ );", diff --git a/src/Ledger.cpp b/src/Ledger.cpp index 728e713b23..a46d0a6e5c 100644 --- a/src/Ledger.cpp +++ b/src/Ledger.cpp @@ -16,14 +16,14 @@ #include "Conversion.h" #include "BitcoinUtil.h" #include "Wallet.h" -#include "BinaryFormats.h" #include "LedgerTiming.h" #include "HashPrefixes.h" #include "Log.h" -Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) : mTotCoins(startAmount), - mCloseTime(0), mLedgerSeq(0), mClosed(false), mValidHash(false), - mAccepted(false), mImmutable(false), mTransactionMap(new SHAMap()), mAccountStateMap(new SHAMap()) +Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) : mTotCoins(startAmount), mLedgerSeq(0), + mCloseTime(0), mParentCloseTime(0), mCloseResolution(LEDGER_TIME_ACCURACY), mCloseFlags(0), + mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false), + mTransactionMap(new SHAMap()), mAccountStateMap(new SHAMap()) { // special case: put coins in root account AccountState::pointer startAccount = boost::make_shared(masterID); @@ -37,15 +37,18 @@ Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) : mTotCoins(s } Ledger::Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash, - uint64 totCoins, uint64 timeStamp, uint32 ledgerSeq) - : mParentHash(parentHash), mTransHash(transHash), mAccountHash(accountHash), - mTotCoins(totCoins), mCloseTime(timeStamp), mLedgerSeq(ledgerSeq), + uint64 totCoins, uint32 closeTime, uint32 parentCloseTime, int closeFlags, int closeResolution, uint32 ledgerSeq) + : mParentHash(parentHash), mTransHash(transHash), mAccountHash(accountHash), mTotCoins(totCoins), + mLedgerSeq(ledgerSeq), mCloseTime(closeTime), mParentCloseTime(parentCloseTime), + mCloseResolution(closeResolution), mCloseFlags(closeFlags), mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false) { updateHash(); } Ledger::Ledger(Ledger& ledger, bool isMutable) : mTotCoins(ledger.mTotCoins), mLedgerSeq(ledger.mLedgerSeq), + mCloseTime(ledger.mCloseTime), mParentCloseTime(ledger.mParentCloseTime), + mCloseResolution(ledger.mCloseResolution), mCloseFlags(ledger.mCloseFlags), mClosed(ledger.mClosed), mValidHash(false), mAccepted(ledger.mAccepted), mImmutable(!isMutable), mTransactionMap(ledger.mTransactionMap->snapShot(isMutable)), mAccountStateMap(ledger.mAccountStateMap->snapShot(isMutable)) @@ -54,9 +57,10 @@ Ledger::Ledger(Ledger& ledger, bool isMutable) : mTotCoins(ledger.mTotCoins), mL } -Ledger::Ledger(uint64 closeTime, Ledger& prevLedger) : - mTotCoins(prevLedger.mTotCoins), mCloseTime(closeTime), mLedgerSeq(prevLedger.mLedgerSeq + 1), - mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false), +Ledger::Ledger(bool dummy, Ledger& prevLedger) : + mTotCoins(prevLedger.mTotCoins), mLedgerSeq(prevLedger.mLedgerSeq + 1), + mCloseTime(0), mParentCloseTime(prevLedger.mCloseTime), mCloseResolution(prevLedger.mCloseResolution), + mCloseFlags(0), mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false), mTransactionMap(new SHAMap()), mAccountStateMap(prevLedger.mAccountStateMap->snapShot(true)) { // Create a new ledger that follows this one prevLedger.updateHash(); @@ -64,42 +68,16 @@ Ledger::Ledger(uint64 closeTime, Ledger& prevLedger) : assert(mParentHash.isNonZero()); } -Ledger::Ledger(const std::vector& rawLedger) : mCloseTime(0), - mLedgerSeq(0), mClosed(false), mValidHash(false), mAccepted(false), mImmutable(true) +Ledger::Ledger(const std::vector& rawLedger) : + mClosed(false), mValidHash(false), mAccepted(false), mImmutable(true) { - Serializer s(rawLedger); - // 32seq, 64fee, 256phash, 256thash, 256ahash, 64ts - if (!s.get32(mLedgerSeq, BLgPIndex)) return; - if (!s.get64(mTotCoins, BLgPTotCoins)) return; - if (!s.get256(mParentHash, BLgPPrevLg)) return; - if (!s.get256(mTransHash, BLgPTxT)) return; - if (!s.get256(mAccountHash, BLgPAcT)) return; - if (!s.get64(mCloseTime, BLgPClTs)) return; - updateHash(); - if(mValidHash) - { - mTransactionMap = boost::make_shared(); - mAccountStateMap = boost::make_shared(); - } + setRaw(Serializer(rawLedger)); } -Ledger::Ledger(const std::string& rawLedger) : mCloseTime(0), - mLedgerSeq(0), mClosed(false), mValidHash(false), mAccepted(false), mImmutable(true) +Ledger::Ledger(const std::string& rawLedger) : + mClosed(false), mValidHash(false), mAccepted(false), mImmutable(true) { - Serializer s(rawLedger); - // 32seq, 64fee, 256phash, 256thash, 256ahash, 64ts - if (!s.get32(mLedgerSeq, BLgPIndex)) return; - if (!s.get64(mTotCoins, BLgPTotCoins)) return; - if (!s.get256(mParentHash, BLgPPrevLg)) return; - if (!s.get256(mTransHash, BLgPTxT)) return; - if (!s.get256(mAccountHash, BLgPAcT)) return; - if (!s.get64(mCloseTime, BLgPClTs)) return; - updateHash(); - if(mValidHash) - { - mTransactionMap = boost::make_shared(); - mAccountStateMap = boost::make_shared(); - } + setRaw(Serializer(rawLedger)); } void Ledger::updateHash() @@ -112,21 +90,62 @@ void Ledger::updateHash() else mAccountHash.zero(); } - Serializer s(116); + Serializer s(118); s.add32(sHP_Ledger); addRaw(s); mHash = s.getSHA512Half(); mValidHash = true; } -void Ledger::addRaw(Serializer &s) +void Ledger::setRaw(const Serializer &s) +{ + SerializerIterator sit(s); + mLedgerSeq = sit.get32(); + mTotCoins = sit.get64(); + mParentHash = sit.get256(); + mTransHash = sit.get256(); + mAccountHash = sit.get256(); + mCloseTime = sit.get32(); + mCloseResolution = sit.get8(); + mCloseFlags = sit.get8(); + updateHash(); + if(mValidHash) + { + mTransactionMap = boost::make_shared(mTransHash); + mAccountStateMap = boost::make_shared(mAccountHash); + } +} + +void Ledger::addRaw(Serializer &s) const { s.add32(mLedgerSeq); s.add64(mTotCoins); s.add256(mParentHash); s.add256(mTransHash); s.add256(mAccountHash); - s.add64(mCloseTime); + s.add32(mParentCloseTime); + s.add32(mCloseTime); + s.add8(mCloseResolution); + s.add8(mCloseFlags); +} + +void Ledger::setAccepted(uint32 closeTime, int closeResolution, bool correctCloseTime) +{ // used when we witnessed the consensus + assert(mClosed && !mAccepted); + mCloseTime = closeTime; + mCloseResolution = closeResolution; + mCloseFlags = correctCloseTime ? 0 : sLCF_NoConsensusTime; + updateHash(); + mAccepted = true; + mImmutable = true; +} + +void Ledger::setAccepted() +{ // used when we acquired the ledger + assert(mClosed && !mAccepted && (mCloseResolution != 0)); + updateHash(); + mAccepted = true; + mImmutable = true; } AccountState::pointer Ledger::getAccountState(const NewcoinAddress& accountID) @@ -238,28 +257,18 @@ void Ledger::saveAcceptedLedger(Ledger::pointer ledger) static boost::format AcctTransExists("SELECT LedgerSeq FROM AccountTransactions WHERE TransId = '%s';"); static boost::format transExists("SELECT Status FROM Transactions WHERE TransID = '%s';"); static boost::format updateTx("UPDATE Transactions SET LedgerSeq = %d, Status = '%c' WHERE TransID = '%s';"); - - std::string sql="INSERT INTO Ledgers " - "(LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,AccountSetHash,TransSetHash) VALUES ('"; - sql.append(ledger->getHash().GetHex()); - sql.append("','"); - sql.append(boost::lexical_cast(ledger->mLedgerSeq)); - sql.append("','"); - sql.append(ledger->mParentHash.GetHex()); - sql.append("','"); - sql.append(boost::lexical_cast(ledger->mTotCoins)); - sql.append("','"); - sql.append(boost::lexical_cast(ledger->mCloseTime)); - sql.append("','"); - sql.append(ledger->mAccountHash.GetHex()); - sql.append("','"); - sql.append(ledger->mTransHash.GetHex()); - sql.append("');"); + static boost::format addLedger("INSERT INTO Ledgers " + "(LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,PrevClosingTime,CloseTimeRes,CloseFlags," + "AccountSetHash,TranSetHash) VALUES ('%s','%u','%s','%s','%u','%u','%d','%u','%s','%s');"); ScopedLock sl(theApp->getLedgerDB()->getDBLock()); if (SQL_EXISTS(theApp->getLedgerDB()->getDB(), boost::str(ledgerExists % ledger->mLedgerSeq))) theApp->getLedgerDB()->getDB()->executeSQL(boost::str(deleteLedger % ledger->mLedgerSeq)); - theApp->getLedgerDB()->getDB()->executeSQL(sql); + theApp->getLedgerDB()->getDB()->executeSQL(boost::str(addLedger % + ledger->getHash().GetHex() % ledger->mLedgerSeq % ledger->mParentHash.GetHex() % + boost::lexical_cast(ledger->mTotCoins) % ledger->mCloseTime % ledger->mParentCloseTime % + ledger->mCloseResolution % ledger->mCloseFlags % + ledger->mAccountHash.GetHex() % ledger->mTransHash.GetHex())); // write out dirty nodes while(ledger->mTransactionMap->flushDirty(256, TRANSACTION_NODE, ledger->mLedgerSeq)) @@ -328,8 +337,10 @@ void Ledger::saveAcceptedLedger(Ledger::pointer ledger) Ledger::pointer Ledger::getSQL(const std::string& sql) { uint256 ledgerHash, prevHash, accountHash, transHash; - uint64 totCoins, closingTime; - uint32 ledgerSeq; + uint64 totCoins; + uint32 closingTime, prevClosingTime, ledgerSeq; + int closeResolution; + unsigned closeFlags; std::string hash; { @@ -349,12 +360,16 @@ Ledger::pointer Ledger::getSQL(const std::string& sql) transHash.SetHex(hash); totCoins = db->getBigInt("TotalCoins"); closingTime = db->getBigInt("ClosingTime"); + prevClosingTime = db->getBigInt("PrevClosingTime"); + closeResolution = db->getBigInt("CloseTimeRes"); + closeFlags = db->getBigInt("CloseFlags"); ledgerSeq = db->getBigInt("LedgerSeq"); db->endIterRows(); } Ledger::pointer ret = - boost::make_shared(prevHash, transHash, accountHash, totCoins, closingTime, ledgerSeq); + boost::make_shared(prevHash, transHash, accountHash, totCoins, closingTime, prevClosingTime, + closeFlags, closeResolution, ledgerSeq); if (ret->getHash() != ledgerHash) { Json::StyledStreamWriter ssw; @@ -474,24 +489,4 @@ void Ledger::setCloseTime(boost::posix_time::ptime ptm) mCloseTime = iToSeconds(ptm); } -uint64 Ledger::sGenesisClose = 0; - -uint64 Ledger::getNextLedgerClose(int prevCloseSeconds) const -{ - if (mCloseTime == 0) - { - if (sGenesisClose == 0) - { - uint64 closeTime = theApp->getOPs().getNetworkTimeNC() + LEDGER_IDLE_INTERVAL - 1; - sGenesisClose = closeTime - (closeTime % LEDGER_IDLE_INTERVAL); - } - return sGenesisClose; - } - if (prevCloseSeconds < 0) - return mCloseTime + LEDGER_IDLE_INTERVAL; - if (prevCloseSeconds < 2) - return mCloseTime + prevCloseSeconds; - return mCloseTime + prevCloseSeconds - 1; -} - // vim:ts=4 diff --git a/src/Ledger.h b/src/Ledger.h index c9c5c5951f..8f12953e69 100644 --- a/src/Ledger.h +++ b/src/Ledger.h @@ -58,15 +58,18 @@ public: TR_TOOSMALL = 9, // amount is less than Tx fee }; + // ledger close flags + static const uint32 sLCF_NoConsensusTime = 1; private: - static uint64 sGenesisClose; uint256 mHash, mParentHash, mTransHash, mAccountHash; uint64 mTotCoins; - uint64 mCloseTime; // when this ledger should close / did close - uint64 mParentCloseTime; uint32 mLedgerSeq; + uint32 mCloseTime; // when this ledger closed + uint32 mParentCloseTime; // when the previous ledger closed + int mCloseResolution; // the resolution for this ledger close time (2-120 seconds) + uint32 mCloseFlags; // flags indicating how this ledger close took place bool mClosed, mValidHash, mAccepted, mImmutable; SHAMap::pointer mTransactionMap, mAccountStateMap; @@ -87,16 +90,23 @@ protected: public: Ledger(const NewcoinAddress& masterID, uint64 startAmount); // used for the starting bootstrap ledger + Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash, - uint64 totCoins, uint64 timeStamp, uint32 ledgerSeq); // used for database ledgers + uint64 totCoins, uint32 closeTime, uint32 parentCloseTime, int closeFlags, int closeResolution, + uint32 ledgerSeq); // used for database ledgers + Ledger(const std::vector& rawLedger); + Ledger(const std::string& rawLedger); - Ledger(uint64 defaultCloseTime, Ledger& previous); // ledger after this one + + Ledger(bool dummy, Ledger& previous); // ledger after this one + Ledger(Ledger& target, bool isMutable); // snapshot void updateHash(); void setClosed() { mClosed = true; } - void setAccepted() { mAccepted = true; } + void setAccepted(uint32 closeTime, int closeResolution, bool correctCloseTime); + void setAccepted(); void setImmutable() { updateHash(); mImmutable = true; } bool isClosed() { return mClosed; } bool isAccepted() { return mAccepted; } @@ -109,7 +119,8 @@ public: void bumpSeq() { mClosed = true; mLedgerSeq++; } // ledger signature operations - void addRaw(Serializer &s); + void addRaw(Serializer &s) const; + void setRaw(const Serializer& s); uint256 getHash(); const uint256& getParentHash() const { return mParentHash; } @@ -117,15 +128,14 @@ public: const uint256& getAccountHash() const { return mAccountHash; } uint64 getTotalCoins() const { return mTotCoins; } void destroyCoins(uint64 fee) { mTotCoins -= fee; } - uint64 getCloseTimeNC() const { return mCloseTime; } - uint64 getParentCloseTimeNC() const { return mParentCloseTime; } + uint32 getCloseTimeNC() const { return mCloseTime; } + uint32 getParentCloseTimeNC() const { return mParentCloseTime; } uint32 getLedgerSeq() const { return mLedgerSeq; } // close time functions - void setCloseTime(uint64 ct) { assert(!mImmutable); mCloseTime = ct; } + void setCloseTime(uint32 ct) { assert(!mImmutable); mCloseTime = ct; } void setCloseTime(boost::posix_time::ptime); boost::posix_time::ptime getCloseTime() const; - uint64 getNextLedgerClose(int prevCloseSeconds) const; // low level functions SHAMap::pointer peekTransactionMap() { return mTransactionMap; }