getVoteAccounts: Limit the length of the `epoch_credits` array
This commit is contained in:
parent
03f7b251b8
commit
34addee882
|
@ -96,6 +96,10 @@ use tokio::runtime::Runtime;
|
||||||
pub const MAX_REQUEST_PAYLOAD_SIZE: usize = 50 * (1 << 10); // 50kB
|
pub const MAX_REQUEST_PAYLOAD_SIZE: usize = 50 * (1 << 10); // 50kB
|
||||||
pub const PERFORMANCE_SAMPLES_LIMIT: usize = 720;
|
pub const PERFORMANCE_SAMPLES_LIMIT: usize = 720;
|
||||||
|
|
||||||
|
// Limit the length of the `epoch_credits` array for each validator in a `get_vote_accounts`
|
||||||
|
// response
|
||||||
|
const MAX_RPC_EPOCH_CREDITS_HISTORY: usize = 5;
|
||||||
|
|
||||||
fn new_response<T>(bank: &Bank, value: T) -> RpcResponse<T> {
|
fn new_response<T>(bank: &Bank, value: T) -> RpcResponse<T> {
|
||||||
let context = RpcResponseContext { slot: bank.slot() };
|
let context = RpcResponseContext { slot: bank.slot() };
|
||||||
Response { context, value }
|
Response { context, value }
|
||||||
|
@ -719,13 +723,25 @@ impl JsonRpcRequestProcessor {
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let epoch_credits = vote_state.epoch_credits();
|
||||||
|
let epoch_credits = if epoch_credits.len() > MAX_RPC_EPOCH_CREDITS_HISTORY {
|
||||||
|
epoch_credits
|
||||||
|
.iter()
|
||||||
|
.skip(epoch_credits.len() - MAX_RPC_EPOCH_CREDITS_HISTORY)
|
||||||
|
.cloned()
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
epoch_credits.clone()
|
||||||
|
};
|
||||||
|
|
||||||
RpcVoteAccountInfo {
|
RpcVoteAccountInfo {
|
||||||
vote_pubkey: (pubkey).to_string(),
|
vote_pubkey: (pubkey).to_string(),
|
||||||
node_pubkey: vote_state.node_pubkey.to_string(),
|
node_pubkey: vote_state.node_pubkey.to_string(),
|
||||||
activated_stake: *activated_stake,
|
activated_stake: *activated_stake,
|
||||||
commission: vote_state.commission,
|
commission: vote_state.commission,
|
||||||
root_slot: vote_state.root_slot.unwrap_or(0),
|
root_slot: vote_state.root_slot.unwrap_or(0),
|
||||||
epoch_credits: vote_state.epoch_credits().clone(),
|
epoch_credits,
|
||||||
epoch_vote_account: epoch_vote_accounts.contains_key(pubkey),
|
epoch_vote_account: epoch_vote_accounts.contains_key(pubkey),
|
||||||
last_vote,
|
last_vote,
|
||||||
}
|
}
|
||||||
|
@ -5908,8 +5924,7 @@ pub mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advance bank to the next epoch
|
let mut advance_bank = || {
|
||||||
for _ in 0..TEST_SLOTS_PER_EPOCH {
|
|
||||||
bank.freeze();
|
bank.freeze();
|
||||||
|
|
||||||
// Votes
|
// Votes
|
||||||
|
@ -5950,6 +5965,11 @@ pub mod tests {
|
||||||
|
|
||||||
bank.process_transaction(&transaction)
|
bank.process_transaction(&transaction)
|
||||||
.expect("process transaction");
|
.expect("process transaction");
|
||||||
|
};
|
||||||
|
|
||||||
|
// Advance bank to the next epoch
|
||||||
|
for _ in 0..TEST_SLOTS_PER_EPOCH {
|
||||||
|
advance_bank();
|
||||||
}
|
}
|
||||||
|
|
||||||
let req = format!(
|
let req = format!(
|
||||||
|
@ -5969,7 +5989,6 @@ pub mod tests {
|
||||||
|
|
||||||
// Both accounts should be active and have voting history.
|
// Both accounts should be active and have voting history.
|
||||||
assert_eq!(vote_account_status.current.len(), 2);
|
assert_eq!(vote_account_status.current.len(), 2);
|
||||||
//let leader_info = &vote_account_status.current[0];
|
|
||||||
let leader_info = vote_account_status
|
let leader_info = vote_account_status
|
||||||
.current
|
.current
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -5986,6 +6005,30 @@ pub mod tests {
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Overflow the epoch credits history and ensure only `MAX_RPC_EPOCH_CREDITS_HISTORY`
|
||||||
|
// results are returned
|
||||||
|
for _ in 0..(TEST_SLOTS_PER_EPOCH * (MAX_RPC_EPOCH_CREDITS_HISTORY) as u64) {
|
||||||
|
advance_bank();
|
||||||
|
}
|
||||||
|
|
||||||
|
let req = format!(
|
||||||
|
r#"{{"jsonrpc":"2.0","id":1,"method":"getVoteAccounts","params":{}}}"#,
|
||||||
|
json!([CommitmentConfig::processed()])
|
||||||
|
);
|
||||||
|
|
||||||
|
let res = io.handle_request_sync(&req, meta.clone());
|
||||||
|
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||||
|
.expect("actual response deserialization");
|
||||||
|
|
||||||
|
let vote_account_status: RpcVoteAccountStatus =
|
||||||
|
serde_json::from_value(result["result"].clone()).unwrap();
|
||||||
|
|
||||||
|
assert!(vote_account_status.delinquent.is_empty());
|
||||||
|
assert!(!vote_account_status
|
||||||
|
.current
|
||||||
|
.iter()
|
||||||
|
.any(|x| x.epoch_credits.len() != MAX_RPC_EPOCH_CREDITS_HISTORY));
|
||||||
|
|
||||||
// Advance bank with no voting
|
// Advance bank with no voting
|
||||||
bank.freeze();
|
bank.freeze();
|
||||||
bank_forks.write().unwrap().insert(Bank::new_from_parent(
|
bank_forks.write().unwrap().insert(Bank::new_from_parent(
|
||||||
|
|
Loading…
Reference in New Issue