//////////////////////////////////////////////////////////////////////////////// // Need a serious debugging method, that will touch all pointers that are // supposed to be not NULL. I'd like to try to force a segfault here, if it // is going to happen, instead of letting it kill my program where I don't // know what happened. void Tx::pprintAlot(ostream & os) { cout << "Tx hash: " << thisHash_.toHexStr(true) << endl; if(!txRefObj_.isNull()) { cout << "HeaderNum: " << getBlockHeight() << endl; //cout << "HeadHash: " << getBlockHash().toHexStr(true) << endl; } cout << endl << "NumTxIn: " << getNumTxIn() << endl; for(uint32_t i=0; i<getNumTxIn(); i++) { TxIn txin = getTxInCopy(i); cout << " TxIn: " << i << endl; cout << " Siz: " << txin.getSize() << endl; cout << " Scr: " << txin.getScriptSize() << " Type: " << (int)txin.getScriptType() << endl; cout << " OPR: " << txin.getOutPoint().getTxHash().toHexStr(true) << txin.getOutPoint().getTxOutIndex() << endl; cout << " Seq: " << txin.getSequence() << endl; } cout << endl << "NumTxOut: " << getNumTxOut() << endl; for(uint32_t i=0; i<getNumTxOut(); i++) { TxOut txout = getTxOutCopy(i); cout << " TxOut: " << i << endl; cout << " Siz: " << txout.getSize() << endl; cout << " Scr: " << txout.getScriptSize() << " Type: " << (int)txout.getScriptType() << endl; cout << " Val: " << txout.getValue() << endl; } }
TxOut TxOutRef::getCopy(void) const { TxOut returnTxOut; returnTxOut.unserialize(getPtr()); returnTxOut.recipientBinAddr20_ = recipientBinAddr20_; return returnTxOut; }
void UnspentTxOut::init(LMDBBlockDatabase *db, TxOut & txout, uint32_t blkNum, bool isMulti) { txHash_ = txout.getParentHash(db); txOutIndex_ = txout.getIndex(); txHeight_ = txout.getParentHeight(); value_ = txout.getValue(); script_ = txout.getScript(); isMultisigRef_ = isMulti; }
///////////////////////////////////////////////////////////////////////////// // This is not a pointer to persistent object, this method actually CREATES // the TxOut. But it's fast and doesn't hold a lot of post-construction // information, so it can probably just be computed on the fly TxOut Tx::getTxOutCopy(int i) const { assert(isInitialized()); uint32_t txoutSize = offsetsTxOut_[i+1] - offsetsTxOut_[i]; TxOut out; out.unserialize_checked(dataCopy_.getPtr()+offsetsTxOut_[i], dataCopy_.getSize()-offsetsTxOut_[i], txoutSize, txRefObj_, i); out.setParentHash(getThisHash()); if(txRefObj_.isInitialized()) out.setParentHeight(txRefObj_.getBlockHeight()); return out; }
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; }
BinaryData Tx::getScrAddrForTxOut(uint32_t txOutIndex) { TxOut txout = getTxOutCopy(txOutIndex); return BtcUtils::getTxOutScrAddr(txout.getScript()); }