@@ -57,7 +57,7 @@ use tokio::runtime::{Handle, Runtime};
5757
5858use authorities:: AuthoritySet ;
5959use communication:: grandpa_protocol_name;
60- use sc_block_builder:: BlockBuilderProvider ;
60+ use sc_block_builder:: { BlockBuilder , BlockBuilderProvider } ;
6161use sc_consensus:: LongestChain ;
6262use sc_keystore:: LocalKeystore ;
6363use sp_application_crypto:: key_types:: GRANDPA ;
@@ -1685,3 +1685,128 @@ fn grandpa_environment_doesnt_send_equivocation_reports_for_itself() {
16851685 let equivocation_proof = sp_finality_grandpa:: Equivocation :: Prevote ( equivocation) ;
16861686 assert ! ( environment. report_equivocation( equivocation_proof) . is_ok( ) ) ;
16871687}
1688+
1689+ #[ test]
1690+ fn revert_prunes_authority_changes ( ) {
1691+ sp_tracing:: try_init_simple ( ) ;
1692+ let runtime = Runtime :: new ( ) . unwrap ( ) ;
1693+
1694+ let peers = & [ Ed25519Keyring :: Alice , Ed25519Keyring :: Bob , Ed25519Keyring :: Charlie ] ;
1695+
1696+ type TestBlockBuilder < ' a > =
1697+ BlockBuilder < ' a , Block , PeersFullClient , substrate_test_runtime_client:: Backend > ;
1698+ let edit_block = |builder : TestBlockBuilder | {
1699+ let mut block = builder. build ( ) . unwrap ( ) . block ;
1700+ add_scheduled_change (
1701+ & mut block,
1702+ ScheduledChange { next_authorities : make_ids ( peers) , delay : 0 } ,
1703+ ) ;
1704+ block
1705+ } ;
1706+
1707+ let api = TestApi :: new ( make_ids ( peers) ) ;
1708+ let mut net = GrandpaTestNet :: new ( api, 3 , 0 ) ;
1709+ runtime. spawn ( initialize_grandpa ( & mut net, peers) ) ;
1710+
1711+ let peer = net. peer ( 0 ) ;
1712+ let client = peer. client ( ) . as_client ( ) ;
1713+
1714+ // Test scenario: (X) = auth-change, 24 = revert-point
1715+ //
1716+ // +---------(27)
1717+ // /
1718+ // 0---(21)---23---24---25---(28)---30
1719+ // ^ \
1720+ // revert-point +------(29)
1721+
1722+ // Construct canonical chain
1723+
1724+ // add 20 blocks
1725+ peer. push_blocks ( 20 , false ) ;
1726+ // at block 21 we add an authority transition
1727+ peer. generate_blocks ( 1 , BlockOrigin :: File , edit_block) ;
1728+ // add more blocks on top of it (until we have 24)
1729+ peer. push_blocks ( 3 , false ) ;
1730+ // add more blocks on top of it (until we have 27)
1731+ peer. push_blocks ( 3 , false ) ;
1732+ // at block 28 we add an authority transition
1733+ peer. generate_blocks ( 1 , BlockOrigin :: File , edit_block) ;
1734+ // add more blocks on top of it (until we have 30)
1735+ peer. push_blocks ( 2 , false ) ;
1736+
1737+ // Fork before revert point
1738+
1739+ // add more blocks on top of block 23 (until we have 26)
1740+ let hash = peer. generate_blocks_at (
1741+ BlockId :: Number ( 23 ) ,
1742+ 3 ,
1743+ BlockOrigin :: File ,
1744+ |builder| {
1745+ let mut block = builder. build ( ) . unwrap ( ) . block ;
1746+ block. header . digest_mut ( ) . push ( DigestItem :: Other ( vec ! [ 1 ] ) ) ;
1747+ block
1748+ } ,
1749+ false ,
1750+ false ,
1751+ true ,
1752+ ForkChoiceStrategy :: LongestChain ,
1753+ ) ;
1754+ // at block 27 of the fork add an authority transition
1755+ peer. generate_blocks_at (
1756+ BlockId :: Hash ( hash) ,
1757+ 1 ,
1758+ BlockOrigin :: File ,
1759+ edit_block,
1760+ false ,
1761+ false ,
1762+ true ,
1763+ ForkChoiceStrategy :: LongestChain ,
1764+ ) ;
1765+
1766+ // Fork after revert point
1767+
1768+ // add more block on top of block 25 (until we have 28)
1769+ let hash = peer. generate_blocks_at (
1770+ BlockId :: Number ( 25 ) ,
1771+ 3 ,
1772+ BlockOrigin :: File ,
1773+ |builder| {
1774+ let mut block = builder. build ( ) . unwrap ( ) . block ;
1775+ block. header . digest_mut ( ) . push ( DigestItem :: Other ( vec ! [ 2 ] ) ) ;
1776+ block
1777+ } ,
1778+ false ,
1779+ false ,
1780+ true ,
1781+ ForkChoiceStrategy :: LongestChain ,
1782+ ) ;
1783+ // at block 29 of the fork add an authority transition
1784+ peer. generate_blocks_at (
1785+ BlockId :: Hash ( hash) ,
1786+ 1 ,
1787+ BlockOrigin :: File ,
1788+ edit_block,
1789+ false ,
1790+ false ,
1791+ true ,
1792+ ForkChoiceStrategy :: LongestChain ,
1793+ ) ;
1794+
1795+ revert ( client. clone ( ) , 6 ) . unwrap ( ) ;
1796+
1797+ let persistent_data: PersistentData < Block > = aux_schema:: load_persistent (
1798+ & * client,
1799+ client. info ( ) . genesis_hash ,
1800+ Zero :: zero ( ) ,
1801+ || unreachable ! ( ) ,
1802+ )
1803+ . unwrap ( ) ;
1804+ let changes_num: Vec < _ > = persistent_data
1805+ . authority_set
1806+ . inner ( )
1807+ . pending_standard_changes
1808+ . iter ( )
1809+ . map ( |( _, n, _) | * n)
1810+ . collect ( ) ;
1811+ assert_eq ! ( changes_num, [ 21 , 27 ] ) ;
1812+ }
0 commit comments