diff --git a/src/cpp/ripple/FieldNames.cpp b/src/cpp/ripple/FieldNames.cpp index d51adf8ad0..0d7617ae41 100644 --- a/src/cpp/ripple/FieldNames.cpp +++ b/src/cpp/ripple/FieldNames.cpp @@ -28,8 +28,16 @@ SField sfIndex(STI_HASH256, 258, "index"); static int initFields() { - sfTxnSignature.notSigningField(); sfTxnSignatures.notSigningField(); + sfTxnSignature.notSigningField(); + sfTxnSignatures.notSigningField(); sfSignature.notSigningField(); + + sfIndexes.setMeta(SField::sMD_Never); + sfPreviousTxnID.setMeta(SField::sMD_Never); + sfPreviousTxnLgrSeq.setMeta(SField::sMD_Never); + sfLedgerEntryType.setMeta(SField::sMD_Never); + sfRootIndex.setMeta(SField::sMD_Always); + return 0; } static const int f = initFields(); diff --git a/src/cpp/ripple/FieldNames.h b/src/cpp/ripple/FieldNames.h index db118ad8b4..507a2bd7f3 100644 --- a/src/cpp/ripple/FieldNames.h +++ b/src/cpp/ripple/FieldNames.h @@ -40,6 +40,14 @@ public: typedef const SField& ref; typedef SField const * ptr; + static const int sMD_Never = 0x00; + static const int sMD_ChangeOrig = 0x01; // original value when it changes + static const int sMD_ChangeNew = 0x02; // new value when it changes + static const int sMD_DeleteFinal = 0x04; // final value when it is deleted + static const int sMD_Create = 0x08; // value when it's created + static const int sMD_Always = 0x10; // value when node containing it is affected at all + static const int sMD_Default = sMD_ChangeOrig | sMD_ChangeNew | sMD_DeleteFinal; + protected: static std::map codeToField; static boost::mutex mapMutex; @@ -52,23 +60,25 @@ public: const SerializedTypeID fieldType; // STI_* const int fieldValue; // Code number for protocol std::string fieldName; + int fieldMeta; bool signingField; SField(int fc, SerializedTypeID tid, int fv, const char* fn) : - fieldCode(fc), fieldType(tid), fieldValue(fv), fieldName(fn), signingField(true) + fieldCode(fc), fieldType(tid), fieldValue(fv), fieldName(fn), fieldMeta(sMD_Default), signingField(true) { boost::mutex::scoped_lock sl(mapMutex); codeToField[fieldCode] = this; } SField(SerializedTypeID tid, int fv, const char *fn) : - fieldCode(FIELD_CODE(tid, fv)), fieldType(tid), fieldValue(fv), fieldName(fn), signingField(true) + fieldCode(FIELD_CODE(tid, fv)), fieldType(tid), fieldValue(fv), fieldName(fn), + fieldMeta(sMD_Default), signingField(true) { boost::mutex::scoped_lock sl(mapMutex); codeToField[fieldCode] = this; } - SField(int fc) : fieldCode(fc), fieldType(STI_UNKNOWN), fieldValue(0) { ; } + SField(int fc) : fieldCode(fc), fieldType(STI_UNKNOWN), fieldValue(0), fieldMeta(sMD_Never) { ; } ~SField(); @@ -86,8 +96,10 @@ public: bool isBinary() const { return fieldValue < 256; } bool isDiscardable() const { return fieldValue > 256; } - bool isSigningField() const { return signingField; } - void notSigningField() { signingField = false; } + bool isSigningField() const { return signingField; } + void notSigningField() { signingField = false; } + bool shouldMeta(int c) const { return (fieldMeta & c) != 0; } + void setMeta(int c) { fieldMeta = c; } bool shouldInclude(bool withSigningField) const { return (fieldValue < 256) && (withSigningField || signingField); } diff --git a/src/cpp/ripple/LedgerEntrySet.cpp b/src/cpp/ripple/LedgerEntrySet.cpp index ab40fb2de7..1ff883fb52 100644 --- a/src/cpp/ripple/LedgerEntrySet.cpp +++ b/src/cpp/ripple/LedgerEntrySet.cpp @@ -407,59 +407,66 @@ void LedgerEntrySet::calcRawMeta(Serializer& s, TER result) mSet.setAffectedNode(it.first, *type, nodeType); if (type == &sfDeletedNode) - { + { // nodes was deleted assert(origNode); assert(curNode); - threadOwners(origNode, mLedger, newMod); + threadOwners(origNode, mLedger, newMod); // thread transaction to owners + STObject mods(sfPreviousFields); STObject finals(sfFinalFields); BOOST_FOREACH(const SerializedType& obj, *curNode) - { // save non-default values - if (!obj.isDefault() && (obj.getFName() != sfLedgerEntryType)) - finals.addObject(obj); - } - if (!finals.empty()) - mSet.getAffectedNode(it.first, *type).addObject(finals); - } - - if ((type == &sfDeletedNode || type == &sfModifiedNode)) - { - STObject mods(sfPreviousFields); - BOOST_FOREACH(const SerializedType& obj, *origNode) - { // search the original node for values saved on modify - if (!obj.isDefault() && (obj.getFName() != sfLedgerEntryType) && !curNode->hasMatchingEntry(obj)) + { + if (obj.getFName().shouldMeta(SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry(obj)) mods.addObject(obj); + if (obj.getFName().shouldMeta(SField::sMD_Always | SField::sMD_DeleteFinal)) + finals.addObject(obj); } if (!mods.empty()) mSet.getAffectedNode(it.first, *type).addObject(mods); + if (!finals.empty()) + mSet.getAffectedNode(it.first, *type).addObject(finals); } + else if (type == &sfModifiedNode) + { + if (curNode->isThreadedType()) // thread transaction to node it modified + threadTx(curNode, mLedger, newMod); - if (type == &sfCreatedNode) // if created, thread to owner(s) + STObject mods(sfPreviousFields); + STObject finals(sfFinalFields); + BOOST_FOREACH(const SerializedType& obj, *origNode) + { // search the original node for values saved on modify + if (obj.getFName().shouldMeta(SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry(obj)) + mods.addObject(obj); + if (obj.getFName().shouldMeta(SField::sMD_Always | SField::sMD_ChangeNew)) + finals.addObject(obj); + } + if (!mods.empty()) + mSet.getAffectedNode(it.first, *type).addObject(mods); + if (!finals.empty()) + mSet.getAffectedNode(it.first, *type).addObject(finals); + } + else if (type == &sfCreatedNode) // if created, thread to owner(s) { assert(!origNode); threadOwners(curNode, mLedger, newMod); + if (curNode->isThreadedType()) // always thread to self + threadTx(curNode, mLedger, newMod); STObject news(sfNewFields); BOOST_FOREACH(const SerializedType& obj, *curNode) { // save non-default values - if (!obj.isDefault() && (obj.getFName() != sfLedgerEntryType)) + if (!obj.isDefault() && obj.getFName().shouldMeta(SField::sMD_Create | SField::sMD_Always)) news.addObject(obj); } if (!news.empty()) mSet.getAffectedNode(it.first, *type).addObject(news); } - - if ((type == &sfCreatedNode) || (type == &sfModifiedNode)) - { - if (curNode->isThreadedType()) // always thread to self - threadTx(curNode, mLedger, newMod); - } } // add any new modified nodes to the modification set - for (boost::unordered_map::iterator it = newMod.begin(), end = newMod.end(); - it != end; ++it) - entryModify(it->second); + typedef std::pair u256_sle_pair; + BOOST_FOREACH(u256_sle_pair& it, newMod) + entryModify(it.second); mSet.addRaw(s, result); cLog(lsTRACE) << "Metadata:" << mSet.getJson(0); @@ -483,6 +490,7 @@ TER LedgerEntrySet::dirAdd( { // No root, make it. sleRoot = entryCreate(ltDIR_NODE, uRootIndex); + sleRoot->setFieldH256(sfRootIndex, uRootIndex); sleNode = sleRoot; uNodeDir = 0; @@ -543,6 +551,7 @@ TER LedgerEntrySet::dirAdd( // Create the new node. sleNode = entryCreate(ltDIR_NODE, Ledger::getDirNodeIndex(uRootIndex, uNodeDir)); + sleNode->setFieldH256(sfRootIndex, uRootIndex); svIndexes = STVector256(); } } diff --git a/src/cpp/ripple/LedgerFormats.cpp b/src/cpp/ripple/LedgerFormats.cpp index ea1240bc5c..5605cd0413 100644 --- a/src/cpp/ripple/LedgerFormats.cpp +++ b/src/cpp/ripple/LedgerFormats.cpp @@ -47,6 +47,7 @@ static bool LEFInit() DECLARE_LEF(DirectoryNode, ltDIR_NODE) << SOElement(sfIndexes, SOE_REQUIRED) + << SOElement(sfRootIndex, SOE_REQUIRED) << SOElement(sfIndexNext, SOE_OPTIONAL) << SOElement(sfIndexPrevious, SOE_OPTIONAL) ; diff --git a/src/cpp/ripple/SerializeProto.h b/src/cpp/ripple/SerializeProto.h index 542451f1ae..8b5920f644 100644 --- a/src/cpp/ripple/SerializeProto.h +++ b/src/cpp/ripple/SerializeProto.h @@ -76,6 +76,7 @@ FIELD(PreviousTxnID, HASH256, 5) FIELD(LedgerIndex, HASH256, 6) FIELD(WalletLocator, HASH256, 7) + FIELD(RootIndex, HASH256, 8) // 256-bit (uncommon) FIELD(BookDirectory, HASH256, 16)