diff --git a/src/ripple/common/jsonrpc_fields.h b/src/ripple/common/jsonrpc_fields.h index 3783f6c904..c923c21771 100644 --- a/src/ripple/common/jsonrpc_fields.h +++ b/src/ripple/common/jsonrpc_fields.h @@ -74,6 +74,8 @@ JSS ( fee_base ); JSS ( fee_ref ); JSS ( fetch_pack ); JSS ( flags ); +JSS ( freeze ); +JSS ( freeze_peer ); JSS ( hash ); JSS ( hostid ); JSS ( id ); diff --git a/src/ripple/module/app/ledger/LedgerEntrySet.cpp b/src/ripple/module/app/ledger/LedgerEntrySet.cpp index c629000c2c..51bb697225 100644 --- a/src/ripple/module/app/ledger/LedgerEntrySet.cpp +++ b/src/ripple/module/app/ledger/LedgerEntrySet.cpp @@ -1367,6 +1367,7 @@ TER LedgerEntrySet::trustCreate ( SLE::ref sleAccount, // --> the account being set. const bool bAuth, // --> authorize account. const bool bNoRipple, // --> others cannot ripple through + const bool bFreeze, // --> funds cannot leave const STAmount& saBalance, // --> balance of account being set. // Issuer should be noAccount() const STAmount& saLimit, // --> limit for account being set. @@ -1435,6 +1436,10 @@ TER LedgerEntrySet::trustCreate ( { uFlags |= (bSetHigh ? lsfHighNoRipple : lsfLowNoRipple); } + if (bFreeze) + { + uFlags |= (!bSetHigh ? lsfLowFreeze : lsfHighFreeze); + } sleRippleState->setFieldU32 (sfFlags, uFlags); ownerCountAdjust ( @@ -1536,6 +1541,7 @@ TER LedgerEntrySet::rippleCredit ( entryCache (ltACCOUNT_ROOT, Ledger::getAccountRootIndex (uReceiverID)), false, false, + false, saBalance, saReceiverLimit); } @@ -1568,6 +1574,7 @@ TER LedgerEntrySet::rippleCredit ( && (uFlags & (!bSenderHigh ? lsfLowReserve : lsfHighReserve)) // Sender reserve is set. && !(uFlags & (!bSenderHigh ? lsfLowNoRipple : lsfHighNoRipple)) + && !(uFlags & (!bSenderHigh ? lsfLowFreeze : lsfHighFreeze)) && !sleRippleState->getFieldAmount ( !bSenderHigh ? sfLowLimit : sfHighLimit) // Sender trust limit is 0. diff --git a/src/ripple/module/app/ledger/LedgerEntrySet.h b/src/ripple/module/app/ledger/LedgerEntrySet.h index 42f8d7374f..0d4cadacb8 100644 --- a/src/ripple/module/app/ledger/LedgerEntrySet.h +++ b/src/ripple/module/app/ledger/LedgerEntrySet.h @@ -246,6 +246,7 @@ public: SLE::ref sleAccount, const bool bAuth, const bool bNoRipple, + const bool bFreeze, const STAmount& saSrcBalance, const STAmount& saSrcLimit, const std::uint32_t uSrcQualityIn = 0, diff --git a/src/ripple/module/app/paths/RippleState.h b/src/ripple/module/app/paths/RippleState.h index 194b507783..7d81493ee5 100644 --- a/src/ripple/module/app/paths/RippleState.h +++ b/src/ripple/module/app/paths/RippleState.h @@ -78,6 +78,18 @@ public: return mFlags & (!mViewLowest ? lsfLowNoRipple : lsfHighNoRipple); } + /** Have we set the freeze flag on our peer */ + bool getFreeze () const + { + return mFlags & (mViewLowest ? lsfLowFreeze : lsfHighFreeze); + } + + /** Has the peer set the freeze flag on us */ + bool getFreezePeer () const + { + return mFlags & (!mViewLowest ? lsfLowFreeze : lsfHighFreeze); + } + const STAmount& getBalance () const { return mBalance; diff --git a/src/ripple/module/app/transactors/SetAccount.cpp b/src/ripple/module/app/transactors/SetAccount.cpp index 12455293ee..98cef9ab9e 100644 --- a/src/ripple/module/app/transactors/SetAccount.cpp +++ b/src/ripple/module/app/transactors/SetAccount.cpp @@ -29,6 +29,12 @@ TER SetAccount::doApply () std::uint32_t const uSetFlag = mTxn.getFieldU32 (sfSetFlag); std::uint32_t const uClearFlag = mTxn.getFieldU32 (sfClearFlag); + if ((uSetFlag != 0) && (uSetFlag == uClearFlag)) + { + m_journal.trace << "Malformed transaction: Set and clear same flag"; + return temINVALID_FLAG; + } + // legacy AccountSet flags bool bSetRequireDest = (uTxFlags & TxFlag::requireDestTag) || (uSetFlag == asfRequireDest); bool bClearRequireDest = (uTxFlags & tfOptionalDestTag) || (uClearFlag == asfRequireDest); @@ -141,6 +147,29 @@ TER SetAccount::doApply () uFlagsOut &= ~lsfDisableMaster; } + if ((uSetFlag == asfNoFreeze) && (uClearFlag != asfNoFreeze)) + { + m_journal.trace << "Set NoFreeze flag"; + uFlagsOut |= lsfNoFreeze; + } + + // Anyone may set global freeze + if ((uSetFlag == asfGlobalFreeze) && (uClearFlag != asfGlobalFreeze)) + { + m_journal.trace << "Set GlobalFreeze flag"; + uFlagsOut |= lsfGlobalFreeze; + } + + // If you have set NoFreeze, you may not clear GlobalFreeze + // This prevents those who have set NoFreeze from using + // GlobalFreeze strategically. + if ((uSetFlag != asfGlobalFreeze) && (uClearFlag == asfGlobalFreeze) && + ((uFlagsOut & lsfNoFreeze) == 0)) + { + m_journal.trace << "Clear GlobalFreeze flag"; + uFlagsOut &= ~lsfGlobalFreeze; + } + // // Track transaction IDs signed by this account in its root // diff --git a/src/ripple/module/app/transactors/SetTrust.cpp b/src/ripple/module/app/transactors/SetTrust.cpp index 3544bde6be..f158df2f3a 100644 --- a/src/ripple/module/app/transactors/SetTrust.cpp +++ b/src/ripple/module/app/transactors/SetTrust.cpp @@ -57,6 +57,8 @@ TER SetTrust::doApply () bool const bSetAuth = (uTxFlags & tfSetfAuth); bool const bSetNoRipple = (uTxFlags & tfSetNoRipple); bool const bClearNoRipple = (uTxFlags & tfClearNoRipple); + bool const bSetFreeze = (uTxFlags & tfSetFreeze); + bool const bClearFreeze = (uTxFlags & tfClearFreeze); if (bSetAuth && !(mTxnAccount->getFieldU32 (sfFlags) & lsfRequireAuth)) { @@ -242,6 +244,15 @@ TER SetTrust::doApply () uFlagsOut &= ~(bHigh ? lsfHighNoRipple : lsfLowNoRipple); } + if (bSetFreeze && !bClearFreeze && !mTxnAccount->isFlag (lsfNoFreeze)) + { + uFlagsOut |= (bHigh ? lsfHighFreeze : lsfLowFreeze); + } + else if (bClearFreeze && !bSetFreeze) + { + uFlagsOut &= ~(bHigh ? lsfHighFreeze : lsfLowFreeze); + } + if (QUALITY_ONE == uLowQualityOut) uLowQualityOut = 0; if (QUALITY_ONE == uHighQualityOut) uHighQualityOut = 0; @@ -249,11 +260,13 @@ TER SetTrust::doApply () bool const bLowReserveSet = uLowQualityIn || uLowQualityOut || (uFlagsOut & lsfLowNoRipple) || + (uFlagsOut & lsfLowFreeze) || !!saLowLimit || saLowBalance > zero; bool const bLowReserveClear = !bLowReserveSet; bool const bHighReserveSet = uHighQualityIn || uHighQualityOut || (uFlagsOut & lsfHighNoRipple) || + (uFlagsOut & lsfHighFreeze) || !!saHighLimit || saHighBalance > zero; bool const bHighReserveClear = !bHighReserveSet; @@ -375,6 +388,7 @@ TER SetTrust::doApply () mTxnAccount, bSetAuth, bSetNoRipple && !bClearNoRipple, + bSetFreeze && !bClearFreeze, saBalance, saLimitAllow, // Limit for who is being charged. uQualityIn, diff --git a/src/ripple/module/data/protocol/LedgerFormats.h b/src/ripple/module/data/protocol/LedgerFormats.h index ebcae8735a..8897c37473 100644 --- a/src/ripple/module/data/protocol/LedgerFormats.h +++ b/src/ripple/module/data/protocol/LedgerFormats.h @@ -102,6 +102,8 @@ enum LedgerSpecificFlags lsfRequireAuth = 0x00040000, // True, to require a authorization to hold IOUs. lsfDisallowXRP = 0x00080000, // True, to disallow sending XRP. lsfDisableMaster = 0x00100000, // True, force regular key + lsfNoFreeze = 0x00200000, // True, cannot freeze ripple states + lsfGlobalFreeze = 0x00400000, // True, all assets frozen // ltOFFER lsfPassive = 0x00010000, @@ -114,6 +116,8 @@ enum LedgerSpecificFlags lsfHighAuth = 0x00080000, lsfLowNoRipple = 0x00100000, lsfHighNoRipple = 0x00200000, + lsfLowFreeze = 0x00400000, // True, low side has set freeze flag + lsfHighFreeze = 0x00800000, // True, high side has set freeze flag }; //------------------------------------------------------------------------------ diff --git a/src/ripple/module/data/protocol/TxFlags.h b/src/ripple/module/data/protocol/TxFlags.h index c6bcf37292..3988802ea8 100644 --- a/src/ripple/module/data/protocol/TxFlags.h +++ b/src/ripple/module/data/protocol/TxFlags.h @@ -63,6 +63,8 @@ const std::uint32_t asfRequireAuth = 2; const std::uint32_t asfDisallowXRP = 3; const std::uint32_t asfDisableMaster = 4; const std::uint32_t asfAccountTxnID = 5; +const std::uint32_t asfNoFreeze = 6; +const std::uint32_t asfGlobalFreeze = 7; // OfferCreate flags: const std::uint32_t tfPassive = 0x00010000; @@ -81,7 +83,10 @@ const std::uint32_t tfPaymentMask = ~ (tfUniversal | tfPartialPayment | const std::uint32_t tfSetfAuth = 0x00010000; const std::uint32_t tfSetNoRipple = 0x00020000; const std::uint32_t tfClearNoRipple = 0x00040000; -const std::uint32_t tfTrustSetMask = ~ (tfUniversal | tfSetfAuth | tfSetNoRipple | tfClearNoRipple); +const std::uint32_t tfSetFreeze = 0x00100000; +const std::uint32_t tfClearFreeze = 0x00200000; +const std::uint32_t tfTrustSetMask = ~ (tfUniversal | tfSetfAuth | tfSetNoRipple | tfClearNoRipple + | tfSetFreeze | tfClearFreeze); } // ripple diff --git a/src/ripple/module/rpc/handlers/AccountLines.cpp b/src/ripple/module/rpc/handlers/AccountLines.cpp index 9347fd5dc4..e483518d78 100644 --- a/src/ripple/module/rpc/handlers/AccountLines.cpp +++ b/src/ripple/module/rpc/handlers/AccountLines.cpp @@ -106,6 +106,10 @@ Json::Value doAccountLines (RPC::Context& context) jPeer[jss::no_ripple] = true; if (line->getNoRipplePeer()) jPeer[jss::no_ripple_peer] = true; + if (line->getFreeze()) + jPeer[jss::freeze] = true; + if (line->getFreezePeer()) + jPeer[jss::freeze_peer] = true; } }