mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Implement MultiSignReserve amendment [RIPD-1647]:
Reduces the account reserve for a multisigning SignerList from (conditionally) 3 to 10 OwnerCounts to (unconditionally) 1 OwnerCount. Includes a transition process.
This commit is contained in:
@@ -218,11 +218,19 @@ SetSignerList::replaceSignerList ()
|
||||
auto const sle = view().peek(accountKeylet);
|
||||
|
||||
// Compute new reserve. Verify the account has funds to meet the reserve.
|
||||
auto const oldOwnerCount = (*sle)[sfOwnerCount];
|
||||
std::uint32_t const addedOwnerCount = ownerCountDelta (signers_.size ());
|
||||
std::uint32_t const oldOwnerCount {(*sle)[sfOwnerCount]};
|
||||
|
||||
auto const newReserve =
|
||||
view().fees().accountReserve(oldOwnerCount + addedOwnerCount);
|
||||
// The required reserve changes based on featureMultiSignReserve...
|
||||
int addedOwnerCount {1};
|
||||
std::uint32_t flags {lsfOneOwnerCount};
|
||||
if (! ctx_.view().rules().enabled(featureMultiSignReserve))
|
||||
{
|
||||
addedOwnerCount = signerCountBasedOwnerCountDelta (signers_.size ());
|
||||
flags = 0;
|
||||
}
|
||||
|
||||
XRPAmount const newReserve {
|
||||
view().fees().accountReserve(oldOwnerCount + addedOwnerCount)};
|
||||
|
||||
// We check the reserve against the starting balance because we want to
|
||||
// allow dipping into the reserve to pay fees. This behavior is consistent
|
||||
@@ -233,15 +241,15 @@ SetSignerList::replaceSignerList ()
|
||||
// Everything's ducky. Add the ltSIGNER_LIST to the ledger.
|
||||
auto signerList = std::make_shared<SLE>(signerListKeylet);
|
||||
view().insert (signerList);
|
||||
writeSignersToSLE (signerList);
|
||||
writeSignersToSLE (signerList, flags);
|
||||
|
||||
auto viewJ = ctx_.app.journal ("View");
|
||||
// Add the signer list to the account's directory.
|
||||
auto page = dirAdd(ctx_.view (), ownerDirKeylet,
|
||||
auto const page = dirAdd (ctx_.view (), ownerDirKeylet,
|
||||
signerListKeylet.key, false, describeOwnerDir (account_), viewJ);
|
||||
|
||||
JLOG(j_.trace()) << "Create signer list for account " <<
|
||||
toBase58(account_) << ": " << (page ? "success" : "failure");
|
||||
toBase58 (account_) << ": " << (page ? "success" : "failure");
|
||||
|
||||
if (!page)
|
||||
return tecDIR_FULL;
|
||||
@@ -283,8 +291,16 @@ SetSignerList::removeSignersFromLedger (Keylet const& accountKeylet,
|
||||
if (!signers)
|
||||
return tesSUCCESS;
|
||||
|
||||
STArray const& actualList = signers->getFieldArray (sfSignerEntries);
|
||||
int const removeFromOwnerCount = ownerCountDelta (actualList.size()) * -1;
|
||||
// There are two different ways that the OwnerCount could be managed.
|
||||
// If the lsfOneOwnerCount bit is set then remove just one owner count.
|
||||
// Otherwise use the pre-MultiSignReserve amendment calculation.
|
||||
int removeFromOwnerCount = -1;
|
||||
if ((signers->getFlags() & lsfOneOwnerCount) == 0)
|
||||
{
|
||||
STArray const& actualList = signers->getFieldArray (sfSignerEntries);
|
||||
removeFromOwnerCount =
|
||||
signerCountBasedOwnerCountDelta (actualList.size()) * -1;
|
||||
}
|
||||
|
||||
// Remove the node from the account directory.
|
||||
auto const hint = (*signers)[sfOwnerNode];
|
||||
@@ -305,13 +321,14 @@ SetSignerList::removeSignersFromLedger (Keylet const& accountKeylet,
|
||||
}
|
||||
|
||||
void
|
||||
SetSignerList::writeSignersToSLE (SLE::pointer const& ledgerEntry) const
|
||||
SetSignerList::writeSignersToSLE (
|
||||
SLE::pointer const& ledgerEntry, std::uint32_t flags) const
|
||||
{
|
||||
// Assign the quorum.
|
||||
// Assign the quorum, default SignerListID, and flags.
|
||||
ledgerEntry->setFieldU32 (sfSignerQuorum, quorum_);
|
||||
|
||||
// For now, assign the default SignerListID.
|
||||
ledgerEntry->setFieldU32 (sfSignerListID, defaultSignerListID_);
|
||||
if (flags) // Only set flags if they are non-default (default is zero).
|
||||
ledgerEntry->setFieldU32 (sfFlags, flags);
|
||||
|
||||
// Create the SignerListArray one SignerEntry at a time.
|
||||
STArray toLedger (signers_.size ());
|
||||
@@ -330,8 +347,12 @@ SetSignerList::writeSignersToSLE (SLE::pointer const& ledgerEntry) const
|
||||
|
||||
// The return type is signed so it is compatible with the 3rd argument
|
||||
// of adjustOwnerCount() (which must be signed).
|
||||
//
|
||||
// NOTE: This way of computing the OwnerCount associated with a SignerList
|
||||
// is valid until the featureMultiSignReserve amendment passes. Once it
|
||||
// passes then just 1 OwnerCount is associated with a SignerList.
|
||||
int
|
||||
SetSignerList::ownerCountDelta (std::size_t entryCount)
|
||||
SetSignerList::signerCountBasedOwnerCountDelta (std::size_t entryCount)
|
||||
{
|
||||
// We always compute the full change in OwnerCount, taking into account:
|
||||
// o The fact that we're adding/removing a SignerList and
|
||||
|
||||
@@ -87,9 +87,14 @@ private:
|
||||
|
||||
TER removeSignersFromLedger (Keylet const& accountKeylet,
|
||||
Keylet const& ownerDirKeylet, Keylet const& signerListKeylet);
|
||||
void writeSignersToSLE (SLE::pointer const& ledgerEntry) const;
|
||||
void writeSignersToSLE (
|
||||
SLE::pointer const& ledgerEntry, std::uint32_t flags) const;
|
||||
|
||||
static int ownerCountDelta (std::size_t entryCount);
|
||||
// Way of computing owner count prior to featureMultiSignReserve.
|
||||
// This needs to stay in the code base until no signerLists remain
|
||||
// in the ledger that were created prior to acceptance of
|
||||
// featureMultiSignReserve... Effectively forever.
|
||||
static int signerCountBasedOwnerCountDelta (std::size_t entryCount);
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
@@ -81,7 +81,8 @@ class FeatureCollections
|
||||
"fix1623",
|
||||
"DepositPreauth",
|
||||
"fix1515",
|
||||
"fix1578"
|
||||
"fix1578",
|
||||
"MultiSignReserve"
|
||||
};
|
||||
|
||||
std::vector<uint256> features;
|
||||
@@ -369,6 +370,7 @@ extern uint256 const fix1623;
|
||||
extern uint256 const featureDepositPreauth;
|
||||
extern uint256 const fix1515;
|
||||
extern uint256 const fix1578;
|
||||
extern uint256 const featureMultiSignReserve;
|
||||
|
||||
} // ripple
|
||||
|
||||
|
||||
@@ -152,6 +152,9 @@ enum LedgerSpecificFlags
|
||||
lsfHighNoRipple = 0x00200000,
|
||||
lsfLowFreeze = 0x00400000, // True, low side has set freeze flag
|
||||
lsfHighFreeze = 0x00800000, // True, high side has set freeze flag
|
||||
|
||||
// ltSIGNER_LIST
|
||||
lsfOneOwnerCount = 0x00010000, // True, uses only one OwnerCount
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -114,7 +114,8 @@ detail::supportedAmendments ()
|
||||
{ "3CBC5C4E630A1B82380295CDA84B32B49DD066602E74E39B85EF64137FA65194 DepositPreauth" },
|
||||
// Use liquidity from strands that consume max offers, but mark as dry
|
||||
{ "5D08145F0A4983F23AFFFF514E83FAD355C5ABFBB6CAB76FB5BC8519FF5F33BE fix1515" },
|
||||
{ "FBD513F1B893AC765B78F250E6FFA6A11B573209D1842ADC787C850696741288 fix1578" }
|
||||
{ "FBD513F1B893AC765B78F250E6FFA6A11B573209D1842ADC787C850696741288 fix1578" },
|
||||
{ "586480873651E106F1D6339B0C4A8945BA705A777F3F4524626FF1FC07EFE41D MultiSignReserve" }
|
||||
};
|
||||
return supported;
|
||||
}
|
||||
@@ -170,5 +171,6 @@ uint256 const fix1623 = *getRegisteredFeature("fix1623");
|
||||
uint256 const featureDepositPreauth = *getRegisteredFeature("DepositPreauth");
|
||||
uint256 const fix1515 = *getRegisteredFeature("fix1515");
|
||||
uint256 const fix1578 = *getRegisteredFeature("fix1578");
|
||||
uint256 const featureMultiSignReserve = *getRegisteredFeature("MultiSignReserve");
|
||||
|
||||
} // ripple
|
||||
|
||||
Reference in New Issue
Block a user