TxOut BlockDataViewer::getPrevTxOut(TxIn & txin) const { if (txin.isCoinbase()) return TxOut(); OutPoint op = txin.getOutPoint(); Tx theTx = getTxByHash(op.getTxHash()); if (!theTx.isInitialized()) throw runtime_error("couldn't find prev tx"); uint32_t idx = op.getTxOutIndex(); return theTx.getTxOutCopy(idx); }
map<BinaryData, map<BinaryData, TxIOPair> > ZeroConfContainer::ZCisMineBulkFilter(const Tx & tx, const BinaryData & ZCkey, uint32_t txtime, function<bool(const BinaryData&)> filter, bool withSecondOrderMultisig) { // Since 99.999%+ of all transactions are not ours, let's do the // fastest bulk filter possible, even though it will add // redundant computation to the tx that are ours. In fact, // we will skip the TxIn/TxOut convenience methods and follow the // pointers directly to the data we want /***filter is a pointer to a function that takes in a scrAddr (21 bytes, including the prefix) and returns a bool. For supernode, it should return true all the time. ***/ map<BinaryData, map<BinaryData, TxIOPair> > processedTxIO; BinaryData txHash = tx.getThisHash(); TxRef txref = db_->getTxRef(txHash); if (txref.isInitialized()) { //Found this tx in the db. It is already part of a block thus //is invalid as a ZC return processedTxIO; } uint8_t const * txStartPtr = tx.getPtr(); for (uint32_t iin = 0; iin<tx.getNumTxIn(); iin++) { // We have the txin, now check if it contains one of our TxOuts OutPoint op; op.unserialize(txStartPtr + tx.getTxInOffset(iin), 36); //check ZC txhash first, always cheaper than grabing a stxo from DB, //and will always be checked if the tx doesn't hit in DB outpoints. { BinaryData opZcKey; if (getKeyForTxHash(op.getTxHash(), opZcKey)) { TxRef outPointRef(opZcKey); uint16_t outPointId = op.getTxOutIndex(); TxIOPair txio(outPointRef, outPointId, TxRef(ZCkey), iin); Tx chainedZC = getTxByHash(op.getTxHash()); const TxOut& chainedTxOut = chainedZC.getTxOutCopy(outPointId); txio.setTxHashOfOutput(op.getTxHash()); txio.setTxHashOfInput(txHash); txio.setValue(chainedTxOut.getValue()); txio.setTxTime(txtime); BinaryData spentSA = chainedTxOut.getScrAddressStr(); auto& key_txioPair = processedTxIO[spentSA]; key_txioPair[txio.getDBKeyOfOutput()] = txio; auto& wltIdVec = keyToSpentScrAddr_[ZCkey]; wltIdVec.push_back(spentSA); txOutsSpentByZC_.insert(txio.getDBKeyOfOutput()); continue; } } //fetch the TxOut from DB BinaryData opKey = op.getDBkey(db_); if (opKey.getSize() == 8) { //found outPoint DBKey, grab the StoredTxOut StoredTxOut stxOut; if (db_->getStoredTxOut(stxOut, opKey)) { BinaryData sa = stxOut.getScrAddress(); if (filter(sa)) { TxIOPair txio(TxRef(opKey.getSliceRef(0, 6)), op.getTxOutIndex(), TxRef(ZCkey), iin); txio.setTxHashOfOutput(op.getTxHash()); txio.setTxHashOfInput(txHash); txio.setValue(stxOut.getValue()); txio.setTxTime(txtime); auto& key_txioPair = processedTxIO[sa]; key_txioPair[opKey] = txio; auto& wltIdVec = keyToSpentScrAddr_[ZCkey]; wltIdVec.push_back(sa); txOutsSpentByZC_.insert(opKey); } } } } // Simply convert the TxOut scripts to scrAddrs and check if registered for (uint32_t iout = 0; iout<tx.getNumTxOut(); iout++) { TxOut txout = tx.getTxOutCopy(iout); BinaryData scrAddr = txout.getScrAddressStr(); if (filter(scrAddr)) { TxIOPair txio(TxRef(ZCkey), iout); txio.setValue(txout.getValue()); txio.setTxHashOfOutput(txHash); txio.setTxTime(txtime); txio.setUTXO(true); auto& key_txioPair = processedTxIO[scrAddr]; key_txioPair[txio.getDBKeyOfOutput()] = txio; continue; } // It's still possible this is a multisig addr involving one of our // existing scrAddrs, even if we aren't explicitly looking for this multisig if (withSecondOrderMultisig && txout.getScriptType() == TXOUT_SCRIPT_MULTISIG) { BinaryRefReader brrmsig(scrAddr); uint8_t PREFIX = brrmsig.get_uint8_t(); (void)PREFIX; uint8_t M = brrmsig.get_uint8_t(); (void)M; uint8_t N = brrmsig.get_uint8_t(); for (uint8_t a = 0; a<N; a++) if (filter(HASH160PREFIX + brrmsig.get_BinaryDataRef(20))) { TxIOPair txio(TxRef(ZCkey), iout); txio.setTxHashOfOutput(txHash); txio.setValue(txout.getValue()); txio.setTxTime(txtime); txio.setUTXO(true); txio.setMultisig(true); auto& key_txioPair = processedTxIO[scrAddr]; key_txioPair[txio.getDBKeyOfOutput()] = txio; } } } // If we got here, it's either non std or not ours return processedTxIO; }