//------------------------------------------------------------------------------ /* Copyright (c) 2011-2013, OpenCoin, Inc. */ //============================================================================== #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; // 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 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); // 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, 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, 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: // The basic Ledger structure, can be opened, closed, or synching // VFALCO TODO eliminate the need for friends friend class TransactionEngine; friend class Transactor; void initializeFees (); private: 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; mutable boost::recursive_mutex mLock; // ledgers not fully saved, validated ledger present but DB may not be correct yet static boost::mutex 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 // vim:ts=4