//------------------------------------------------------------------------------ /* This file is part of rippled: https://github.com/ripple/rippled Copyright (c) 2012, 2013 Ripple Labs Inc. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ //============================================================================== #ifndef RIPPLE_LEDGER_H #define RIPPLE_LEDGER_H class Job; enum LedgerStateParms { lepNONE = 0, // no special flags // input flags lepCREATE = 1, // Create if not present // output flags lepOKAY = 2, // success lepMISSING = 4, // No node in that slot lepWRONGTYPE = 8, // Node of different type there lepCREATED = 16, // Node was created lepERROR = 32, // error }; #define LEDGER_JSON_DUMP_TXRP 0x10000000 #define LEDGER_JSON_DUMP_STATE 0x20000000 #define LEDGER_JSON_EXPAND 0x40000000 #define LEDGER_JSON_FULL 0x80000000 class SqliteStatement; class LedgerBase { protected: LedgerBase (); // VFALCO TODO eliminate the need for friends friend class TransactionEngine; friend class Transactor; typedef RippleRecursiveMutex LockType; typedef LockType::ScopedLockType ScopedLockType; LockType mLock; }; // VFALCO TODO figure out exactly how this thing works. // It seems like some ledger database is stored as a global, static in the // class. But then what is the meaning of a Ledger object? Is this // really two classes in one? StoreOfAllLedgers + SingleLedgerObject? // class Ledger : public boost::enable_shared_from_this , public LedgerBase , public CountedObject , public Uncopyable { public: static char const* getCountedObjectName () { return "Ledger"; } typedef boost::shared_ptr pointer; typedef const boost::shared_ptr& ref; enum TransResult { TR_ERROR = -1, TR_SUCCESS = 0, TR_NOTFOUND = 1, TR_ALREADY = 2, TR_BADTRANS = 3, // the transaction itself is corrupt TR_BADACCT = 4, // one of the accounts is invalid TR_INSUFF = 5, // the sending(apply)/receiving(remove) account is broke TR_PASTASEQ = 6, // account is past this transaction TR_PREASEQ = 7, // account is missing transactions before this TR_BADLSEQ = 8, // ledger too early TR_TOOSMALL = 9, // amount is less than Tx fee }; // ledger close flags static const uint32 sLCF_NoConsensusTime = 1; public: Ledger (const RippleAddress & masterID, uint64 startAmount); // used for the starting bootstrap ledger Ledger (uint256 const & parentHash, uint256 const & transHash, uint256 const & accountHash, uint64 totCoins, uint32 closeTime, uint32 parentCloseTime, int closeFlags, int closeResolution, uint32 ledgerSeq, bool & loaded); // used for database ledgers Ledger (Blob const & rawLedger, bool hasPrefix); Ledger (const std::string & rawLedger, bool hasPrefix); Ledger (bool dummy, Ledger & previous); // ledger after this one Ledger (Ledger & target, bool isMutable); // snapshot ~Ledger (); static Ledger::pointer getSQL (const std::string & sqlStatement); static Ledger::pointer getSQL1 (SqliteStatement*); static void getSQL2 (Ledger::ref); static Ledger::pointer getLastFullLedger (); static uint32 roundCloseTime (uint32 closeTime, uint32 closeResolution); void updateHash (); void setClosed () { mClosed = true; } void setValidated() { mValidated = true; } void setAccepted (uint32 closeTime, int closeResolution, bool correctCloseTime); void setAccepted (); void setImmutable (); bool isClosed () { return mClosed; } bool isAccepted () { return mAccepted; } bool isValidated () { return mValidated; } bool isImmutable () { return mImmutable; } bool isFixed () { return mClosed || mImmutable; } void setFull () { mTransactionMap->setLedgerSeq (mLedgerSeq); mAccountStateMap->setLedgerSeq (mLedgerSeq); } // ledger signature operations void addRaw (Serializer & s) const; void setRaw (Serializer & s, bool hasPrefix); uint256 getHash (); uint256 const& getParentHash () const { return mParentHash; } uint256 const& getTransHash () const { return mTransHash; } uint256 const& getAccountHash () const { return mAccountHash; } uint64 getTotalCoins () const { return mTotCoins; } void destroyCoins (uint64 fee) { mTotCoins -= fee; } uint32 getCloseTimeNC () const { return mCloseTime; } uint32 getParentCloseTimeNC () const { return mParentCloseTime; } uint32 getLedgerSeq () const { return mLedgerSeq; } int getCloseResolution () const { return mCloseResolution; } bool getCloseAgree () const { return (mCloseFlags & sLCF_NoConsensusTime) == 0; } // close time functions void setCloseTime (uint32 ct) { assert (!mImmutable); mCloseTime = ct; } void setCloseTime (boost::posix_time::ptime); boost::posix_time::ptime getCloseTime () const; // low level functions SHAMap::ref peekTransactionMap () { return mTransactionMap; } SHAMap::ref peekAccountStateMap () { return mAccountStateMap; } void dropCache () { assert (isImmutable ()); if (mTransactionMap) mTransactionMap->dropCache (); if (mAccountStateMap) mAccountStateMap->dropCache (); } // ledger sync functions void setAcquiring (void); bool isAcquiring (void); bool isAcquiringTx (void); bool isAcquiringAS (void); // Transaction Functions bool addTransaction (uint256 const & id, const Serializer & txn); bool addTransaction (uint256 const & id, const Serializer & txn, const Serializer & metaData); bool hasTransaction (uint256 const & TransID) const { return mTransactionMap->hasItem (TransID); } Transaction::pointer getTransaction (uint256 const & transID) const; bool getTransaction (uint256 const & transID, Transaction::pointer & txn, TransactionMetaSet::pointer & txMeta); bool getTransactionMeta (uint256 const & transID, TransactionMetaSet::pointer & txMeta); bool getMetaHex (uint256 const & transID, std::string & hex); static SerializedTransaction::pointer getSTransaction (SHAMapItem::ref, SHAMapTreeNode::TNType); SerializedTransaction::pointer getSMTransaction (SHAMapItem::ref, SHAMapTreeNode::TNType, TransactionMetaSet::pointer & txMeta); // high-level functions bool hasAccount (const RippleAddress & acctID); AccountState::pointer getAccountState (const RippleAddress & acctID); LedgerStateParms writeBack (LedgerStateParms parms, SLE::ref); SLE::pointer getAccountRoot (const uint160 & accountID); SLE::pointer getAccountRoot (const RippleAddress & naAccountID); void updateSkipList (); void visitAccountItems (const uint160 & acctID, FUNCTION_TYPE); void visitStateItems (FUNCTION_TYPE); // database functions (low-level) static Ledger::pointer loadByIndex (uint32 ledgerIndex); static Ledger::pointer loadByHash (uint256 const & ledgerHash); static uint256 getHashByIndex (uint32 index); static bool getHashesByIndex (uint32 index, uint256 & ledgerHash, uint256 & parentHash); static std::map< uint32, std::pair > getHashesByIndex (uint32 minSeq, uint32 maxSeq); bool pendSaveValidated (bool isSynchronous, bool isCurrent); // next/prev function SLE::pointer getSLE (uint256 const & uHash); // SLE is mutable SLE::pointer getSLEi (uint256 const & uHash); // SLE is immutable // VFALCO NOTE These seem to let you walk the list of ledgers // uint256 getFirstLedgerIndex (); uint256 getLastLedgerIndex (); uint256 getNextLedgerIndex (uint256 const & uHash); // first node >hash uint256 getNextLedgerIndex (uint256 const & uHash, uint256 const & uEnd); // first node >hash, begin // Ledger hash table function static uint256 getLedgerHashIndex (); static uint256 getLedgerHashIndex (uint32 desiredLedgerIndex); static int getLedgerHashOffset (uint32 desiredLedgerIndex); static int getLedgerHashOffset (uint32 desiredLedgerIndex, uint32 currentLedgerIndex); uint256 getLedgerHash (uint32 ledgerIndex); std::vector< std::pair > getLedgerHashes (); static uint256 getLedgerFeatureIndex (); static uint256 getLedgerFeeIndex (); std::vector getLedgerFeatures (); std::vector getNeededTransactionHashes (int max, SHAMapSyncFilter * filter); std::vector getNeededAccountStateHashes (int max, SHAMapSyncFilter * filter); // index calculation functions static uint256 getAccountRootIndex (const uint160 & uAccountID); static uint256 getAccountRootIndex (const RippleAddress & account) { return getAccountRootIndex (account.getAccountID ()); } // // Generator Map functions // SLE::pointer getGenerator (const uint160 & uGeneratorID); static uint256 getGeneratorIndex (const uint160 & uGeneratorID); // // Nickname functions // static uint256 getNicknameHash (const std::string & strNickname) { Serializer s (strNickname); return s.getSHA256 (); } NicknameState::pointer getNicknameState (uint256 const & uNickname); NicknameState::pointer getNicknameState (const std::string & strNickname) { return getNicknameState (getNicknameHash (strNickname)); } SLE::pointer getNickname (uint256 const & uNickname); SLE::pointer getNickname (const std::string & strNickname) { return getNickname (getNicknameHash (strNickname)); } static uint256 getNicknameIndex (uint256 const & uNickname); // // Order book functions // // Order book dirs have a base so we can use next to step through them in quality order. static bool isValidBook (const uint160 & uTakerPaysCurrency, const uint160 & uTakerPaysIssuerID, const uint160 & uTakerGetsCurrency, const uint160 & uTakerGetsIssuerID); static uint256 getBookBase (const uint160 & uTakerPaysCurrency, const uint160 & uTakerPaysIssuerID, const uint160 & uTakerGetsCurrency, const uint160 & uTakerGetsIssuerID); // // Offer functions // SLE::pointer getOffer (uint256 const & uIndex); SLE::pointer getOffer (const uint160 & uAccountID, uint32 uSequence) { return getOffer (getOfferIndex (uAccountID, uSequence)); } // The index of an offer. static uint256 getOfferIndex (const uint160 & uAccountID, uint32 uSequence); // // Owner functions // // VFALCO NOTE This is a simple math operation that converts the account ID // into a 256 bit object (I think....need to research this) // // All items controlled by an account are here: offers static uint256 getOwnerDirIndex (const uint160 & uAccountID); // // Directory functions // Directories are doubly linked lists of nodes. // Given a directory root and and index compute the index of a node. static uint256 getDirNodeIndex (uint256 const & uDirRoot, const uint64 uNodeIndex = 0); static void ownerDirDescriber (SLE::ref, bool, const uint160 & owner); // Return a node: root or normal SLE::pointer getDirNode (uint256 const & uNodeIndex); // // Quality // static uint256 getQualityIndex (uint256 const & uBase, const uint64 uNodeDir = 0); static uint256 getQualityNext (uint256 const & uBase); static uint64 getQuality (uint256 const & uBase); static void qualityDirDescriber (SLE::ref, bool, const uint160 & uTakerPaysCurrency, const uint160 & uTakerPaysIssuer, const uint160 & uTakerGetsCurrency, const uint160 & uTakerGetsIssuer, const uint64 & uRate); // // Ripple functions : credit lines // // Index of node which is the ripple state between two accounts for a currency. // VFALCO NOTE Rename these to make it clear they are simple functions that // don't access global variables. e.g. "calculateKeyFromRippleStateAndAddress" // static uint256 getRippleStateIndex (const RippleAddress & naA, const RippleAddress & naB, const uint160 & uCurrency); static uint256 getRippleStateIndex (const uint160 & uiA, const uint160 & uiB, const uint160 & uCurrency) { return getRippleStateIndex (RippleAddress::createAccountID (uiA), RippleAddress::createAccountID (uiB), uCurrency); } SLE::pointer getRippleState (uint256 const & uNode); SLE::pointer getRippleState (const RippleAddress & naA, const RippleAddress & naB, const uint160 & uCurrency) { return getRippleState (getRippleStateIndex (naA, naB, uCurrency)); } SLE::pointer getRippleState (const uint160 & uiA, const uint160 & uiB, const uint160 & uCurrency) { return getRippleState (getRippleStateIndex (RippleAddress::createAccountID (uiA), RippleAddress::createAccountID (uiB), uCurrency)); } uint32 getReferenceFeeUnits () { if (!mBaseFee) updateFees (); return mReferenceFeeUnits; } uint64 getBaseFee () { if (!mBaseFee) updateFees (); return mBaseFee; } uint64 getReserve (int increments) { if (!mBaseFee) updateFees (); return scaleFeeBase (static_cast (increments) * mReserveIncrement + mReserveBase); } uint64 getReserveInc () { if (!mBaseFee) updateFees (); return mReserveIncrement; } uint64 scaleFeeBase (uint64 fee); uint64 scaleFeeLoad (uint64 fee, bool bAdmin); static std::set getPendingSaves(); Json::Value getJson (int options); void addJson (Json::Value&, int options); bool walkLedger (); bool assertSane (); protected: SLE::pointer getASNode (LedgerStateParms & parms, uint256 const & nodeID, LedgerEntryType let); // returned SLE is immutable SLE::pointer getASNodeI (uint256 const & nodeID, LedgerEntryType let); void saveValidatedLedgerAsync(Job&, bool current) { saveValidatedLedger(current); } void saveValidatedLedger (bool current); void updateFees (); private: void initializeFees (); private: // The basic Ledger structure, can be opened, closed, or synching uint256 mHash; uint256 mParentHash; uint256 mTransHash; uint256 mAccountHash; uint64 mTotCoins; 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, mValidated, mValidHash, mAccepted, mImmutable; uint32 mReferenceFeeUnits; // Fee units for the reference transaction uint32 mReserveBase, mReserveIncrement; // Reserve basse and increment in fee units uint64 mBaseFee; // Ripple cost of the reference transaction SHAMap::pointer mTransactionMap; SHAMap::pointer mAccountStateMap; typedef RippleMutex StaticLockType; typedef StaticLockType::ScopedLockType StaticScopedLockType; // ledgers not fully saved, validated ledger present but DB may not be correct yet static StaticLockType sPendingSaveLock; static std::set sPendingSaves; }; inline LedgerStateParms operator| (const LedgerStateParms& l1, const LedgerStateParms& l2) { return static_cast (static_cast (l1) | static_cast (l2)); } inline LedgerStateParms operator& (const LedgerStateParms& l1, const LedgerStateParms& l2) { return static_cast (static_cast (l1) & static_cast (l2)); } #endif