Add getRecentPrioritizationFees RPC endpoint (#27278)

* Plumb priority_fee_cache into rpc

* Add PrioritizationFeeCache api

* Add getRecentPrioritizationFees rpc endpoint

* Use MAX_TX_ACCOUNT_LOCKS to limit input keys

* Remove unused cache apis

* Map fee data by slot, and make rpc account inputs optional

* Add priority_fee_cache to rpc test framework, and add test

* Add endpoint to jsonrpc docs

* Update docs/src/developing/clients/jsonrpc-api.md

* Update docs/src/developing/clients/jsonrpc-api.md
This commit is contained in:
Tyera Eulberg 2022-09-01 16:12:12 -07:00 committed by GitHub
parent dce99f1d0d
commit 9b8bed86f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 484 additions and 200 deletions

View File

@ -823,6 +823,7 @@ impl Validator {
leader_schedule_cache.clone(),
connection_cache.clone(),
max_complete_transaction_status_slot,
prioritization_fee_cache.clone(),
)?;
(

View File

@ -48,6 +48,7 @@ gives a convenient interface for the RPC methods.
- [getMultipleAccounts](jsonrpc-api.md#getmultipleaccounts)
- [getProgramAccounts](jsonrpc-api.md#getprogramaccounts)
- [getRecentPerformanceSamples](jsonrpc-api.md#getrecentperformancesamples)
- [getRecentPrioritizationFees](jsonrpc-api.md#getrecentprioritizationfees)
- [getSignaturesForAddress](jsonrpc-api.md#getsignaturesforaddress)
- [getSignatureStatuses](jsonrpc-api.md#getsignaturestatuses)
- [getSlot](jsonrpc-api.md#getslot)
@ -2096,6 +2097,65 @@ Result:
}
```
### getRecentPrioritizationFees
Returns a list of minimum prioritization fees from recent blocks. Currently, a
node's prioritization-fee cache stores data from up to 150 blocks.
#### Parameters:
- `<array>` - (optional) An array of account address strings. If this parameter is provided, the response will reflect the minimum prioritization fee to land a transaction locking all of the provided accounts as writable.
#### Results:
An array of:
- `RpcPrioritizationFee<object>`
- `slot: <u64>` - Slot in which minimum fee was observed
- `prioritizationFee: <u64>` - Minimum fee paid for a successfully landed transaction
#### Example:
Request:
```bash
// Request
curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d '
{"jsonrpc":"2.0", "id":1, "method":"getRecentPrioritizationFees", "params": [["CxELquR1gPP8wHe33gZ4QxqGB3sZ9RSwsJ2KshVewkFY"]]}
'
```
Result:
```json
{
"jsonrpc": "2.0",
"result": [
{
"slot": 348125,
"prioritizationFee": 0,
},
{
"slot": 348126,
"prioritizationFee": 1000,
},
{
"slot": 348127,
"prioritizationFee": 500,
},
{
"slot": 348128,
"prioritizationFee": 0,
},
{
"slot": 348129,
"prioritizationFee": 1234,
}
],
"id": 1
}
```
### getSignaturesForAddress
Returns signatures for confirmed transactions that include the given address in

View File

@ -544,3 +544,9 @@ pub struct RpcSnapshotSlotInfo {
pub full: Slot,
pub incremental: Option<Slot>,
}
#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq)]
pub struct RpcPrioritizationFee {
pub slot: Slot,
pub prioritization_fee: u64,
}

View File

@ -48,6 +48,7 @@ use {
inline_spl_token::{SPL_TOKEN_ACCOUNT_MINT_OFFSET, SPL_TOKEN_ACCOUNT_OWNER_OFFSET},
inline_spl_token_2022::{self, ACCOUNTTYPE_ACCOUNT},
non_circulating_supply::calculate_non_circulating_supply,
prioritization_fee_cache::PrioritizationFeeCache,
snapshot_config::SnapshotConfig,
snapshot_utils,
},
@ -71,7 +72,7 @@ use {
sysvar::stake_history,
transaction::{
self, AddressLoader, MessageHash, SanitizedTransaction, TransactionError,
VersionedTransaction,
VersionedTransaction, MAX_TX_ACCOUNT_LOCKS,
},
},
solana_send_transaction_service::{
@ -211,6 +212,7 @@ pub struct JsonRpcRequestProcessor {
max_slots: Arc<MaxSlots>,
leader_schedule_cache: Arc<LeaderScheduleCache>,
max_complete_transaction_status_slot: Arc<AtomicU64>,
prioritization_fee_cache: Arc<PrioritizationFeeCache>,
}
impl Metadata for JsonRpcRequestProcessor {}
@ -316,6 +318,7 @@ impl JsonRpcRequestProcessor {
max_slots: Arc<MaxSlots>,
leader_schedule_cache: Arc<LeaderScheduleCache>,
max_complete_transaction_status_slot: Arc<AtomicU64>,
prioritization_fee_cache: Arc<PrioritizationFeeCache>,
) -> (Self, Receiver<TransactionInfo>) {
let (sender, receiver) = unbounded();
(
@ -336,6 +339,7 @@ impl JsonRpcRequestProcessor {
max_slots,
leader_schedule_cache,
max_complete_transaction_status_slot,
prioritization_fee_cache,
},
receiver,
)
@ -400,6 +404,7 @@ impl JsonRpcRequestProcessor {
max_slots: Arc::new(MaxSlots::default()),
leader_schedule_cache: Arc::new(LeaderScheduleCache::new_from_bank(bank)),
max_complete_transaction_status_slot: Arc::new(AtomicU64::default()),
prioritization_fee_cache: Arc::new(PrioritizationFeeCache::default()),
}
}
@ -2177,6 +2182,21 @@ impl JsonRpcRequestProcessor {
solana_stake_program::get_minimum_delegation(&bank.feature_set);
Ok(new_response(&bank, stake_minimum_delegation))
}
fn get_recent_prioritization_fees(
&self,
pubkeys: Vec<Pubkey>,
) -> Result<Vec<RpcPrioritizationFee>> {
Ok(self
.prioritization_fee_cache
.get_prioritization_fees(&pubkeys)
.into_iter()
.map(|(slot, prioritization_fee)| RpcPrioritizationFee {
slot,
prioritization_fee,
})
.collect())
}
}
fn optimize_filters(filters: &mut [RpcFilterType]) {
@ -3416,6 +3436,13 @@ pub mod rpc_full {
meta: Self::Metadata,
config: Option<RpcContextConfig>,
) -> Result<RpcResponse<u64>>;
#[rpc(meta, name = "getRecentPrioritizationFees")]
fn get_recent_prioritization_fees(
&self,
meta: Self::Metadata,
pubkey_strs: Option<Vec<String>>,
) -> Result<Vec<RpcPrioritizationFee>>;
}
pub struct FullImpl;
@ -3992,6 +4019,29 @@ pub mod rpc_full {
debug!("get_stake_minimum_delegation rpc request received");
meta.get_stake_minimum_delegation(config.unwrap_or_default())
}
fn get_recent_prioritization_fees(
&self,
meta: Self::Metadata,
pubkey_strs: Option<Vec<String>>,
) -> Result<Vec<RpcPrioritizationFee>> {
let pubkey_strs = pubkey_strs.unwrap_or_default();
debug!(
"get_recent_prioritization_fees rpc request received: {:?} pubkeys",
pubkey_strs.len()
);
if pubkey_strs.len() > MAX_TX_ACCOUNT_LOCKS {
return Err(Error::invalid_params(format!(
"Too many inputs provided; max {}",
MAX_TX_ACCOUNT_LOCKS
)));
}
let pubkeys = pubkey_strs
.into_iter()
.map(|pubkey_str| verify_pubkey(&pubkey_str))
.collect::<Result<Vec<_>>>()?;
meta.get_recent_prioritization_fees(pubkeys)
}
}
}
@ -4594,6 +4644,7 @@ pub mod tests {
solana_sdk::{
account::{Account, WritableAccount},
clock::MAX_RECENT_BLOCKHASHES,
compute_budget::ComputeBudgetInstruction,
fee_calculator::DEFAULT_BURN_PERCENT,
hash::{hash, Hash},
instruction::InstructionError,
@ -4726,6 +4777,7 @@ pub mod tests {
max_slots.clone(),
Arc::new(LeaderScheduleCache::new_from_bank(&bank)),
max_complete_transaction_status_slot.clone(),
Arc::new(PrioritizationFeeCache::default()),
)
.0;
@ -4938,6 +4990,20 @@ pub mod tests {
bank.store_account(vote_pubkey, &vote_account);
}
fn update_prioritization_fee_cache(&self, transactions: Vec<Transaction>) {
let bank = self.working_bank();
let prioritization_fee_cache = &self.meta.prioritization_fee_cache;
let transactions: Vec<_> = transactions
.into_iter()
.map(|tx| SanitizedTransaction::try_from_legacy_transaction(tx).unwrap())
.collect();
prioritization_fee_cache.update(bank, transactions.iter());
}
fn get_prioritization_fee_cache(&self) -> &PrioritizationFeeCache {
&self.meta.prioritization_fee_cache
}
fn working_bank(&self) -> Arc<Bank> {
self.bank_forks.read().unwrap().working_bank()
}
@ -6300,6 +6366,7 @@ pub mod tests {
Arc::new(MaxSlots::default()),
Arc::new(LeaderScheduleCache::default()),
Arc::new(AtomicU64::default()),
Arc::new(PrioritizationFeeCache::default()),
);
let connection_cache = Arc::new(ConnectionCache::default());
SendTransactionService::new::<NullTpuInfo>(
@ -6569,6 +6636,7 @@ pub mod tests {
Arc::new(MaxSlots::default()),
Arc::new(LeaderScheduleCache::default()),
Arc::new(AtomicU64::default()),
Arc::new(PrioritizationFeeCache::default()),
);
let connection_cache = Arc::new(ConnectionCache::default());
SendTransactionService::new::<NullTpuInfo>(
@ -8196,6 +8264,7 @@ pub mod tests {
Arc::new(MaxSlots::default()),
Arc::new(LeaderScheduleCache::default()),
Arc::new(AtomicU64::default()),
Arc::new(PrioritizationFeeCache::default()),
);
let mut io = MetaIoHandler::default();
@ -8403,4 +8472,167 @@ pub mod tests {
expected_stake_minimum_delegation
);
}
#[test]
fn test_rpc_get_recent_prioritization_fees() {
fn wait_for_cache_blocks(cache: &PrioritizationFeeCache, num_blocks: usize) {
while cache.available_block_count() < num_blocks {
std::thread::sleep(std::time::Duration::from_millis(100));
}
}
fn assert_fee_vec_eq(
expected: &mut Vec<RpcPrioritizationFee>,
actual: &mut Vec<RpcPrioritizationFee>,
) {
expected.sort_by(|a, b| a.slot.partial_cmp(&b.slot).unwrap());
actual.sort_by(|a, b| a.slot.partial_cmp(&b.slot).unwrap());
assert_eq!(expected, actual);
}
let rpc = RpcHandler::start();
assert_eq!(
rpc.get_prioritization_fee_cache().available_block_count(),
0
);
let slot0 = rpc.working_bank().slot();
let account0 = Pubkey::new_unique();
let account1 = Pubkey::new_unique();
let account2 = Pubkey::new_unique();
let price0 = 42;
let transactions = vec![
Transaction::new_unsigned(Message::new(
&[
system_instruction::transfer(&account0, &account1, 1),
ComputeBudgetInstruction::set_compute_unit_price(price0),
],
Some(&account0),
)),
Transaction::new_unsigned(Message::new(
&[system_instruction::transfer(&account0, &account2, 1)],
Some(&account0),
)),
];
rpc.update_prioritization_fee_cache(transactions);
let cache = rpc.get_prioritization_fee_cache();
cache.finalize_priority_fee(slot0);
wait_for_cache_blocks(cache, 1);
let request = create_test_request("getRecentPrioritizationFees", None);
let mut response: Vec<RpcPrioritizationFee> =
parse_success_result(rpc.handle_request_sync(request));
assert_fee_vec_eq(
&mut response,
&mut vec![RpcPrioritizationFee {
slot: slot0,
prioritization_fee: 0,
}],
);
let request = create_test_request(
"getRecentPrioritizationFees",
Some(json!([[account1.to_string()]])),
);
let mut response: Vec<RpcPrioritizationFee> =
parse_success_result(rpc.handle_request_sync(request));
assert_fee_vec_eq(
&mut response,
&mut vec![RpcPrioritizationFee {
slot: slot0,
prioritization_fee: price0,
}],
);
let request = create_test_request(
"getRecentPrioritizationFees",
Some(json!([[account2.to_string()]])),
);
let mut response: Vec<RpcPrioritizationFee> =
parse_success_result(rpc.handle_request_sync(request));
assert_fee_vec_eq(
&mut response,
&mut vec![RpcPrioritizationFee {
slot: slot0,
prioritization_fee: 0,
}],
);
rpc.advance_bank_to_confirmed_slot(1);
let slot1 = rpc.working_bank().slot();
let price1 = 11;
let transactions = vec![
Transaction::new_unsigned(Message::new(
&[
system_instruction::transfer(&account0, &account2, 1),
ComputeBudgetInstruction::set_compute_unit_price(price1),
],
Some(&account0),
)),
Transaction::new_unsigned(Message::new(
&[system_instruction::transfer(&account0, &account1, 1)],
Some(&account0),
)),
];
rpc.update_prioritization_fee_cache(transactions);
let cache = rpc.get_prioritization_fee_cache();
cache.finalize_priority_fee(slot1);
wait_for_cache_blocks(cache, 2);
let request = create_test_request("getRecentPrioritizationFees", None);
let mut response: Vec<RpcPrioritizationFee> =
parse_success_result(rpc.handle_request_sync(request));
assert_fee_vec_eq(
&mut response,
&mut vec![
RpcPrioritizationFee {
slot: slot0,
prioritization_fee: 0,
},
RpcPrioritizationFee {
slot: slot1,
prioritization_fee: 0,
},
],
);
let request = create_test_request(
"getRecentPrioritizationFees",
Some(json!([[account1.to_string()]])),
);
let mut response: Vec<RpcPrioritizationFee> =
parse_success_result(rpc.handle_request_sync(request));
assert_fee_vec_eq(
&mut response,
&mut vec![
RpcPrioritizationFee {
slot: slot0,
prioritization_fee: price0,
},
RpcPrioritizationFee {
slot: slot1,
prioritization_fee: 0,
},
],
);
let request = create_test_request(
"getRecentPrioritizationFees",
Some(json!([[account2.to_string()]])),
);
let mut response: Vec<RpcPrioritizationFee> =
parse_success_result(rpc.handle_request_sync(request));
assert_fee_vec_eq(
&mut response,
&mut vec![
RpcPrioritizationFee {
slot: slot0,
prioritization_fee: 0,
},
RpcPrioritizationFee {
slot: slot1,
prioritization_fee: price1,
},
],
);
}
}

View File

@ -30,6 +30,7 @@ use {
solana_poh::poh_recorder::PohRecorder,
solana_runtime::{
bank_forks::BankForks, commitment::BlockCommitmentCache,
prioritization_fee_cache::PrioritizationFeeCache,
snapshot_archive_info::SnapshotArchiveInfoGetter, snapshot_config::SnapshotConfig,
snapshot_utils,
},
@ -356,6 +357,7 @@ impl JsonRpcService {
leader_schedule_cache: Arc<LeaderScheduleCache>,
connection_cache: Arc<ConnectionCache>,
current_transaction_status_slot: Arc<AtomicU64>,
prioritization_fee_cache: Arc<PrioritizationFeeCache>,
) -> Result<Self, String> {
info!("rpc bound to {:?}", rpc_addr);
info!("rpc configuration: {:?}", config);
@ -464,6 +466,7 @@ impl JsonRpcService {
max_slots,
leader_schedule_cache,
current_transaction_status_slot,
prioritization_fee_cache,
);
let leader_info =
@ -646,6 +649,7 @@ mod tests {
Arc::new(LeaderScheduleCache::default()),
connection_cache,
Arc::new(AtomicU64::default()),
Arc::new(PrioritizationFeeCache::default()),
)
.expect("assume successful JsonRpcService start");
let thread = rpc_service.thread_hdl.thread();

View File

@ -11,6 +11,7 @@ use {
clock::Slot, pubkey::Pubkey, saturating_add_assign, transaction::SanitizedTransaction,
},
std::{
collections::HashMap,
sync::{
atomic::{AtomicU64, Ordering},
Arc, Mutex, RwLock,
@ -347,37 +348,26 @@ impl PrioritizationFeeCache {
.count()
}
/// Query block minimum fees from finalized blocks in cache,
/// Returns a vector of fee; call site can use it to produce
/// average, or top 5% etc.
pub fn get_prioritization_fees(&self) -> Vec<u64> {
pub fn get_prioritization_fees(&self, account_keys: &[Pubkey]) -> HashMap<Slot, u64> {
self.cache
.read()
.unwrap()
.iter()
.filter_map(|(_slot, prioritization_fee)| {
.filter_map(|(slot, prioritization_fee)| {
let prioritization_fee_read = prioritization_fee.lock().unwrap();
prioritization_fee_read
.is_finalized()
.then(|| prioritization_fee_read.get_min_transaction_fee())
})
.flatten()
.collect()
}
/// Query given account minimum fees from finalized blocks in cache,
/// Returns a vector of fee; call site can use it to produce
/// average, or top 5% etc.
pub fn get_account_prioritization_fees(&self, account_key: &Pubkey) -> Vec<u64> {
self.cache
.read()
.unwrap()
.iter()
.filter_map(|(_slot, prioritization_fee)| {
let prioritization_fee_read = prioritization_fee.lock().unwrap();
prioritization_fee_read
.is_finalized()
.then(|| prioritization_fee_read.get_writable_account_fee(account_key))
prioritization_fee_read.is_finalized().then(|| {
let mut fee = prioritization_fee_read
.get_min_transaction_fee()
.unwrap_or_default();
for account_key in account_keys {
if let Some(account_fee) =
prioritization_fee_read.get_writable_account_fee(account_key)
{
fee = std::cmp::max(fee, account_fee);
}
}
Some((*slot, fee))
})
})
.flatten()
.collect()
@ -546,10 +536,8 @@ mod tests {
assert_eq!(2, prioritization_fee_cache.available_block_count());
}
fn assert_vec_eq(expected: &mut Vec<u64>, actual: &mut Vec<u64>) {
expected.sort_unstable();
actual.sort_unstable();
assert_eq!(expected, actual);
fn hashmap_of(vec: Vec<(Slot, u64)>) -> HashMap<Slot, u64> {
vec.into_iter().collect()
}
#[test]
@ -572,239 +560,232 @@ mod tests {
// Assert no minimum fee from empty cache
assert!(prioritization_fee_cache
.get_prioritization_fees()
.is_empty());
// Assert after add one transaction for slot 1
{
let txs = vec![build_sanitized_transaction_for_test(
5,
&write_account_a,
&write_account_b,
)];
sync_update(&mut prioritization_fee_cache, bank1.clone(), txs.iter());
assert_eq!(
5,
PrioritizationFeeCache::get_prioritization_fee(
prioritization_fee_cache.cache.clone(),
&bank1.slot()
)
.lock()
.unwrap()
.get_min_transaction_fee()
.unwrap()
);
// before block is marked as completed
assert!(prioritization_fee_cache
.get_prioritization_fees()
.is_empty());
// after block is completed
sync_finalize_priority_fee_for_test(&mut prioritization_fee_cache, bank1.slot());
assert_eq!(vec![5], prioritization_fee_cache.get_prioritization_fees());
}
// Assert after add one transaction for slot 2
{
let txs = vec![build_sanitized_transaction_for_test(
9,
&write_account_b,
&write_account_c,
)];
sync_update(&mut prioritization_fee_cache, bank2.clone(), txs.iter());
assert_eq!(
9,
PrioritizationFeeCache::get_prioritization_fee(
prioritization_fee_cache.cache.clone(),
&bank2.slot()
)
.lock()
.unwrap()
.get_min_transaction_fee()
.unwrap()
);
// before block is marked as completed
assert_eq!(vec![5], prioritization_fee_cache.get_prioritization_fees());
// after block is completed
sync_finalize_priority_fee_for_test(&mut prioritization_fee_cache, bank2.slot());
assert_vec_eq(
&mut vec![5, 9],
&mut prioritization_fee_cache.get_prioritization_fees(),
);
}
// Assert after add one transaction for slot 3
{
let txs = vec![build_sanitized_transaction_for_test(
2,
&write_account_a,
&write_account_c,
)];
sync_update(&mut prioritization_fee_cache, bank3.clone(), txs.iter());
assert_eq!(
2,
PrioritizationFeeCache::get_prioritization_fee(
prioritization_fee_cache.cache.clone(),
&bank3.slot()
)
.lock()
.unwrap()
.get_min_transaction_fee()
.unwrap()
);
// before block is marked as completed
assert_vec_eq(
&mut vec![5, 9],
&mut prioritization_fee_cache.get_prioritization_fees(),
);
// after block is completed
sync_finalize_priority_fee_for_test(&mut prioritization_fee_cache, bank3.slot());
assert_vec_eq(
&mut vec![5, 9, 2],
&mut prioritization_fee_cache.get_prioritization_fees(),
);
}
}
#[test]
fn test_get_account_prioritization_fees() {
solana_logger::setup();
let write_account_a = Pubkey::new_unique();
let write_account_b = Pubkey::new_unique();
let write_account_c = Pubkey::new_unique();
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
let bank0 = Bank::new_for_benches(&genesis_config);
let bank_forks = BankForks::new(bank0);
let bank = bank_forks.working_bank();
let collector = solana_sdk::pubkey::new_rand();
let bank1 = Arc::new(Bank::new_from_parent(&bank, &collector, 1));
let bank2 = Arc::new(Bank::new_from_parent(&bank, &collector, 2));
let bank3 = Arc::new(Bank::new_from_parent(&bank, &collector, 3));
let mut prioritization_fee_cache = PrioritizationFeeCache::default();
// Assert no minimum fee from empty cache
assert!(prioritization_fee_cache
.get_account_prioritization_fees(&write_account_a)
.get_prioritization_fees(&[])
.is_empty());
assert!(prioritization_fee_cache
.get_account_prioritization_fees(&write_account_b)
.get_prioritization_fees(&[write_account_a])
.is_empty());
assert!(prioritization_fee_cache
.get_account_prioritization_fees(&write_account_c)
.get_prioritization_fees(&[write_account_b])
.is_empty());
assert!(prioritization_fee_cache
.get_prioritization_fees(&[write_account_c])
.is_empty());
assert!(prioritization_fee_cache
.get_prioritization_fees(&[write_account_a, write_account_b])
.is_empty());
assert!(prioritization_fee_cache
.get_prioritization_fees(&[write_account_a, write_account_b, write_account_c])
.is_empty());
// Assert after add one transaction for slot 1
{
let txs = vec![
build_sanitized_transaction_for_test(5, &write_account_a, &write_account_b),
build_sanitized_transaction_for_test(2, &write_account_a, &write_account_b),
build_sanitized_transaction_for_test(
0,
1,
&Pubkey::new_unique(),
&Pubkey::new_unique(),
),
];
prioritization_fee_cache.update(bank1.clone(), txs.iter());
sync_update(&mut prioritization_fee_cache, bank1, txs.iter());
// before block is marked as completed
assert!(prioritization_fee_cache
.get_account_prioritization_fees(&write_account_a)
.get_prioritization_fees(&[])
.is_empty());
assert!(prioritization_fee_cache
.get_account_prioritization_fees(&write_account_b)
.get_prioritization_fees(&[write_account_a])
.is_empty());
assert!(prioritization_fee_cache
.get_account_prioritization_fees(&write_account_c)
.get_prioritization_fees(&[write_account_b])
.is_empty());
assert!(prioritization_fee_cache
.get_prioritization_fees(&[write_account_c])
.is_empty());
assert!(prioritization_fee_cache
.get_prioritization_fees(&[write_account_a, write_account_b])
.is_empty());
assert!(prioritization_fee_cache
.get_prioritization_fees(&[write_account_a, write_account_b, write_account_c])
.is_empty());
// after block is completed
sync_finalize_priority_fee_for_test(&mut prioritization_fee_cache, bank1.slot());
sync_finalize_priority_fee_for_test(&mut prioritization_fee_cache, 1);
assert_eq!(
vec![5],
prioritization_fee_cache.get_account_prioritization_fees(&write_account_a)
hashmap_of(vec![(1, 1)]),
prioritization_fee_cache.get_prioritization_fees(&[])
);
assert_eq!(
vec![5],
prioritization_fee_cache.get_account_prioritization_fees(&write_account_b)
hashmap_of(vec![(1, 2)]),
prioritization_fee_cache.get_prioritization_fees(&[write_account_a])
);
assert_eq!(
hashmap_of(vec![(1, 2)]),
prioritization_fee_cache.get_prioritization_fees(&[write_account_b])
);
assert_eq!(
hashmap_of(vec![(1, 1)]),
prioritization_fee_cache.get_prioritization_fees(&[write_account_c])
);
assert_eq!(
hashmap_of(vec![(1, 2)]),
prioritization_fee_cache
.get_prioritization_fees(&[write_account_a, write_account_b])
);
assert_eq!(
hashmap_of(vec![(1, 2)]),
prioritization_fee_cache.get_prioritization_fees(&[
write_account_a,
write_account_b,
write_account_c
])
);
assert!(prioritization_fee_cache
.get_account_prioritization_fees(&write_account_c)
.is_empty());
}
// Assert after add one transaction for slot 2
{
let txs = vec![
build_sanitized_transaction_for_test(9, &write_account_b, &write_account_c),
build_sanitized_transaction_for_test(4, &write_account_b, &write_account_c),
build_sanitized_transaction_for_test(
0,
3,
&Pubkey::new_unique(),
&Pubkey::new_unique(),
),
];
prioritization_fee_cache.update(bank2.clone(), txs.iter());
sync_update(&mut prioritization_fee_cache, bank2, txs.iter());
// before block is marked as completed
assert_eq!(
vec![5],
prioritization_fee_cache.get_account_prioritization_fees(&write_account_a)
hashmap_of(vec![(1, 1)]),
prioritization_fee_cache.get_prioritization_fees(&[])
);
assert_eq!(
vec![5],
prioritization_fee_cache.get_account_prioritization_fees(&write_account_b)
hashmap_of(vec![(1, 2)]),
prioritization_fee_cache.get_prioritization_fees(&[write_account_a])
);
assert_eq!(
hashmap_of(vec![(1, 2)]),
prioritization_fee_cache.get_prioritization_fees(&[write_account_b])
);
assert_eq!(
hashmap_of(vec![(1, 1)]),
prioritization_fee_cache.get_prioritization_fees(&[write_account_c])
);
assert_eq!(
hashmap_of(vec![(1, 2)]),
prioritization_fee_cache
.get_prioritization_fees(&[write_account_a, write_account_b])
);
assert_eq!(
hashmap_of(vec![(1, 2)]),
prioritization_fee_cache.get_prioritization_fees(&[
write_account_a,
write_account_b,
write_account_c
])
);
assert!(prioritization_fee_cache
.get_account_prioritization_fees(&write_account_c)
.is_empty());
// after block is completed
sync_finalize_priority_fee_for_test(&mut prioritization_fee_cache, bank2.slot());
sync_finalize_priority_fee_for_test(&mut prioritization_fee_cache, 2);
assert_eq!(
vec![5],
prioritization_fee_cache.get_account_prioritization_fees(&write_account_a)
);
assert_vec_eq(
&mut vec![5, 9],
&mut prioritization_fee_cache.get_account_prioritization_fees(&write_account_b),
hashmap_of(vec![(2, 3), (1, 1)]),
prioritization_fee_cache.get_prioritization_fees(&[]),
);
assert_eq!(
vec![9],
prioritization_fee_cache.get_account_prioritization_fees(&write_account_c)
hashmap_of(vec![(2, 3), (1, 2)]),
prioritization_fee_cache.get_prioritization_fees(&[write_account_a]),
);
assert_eq!(
hashmap_of(vec![(2, 4), (1, 2)]),
prioritization_fee_cache.get_prioritization_fees(&[write_account_b]),
);
assert_eq!(
hashmap_of(vec![(2, 4), (1, 1)]),
prioritization_fee_cache.get_prioritization_fees(&[write_account_c]),
);
assert_eq!(
hashmap_of(vec![(2, 4), (1, 2)]),
prioritization_fee_cache
.get_prioritization_fees(&[write_account_a, write_account_b]),
);
assert_eq!(
hashmap_of(vec![(2, 4), (1, 2)]),
prioritization_fee_cache.get_prioritization_fees(&[
write_account_a,
write_account_b,
write_account_c,
]),
);
}
// Assert after add one transaction for slot 3
{
let txs = vec![
build_sanitized_transaction_for_test(2, &write_account_a, &write_account_c),
build_sanitized_transaction_for_test(6, &write_account_a, &write_account_c),
build_sanitized_transaction_for_test(
0,
5,
&Pubkey::new_unique(),
&Pubkey::new_unique(),
),
];
prioritization_fee_cache.update(bank3.clone(), txs.iter());
sync_update(&mut prioritization_fee_cache, bank3, txs.iter());
// before block is marked as completed
assert_eq!(
vec![5],
prioritization_fee_cache.get_account_prioritization_fees(&write_account_a)
);
assert_vec_eq(
&mut vec![5, 9],
&mut prioritization_fee_cache.get_account_prioritization_fees(&write_account_b),
hashmap_of(vec![(2, 3), (1, 1)]),
prioritization_fee_cache.get_prioritization_fees(&[]),
);
assert_eq!(
vec![9],
prioritization_fee_cache.get_account_prioritization_fees(&write_account_c)
hashmap_of(vec![(2, 3), (1, 2)]),
prioritization_fee_cache.get_prioritization_fees(&[write_account_a]),
);
assert_eq!(
hashmap_of(vec![(2, 4), (1, 2)]),
prioritization_fee_cache.get_prioritization_fees(&[write_account_b]),
);
assert_eq!(
hashmap_of(vec![(2, 4), (1, 1)]),
prioritization_fee_cache.get_prioritization_fees(&[write_account_c]),
);
assert_eq!(
hashmap_of(vec![(2, 4), (1, 2)]),
prioritization_fee_cache
.get_prioritization_fees(&[write_account_a, write_account_b]),
);
assert_eq!(
hashmap_of(vec![(2, 4), (1, 2)]),
prioritization_fee_cache.get_prioritization_fees(&[
write_account_a,
write_account_b,
write_account_c,
]),
);
// after block is completed
sync_finalize_priority_fee_for_test(&mut prioritization_fee_cache, bank3.slot());
assert_vec_eq(
&mut vec![5, 2],
&mut prioritization_fee_cache.get_account_prioritization_fees(&write_account_a),
sync_finalize_priority_fee_for_test(&mut prioritization_fee_cache, 3);
assert_eq!(
hashmap_of(vec![(3, 5), (2, 3), (1, 1)]),
prioritization_fee_cache.get_prioritization_fees(&[]),
);
assert_vec_eq(
&mut vec![5, 9],
&mut prioritization_fee_cache.get_account_prioritization_fees(&write_account_b),
assert_eq!(
hashmap_of(vec![(3, 6), (2, 3), (1, 2)]),
prioritization_fee_cache.get_prioritization_fees(&[write_account_a]),
);
assert_vec_eq(
&mut vec![9, 2],
&mut prioritization_fee_cache.get_account_prioritization_fees(&write_account_c),
assert_eq!(
hashmap_of(vec![(3, 5), (2, 4), (1, 2)]),
prioritization_fee_cache.get_prioritization_fees(&[write_account_b]),
);
assert_eq!(
hashmap_of(vec![(3, 6), (2, 4), (1, 1)]),
prioritization_fee_cache.get_prioritization_fees(&[write_account_c]),
);
assert_eq!(
hashmap_of(vec![(3, 6), (2, 4), (1, 2)]),
prioritization_fee_cache
.get_prioritization_fees(&[write_account_a, write_account_b]),
);
assert_eq!(
hashmap_of(vec![(3, 6), (2, 4), (1, 2)]),
prioritization_fee_cache.get_prioritization_fees(&[
write_account_a,
write_account_b,
write_account_c,
]),
);
}
}