diff --git a/src/FieldNames.cpp b/src/FieldNames.cpp index 2f84ec7abc..67695731d8 100644 --- a/src/FieldNames.cpp +++ b/src/FieldNames.cpp @@ -26,6 +26,31 @@ SField sfIndex(STI_HASH256, 258, "index"); #undef FIELD #undef TYPE +static int initFields() +{ + sfHighQualityIn.setMeta(SFM_CHANGE); sfHighQualityOut.setMeta(SFM_CHANGE); + sfLowQualityIn.setMeta(SFM_CHANGE); sfLowQualityOut.setMeta(SFM_CHANGE); + + sfLowLimit.setMeta(SFM_ALWAYS); sfHighLimit.setMeta(SFM_ALWAYS); + sfTakerPays.setMeta(SFM_ALWAYS); sfTakerGets.setMeta(SFM_ALWAYS); + sfQualityIn.setMeta(SFM_ALWAYS); sfQualityOut.setMeta(SFM_ALWAYS); + + sfBalance.setMeta(SFM_ALWAYS); + + sfPublicKey.setMeta(SFM_CHANGE); sfMessageKey.setMeta(SFM_CHANGE); + sfSigningPubKey.setMeta(SFM_CHANGE); sfAuthorizedKey.setMeta(SFM_CHANGE); + sfSigningAccounts.setMeta(SFM_CHANGE); + + sfWalletLocator.setMeta(SFM_CHANGE); + sfNickname.setMeta(SFM_CHANGE); + sfAmount.setMeta(SFM_ALWAYS); + sfDomain.setMeta(SFM_CHANGE); + sfOwner.setMeta(SFM_ALWAYS); + + return 0; +} +static const int f = initFields(); + SField::SField(SerializedTypeID tid, int fv) : fieldCode(FIELD_CODE(tid, fv)), fieldType(tid), fieldValue(fv) { // call with the map mutex diff --git a/src/FieldNames.h b/src/FieldNames.h index 3a09f67a47..cdb11ad6b7 100644 --- a/src/FieldNames.h +++ b/src/FieldNames.h @@ -33,6 +33,14 @@ enum SOE_Flags SOE_OPTIONAL = 1, // optional }; +enum SF_Meta +{ + SFM_NEVER = 0, + SFM_CHANGE = 1, + SFM_DELETE = 2, + SFM_ALWAYS = 3 +}; + class SField { public: @@ -51,16 +59,17 @@ public: const SerializedTypeID fieldType; // STI_* const int fieldValue; // Code number for protocol std::string fieldName; + SF_Meta fieldMeta; SField(int fc, SerializedTypeID tid, int fv, const char* fn) : - fieldCode(fc), fieldType(tid), fieldValue(fv), fieldName(fn) + fieldCode(fc), fieldType(tid), fieldValue(fv), fieldName(fn), fieldMeta(SFM_NEVER) { 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) + fieldCode(FIELD_CODE(tid, fv)), fieldType(tid), fieldValue(fv), fieldName(fn), fieldMeta(SFM_NEVER) { boost::mutex::scoped_lock sl(mapMutex); codeToField[fieldCode] = this; @@ -84,6 +93,11 @@ public: bool isBinary() const { return fieldValue < 256; } bool isDiscardable() const { return fieldValue > 256; } + SF_Meta getMeta() const { return fieldMeta; } + bool shouldMetaDel() const { return (fieldMeta == SFM_DELETE) || (fieldMeta == SFM_ALWAYS); } + bool shouldMetaMod() const { return (fieldMeta == SFM_CHANGE) || (fieldMeta == SFM_ALWAYS); } + void setMeta(SF_Meta m) { fieldMeta = m; } + bool operator==(const SField& f) const { return fieldCode == f.fieldCode; } bool operator!=(const SField& f) const { return fieldCode != f.fieldCode; } diff --git a/src/LedgerEntrySet.cpp b/src/LedgerEntrySet.cpp index 5cbca45df0..8371b3119d 100644 --- a/src/LedgerEntrySet.cpp +++ b/src/LedgerEntrySet.cpp @@ -319,9 +319,11 @@ bool LedgerEntrySet::threadTx(SLE::ref threadTo, Ledger::ref ledger, uint32 prevLgrID; if (!threadTo->thread(mSet.getTxID(), mSet.getLgrSeq(), prevTxID, prevLgrID)) return false; - if (TransactionMetaSet::thread(mSet.getAffectedNode(threadTo->getIndex(), sfModifiedNode), + + if (prevTxID.isZero() || TransactionMetaSet::thread(mSet.getAffectedNode(threadTo->getIndex(), sfModifiedNode), prevTxID, prevLgrID)) return true; + assert(false); return false; } @@ -403,34 +405,26 @@ void LedgerEntrySet::calcRawMeta(Serializer& s, TER result) assert(origNode); threadOwners(origNode, mLedger, newMod); - if (origNode->isFieldPresent(sfAmount)) - { // node has an amount, covers ripple state nodes - STAmount amount = origNode->getFieldAmount(sfAmount); - if (amount.isNonZero()) - mSet.getAffectedNode(it.first).setFieldAmount(sfPreviousBalance, amount); - amount = curNode->getFieldAmount(sfAmount); - if (amount.isNonZero()) - mSet.getAffectedNode(it.first).setFieldAmount(sfFinalBalance, amount); - - if (origNode->getType() == ltRIPPLE_STATE) - { - mSet.getAffectedNode(it.first).setFieldAccount(sfLowID, - RippleAddress::createAccountID(origNode->getFieldAmount(sfLowLimit).getIssuer())); - mSet.getAffectedNode(it.first).setFieldAccount(sfHighID, - RippleAddress::createAccountID(origNode->getFieldAmount(sfHighLimit).getIssuer())); - } + STObject finals(sfFinalFields); + BOOST_FOREACH(const SerializedType& obj, *curNode) + { // search the deleted node for values saved on delete + if (obj.getFName().shouldMetaDel()) + finals.addObject(obj); } + if (!finals.empty()) + mSet.getAffectedNode(it.first, *type).addObject(finals); + } - if (origNode->getType() == ltOFFER) - { // check for non-zero balances - STAmount amount = origNode->getFieldAmount(sfTakerPays); - if (amount.isNonZero()) - mSet.getAffectedNode(it.first).setFieldAmount(sfFinalTakerPays, amount); - amount = origNode->getFieldAmount(sfTakerGets); - if (amount.isNonZero()) - mSet.getAffectedNode(it.first).setFieldAmount(sfFinalTakerGets, amount); + 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.getFName().shouldMetaMod() && !curNode->hasMatchingEntry(obj)) + mods.addObject(obj); } - + if (!mods.empty()) + mSet.getAffectedNode(it.first, *type).addObject(mods); } if (type == &sfCreatedNode) // if created, thread to owner(s) @@ -444,28 +438,6 @@ void LedgerEntrySet::calcRawMeta(Serializer& s, TER result) if (curNode->isThreadedType()) // always thread to self threadTx(curNode, mLedger, newMod); } - - if (type == &sfModifiedNode) - { - assert(origNode); - if (origNode->isFieldPresent(sfAmount)) - { // node has an amount, covers account root nodes and ripple nodes - STAmount amount = origNode->getFieldAmount(sfAmount); - if (amount != curNode->getFieldAmount(sfAmount)) - mSet.getAffectedNode(it.first).setFieldAmount(sfPreviousBalance, amount); - } - - if (origNode->getType() == ltOFFER) - { - STAmount amount = origNode->getFieldAmount(sfTakerPays); - if (amount != curNode->getFieldAmount(sfTakerPays)) - mSet.getAffectedNode(it.first).setFieldAmount(sfPreviousTakerPays, amount); - amount = origNode->getFieldAmount(sfTakerGets); - if (amount != curNode->getFieldAmount(sfTakerGets)) - mSet.getAffectedNode(it.first).setFieldAmount(sfPreviousTakerGets, amount); - } - - } } // add any new modified nodes to the modification set diff --git a/src/SerializeProto.h b/src/SerializeProto.h index 1a7b676412..0654aa4c39 100644 --- a/src/SerializeProto.h +++ b/src/SerializeProto.h @@ -95,12 +95,6 @@ // currency amount (uncommon) FIELD(MinimumOffer, AMOUNT, 16) FIELD(RippleEscrow, AMOUNT, 17) - FIELD(PreviousBalance, AMOUNT, 18) - FIELD(FinalBalance, AMOUNT, 19) - FIELD(PreviousTakerPays, AMOUNT, 20) - FIELD(PreviousTakerGets, AMOUNT, 21) - FIELD(FinalTakerPays, AMOUNT, 22) - FIELD(FinalTakerGets, AMOUNT, 23) // variable length FIELD(PublicKey, VL, 1) @@ -123,11 +117,6 @@ FIELD(Target, ACCOUNT, 7) FIELD(AuthorizedKey, ACCOUNT, 8) - // account (uncommon) - FIELD(PreviousAccount, ACCOUNT, 16) - FIELD(LowID, ACCOUNT, 17) - FIELD(HighID, ACCOUNT, 18) - // path set FIELD(Paths, PATHSET, 1) @@ -141,6 +130,8 @@ FIELD(CreatedNode, OBJECT, 3) FIELD(DeletedNode, OBJECT, 4) FIELD(ModifiedNode, OBJECT, 5) + FIELD(PreviousFields, OBJECT, 6) + FIELD(FinalFields, OBJECT, 7) // array of objects // ARRAY/1 is reserved for end of array