diff --git a/src/cpp/ripple/AccountState.cpp b/src/cpp/ripple/AccountState.cpp index beaa5cbcc9..8e6ff69a78 100644 --- a/src/cpp/ripple/AccountState.cpp +++ b/src/cpp/ripple/AccountState.cpp @@ -15,8 +15,7 @@ AccountState::AccountState(const RippleAddress& naAccountID) : mAccountID(naAcco { if (!naAccountID.isValid()) return; - mLedgerEntry = boost::make_shared(ltACCOUNT_ROOT); - mLedgerEntry->setIndex(Ledger::getAccountRootIndex(naAccountID)); + mLedgerEntry = boost::make_shared(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(naAccountID)); mLedgerEntry->setFieldAccount(sfAccount, naAccountID.getAccountID()); mValid = true; diff --git a/src/cpp/ripple/Ledger.cpp b/src/cpp/ripple/Ledger.cpp index 693b3cd0d2..22eeba34a1 100644 --- a/src/cpp/ripple/Ledger.cpp +++ b/src/cpp/ripple/Ledger.cpp @@ -756,8 +756,7 @@ SLE::pointer Ledger::getASNode(LedgerStateParms& parms, const uint256& nodeID, } parms = parms | lepCREATED | lepOKAY; - SLE::pointer sle=boost::make_shared(let); - sle->setIndex(nodeID); + SLE::pointer sle=boost::make_shared(let, nodeID); return sle; } @@ -890,7 +889,7 @@ uint256 Ledger::getAccountRootIndex(const uint160& uAccountID) uint256 Ledger::getLedgerHashIndex() { // get the index of the node that holds the last 256 ledgers Serializer s(2); - s.add16(spaceHashes); + s.add16(spaceSkipList); return s.getSHA512Half(); } @@ -898,7 +897,7 @@ uint256 Ledger::getLedgerHashIndex(uint32 desiredLedgerIndex) { // get the index of the node that holds the set of 256 ledgers that includes this ledger's hash // (or the first ledger after it if it's not a multiple of 256) Serializer s(6); - s.add16(spaceHashes); + s.add16(spaceSkipList); s.add32(desiredLedgerIndex >> 16); return s.getSHA512Half(); } @@ -1063,6 +1062,56 @@ bool Ledger::assertSane() return false; } +void Ledger::updateSkipList() +{ // update the skip list with the information from our previous ledger + + if (mLedgerSeq == 0) // genesis ledger has no previous ledger + return; + + uint32 prevIndex = mLedgerSeq - 1; + + if ((prevIndex & 0xff) == 0) + { // update record of every 256th ledger + uint256 hash = getLedgerHashIndex(prevIndex); + SLE::pointer skipList = getSLE(hash); + std::vector hashes; + + if (!skipList) + skipList = boost::make_shared(ltLEDGER_HASHES, hash); + else + hashes = skipList->getFieldV256(sfHashes).peekValue(); + + assert(hashes.size() <= 256); + hashes.push_back(mParentHash); + skipList->setFieldV256(sfHashes, STVector256(hashes)); + + if (writeBack(lepCREATE, skipList) == lepERROR) + { + assert(false); + } + } + + // update record of past 256 ledger + uint256 hash = getLedgerHashIndex(); + SLE::pointer skipList = getSLE(hash); + std::vector hashes; + if (!skipList) + skipList = boost::make_shared(ltLEDGER_HASHES, hash); + else + hashes = skipList->getFieldV256(sfHashes).peekValue(); + + assert(hashes.size() <= 256); + if (hashes.size() == 256) + hashes.erase(hashes.begin()); + hashes.push_back(mParentHash); + skipList->setFieldV256(sfHashes, STVector256(hashes)); + + if (writeBack(lepCREATE, skipList) == lepERROR) + { + assert(false); + } +} + int Ledger::sPendingSaves = 0; boost::recursive_mutex Ledger::sPendingSaveLock; diff --git a/src/cpp/ripple/Ledger.h b/src/cpp/ripple/Ledger.h index d89fcbba42..fae8b107b1 100644 --- a/src/cpp/ripple/Ledger.h +++ b/src/cpp/ripple/Ledger.h @@ -166,6 +166,7 @@ public: LedgerStateParms writeBack(LedgerStateParms parms, SLE::ref); SLE::pointer getAccountRoot(const uint160& accountID); SLE::pointer getAccountRoot(const RippleAddress& naAccountID); + void updateSkipList(); // database functions static Ledger::pointer loadByIndex(uint32 ledgerIndex); diff --git a/src/cpp/ripple/LedgerConsensus.cpp b/src/cpp/ripple/LedgerConsensus.cpp index 96604df891..0fc07a4aad 100644 --- a/src/cpp/ripple/LedgerConsensus.cpp +++ b/src/cpp/ripple/LedgerConsensus.cpp @@ -1159,6 +1159,7 @@ void LedgerConsensus::accept(SHAMap::ref set) newLCL->peekTransactionMap()->armDirty(); newLCL->peekAccountStateMap()->armDirty(); applyTransactions(set, newLCL, newLCL, failedTransactions, false); + newLCL->updateSkipList(); newLCL->setClosed(); boost::shared_ptr acctNodes = newLCL->peekAccountStateMap()->disarmDirty(); boost::shared_ptr txnNodes = newLCL->peekTransactionMap()->disarmDirty(); diff --git a/src/cpp/ripple/LedgerEntrySet.cpp b/src/cpp/ripple/LedgerEntrySet.cpp index 3b3017b744..e7d361c671 100644 --- a/src/cpp/ripple/LedgerEntrySet.cpp +++ b/src/cpp/ripple/LedgerEntrySet.cpp @@ -72,8 +72,7 @@ SLE::pointer LedgerEntrySet::getEntry(const uint256& index, LedgerEntryAction& a SLE::pointer LedgerEntrySet::entryCreate(LedgerEntryType letType, const uint256& index) { assert(index.isNonZero()); - SLE::pointer sleNew = boost::make_shared(letType); - sleNew->setIndex(index); + SLE::pointer sleNew = boost::make_shared(letType, index); entryCreate(sleNew); return sleNew; } diff --git a/src/cpp/ripple/LedgerFormats.h b/src/cpp/ripple/LedgerFormats.h index cae045f23a..2c3f3cd5a4 100644 --- a/src/cpp/ripple/LedgerFormats.h +++ b/src/cpp/ripple/LedgerFormats.h @@ -29,7 +29,7 @@ enum LedgerNameSpace spaceOwnerDir = 'O', // Directory of things owned by an account. spaceBookDir = 'B', // Directory of order books. spaceContract = 'c', - spaceHashes = 'h', + spaceSkipList = 's', }; enum LedgerSpecificFlags diff --git a/src/cpp/ripple/SerializedLedger.cpp b/src/cpp/ripple/SerializedLedger.cpp index 00a3539878..9f70f7c522 100644 --- a/src/cpp/ripple/SerializedLedger.cpp +++ b/src/cpp/ripple/SerializedLedger.cpp @@ -39,7 +39,8 @@ SerializedLedgerEntry::SerializedLedgerEntry(const Serializer& s, const uint256& } } -SerializedLedgerEntry::SerializedLedgerEntry(LedgerEntryType type) : STObject(sfLedgerEntry), mType(type) +SerializedLedgerEntry::SerializedLedgerEntry(LedgerEntryType type, const uint256& index) : + STObject(sfLedgerEntry), mIndex(index), mType(type) { mFormat = LedgerEntryFormat::getLgrFormat(type); if (mFormat == NULL) throw std::runtime_error("invalid ledger entry type"); diff --git a/src/cpp/ripple/SerializedLedger.h b/src/cpp/ripple/SerializedLedger.h index 7bbdfaf992..ec344d9b91 100644 --- a/src/cpp/ripple/SerializedLedger.h +++ b/src/cpp/ripple/SerializedLedger.h @@ -24,7 +24,7 @@ protected: public: SerializedLedgerEntry(const Serializer& s, const uint256& index); SerializedLedgerEntry(SerializerIterator& sit, const uint256& index); - SerializedLedgerEntry(LedgerEntryType type); + SerializedLedgerEntry(LedgerEntryType type, const uint256& index); SerializedTypeID getSType() const { return STI_LEDGERENTRY; } std::string getFullText() const;