From 48d3099c001c3d911b0b32a8fdff75f3e0bd2e26 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Sat, 26 May 2012 02:54:03 -0700 Subject: [PATCH] Add ledger support for directories and ripple state. --- src/Ledger.h | 54 ++++++++++++++++++++---------- src/LedgerFormats.cpp | 62 ++++++++++++++++++---------------- src/LedgerFormats.h | 31 +++++++++++++---- src/LedgerIndex.cpp | 17 +++++++--- src/LedgerNode.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++ src/SerializedLedger.h | 7 ++++ 6 files changed, 190 insertions(+), 57 deletions(-) diff --git a/src/Ledger.h b/src/Ledger.h index 42e32bdf87..61b4e47aaa 100644 --- a/src/Ledger.h +++ b/src/Ledger.h @@ -18,17 +18,17 @@ enum LedgerStateParms { - lepNONE = 0, // no special flags + lepNONE = 0, // no special flags // input flags - lepCREATE = 1, // Create if not present + 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 + 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 }; class Ledger : public boost::enable_shared_from_this @@ -132,8 +132,6 @@ public: SerializedLedgerEntry::pointer getAccountRoot(LedgerStateParms& parms, const NewcoinAddress& naAccountID); SerializedLedgerEntry::pointer getNickname(LedgerStateParms& parms, const std::string& nickname); SerializedLedgerEntry::pointer getNickname(LedgerStateParms& parms, const uint256& nickHash); -// SerializedLedgerEntry::pointer getRippleState(LedgerStateParms parms, const uint160& offeror, -// const uint160& borrower, const Currency& currency); // database functions static void saveAcceptedLedger(Ledger::pointer); @@ -142,7 +140,7 @@ public: // index calculation functions static uint256 getAccountRootIndex(const uint160& account) - { return uint160extend256(account, 0); } // Index is accountID extended to 256 bits + { return uint160extend256(account, lnsAccounts); } // Index is accountID extended to 256 bits static uint256 getAccountRootIndex(const NewcoinAddress& account) { return getAccountRootIndex(account.getAccountID()); } @@ -154,28 +152,48 @@ public: SerializedLedgerEntry::pointer getGenerator(LedgerStateParms& parms, const uint160& uGeneratorID); static uint256 getGeneratorIndex(const uint160& uGeneratorID) - { return uint160extend256(uGeneratorID, 1); } // Index is the generator ID extended to 256 bits in namespace 1 + { return uint160extend256(uGeneratorID, lnsGenerator); } // Index is the generator ID extended to 256 bits in namespace 1 // // Ripple functions // - static uint256 getRippleIndex(const uint160& account, const uint160& extendTo, const uint160& currency); + static uint256 getRippleStateIndex(const NewcoinAddress& naA, const NewcoinAddress& naB, const uint160& uCurrency); + static uint256 getRippleStateIndex(const uint160& uiA, const uint160& uiB, const uint160& uCurrency) + { return getRippleStateIndex(NewcoinAddress::createAccountID(uiA), NewcoinAddress::createAccountID(uiB), uCurrency); } - static uint256 getRippleIndex(const uint160& account, const uint160& extendTo) - { return getRippleIndex(account, extendTo, uint160()); } - - static uint256 getRippleIndex(const NewcoinAddress& account, const NewcoinAddress& extendTo, - const uint160& currency) - { return getRippleIndex(account.getAccountID(), extendTo.getAccountID(), currency); } + static uint256 getRippleStateIndex(const NewcoinAddress& naA, const NewcoinAddress& naB) + { return getRippleStateIndex(naA, naB, uint160()); } static uint160 getOfferBase(const uint160& currencyIn, const uint160& accountIn, const uint160& currencyOut, const uint160& accountOut); + // + // Offer functions + // + static uint256 getOfferIndex(const uint160& offerBase, uint64 rate, int skip = 0); static int getOfferSkip(const uint256& offerId); + SerializedLedgerEntry::pointer getRippleState(LedgerStateParms& parms, const NewcoinAddress& naA, const NewcoinAddress& naB, const uint160& uCurrency); + SerializedLedgerEntry::pointer getRippleState(LedgerStateParms& parms, const uint160& uiA, const uint160& uiB, const uint160& uCurrency) + { + return getRippleState(parms, NewcoinAddress::createAccountID(uiA), NewcoinAddress::createAccountID(uiB), uCurrency); + } + + // + // Directory functions + // + + static uint256 getDirIndex(const uint256& uBase, const LedgerEntryType letKind, const uint64 uNodeDir=0); + + SerializedLedgerEntry::pointer getDirRoot(LedgerStateParms& parms, const uint256& uRootIndex); + SerializedLedgerEntry::pointer getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex); + + // + // Misc + // bool isCompatible(boost::shared_ptr other); // bool signLedger(std::vector &signature, const LocalHanko &hanko); diff --git a/src/LedgerFormats.cpp b/src/LedgerFormats.cpp index b0321ad991..2481d80186 100644 --- a/src/LedgerFormats.cpp +++ b/src/LedgerFormats.cpp @@ -17,42 +17,48 @@ LedgerEntryFormat LedgerFormats[]= { S_FIELD(WalletLocator), STI_HASH256, SOE_IFFLAG, 4 }, { S_FIELD(MessageKey), STI_VL, SOE_IFFLAG, 8 }, { S_FIELD(TransitRate), STI_UINT32, SOE_IFFLAG, 16 }, - { S_FIELD(TransitExpire), STI_UINT32, SOE_IFFLAG, 32 }, - { S_FIELD(NextTransitRate), STI_UINT32, SOE_IFFLAG, 64 }, - { S_FIELD(NextTransitStart), STI_UINT32, SOE_IFFLAG, 128 }, - { S_FIELD(NextTransitExpire), STI_UINT32, SOE_IFFLAG, 256 }, { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 }, { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } }, + { "DirectoryRoot", ltDIR_ROOT, { + { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, + { S_FIELD(FirstNode), STI_UINT64, SOE_REQUIRED, 0 }, + { S_FIELD(LastNode), STI_UINT64, SOE_REQUIRED, 0 }, + { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 }, + { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } + }, + { "DirectoryNode", ltDIR_NODE, { + { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, + { S_FIELD(Indexes), STI_VECTOR256, SOE_REQUIRED, 0 }, + { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 }, + { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } + }, { "GeneratorMap", ltGENERATOR_MAP, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(GeneratorID), STI_HASH160, SOE_REQUIRED, 0 }, - { S_FIELD(Generator), STI_VL, SOE_REQUIRED, 0 }, - { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } + { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, + { S_FIELD(GeneratorID), STI_HASH160, SOE_REQUIRED, 0 }, + { S_FIELD(Generator), STI_VL, SOE_REQUIRED, 0 }, + { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 }, + { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } }, { "Nickname", ltNICKNAME, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(Nickname), STI_HASH256, SOE_REQUIRED, 0 }, - { S_FIELD(Account), STI_ACCOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(MinimumOffer), STI_AMOUNT, SOE_IFFLAG, 1 }, - { S_FIELD(OfferCurrency),STI_HASH160, SOE_IFFLAG, 2 }, - { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } + { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, + { S_FIELD(Nickname), STI_HASH256, SOE_REQUIRED, 0 }, + { S_FIELD(Account), STI_ACCOUNT, SOE_REQUIRED, 0 }, + { S_FIELD(MinimumOffer), STI_AMOUNT, SOE_IFFLAG, 1 }, + { S_FIELD(OfferCurrency), STI_HASH160, SOE_IFFLAG, 2 }, + { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 }, + { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } }, { "RippleState", ltRIPPLE_STATE, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(Borrower), STI_ACCOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(Lender), STI_ACCOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(Limit), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(Balance), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(CurrentRate), STI_UINT32, SOE_IFFLAG, 1 }, - { S_FIELD(RateLock), STI_UINT32, SOE_IFFLAG, 2 }, - { S_FIELD(NextRate), STI_UINT32, SOE_IFFLAG, 4 }, - { S_FIELD(NextRateLgr), STI_UINT32, SOE_IFFLAG, 8 }, - { S_FIELD(NextRateExp), STI_UINT32, SOE_IFFLAG, 16 }, - { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } + { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, + { S_FIELD(Balance), STI_AMOUNT, SOE_REQUIRED, 0 }, + { S_FIELD(LowID), STI_ACCOUNT, SOE_REQUIRED, 0 }, + { S_FIELD(LowLimit), STI_AMOUNT, SOE_REQUIRED, 0 }, + { S_FIELD(HighID), STI_ACCOUNT, SOE_REQUIRED, 0 }, + { S_FIELD(HighLimit), STI_AMOUNT, SOE_REQUIRED, 0 }, + { S_FIELD(AcceptRate), STI_UINT32, SOE_IFFLAG, 1 }, + { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 }, + { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } }, { NULL, ltINVALID } }; diff --git a/src/LedgerFormats.h b/src/LedgerFormats.h index 931f359a3e..6adc19bc67 100644 --- a/src/LedgerFormats.h +++ b/src/LedgerFormats.h @@ -5,18 +5,37 @@ enum LedgerEntryType { - ltINVALID =-1, - ltACCOUNT_ROOT =0, - ltRIPPLE_STATE =1, - ltGENERATOR_MAP =2, - ltNICKNAME =3 + ltINVALID = -1, + ltACCOUNT_ROOT, + ltDIR_ROOT, + ltDIR_NODE, + ltGENERATOR_MAP, + ltRIPPLE_STATE, + ltNICKNAME +}; + +// In the format 160 + namespace + other. +enum LedgerNameSpace +{ + lnsGenerator = -1, + lnsAccounts, + lnsRipple, + lnsBonds, + lnsInvoices, + lnsMultiSig +}; + +enum LedgerSpecificFlags +{ + lsfLowIndexed = 0x00010000, + lsfHighIndexed = 0x00020000, }; struct LedgerEntryFormat { const char *t_name; LedgerEntryType t_type; - SOElement elements[16]; + SOElement elements[20]; }; extern LedgerEntryFormat LedgerFormats[]; diff --git a/src/LedgerIndex.cpp b/src/LedgerIndex.cpp index 8fd3b65708..a00f708344 100644 --- a/src/LedgerIndex.cpp +++ b/src/LedgerIndex.cpp @@ -1,11 +1,18 @@ #include "Ledger.h" -uint256 Ledger::getRippleIndex(const uint160& accountID, const uint160& extendTo, const uint160& currency) -{ // Index is 160-bit account credit extended to, 96-bit XOR of extending account and currency - uint256 base = getAccountRootIndex(extendTo); - memcpy(base.begin() + (160 / 8), (accountID ^ currency).begin(), (256 / 8) - (160 / 8)); - return base; +uint256 Ledger::getRippleStateIndex(const NewcoinAddress& naA, const NewcoinAddress& naB, const uint160& uCurrency) +{ + uint160 uAID = naA.getAccountID(); + uint160 uBID = naB.getAccountID(); + bool bAltB = uAID < uBID; + Serializer s; + + s.add160(bAltB ? uAID : uBID); + s.add160(bAltB ? uBID : uAID); + s.add160(uCurrency); + + return s.getSHA512Half(); } uint160 Ledger::getOfferBase(const uint160& currencyIn, const uint160& accountIn, diff --git a/src/LedgerNode.cpp b/src/LedgerNode.cpp index dc932ccbd9..5b079fedc7 100644 --- a/src/LedgerNode.cpp +++ b/src/LedgerNode.cpp @@ -137,4 +137,80 @@ SerializedLedgerEntry::pointer Ledger::getGenerator(LedgerStateParms& parms, con } } +// +// Ripple State +// + +SerializedLedgerEntry::pointer Ledger::getRippleState(LedgerStateParms& parms, const NewcoinAddress& naA, const NewcoinAddress& naB, const uint160& uCurrency) +{ + uint256 nodeID=getRippleStateIndex(naA, naB, uCurrency); + + ScopedLock l(mAccountStateMap->Lock()); + + try + { + return getASNode(parms, nodeID, ltRIPPLE_STATE); + } + catch (...) + { + parms = lepERROR; + return SerializedLedgerEntry::pointer(); + } +} + +// +// Directory +// + +uint256 Ledger::getDirIndex(const uint256& uBase, const LedgerEntryType letKind, const uint64 uNodeDir) +{ + // Indexes are stored in little endian format. + // The low bytes are indexed first, so when printed as a hex stream the hex is in byte order. + // Therefore, we place uNodeDir in the 8 right most bytes. + Serializer sKey; + + sKey.add256(uBase); + sKey.add8(letKind); + + uint256 uResult = sKey.getSHA512Half(); + + Serializer sNode; // Put in a fixed byte order: BIG. YYY + + sNode.add64(uNodeDir); + + std::copy(sNode.getData().end()-8, sNode.getData().end(), uResult.begin()+((256-64)/8)); + + return uResult; +} + +SerializedLedgerEntry::pointer Ledger::getDirRoot(LedgerStateParms& parms, const uint256& uRootIndex) +{ + ScopedLock l(mAccountStateMap->Lock()); + + try + { + return getASNode(parms, uRootIndex, ltDIR_ROOT); + } + catch (...) + { + parms = lepERROR; + return SerializedLedgerEntry::pointer(); + } +} + +SerializedLedgerEntry::pointer Ledger::getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex) +{ + ScopedLock l(mAccountStateMap->Lock()); + + try + { + return getASNode(parms, uNodeIndex, ltDIR_NODE); + } + catch (...) + { + parms = lepERROR; + return SerializedLedgerEntry::pointer(); + } +} + // vim:ts=4 diff --git a/src/SerializedLedger.h b/src/SerializedLedger.h index f858629e28..da0eb6ad3a 100644 --- a/src/SerializedLedger.h +++ b/src/SerializedLedger.h @@ -32,6 +32,10 @@ public: void add(Serializer& s) const { mVersion.add(s); mObject.add(s); } virtual bool isEquivalent(const SerializedType& t) const; + bool setFlag(uint32 uSet) { return mObject.setFlag(uSet); } + bool clearFlag(uint32 uClear) { return mObject.clearFlag(uClear); } + uint32 getFlags() const { return mObject.getFlags(); } + const uint256& getIndex() const { return mIndex; } void setIndex(const uint256& i) { mIndex = i; } @@ -55,6 +59,8 @@ public: std::vector getIFieldTL(SOE_Field field) const { return mObject.getValueFieldTL(field); } NewcoinAddress getIValueFieldAccount(SOE_Field field) const { return mObject.getValueFieldAccount(field); } STAmount getIValueFieldAmount(SOE_Field field) const { return mObject.getValueFieldAmount(field); } + STVector256 getIFieldV256(SOE_Field field) { return mObject.getValueFieldV256(field); } + void setIFieldU8(SOE_Field field, unsigned char v) { return mObject.setValueFieldU8(field, v); } void setIFieldU16(SOE_Field field, uint16 v) { return mObject.setValueFieldU16(field, v); } void setIFieldU32(SOE_Field field, uint32 v) { return mObject.setValueFieldU32(field, v); } @@ -71,6 +77,7 @@ public: { return mObject.setValueFieldAccount(field, account); } void setIFieldAmount(SOE_Field field, const STAmount& amount) { return mObject.setValueFieldAmount(field, amount); } + void setIFieldV256(SOE_Field field, const STVector256& v) { return mObject.setValueFieldV256(field, v); } bool getIFieldPresent(SOE_Field field) const { return mObject.isFieldPresent(field); } void makeIFieldPresent(SOE_Field field) { mObject.makeFieldPresent(field); }