@@ -593,7 +593,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
593593 origin : BlockOrigin ,
594594 hash : Block :: Hash ,
595595 import_headers : PrePostHeader < Block :: Header > ,
596- justification : Justification ,
596+ justification : Option < Justification > ,
597597 body : Option < Vec < Block :: Extrinsic > > ,
598598 authorities : Option < Vec < AuthorityId > > ,
599599 finalized : bool ,
@@ -624,7 +624,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
624624 // ensure parent block is finalized to maintain invariant that
625625 // finality is called sequentially.
626626 if finalized {
627- self . apply_finality ( parent_hash, last_best, make_notifications) ?;
627+ self . apply_finality ( parent_hash, None , last_best, make_notifications) ?;
628628 }
629629
630630 let tags = self . transaction_tags ( parent_hash, & body) ?;
@@ -678,7 +678,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
678678 transaction. set_block_data (
679679 import_headers. post ( ) . clone ( ) ,
680680 body,
681- Some ( justification) ,
681+ justification,
682682 leaf_state,
683683 ) ?;
684684
@@ -727,8 +727,16 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
727727 Ok ( ImportResult :: Queued )
728728 }
729729
730- /// Finalizes all blocks up to given.
731- fn apply_finality ( & self , block : Block :: Hash , best_block : Block :: Hash , notify : bool ) -> error:: Result < ( ) > {
730+ /// Finalizes all blocks up to given. If a justification is provided it is
731+ /// stored with the given finalized block (any other finalized blocks are
732+ /// left unjustified).
733+ fn apply_finality (
734+ & self ,
735+ block : Block :: Hash ,
736+ justification : Option < Justification > ,
737+ best_block : Block :: Hash ,
738+ notify : bool ,
739+ ) -> error:: Result < ( ) > {
732740 // find tree route from last finalized to given block.
733741 let last_finalized = self . backend . blockchain ( ) . last_finalized ( ) ?;
734742
@@ -759,10 +767,15 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
759767 // `block`.
760768 }
761769
762- for finalize_new in route_from_finalized. enacted ( ) {
763- self . backend . finalize_block ( BlockId :: Hash ( finalize_new. hash ) ) ?;
770+ let enacted = route_from_finalized. enacted ( ) ;
771+ assert ! ( enacted. len( ) > 0 ) ;
772+ for finalize_new in & enacted[ ..enacted. len ( ) - 1 ] {
773+ self . backend . finalize_block ( BlockId :: Hash ( finalize_new. hash ) , None ) ?;
764774 }
765775
776+ assert_eq ! ( enacted. last( ) . map( |e| e. hash) , Some ( block) ) ;
777+ self . backend . finalize_block ( BlockId :: Hash ( block) , justification) ?;
778+
766779 if notify {
767780 // sometimes when syncing, tons of blocks can be finalized at once.
768781 // we'll send notifications spuriously in that case.
@@ -791,15 +804,15 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
791804 /// Pass a flag to indicate whether finality notifications should be propagated.
792805 /// This is usually tied to some synchronization state, where we don't send notifications
793806 /// while performing major synchronization work.
794- pub fn finalize_block ( & self , id : BlockId < Block > , notify : bool ) -> error:: Result < ( ) > {
807+ pub fn finalize_block ( & self , id : BlockId < Block > , justification : Option < Justification > , notify : bool ) -> error:: Result < ( ) > {
795808 let last_best = self . backend . blockchain ( ) . info ( ) ?. best_hash ;
796809 let to_finalize_hash = match id {
797810 BlockId :: Hash ( h) => h,
798811 BlockId :: Number ( n) => self . backend . blockchain ( ) . hash ( n) ?
799812 . ok_or_else ( || error:: ErrorKind :: UnknownBlock ( format ! ( "No block with number {:?}" , n) ) ) ?,
800813 } ;
801814
802- self . apply_finality ( to_finalize_hash, last_best, notify)
815+ self . apply_finality ( to_finalize_hash, justification , last_best, notify)
803816 }
804817
805818 /// Attempts to revert the chain by `n` blocks. Returns the number of blocks that were
@@ -858,7 +871,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
858871 -> error:: Result < Option < SignedBlock < Block > > >
859872 {
860873 Ok ( match ( self . header ( id) ?, self . body ( id) ?, self . justification ( id) ?) {
861- ( Some ( header) , Some ( extrinsics) , Some ( justification) ) =>
874+ ( Some ( header) , Some ( extrinsics) , justification) =>
862875 Some ( SignedBlock { block : Block :: new ( header, extrinsics) , justification } ) ,
863876 _ => None ,
864877 } )
@@ -1064,7 +1077,8 @@ impl<B, E, Block, RA> consensus::BlockImport<Block> for Client<B, E, Block, RA>
10641077{
10651078 type Error = Error ;
10661079
1067- /// Import a checked and validated block
1080+ /// Import a checked and validated block. If a justification is provided in
1081+ /// `ImportBlock` then `finalized` *must* be true.
10681082 fn import_block (
10691083 & self ,
10701084 import_block : ImportBlock < Block > ,
@@ -1081,6 +1095,9 @@ impl<B, E, Block, RA> consensus::BlockImport<Block> for Client<B, E, Block, RA>
10811095 finalized,
10821096 auxiliary,
10831097 } = import_block;
1098+
1099+ assert ! ( justification. is_some( ) && finalized || justification. is_none( ) ) ;
1100+
10841101 let parent_hash = header. parent_hash ( ) . clone ( ) ;
10851102
10861103 match self . backend . blockchain ( ) . status ( BlockId :: Hash ( parent_hash) ) ? {
@@ -1254,7 +1271,7 @@ pub(crate) mod tests {
12541271 nonce : * nonces. entry ( from) . and_modify ( |n| { * n = * n + 1 } ) . or_default ( ) ,
12551272 } ) . unwrap ( ) ;
12561273 }
1257- remote_client. justify_and_import ( BlockOrigin :: Own , builder. bake ( ) . unwrap ( ) ) . unwrap ( ) ;
1274+ remote_client. import ( BlockOrigin :: Own , builder. bake ( ) . unwrap ( ) ) . unwrap ( ) ;
12581275
12591276 let header = remote_client. header ( & BlockId :: Number ( i as u64 + 1 ) ) . unwrap ( ) . unwrap ( ) ;
12601277 let trie_root = header. digest ( ) . log ( DigestItem :: as_changes_trie_root)
@@ -1334,7 +1351,7 @@ pub(crate) mod tests {
13341351
13351352 let builder = client. new_block ( ) . unwrap ( ) ;
13361353
1337- client. justify_and_import ( BlockOrigin :: Own , builder. bake ( ) . unwrap ( ) ) . unwrap ( ) ;
1354+ client. import ( BlockOrigin :: Own , builder. bake ( ) . unwrap ( ) ) . unwrap ( ) ;
13381355
13391356 assert_eq ! ( client. info( ) . unwrap( ) . chain. best_number, 1 ) ;
13401357 }
@@ -1352,7 +1369,7 @@ pub(crate) mod tests {
13521369 nonce : 0 ,
13531370 } ) . unwrap ( ) ;
13541371
1355- client. justify_and_import ( BlockOrigin :: Own , builder. bake ( ) . unwrap ( ) ) . unwrap ( ) ;
1372+ client. import ( BlockOrigin :: Own , builder. bake ( ) . unwrap ( ) ) . unwrap ( ) ;
13561373
13571374 assert_eq ! ( client. info( ) . unwrap( ) . chain. best_number, 1 ) ;
13581375 assert ! ( client. state_at( & BlockId :: Number ( 1 ) ) . unwrap( ) != client. state_at( & BlockId :: Number ( 0 ) ) . unwrap( ) ) ;
@@ -1404,7 +1421,7 @@ pub(crate) mod tests {
14041421 nonce: 0 ,
14051422 } ) . is_err( ) ) ;
14061423
1407- client. justify_and_import ( BlockOrigin :: Own , builder. bake ( ) . unwrap ( ) ) . unwrap ( ) ;
1424+ client. import ( BlockOrigin :: Own , builder. bake ( ) . unwrap ( ) ) . unwrap ( ) ;
14081425
14091426 assert_eq ! ( client. info( ) . unwrap( ) . chain. best_number, 1 ) ;
14101427 assert ! ( client. state_at( & BlockId :: Number ( 1 ) ) . unwrap( ) != client. state_at( & BlockId :: Number ( 0 ) ) . unwrap( ) ) ;
@@ -1444,11 +1461,11 @@ pub(crate) mod tests {
14441461
14451462 // G -> A1
14461463 let a1 = client. new_block ( ) . unwrap ( ) . bake ( ) . unwrap ( ) ;
1447- client. justify_and_import ( BlockOrigin :: Own , a1. clone ( ) ) . unwrap ( ) ;
1464+ client. import ( BlockOrigin :: Own , a1. clone ( ) ) . unwrap ( ) ;
14481465
14491466 // A1 -> A2
14501467 let a2 = client. new_block ( ) . unwrap ( ) . bake ( ) . unwrap ( ) ;
1451- client. justify_and_import ( BlockOrigin :: Own , a2. clone ( ) ) . unwrap ( ) ;
1468+ client. import ( BlockOrigin :: Own , a2. clone ( ) ) . unwrap ( ) ;
14521469
14531470 let genesis_hash = client. info ( ) . unwrap ( ) . chain . genesis_hash ;
14541471
@@ -1473,23 +1490,23 @@ pub(crate) mod tests {
14731490
14741491 // G -> A1
14751492 let a1 = client. new_block ( ) . unwrap ( ) . bake ( ) . unwrap ( ) ;
1476- client. justify_and_import ( BlockOrigin :: Own , a1. clone ( ) ) . unwrap ( ) ;
1493+ client. import ( BlockOrigin :: Own , a1. clone ( ) ) . unwrap ( ) ;
14771494
14781495 // A1 -> A2
14791496 let a2 = client. new_block_at ( & BlockId :: Hash ( a1. hash ( ) ) ) . unwrap ( ) . bake ( ) . unwrap ( ) ;
1480- client. justify_and_import ( BlockOrigin :: Own , a2. clone ( ) ) . unwrap ( ) ;
1497+ client. import ( BlockOrigin :: Own , a2. clone ( ) ) . unwrap ( ) ;
14811498
14821499 // A2 -> A3
14831500 let a3 = client. new_block_at ( & BlockId :: Hash ( a2. hash ( ) ) ) . unwrap ( ) . bake ( ) . unwrap ( ) ;
1484- client. justify_and_import ( BlockOrigin :: Own , a3. clone ( ) ) . unwrap ( ) ;
1501+ client. import ( BlockOrigin :: Own , a3. clone ( ) ) . unwrap ( ) ;
14851502
14861503 // A3 -> A4
14871504 let a4 = client. new_block_at ( & BlockId :: Hash ( a3. hash ( ) ) ) . unwrap ( ) . bake ( ) . unwrap ( ) ;
1488- client. justify_and_import ( BlockOrigin :: Own , a4. clone ( ) ) . unwrap ( ) ;
1505+ client. import ( BlockOrigin :: Own , a4. clone ( ) ) . unwrap ( ) ;
14891506
14901507 // A4 -> A5
14911508 let a5 = client. new_block_at ( & BlockId :: Hash ( a4. hash ( ) ) ) . unwrap ( ) . bake ( ) . unwrap ( ) ;
1492- client. justify_and_import ( BlockOrigin :: Own , a5. clone ( ) ) . unwrap ( ) ;
1509+ client. import ( BlockOrigin :: Own , a5. clone ( ) ) . unwrap ( ) ;
14931510
14941511 // A1 -> B2
14951512 let mut builder = client. new_block_at ( & BlockId :: Hash ( a1. hash ( ) ) ) . unwrap ( ) ;
@@ -1501,15 +1518,15 @@ pub(crate) mod tests {
15011518 nonce : 0 ,
15021519 } ) . unwrap ( ) ;
15031520 let b2 = builder. bake ( ) . unwrap ( ) ;
1504- client. justify_and_import ( BlockOrigin :: Own , b2. clone ( ) ) . unwrap ( ) ;
1521+ client. import ( BlockOrigin :: Own , b2. clone ( ) ) . unwrap ( ) ;
15051522
15061523 // B2 -> B3
15071524 let b3 = client. new_block_at ( & BlockId :: Hash ( b2. hash ( ) ) ) . unwrap ( ) . bake ( ) . unwrap ( ) ;
1508- client. justify_and_import ( BlockOrigin :: Own , b3. clone ( ) ) . unwrap ( ) ;
1525+ client. import ( BlockOrigin :: Own , b3. clone ( ) ) . unwrap ( ) ;
15091526
15101527 // B3 -> B4
15111528 let b4 = client. new_block_at ( & BlockId :: Hash ( b3. hash ( ) ) ) . unwrap ( ) . bake ( ) . unwrap ( ) ;
1512- client. justify_and_import ( BlockOrigin :: Own , b4. clone ( ) ) . unwrap ( ) ;
1529+ client. import ( BlockOrigin :: Own , b4. clone ( ) ) . unwrap ( ) ;
15131530
15141531 // // B2 -> C3
15151532 let mut builder = client. new_block_at ( & BlockId :: Hash ( b2. hash ( ) ) ) . unwrap ( ) ;
@@ -1521,7 +1538,7 @@ pub(crate) mod tests {
15211538 nonce : 1 ,
15221539 } ) . unwrap ( ) ;
15231540 let c3 = builder. bake ( ) . unwrap ( ) ;
1524- client. justify_and_import ( BlockOrigin :: Own , c3. clone ( ) ) . unwrap ( ) ;
1541+ client. import ( BlockOrigin :: Own , c3. clone ( ) ) . unwrap ( ) ;
15251542
15261543 // A1 -> D2
15271544 let mut builder = client. new_block_at ( & BlockId :: Hash ( a1. hash ( ) ) ) . unwrap ( ) ;
@@ -1533,7 +1550,7 @@ pub(crate) mod tests {
15331550 nonce : 0 ,
15341551 } ) . unwrap ( ) ;
15351552 let d2 = builder. bake ( ) . unwrap ( ) ;
1536- client. justify_and_import ( BlockOrigin :: Own , d2. clone ( ) ) . unwrap ( ) ;
1553+ client. import ( BlockOrigin :: Own , d2. clone ( ) ) . unwrap ( ) ;
15371554
15381555 assert_eq ! ( client. info( ) . unwrap( ) . chain. best_hash, a5. hash( ) ) ;
15391556
@@ -1686,4 +1703,44 @@ pub(crate) mod tests {
16861703 }
16871704 }
16881705 }
1706+
1707+ #[ test]
1708+ fn import_with_justification ( ) {
1709+ use test_client:: blockchain:: Backend ;
1710+
1711+ let client = test_client:: new ( ) ;
1712+
1713+ // G -> A1
1714+ let a1 = client. new_block ( ) . unwrap ( ) . bake ( ) . unwrap ( ) ;
1715+ client. import ( BlockOrigin :: Own , a1. clone ( ) ) . unwrap ( ) ;
1716+
1717+ // A1 -> A2
1718+ let a2 = client. new_block_at ( & BlockId :: Hash ( a1. hash ( ) ) ) . unwrap ( ) . bake ( ) . unwrap ( ) ;
1719+ client. import ( BlockOrigin :: Own , a2. clone ( ) ) . unwrap ( ) ;
1720+
1721+ // A2 -> A3
1722+ let justification = vec ! [ 1 , 2 , 3 ] ;
1723+ let a3 = client. new_block_at ( & BlockId :: Hash ( a2. hash ( ) ) ) . unwrap ( ) . bake ( ) . unwrap ( ) ;
1724+ client. import_justified ( BlockOrigin :: Own , a3. clone ( ) , justification. clone ( ) ) . unwrap ( ) ;
1725+
1726+ assert_eq ! (
1727+ client. backend( ) . blockchain( ) . last_finalized( ) . unwrap( ) ,
1728+ a3. hash( ) ,
1729+ ) ;
1730+
1731+ assert_eq ! (
1732+ client. backend( ) . blockchain( ) . justification( BlockId :: Hash ( a3. hash( ) ) ) . unwrap( ) ,
1733+ Some ( justification) ,
1734+ ) ;
1735+
1736+ assert_eq ! (
1737+ client. backend( ) . blockchain( ) . justification( BlockId :: Hash ( a1. hash( ) ) ) . unwrap( ) ,
1738+ None ,
1739+ ) ;
1740+
1741+ assert_eq ! (
1742+ client. backend( ) . blockchain( ) . justification( BlockId :: Hash ( a2. hash( ) ) ) . unwrap( ) ,
1743+ None ,
1744+ ) ;
1745+ }
16891746}
0 commit comments