Skip to content

ExtendedHookState #406

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 26 commits into
base: dev
Choose a base branch
from
Open

ExtendedHookState #406

wants to merge 26 commits into from

Conversation

tequdev
Copy link
Collaborator

@tequdev tequdev commented Dec 11, 2024

  • Extended the size of HookStateData, and cost one incremental reserve for every 256 bytes
  • The maximum HookStateData size is tentatively set to 2048 (256*8) / Discussion needed

High Level Overview of Change

Context of Change

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (non-breaking change that only restructures code)
  • Tests (you added tests for code that already exists, or your new feature included in this PR)
  • Documentation update
  • Chore (no impact to binary, e.g. .gitignore, formatting, dropping support for older tooling)
  • Release

API Impact

  • Public API: New feature (new methods and/or new fields)
  • Public API: Breaking change (in general, breaking changes should only impact the next api_version)
  • libxrpl change (any change that may affect libxrpl or dependents of libxrpl)
  • Peer protocol change (must be backward compatible or bump the peer protocol version)

tequdev

This comment was marked as resolved.

@tequdev tequdev changed the title ExtendedHookState [DO NOT MERGE] ExtendedHookState Mar 30, 2025
@tequdev tequdev added Amendment New feature or fix amendment feature Feature Request labels Mar 30, 2025
@RichardAH
Copy link
Contributor

RichardAH commented Jun 18, 2025

I think we should not add the complexity of incremental reserve increase, rather just increase the allowable size for the same existing reserve cost. I think 1 reserve for 2048 bytes is probably ok.

An alternative simpler fee model would be to nominate your account for "large hook data" whereupon all your hook states cost more to store but you have access to the larger size. I really dislike the idea of a variable length field claiming different reserves depending on its current size.

@tequdev
Copy link
Collaborator Author

tequdev commented Jun 19, 2025

I think we should not add the complexity of incremental reserve increase, rather just increase the allowable size for the same existing reserve cost. I think 1 reserve for 2048 bytes is probably ok.

An alternative simpler fee model would be to nominate your account for "large hook data" whereupon all your hook states cost more to store but you have access to the larger size. I really dislike the idea of a variable length field claiming different reserves depending on its current size.

Can you explain “large hook data” in more detail?

@RichardAH
Copy link
Contributor

Can you explain “large hook data” in more detail?

Sure, so you do an account set flag which is like the equivalent of specifying large pages in your OS. All your hook states cost more but they're allowed to be bigger. It makes the computation easier. So let's say in large mode you get 2048 bytes per hook state but in computing reserve requirements for your hook state we take your HookStateCount and multiply it by 8. Once the flag is enabled it can only be disabled if HookStateCount is 0.

@tequdev
Copy link
Collaborator Author

tequdev commented Jun 22, 2025

Can you explain “large hook data” in more detail?

Sure, so you do an account set flag which is like the equivalent of specifying large pages in your OS. All your hook states cost more but they're allowed to be bigger. It makes the computation easier. So let's say in large mode you get 2048 bytes per hook state but in computing reserve requirements for your hook state we take your HookStateCount and multiply it by 8. Once the flag is enabled it can only be disabled if HookStateCount is 0.

That's interesting.
Instead of using the flag, how about using a numeric field to represent the maximum size the account allows?

If we use the flag, whenever we need to increase the protocol's maximum allowed size, we end up having to add a new flag.

@RichardAH
Copy link
Contributor

That's interesting. Instead of using the flag, how about using a numeric field to represent the maximum size the account allows?

If we use the flag, whenever we need to increase the protocol's maximum allowed size, we end up having to add a new flag.

I think that's reasonable. We could say HookStateScale or something 0,1 ...

@@ -32,6 +32,7 @@ class HookStateMap : public std::map<
std::tuple<
int64_t, // remaining available ownercount
int64_t, // total namespace count
int16_t, // hook state scale
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind if you use int16_t or uint16_t or uint32_t but keep it consistent with the function calls? like maxHookStateDataSize(uint32_t hookStateScale) same for the sf type

@@ -921,7 +927,7 @@ SetHook::destroyNamespace(
view.erase(sleItem);
}

uint32_t stateCount = oldStateCount - toDelete.size();
uint32_t stateCount = oldStateCount - toDeleteStateCount;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was there a reason for changing this? I assume it doesn't change the outcome

@@ -937,7 +943,7 @@ SetHook::destroyNamespace(
sleAccount->setFieldU32(sfHookStateCount, stateCount);

if (ctx.rules.enabled(fixNSDelete))
adjustOwnerCount(view, sleAccount, -toDelete.size(), ctx.j);
adjustOwnerCount(view, sleAccount, -toDeleteStateCount * scale, ctx.j);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should do a sanity check on this value before passing it to make sure it is reasonable and hasn't overflowed

@@ -1517,19 +1528,22 @@ set_state_cache(
stateMap.modified_entry_count++;

stateMap[acc] = {
availableForReserves - 1,
availableForReserves - hookStateScale,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need defensive sanity checks on math like this

@@ -1547,7 +1561,7 @@ set_state_cache(
namespaceCount++;
}

availableForReserves--;
availableForReserves -= hookStateScale;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overflow sanity check needed

if (modified)
{
if (!canReserveNew)
return RESERVE_INSUFFICIENT;
availableForReserves--;
availableForReserves -= hookStateScale;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here too

@@ -94,6 +94,8 @@ transResults()
MAKE_ERROR(tecINSUF_RESERVE_SELLER, "The seller of an object has insufficient reserves, and thus cannot complete the sale."),
MAKE_ERROR(tecIMMUTABLE, "The remark is marked immutable on the object, and therefore cannot be updated."),
MAKE_ERROR(tecTOO_MANY_REMARKS, "The number of remarks on the object would exceed the limit of 32."),
MAKE_ERROR(tecHAS_HOOK_STATE, "The account has hook state."),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe expand the explanation to "The account has hook state. Delete all existing state before changing the scale."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Amendment New feature or fix amendment feature Feature Request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants