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:
Scott Schurr
2018-07-13 12:34:26 -07:00
parent 3ce4dda5cb
commit 6572fc8e95
7 changed files with 390 additions and 208 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
};
//------------------------------------------------------------------------------

View File

@@ -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