@@ -75,6 +75,64 @@ enum State {
7575 Full ,
7676}
7777
78+ impl State {
79+ fn initial ( client : & Client , snapshot_target : Option < ( BlockHash , u64 ) > ) -> Self {
80+ let ( hash, num) = match snapshot_target {
81+ Some ( target) => target,
82+ None => return State :: Full ,
83+ } ;
84+ let header = match client. block_header ( & num. into ( ) ) {
85+ Some ( ref h) if h. hash ( ) == hash => h. clone ( ) ,
86+ _ => return State :: SnapshotHeader ( hash, num) ,
87+ } ;
88+ if client. block_body ( & hash. into ( ) ) . is_none ( ) {
89+ let parent_hash = header. parent_hash ( ) ;
90+ let parent =
91+ client. block_header ( & parent_hash. into ( ) ) . expect ( "Parent header of the snapshot header must exist" ) ;
92+ return State :: SnapshotBody {
93+ header,
94+ prev_root : parent. transactions_root ( ) ,
95+ }
96+ }
97+
98+ let state_db = client. state_db ( ) . read ( ) ;
99+ let state_root = header. state_root ( ) ;
100+ match TrieFactory :: readonly ( state_db. as_hashdb ( ) , & state_root) {
101+ Ok ( ref trie) if trie. is_complete ( ) => State :: Full ,
102+ _ => State :: SnapshotChunk {
103+ block : hash,
104+ restore : SnapshotRestore :: new ( state_root) ,
105+ } ,
106+ }
107+ }
108+
109+ fn next ( & self , client : & Client ) -> Self {
110+ match self {
111+ State :: SnapshotHeader ( hash, _) => {
112+ let header = client. block_header ( & ( * hash) . into ( ) ) . expect ( "Snapshot header is imported" ) ;
113+ let parent = client
114+ . block_header ( & header. parent_hash ( ) . into ( ) )
115+ . expect ( "Parent of the snapshot header must be imported" ) ;
116+ State :: SnapshotBody {
117+ header,
118+ prev_root : parent. transactions_root ( ) ,
119+ }
120+ }
121+ State :: SnapshotBody {
122+ header,
123+ ..
124+ } => State :: SnapshotChunk {
125+ block : header. hash ( ) ,
126+ restore : SnapshotRestore :: new ( header. state_root ( ) ) ,
127+ } ,
128+ State :: SnapshotChunk {
129+ ..
130+ } => State :: Full ,
131+ State :: Full => State :: Full ,
132+ }
133+ }
134+ }
135+
78136pub struct Extension {
79137 state : State ,
80138 requests : HashMap < NodeId , Vec < ( u64 , RequestMessage ) > > ,
@@ -100,7 +158,7 @@ impl Extension {
100158 ) -> Extension {
101159 api. set_timer ( SYNC_TIMER_TOKEN , Duration :: from_millis ( SYNC_TIMER_INTERVAL ) ) . expect ( "Timer set succeeds" ) ;
102160
103- let state = Extension :: initial_state ( client. clone ( ) , snapshot_target) ;
161+ let state = State :: initial ( & client, snapshot_target) ;
104162 cdebug ! ( SYNC , "Initial state is {:?}" , state) ;
105163 let mut header = client. best_header ( ) ;
106164 let mut hollow_headers = vec ! [ header. decode( ) ] ;
@@ -138,34 +196,29 @@ impl Extension {
138196 }
139197 }
140198
141- fn initial_state ( client : Arc < Client > , snapshot_target : Option < ( BlockHash , u64 ) > ) -> State {
142- let ( hash, num) = match snapshot_target {
143- Some ( target) => target,
144- None => return State :: Full ,
145- } ;
146- let header = match client. block_header ( & num. into ( ) ) {
147- Some ( ref h) if h. hash ( ) == hash => h. clone ( ) ,
148- _ => return State :: SnapshotHeader ( hash, num) ,
149- } ;
150- if client. block_body ( & hash. into ( ) ) . is_none ( ) {
151- let parent_hash = header. parent_hash ( ) ;
152- let parent =
153- client. block_header ( & parent_hash. into ( ) ) . expect ( "Parent header of the snapshot header must exist" ) ;
154- return State :: SnapshotBody {
155- header,
156- prev_root : parent. transactions_root ( ) ,
199+ fn move_state ( & mut self ) {
200+ let next_state = self . state . next ( & self . client ) ;
201+ cdebug ! ( SYNC , "Transitioning the state to {:?}" , next_state) ;
202+ if discriminant ( & next_state) == discriminant ( & State :: Full ) {
203+ let best_hash = match & self . state {
204+ State :: SnapshotHeader ( hash, _) => * hash,
205+ State :: SnapshotBody {
206+ header,
207+ ..
208+ } => header. hash ( ) ,
209+ State :: SnapshotChunk {
210+ block,
211+ ..
212+ } => * block,
213+ State :: Full => unreachable ! ( "Trying to transition state from State::Full" ) ,
214+ } ;
215+ self . client . force_update_best_block ( & best_hash) ;
216+ for downloader in self . header_downloaders . values_mut ( ) {
217+ downloader. update_pivot ( best_hash) ;
157218 }
219+ self . send_status_broadcast ( ) ;
158220 }
159-
160- let state_db = client. state_db ( ) . read ( ) ;
161- let state_root = header. state_root ( ) ;
162- match TrieFactory :: readonly ( state_db. as_hashdb ( ) , & state_root) {
163- Ok ( ref trie) if trie. is_complete ( ) => State :: Full ,
164- _ => State :: SnapshotChunk {
165- block : hash,
166- restore : SnapshotRestore :: new ( state_root) ,
167- } ,
168- }
221+ self . state = next_state;
169222 }
170223
171224 fn dismiss_request ( & mut self , id : & NodeId , request_id : u64 ) {
@@ -476,8 +529,7 @@ impl NetworkExtension<Event> for Extension {
476529 if let Some ( root) = restore. next_to_feed ( ) {
477530 self . send_chunk_request ( & block, & root) ;
478531 } else {
479- self . client . force_update_best_block ( & block) ;
480- self . transition_to_full ( ) ;
532+ self . move_state ( ) ;
481533 }
482534 }
483535 State :: Full => {
@@ -863,11 +915,7 @@ impl Extension {
863915 return
864916 }
865917 }
866- self . state = State :: SnapshotBody {
867- header : EncodedHeader :: new ( header. rlp_bytes ( ) . to_vec ( ) ) ,
868- prev_root : * parent. transactions_root ( ) ,
869- } ;
870- cdebug ! ( SYNC , "Transitioning state to {:?}" , self . state) ;
918+ self . move_state ( ) ;
871919 }
872920 _ => cdebug ! (
873921 SYNC ,
@@ -941,11 +989,7 @@ impl Extension {
941989 } ;
942990 match self . client . import_trusted_block ( & block) {
943991 Ok ( _) | Err ( BlockImportError :: Import ( ImportError :: AlreadyInChain ) ) => {
944- self . state = State :: SnapshotChunk {
945- block : header. hash ( ) ,
946- restore : SnapshotRestore :: new ( header. state_root ( ) ) ,
947- } ;
948- cdebug ! ( SYNC , "Transitioning state to {:?}" , self . state) ;
992+ self . move_state ( ) ;
949993 }
950994 Err ( BlockImportError :: Import ( ImportError :: AlreadyQueued ) ) => { }
951995 // FIXME: handle import errors
@@ -1051,20 +1095,9 @@ impl Extension {
10511095 if let Some ( root) = restore. next_to_feed ( ) {
10521096 self . send_chunk_request ( & block, & root) ;
10531097 } else {
1054- self . client . force_update_best_block ( & block) ;
1055- self . transition_to_full ( ) ;
1098+ self . move_state ( ) ;
10561099 }
10571100 }
1058-
1059- fn transition_to_full ( & mut self ) {
1060- cdebug ! ( SYNC , "Transitioning state to {:?}" , State :: Full ) ;
1061- let best_hash = self . client . best_block_header ( ) . hash ( ) ;
1062- for downloader in self . header_downloaders . values_mut ( ) {
1063- downloader. update_pivot ( best_hash) ;
1064- }
1065- self . state = State :: Full ;
1066- self . send_status_broadcast ( ) ;
1067- }
10681101}
10691102
10701103pub struct BlockSyncSender ( EventSender < Event > ) ;
0 commit comments