mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Move to new directory format.
This commit is contained in:
@@ -209,11 +209,16 @@ public:
|
||||
// Directory functions
|
||||
//
|
||||
|
||||
static uint256 getDirIndex(const uint256& uBase, const uint64 uNodeDir=0);
|
||||
static uint256 getDirNodeIndex(const uint256& uDirRoot, const uint64 uNodeIndex=0);
|
||||
|
||||
SLE::pointer getDirRoot(LedgerStateParms& parms, const uint256& uRootIndex);
|
||||
SLE::pointer getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex);
|
||||
|
||||
//
|
||||
// Quality
|
||||
//
|
||||
|
||||
static uint256 getQualityIndex(const uint256& uBase, const uint64 uNodeDir=0);
|
||||
|
||||
//
|
||||
// Ripple functions : credit lines
|
||||
//
|
||||
|
||||
@@ -20,16 +20,11 @@ LedgerEntryFormat LedgerFormats[]=
|
||||
{ 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(IndexNext), STI_UINT64, SOE_IFFLAG, 1 },
|
||||
{ S_FIELD(IndexPrevious), STI_UINT64, SOE_IFFLAG, 2 },
|
||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||
},
|
||||
|
||||
@@ -8,7 +8,6 @@ enum LedgerEntryType
|
||||
{
|
||||
ltINVALID = -1,
|
||||
ltACCOUNT_ROOT = 'a',
|
||||
ltDIR_ROOT = 'D',
|
||||
ltDIR_NODE = 'd',
|
||||
ltGENERATOR_MAP = 'g',
|
||||
ltRIPPLE_STATE = 'r',
|
||||
@@ -20,6 +19,7 @@ enum LedgerEntryType
|
||||
enum LedgerNameSpace
|
||||
{
|
||||
spaceAccount = 'a',
|
||||
spaceDirNode = 'd',
|
||||
spaceGenerator = 'g',
|
||||
spaceNickname = 'n',
|
||||
spaceRipple = 'r',
|
||||
|
||||
@@ -1,60 +1,26 @@
|
||||
|
||||
#include "Ledger.h"
|
||||
|
||||
// For an entry put in the 64 bit index or quality.
|
||||
uint256 Ledger::getQualityIndex(const uint256& uBase, const uint64 uNodeDir)
|
||||
{
|
||||
// Indexes are stored in big endian format: they print as hex as stored.
|
||||
// Most significant bytes are first. Least significant bytes repesent adjcent entries.
|
||||
// We place uNodeDir in the 8 right most bytes to be adjcent.
|
||||
// Want uNodeDir in big endian format so ++ goes to the next entry for indexes.
|
||||
uint256 uNode(uBase);
|
||||
|
||||
((uint64*) uNode.end())[-1] = htobe64(uNodeDir);
|
||||
|
||||
return uNode;
|
||||
}
|
||||
|
||||
uint256 Ledger::getAccountRootIndex(const uint160& uAccountID)
|
||||
{
|
||||
Serializer s;
|
||||
Serializer s(22);
|
||||
|
||||
s.add16(spaceAccount);
|
||||
s.add160(uAccountID);
|
||||
|
||||
return s.getSHA512Half();
|
||||
}
|
||||
|
||||
// What is important:
|
||||
// --> uNickname: is a Sha256
|
||||
// <-- SHA512/2: for consistency and speed in generating indexes.
|
||||
uint256 Ledger::getNicknameIndex(const uint256& uNickname)
|
||||
{
|
||||
Serializer s;
|
||||
|
||||
s.add16(spaceNickname);
|
||||
s.add256(uNickname);
|
||||
|
||||
return s.getSHA512Half();
|
||||
}
|
||||
|
||||
uint256 Ledger::getGeneratorIndex(const uint160& uGeneratorID)
|
||||
{
|
||||
Serializer s;
|
||||
|
||||
s.add16(spaceGenerator);
|
||||
s.add160(uGeneratorID);
|
||||
|
||||
return s.getSHA512Half();
|
||||
}
|
||||
|
||||
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.add16(spaceRipple);
|
||||
s.add160(bAltB ? uAID : uBID);
|
||||
s.add160(bAltB ? uBID : uAID);
|
||||
s.add160(uCurrency);
|
||||
|
||||
return s.getSHA512Half();
|
||||
}
|
||||
|
||||
uint256 Ledger::getRippleDirIndex(const uint160& uAccountID)
|
||||
{
|
||||
Serializer s;
|
||||
|
||||
s.add16(spaceRippleDir);
|
||||
s.add160(uAccountID);
|
||||
s.add16(spaceAccount); // 2
|
||||
s.add160(uAccountID); // 20
|
||||
|
||||
return s.getSHA512Half();
|
||||
}
|
||||
@@ -78,26 +44,92 @@ uint256 Ledger::getBookBase(const uint160& uCurrencyIn, const uint160& uAccountI
|
||||
s.add160(uAccountIn); // 20
|
||||
s.add160(uAccountOut); // 20
|
||||
|
||||
return getDirIndex(s.getSHA512Half()); // Return with index 0.
|
||||
return getQualityIndex(s.getSHA512Half()); // Return with quality 0.
|
||||
}
|
||||
|
||||
uint256 Ledger::getDirNodeIndex(const uint256& uDirRoot, const uint64 uNodeIndex)
|
||||
{
|
||||
if (uNodeIndex)
|
||||
{
|
||||
Serializer s(42);
|
||||
|
||||
s.add16(spaceDirNode); // 2
|
||||
s.add256(uDirRoot); // 32
|
||||
s.add64(uNodeIndex); // 8
|
||||
|
||||
return s.getSHA512Half();
|
||||
}
|
||||
else
|
||||
{
|
||||
return uDirRoot;
|
||||
}
|
||||
}
|
||||
|
||||
uint256 Ledger::getGeneratorIndex(const uint160& uGeneratorID)
|
||||
{
|
||||
Serializer s(22);
|
||||
|
||||
s.add16(spaceGenerator); // 2
|
||||
s.add160(uGeneratorID); // 20
|
||||
|
||||
return s.getSHA512Half();
|
||||
}
|
||||
|
||||
// What is important:
|
||||
// --> uNickname: is a Sha256
|
||||
// <-- SHA512/2: for consistency and speed in generating indexes.
|
||||
uint256 Ledger::getNicknameIndex(const uint256& uNickname)
|
||||
{
|
||||
Serializer s(34);
|
||||
|
||||
s.add16(spaceNickname); // 2
|
||||
s.add256(uNickname); // 32
|
||||
|
||||
return s.getSHA512Half();
|
||||
}
|
||||
|
||||
uint256 Ledger::getOfferIndex(const uint160& uAccountID, uint32 uSequence)
|
||||
{
|
||||
Serializer s;
|
||||
Serializer s(26);
|
||||
|
||||
s.add16(spaceOffer);
|
||||
s.add160(uAccountID);
|
||||
s.add32(uSequence);
|
||||
s.add16(spaceOffer); // 2
|
||||
s.add160(uAccountID); // 20
|
||||
s.add32(uSequence); // 4
|
||||
|
||||
return s.getSHA512Half();
|
||||
}
|
||||
|
||||
uint256 Ledger::getOfferDirIndex(const uint160& uAccountID)
|
||||
{
|
||||
Serializer s;
|
||||
Serializer s(22);
|
||||
|
||||
s.add16(spaceOfferDir);
|
||||
s.add160(uAccountID);
|
||||
s.add16(spaceOfferDir); // 2
|
||||
s.add160(uAccountID); // 20
|
||||
|
||||
return s.getSHA512Half();
|
||||
}
|
||||
|
||||
uint256 Ledger::getRippleDirIndex(const uint160& uAccountID)
|
||||
{
|
||||
Serializer s(22);
|
||||
|
||||
s.add16(spaceRippleDir); // 2
|
||||
s.add160(uAccountID); // 20
|
||||
|
||||
return s.getSHA512Half();
|
||||
}
|
||||
|
||||
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(62);
|
||||
|
||||
s.add16(spaceRipple); // 2
|
||||
s.add160(bAltB ? uAID : uBID); // 20
|
||||
s.add160(bAltB ? uBID : uAID); // 20
|
||||
s.add160(uCurrency); // 20
|
||||
|
||||
return s.getSHA512Half();
|
||||
}
|
||||
|
||||
@@ -29,7 +29,8 @@ LedgerStateParms Ledger::writeBack(LedgerStateParms parms, SLE::pointer entry)
|
||||
if (create)
|
||||
{
|
||||
assert(!mAccountStateMap->hasItem(entry->getIndex()));
|
||||
if(!mAccountStateMap->addGiveItem(item, false))
|
||||
|
||||
if (!mAccountStateMap->addGiveItem(item, false))
|
||||
{
|
||||
assert(false);
|
||||
return lepERROR;
|
||||
@@ -68,7 +69,7 @@ SLE::pointer Ledger::getASNode(LedgerStateParms& parms, const uint256& nodeID,
|
||||
SLE::pointer sle =
|
||||
boost::make_shared<SLE>(account->peekSerializer(), nodeID);
|
||||
|
||||
if(sle->getType() != let)
|
||||
if (sle->getType() != let)
|
||||
{ // maybe it's a currency or something
|
||||
parms = parms | lepWRONGTYPE;
|
||||
return SLE::pointer();
|
||||
@@ -92,6 +93,17 @@ SLE::pointer Ledger::getAccountRoot(LedgerStateParms& parms, const NewcoinAddres
|
||||
return getAccountRoot(parms, naAccountID.getAccountID());
|
||||
}
|
||||
|
||||
//
|
||||
// Directory
|
||||
//
|
||||
|
||||
SLE::pointer Ledger::getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex)
|
||||
{
|
||||
ScopedLock l(mAccountStateMap->Lock());
|
||||
|
||||
return getASNode(parms, uNodeIndex, ltDIR_NODE);
|
||||
}
|
||||
|
||||
//
|
||||
// Generator Map
|
||||
//
|
||||
@@ -137,36 +149,4 @@ SLE::pointer Ledger::getRippleState(LedgerStateParms& parms, const uint256& uNod
|
||||
return getASNode(parms, uNode, ltRIPPLE_STATE);
|
||||
}
|
||||
|
||||
//
|
||||
// Directory
|
||||
//
|
||||
|
||||
// For a directory entry put in the 64 bit index or quality.
|
||||
uint256 Ledger::getDirIndex(const uint256& uBase, const uint64 uNodeDir)
|
||||
{
|
||||
// Indexes are stored in big endian format: they print as hex as stored.
|
||||
// Most significant bytes are first. Least significant bytes repesent adjcent entries.
|
||||
// We place uNodeDir in the 8 right most bytes to be adjcent.
|
||||
// Want uNodeDir in big endian format so ++ goes to the next entry for indexes.
|
||||
uint256 uNode(uBase);
|
||||
|
||||
((uint64*) uNode.end())[-1] = htobe64(uNodeDir);
|
||||
|
||||
return uNode;
|
||||
}
|
||||
|
||||
SLE::pointer Ledger::getDirRoot(LedgerStateParms& parms, const uint256& uRootIndex)
|
||||
{
|
||||
ScopedLock l(mAccountStateMap->Lock());
|
||||
|
||||
return getASNode(parms, uRootIndex, ltDIR_ROOT);
|
||||
}
|
||||
|
||||
SLE::pointer Ledger::getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex)
|
||||
{
|
||||
ScopedLock l(mAccountStateMap->Lock());
|
||||
|
||||
return getASNode(parms, uNodeIndex, ltDIR_NODE);
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -98,7 +98,7 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
|
||||
return trans;
|
||||
}
|
||||
|
||||
Log(lsDEBUG) << "Status other than success " << r ;
|
||||
Log(lsDEBUG) << "Status other than success " << r;
|
||||
if ((mMode != omFULL) && (mMode != omTRACKING) && (theApp->isNew(trans->getID())))
|
||||
{
|
||||
newcoin::TMTransaction tx;
|
||||
@@ -171,53 +171,32 @@ SLE::pointer NetworkOPs::getGenerator(const uint256& uLedger, const uint160& uGe
|
||||
//
|
||||
|
||||
// <-- false : no entrieS
|
||||
bool NetworkOPs::getDirInfo(
|
||||
const uint256& uLedger,
|
||||
const uint256& uBase,
|
||||
uint256& uDirLineNodeFirst,
|
||||
uint256& uDirLineNodeLast)
|
||||
STVector256 NetworkOPs::getDirNodeInfo(
|
||||
const uint256& uLedger,
|
||||
const uint256& uNodeIndex,
|
||||
uint64& uNodePrevious,
|
||||
uint64& uNodeNext)
|
||||
{
|
||||
uint256 uRootIndex = Ledger::getDirIndex(uBase, 0);
|
||||
LedgerStateParms lspRoot = lepNONE;
|
||||
SLE::pointer sleRoot = mLedgerMaster->getLedgerByHash(uLedger)->getDirRoot(lspRoot, uRootIndex);
|
||||
|
||||
if (sleRoot)
|
||||
{
|
||||
Log(lsDEBUG) << "getDirInfo: root index: " << uRootIndex.ToString() ;
|
||||
|
||||
Log(lsTRACE) << "getDirInfo: first: " << strHex(sleRoot->getIFieldU64(sfFirstNode)) ;
|
||||
Log(lsTRACE) << "getDirInfo: last: " << strHex(sleRoot->getIFieldU64(sfLastNode)) ;
|
||||
|
||||
uDirLineNodeFirst = Ledger::getDirIndex(uBase, sleRoot->getIFieldU64(sfFirstNode));
|
||||
uDirLineNodeLast = Ledger::getDirIndex(uBase, sleRoot->getIFieldU64(sfLastNode));
|
||||
|
||||
Log(lsTRACE) << "getDirInfo: first: " << uDirLineNodeFirst.ToString() ;
|
||||
Log(lsTRACE) << "getDirInfo: last: " << uDirLineNodeLast.ToString() ;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsINFO) << "getDirInfo: root index: NOT FOUND: " << uRootIndex.ToString() ;
|
||||
}
|
||||
|
||||
return !!sleRoot;
|
||||
}
|
||||
|
||||
STVector256 NetworkOPs::getDirNode(const uint256& uLedger, const uint256& uDirLineNode)
|
||||
{
|
||||
STVector256 svIndexes;
|
||||
|
||||
STVector256 svIndexes;
|
||||
LedgerStateParms lspNode = lepNONE;
|
||||
SLE::pointer sleNode = mLedgerMaster->getLedgerByHash(uLedger)->getDirNode(lspNode, uDirLineNode);
|
||||
SLE::pointer sleNode = mLedgerMaster->getLedgerByHash(uLedger)->getDirNode(lspNode, uNodeIndex);
|
||||
|
||||
if (sleNode)
|
||||
{
|
||||
Log(lsWARNING) << "getDirNode: node index: " << uDirLineNode.ToString() ;
|
||||
Log(lsDEBUG) << "getDirNodeInfo: node index: " << uNodeIndex.ToString();
|
||||
|
||||
svIndexes = sleNode->getIFieldV256(sfIndexes);
|
||||
Log(lsTRACE) << "getDirNodeInfo: first: " << strHex(sleNode->getIFieldU64(sfIndexPrevious));
|
||||
Log(lsTRACE) << "getDirNodeInfo: last: " << strHex(sleNode->getIFieldU64(sfIndexNext));
|
||||
|
||||
uNodePrevious = sleNode->getIFieldU64(sfIndexPrevious);
|
||||
uNodeNext = sleNode->getIFieldU64(sfIndexNext);
|
||||
|
||||
Log(lsTRACE) << "getDirNodeInfo: first: " << strHex(uNodePrevious);
|
||||
Log(lsTRACE) << "getDirNodeInfo: last: " << strHex(uNodeNext);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsINFO) << "getDirNode: node index: NOT FOUND: " << uDirLineNode.ToString() ;
|
||||
Log(lsINFO) << "getDirNodeInfo: node index: NOT FOUND: " << uNodeIndex.ToString();
|
||||
}
|
||||
|
||||
return svIndexes;
|
||||
@@ -473,7 +452,7 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector<Peer::pointer>& peerLis
|
||||
void NetworkOPs::switchLastClosedLedger(Ledger::pointer newLedger)
|
||||
{ // set the newledger as our last closed ledger -- this is abnormal code
|
||||
|
||||
Log(lsERROR) << "ABNORMAL Switching last closed ledger to " << newLedger->getHash().GetHex() ;
|
||||
Log(lsERROR) << "ABNORMAL Switching last closed ledger to " << newLedger->getHash().GetHex();
|
||||
|
||||
if (mConsensus)
|
||||
{
|
||||
@@ -499,7 +478,7 @@ void NetworkOPs::switchLastClosedLedger(Ledger::pointer newLedger)
|
||||
|
||||
int NetworkOPs::beginConsensus(const uint256& networkClosed, Ledger::pointer closingLedger)
|
||||
{
|
||||
Log(lsINFO) << "Ledger close time for ledger " << closingLedger->getLedgerSeq() ;
|
||||
Log(lsINFO) << "Ledger close time for ledger " << closingLedger->getLedgerSeq();
|
||||
Log(lsINFO) << " LCL is " << closingLedger->getParentHash().GetHex();
|
||||
|
||||
Ledger::pointer prevLedger = mLedgerMaster->getLedgerByHash(closingLedger->getParentHash());
|
||||
|
||||
@@ -109,9 +109,8 @@ public:
|
||||
// Directory functions
|
||||
//
|
||||
|
||||
bool getDirInfo(const uint256& uLedger, const uint256& uBase,
|
||||
uint256& uDirNodeFirst, uint256& uDirNodeLast);
|
||||
STVector256 getDirNode(const uint256& uLedger, const uint256& uDirLineNode);
|
||||
STVector256 getDirNodeInfo(const uint256& uLedger, const uint256& uRootIndex,
|
||||
uint64& uNodePrevious, uint64& uNodeNext);
|
||||
|
||||
//
|
||||
// Nickname functions
|
||||
@@ -123,8 +122,14 @@ public:
|
||||
// Ripple functions
|
||||
//
|
||||
|
||||
bool getDirLineInfo(const uint256& uLedger, const NewcoinAddress& naAccount, uint256& uDirLineNodeFirst, uint256& uDirLineNodeLast)
|
||||
{ return getDirInfo(uLedger, Ledger::getRippleDirIndex(naAccount.getAccountID()), uDirLineNodeFirst, uDirLineNodeLast); }
|
||||
bool getDirLineInfo(const uint256& uLedger, const NewcoinAddress& naAccount, uint256& uRootIndex)
|
||||
{
|
||||
LedgerStateParms lspNode = lepNONE;
|
||||
|
||||
uRootIndex = Ledger::getRippleDirIndex(naAccount.getAccountID());
|
||||
|
||||
return !!mLedgerMaster->getLedgerByHash(uLedger)->getDirNode(lspNode, uRootIndex);
|
||||
}
|
||||
|
||||
RippleState::pointer getRippleState(const uint256& uLedger, const uint256& uIndex);
|
||||
|
||||
|
||||
@@ -559,14 +559,17 @@ Json::Value RPCServer::doAccountLines(const Json::Value ¶ms)
|
||||
ret["account"] = naAccount.humanAccountID();
|
||||
|
||||
// We access a committed ledger and need not worry about changes.
|
||||
uint256 uDirLineNodeFirst;
|
||||
uint256 uDirLineNodeLast;
|
||||
uint256 uRootIndex;
|
||||
|
||||
if (mNetOps->getDirLineInfo(uCurrent, naAccount, uDirLineNodeFirst, uDirLineNodeLast))
|
||||
if (mNetOps->getDirLineInfo(uCurrent, naAccount, uRootIndex))
|
||||
{
|
||||
for (; uDirLineNodeFirst <= uDirLineNodeLast; uDirLineNodeFirst++)
|
||||
bool bDone = false;
|
||||
|
||||
while (!bDone)
|
||||
{
|
||||
STVector256 svRippleNodes = mNetOps->getDirNode(uCurrent, uDirLineNodeFirst);
|
||||
uint64 uNodePrevious;
|
||||
uint64 uNodeNext;
|
||||
STVector256 svRippleNodes = mNetOps->getDirNodeInfo(uCurrent, uRootIndex, uNodePrevious, uNodeNext);
|
||||
|
||||
BOOST_FOREACH(uint256& uNode, svRippleNodes.peekValue())
|
||||
{
|
||||
@@ -602,6 +605,15 @@ Json::Value RPCServer::doAccountLines(const Json::Value ¶ms)
|
||||
std::cerr << "doAccountLines: Bad index: " << uNode.ToString() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (uNodeNext)
|
||||
{
|
||||
uCurrent = Ledger::getDirNodeIndex(uRootIndex, uNodeNext);
|
||||
}
|
||||
else
|
||||
{
|
||||
bDone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret["lines"] = jsonLines;
|
||||
|
||||
@@ -55,6 +55,8 @@ enum SOE_Field
|
||||
sfHighLimit,
|
||||
sfIdentifier,
|
||||
sfIndexes,
|
||||
sfIndexNext,
|
||||
sfIndexPrevious,
|
||||
sfInvoiceID,
|
||||
sfIssuerIn,
|
||||
sfIssuerOut,
|
||||
|
||||
@@ -30,8 +30,8 @@ bool transResultInfo(TransactionEngineResult terCode, std::string& strToken, std
|
||||
{ tenBAD_CLAIM_ID, "tenBAD_CLAIM_ID", "Malformed." },
|
||||
{ tenBAD_EXPIRATION, "tenBAD_EXPIRATION", "Malformed." },
|
||||
{ tenBAD_GEN_AUTH, "tenBAD_GEN_AUTH", "Not authorized to claim generator." },
|
||||
{ tenBAD_OFFER, "tenBAD_OFFER", "Malformed." },
|
||||
{ tenBAD_ISSUER, "tenBAD_ISSUER", "Malformed." },
|
||||
{ tenBAD_OFFER, "tenBAD_OFFER", "Malformed." },
|
||||
{ tenBAD_RIPPLE, "tenBAD_RIPPLE", "Ledger prevents ripple from succeeding." },
|
||||
{ tenBAD_SET_ID, "tenBAD_SET_ID", "Malformed." },
|
||||
{ tenCLAIMED, "tenCLAIMED", "Can not claim a previously claimed account." },
|
||||
@@ -51,6 +51,7 @@ bool transResultInfo(TransactionEngineResult terCode, std::string& strToken, std
|
||||
{ tenUNKNOWN, "tenUNKNOWN", "The transactions requires logic not implemented yet" },
|
||||
{ terALREADY, "terALREADY", "The exact transaction was already in this ledger" },
|
||||
{ terBAD_AUTH, "terBAD_AUTH", "Transaction's public key is not authorized." },
|
||||
{ terBAD_LEDGER, "terBAD_LEDGER", "Ledger in unexpected state." },
|
||||
{ terBAD_RIPPLE, "terBAD_RIPPLE", "No ripple path can be satisfied." },
|
||||
{ terBAD_SEQ, "terBAD_SEQ", "This sequence number should be zero for prepaid transactions." },
|
||||
{ terCREATED, "terCREATED", "Can not create a previously created account." },
|
||||
@@ -58,9 +59,9 @@ bool transResultInfo(TransactionEngineResult terCode, std::string& strToken, std
|
||||
{ terFUNDS_SPENT, "terFUNDS_SPENT", "Can't set password, password set funds already spent." },
|
||||
{ terINSUF_FEE_B, "terINSUF_FEE_B", "Account balance can't pay fee" },
|
||||
{ terINSUF_FEE_T, "terINSUF_FEE_T", "fee insufficient now (account doesn't exist, network load)" },
|
||||
{ terNODE_NOT_FOUND, "terNODE_NOT_FOUND", "Can not delete a dir node." },
|
||||
{ terNODE_NOT_MENTIONED, "terNODE_NOT_MENTIONED", "?" },
|
||||
{ terNODE_NO_ROOT, "terNODE_NO_ROOT", "?" },
|
||||
{ terNODE_NOT_FOUND, "terNODE_NOT_FOUND", "Can not delete a directory node." },
|
||||
{ terNODE_NOT_MENTIONED, "terNODE_NOT_MENTIONED", "Could not remove node from a directory." },
|
||||
{ terNODE_NO_ROOT, "terNODE_NO_ROOT", "Directory doesn't exist." },
|
||||
{ terNO_ACCOUNT, "terNO_ACCOUNT", "The source account does not exist" },
|
||||
{ terNO_DST, "terNO_DST", "The destination does not exist" },
|
||||
{ terNO_LINE_NO_ZERO, "terNO_LINE_NO_ZERO", "Can't zero non-existant line, destination might make it." },
|
||||
@@ -92,123 +93,126 @@ bool transResultInfo(TransactionEngineResult terCode, std::string& strToken, std
|
||||
|
||||
// <-> accounts: Affected accounts for the transaction.
|
||||
// <-- uNodeDir: For deletion, present to make dirDelete efficient.
|
||||
// --> uBase: The index of the base of the directory. Nodes are based off of this.
|
||||
// --> uRootIndex: The index of the base of the directory. Nodes are based off of this.
|
||||
// --> uLedgerIndex: Value to add to directory.
|
||||
// We only append. This allow for things that watch append only structure to just monitor from the last node on ward.
|
||||
// Within a node with no deletions order of elements is sequential. Otherwise, order of elements is random.
|
||||
TransactionEngineResult TransactionEngine::dirAdd(
|
||||
std::vector<AffectedAccount>& accounts,
|
||||
uint64& uNodeDir,
|
||||
const uint256& uBase,
|
||||
const uint256& uRootIndex,
|
||||
const uint256& uLedgerIndex)
|
||||
{
|
||||
// Get the root.
|
||||
uint256 uRootIndex = Ledger::getDirIndex(uBase, 0);
|
||||
SLE::pointer sleNode;
|
||||
STVector256 svIndexes;
|
||||
LedgerStateParms lspRoot = lepNONE;
|
||||
SLE::pointer sleRoot = mLedger->getDirRoot(lspRoot, uRootIndex);
|
||||
bool bRootNew;
|
||||
SLE::pointer sleRoot = mLedger->getDirNode(lspRoot, uRootIndex);
|
||||
|
||||
// Get the last node index.
|
||||
if (sleRoot)
|
||||
if (!sleRoot)
|
||||
{
|
||||
bRootNew = false;
|
||||
uNodeDir = sleRoot->getIFieldU64(sfLastNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
bRootNew = true;
|
||||
uNodeDir = 1;
|
||||
// No root, make it.
|
||||
Log(lsTRACE) << "dirAdd: Creating dir root: " << uRootIndex.ToString();
|
||||
|
||||
sleRoot = boost::make_shared<SerializedLedgerEntry>(ltDIR_ROOT);
|
||||
uNodeDir = 0;
|
||||
|
||||
sleRoot = boost::make_shared<SerializedLedgerEntry>(ltDIR_NODE);
|
||||
sleRoot->setIndex(uRootIndex);
|
||||
Log(lsTRACE) << "dirAdd: Creating dir index: " << sleRoot->getIndex().ToString();
|
||||
|
||||
sleRoot->setIFieldU64(sfFirstNode, uNodeDir);
|
||||
sleRoot->setIFieldU64(sfLastNode, uNodeDir);
|
||||
|
||||
Log(lsTRACE) << "dirAdd: first & last: " << strHex(uNodeDir);
|
||||
sleNode = sleRoot;
|
||||
|
||||
accounts.push_back(std::make_pair(taaCREATE, sleRoot));
|
||||
}
|
||||
|
||||
// Get the last node.
|
||||
uint256 uNodeIndex = Ledger::getDirIndex(uBase, uNodeDir);
|
||||
LedgerStateParms lspNode = lepNONE;
|
||||
SLE::pointer sleNode = bRootNew ? SLE::pointer() : mLedger->getDirNode(lspNode, uNodeIndex);
|
||||
|
||||
if (sleNode)
|
||||
else
|
||||
{
|
||||
STVector256 svIndexes;
|
||||
uNodeDir = sleRoot->getIFieldU64(sfIndexPrevious);
|
||||
|
||||
uint64 uNodePrevious = uNodeDir;
|
||||
uint256 uNodeIndex;
|
||||
|
||||
if (uNodeDir)
|
||||
{
|
||||
// Try adding to non-root.
|
||||
uNodeIndex = Ledger::getDirNodeIndex(uRootIndex, uNodeDir);
|
||||
lspRoot = lepNONE;
|
||||
sleNode = mLedger->getDirNode(lspRoot, uNodeIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try adding to root.
|
||||
uNodeIndex = uRootIndex;
|
||||
}
|
||||
|
||||
svIndexes = sleNode->getIFieldV256(sfIndexes);
|
||||
|
||||
if (DIR_NODE_MAX != svIndexes.peekValue().size())
|
||||
{
|
||||
// Last node is not full, append.
|
||||
|
||||
Log(lsTRACE) << "dirAdd: appending: PREV: " << svIndexes.peekValue()[0].ToString();
|
||||
Log(lsTRACE) << "dirAdd: appending: Node: " << strHex(uNodeDir);
|
||||
Log(lsTRACE) << "dirAdd: appending: Entry: " << uLedgerIndex.ToString();
|
||||
|
||||
svIndexes.peekValue().push_back(uLedgerIndex);
|
||||
sleNode->setIFieldV256(sfIndexes, svIndexes);
|
||||
|
||||
// Add to current node.
|
||||
accounts.push_back(std::make_pair(taaMODIFY, sleNode));
|
||||
}
|
||||
// Last node is full, add a new node.
|
||||
// Add to new node.
|
||||
else if (!++uNodeDir)
|
||||
{
|
||||
return terDIR_FULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Record new last node.
|
||||
sleNode = SLE::pointer();
|
||||
|
||||
Log(lsTRACE) << "dirAdd: last: " << strHex(uNodeDir);
|
||||
|
||||
sleRoot->setIFieldU64(sfLastNode, uNodeDir);
|
||||
|
||||
// Have root point to new node.
|
||||
sleRoot->setIFieldU64(sfIndexPrevious, uNodeDir);
|
||||
accounts.push_back(std::make_pair(taaMODIFY, sleRoot));
|
||||
|
||||
// Have old last point to new node, if it was not root.
|
||||
if (uNodePrevious)
|
||||
{
|
||||
// Previous node is not root node.
|
||||
sleNode->setIFieldU64(sfIndexNext, uNodeDir);
|
||||
accounts.push_back(std::make_pair(taaMODIFY, sleNode));
|
||||
}
|
||||
|
||||
// Create the new node.
|
||||
svIndexes = STVector256();
|
||||
sleNode = boost::make_shared<SerializedLedgerEntry>(ltDIR_NODE);
|
||||
sleNode->setIndex(uNodeIndex);
|
||||
|
||||
if (uNodePrevious)
|
||||
sleNode->setIFieldU64(sfIndexPrevious, uNodePrevious);
|
||||
|
||||
accounts.push_back(std::make_pair(taaCREATE, sleNode));
|
||||
}
|
||||
}
|
||||
|
||||
if (!sleNode)
|
||||
{
|
||||
// Add to last node, which is empty.
|
||||
sleNode = boost::make_shared<SerializedLedgerEntry>(ltDIR_NODE);
|
||||
sleNode->setIndex(uNodeIndex);
|
||||
Log(lsTRACE) << "dirAdd: appending: PREV: " << svIndexes.peekValue()[0].ToString();
|
||||
Log(lsTRACE) << "dirAdd: appending: Node: " << strHex(uNodeDir);
|
||||
Log(lsTRACE) << "dirAdd: appending: Entry: " << uLedgerIndex.ToString();
|
||||
|
||||
Log(lsTRACE) << "dirAdd: Creating dir node: " << sleNode->getIndex().ToString();
|
||||
|
||||
STVector256 svIndexes;
|
||||
|
||||
svIndexes.peekValue().push_back(uLedgerIndex);
|
||||
sleNode->setIFieldV256(sfIndexes, svIndexes);
|
||||
|
||||
accounts.push_back(std::make_pair(taaCREATE, sleNode));
|
||||
}
|
||||
svIndexes.peekValue().push_back(uLedgerIndex); // Append entry.
|
||||
sleNode->setIFieldV256(sfIndexes, svIndexes); // Save entry.
|
||||
|
||||
return terSUCCESS;
|
||||
}
|
||||
|
||||
// <-> accounts: Affected accounts for the transaction.
|
||||
// --> uNodeDir: Node containing entry.
|
||||
// --> uBase: The index of the base of the directory. Nodes are based off of this.
|
||||
// --> uRootIndex: The index of the base of the directory. Nodes are based off of this.
|
||||
// --> uLedgerIndex: Value to add to directory.
|
||||
// Ledger must be in a state for this to work.
|
||||
TransactionEngineResult TransactionEngine::dirDelete(
|
||||
std::vector<AffectedAccount>& accounts,
|
||||
const uint64& uNodeDir,
|
||||
const uint256& uBase,
|
||||
const uint256& uRootIndex,
|
||||
const uint256& uLedgerIndex)
|
||||
{
|
||||
uint64 uNodeCur = uNodeDir;
|
||||
uint256 uNodeIndex = Ledger::getDirIndex(uBase, uNodeCur);
|
||||
uint256 uNodeIndex = Ledger::getDirNodeIndex(uRootIndex, uNodeCur);
|
||||
LedgerStateParms lspNode = lepNONE;
|
||||
SLE::pointer sleNode = mLedger->getDirNode(lspNode, uNodeIndex);
|
||||
|
||||
assert(sleNode);
|
||||
|
||||
if (!sleNode)
|
||||
{
|
||||
Log(lsWARNING) << "dirDelete: no such node";
|
||||
return terNODE_NOT_FOUND;
|
||||
|
||||
return terBAD_LEDGER;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -217,93 +221,151 @@ TransactionEngineResult TransactionEngine::dirDelete(
|
||||
std::vector<uint256>::iterator it;
|
||||
|
||||
it = std::find(vuiIndexes.begin(), vuiIndexes.end(), uLedgerIndex);
|
||||
|
||||
assert(vuiIndexes.end() != it);
|
||||
if (vuiIndexes.end() == it)
|
||||
{
|
||||
Log(lsWARNING) << "dirDelete: node not mentioned";
|
||||
return terNODE_NOT_MENTIONED;
|
||||
|
||||
return terBAD_LEDGER;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get root information
|
||||
LedgerStateParms lspRoot = lepNONE;
|
||||
SLE::pointer sleRoot = mLedger->getDirRoot(lspRoot, Ledger::getDirIndex(uBase, 0));
|
||||
|
||||
if (!sleRoot)
|
||||
{
|
||||
Log(lsWARNING) << "dirDelete: root node is missing";
|
||||
return terNODE_NO_ROOT;
|
||||
}
|
||||
|
||||
uint64 uFirstNodeOrig = sleRoot->getIFieldU64(sfFirstNode);
|
||||
uint64 uLastNodeOrig = sleRoot->getIFieldU64(sfLastNode);
|
||||
uint64 uFirstNode = uFirstNodeOrig;
|
||||
uint64 uLastNode = uLastNodeOrig;
|
||||
|
||||
// Remove the element.
|
||||
if (vuiIndexes.size() > 1)
|
||||
{
|
||||
*it = vuiIndexes[vuiIndexes.size()-1];
|
||||
}
|
||||
|
||||
vuiIndexes.resize(vuiIndexes.size()-1);
|
||||
|
||||
sleNode->setIFieldV256(sfIndexes, svIndexes);
|
||||
|
||||
if (!vuiIndexes.empty() || (uFirstNode != uNodeCur && uLastNode != uNodeCur))
|
||||
if (vuiIndexes.size() > 0)
|
||||
{
|
||||
// Node is not being deleted.
|
||||
sleNode->setIFieldV256(sfIndexes, svIndexes);
|
||||
accounts.push_back(std::make_pair(taaMODIFY, sleNode));
|
||||
}
|
||||
|
||||
while (uFirstNode && svIndexes.peekValue().empty()
|
||||
&& (uFirstNode == uNodeCur || uLastNode == uNodeCur))
|
||||
{
|
||||
// Current node is empty and first or last, delete it.
|
||||
accounts.push_back(std::make_pair(taaDELETE, sleNode));
|
||||
|
||||
if (uFirstNode == uLastNode)
|
||||
{
|
||||
// Complete deletion.
|
||||
uFirstNode = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uFirstNode == uNodeCur)
|
||||
{
|
||||
// Advance first node
|
||||
++uNodeCur;
|
||||
++uFirstNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rewind last node
|
||||
--uNodeCur;
|
||||
--uLastNode;
|
||||
}
|
||||
|
||||
// Get replacement node.
|
||||
lspNode = lepNONE;
|
||||
sleNode = mLedger->getDirNode(lspNode, Ledger::getDirIndex(uBase, uNodeCur));
|
||||
svIndexes = sleNode->getIFieldV256(sfIndexes);
|
||||
}
|
||||
}
|
||||
|
||||
if (uFirstNode == uFirstNodeOrig && uLastNode == uLastNodeOrig)
|
||||
{
|
||||
// Dir is fine.
|
||||
nothing();
|
||||
}
|
||||
else if (uFirstNode)
|
||||
{
|
||||
// Update root's pointer pointers.
|
||||
sleRoot->setIFieldU64(sfFirstNode, uFirstNode);
|
||||
sleRoot->setIFieldU64(sfLastNode, uLastNode);
|
||||
|
||||
accounts.push_back(std::make_pair(taaMODIFY, sleRoot));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Delete the root.
|
||||
accounts.push_back(std::make_pair(taaDELETE, sleRoot));
|
||||
bool bRootDirty = false;
|
||||
SLE::pointer sleRoot;
|
||||
|
||||
// May be able to delete nodes.
|
||||
if (uNodeCur)
|
||||
{
|
||||
uint64 uNodePrevious = sleNode->getIFieldU64(sfIndexPrevious);
|
||||
uint64 uNodeNext = sleNode->getIFieldU64(sfIndexNext);
|
||||
|
||||
accounts.push_back(std::make_pair(taaDELETE, sleNode));
|
||||
|
||||
// Fix previous link.
|
||||
if (uNodePrevious)
|
||||
{
|
||||
LedgerStateParms lspPrevious = lepNONE;
|
||||
SLE::pointer slePrevious = mLedger->getDirNode(lspPrevious, Ledger::getDirNodeIndex(uRootIndex, uNodePrevious));
|
||||
|
||||
assert(slePrevious);
|
||||
if (!slePrevious)
|
||||
{
|
||||
Log(lsWARNING) << "dirDelete: previous node is missing";
|
||||
|
||||
return terBAD_LEDGER;
|
||||
}
|
||||
else if (uNodeNext)
|
||||
{
|
||||
slePrevious->setIFieldU64(sfIndexNext, uNodeNext);
|
||||
}
|
||||
else
|
||||
{
|
||||
slePrevious->makeIFieldAbsent(sfIndexNext);
|
||||
}
|
||||
accounts.push_back(std::make_pair(taaMODIFY, slePrevious));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Read root.
|
||||
bRootDirty = true;
|
||||
|
||||
sleRoot = mLedger->getDirNode(lspNode, uRootIndex);
|
||||
|
||||
if (uNodeNext)
|
||||
{
|
||||
sleRoot->setIFieldU64(sfIndexNext, uNodeNext);
|
||||
}
|
||||
else
|
||||
{
|
||||
sleRoot->makeIFieldAbsent(sfIndexNext);
|
||||
}
|
||||
}
|
||||
|
||||
// Fix next link.
|
||||
if (uNodeNext)
|
||||
{
|
||||
LedgerStateParms lspNext = lepNONE;
|
||||
SLE::pointer sleNext = mLedger->getDirNode(lspNext, Ledger::getDirNodeIndex(uRootIndex, uNodeNext));
|
||||
|
||||
assert(sleNext);
|
||||
if (!sleNext)
|
||||
{
|
||||
Log(lsWARNING) << "dirDelete: next node is missing";
|
||||
|
||||
return terBAD_LEDGER;
|
||||
}
|
||||
else if (uNodeNext)
|
||||
{
|
||||
sleNext->setIFieldU64(sfIndexNext, uNodeNext);
|
||||
}
|
||||
else
|
||||
{
|
||||
sleNext->makeIFieldAbsent(sfIndexNext);
|
||||
}
|
||||
accounts.push_back(std::make_pair(taaMODIFY, sleNext));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Read root.
|
||||
bRootDirty = true;
|
||||
|
||||
sleRoot = mLedger->getDirNode(lspNode, uRootIndex);
|
||||
|
||||
if (uNodePrevious)
|
||||
{
|
||||
sleRoot->setIFieldU64(sfIndexPrevious, uNodePrevious);
|
||||
}
|
||||
else
|
||||
{
|
||||
sleRoot->makeIFieldAbsent(sfIndexPrevious);
|
||||
}
|
||||
}
|
||||
|
||||
if (bRootDirty)
|
||||
{
|
||||
// Need to update sleRoot;
|
||||
uNodeCur = 0;
|
||||
|
||||
// If we might be able to delete root, load it.
|
||||
if (!uNodePrevious && !uNodeNext)
|
||||
vuiIndexes = svIndexes.peekValue();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bRootDirty = true;
|
||||
}
|
||||
|
||||
if (!uNodeCur)
|
||||
{
|
||||
// Looking at root node.
|
||||
uint64 uRootPrevious = sleNode->getIFieldU64(sfIndexPrevious);
|
||||
uint64 uRootNext = sleNode->getIFieldU64(sfIndexNext);
|
||||
|
||||
if (!uRootPrevious && !uRootNext && vuiIndexes.empty())
|
||||
{
|
||||
accounts.push_back(std::make_pair(taaDELETE, sleRoot));
|
||||
}
|
||||
else if (bRootDirty)
|
||||
{
|
||||
accounts.push_back(std::make_pair(taaMODIFY, sleRoot));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1758,7 +1820,7 @@ TransactionEngineResult TransactionEngine::doOffer(
|
||||
if (terSUCCESS == terResult)
|
||||
{
|
||||
terResult = dirAdd(accounts, uOfferNode,
|
||||
Ledger::getDirIndex(
|
||||
Ledger::getQualityIndex(
|
||||
Ledger::getBookBase(uCurrencyIn, uIssuerIn, uCurrencyOut, uIssuerOut),
|
||||
STAmount::getRate(saAmountOut, saAmountIn)),
|
||||
uLedgerIndex);
|
||||
|
||||
@@ -52,6 +52,7 @@ enum TransactionEngineResult
|
||||
// Conflict with ledger database: Fee claimed
|
||||
// Might succeed if not conflict is not caused by transaction ordering.
|
||||
terBAD_AUTH,
|
||||
terBAD_LEDGER,
|
||||
terBAD_RIPPLE,
|
||||
terBAD_SEQ,
|
||||
terCREATED,
|
||||
@@ -102,13 +103,13 @@ private:
|
||||
TransactionEngineResult dirAdd(
|
||||
std::vector<AffectedAccount>& accounts,
|
||||
uint64& uNodeDir, // Node of entry.
|
||||
const uint256& uBase,
|
||||
const uint256& uRootIndex,
|
||||
const uint256& uLedgerIndex);
|
||||
|
||||
TransactionEngineResult dirDelete(
|
||||
std::vector<AffectedAccount>& accounts,
|
||||
const uint64& uNodeDir, // Node item is mentioned in.
|
||||
const uint256& uBase, // Key of item.
|
||||
const uint256& uRootIndex,
|
||||
const uint256& uLedgerIndex); // Item being deleted
|
||||
|
||||
#ifdef WORK_IN_PROGRESS
|
||||
|
||||
Reference in New Issue
Block a user