Merge pull request #1225 from jl777/jl777

initial sudoku validation
This commit is contained in:
jl777
2019-01-31 02:55:08 -11:00
committed by GitHub
3 changed files with 189 additions and 30 deletions

View File

@@ -203,7 +203,7 @@ bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t
else
{
txid = tx.GetHash();
if ( (funcid= DecodeRewardsOpRet(txid,tx.vout[numvouts-1].scriptPubKey,sbits,fundingtxid)) != 0 )
if ( (funcid= DecodeRewardsOpRet(txid,tx.vout[numvouts-1].scriptPubKey,sbits,fundingtxid)) != 0 )
{
if ( eval->GetTxUnconfirmed(fundingtxid,fundingTx,hashBlock) == 0 )
return eval->Invalid("cant find fundingtxid");

View File

@@ -1773,7 +1773,7 @@ static char *cvt_to_mask(char *mbuf, char *sbuf)
/* Mainline logic. */
/*******************/
int dupree_solver(int32_t *scorep,char *puzzle)
int dupree_solver(int32_t dispflag,int32_t *scorep,char *puzzle)
{
int argc; char *argv[4];
int i, rc, bog, count, solved, unsolved, solncount=0, flag, prt_count, prt_num, prt_score, prt_answer, prt_depth, prt_grid, prt_mask, prt_givens, prt, len;
@@ -1781,12 +1781,13 @@ int dupree_solver(int32_t *scorep,char *puzzle)
grid g, *s=0;
FILE *h=0;
soln_list = NULL;
/* Get our command name from invoking command line */
myname = (char *)"internal";
/* Get our command name from invoking command line
if ((myname = strrchr(argv[0], '/')) == NULL)
myname = argv[0];
else
myname++;
/*argc = 3;
argc = 3;
argv[1] = "-p";
argv[2] = puzzle;
argv[3] = 0;*/
@@ -1872,15 +1873,6 @@ int dupree_solver(int32_t *scorep,char *puzzle)
exit(1);
}
}
#endif
prt_answer = 1; /* print solution */
//prt_count = 1; /* number solutions */
prt_score = 1;
prt_givens = 1;
prt_num = 1;
/* Set prt flag if we're printing anything at all */
prt = prt_mask | prt_grid | prt_score | prt_depth | prt_answer | prt_num | prt_givens;
/* Anthing else on the command line is bogus */
if (argc > optind) {
fprintf(stderr, "Extraneous args: ");
@@ -1911,6 +1903,15 @@ int dupree_solver(int32_t *scorep,char *puzzle)
exit(1);
}
if (h) fgets(inbuf, 128, h);*/
#endif
prt_answer = dispflag; /* print solution */
//prt_count = dispflag; /* number solutions */
prt_score = dispflag;
prt_givens = dispflag;
prt_num = dispflag;
/* Set prt flag if we're printing anything at all */
prt = prt_mask | prt_grid | prt_score | prt_depth | prt_answer | prt_num | prt_givens;
strcpy(inbuf,puzzle);
count = solved = unsolved = 0;
//printf("inbuf.(%s)\n",inbuf);
@@ -1926,7 +1927,7 @@ int dupree_solver(int32_t *scorep,char *puzzle)
fprintf(rejects, "%d: %s bogus puzzle format\n", count, inbuf); fflush(rejects);
*inbuf = 0;
bog += 1;
if (h) fgets(inbuf, 128, h);
//if (h) fgets(inbuf, 128, h);
continue;
}
@@ -1935,7 +1936,7 @@ int dupree_solver(int32_t *scorep,char *puzzle)
fprintf(rejects, "%d: %*.*s bogus puzzle has less than 17 givens\n", count, PUZZLE_CELLS, PUZZLE_CELLS, inbuf); fflush(rejects);
*inbuf = 0;
bog += 1;
if (h) fgets(inbuf, 128, h);
//if (h) fgets(inbuf, 128, h);
continue;
}
@@ -1972,6 +1973,11 @@ int dupree_solver(int32_t *scorep,char *puzzle)
if (solncount > 1 && enumerate_all) {
rc |= 1;
}
for (s = soln_list; s;) {
s = soln_list->next;
free(soln_list);
soln_list = s;
}
}
else {
unsolved++;
@@ -1984,7 +1990,7 @@ int dupree_solver(int32_t *scorep,char *puzzle)
}
*inbuf = 0;
if (h) fgets(inbuf, 128, h);
//if (h) fgets(inbuf, 128, h);
}
//if (prt) fprintf(solnfile, "\nPuzzles: %d, Solved: %d, Unsolved: %d, Bogus: %d\n", count, solved, unsolved, bog);
@@ -2511,9 +2517,9 @@ void sudoku_gen(uint8_t key32[32],uint8_t unsolved[9][9],uint32_t srandi)
cclib solution 17 \"[%224d50336780d5a300a1f01b12fe36f46a82f3b9935bb115e01e0113dc4f337aae%22,%22234791685716258943589643712865934127341827596927516438492375861178462359653189274%22,0,0,1548859143,1548859146,0,1548859146,0,1548859148,1548859149,0,1548859151,1548859152,0,1548859154,1548859155,1548859158,1548859159,0,0,0,1548859161,1548859163,0,1548859164,1548859168,0,1548859168,1548859170,1548859172,1548859172,1548859175,0,0,1548859176,0,0,1548859178,1548859178,0,0,1548859180,1548859181,1548859183,1548859184,1548859185,1548859186,1548859188,1548859190,1548859191,1548859192,1548859192,0,0,1548859195,1548859196,1548859197,1548859198,0,0,1548859199,1548859202,1548859202,0,1548859204,1548859205,1548859206,1548859209,1548859210,1548859211,1548859212,0,1548859214,1548859216,0,1548859217,1548859218,1548859219,1548859220,0,1548859222,1548859222]\"
*/
int32_t sudoku_captcha(uint32_t timestamps[81])
int32_t sudoku_captcha(int32_t dispflag,uint32_t timestamps[81],int32_t height)
{
int32_t i,solvetime,diff,avetime,n = 0; uint64_t variance = 0; std::vector<uint32_t> list;
int32_t i,solvetime,diff,avetime,n = 0,retval = 0; uint64_t variance = 0; std::vector<uint32_t> list;
for (i=0; i<81; i++)
{
if ( timestamps[i] != 0 )
@@ -2529,31 +2535,38 @@ int32_t sudoku_captcha(uint32_t timestamps[81])
if ( list[0] >= list[n-1] )
{
printf("list[0] %u vs list[%d-1] %u\n",list[0],n,list[n-1]);
return(-1);
retval = -1;
}
else if ( list[n-1] > chainActive.LastTip()->nTime+200 )
return(-1);
retval = -2;
else if ( solvetime >= 777 )
return(0);
retval = 0;
else
{
avetime = (solvetime / (n-1));
if ( avetime == 0 )
return(-1);
retval = -3;
for (i=0; i<n-1; i++)
{
diff = (list[i+1] - list[i]);
printf("%d ",diff);
if ( dispflag != 0 )
printf("%d ",diff);
diff -= avetime;
variance += (diff * diff);
}
variance /= (n - 1);
printf("solvetime.%d n.%d avetime.%d variance.%llu vs ave2 %d\n",solvetime,n,avetime,(long long)variance,avetime*avetime);
if ( variance < avetime*avetime )
return(-1 * 0);
if ( dispflag != 0 )
printf("solvetime.%d n.%d avetime.%d variance.%llu vs ave2 %d\n",solvetime,n,avetime,(long long)variance,avetime*avetime);
if ( variance < avetime )
retval = -5;
else return(0);
}
} else return(-1);
} else retval = -6;
if ( dispflag != 0 && retval != 0 )
fprintf(stderr,"ERR >>>>>>>>>>>>>>> ht.%d retval.%d\n",height,retval);
if ( height <= 2036 )
return(0);
else return(retval);
}
CScript sudoku_genopret(uint8_t unsolved[9][9])
@@ -2580,6 +2593,33 @@ CScript sudoku_solutionopret(char *solution,uint32_t timestamps[81])
return(opret);
}
uint8_t sudoku_solutionopreturndecode(char solution[82],uint32_t timestamps[81],CScript scriptPubKey)
{
std::vector<uint8_t> vopret; uint8_t *script,e,f; std::string str; std::vector<uint8_t> data; int32_t i,ind; uint32_t x;
GetOpReturnData(scriptPubKey,vopret);
script = (uint8_t *)vopret.data();
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> str; ss >> data) != 0 && e == EVAL_SUDOKU && f == 'S' )
{
if ( data.size() == 81*sizeof(uint32_t) && str.size() == 81 )
{
strcpy(solution,str.c_str());
for (i=ind=0; i<81; i++)
{
if ( solution[i] < '1' || solution[i] > '9' )
break;
x = data[ind++];
x <<= 8, x |= (data[ind++] & 0xff);
x <<= 8, x |= (data[ind++] & 0xff);
x <<= 8, x |= (data[ind++] & 0xff);
timestamps[i] = x;
}
if ( i == 81 )
return(f);
} else fprintf(stderr,"datasize %d sol[%d]\n",(int32_t)data.size(),(int32_t)str.size());
}
return(0);
}
uint8_t sudoku_genopreturndecode(char *unsolved,CScript scriptPubKey)
{
std::vector<uint8_t> vopret; uint8_t *script,e,f; std::vector<uint8_t> data; int32_t i;
@@ -2628,7 +2668,7 @@ UniValue sudoku_generate(uint64_t txfee,struct CCcontract_info *cp,cJSON *params
str[i] = '0' + unsolved[i/9][i%9];
str[i] = 0;
printf("solve: %s\n",str);
if ( dupree_solver(&score,str) == 1 )
if ( dupree_solver(1,&score,str) == 1 )
{
amount = score * COIN;
break;
@@ -2825,7 +2865,7 @@ UniValue sudoku_solution(uint64_t txfee,struct CCcontract_info *cp,cJSON *params
result.push_back(Pair("sudokuaddr",CCaddr));
balance = CCaddress_balance(CCaddr);
result.push_back(Pair("amount",ValueFromAmount(balance)));
if ( sudoku_captcha(timestamps) < 0 )
if ( sudoku_captcha(1,timestamps,komodo_nextheight()) < 0 )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","captcha failure"));
@@ -2907,7 +2947,124 @@ UniValue sudoku_solution(uint64_t txfee,struct CCcontract_info *cp,cJSON *params
return(result);
}
int32_t sudoku_minval(uint32_t timestamps[81])
{
int32_t i,ind = -1; uint32_t mintimestamp = 0xffffffff;
for (i=0; i<81; i++)
if ( timestamps[i] != 0 && timestamps[i] < mintimestamp )
{
mintimestamp = timestamps[i], ind = i;
//fprintf(stderr,"%d ",i);
}
//fprintf(stderr,"mintimestamp.%u\n",mintimestamp);
return(ind);
}
bool sudoku_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx)
{
return(true);
static char laststr[512];
CScript scriptPubKey; std::vector<uint8_t> vopret; uint8_t *script,e,f,funcid; int32_t i,ind,errflag,dispflag,score,numvouts; char unsolved[82],solution[82],str[512]; uint32_t timestamps[81]; CTransaction vintx; uint256 hashBlock;
if ( (numvouts= tx.vout.size()) > 1 )
{
scriptPubKey = tx.vout[numvouts-1].scriptPubKey;
GetOpReturnData(scriptPubKey,vopret);
if ( vopret.size() > 2 )
{
script = (uint8_t *)vopret.data();
if ( script[0] == EVAL_SUDOKU )
{
switch ( script[1] )
{
case 'G':
if ( sudoku_genopreturndecode(unsolved,scriptPubKey) == 'G' )
{
//fprintf(stderr,"unsolved.(%s)\n",unsolved);
if ( dupree_solver(0,&score,unsolved) != 1 || score*COIN != tx.vout[1].nValue )
{
sprintf(str,"ht.%d score.%d vs %.8f %s",height,score,(double)tx.vout[1].nValue/COIN,tx.GetHash().ToString().c_str());
if ( strcmp(str,laststr) != 0 )
{
strcpy(laststr,str);
fprintf(stderr,"%s\n",str);
}
if ( strcmp(ASSETCHAINS_SYMBOL,"SUDOKU") != 0 || height > 2000 )
return eval->Invalid("mismatched sudoku value vs score");
else return(true);
} else return(true);
}
fprintf(stderr,"height.%d txid.%s\n",height,tx.GetHash().ToString().c_str());
return eval->Invalid("invalid generate opreturn");
case 'S':
sprintf(str,"SOLVED ht.%d %.8f %s",height,(double)tx.vout[0].nValue/COIN,tx.GetHash().ToString().c_str());
if ( strcmp(str,laststr) != 0 )
{
strcpy(laststr,str);
fprintf(stderr,"%s\n",str);
dispflag = 1;
} else dispflag = 0;
if ( sudoku_solutionopreturndecode(solution,timestamps,scriptPubKey) == 'S' )
{
if ( tx.vin.size() > 1 && tx.vin[0].prevout.hash == tx.vin[1].prevout.hash && tx.vin[0].prevout.n == 0 && tx.vin[1].prevout.n == 1 && myGetTransaction(tx.vin[0].prevout.hash,vintx,hashBlock) != 0 )
{
if ( vintx.vout.size() > 1 && sudoku_genopreturndecode(unsolved,vintx.vout[vintx.vout.size()-1].scriptPubKey) == 'G' )
{
for (i=errflag=0; i<81; i++)
{
if ( 0 && dispflag != 0 )
fprintf(stderr,"%u ",timestamps[i]);
if ( (timestamps[i] != 0 && unsolved[i] >= '1' && unsolved[i] <= '9') || (timestamps[i] == 0 && (unsolved[i] < '1' || unsolved[i] > '9')) )
errflag++;
}
if ( errflag != 0 )
{
if ( dispflag != 0 )
fprintf(stderr,"ht.%d errflag.%d %s\n",height,errflag,unsolved);
if ( (height != 1220 && height != 1383) || strcmp(ASSETCHAINS_SYMBOL,"SUDOKU") != 0 )
return eval->Invalid("invalid timestamp vs unsolved");
}
if ( dupree_solver(0,&score,unsolved) != 1 )
{
if ( dispflag != 0 )
fprintf(stderr,"non-unique sudoku at ht.%d\n",height);
if ( strcmp(ASSETCHAINS_SYMBOL,"SUDOKU") != 0 )
return eval->Invalid("invalid sudoku with multiple solutions");
}
if ( dispflag != 0 )
fprintf(stderr,"%s score.%d %s\n",solution,score,unsolved);
if ( sudoku_captcha(dispflag,timestamps,height) < 0 )
return eval->Invalid("failed captcha");
/*for (i=lasttime=0; i<81; i++)
{
if ( (ind= sudoku_minval(timestamps)) >= 0 )
{
unsolved[ind] = solution[ind];
if ( lasttime == 0 )
lasttime = timestamps[ind];
if ( dupree_solver(0,&score,unsolved) != 1 )
fprintf(stderr,"i.%d ind.%d non-unique\n",i,ind);
if ( dispflag != 0 )
fprintf(stderr,"%d.%d ",score,timestamps[ind]-lasttime);
lasttime = timestamps[ind];
timestamps[ind] = 0;
} else break;
}
if ( dispflag != 0 )
fprintf(stderr,"scores convergence\n");*/
return(true);
} else return eval->Invalid("invalid solution opret");
}
else if ( strcmp(ASSETCHAINS_SYMBOL,"SUDOKU") == 0 && height == 236 )
return(true);
else return eval->Invalid("invalid solution vin");
}
fprintf(stderr,"solution ht.%d %s bad opret\n",height,tx.GetHash().ToString().c_str());
return eval->Invalid("invalid solution opreturn");
default: return eval->Invalid("invalid funcid");
}
} else return eval->Invalid("invalid evalcode");
}
}
return eval->Invalid("not enough vouts");
}

View File

@@ -1190,6 +1190,8 @@ uint64_t komodo_commission(const CBlock *pblock,int32_t height)
n = pblock->vtx[i].vout.size();
for (j=0; j<n; j++)
{
if ( height > 100000 && ASSETCHAINS_STAKED != 0 && txn_count > 1 && i == txn_count-1 && n == 1 )
break;
//fprintf(stderr,"(%d %.8f).%d ",i,dstr(pblock->vtx[i].vout[j].nValue),j);
if ( i != 0 || j != 1 )
total += pblock->vtx[i].vout[j].nValue;