diff --git a/src/cc/dice.cpp b/src/cc/dice.cpp index e456ea6ae..c5bebeba0 100644 --- a/src/cc/dice.cpp +++ b/src/cc/dice.cpp @@ -85,11 +85,11 @@ WARNING: there is an attack vector that precludes betting any large amounts, it 3. reorg the chain and make a big bet using the winning entropy calculated in 2. In order to mitigate this, the disclosure of the house entropy needs to be delayed beyond a reasonable reorg depth (notarization). It is recommended for production dice game with significant amounts of money to use such a delayed disclosure method. - + Actually a much better solution to this is possible, which allows to retain the realtime response aspect of dice CC, which is critical to its usage. - - - + + + */ #include "../compat/endian.h" @@ -552,7 +552,7 @@ bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx) 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 ) - return eval->Invalid("always should find looking vin.0, but didnt for wlt"); + return eval->Invalid("always should find 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 ) diff --git a/src/cc/eval.cpp b/src/cc/eval.cpp index 113c4a6e8..9ae6d4626 100644 --- a/src/cc/eval.cpp +++ b/src/cc/eval.cpp @@ -98,10 +98,9 @@ bool Eval::GetSpendsConfirmed(uint256 hash, std::vector &spends) c bool Eval::GetTxUnconfirmed(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) const { - // there is a LOCK(cs_main) in the normal GetTransaction(), which leads to deadlocks - //bool fAllowSlow = false; // Don't allow slow - //return GetTransaction(hash, txOut, hashBlock, fAllowSlow); - return myGetTransaction(hash, txOut,hashBlock); + if (!myGetTransaction(hash, txOut,hashBlock)) { + return(GetTransaction(hash, txOut,hashBlock)); + } else return(true); } diff --git a/src/main.cpp b/src/main.cpp index 938cfdfe0..f6c8520d8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1310,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 fNullifiers) +bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,bool* pfMissingInputs, bool fRejectAbsurdFee) { AssertLockHeld(cs_main); if (pfMissingInputs) @@ -1391,17 +1391,14 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa return false; } } - if (fNullifiers == false) + BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { - BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) + BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) { - BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) + if (pool.mapNullifiers.count(nf)) { - if (pool.mapNullifiers.count(nf)) - { - fprintf(stderr,"pool.mapNullifiers.count\n"); - return false; - } + fprintf(stderr,"pool.mapNullifiers.count\n"); + return false; } } } @@ -1454,13 +1451,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } } // are the joinsplit's requirements met? - if ( fNullifiers == true ) + if (!view.HaveJoinSplitRequirements(tx)) { - 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"); - } + //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(); @@ -4253,16 +4247,21 @@ 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. + // Copy all non Z-txs in mempool to temporary mempool because there can be tx in local mempool that make the block invalid. LOCK(mempool.cs); + list transactionsToRemove; 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"); + if ( tx.vjoinsplit.size() == 0 ) { + transactionsToRemove.push_back(tx); + tmpmempool.addUnchecked(hash,e,!IsInitialBlockDownload()); + } + } + BOOST_FOREACH(const CTransaction& tx, transactionsToRemove) { + list removed; + mempool.remove(tx, removed, false); } - // 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 ) { @@ -4312,15 +4311,18 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C LogPrintf("CheckBlockHeader komodo_check_deposit error"); return(false); } - if ( ASSETCHAINS_CC != 0 ) // CC contracts might refer to transactions in the current block, from a CC spend within the same block and out of order + if ( ASSETCHAINS_CC != 0 ) { + // here we add back all txs from the temp mempool to the main mempool. + // which removes any tx locally that were invalid after the block arrives. int invalidtxs = 0; BOOST_FOREACH(const CTxMemPoolEntry& e, tmpmempool.mapTx) { CTransaction tx = e.GetTx(); CValidationState state; bool fMissingInputs,fOverrideFees = false; - if (AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, !fOverrideFees,true) == false ) + + if (AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, !fOverrideFees) == false ) invalidtxs++; - //else fprintf(stderr, "added mempool tx back to mempool\n"); + else fprintf(stderr, "added mempool tx back to mempool\n"); } if ( 0 && invalidtxs > 0 ) fprintf(stderr, "number of invalid txs: %d\n",invalidtxs ); diff --git a/src/main.h b/src/main.h index 244817a61..76e0f73ae 100644 --- a/src/main.h +++ b/src/main.h @@ -267,7 +267,7 @@ void PruneAndFlush(); /** (try to) add transaction to memory pool **/ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree, - bool* pfMissingInputs, bool fRejectAbsurdFee=false, bool fNullifiers=false); + bool* pfMissingInputs, bool fRejectAbsurdFee=false); struct CNodeStateStats {