Skip to content
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

Nuke cows in Receipt #12470

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft

Nuke cows in Receipt #12470

wants to merge 2 commits into from

Conversation

eagr
Copy link
Contributor

@eagr eagr commented Nov 15, 2024

Addressing #12313 (comment) from @wacban

Getting rid of the Cows should make the receipt interface nicer to use.

@eagr eagr requested a review from a team as a code owner November 15, 2024 21:16
@eagr eagr requested a review from wacban November 15, 2024 21:16
@@ -491,10 +490,11 @@ impl DelayedReceiptQueueWrapper {
true => {
let metadata =
StateStoredReceiptMetadata { congestion_gas: gas, congestion_size: size };
let receipt = StateStoredReceipt::new_borrowed(receipt, metadata);
// FIXME eagr
let receipt = StateStoredReceipt::new(receipt.clone(), metadata);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Are these clones gonna be deal breaker? @wacban

Copy link
Contributor

@jancionear jancionear Nov 15, 2024

Choose a reason for hiding this comment

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

It would be great if we could avoid cloning receipts. Cloning a receipt is a dangerous operation because it duplicates the operation that will be performed when the receipt is executed. For example duplicating a transfer receipt could potentially lead to double spending.
Ideally the receipts would never be cloned. Pushing a receipt onto a queue should consume the receipt. This way the compiler would ensure that a receipt is never cloned and receipts are never duplicated.

I'm not a fan of cloning as a solution for Cow, is it possible to refactor the code so that the receipts are consumed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not a fan of cloning as a solution for Cow, is it possible to refactor the code so that the receipts are consumed?

I was entirely not sure those either, kinda wanna go the naive way first to see what it breaks to gain a better idea of why Cow was used in the first place. Yeah, I'll see what I could do

Copy link
Contributor

Choose a reason for hiding this comment

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

If the receipts can't be consumed because information about them is needed later, maybe it would be possible to save the information and consume the receipt? Like having a queue which consumes the Receipt and returns ReceiptInfo that is used later. ReceiptInfo would contain the needed information, while not being a cloned receipt that can be executed.

I don't remember why exactly there was a problem with consuming them.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree with jancio, the clones were introduced precisely in order to avoid clone on receipts.

Agree with jancio again, the receipt should be consumed, I think only some metadata about it is needed after it's been stored in the StateStoredReceipt. That would require some refactoring.

@eagr It's a great first step! I think now you can just make the receipt consumed by removing reference, see what breaks and refactor as needed. IIRC there was only one such place, where we need some simple stats about local receipts.

Copy link

codecov bot commented Nov 15, 2024

Codecov Report

Attention: Patch coverage is 91.66667% with 1 line in your changes missing coverage. Please review.

Project coverage is 71.45%. Comparing base (bd73c72) to head (afbf528).

Files with missing lines Patch % Lines
runtime/runtime/src/congestion_control.rs 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #12470      +/-   ##
==========================================
- Coverage   71.45%   71.45%   -0.01%     
==========================================
  Files         838      838              
  Lines      169343   169332      -11     
  Branches   169343   169332      -11     
==========================================
- Hits       121004   120996       -8     
+ Misses      42993    42991       -2     
+ Partials     5346     5345       -1     
Flag Coverage Δ
backward-compatibility 0.16% <0.00%> (+<0.01%) ⬆️
db-migration 0.16% <0.00%> (+<0.01%) ⬆️
genesis-check 1.29% <0.00%> (+<0.01%) ⬆️
integration-tests 39.33% <58.33%> (-0.02%) ⬇️
linux 70.78% <91.66%> (-0.01%) ⬇️
linux-nightly 71.01% <91.66%> (+<0.01%) ⬆️
macos 51.03% <50.00%> (+<0.01%) ⬆️
pytests 1.60% <0.00%> (+<0.01%) ⬆️
sanity-checks 1.40% <0.00%> (+<0.01%) ⬆️
unittests 63.99% <83.33%> (+<0.01%) ⬆️
upgradability 0.21% <0.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@jancionear
Copy link
Contributor

There is gonna be a merge conflict with #12464 which adds StateStoredReceiptV1, but it shouldn't be too bad.

Comment on lines 143 to 147
#[derive(PartialEq, Eq, Debug, ProtocolSchema)]
pub enum ReceiptOrStateStoredReceipt<'a> {
Receipt(Cow<'a, Receipt>),
StateStoredReceipt(StateStoredReceipt<'a>),
pub enum ReceiptOrStateStoredReceipt {
Receipt(Receipt),
StateStoredReceipt(StateStoredReceipt),
}
Copy link
Contributor

@jancionear jancionear Nov 15, 2024

Choose a reason for hiding this comment

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

The protocol schema CI check is failing because structs with ProtocolSchema derive were updated without updating the checksum file. This is a sanity check to ensure that the serialization format of structs that are part of the protocol doesn't accidentally change. Please ensure that modifying the struct doesn't change the serialization format (you can borsh serialize it before and after the change and compare) and update the checksums.

See: https://github.com/near/nearcore/tree/master/tools/protocol-schema-check

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nice to know, thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

could confirm that removing the Cows doesn't change the data layout

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The protocol schema check is great. But is it possible that there could be a false false-positive (author decides a change of schema doesn't alter the data layout or it's backward compatible, but they are wrong)? When the checks fail, it's still up to developers to decide whether migration is needed. Cows here are alright, the serialization is straightforward, kinda obvious it wouldn't change the serialized format and it's easy to verify. But for more intricate cases, is there a safety net to ensure the data layout actually doesn't change? I may be overthinking. :))

Copy link
Contributor

Choose a reason for hiding this comment

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

It's possible but in my experience it's more likely that a developer forgets to add ProtocolSchema to a new structure.

We have canary nodes running on master (updated nightly) so if there is any protocol upgrade that isn't correctly handled we would see that. Then we have pre-release tests where we spin up a small network and gradually update nodes. Finally there is testnet and we really shouldn't break anything there but it is the final line of defense before mainnet.

@eagr
Copy link
Contributor Author

eagr commented Nov 15, 2024

There is gonna be a merge conflict with #12464 which adds StateStoredReceiptV1, but it shouldn't be too bad.

In that case, as this is not critical, it could wait until your PR is landed. :)

@eagr eagr marked this pull request as draft November 16, 2024 03:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants