mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Compare commits
15 Commits
ximinez/di
...
ximinez/em
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f267c3bc9 | ||
|
|
bface8d5d6 | ||
|
|
24174f6ea7 | ||
|
|
cf3ad16bdf | ||
|
|
a4046aa135 | ||
|
|
46f6332e60 | ||
|
|
ff3c2bf2f9 | ||
|
|
379e1ed555 | ||
|
|
e9fb99056b | ||
|
|
e9fa9d7aa6 | ||
|
|
2c3f169dec | ||
|
|
23565405ee | ||
|
|
a5d08b0cd5 | ||
|
|
7bf3f543b3 | ||
|
|
c773288df5 |
@@ -16,7 +16,6 @@
|
|||||||
// Add new amendments to the top of this list.
|
// Add new amendments to the top of this list.
|
||||||
// Keep it sorted in reverse chronological order.
|
// Keep it sorted in reverse chronological order.
|
||||||
|
|
||||||
XRPL_FEATURE(DefragDirectories, Supported::no, VoteBehavior::DefaultNo)
|
|
||||||
XRPL_FEATURE(LendingProtocol, Supported::no, VoteBehavior::DefaultNo)
|
XRPL_FEATURE(LendingProtocol, Supported::no, VoteBehavior::DefaultNo)
|
||||||
XRPL_FEATURE(PermissionDelegationV1_1, Supported::no, VoteBehavior::DefaultNo)
|
XRPL_FEATURE(PermissionDelegationV1_1, Supported::no, VoteBehavior::DefaultNo)
|
||||||
XRPL_FIX (DirectoryLimit, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FIX (DirectoryLimit, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
|
|||||||
@@ -10,14 +10,6 @@ namespace ripple {
|
|||||||
|
|
||||||
namespace directory {
|
namespace directory {
|
||||||
|
|
||||||
struct Gap
|
|
||||||
{
|
|
||||||
uint64_t const page;
|
|
||||||
SLE::pointer node;
|
|
||||||
uint64_t const nextPage;
|
|
||||||
SLE::pointer next;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::uint64_t
|
std::uint64_t
|
||||||
createRoot(
|
createRoot(
|
||||||
ApplyView& view,
|
ApplyView& view,
|
||||||
@@ -120,9 +112,7 @@ insertPage(
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
if (!view.rules().enabled(fixDirectoryLimit) &&
|
if (!view.rules().enabled(fixDirectoryLimit) &&
|
||||||
page >= dirNodeMaxPages) // Old pages limit
|
page >= dirNodeMaxPages) // Old pages limit
|
||||||
{
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
|
||||||
|
|
||||||
// We are about to create a new node; we'll link it to
|
// We are about to create a new node; we'll link it to
|
||||||
// the chain first:
|
// the chain first:
|
||||||
@@ -144,8 +134,15 @@ insertPage(
|
|||||||
// it's the default.
|
// it's the default.
|
||||||
if (page != 1)
|
if (page != 1)
|
||||||
node->setFieldU64(sfIndexPrevious, page - 1);
|
node->setFieldU64(sfIndexPrevious, page - 1);
|
||||||
|
XRPL_ASSERT_PARTS(
|
||||||
|
!nextPage,
|
||||||
|
"ripple::directory::insertPage",
|
||||||
|
"nextPage has default value");
|
||||||
|
/* Reserved for future use when directory pages may be inserted in
|
||||||
|
* between two other pages instead of only at the end of the chain.
|
||||||
if (nextPage)
|
if (nextPage)
|
||||||
node->setFieldU64(sfIndexNext, nextPage);
|
node->setFieldU64(sfIndexNext, nextPage);
|
||||||
|
*/
|
||||||
describe(node);
|
describe(node);
|
||||||
view.insert(node);
|
view.insert(node);
|
||||||
|
|
||||||
@@ -161,7 +158,7 @@ ApplyView::dirAdd(
|
|||||||
uint256 const& key,
|
uint256 const& key,
|
||||||
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
|
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
|
||||||
{
|
{
|
||||||
auto const root = peek(directory);
|
auto root = peek(directory);
|
||||||
|
|
||||||
if (!root)
|
if (!root)
|
||||||
{
|
{
|
||||||
@@ -172,44 +169,6 @@ ApplyView::dirAdd(
|
|||||||
auto [page, node, indexes] =
|
auto [page, node, indexes] =
|
||||||
directory::findPreviousPage(*this, directory, root);
|
directory::findPreviousPage(*this, directory, root);
|
||||||
|
|
||||||
if (rules().enabled(featureDefragDirectories))
|
|
||||||
{
|
|
||||||
// If there are more nodes than just the root, and there's no space in
|
|
||||||
// the last one, walk backwards to find one with space, or to find one
|
|
||||||
// missing.
|
|
||||||
std::optional<directory::Gap> gapPages;
|
|
||||||
while (page && indexes.size() >= dirNodeMaxEntries)
|
|
||||||
{
|
|
||||||
// Find a page with space, or a gap in pages.
|
|
||||||
auto [prevPage, prevNode, prevIndexes] =
|
|
||||||
directory::findPreviousPage(*this, directory, node);
|
|
||||||
if (!gapPages && prevPage != page - 1)
|
|
||||||
gapPages.emplace(prevPage, prevNode, page, node);
|
|
||||||
page = prevPage;
|
|
||||||
node = prevNode;
|
|
||||||
indexes = prevIndexes;
|
|
||||||
}
|
|
||||||
// We looped through all the pages back to the root.
|
|
||||||
if (!page)
|
|
||||||
{
|
|
||||||
// If we found a gap, use it.
|
|
||||||
if (gapPages)
|
|
||||||
{
|
|
||||||
return directory::insertPage(
|
|
||||||
*this,
|
|
||||||
gapPages->page,
|
|
||||||
gapPages->node,
|
|
||||||
gapPages->nextPage,
|
|
||||||
gapPages->next,
|
|
||||||
key,
|
|
||||||
directory,
|
|
||||||
describe);
|
|
||||||
}
|
|
||||||
std::tie(page, node, indexes) =
|
|
||||||
directory::findPreviousPage(*this, directory, root);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there's space, we use it:
|
// If there's space, we use it:
|
||||||
if (indexes.size() < dirNodeMaxEntries)
|
if (indexes.size() < dirNodeMaxEntries)
|
||||||
{
|
{
|
||||||
@@ -297,6 +256,7 @@ ApplyView::dirRemove(
|
|||||||
uint256 const& key,
|
uint256 const& key,
|
||||||
bool keepRoot)
|
bool keepRoot)
|
||||||
{
|
{
|
||||||
|
keepRoot = false;
|
||||||
auto node = peek(keylet::page(directory, page));
|
auto node = peek(keylet::page(directory, page));
|
||||||
|
|
||||||
if (!node)
|
if (!node)
|
||||||
|
|||||||
@@ -3553,4 +3553,42 @@ ValidVault::finalize(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void
|
||||||
|
NoEmptyDirectory::visitEntry(
|
||||||
|
bool isDelete,
|
||||||
|
std::shared_ptr<SLE const> const& before,
|
||||||
|
std::shared_ptr<SLE const> const& after)
|
||||||
|
{
|
||||||
|
if (isDelete)
|
||||||
|
return;
|
||||||
|
if (before && before->getType() != ltDIR_NODE)
|
||||||
|
return;
|
||||||
|
if (after && after->getType() != ltDIR_NODE)
|
||||||
|
return;
|
||||||
|
if (!after->isFieldPresent(sfOwner))
|
||||||
|
// Not an account dir
|
||||||
|
return;
|
||||||
|
|
||||||
|
bad_ = after->at(sfIndexes).empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
NoEmptyDirectory::finalize(
|
||||||
|
STTx const& tx,
|
||||||
|
TER const result,
|
||||||
|
XRPAmount const,
|
||||||
|
ReadView const& view,
|
||||||
|
beast::Journal const& j)
|
||||||
|
{
|
||||||
|
if (bad_)
|
||||||
|
{
|
||||||
|
JLOG(j.fatal()) << "Invariant failed: empty owner directory.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
|
|||||||
@@ -901,6 +901,30 @@ public:
|
|||||||
beast::Journal const&);
|
beast::Journal const&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Invariants: An account's directory should never be empty
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class NoEmptyDirectory
|
||||||
|
{
|
||||||
|
bool bad_ = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void
|
||||||
|
visitEntry(
|
||||||
|
bool,
|
||||||
|
std::shared_ptr<SLE const> const&,
|
||||||
|
std::shared_ptr<SLE const> const&);
|
||||||
|
|
||||||
|
bool
|
||||||
|
finalize(
|
||||||
|
STTx const&,
|
||||||
|
TER const,
|
||||||
|
XRPAmount const,
|
||||||
|
ReadView const&,
|
||||||
|
beast::Journal const&);
|
||||||
|
};
|
||||||
|
|
||||||
// additional invariant checks can be declared above and then added to this
|
// additional invariant checks can be declared above and then added to this
|
||||||
// tuple
|
// tuple
|
||||||
using InvariantChecks = std::tuple<
|
using InvariantChecks = std::tuple<
|
||||||
@@ -927,7 +951,8 @@ using InvariantChecks = std::tuple<
|
|||||||
ValidPseudoAccounts,
|
ValidPseudoAccounts,
|
||||||
ValidLoanBroker,
|
ValidLoanBroker,
|
||||||
ValidLoan,
|
ValidLoan,
|
||||||
ValidVault>;
|
ValidVault,
|
||||||
|
NoEmptyDirectory>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get a tuple of all invariant checks
|
* @brief get a tuple of all invariant checks
|
||||||
|
|||||||
Reference in New Issue
Block a user