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
[breaking][libra-framework] Refactor writeset prologue and epilogue #6042
[breaking][libra-framework] Refactor writeset prologue and epilogue #6042
Conversation
@@ -443,22 +443,6 @@ impl LibraVM { | |||
return Ok((e, discard_error_output(StatusCode::REJECTED_WRITE_SET))); | |||
}; | |||
|
|||
// Bump the sequence number of sender. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By refactoring the epilogue we can get rid of this piece of ugly code.
@@ -69,7 +69,7 @@ impl BlockMetadata { | |||
} | |||
|
|||
pub fn new_block_event_key() -> EventKey { | |||
EventKey::new_from_address(&libra_root_address(), 20) | |||
EventKey::new_from_address(&libra_root_address(), 21) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an unforunate consequnce of this change as we changed the order of how event handles are generated. Do we want to keep the same magic value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update: I got rid of this change by reorganizing the genesis intialization code, as this will also change the event key for a number of other system events (all mint related events).
UpgradeEvent { writeset_payload }, | ||
); | ||
// Currency code don't matter here as it won't be charged anyway. | ||
epilogue<LBR::LBR>(lr_account, writeset_sequence_number, 0, 0, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 0
uglyness still resides. Do we want to make clean separation of incrementing sequence number only? IMHO having multiple function will introduce extra borrow_global. Do we want to trade that for the code cleaness?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's fine like this. Keep it simple....
0bd7372
to
74ffffd
Compare
a9ff90e
to
035ea01
Compare
@bob-wilson @sblackshear @tzakian @tnowacki you all have looked at and talked about this quite a bit. |
/// The prologue for WriteSet transaction | ||
fun writeset_prologue( | ||
sender: &signer, | ||
writeset_sequence_number: u64, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we name these "txn_sequence_number" and "txn_public_key" for consistency with the other prologue functions? The account has a single sequence number shared for all kinds of transactions, right?
UpgradeEvent { writeset_payload }, | ||
); | ||
// Currency code don't matter here as it won't be charged anyway. | ||
epilogue<LBR::LBR>(lr_account, writeset_sequence_number, 0, 0, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's fine like this. Keep it simple....
Added back the specs from the old module. Renamed writeset_sequence_number to transaction_sequence_number |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall this looks good to me. A couple nits here and there.
The main thing I think we should consider here is combining the two singleton resources in this module (LibraWriteSetManager
and AccountOperationsCapability
). I would be in favor of combining them unless there are reasons that I'm not aware of.
@@ -188,6 +201,25 @@ module LibraAccount { | |||
); | |||
} | |||
|
|||
public fun initialize_writeset_manager( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be combined with the initialize
function for this module? It seems like a cleaner approach to include this with that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yesss! There's a slight gotcha here: the order of how event handles are generated are depending on the order of calls in the genesis module. If we merge those functions, the event key for a number of functions will be modified. The most important one of them is probably the EventKey for new_epoch_event will be off by one, which will be a "bigger" change. Some of the json-rpc tests also hard coded those event keys. That's why I keep the two resource separate and have two init functions so that the order of creating event handles could be perserved.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoiding churn in the EventKeys seems worth it to have 2 init functions. My $0.02
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is already a breaking PR that changes the initialization sequence of events and changes these event keys (see Davids SEV post in libra core). It might be worthwhile to try and coordinate this with that PR, and then we could combine these and have only one break of the event keys?
@@ -79,10 +80,18 @@ module LibraAccount { | |||
limits_cap: AccountLimitMutationCapability, | |||
} | |||
|
|||
/// A resource for the number of WriteSets that has been committed on chain. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think of including this in the AccountOperationsCapability
(and possibly renaming to something more descriptive)? It's a singleton resource as well, so seems like it would be a good fit.
The comment also seems opaque: "number of Writesets" doesn't really make sense to me. Please update to clarify.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Certainly the comment should be fixed up, but at this point, I'd say that it would be best to minimize the change and keep it as a separate resource, just from the perspective of reducing risk and churn in the code. I could be convinced otherwise if you really think it is worth doing....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question about churn, and I would agree if this weren't already a breaking change...
I guess my opinion here is that since it is a breaking change already that we should combine these since combining them is no more "breaking" than moving the LibraWriteSetManager resource which is being done in this PR. This will need to be a genesis reset either way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I defer to your expertise but please be cautious....
cc @shazqadeer in case you're working on the prologue |
63cc29b
to
2153e46
Compare
); | ||
assert(Roles::has_libra_root_role(sender), Errors::invalid_argument(PROLOGUE_INVALID_WRITESET_SENDER)); | ||
|
||
// Currency code don't matter here as it won't be charged anyway. Gas constants are ommitted. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could go either way on this but...
It feels a bit bizarre to me to that we are using a "common" prologue function here when a few of the checks aren't common.
I would want it to be extraordinarily clear what checks are being done in each prologue. Passing in 0's and then saying we ignoring type arguments feels brittle to me. And I feel might be confusing. I feel the goal of these prologue functions should be to make it 100% clear what checks are being performed on each transaction type.
So counter proposal here, split prologue common into separate verification/check passes
The existing calls to prologue_common
would be something like
prologue_check_account_data(...);
prologue_check_gas_payment<TOKEN>(...);
prologue_check_sequence_number(...);
Then for the writeset check here, we would have
prologue_check_account_data(...);
prologue_check_sequence_number(...);
UpgradeEvent { writeset_payload }, | ||
); | ||
// Currency code don't matter here as it won't be charged anyway. | ||
epilogue<LBR::LBR>(lr_account, txn_sequence_number, 0, 0, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment above about splitting off checks. I'd prefer to see separate functions then one centralized function with a bunch of dummy arguments
Existing epilogue would contain
fun epilogue<...>(...) {
epilogue_deduct_gas_payment(...)
epilogue_bump_sequence_number(...)
}
I do not like having one central function and then having to jump through hoops to convince ourselves it is safe
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit torn over here. On one hand I love this idea of having separate functions we can call to get the logics we want. On the other hand, I'm trying to minimize the code change and keep the code structure as it was (and try to merge it ASAP as soon as #5997 lands to leverage the fact that it is touching the genesis init order). I'm also wasn't sure how it might affect the prover side work. Do you have any strong preference over here? cc @tzakian @sblackshear @shazqadeer for thoughts as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like splitting it up might make the prover's life easier? beats me though
If its seems like work to convince a human that the checks aren't happening, I feel like it might be cumbersome to convey this in the spec as well, but I could be wrong
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think splitting it would make the prover's life easier (but, it's one of those things where it's hard to determine exactly what will make it harder/easier until you start proving it). I think for now in the interest of getting the breaking change in for this release cycle (cut tomorrow morning) I would like to hold off on this, and if we do decide to refactor it out we can later on and that shouldn't be a breaking change.
@@ -1121,6 +1198,14 @@ module LibraAccount { | |||
// Check that the chain ID stored on-chain matches the chain ID specified by the transaction | |||
assert(ChainId::get() == chain_id, Errors::invalid_argument(PROLOGUE_EBAD_CHAIN_ID)); | |||
|
|||
// Check that the gas calculation will not overflow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was this check moved?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I shouldn't move them. This was coming from my previous version of refactor where I had the gas related function outside of prologue_common
2153e46
to
1cabb18
Compare
Interestingly, when bundled this PR with #5997, it reverted the change to json-rpc tests as the orders are still preserved. However there's still changes done to new_epoch_event and new_block_event which still made this PR a "hard" breaking change. |
92df18b
to
47221b9
Compare
2deba20
to
af9c2a2
Compare
510febb
to
b6896c0
Compare
@tzakian @bob-wilson Is the current version with what is checked in now? In that case I'm happy with that too. It looks like there were two checks added to the writeset prologue and the VM? Maybe we should just do those two changes as a smaller PR and get them in ASAP |
I'm not sure what you're asking. I was referring to the current contents of this PR. I think it's ready to land.
Yes, this fixes #5708 by adding checks for the ChainID and txn expiration. I'd much prefer to just land this one. Otherwise, if this doesn't go in along with #5997, I think we should go back to a separate initialization function to preserve the event keys, and Tim really didn't like like that. |
Yep, I'm good with this going in as-is. Agreed on getting this in ASAP (need to land before tomorrow morning!) |
/help |
Bors help and documentationBors is a Github App used to manage merging of PRs in order to ensure that CI is always green. It does so by maintaining a Merge Queue. Once a PR reaches the head of the Merge Queue it is rebased on top of the latest version of the PR's General
CommandsBors actions can be triggered by posting a comment which includes a line of the form
OptionsOptions for Pull Requests are configured through the application of labels. |
/land |
Cluster Test Result
Repro cmd:
🎉 Land-blocking cluster test passed! 👌 |
b6896c0
to
ce88eb4
Compare
Motivation
Refactored writeset prologue and epilogue by merging the LibraWriteSetManager module into LibraAccount. This will make the prologue/epilogue code more modular. Also added checks for chain_id and expiration time for WriteSet Transaction.
This change is a breaking change.
Have you read the Contributing Guidelines on pull requests?
Yes
Test Plan
cargo test
Related PRs
This is a less aggressive version of #5881