Prioritize Substrate txns by tip-per-effective-gas#1957
Conversation
| from: charleth.address, | ||
| privateKey: CHARLETH_PRIVATE_KEY, | ||
| maxFeePerGas: HIGH_MAX_FEE_PER_GAS, | ||
| maxPriorityFeePerGas: "0x" + TIP_PER_GAS_0.toString(16), |
There was a problem hiding this comment.
nToHex(TIP_PER_GAS_0) exists in polkadotjs for this operation.
There was a problem hiding this comment.
Ah, thanks, this is definitely the cumbersome way to do it.
I was bothered enough by it that I made createTransaction optionally take a bigint here: #2066 -- I should take advantage of that in this PR :)
| }); | ||
|
|
||
| expect(transferExts.length).to.eq(4); | ||
| expect(transferExts[0].method.section).to.eq("balances"); |
There was a problem hiding this comment.
We should also assert that the correct TX type was ordered in accordance with the Tip and not just the type (since there are 2 of each we can't be sure that the appropriate tx was picked first)
Co-authored-by: Nisheeth Barthwal <nbaztec@gmail.com>
Co-authored-by: Nisheeth Barthwal <nbaztec@gmail.com>
Co-authored-by: Nisheeth Barthwal <nbaztec@gmail.com>
Co-authored-by: Nisheeth Barthwal <nbaztec@gmail.com>
Co-authored-by: Nisheeth Barthwal <nbaztec@gmail.com>
Co-authored-by: Nisheeth Barthwal <nbaztec@gmail.com>
| [...topDelegators].map((account, i) => { | ||
| // add a tip such that the delegation ordering will be preserved, e.g. the first txns sent | ||
| // will have the highest tip | ||
| let tip = BigInt(topDelegators.length - i + 1) * MILLIGLMR; | ||
| return context.polkadotApi.tx.parachainStaking | ||
| .delegate(alith.address, MIN_GLMR_DELEGATOR + 1n * GLMR, i + 1, 1) | ||
| .signAsync(account, { tip }); | ||
| }) |
There was a problem hiding this comment.
This can be simplified byusing tip-- as be build the tx:
let tip = 1 * GLMR;
await expectOk(
context.createBlock(
[...topDelegators].map((account, i) => {
// add a tip such that the delegation ordering will be preserved, e.g. the first txns sent
// will have the highest tip
return context.polkadotApi.tx.parachainStaking
.delegate(alith.address, MIN_GLMR_DELEGATOR + 1n * GLMR, i + 1, 1)
.signAsync(account, { tip: tip-- });
})
)
);| [...bottomDelegators].map((account, i) => { | ||
| // add a tip such that the delegation ordering will be preserved, e.g. the first txns sent | ||
| // will have the highest tip | ||
| let tip = BigInt(topDelegators.length + (bottomDelegators.length - i) + 1) * MILLIGLMR; |
| // lossy, we have to handle the case where a very low weight maps to zero gas. | ||
| let effective_gas_price = if effective_gas > 0 { | ||
| fee / effective_gas | ||
| let tip_per_gas = if effective_gas > 0 { |
There was a problem hiding this comment.
We should also add an associated rust test for this validation function (if possible)
There was a problem hiding this comment.
I added some tests, but they're not in good shape. The call to Executive::validate_transaction early in the fn fails on an unsigned UncheckedExtrinsic except for an Ethereum one, and signing one is proving difficult.
I'll revisit this again with a fresh mind, but we may also want to consider creating a task to do these tests later.
In any case, I agree that they're a good idea...
…on#1957) * Prioritize Substrate txns by tip-per-effective-gas * s/<spaces>/<tabs>/ * fmt * Remove unused import * Remove useless calls to setBlocksPerRound * wtf * Replace createBlock([]) with one block per extrinsic * A more performant workaround for txn ordering * prettier * Include some basic tests * Fix test * Add txn replacement tests * prettier * Don't assume nonce is 0 * Update tests/tests/test-txpool/test-txpool-fairness.ts Co-authored-by: Nisheeth Barthwal <nbaztec@gmail.com> * Update tests/tests/test-txpool/test-txpool-fairness.ts Co-authored-by: Nisheeth Barthwal <nbaztec@gmail.com> * Update tests/tests/test-txpool/test-txpool-fairness.ts Co-authored-by: Nisheeth Barthwal <nbaztec@gmail.com> * Update tests/tests/test-txpool/test-txpool-fairness.ts Co-authored-by: Nisheeth Barthwal <nbaztec@gmail.com> * Update tests/tests/test-staking/test-staking-locks.ts Co-authored-by: Nisheeth Barthwal <nbaztec@gmail.com> * Update tests/tests/test-staking/test-staking-locks.ts Co-authored-by: Nisheeth Barthwal <nbaztec@gmail.com> * Add some (failing) tests around validate_transaction * Remove failing tests * Remove unused imports * Attempt to break up extremely long import line * Another attempt * Respect my authoritah --------- Co-authored-by: Nisheeth Barthwal <nbaztec@gmail.com>
What does it do?
This modifies our substrate txn priority-override to compute a "tip per effective gas" metric. This should make the prioritization mechanism comparable to what is currently being done in Frontier (which is solely based on the priority fee paid after considering base fee).
Frontier's calculation currently takes a transaction's
maxFeePerGasandmaxPriorityFeePerGasas well as the current block'sbaseFeeinto account, so it basically calculates the effective tip per-gas at any point in time.There are probably some issues related to the txpool prioritization when it comes to txn size which are not addressed by this PR. They are discussed in the comments but I'm considering them out-of-scope and want to keep this PR minimal.