@@ -14,6 +14,7 @@ use simperby_common::verify::CommitSequenceVerifier;
1414use simperby_common:: * ;
1515use simperby_network:: { NetworkConfig , Peer , SharedKnownPeers } ;
1616use std:: { collections:: HashSet , fmt} ;
17+ use utils:: * ;
1718
1819pub type Branch = String ;
1920pub type Tag = String ;
@@ -226,13 +227,139 @@ impl<T: RawRepository> DistributedRepository<T> {
226227 /// Checks the validity of the repository, starting from the given height.
227228 ///
228229 /// It checks
229- /// 1. all the reserved branches and tags
230- /// 2. the finalization proof in the `fp` branch.
231- /// 3. the existence of merge commits
232- /// 4. the canonical history of the `finalized` branch.
230+ /// 1. all the reserved branches and tags,
231+ /// 2. the finalization proof in the `fp` branch,
232+ /// 3. the existence of merge commits,
233+ /// 4. the canonical history of the `finalized` branch,
233234 /// 5. the reserved state in a valid format.
234- pub async fn check ( & self , _starting_height : BlockHeight ) -> Result < bool , Error > {
235- unimplemented ! ( )
235+ pub async fn check ( & self , starting_height : BlockHeight ) -> Result < bool , Error > {
236+ let last_header = self . get_last_finalized_block_header ( ) . await ?;
237+ if last_header. height < starting_height {
238+ return Err ( anyhow ! (
239+ "starting height {} is higher than the last finalized block height {}" ,
240+ starting_height,
241+ last_header. height
242+ ) ) ;
243+ }
244+
245+ // Construct a commit list starting from the block commit of the `starting_height`
246+ // to the `last_header_commit`(the most recent commit of the `finalized` branch)
247+ let inital_commit_hash = self . raw . get_initial_commit ( ) . await ?;
248+ let last_header_commit = self . raw . locate_branch ( FINALIZED_BRANCH_NAME . into ( ) ) . await ?;
249+ let all_commits = read_commits ( self , inital_commit_hash, last_header_commit) . await ?;
250+ let starting_block_commit_position = all_commits
251+ . iter ( )
252+ . position ( |( commit, _) | {
253+ if let Commit :: Block ( block_header) = commit {
254+ block_header. height == starting_height
255+ } else {
256+ false
257+ }
258+ } )
259+ . ok_or_else ( || {
260+ anyhow ! (
261+ "cannot find the commit of the block at height {}" ,
262+ starting_height
263+ )
264+ } ) ?;
265+ let commits = all_commits
266+ . into_iter ( )
267+ . skip ( starting_block_commit_position)
268+ . collect :: < Vec < _ > > ( ) ;
269+
270+ // TODO: Get the reserved state of the `starting_height` block and verify.
271+ // to check the canonical history of the `finalized` branch
272+ // Note that whether the reserved state in a valid format is also checked
273+ // by the `CommitSequenceVerifier`. (See #166)
274+ // TODO: Check the existence of merge commits
275+ for ( commit, commit_hash) in commits {
276+ // Check all the reserved branches
277+ let branches = self . raw . get_branches ( commit_hash) . await ?;
278+ for branch in branches {
279+ match commit {
280+ Commit :: Agenda ( _) => {
281+ if branch
282+ != format ! (
283+ "a-{:?}" ,
284+ commit
285+ . to_hash256( )
286+ . to_string( )
287+ . truncate( TAG_NAME_HASH_DIGITS )
288+ )
289+ {
290+ return Ok ( false ) ;
291+ }
292+ }
293+ Commit :: AgendaProof ( _) => {
294+ if branch
295+ != format ! (
296+ "a-{:?}" ,
297+ commit
298+ . to_hash256( )
299+ . to_string( )
300+ . truncate( TAG_NAME_HASH_DIGITS )
301+ )
302+ {
303+ return Ok ( false ) ;
304+ }
305+ }
306+ Commit :: Block ( _) => {
307+ if branch
308+ != format ! (
309+ "b-{:?}" ,
310+ commit
311+ . to_hash256( )
312+ . to_string( )
313+ . truncate( TAG_NAME_HASH_DIGITS )
314+ )
315+ {
316+ return Ok ( false ) ;
317+ }
318+ }
319+ _ => {
320+ return Ok ( false ) ;
321+ }
322+ }
323+ }
324+
325+ // Check all the reserved tags
326+ let tags = self . raw . get_tag ( commit_hash) . await ?;
327+ for tag in tags {
328+ match commit {
329+ Commit :: Agenda ( _) => {
330+ if tag
331+ != format ! (
332+ "vote-{:?}" ,
333+ commit
334+ . to_hash256( )
335+ . to_string( )
336+ . truncate( TAG_NAME_HASH_DIGITS )
337+ )
338+ {
339+ return Ok ( false ) ;
340+ }
341+ }
342+ Commit :: Block ( _) => {
343+ if tag
344+ != format ! (
345+ "veto-{:?}" ,
346+ commit
347+ . to_hash256( )
348+ . to_string( )
349+ . truncate( TAG_NAME_HASH_DIGITS )
350+ )
351+ {
352+ return Ok ( false ) ;
353+ }
354+ }
355+ _ => {
356+ return Ok ( false ) ;
357+ }
358+ }
359+ }
360+ }
361+
362+ Ok ( true )
236363 }
237364
238365 /// Synchronizes the `finalized` branch to the given commit.
0 commit comments