@@ -68,12 +68,31 @@ pub struct TestChainBuilder<N: Network> {
6868}
6969
7070/// Additional options you can pass to the builder when generating a set of blocks.
71- #[ derive( Clone , Default ) ]
72- pub struct GenerateBlocksOptions {
71+ #[ derive( Clone ) ]
72+ pub struct GenerateBlocksOptions < N : Network > {
7373 /// Do not include votes to the previous leader certificate
7474 pub skip_votes : bool ,
7575 /// Do not generate certificates for the specific node indices (to simulate a partition).
7676 pub skip_nodes : Vec < usize > ,
77+ /// A flag indicating that a number of initial "placeholder blocks" should be baked
78+ /// wthout transactions in order to skip to the latest version of consensus.
79+ pub skip_to_current_version : bool ,
80+ /// The number of validators.
81+ pub num_validators : usize ,
82+ /// Preloaded transactions to populate the blocks with.
83+ pub transactions : Vec < Transaction < N > > ,
84+ }
85+
86+ impl < N : Network > Default for GenerateBlocksOptions < N > {
87+ fn default ( ) -> Self {
88+ Self {
89+ skip_votes : false ,
90+ skip_nodes : Default :: default ( ) ,
91+ skip_to_current_version : false ,
92+ num_validators : 0 ,
93+ transactions : Default :: default ( ) ,
94+ }
95+ }
7796}
7897
7998/// Additional options you can pass to the builder when generating a single block.
@@ -178,7 +197,6 @@ impl<N: Network> TestChainBuilder<N> {
178197 Ok ( Self {
179198 private_keys,
180199 ledger,
181-
182200 genesis_block,
183201 last_batch_round : Default :: default ( ) ,
184202 last_committed_batch_round : Default :: default ( ) ,
@@ -190,7 +208,9 @@ impl<N: Network> TestChainBuilder<N> {
190208
191209 /// Create multiple blocks, with fully-connected DAGs.
192210 pub fn generate_blocks ( & mut self , num_blocks : usize , rng : & mut TestRng ) -> Result < Vec < Block < N > > > {
193- self . generate_blocks_with_opts ( num_blocks, GenerateBlocksOptions :: default ( ) , rng)
211+ let num_validators = self . private_keys . len ( ) ;
212+
213+ self . generate_blocks_with_opts ( num_blocks, GenerateBlocksOptions { num_validators, ..Default :: default ( ) } , rng)
194214 }
195215
196216 /// Create multiple blocks, with additional parameters.
@@ -200,20 +220,53 @@ impl<N: Network> TestChainBuilder<N> {
200220 pub fn generate_blocks_with_opts (
201221 & mut self ,
202222 num_blocks : usize ,
203- options : GenerateBlocksOptions ,
223+ mut options : GenerateBlocksOptions < N > ,
204224 rng : & mut TestRng ,
205225 ) -> Result < Vec < Block < N > > > {
206226 assert ! ( num_blocks > 0 , "Need to build at least one block" ) ;
207227
208- let options = GenerateBlockOptions {
209- skip_votes : options. skip_votes ,
210- skip_nodes : options. skip_nodes ,
211- ..Default :: default ( )
212- } ;
213-
214228 let mut result = vec ! [ ] ;
215- for _ in 0 ..num_blocks {
216- let block = self . generate_block_with_opts ( options. clone ( ) , rng) ?;
229+
230+ // If configured, skip enough blocks to reach the current consensus version.
231+ if options. skip_to_current_version {
232+ let ( version, target_height) = TEST_CONSENSUS_VERSION_HEIGHTS . last ( ) . unwrap ( ) ;
233+ let mut current_height = self . ledger . latest_height ( ) ;
234+
235+ let diff = target_height. saturating_sub ( current_height) ;
236+
237+ if diff > 0 {
238+ println ! ( "Skipping {diff} blocks to reach {version}" ) ;
239+
240+ while current_height < * target_height && result. len ( ) < num_blocks {
241+ let options = GenerateBlockOptions {
242+ skip_votes : options. skip_votes ,
243+ skip_nodes : options. skip_nodes . clone ( ) ,
244+ ..Default :: default ( )
245+ } ;
246+
247+ let block = self . generate_block_with_opts ( options, rng) ?;
248+ current_height = block. height ( ) ;
249+ result. push ( block) ;
250+ }
251+
252+ println ! ( "Advanced to the current consensus version at height {target_height}" ) ;
253+ } else {
254+ debug ! ( "Already at the current consensus version. No blocks to skip." ) ;
255+ }
256+ }
257+
258+ while result. len ( ) < num_blocks {
259+ let num_txs = ( BatchHeader :: < N > :: MAX_TRANSMISSIONS_PER_BATCH * options. num_validators )
260+ . min ( options. transactions . len ( ) ) ;
261+
262+ let options = GenerateBlockOptions {
263+ skip_votes : options. skip_votes ,
264+ skip_nodes : options. skip_nodes . clone ( ) ,
265+ transactions : options. transactions . drain ( ..num_txs) . collect ( ) ,
266+ ..Default :: default ( )
267+ } ;
268+
269+ let block = self . generate_block_with_opts ( options, rng) ?;
217270 result. push ( block) ;
218271 }
219272
@@ -262,8 +315,6 @@ impl<N: Network> TestChainBuilder<N> {
262315 transmissions. insert ( transmission_id, transmission) ;
263316 }
264317
265- let transmission_ids: IndexSet < _ > = transmissions. keys ( ) . copied ( ) . collect ( ) ;
266-
267318 // =======================================
268319 // Create certificates for the new block.
269320 // =======================================
@@ -303,6 +354,13 @@ impl<N: Network> TestChainBuilder<N> {
303354 continue ;
304355 }
305356
357+ let transmission_ids: IndexSet < _ > = transmissions
358+ . keys ( )
359+ . skip ( key1_idx * BatchHeader :: < N > :: MAX_TRANSMISSIONS_PER_BATCH )
360+ . take ( BatchHeader :: < N > :: MAX_TRANSMISSIONS_PER_BATCH )
361+ . copied ( )
362+ . collect ( ) ;
363+
306364 let batch_header = BatchHeader :: new (
307365 private_key_1,
308366 round,
@@ -404,6 +462,7 @@ impl<N: Network> TestChainBuilder<N> {
404462
405463 // Construct the block.
406464 let subdag = Subdag :: from ( subdag_map) . unwrap ( ) ;
465+
407466 let block = self . ledger . prepare_advance_to_next_quorum_block ( subdag, transmissions, rng) ?;
408467
409468 // Skip to increase performance.
0 commit comments