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

add instruction to close violation report #19

Merged
merged 6 commits into from
Feb 25, 2025

Conversation

AshwinSekar
Copy link
Contributor

After a violation report has been written and at least 3 epochs have passed, anyone can close the report account and credit the lamports to the destination account specified on the report.

Requires write access to the report account, and the destination account and then:

  • Check that we own the report account and it is not empty
  • Check that current epoch >= report epoch + 3
  • Check that the destination account matches the destination specified on the report
  • Realloc the report account to 0 bytes and assign the system program as the owner
  • Transfer all the lamports from report account to the destination account

@@ -37,3 +37,51 @@ pub fn get_violation_report_address(
&id(),
)
}

struct ViolationReportAddress<'a> {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

not sure if me trying to reuse some code made this better or worse, happy to delete this if you think worse.

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks good actually! My only comment would be to move it to another file like state.rs or create address.rs since it's only used internally.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved it to a separate file here f9ab512
After removing the system program from CloseViolationReport, we actually don't need it there, so there's only one consumer. I've kept it here in case we need it in the future.

Copy link
Contributor

@joncinque joncinque left a comment

Choose a reason for hiding this comment

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

Looks good overall! Mostly nits and a way to simplify the logic a bit (I hope)

/// `[get_violation_report_address]` for the address derivation.
/// 1. `[WRITE]` Destination account which will be credited the lamports
/// from the PDA.
/// 2. `[]` System program
Copy link
Contributor

Choose a reason for hiding this comment

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

This shouldn't be needed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed it here 754ad31

encode_instruction(
accounts,
SlashingInstruction::CloseViolationReport,
&[0u8; 0],
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: is it possible to use some form of () instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good point, used &() instead 68e2d6a

@@ -37,3 +37,51 @@ pub fn get_violation_report_address(
&id(),
)
}

struct ViolationReportAddress<'a> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks good actually! My only comment would be to move it to another file like state.rs or create address.rs since it's only used internally.

Comment on lines 317 to 326
let transfer_instruction = system_instruction::transfer(&report_key, &destination, lamports);
invoke_signed(
&transfer_instruction,
&[
report_account.clone(),
destination_account.clone(),
system_program_account.clone(),
],
&[&seeds],
)?;
Copy link
Contributor

Choose a reason for hiding this comment

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

It'll be much easier to just subtract the lamports directly from report_account and then realloc / reassign, and that way there's no need to CPI to the system program.

Check out how the token program does this: https://github.com/solana-program/token/blob/08aa3ccecb30692bca18d6f927804337de82d5ff/program/src/processor.rs#L702-L708

We'll just need some special logic to do nothing if the destination is the report account itself, so that accounts are always closable. Alternatively, we can make sure the destination isn't the report account during creation

Copy link
Contributor Author

@AshwinSekar AshwinSekar Feb 15, 2025

Choose a reason for hiding this comment

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

That's much easier! Removed it here 754ad31

And good point, i decided to return an error if your destination is equal to the report address on report creation and added a test 3dfef7d

Comment on lines 160 to 169
context
.banks_client
.simulate_transaction(transaction.clone())
.await?
.result
.unwrap()?;
context
.banks_client
.process_transaction(transaction)
.await?;
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the point of simulating before processing? You should get an error back either way if the transaction fails

Copy link
Contributor Author

@AshwinSekar AshwinSekar Feb 15, 2025

Choose a reason for hiding this comment

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

I was running into what I believe was status cache issues because I was sending the same close report transaction with the same block hash while updating the clock sysvar. Got lazy and put in this hack to simulate instead 😅 .

Turns out there's a warp_to_epoch that does the proper setup of the new bank so we don't need this hack and also removes the need for incrementing the clock's epoch field manually cc8d301

context: &mut ProgramTestContext,
report_key: Pubkey,
destination: Pubkey,
initial_lamports: u64,
Copy link
Contributor

Choose a reason for hiding this comment

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

Up to you, but rather than passing this in, it could be fetched from the report account in this function

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Saves us an arg, fetched it instead 68e2d6a

Comment on lines 657 to 664
let err = context
.banks_client
.process_transaction(transaction)
.simulate_transaction(transaction)
.await
.unwrap_err()
.unwrap();
.unwrap()
.result
.unwrap()
.unwrap_err();
Copy link
Contributor

Choose a reason for hiding this comment

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

Was this change intended?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not intended, this is leftover from when I was testing out simulate transaction for the hack, removed it and the ones below

Comment on lines 755 to 762
let err = context
.banks_client
.process_transaction(transaction)
.simulate_transaction(transaction)
.await
.unwrap_err()
.unwrap();
.unwrap()
.result
.unwrap()
.unwrap_err();
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here, was this change intended?

Comment on lines 1105 to 1115
// Close report should fail with invalid destination account
let err = close_report(
&mut context,
report_key,
Pubkey::new_unique(),
report_account.lamports,
3,
)
.await
.unwrap_err()
.unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

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

Not a big deal, but this is missing a call to setup_clock before calling close_report

Copy link
Contributor

@joncinque joncinque left a comment

Choose a reason for hiding this comment

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

Looks great, thanks for integrating all the feedback!

@AshwinSekar AshwinSekar merged commit 9330097 into solana-program:main Feb 25, 2025
7 checks passed
@AshwinSekar AshwinSekar deleted the close-report branch February 25, 2025 19:49
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.

2 participants