diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index 71669a0a6..60b52fba0 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -276,6 +276,11 @@ int32_t CC_vinselect(int32_t *aboveip,int64_t *abovep,int32_t *belowip,int64_t * abovei = belowi = -1; for (above=below=i=0; i 500 ) { + // if ( (rand() % 100) < 80 ) + // continue; + //} if ( (atx_value= utxos[i].nValue) <= 0 ) continue; if ( atx_value == value ) diff --git a/src/cc/dice.cpp b/src/cc/dice.cpp index 67d251bcc..7e013ffe2 100644 --- a/src/cc/dice.cpp +++ b/src/cc/dice.cpp @@ -443,7 +443,6 @@ bool DiceVerifyTimeout(CTransaction &betTx,int32_t timeoutblocks) bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx) { uint256 txid,fundingtxid,vinfundingtxid,vinhentropy,vinproof,hashBlock,hash,proof,entropy; int64_t minbet,maxbet,maxodds,timeoutblocks,odds,winnings; uint64_t vinsbits,sbits,amount,inputs,outputs,txfee=10000; int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,iswin; uint8_t funcid; CScript fundingPubKey; CTransaction fundingTx,vinTx,vinofvinTx; char CCaddr[64]; - CBlockIndex block; int skipped = 0; numvins = tx.vin.size(); numvouts = tx.vout.size(); preventCCvins = preventCCvouts = -1; @@ -542,19 +541,13 @@ bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx) //vin.3+: funding CC vout.0 from 'F', 'E', 'W', 'L' or 'T' //vout.1: tag to owner address for entropy funds preventCCvouts = 1; - CBlockIndex block; DiceAmounts(inputs,outputs,cp,eval,tx,sbits,fundingtxid); if ( IsCCInput(tx.vin[1].scriptSig) == 0 || IsCCInput(tx.vin[2].scriptSig) == 0 ) return eval->Invalid("vin0 or vin1 normal vin for bet"); else if ( tx.vin[1].prevout.hash != tx.vin[2].prevout.hash ) return eval->Invalid("vin0 != vin1 prevout.hash for bet"); - else if ( eval->GetTxUnconfirmed(tx.vin[1].prevout.hash,vinTx,hashBlock) == 0 ) { - char str[65],str2[65],str3[65]; - fprintf(stderr, "txid.%s tx.%s hashBlock.%s\n",uint256_str(str,txid),uint256_str(str2,tx.vin[1].prevout.hash),uint256_str(str3,hashBlock)); - //return eval->Invalid("always should find looking vin.0, but didnt for wlt"); - skipped = 1; - } else if (hashBlock.IsNull() || !eval->GetBlock(hashBlock, block)) - return eval->Invalid(" TX not confirmed! always should find vin.0, but didnt for wlt"); + else if ( eval->GetTxUnconfirmed(tx.vin[1].prevout.hash,vinTx,hashBlock) == 0 ) + return eval->Invalid("always should find looking vin.0, but didnt for wlt"); else if ( vinTx.vout.size() < 3 || DecodeDiceOpRet(tx.vin[1].prevout.hash,vinTx.vout[vinTx.vout.size()-1].scriptPubKey,vinsbits,vinfundingtxid,vinhentropy,vinproof) != 'B' ) return eval->Invalid("not betTx for vin0/1 for wlt"); else if ( sbits != vinsbits || fundingtxid != vinfundingtxid ) @@ -576,30 +569,27 @@ bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx) } else { - if ( skipped == 0 ) + //vout.0: funding CC change to entropy owner + //vout.2: normal output to bettor's address + //vout.n-1: opreturn 'W' sbits fundingtxid hentropy proof + odds = vinTx.vout[2].nValue - txfee; + if ( ConstrainVout(tx.vout[0],1,cp->unspendableCCaddr,0) == 0 ) + return eval->Invalid("vout[0] != inputs-txfee for win/timeout"); + else if ( tx.vout[2].scriptPubKey != vinTx.vout[2].scriptPubKey ) + return eval->Invalid("vout[2] scriptPubKey mismatch for win/timeout"); + else if ( tx.vout[2].nValue != (odds+1)*vinTx.vout[1].nValue ) + return eval->Invalid("vout[2] payut mismatch for win/timeout"); + else if ( inputs != (outputs + tx.vout[2].nValue) && inputs != (outputs + tx.vout[2].nValue+txfee) ) { - //vout.0: funding CC change to entropy owner - //vout.2: normal output to bettor's address - //vout.n-1: opreturn 'W' sbits fundingtxid hentropy proof - odds = vinTx.vout[2].nValue - txfee; - if ( ConstrainVout(tx.vout[0],1,cp->unspendableCCaddr,0) == 0 ) - return eval->Invalid("vout[0] != inputs-txfee for win/timeout"); - else if ( tx.vout[2].scriptPubKey != vinTx.vout[2].scriptPubKey ) - return eval->Invalid("vout[2] scriptPubKey mismatch for win/timeout"); - else if ( tx.vout[2].nValue != (odds+1)*vinTx.vout[1].nValue ) - return eval->Invalid("vout[2] payut mismatch for win/timeout"); - else if ( inputs != (outputs + tx.vout[2].nValue) && inputs != (outputs + tx.vout[2].nValue+txfee) ) - { - fprintf(stderr,"inputs %.8f != outputs %.8f + %.8f\n",(double)inputs/COIN,(double)outputs/COIN,(double)tx.vout[2].nValue/COIN); - return eval->Invalid("CC funds mismatch for win/timeout"); - } - else if ( tx.vout[3].scriptPubKey != fundingPubKey ) - { - if ( tx.vout[3].scriptPubKey.size() == 0 || ((uint8_t *)tx.vout[3].scriptPubKey.data())[0] != 0x6a ) - return eval->Invalid("vout[3] not send to fundingPubKey for win/timeout"); - } - iswin = (funcid == 'W'); + fprintf(stderr,"inputs %.8f != outputs %.8f + %.8f\n",(double)inputs/COIN,(double)outputs/COIN,(double)tx.vout[2].nValue/COIN); + return eval->Invalid("CC funds mismatch for win/timeout"); } + else if ( tx.vout[3].scriptPubKey != fundingPubKey ) + { + if ( tx.vout[3].scriptPubKey.size() == 0 || ((uint8_t *)tx.vout[3].scriptPubKey.data())[0] != 0x6a ) + return eval->Invalid("vout[3] not send to fundingPubKey for win/timeout"); + } + iswin = (funcid == 'W'); } if ( iswin != 0 ) { diff --git a/src/main.cpp b/src/main.cpp index 11df78609..34492dc9f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -92,6 +92,7 @@ unsigned int expiryDelta = DEFAULT_TX_EXPIRY_DELTA; CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE); CTxMemPool mempool(::minRelayTxFee); +CTxMemPool tmpmempool(::minRelayTxFee); struct COrphanTx { CTransaction tx; @@ -1309,7 +1310,7 @@ CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowF } -bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,bool* pfMissingInputs, bool fRejectAbsurdFee) +bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,bool* pfMissingInputs, bool fRejectAbsurdFee, bool fNullifiers) { AssertLockHeld(cs_main); if (pfMissingInputs) @@ -1390,14 +1391,17 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa return false; } } - BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) + if (fNullifiers == false) { - BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) + BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { - if (pool.mapNullifiers.count(nf)) + BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) { - fprintf(stderr,"pool.mapNullifiers.count\n"); - return false; + if (pool.mapNullifiers.count(nf)) + { + fprintf(stderr,"pool.mapNullifiers.count\n"); + return false; + } } } } @@ -1450,12 +1454,14 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } } // are the joinsplit's requirements met? - if (!view.HaveJoinSplitRequirements(tx)) + if ( fNullifiers == true ) { - //fprintf(stderr,"accept failure.2\n"); - return state.Invalid(error("AcceptToMemoryPool: joinsplit requirements not met"),REJECT_DUPLICATE, "bad-txns-joinsplit-requirements-not-met"); + if (!view.HaveJoinSplitRequirements(tx)) + { + //fprintf(stderr,"accept failure.2\n"); + return state.Invalid(error("AcceptToMemoryPool: joinsplit requirements not met"),REJECT_DUPLICATE, "bad-txns-joinsplit-requirements-not-met"); + } } - // Bring the best block into scope view.GetBestBlock(); @@ -1697,7 +1703,7 @@ bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlo } } //fprintf(stderr,"check disk\n"); - + if (fTxIndex) { CDiskTxPos postx; //fprintf(stderr,"ReadTxIndex\n"); @@ -4247,6 +4253,17 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C { CValidationState stateDummy; int32_t i,j,rejects=0,lastrejects=0; //fprintf(stderr,"put block's tx into mempool\n"); + // Copy the mempool to temporary mempool because there can be tx in local mempool that make the block invalid. + LOCK(mempool.cs); + BOOST_FOREACH(const CTxMemPoolEntry& e, mempool.mapTx) { + const CTransaction &tx = e.GetTx(); + const uint256 &hash = tx.GetHash(); + tmpmempool.addUnchecked(hash,e,!IsInitialBlockDownload()); + fprintf(stderr, "added mempool tx to temp mempool\n"); + } + // clear the mempool before importing all block txs to mempool. + mempool.clear(); + // add all the txs in the block to the empty mempool. while ( 1 ) { for (i=0; i