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

Remove congestion multiplier from calculate_fee function #34537

Conversation

tao-stones
Copy link
Contributor

@tao-stones tao-stones commented Dec 19, 2023

Problem

bank.calculate_fee() takes a parameter with misleading name (lamports_per_signature) for testing congestion multiplier to be zero, which has been removed everywhere. That parameter should also be removed.

Due to legacy or perhaps misleading name of the parameter, call sites are calling extra code to resolve lamports_per_signature before calling calculate_fee(), in some instances, it locks hash_queue to do so. All of these are not necessary.

Summary of Changes

  • remove congestion_multiplier within calculate_fee()
  • remove lamports_per_signature input parameter of calculate_fee(), durable transaction also uses fee rate from time of execution.
  • remove code that fetches lamports_per_signature from nonce account leading to call of calculate_fee()

Fixes #

sdk/src/fee.rs Show resolved Hide resolved
@@ -4058,22 +4055,6 @@ impl Bank {
.verification_complete()
}

pub fn get_fee_for_message_with_lamports_per_signature(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

fee_structure.calculate_fee() doesn't take lamports_per_signature anymore, this function can be fold into above bank.get_fee_for_message().

})
})?;
Some(self.get_fee_for_message_with_lamports_per_signature(message, lamports_per_signature))
pub fn get_fee_for_message(&self, message: &SanitizedMessage) -> u64 {
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 return type changed from option<u64> to u64, that leads to many updates on callsite

@@ -52,7 +51,6 @@ pub(super) fn load_accounts(
ancestors: &Ancestors,
txs: &[SanitizedTransaction],
lock_results: Vec<TransactionCheckResult>,
hash_queue: &BlockhashQueue,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

hash_queue was used to resolve lamports_per_signature, which is no longer needed.

@tao-stones tao-stones force-pushed the remove-congestion-multipler-from-calc-fee branch from cec0ec8 to 068db48 Compare December 20, 2023 15:54
@tao-stones tao-stones marked this pull request as ready for review December 20, 2023 15:54
let genesis = create_genesis_config(10);
// Fund payer account with minimal transaction fee for one signature, plus some extra.
let mint_lamports = 10 + solana_sdk::fee::FeeStructure::default().lamports_per_signature;
let genesis = create_genesis_config(mint_lamports);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Previously, load_accounts() read BlockHashQueue for fee_calculator.lamports_per_signature, then use it as "congestion_multiplier". fee_calculator perhaps should not be used anymore. In any case, fee_calculator.lamports_per_signature would be zero in this test, therefore would have set transaction fee to 0.

With the change in this PR, eg removing congestion_multiplier all together, this transaction transaction will have fee of 1 signature (eg 5000 lamports). Account this in mint account corrects the test.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Bunch of other tests, including those form local-cluster tests, might have been broken for the same reason:

  • genesis is configured with 0 lamports_per_signature in fee_calculator.
  • it is read in as congestion_multipler, that effectively set transaction fee to 0.
  • tests were setup with low balance since transaction has zero fee.
  • with changes in this PR, transaction will have 5000 lamports per signature fee, that fails transactions with low payer balance.

One option is to initialize bank.fee_structure from blockhash_queue.fee_calculate.lamport_per_signature, instead of default, that should keep all exist tests success without further changes. But that itself has risk, should be in its own pr.

@tao-stones tao-stones force-pushed the remove-congestion-multipler-from-calc-fee branch 2 times, most recently from 3238dcf to e3d9b1a Compare December 21, 2023 04:02
@github-actions github-actions bot added the stale [bot only] Added to stale content; results in auto-close after a week. label Jan 4, 2024
@jstarry
Copy link
Contributor

jstarry commented Jan 10, 2024

I agree that this code is messy but I'm not sure that this is the right way to clean it up. I believe the reason that the lamports_per_signature is passed here is so that it can be overridden for durable nonce transactions. Maybe @t-nelson can add more context on what the latest discussion on durable nonce tx fees was?

@github-actions github-actions bot removed the stale [bot only] Added to stale content; results in auto-close after a week. label Jan 10, 2024
@t-nelson
Copy link
Contributor

I agree that this code is messy but I'm not sure that this is the right way to clean it up. I believe the reason that the lamports_per_signature is passed here is so that it can be overridden for durable nonce transactions. Maybe @t-nelson can add more context on what the latest discussion on durable nonce tx fees was?

was this supposed to be a line comment? where's "here"?

} else {
1.0 // multiplier that has no effect
};

let signature_fee = message
.num_signatures()
.saturating_mul(self.lamports_per_signature);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

while removing "no-longer necessary" congestion_multipler, realized there might be a bug in this line 88 above. The signature_fee is always calculated with current bank's fee_structure's lamports_per_signature, it should be using passed in parameter lamports_per_signature, which is determined differently for nonce tx and normal tx.

Isn't this a bug? @t-nelson @jstarry

I traced it back to #23095 where behavior seems changed.

Copy link
Contributor

Choose a reason for hiding this comment

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

mmm, i don't remember the intent of this "congestion" fee. lamports_per_signature already contains the signature rate based congestion fee. it's calculated at the start of the slot, https://github.com/jackcmay/solana/blob/176ef5aeb25d7b3f331a12655654e801fed06235/runtime/src/bank.rs#L1563-L1578.

Copy link
Contributor

Choose a reason for hiding this comment

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

@t-nelson can you comment on why durable nonces store lamports_per_signature and if we still intend to use that value in the future. The main thing we need to figure out to accept or reject this PR is whether or not we should be using the nonce-stored lamports_per_signature value from a previous bank here instead of the one calculated by the current bank.

Copy link
Contributor

Choose a reason for hiding this comment

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

durable nonces store lamports_per_signature because some opinionated people were very adamant about preserving the "fee-payer pays deterministic fees" meme. afaik we've already unhooked them and just use fee rate from time of execution

Copy link
Contributor Author

@tao-stones tao-stones Jan 11, 2024

Choose a reason for hiding this comment

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

another way to look at it: if #34754 is legit bugfix? (somehow, I didn't see trent's comment early) So #34754 is not legit, and durable nonce does not need to store lamports_per_signature?

@tao-stones
Copy link
Contributor Author

I agree that this code is messy but I'm not sure that this is the right way to clean it up. I believe the reason that the lamports_per_signature is passed here is so that it can be overridden for durable nonce transactions. Maybe @t-nelson can add more context on what the latest discussion on durable nonce tx fees was?

was this supposed to be a line comment? where's "here"?

"here" is calculate_fee().

It suppose to be an innocent PR to remove unused stuff 😇 But it revealed few issues. The first one is: have we been wrong in calculating nonce tx signature fee? line commente here.

2. simply bank.get_fee_for_message(), no need to resolve lamports_per_signature before calling;
3. remove a dead test that was for congestion multiplier;
@tao-stones tao-stones force-pushed the remove-congestion-multipler-from-calc-fee branch from e3d9b1a to 2743154 Compare January 12, 2024 17:22
@tao-stones
Copy link
Contributor Author

Convert this PR to Draft, going to break it into smaller and separated PRs:

  • just remove congestion_multiplier from fee calculation, and fix/harden all tests
  • new issue/PR to state durable transaction will be charged with current bank's fee rate, not by fee rate in nonce account, remove related code.

@mergify mergify bot added community Community contribution need:merge-assist labels Jan 23, 2024
@tao-stones tao-stones closed this Jan 26, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
community Community contribution need:merge-assist
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants