Skip to content

Commit ab66df9

Browse files
committed
test: batch propose from peer over spend limit
1 parent bdd0329 commit ab66df9

File tree

1 file changed

+114
-41
lines changed

1 file changed

+114
-41
lines changed

Diff for: node/bft/src/primary.rs

+114-41
Original file line numberDiff line numberDiff line change
@@ -2192,6 +2192,56 @@ mod tests {
21922192
);
21932193
}
21942194

2195+
#[tokio::test]
2196+
async fn test_propose_batch_over_spend_limit() {
2197+
let mut rng = TestRng::default();
2198+
// Create two primaries to test spend limit activation on V4.
2199+
let (accounts, committee) = sample_committee(&mut rng);
2200+
let primary_v3 = primary_with_committee(
2201+
0,
2202+
&accounts,
2203+
committee.clone(),
2204+
CurrentNetwork::CONSENSUS_HEIGHT(ConsensusVersion::V3).unwrap(),
2205+
);
2206+
let primary_v4 = primary_with_committee(
2207+
1,
2208+
&accounts,
2209+
committee,
2210+
CurrentNetwork::CONSENSUS_HEIGHT(ConsensusVersion::V4).unwrap(),
2211+
);
2212+
2213+
// Check there is no batch currently proposed.
2214+
assert!(primary_v3.proposed_batch.read().is_none());
2215+
assert!(primary_v4.proposed_batch.read().is_none());
2216+
// Check the workers are empty.
2217+
primary_v3.workers().iter().for_each(|worker| assert!(worker.transmissions().is_empty()));
2218+
primary_v4.workers().iter().for_each(|worker| assert!(worker.transmissions().is_empty()));
2219+
2220+
// Generate a solution and a transaction.
2221+
let (solution_id, solution) = sample_unconfirmed_solution(&mut rng);
2222+
primary_v3.workers[0].process_unconfirmed_solution(solution_id, solution.clone()).await.unwrap();
2223+
primary_v4.workers[0].process_unconfirmed_solution(solution_id, solution).await.unwrap();
2224+
2225+
// At 10 credits per execution, 10 transactions should max out a batch, add a few more.
2226+
for _i in 0..15 {
2227+
let (transaction_id, transaction) = sample_unconfirmed_transaction(&mut rng);
2228+
// Store it on one of the workers.
2229+
primary_v3.workers[0].process_unconfirmed_transaction(transaction_id, transaction.clone()).await.unwrap();
2230+
primary_v4.workers[0].process_unconfirmed_transaction(transaction_id, transaction).await.unwrap();
2231+
}
2232+
2233+
// Try to propose a batch again. This time, it should succeed.
2234+
assert!(primary_v3.propose_batch().await.is_ok());
2235+
assert!(primary_v4.propose_batch().await.is_ok());
2236+
// Expect 10/15 transactions to be included in the proposal, along with
2237+
// the solution, for v3 consensus all 15 should be included.
2238+
assert_eq!(primary_v3.proposed_batch.read().as_ref().unwrap().transmissions().len(), 16);
2239+
assert_eq!(primary_v4.proposed_batch.read().as_ref().unwrap().transmissions().len(), 11);
2240+
// Check the transactions were correctly drained from the workers (15 + 1 - 11).
2241+
assert_eq!(primary_v3.workers().iter().map(|worker| worker.transmissions().len()).sum::<usize>(), 0);
2242+
assert_eq!(primary_v4.workers().iter().map(|worker| worker.transmissions().len()).sum::<usize>(), 5);
2243+
}
2244+
21952245
#[tokio::test]
21962246
async fn test_batch_propose_from_peer() {
21972247
let mut rng = TestRng::default();
@@ -2464,6 +2514,70 @@ mod tests {
24642514
);
24652515
}
24662516

2517+
#[tokio::test]
2518+
async fn test_batch_propose_from_peer_over_spend_limit() {
2519+
let mut rng = TestRng::default();
2520+
2521+
// Create two primaries to test spend limit activation on V4.
2522+
let (accounts, committee) = sample_committee(&mut rng);
2523+
let primary_v3 = primary_with_committee(
2524+
0,
2525+
&accounts,
2526+
committee.clone(),
2527+
CurrentNetwork::CONSENSUS_HEIGHT(ConsensusVersion::V3).unwrap(),
2528+
);
2529+
let primary_v4 = primary_with_committee(
2530+
1,
2531+
&accounts,
2532+
committee.clone(),
2533+
CurrentNetwork::CONSENSUS_HEIGHT(ConsensusVersion::V4).unwrap(),
2534+
);
2535+
2536+
// Create a valid proposal with an author that isn't the primary.
2537+
let round = 1;
2538+
let peer_account = &accounts[1];
2539+
let peer_ip = peer_account.0;
2540+
let timestamp = now() + MIN_BATCH_DELAY_IN_SECS as i64;
2541+
let proposal = create_test_proposal(
2542+
&peer_account.1,
2543+
committee,
2544+
round,
2545+
Default::default(),
2546+
timestamp,
2547+
// At 10 credits per execution, this should bring the batch above
2548+
// the spend limit.
2549+
11,
2550+
&mut rng,
2551+
);
2552+
2553+
// Make sure the primary is aware of the transmissions in the proposal.
2554+
for (transmission_id, transmission) in proposal.transmissions() {
2555+
primary_v3.workers[0].process_transmission_from_peer(peer_ip, *transmission_id, transmission.clone());
2556+
primary_v4.workers[0].process_transmission_from_peer(peer_ip, *transmission_id, transmission.clone());
2557+
}
2558+
2559+
// The author must be known to resolver to pass propose checks.
2560+
primary_v3.gateway.resolver().insert_peer(peer_ip, peer_ip, peer_account.1.address());
2561+
primary_v4.gateway.resolver().insert_peer(peer_ip, peer_ip, peer_account.1.address());
2562+
// The primary must be considered synced.
2563+
primary_v3.sync.block_sync().try_block_sync(&primary_v3.gateway.clone()).await;
2564+
primary_v4.sync.block_sync().try_block_sync(&primary_v4.gateway.clone()).await;
2565+
2566+
// Check the spend limit is enforced from V4 onwards.
2567+
assert!(
2568+
primary_v3
2569+
.process_batch_propose_from_peer(peer_ip, (*proposal.batch_header()).clone().into())
2570+
.await
2571+
.is_ok()
2572+
);
2573+
assert!(
2574+
primary_v4
2575+
.process_batch_propose_from_peer(peer_ip, (*proposal.batch_header()).clone().into())
2576+
.await
2577+
.is_err()
2578+
);
2579+
}
2580+
24672581
#[tokio::test]
24682582
async fn test_propose_batch_with_storage_round_behind_proposal_lock() {
24692583
let round = 3;
@@ -2527,47 +2641,6 @@ mod tests {
25272641
assert!(primary.proposed_batch.read().as_ref().unwrap().round() > primary.current_round());
25282642
}
25292643

2530-
#[tokio::test]
2531-
async fn test_propose_batch_over_spend_limit() {
2532-
let mut rng = TestRng::default();
2533-
// Instantiate two primaries to test spend limit activation on V4.
2534-
let (primary_v3, _) =
2535-
primary_without_handlers(&mut rng, CurrentNetwork::CONSENSUS_HEIGHT(ConsensusVersion::V3).unwrap()).await;
2536-
let (primary_v4, _) =
2537-
primary_without_handlers(&mut rng, CurrentNetwork::CONSENSUS_HEIGHT(ConsensusVersion::V4).unwrap()).await;
2538-
2539-
// Check there is no batch currently proposed.
2540-
assert!(primary_v3.proposed_batch.read().is_none());
2541-
assert!(primary_v4.proposed_batch.read().is_none());
2542-
// Check the workers are empty.
2543-
primary_v3.workers().iter().for_each(|worker| assert!(worker.transmissions().is_empty()));
2544-
primary_v4.workers().iter().for_each(|worker| assert!(worker.transmissions().is_empty()));
2545-
2546-
// Generate a solution and a transaction.
2547-
let (solution_id, solution) = sample_unconfirmed_solution(&mut rng);
2548-
primary_v3.workers[0].process_unconfirmed_solution(solution_id, solution.clone()).await.unwrap();
2549-
primary_v4.workers[0].process_unconfirmed_solution(solution_id, solution).await.unwrap();
2550-
2551-
// At 10 credits per execution, 10 transactions should max out a batch, add a few more.
2552-
for _i in 0..15 {
2553-
let (transaction_id, transaction) = sample_unconfirmed_transaction(&mut rng);
2554-
// Store it on one of the workers.
2555-
primary_v3.workers[0].process_unconfirmed_transaction(transaction_id, transaction.clone()).await.unwrap();
2556-
primary_v4.workers[0].process_unconfirmed_transaction(transaction_id, transaction).await.unwrap();
2557-
}
2558-
2559-
// Try to propose a batch again. This time, it should succeed.
2560-
assert!(primary_v3.propose_batch().await.is_ok());
2561-
assert!(primary_v4.propose_batch().await.is_ok());
2562-
// Expect 10/15 transactions to be included in the proposal, along with
2563-
// the solution, for v3 consensus all 15 should be included.
2564-
assert_eq!(primary_v3.proposed_batch.read().as_ref().unwrap().transmissions().len(), 16);
2565-
assert_eq!(primary_v4.proposed_batch.read().as_ref().unwrap().transmissions().len(), 11);
2566-
// Check the transactions were correctly drained from the workers (15 + 1 - 11).
2567-
assert_eq!(primary_v3.workers().iter().map(|worker| worker.transmissions().len()).sum::<usize>(), 0);
2568-
assert_eq!(primary_v4.workers().iter().map(|worker| worker.transmissions().len()).sum::<usize>(), 5);
2569-
}
2570-
25712644
#[tokio::test(flavor = "multi_thread")]
25722645
async fn test_batch_signature_from_peer() {
25732646
let mut rng = TestRng::default();

0 commit comments

Comments
 (0)