Skip to content
This repository has been archived by the owner on Jan 22, 2025. It is now read-only.

system-program: Remove zero lamport check on transfers #17726

Merged
merged 9 commits into from
Jun 5, 2021

Conversation

joncinque
Copy link
Contributor

Problem

It's possible to bypass signature checks if transferring 0 lamports, causing potential unclear / misleading behavior.

Summary of Changes

Perform all checks on transfers, even for 0 lamports.

Fixes #

@joncinque joncinque requested review from jstarry and mvines June 3, 2021 23:20
Comment on lines 182 to 188

if invoke_context.is_feature_active(&feature_set::system_transfer_zero_check::id())
&& lamports == 0
{
return Ok(());
}

Copy link
Contributor

Choose a reason for hiding this comment

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

this looks unnecessary. The lamports check below will be bypassed when lamports == 0

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah it looks a bit silly, but it avoids unnecessary calls to try_account_ref_mut() later on. If there's no possible issues with doing those, I'm happy to get rid of this

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah no possible issues with that, let's get rid of it

jstarry
jstarry previously approved these changes Jun 3, 2021
@@ -1103,7 +1125,7 @@ mod tests {
0,
&MockInvokeContext::new(vec![]),
)
.is_ok(),);
.is_err(),);
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we assert_eq!(transfer(), Err(InstructionError::MissingRequiredSignature)); here instead? Reordering of errors will break consensus and we should be able to catch it.

@joncinque joncinque changed the title system-program: Move zero lamport check on transfers system-program: Remove zero lamport check on transfers Jun 4, 2021
@mergify mergify bot dismissed jstarry’s stale review June 4, 2021 10:36

Pull request has been modified.

@joncinque
Copy link
Contributor Author

@jstarry @t-nelson Could I ask for another quick check? The stake split instruction uses the create_account with 0 lamports assumption, which makes one test fail in particular at

assert!(bank_client
. In the test, we're splitting from a stake that is auto-authorized, so when we try to split from it, we get an error because an account with data is trying to transfer lamports. I've updated the split instruction to allocate + assign separately. Since this could break people using split with auto-authorized stakes in 1.6, I'll remove that backport and only backport to 1.7. Let me know what you think.

@joncinque joncinque removed the v1.6 label Jun 4, 2021
@@ -179,6 +179,7 @@ fn transfer_verified(
ic_msg!(invoke_context, "Transfer: `from` must not carry data");
return Err(InstructionError::InvalidArgument);
}

Copy link
Contributor

Choose a reason for hiding this comment

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

nit: avoid change here

mvines
mvines previously approved these changes Jun 4, 2021
@mvines mvines added the v1.6 label Jun 4, 2021
&id(),
),
system_instruction::allocate(split_stake_pubkey, std::mem::size_of::<StakeState>() as u64),
system_instruction::assign(split_stake_pubkey, &id()),
Copy link
Contributor

Choose a reason for hiding this comment

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

This will break the Ledger app's parser. Splits will need to be blind signed until it's updated

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah right. Good ole lazy past-Trent saves the day 😉

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a rarity. I don't think past me has ever helped me that much

t-nelson
t-nelson previously approved these changes Jun 4, 2021
@mergify mergify bot dismissed stale reviews from mvines and t-nelson June 4, 2021 16:20

Pull request has been modified.

@@ -288,7 +288,6 @@ pub fn split_with_seed(
std::mem::size_of::<StakeState>() as u64,
&id(),
),
system_instruction::assign_with_seed(split_stake_pubkey, base, seed, &id()),
Copy link
Contributor

Choose a reason for hiding this comment

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

Landmines everywhere!

SystemInstruction::AllocateWithSeed {
base,
seed,
space,
owner,
} => {
let keyed_account = keyed_account_at_index(keyed_accounts, 0)?;
let mut account = keyed_account.try_account_ref_mut()?;
let address = Address::create(
keyed_account.unsigned_key(),
Some((&base, &seed, &owner)),
invoke_context,
)?;
allocate_and_assign(

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Seriously. You should see my most recent commit 😅

@joncinque
Copy link
Contributor Author

@t-nelson @jstarry sorry, just one more check please on bdd6da6 -- with these changes, it's also possible to split a stake into an account that already has lamports, which is currently supported by the stake program. For some reason, there's an existing test to make sure that this isn't possible, even though this behavior is reasonable. As such, I've updated the test from a failure to a success.

@jstarry
Copy link
Contributor

jstarry commented Jun 4, 2021

It's usually a mistake to split into an account which already has lamports. However, this is a recoverable mistake because a split account can have its extra lamports withdrawn and it can also be merged and closed completely if needed. I think that the "existing account" check should be a client side check in the cli rather than in the transaction. This looks good to me

@t-nelson
Copy link
Contributor

t-nelson commented Jun 4, 2021

It's usually a mistake to split into an account which already has lamports. However, this is a recoverable mistake because a split account can have its extra lamports withdrawn and it can also be merged and closed completely if needed. I think that the "existing account" check should be a client side check in the cli rather than in the transaction. This looks good to me

Agreed. This is no worse than doing a system transfer into a delegated stake account. Which is annoying, but no funds are at risk past a bit of dust for fees

@codecov
Copy link

codecov bot commented Jun 5, 2021

Codecov Report

Merging #17726 (bdd6da6) into master (708bbcb) will decrease coverage by 0.0%.
The diff coverage is 40.7%.

@@            Coverage Diff            @@
##           master   #17726     +/-   ##
=========================================
- Coverage    82.7%    82.7%   -0.1%     
=========================================
  Files         431      431             
  Lines      120590   120610     +20     
=========================================
+ Hits        99839    99841      +2     
- Misses      20751    20769     +18     

@joncinque joncinque merged commit 8f5e773 into solana-labs:master Jun 5, 2021
@joncinque joncinque deleted the transfer-check branch June 5, 2021 23:45
mergify bot pushed a commit that referenced this pull request Jun 5, 2021
* system-program: Move lamports == 0 check on transfers

* Address feedback

* Update stake split to explicitly allocate + assign

* Update stake tests referring to split instruction

* Revert whitespace

* Update split instruction index in test

* Remove unnecessary `assign_with_seed` from `split_with_seed`

* Fix stake instruction parser

* Update test to allow splitting into account with lamports

(cherry picked from commit 8f5e773)

# Conflicts:
#	runtime/src/system_instruction_processor.rs
#	sdk/src/feature_set.rs
mergify bot pushed a commit that referenced this pull request Jun 5, 2021
* system-program: Move lamports == 0 check on transfers

* Address feedback

* Update stake split to explicitly allocate + assign

* Update stake tests referring to split instruction

* Revert whitespace

* Update split instruction index in test

* Remove unnecessary `assign_with_seed` from `split_with_seed`

* Fix stake instruction parser

* Update test to allow splitting into account with lamports

(cherry picked from commit 8f5e773)
mergify bot added a commit that referenced this pull request Jun 6, 2021
* system-program: Move lamports == 0 check on transfers

* Address feedback

* Update stake split to explicitly allocate + assign

* Update stake tests referring to split instruction

* Revert whitespace

* Update split instruction index in test

* Remove unnecessary `assign_with_seed` from `split_with_seed`

* Fix stake instruction parser

* Update test to allow splitting into account with lamports

(cherry picked from commit 8f5e773)

Co-authored-by: Jon Cinque <jon.cinque@gmail.com>
mergify bot added a commit that referenced this pull request Jun 7, 2021
…) (#17763)

* system-program: Remove zero lamport check on transfers (#17726)

* system-program: Move lamports == 0 check on transfers

* Address feedback

* Update stake split to explicitly allocate + assign

* Update stake tests referring to split instruction

* Revert whitespace

* Update split instruction index in test

* Remove unnecessary `assign_with_seed` from `split_with_seed`

* Fix stake instruction parser

* Update test to allow splitting into account with lamports

(cherry picked from commit 8f5e773)

# Conflicts:
#	runtime/src/system_instruction_processor.rs
#	sdk/src/feature_set.rs

* Resolve merge conflicts

Co-authored-by: Jon Cinque <jon.cinque@gmail.com>
This was referenced Aug 23, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants