]> git.sesse.net Git - freerainbowtables/blob - BOINC software/BOINC server apps/distrrtgen_validator/validate_util2.cpp
initial
[freerainbowtables] / BOINC software / BOINC server apps / distrrtgen_validator / validate_util2.cpp
1 // This file is part of BOINC.
2 // http://boinc.berkeley.edu
3 // Copyright (C) 2008 University of California
4 //
5 // BOINC is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU Lesser General Public License
7 // as published by the Free Software Foundation,
8 // either version 3 of the License, or (at your option) any later version.
9 //
10 // BOINC is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 // See the GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with BOINC.  If not, see <http://www.gnu.org/licenses/>.
17
18 // Simple validator framework:
19 // Lets you create a custom validator by supplying three functions.
20 // See http://boinc.berkeley.edu/trac/wiki/ValidationSimple
21 //
22
23 #include "config.h"
24 #include <vector>
25 #include <cstdlib>
26 #include <string>
27
28 #include "boinc_db.h"
29 #include "error_numbers.h"
30
31 #include "sched_config.h"
32 #include "sched_msgs.h"
33
34 #include "validator.h"
35 #include "validate_util.h"
36 #include "validate_util2.h"
37 #include "ChainWalkContext.h"
38 #include "Public.h"
39 #include "part_validator.h"
40
41 using std::vector;
42
43 // Given a set of results, check for a canonical result,
44 // i.e. a set of at least min_quorum/2+1 results for which
45 // that are equivalent according to check_pair().
46 //
47 // invariants:
48 // results.size() >= wu.min_quorum
49 // for each result:
50 //   result.outcome == SUCCESS
51 //   result.validate_state == INIT
52 //
53 int check_set(
54     vector<RESULT>& results, WORKUNIT& wu,
55     int& canonicalid, double& credit, bool& retry
56 ) {
57     DB_CONN frt;
58     char query[1024];
59     MYSQL_RES* resp;
60     MYSQL_ROW row;
61     int retval = frt.open("rainbowtables-distrrtgen", config.db_host, config.db_user, config.db_passwd);
62     if (retval) {
63         log_messages.printf(MSG_CRITICAL, "can't open db rainbowtables-distrrtgen\n");
64          return retry = true;
65     }
66     log_messages.printf(MSG_DEBUG, "Validating WU %i\n", wu.id);
67     
68     vector<void *> data;
69     vector<bool> had_error;
70     int i, j, neq = 0, n;
71     int min_valid = wu.min_quorum/2+1;
72
73     retry = false;
74     n = results.size();
75     data.resize(n);
76     had_error.resize(n);
77
78     // Initialize results
79
80     for (i=0; i<n; i++) {
81 //        data[i] = "";
82         had_error[i] = false;
83     }
84     int good_results = 0;
85     for (i=0; i<n; i++) {
86         retval = init_result(results[i], data[i]);
87         if (retval == ERR_OPENDIR) {
88             log_messages.printf(MSG_CRITICAL,
89                 "check_set: init_result([RESULT#%d %s]) transient failure\n",
90                 results[i].id, results[i].name
91             );
92             had_error[i] = true;
93         } else if (retval) {
94             log_messages.printf(MSG_CRITICAL,
95                 "check_set: init_result([RESULT#%d %s]) failed: %d\n",
96                 results[i].id, results[i].name, retval
97             );
98             results[i].outcome = RESULT_OUTCOME_VALIDATE_ERROR;
99             results[i].validate_state = VALIDATE_STATE_INVALID;
100             had_error[i] = true;
101         } else  {
102             log_messages.printf(MSG_DEBUG, "check_set: init_result([RESULTÂ#%d %s]) fie is ok\n", results[i].id, results[i].name);
103             good_results++;
104
105         }
106     }
107     if (good_results < wu.min_quorum) {
108         log_messages.printf(MSG_DEBUG, "good_results < wu.min_quorum (%d < %d)", good_results, wu.min_quorum);
109         goto cleanup;
110         }
111     // Compare results
112
113     for (i=0; i<n; i++) {
114         if (had_error[i]) continue;
115         vector<bool> matches;
116         matches.resize(n);
117         neq = 0;
118         RainbowPartFile *curData = (RainbowPartFile*)data[i];
119         const char *pos = strchr(results[i].name, ' ');
120         char partnum[256] = {0};
121         strncpy(partnum, results[i].name, pos - results[i].name);
122         int partid = atoi(partnum);
123         sprintf(query, "SELECT t.PartSize, t.HashRoutine, t.Charset, t.MinLetters, t.MaxLetters, t.Index, t.ChainLength, p.ChainStart, t.Credits FROM generator_parts p INNER JOIN generator_tables t ON t.TableID = p.TableID WHERE p.PartID = %i", partid);
124         retval = frt.do_query(query);
125         if(retval)  {
126                 retry = true;
127                 log_messages.printf(MSG_CRITICAL, "Error executing query '%s'", query);
128                 goto cleanup;
129         }
130         resp = mysql_store_result(frt.mysql);
131         if (!resp) {
132                 log_messages.printf(MSG_CRITICAL, "Error doing mysql_store_result()");
133                 retry = true;
134                 goto cleanup;
135         }
136         row = mysql_fetch_row(resp);
137         if (!row) { 
138                 log_messages.printf(MSG_CRITICAL, "mysql row not found for query '%s'", query);
139                 retry = true;
140                 goto cleanup;
141         }
142         int PartSize = atoi(row[0]);
143         log_messages.printf(MSG_DEBUG, "Starting verification...\n");
144         log_messages.printf(MSG_DEBUG, "Num chains: %i PartSize: %i...\n", curData->numchains, PartSize);
145          
146          if(curData->numchains != PartSize)
147          {              
148                 log_messages.printf(MSG_CRITICAL,
149                     "[RESULT#%d %s] File size doesn't match. Expectected %i, but got %i chains\n",
150                     results[i].id, results[i].name, PartSize, curData->numchains
151                 );
152             results[i].outcome = RESULT_OUTCOME_VALIDATE_ERROR;
153             results[i].validate_state = VALIDATE_STATE_INVALID;         
154              break;
155          }
156         log_messages.printf(MSG_DEBUG, "Converting %i %s %s %s %s %s %s %s %s...\n", partid, row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]);
157         
158          string sHashRoutineName = row[1];
159          string sCharsetName = row[2];
160         int nPlainLenMin = atoi(row[3]);
161          int nPlainLenMax = atoi(row[4]);
162         int nRainbowTableIndex = atoi(row[5]);
163          int nRainbowChainLen = atoi(row[6]);
164     mysql_free_result(resp);
165
166          uint64 nChainStartPosition = atoll(row[7]);
167          float creditvalue = atof(row[8]);
168         log_messages.printf(MSG_DEBUG, "Setting hash routine to %s...\n", sHashRoutineName.c_str());
169          if (!CChainWalkContext::SetHashRoutine(sHashRoutineName))
170          {
171                 log_messages.printf(MSG_CRITICAL,"[RESULT#%d %s]hash routine %s not supported\n", results[i].id, results[i].name, sHashRoutineName.c_str());
172               results[i].outcome = RESULT_OUTCOME_VALIDATE_ERROR;
173               results[i].validate_state = VALIDATE_STATE_INVALID;                                       
174                 break;
175          }
176         log_messages.printf(MSG_DEBUG, "Setting charset to %s (%i-%i)...\n", sCharsetName.c_str(), nPlainLenMin, nPlainLenMax);
177          if (!CChainWalkContext::SetPlainCharset(sCharsetName, nPlainLenMin, nPlainLenMax))
178          {
179                 log_messages.printf(MSG_CRITICAL,"[RESULT#%d %s]charset %s (%i - %i) not supported\n", results[i].id, results[i].name, sCharsetName.c_str(), nPlainLenMin, nPlainLenMax);
180               results[i].outcome = RESULT_OUTCOME_VALIDATE_ERROR;
181               results[i].validate_state = VALIDATE_STATE_INVALID;                                       
182                 break;
183          }
184         log_messages.printf(MSG_DEBUG, "Setting index to %i...\n", nRainbowTableIndex);
185
186          if (!CChainWalkContext::SetRainbowTableIndex(nRainbowTableIndex))
187          {
188                 log_messages.printf(MSG_CRITICAL,"[RESULT#%d %s]invalid rainbow table index %d\n", results[i].id, results[i].name, nRainbowTableIndex);
189               results[i].outcome = RESULT_OUTCOME_VALIDATE_ERROR;
190               results[i].validate_state = VALIDATE_STATE_INVALID;                                       
191                 break;
192          }
193          RainbowChainCP *pChain = curData->pChain;
194          int nRainbowChainCountRead = curData->numchains;
195                                                 // Chain length test
196         for(j = 1; j <= 25; j++)
197         {
198                 int nIndexToVerify = nRainbowChainCountRead / 25 * j - 1;
199                 CChainWalkContext cwc;
200         log_messages.printf(MSG_DEBUG, "Setting seed to %lld for verification step %i...\n", pChain[nIndexToVerify].nIndexS, j);
201
202                 cwc.SetIndex(pChain[nIndexToVerify].nIndexS);
203                 int nPos;
204                 for (nPos = 0; nPos < nRainbowChainLen - 1; nPos++)
205                 {
206                         cwc.IndexToPlain();
207                         cwc.PlainToHash();
208                         cwc.HashToIndex(nPos);
209                 }
210                 
211                 if (cwc.GetIndex() != pChain[nIndexToVerify].nIndexE)
212                 {
213                         log_messages.printf(MSG_CRITICAL,
214                                 "[RESULT#%d %s] Rainbow chain length verification failed at step %i index %i (%lld != %lld)\n", results[i].id, results[i].name, j, nIndexToVerify, cwc.GetIndex(), pChain[nIndexToVerify].nIndexE);
215                       results[i].outcome = RESULT_OUTCOME_VALIDATE_ERROR;
216                      results[i].validate_state = VALIDATE_STATE_INVALID;                
217                         break;
218                 }
219         }
220         if(results[i].outcome == RESULT_OUTCOME_VALIDATE_ERROR && results[i].validate_state == VALIDATE_STATE_INVALID) break;
221         log_messages.printf(MSG_DEBUG, "Checking if all %i chains is within bounds...\n", PartSize);
222
223         for(j = 0; j < PartSize; j++)
224         {
225                 if(pChain[j].nIndexS < (nChainStartPosition - 500000) ||  pChain[j].nIndexS > (nChainStartPosition + PartSize))
226                 {
227                         log_messages.printf(MSG_CRITICAL,
228                         "[RESULT#%d %s] Start index verification failed at step %i with number %llu. (< %llu | > %llu)\n", results[i].id, results[i].name, j, pChain[j].nIndexS, nChainStartPosition, (nChainStartPosition + PartSize));
229                       results[i].outcome = RESULT_OUTCOME_VALIDATE_ERROR;
230                      results[i].validate_state = VALIDATE_STATE_INVALID;                
231                         break;
232                 }
233                 if(j > 0 && pChain[j].nIndexE < pChain[j-1].nIndexE)
234                 {
235                         log_messages.printf(MSG_CRITICAL,
236                         "[RESULT#%d %s] Chain sort test failed at step %i with number %llu < %llu\n", results[i].id, results[i].name, j, pChain[j].nIndexE, pChain[j-1].nIndexE);
237                       results[i].outcome = RESULT_OUTCOME_VALIDATE_ERROR;
238                      results[i].validate_state = VALIDATE_STATE_INVALID;                
239                         break;
240                 }
241         }
242         if(results[i].outcome == RESULT_OUTCOME_VALIDATE_ERROR && results[i].validate_state == VALIDATE_STATE_INVALID) break;
243
244         results[i].validate_state = VALIDATE_STATE_VALID;
245        canonicalid = results[i].id;     
246         credit = creditvalue;
247        log_messages.printf(MSG_DEBUG, "WU %i is OK\n", wu.id);
248          /*
249         for (j=0; j!=n; j++) {
250             if (had_error[j]) continue;
251             bool match = false;
252             if (i == j) {
253                 ++neq;
254                 matches[j] = true;
255             } else if (compare_results(results[i], data[i], results[j], data[j], match)) {
256                 log_messages.printf(MSG_CRITICAL,
257                     "generic_check_set: check_pair_with_data([RESULT#%d %s], [RESULT#%d %s]) failed\n",
258                     results[i].id, results[i].name, results[j].id, results[j].name
259                 );
260             } else if (match) {
261                 ++neq;
262                 matches[j] = true;
263             }
264         }
265         if (neq >= min_valid) {
266
267             // set validate state for each result
268             //
269             for (j=0; j!=n; j++) {
270                 if (had_error[j]) continue;
271                 if (max_claimed_credit && results[j].claimed_credit > max_claimed_credit) {
272                     results[j].validate_state = VALIDATE_STATE_INVALID;
273                 } else {
274                     results[j].validate_state = matches[j] ? VALIDATE_STATE_VALID : VALIDATE_STATE_INVALID;
275                 }
276             }
277             canonicalid = results[i].id;
278             credit = compute_granted_credit(wu, results);
279             break;
280         }*/
281     }
282
283 cleanup:
284
285     for (i=0; i<n; i++) {
286         cleanup_result(results[i], data[i]);
287     }
288     frt.close();
289 //      exit(0);
290     return 0;
291 }
292
293 // r1 is the new result; r2 is canonical result
294 //
295
296 /*
297 void check_pair(RESULT& r1, RESULT& r2, bool& retry) {
298     string data1;
299     string data2;
300     int retval;
301     bool match;
302
303     retry = false;
304     retval = init_result(r1, data1);
305     if (retval == ERR_OPENDIR) {
306         log_messages.printf(MSG_CRITICAL,
307             "check_pair: init_result([RESULT#%d %s]) transient failure 1\n",
308             r1.id, r1.name
309         );
310         retry = true;
311         return;
312     } else if (retval) {
313         log_messages.printf(MSG_CRITICAL,
314             "check_pair: init_result([RESULT#%d %s]) perm failure 1\n",
315             r1.id, r1.name
316         );
317         r1.outcome = RESULT_OUTCOME_VALIDATE_ERROR;
318         r1.validate_state = VALIDATE_STATE_INVALID;
319         return;
320     }
321
322     retval = init_result(r2, data2);
323     if (retval == ERR_OPENDIR) {
324         log_messages.printf(MSG_CRITICAL,
325             "check_pair: init_result([RESULT#%d %s]) transient failure 2\n",
326             r2.id, r2.name
327         );
328         cleanup_result(r1, data1);
329         retry = true;
330         return;
331     } else if (retval) {
332         log_messages.printf(MSG_CRITICAL,
333             "check_pair: init_result([RESULT#%d %s]) perm failure2\n",
334             r2.id, r2.name
335         );
336         cleanup_result(r1, data1);
337         r1.outcome = RESULT_OUTCOME_VALIDATE_ERROR;
338         r1.validate_state = VALIDATE_STATE_INVALID;
339         return;
340     }
341
342     retval = compare_results(r1, data1, r2, data2, match);
343     if (max_claimed_credit && r1.claimed_credit > max_claimed_credit) {
344         r1.validate_state = VALIDATE_STATE_INVALID;
345     } else {
346         r1.validate_state = match?VALIDATE_STATE_VALID:VALIDATE_STATE_INVALID;
347     }
348     cleanup_result(r1, data1);
349     cleanup_result(r2, data2);
350 }
351
352 */