diff --git a/src/cc/rewards.cpp b/src/cc/rewards.cpp index bd5a6d919..b9f4677be 100644 --- a/src/cc/rewards.cpp +++ b/src/cc/rewards.cpp @@ -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"); diff --git a/src/cc/sudoku.cpp b/src/cc/sudoku.cpp index 5968f59d9..7cff6b280 100644 --- a/src/cc/sudoku.cpp +++ b/src/cc/sudoku.cpp @@ -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 list; + int32_t i,solvetime,diff,avetime,n = 0,retval = 0; uint64_t variance = 0; std::vector 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>>>>>>>>>>>>>> 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 vopret; uint8_t *script,e,f; std::string str; std::vector 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 vopret; uint8_t *script,e,f; std::vector 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 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"); } + diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index b3248d7d4..f638afa8a 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -1190,6 +1190,8 @@ uint64_t komodo_commission(const CBlock *pblock,int32_t height) n = pblock->vtx[i].vout.size(); for (j=0; j 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;