1515
1616use crate :: {
1717 MAX_LEADER_CERTIFICATE_DELAY_IN_SECS ,
18- Primary ,
19- helpers:: {
20- BFTReceiver ,
21- ConsensusSender ,
22- DAG ,
23- PrimaryReceiver ,
24- PrimarySender ,
25- Storage ,
26- fmt_id,
27- init_bft_channels,
28- now,
29- } ,
18+ helpers:: { ConsensusSender , DAG , PrimaryReceiver , PrimarySender , Storage , fmt_id, now} ,
19+ primary:: { Primary , PrimaryCallback } ,
20+ sync:: SyncCallback ,
3021} ;
3122
3223use snarkos_account:: Account ;
@@ -50,15 +41,11 @@ use anyhow::Context;
5041use colored:: Colorize ;
5142use indexmap:: { IndexMap , IndexSet } ;
5243#[ cfg( feature = "locktick" ) ]
53- use locktick:: {
54- parking_lot:: { Mutex , RwLock } ,
55- tokio:: Mutex as TMutex ,
56- } ;
44+ use locktick:: { parking_lot:: RwLock , tokio:: Mutex as TMutex } ;
5745#[ cfg( not( feature = "locktick" ) ) ]
58- use parking_lot:: { Mutex , RwLock } ;
46+ use parking_lot:: RwLock ;
5947use std:: {
6048 collections:: { BTreeMap , HashSet } ,
61- future:: Future ,
6249 net:: SocketAddr ,
6350 sync:: {
6451 Arc ,
@@ -67,10 +54,7 @@ use std::{
6754} ;
6855#[ cfg( not( feature = "locktick" ) ) ]
6956use tokio:: sync:: Mutex as TMutex ;
70- use tokio:: {
71- sync:: { OnceCell , oneshot} ,
72- task:: JoinHandle ,
73- } ;
57+ use tokio:: sync:: { OnceCell , oneshot} ;
7458
7559#[ derive( Clone ) ]
7660pub struct BFT < N : Network > {
@@ -84,8 +68,6 @@ pub struct BFT<N: Network> {
8468 leader_certificate_timer : Arc < AtomicI64 > ,
8569 /// The consensus sender.
8670 consensus_sender : Arc < OnceCell < ConsensusSender < N > > > ,
87- /// Handles for all spawned tasks.
88- handles : Arc < Mutex < Vec < JoinHandle < ( ) > > > > ,
8971 /// The BFT lock.
9072 lock : Arc < TMutex < ( ) > > ,
9173}
@@ -120,7 +102,6 @@ impl<N: Network> BFT<N> {
120102 leader_certificate : Default :: default ( ) ,
121103 leader_certificate_timer : Default :: default ( ) ,
122104 consensus_sender : Default :: default ( ) ,
123- handles : Default :: default ( ) ,
124105 lock : Default :: default ( ) ,
125106 } )
126107 }
@@ -137,14 +118,16 @@ impl<N: Network> BFT<N> {
137118 primary_receiver : PrimaryReceiver < N > ,
138119 ) -> Result < ( ) > {
139120 info ! ( "Starting the BFT instance..." ) ;
140- // Initialize the BFT channels.
141- let ( bft_sender, bft_receiver) = init_bft_channels :: < N > ( ) ;
142- // First, start the BFT handlers.
143- self . start_handlers ( bft_receiver) ;
121+ // Set up callbacks.
122+ let primary_callback = Some ( Arc :: new ( self . clone ( ) ) as Arc < dyn PrimaryCallback < N > > ) ;
123+
124+ let sync_callback = Some ( Arc :: new ( self . clone ( ) ) as Arc < dyn SyncCallback < N > > ) ;
125+
144126 // Next, run the primary instance.
145- self . primary . run ( ping, Some ( bft_sender) , primary_sender, primary_receiver) . await ?;
127+ self . primary . run ( ping, primary_callback, sync_callback, primary_sender, primary_receiver) . await ?;
128+
146129 // Lastly, set the consensus sender.
147- // Note: This ensures during initial syncing, that the BFT does not advance the ledger.
130+ // Note: This ensures that the BFT does not advance the ledger during initial syncing .
148131 if let Some ( consensus_sender) = consensus_sender {
149132 self . consensus_sender . set ( consensus_sender) . expect ( "Consensus sender already set" ) ;
150133 }
@@ -226,8 +209,9 @@ impl<N: Network> BFT<N> {
226209 }
227210}
228211
229- impl < N : Network > BFT < N > {
230- /// Stores the certificate in the DAG, and attempts to commit one or more anchors.
212+ #[ async_trait:: async_trait]
213+ impl < N : Network > PrimaryCallback < N > for BFT < N > {
214+ /// Notification that a new round has started.
231215 fn update_to_next_round ( & self , current_round : u64 ) -> bool {
232216 // Ensure the current round is at least the storage round (this is a sanity check).
233217 let storage_round = self . storage ( ) . current_round ( ) ;
@@ -299,6 +283,39 @@ impl<N: Network> BFT<N> {
299283 is_ready
300284 }
301285
286+ /// Notification about a new certificated generated by `Primary` or received by the `Primary` from a peer.
287+ async fn add_new_certificate ( & self , certificate : BatchCertificate < N > ) -> Result < ( ) > {
288+ // Update the DAG with the certificate.
289+ self . update_dag :: < true , false > ( certificate) . await
290+ }
291+ }
292+
293+ #[ async_trait:: async_trait]
294+ impl < N : Network > SyncCallback < N > for BFT < N > {
295+ /// Syncs the BFT DAG with the given batch certificates. These batch certificates **must**
296+ /// already exist in the ledger.
297+ ///
298+ /// This method commits all the certificates into the DAG.
299+ /// Note that there is no need to insert the certificates into the DAG, because these certificates
300+ /// already exist in the ledger and therefore do not need to be re-ordered into future committed subdags.
301+ async fn sync_dag_at_bootup ( & self , certificates : Vec < BatchCertificate < N > > ) {
302+ // Acquire the BFT write lock.
303+ let mut dag = self . dag . write ( ) ;
304+
305+ // Commit all the certificates.
306+ for certificate in certificates {
307+ dag. commit ( & certificate, self . storage ( ) . max_gc_rounds ( ) ) ;
308+ }
309+ }
310+
311+ /// Notification about a new certificate detected by the `Sync` instance after fetching a new block.
312+ async fn add_new_certificate ( & self , certificate : BatchCertificate < N > ) -> Result < ( ) > {
313+ // Update the DAG with the certificate.
314+ self . update_dag :: < true , true > ( certificate) . await
315+ }
316+ }
317+
318+ impl < N : Network > BFT < N > {
302319 /// Updates the leader certificate to the current even round,
303320 /// returning `true` if the BFT is ready to update to the next round.
304321 ///
@@ -901,86 +918,13 @@ impl<N: Network> BFT<N> {
901918}
902919
903920impl < N : Network > BFT < N > {
904- /// Starts the BFT handlers.
905- fn start_handlers ( & self , bft_receiver : BFTReceiver < N > ) {
906- let BFTReceiver {
907- mut rx_primary_round,
908- mut rx_primary_certificate,
909- mut rx_sync_bft_dag_at_bootup,
910- mut rx_sync_bft,
911- } = bft_receiver;
912-
913- // Process the current round from the primary.
914- let self_ = self . clone ( ) ;
915- self . spawn ( async move {
916- while let Some ( ( current_round, callback) ) = rx_primary_round. recv ( ) . await {
917- callback. send ( self_. update_to_next_round ( current_round) ) . ok ( ) ;
918- }
919- } ) ;
920-
921- // Process the certificate from the primary.
922- let self_ = self . clone ( ) ;
923- self . spawn ( async move {
924- while let Some ( ( certificate, callback) ) = rx_primary_certificate. recv ( ) . await {
925- // Update the DAG with the certificate.
926- let result = self_. update_dag :: < true , false > ( certificate) . await ;
927- // Send the callback **after** updating the DAG.
928- // Note: We must await the DAG update before proceeding.
929- callback. send ( result) . ok ( ) ;
930- }
931- } ) ;
932-
933- // Process the request to sync the BFT DAG at bootup.
934- let self_ = self . clone ( ) ;
935- self . spawn ( async move {
936- while let Some ( certificates) = rx_sync_bft_dag_at_bootup. recv ( ) . await {
937- self_. sync_bft_dag_at_bootup ( certificates) . await ;
938- }
939- } ) ;
940-
941- // Handler for new certificates that were fetched by the sync module.
942- let self_ = self . clone ( ) ;
943- self . spawn ( async move {
944- while let Some ( ( certificate, callback) ) = rx_sync_bft. recv ( ) . await {
945- // Update the DAG with the certificate.
946- let result = self_. update_dag :: < true , true > ( certificate) . await ;
947- // Send the callback **after** updating the DAG.
948- // Note: We must await the DAG update before proceeding.
949- callback. send ( result) . ok ( ) ;
950- }
951- } ) ;
952- }
953-
954- /// Syncs the BFT DAG with the given batch certificates. These batch certificates **must**
955- /// already exist in the ledger.
956- ///
957- /// This method commits all the certificates into the DAG.
958- /// Note that there is no need to insert the certificates into the DAG, because these certificates
959- /// already exist in the ledger and therefore do not need to be re-ordered into future committed subdags.
960- async fn sync_bft_dag_at_bootup ( & self , certificates : Vec < BatchCertificate < N > > ) {
961- // Acquire the BFT write lock.
962- let mut dag = self . dag . write ( ) ;
963-
964- // Commit all the certificates.
965- for certificate in certificates {
966- dag. commit ( & certificate, self . storage ( ) . max_gc_rounds ( ) ) ;
967- }
968- }
969-
970- /// Spawns a task with the given future; it should only be used for long-running tasks.
971- fn spawn < T : Future < Output = ( ) > + Send + ' static > ( & self , future : T ) {
972- self . handles . lock ( ) . push ( tokio:: spawn ( future) ) ;
973- }
974-
975921 /// Shuts down the BFT.
976922 pub async fn shut_down ( & self ) {
977923 info ! ( "Shutting down the BFT..." ) ;
978924 // Acquire the lock.
979925 let _lock = self . lock . lock ( ) . await ;
980926 // Shut down the primary.
981927 self . primary . shut_down ( ) . await ;
982- // Abort the tasks.
983- self . handles . lock ( ) . iter ( ) . for_each ( |handle| handle. abort ( ) ) ;
984928 }
985929}
986930
@@ -990,6 +934,7 @@ mod tests {
990934 BFT ,
991935 MAX_LEADER_CERTIFICATE_DELAY_IN_SECS ,
992936 helpers:: { Storage , dag:: test_helpers:: mock_dag_with_modified_last_committed_round} ,
937+ sync:: SyncCallback ,
993938 } ;
994939
995940 use snarkos_account:: Account ;
@@ -1587,7 +1532,7 @@ mod tests {
15871532 let bootup_bft = initialize_bft ( account. clone ( ) , storage_2, ledger) ?;
15881533
15891534 // Sync the BFT DAG at bootup.
1590- bootup_bft. sync_bft_dag_at_bootup ( certificates. clone ( ) ) . await ;
1535+ bootup_bft. sync_dag_at_bootup ( certificates. clone ( ) ) . await ;
15911536
15921537 // Check that the BFT starts from the same last committed round.
15931538 assert_eq ! ( bft. dag. read( ) . last_committed_round( ) , bootup_bft. dag. read( ) . last_committed_round( ) ) ;
@@ -1766,7 +1711,7 @@ mod tests {
17661711 let bootup_bft = initialize_bft ( account. clone ( ) , bootup_storage. clone ( ) , ledger. clone ( ) ) ?;
17671712
17681713 // Sync the BFT DAG at bootup.
1769- bootup_bft. sync_bft_dag_at_bootup ( pre_shutdown_certificates. clone ( ) ) . await ;
1714+ bootup_bft. sync_dag_at_bootup ( pre_shutdown_certificates. clone ( ) ) . await ;
17701715
17711716 // Insert the post shutdown certificates to the storage and BFT with bootup.
17721717 for certificate in post_shutdown_certificates. iter ( ) {
@@ -1946,7 +1891,7 @@ mod tests {
19461891 // Insert a mock DAG in the BFT without bootup.
19471892 * bootup_bft. dag . write ( ) = crate :: helpers:: dag:: test_helpers:: mock_dag_with_modified_last_committed_round ( 0 ) ;
19481893 // Sync the BFT DAG at bootup.
1949- bootup_bft. sync_bft_dag_at_bootup ( pre_shutdown_certificates. clone ( ) ) . await ;
1894+ bootup_bft. sync_dag_at_bootup ( pre_shutdown_certificates. clone ( ) ) . await ;
19501895
19511896 // Insert the post shutdown certificates into the storage.
19521897 let mut post_shutdown_certificates: Vec < snarkvm:: ledger:: narwhal:: BatchCertificate < CurrentNetwork > > =
0 commit comments