Add ledger support for directories and ripple state.

This commit is contained in:
Arthur Britto
2012-05-26 02:54:03 -07:00
parent e03f452a05
commit 48d3099c00
6 changed files with 190 additions and 57 deletions

View File

@@ -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<Ledger>
@@ -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<Ledger> other);
// bool signLedger(std::vector<unsigned char> &signature, const LocalHanko &hanko);

View File

@@ -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 }
};

View File

@@ -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[];

View File

@@ -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,

View File

@@ -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

View File

@@ -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<TaggedListItem> 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); }