@@ -81,77 +81,101 @@ public void Initialize()
8181 return ;
8282 }
8383
84- this . highestPollId = ( polls . Length > 0 ) ? polls . Max ( p => p . Id ) : - 1 ;
85-
8684 Row < byte [ ] , byte [ ] > rowTip = transaction . Select < byte [ ] , byte [ ] > ( DataTable , RepositoryTipKey ) ;
85+ if ( ! rowTip . Exists )
86+ {
87+ this . logger . LogInformation ( "The polls repository tip is unknown. Will re-build the repo." ) ;
88+ this . ResetLocked ( transaction ) ;
89+ transaction . Commit ( ) ;
90+ return ;
91+ }
8792
88- if ( rowTip . Exists )
93+ this . CurrentTip = this . dBreezeSerializer . Deserialize < HashHeightPair > ( rowTip . Value ) ;
94+ if ( this . chainIndexer == null || this . chainIndexer . GetHeader ( this . CurrentTip . Hash ) != null )
8995 {
90- this . CurrentTip = this . dBreezeSerializer . Deserialize < HashHeightPair > ( rowTip . Value ) ;
91- if ( this . chainIndexer != null && this . chainIndexer . GetHeader ( this . CurrentTip . Hash ) == null )
92- this . CurrentTip = null ;
96+ this . highestPollId = ( polls . Length > 0 ) ? polls . Max ( p => p . Id ) : - 1 ;
97+ return ;
9398 }
9499
95- if ( this . CurrentTip == null )
100+ this . logger . LogInformation ( "The polls repository tip {0} was not found in the consensus chain. Determining fork." , this . CurrentTip ) ;
101+
102+ // == Find fork.
103+ // The polls repository tip could not be found in the consenus chain.
104+ // Look at all other known hash/height pairs to find something in common with the consensus chain.
105+ // We will take that as the last known valid height.
106+
107+ int maxGoodHeight = - 1 ;
108+
109+ foreach ( Poll poll in polls )
96110 {
111+ if ( poll . PollStartBlockData . Height > maxGoodHeight && this . chainIndexer . GetHeader ( poll . PollStartBlockData . Hash ) != null )
112+ maxGoodHeight = poll . PollStartBlockData . Height ;
113+ if ( poll . PollExecutedBlockData ? . Height > maxGoodHeight && this . chainIndexer . GetHeader ( poll . PollExecutedBlockData . Hash ) != null )
114+ maxGoodHeight = poll . PollStartBlockData . Height ;
115+ if ( poll . PollVotedInFavorBlockData ? . Height > maxGoodHeight && this . chainIndexer . GetHeader ( poll . PollExecutedBlockData . Hash ) != null )
116+ maxGoodHeight = poll . PollStartBlockData . Height ;
117+ }
118+
119+ if ( maxGoodHeight == - 1 )
120+ {
121+ this . logger . LogInformation ( "No common blocks found. Will rebuild the repo from scratch." ) ;
97122 this . ResetLocked ( transaction ) ;
98123 transaction . Commit ( ) ;
124+ return ;
99125 }
100- else if ( this . chainIndexer != null )
126+
127+ this . CurrentTip = new HashHeightPair ( this . chainIndexer . GetHeader ( maxGoodHeight ) ) ;
128+
129+ this . logger . LogInformation ( "Common block found at height {0}. Will re-build the repo from there." , this . CurrentTip . Height ) ;
130+
131+ // Trim polls to tip.
132+ HashSet < Poll > pollsToDelete = new HashSet < Poll > ( ) ;
133+ foreach ( Poll poll in polls )
101134 {
102- // Trim poll information to chain indexer tip.
103- ChainedHeader newTip = this . chainIndexer . Tip ;
135+ if ( poll . PollStartBlockData . Height > this . CurrentTip . Height )
136+ {
137+ pollsToDelete . Add ( poll ) ;
138+ continue ;
139+ }
104140
105- HashSet < Poll > pollsToDelete = new HashSet < Poll > ( ) ;
106- foreach ( Poll poll in polls )
141+ bool modified = false ;
142+
143+ if ( poll . PubKeysHexVotedInFavor . Any ( v => v . Height > this . CurrentTip . Height ) )
107144 {
108- if ( poll . PollStartBlockData . Height > newTip . Height )
109- {
110- pollsToDelete . Add ( poll ) ;
111- continue ;
112- }
113-
114- bool modified = false ;
115-
116- if ( poll . PubKeysHexVotedInFavor . Any ( v => v . Height > newTip . Height ) )
117- {
118- poll . PubKeysHexVotedInFavor = poll . PubKeysHexVotedInFavor . Where ( v => v . Height <= newTip . Height ) . ToList ( ) ;
119- modified = true ;
120- }
121-
122- if ( poll . PollExecutedBlockData ? . Height > newTip . Height )
123- {
124- poll . PollExecutedBlockData = null ;
125- modified = true ;
126- }
127-
128- if ( poll . PollVotedInFavorBlockData ? . Height > newTip . Height )
129- {
130- poll . PollVotedInFavorBlockData = null ;
131- modified = true ;
132- }
133-
134- if ( modified )
135- UpdatePoll ( transaction , poll ) ;
145+ poll . PubKeysHexVotedInFavor = poll . PubKeysHexVotedInFavor . Where ( v => v . Height <= this . CurrentTip . Height ) . ToList ( ) ;
146+ modified = true ;
136147 }
137148
138- DeletePollsAndSetHighestPollId ( transaction , pollsToDelete . Select ( p => p . Id ) . ToArray ( ) ) ;
149+ if ( poll . PollExecutedBlockData ? . Height > this . CurrentTip . Height )
150+ {
151+ poll . PollExecutedBlockData = null ;
152+ modified = true ;
153+ }
139154
140- SaveCurrentTip ( transaction , newTip ) ;
155+ if ( poll . PollVotedInFavorBlockData ? . Height > this . CurrentTip . Height )
156+ {
157+ poll . PollVotedInFavorBlockData = null ;
158+ modified = true ;
159+ }
141160
142- transaction . Commit ( ) ;
161+ if ( modified )
162+ UpdatePoll ( transaction , poll ) ;
143163 }
164+
165+ DeletePollsAndSetHighestPollId ( transaction , pollsToDelete . Select ( p => p . Id ) . ToArray ( ) ) ;
166+
167+ transaction . Commit ( ) ;
168+
169+ this . logger . LogDebug ( "Polls repo initialized with highest id: {0}." , this . highestPollId ) ;
144170 }
145171 catch ( Exception err ) when ( err . Message == "No more byte to read" )
146172 {
147- // The polls repository requires an upgrade.
173+ this . logger . LogWarning ( "There was an error reading the polls repository. Will rebuild it." ) ;
148174 this . ResetLocked ( transaction ) ;
149175 transaction . Commit ( ) ;
150176 }
151177 }
152178 }
153-
154- this . logger . LogDebug ( "Polls repo initialized with highest id: {0}." , this . highestPollId ) ;
155179 }
156180
157181 private void ResetLocked ( DBreeze . Transactions . Transaction transaction )
0 commit comments