diff --git a/src/cc/oracles.cpp b/src/cc/oracles.cpp index 8cb784b63..5bee9ce86 100644 --- a/src/cc/oracles.cpp +++ b/src/cc/oracles.cpp @@ -235,7 +235,7 @@ int64_t OracleDatafee(CScript &scriptPubKey,uint256 oracletxid,CPubKey publisher } else { - fprintf(stderr,"Could not decode op_ret from transaction %x\nscriptPubKey: %s\n", oracletxid, oracletx.vout[numvouts-1].scriptPubKey.ToString().c_str()); + fprintf(stderr,"Could not decode op_ret from transaction %s\nscriptPubKey: %s\n", oracletxid.GetHex().c_str(), oracletx.vout[numvouts-1].scriptPubKey.ToString().c_str()); } } return(datafee); @@ -545,7 +545,7 @@ bool OraclesDataValidate(struct CCcontract_info *cp,Eval* eval,const CTransactio CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis; CScript scriptPubKey; numvins = tx.vin.size(); numvouts = tx.vout.size(); - if ( OracleDatafee(scriptPubKey,oracletxid,publisher) > datafee ) + if ( OracleDatafee(scriptPubKey,oracletxid,publisher) != datafee ) return eval->Invalid("mismatched datafee"); scriptPubKey = MakeCC1vout(cp->evalcode,0,publisher).scriptPubKey; for (i=0; ikey(); + try { + ssKey = CDataStream(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION); + } catch(std::exception &e) { + return false; + } + return true; + } + unsigned int GetKeySize() { return piter->key().size(); } diff --git a/src/main.cpp b/src/main.cpp index 5fabb00dd..db3008ef1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2844,52 +2844,31 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex for (unsigned int k = tx.vout.size(); k-- > 0;) { const CTxOut &out = tx.vout[k]; - if (out.scriptPubKey.IsPayToScriptHash()) { - vector hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22); - - // undo receiving activity - addressIndex.push_back(make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->GetHeight(), i, hash, k, false), out.nValue)); - - // undo unspent index - addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), hash, k), CAddressUnspentValue())); - + vector> vSols; + CTxDestination vDest; + txnouttype txType = TX_PUBKEYHASH; + int keyType = 1; + if ((Solver(out.scriptPubKey, txType, vSols) || ExtractDestination(out.scriptPubKey, vDest)) && txType != TX_MULTISIG) { + if (vDest.which()) + { + CKeyID kid; + if (CBitcoinAddress(vDest).GetKeyID(kid)) + { + vSols.push_back(vector(kid.begin(), kid.end())); + } + } + else if (txType == TX_SCRIPTHASH) + { + keyType = 2; + } + for (auto addr : vSols) + { + uint160 addrHash = addr.size() == 20 ? uint160(addr) : Hash160(addr); + addressIndex.push_back(make_pair(CAddressIndexKey(keyType, addrHash, pindex->GetHeight(), i, hash, k, false), out.nValue)); + addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(keyType, addrHash, hash, k), CAddressUnspentValue())); + } } - else if (out.scriptPubKey.IsPayToPublicKeyHash()) { - vector hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23); - - // undo receiving activity - addressIndex.push_back(make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->GetHeight(), i, hash, k, false), out.nValue)); - - // undo unspent index - addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), hash, k), CAddressUnspentValue())); - - } - else if (out.scriptPubKey.IsPayToPublicKey()) { - vector hashBytes(out.scriptPubKey.begin()+1, out.scriptPubKey.begin()+34); - - // undo receiving activity - addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->GetHeight(), i, hash, k, false), out.nValue)); - - // undo unspent index - addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), hash, k), CAddressUnspentValue())); - - } - else if (out.scriptPubKey.IsPayToCryptoCondition()) { - vector hashBytes(out.scriptPubKey.begin(), out.scriptPubKey.end()); - - // undo receiving activity - addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->GetHeight(), i, hash, k, false), out.nValue)); - - // undo unspent index - addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), hash, k), CAddressUnspentValue())); - - } - else { - continue; - } - } - } // Check that all outputs are available and match the outputs in the block itself @@ -2934,49 +2913,36 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex if (fAddressIndex) { const CTxOut &prevout = view.GetOutputFor(tx.vin[j]); - if (prevout.scriptPubKey.IsPayToScriptHash()) { - vector hashBytes(prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22); - // undo spending activity - addressIndex.push_back(make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->GetHeight(), i, hash, j, true), prevout.nValue * -1)); + vector> vSols; + CTxDestination vDest; + txnouttype txType = TX_PUBKEYHASH; + int keyType = 1; + // some non-standard types, like time lock coinbases, don't solve, but do extract + if ((Solver(prevout.scriptPubKey, txType, vSols) || ExtractDestination(prevout.scriptPubKey, vDest))) + { + // if we failed to solve, and got a vDest, assume P2PKH or P2PK address returned + if (vDest.which()) + { + CKeyID kid; + if (CBitcoinAddress(vDest).GetKeyID(kid)) + { + vSols.push_back(vector(kid.begin(), kid.end())); + } + } + else if (txType == TX_SCRIPTHASH) + { + keyType = 2; + } + for (auto addr : vSols) + { + uint160 addrHash = addr.size() == 20 ? uint160(addr) : Hash160(addr); + // undo spending activity + addressIndex.push_back(make_pair(CAddressIndexKey(keyType, addrHash, pindex->GetHeight(), i, hash, j, true), prevout.nValue * -1)); - // restore unspent index - addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight))); - - - } - else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) { - vector hashBytes(prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23); - - // undo spending activity - addressIndex.push_back(make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->GetHeight(), i, hash, j, true), prevout.nValue * -1)); - - // restore unspent index - addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight))); - - } - else if (prevout.scriptPubKey.IsPayToPublicKey()) { - vector hashBytes(prevout.scriptPubKey.begin()+1, prevout.scriptPubKey.begin()+34); - - // undo spending activity - addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->GetHeight(), i, hash, j, true), prevout.nValue * -1)); - - // restore unspent index - addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight))); - - } - else if (prevout.scriptPubKey.IsPayToCryptoCondition()) { - vector hashBytes(prevout.scriptPubKey.begin(), prevout.scriptPubKey.end()); - - // undo spending activity - addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->GetHeight(), i, hash, j, true), prevout.nValue * -1)); - - // restore unspent index - addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight))); - - } - else { - continue; + // restore unspent index + addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(keyType, addrHash, input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight))); + } } } } @@ -3269,45 +3235,47 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin const CTxIn input = tx.vin[j]; const CTxOut &prevout = view.GetOutputFor(tx.vin[j]); - uint160 hashBytes; - int addressType; - if (prevout.scriptPubKey.IsPayToScriptHash()) { - hashBytes = uint160(vector (prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22)); - addressType = 2; - } - else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) { - hashBytes = uint160(vector (prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23)); - addressType = 1; - } - else if (prevout.scriptPubKey.IsPayToPublicKey()) { - hashBytes = Hash160(vector (prevout.scriptPubKey.begin()+1, prevout.scriptPubKey.begin()+34)); - addressType = 1; - } - else if (prevout.scriptPubKey.IsPayToCryptoCondition()) { - hashBytes = Hash160(vector (prevout.scriptPubKey.begin(), prevout.scriptPubKey.end())); - addressType = 1; - } - else { - hashBytes.SetNull(); - addressType = 0; - } + vector> vSols; + CTxDestination vDest; + txnouttype txType = TX_PUBKEYHASH; + uint160 addrHash; + int keyType = 0; + // some non-standard types, like time lock coinbases, don't solve, but do extract + if ((Solver(prevout.scriptPubKey, txType, vSols) || ExtractDestination(prevout.scriptPubKey, vDest))) + { + keyType = 1; - if (fAddressIndex && addressType > 0) { - // record spending activity - addressIndex.push_back(make_pair(CAddressIndexKey(addressType, hashBytes, pindex->GetHeight(), i, txhash, j, true), prevout.nValue * -1)); + // if we failed to solve, and got a vDest, assume P2PKH or P2PK address returned + if (vDest.which()) + { + CKeyID kid; + if (CBitcoinAddress(vDest).GetKeyID(kid)) + { + vSols.push_back(vector(kid.begin(), kid.end())); + } + } + else if (txType == TX_SCRIPTHASH) + { + keyType = 2; + } + for (auto addr : vSols) + { + addrHash = addr.size() == 20 ? uint160(addr) : Hash160(addr); + // record spending activity + addressIndex.push_back(make_pair(CAddressIndexKey(keyType, addrHash, pindex->GetHeight(), i, txhash, j, true), prevout.nValue * -1)); - // remove address from unspent index - addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(addressType, hashBytes, input.prevout.hash, input.prevout.n), CAddressUnspentValue())); + // remove address from unspent index + addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(keyType, addrHash, input.prevout.hash, input.prevout.n), CAddressUnspentValue())); + } } if (fSpentIndex) { // add the spent index to determine the txid and input that spent an output // and to find the amount and address from an input - spentIndex.push_back(make_pair(CSpentIndexKey(input.prevout.hash, input.prevout.n), CSpentIndexValue(txhash, j, pindex->GetHeight(), prevout.nValue, addressType, hashBytes))); + spentIndex.push_back(make_pair(CSpentIndexKey(input.prevout.hash, input.prevout.n), CSpentIndexValue(txhash, j, pindex->GetHeight(), prevout.nValue, keyType, addrHash))); } } - } // Add in sigops done by pay-to-script-hash inputs; // this is to prevent a "rogue miner" from creating @@ -3334,51 +3302,39 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (fAddressIndex) { for (unsigned int k = 0; k < tx.vout.size(); k++) { const CTxOut &out = tx.vout[k]; -//fprintf(stderr,"add %d vouts\n",(int32_t)tx.vout.size()); - if (out.scriptPubKey.IsPayToScriptHash()) { - vector hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22); - // record receiving activity - addressIndex.push_back(make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->GetHeight(), i, txhash, k, false), out.nValue)); + uint160 addrHash; - // record unspent output - addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->GetHeight()))); + vector> vSols; + CTxDestination vDest; + txnouttype txType = TX_PUBKEYHASH; + int keyType = 1; + // some non-standard types, like time lock coinbases, don't solve, but do extract + if ((Solver(out.scriptPubKey, txType, vSols) || ExtractDestination(out.scriptPubKey, vDest)) && txType != TX_MULTISIG) + { + // if we failed to solve, and got a vDest, assume P2PKH or P2PK address returned + if (vDest.which()) + { + CKeyID kid; + if (CBitcoinAddress(vDest).GetKeyID(kid)) + { + vSols.push_back(vector(kid.begin(), kid.end())); + } + } + else if (txType == TX_SCRIPTHASH) + { + keyType = 2; + } + for (auto addr : vSols) + { + addrHash = addr.size() == 20 ? uint160(addr) : Hash160(addr); + // record receiving activity + addressIndex.push_back(make_pair(CAddressIndexKey(keyType, addrHash, pindex->GetHeight(), i, txhash, k, false), out.nValue)); + // record unspent output + addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(keyType, addrHash, txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->GetHeight()))); + } } - else if (out.scriptPubKey.IsPayToPublicKeyHash()) { - vector hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23); - - // record receiving activity - addressIndex.push_back(make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->GetHeight(), i, txhash, k, false), out.nValue)); - - // record unspent output - addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->GetHeight()))); - - } - else if (out.scriptPubKey.IsPayToPublicKey()) { - vector hashBytes(out.scriptPubKey.begin()+1, out.scriptPubKey.begin()+34); - - // record receiving activity - addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->GetHeight(), i, txhash, k, false), out.nValue)); - - // record unspent output - addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->GetHeight()))); - - } - else if (out.scriptPubKey.IsPayToCryptoCondition()) { - vector hashBytes(out.scriptPubKey.begin(), out.scriptPubKey.end()); - - // record receiving activity - addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->GetHeight(), i, txhash, k, false), out.nValue)); - - // record unspent output - addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->GetHeight()))); - - } - else { - continue; - } - } } diff --git a/src/txdb.cpp b/src/txdb.cpp index 42c320675..cb853331f 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -332,27 +332,21 @@ bool CBlockTreeDB::ReadAddressUnspentIndex(uint160 addressHash, int type, boost::scoped_ptr pcursor(NewIterator()); - CDataStream ssKeySet(SER_DISK, CLIENT_VERSION); - ssKeySet << make_pair(DB_ADDRESSUNSPENTINDEX, CAddressIndexIteratorKey(type, addressHash)); - pcursor->Seek(ssKeySet.str()); + pcursor->Seek(make_pair(DB_ADDRESSUNSPENTINDEX, CAddressIndexIteratorKey(type, addressHash))); while (pcursor->Valid()) { boost::this_thread::interruption_point(); try { - std::vector slKey = std::vector(); - pcursor->GetKey(slKey); - CDataStream ssKey(slKey, SER_DISK, CLIENT_VERSION); - char chType; - CAddressUnspentKey indexKey; - ssKey >> chType; - ssKey >> indexKey; + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + pair keyObj; + pcursor->GetKey(keyObj); + char chType = keyObj.first; + CAddressUnspentKey indexKey = keyObj.second; + if (chType == DB_ADDRESSUNSPENTINDEX && indexKey.hashBytes == addressHash) { try { - std::vector slValue = std::vector(); - pcursor->GetValue(slValue); - CDataStream ssValue(slValue, SER_DISK, CLIENT_VERSION); CAddressUnspentValue nValue; - ssValue >> nValue; + pcursor->GetValue(nValue); unspentOutputs.push_back(make_pair(indexKey, nValue)); pcursor->Next(); } catch (const std::exception& e) { @@ -365,7 +359,6 @@ bool CBlockTreeDB::ReadAddressUnspentIndex(uint160 addressHash, int type, break; } } - return true; } @@ -389,34 +382,27 @@ bool CBlockTreeDB::ReadAddressIndex(uint160 addressHash, int type, boost::scoped_ptr pcursor(NewIterator()); - CDataStream ssKeySet(SER_DISK, CLIENT_VERSION); if (start > 0 && end > 0) { - ssKeySet << make_pair(DB_ADDRESSINDEX, CAddressIndexIteratorHeightKey(type, addressHash, start)); + pcursor->Seek(make_pair(DB_ADDRESSINDEX, CAddressIndexIteratorHeightKey(type, addressHash, start))); } else { - ssKeySet << make_pair(DB_ADDRESSINDEX, CAddressIndexIteratorKey(type, addressHash)); + pcursor->Seek(make_pair(DB_ADDRESSINDEX, CAddressIndexIteratorKey(type, addressHash))); } - pcursor->Seek(ssKeySet.str()); while (pcursor->Valid()) { boost::this_thread::interruption_point(); try { - std::vector slKey = std::vector(); - pcursor->GetKey(slKey); - CDataStream ssKey(slKey, SER_DISK, CLIENT_VERSION); - char chType; - CAddressIndexKey indexKey; - ssKey >> chType; - ssKey >> indexKey; + pair keyObj; + pcursor->GetKey(keyObj); + char chType = keyObj.first; + CAddressIndexKey indexKey = keyObj.second; + if (chType == DB_ADDRESSINDEX && indexKey.hashBytes == addressHash) { if (end > 0 && indexKey.blockHeight > end) { break; } try { - std::vector slValue = std::vector(); - pcursor->GetValue(slValue); - CDataStream ssValue(slValue, SER_DISK, CLIENT_VERSION); CAmount nValue; - ssValue >> nValue; + pcursor->GetValue(nValue); addressIndex.push_back(make_pair(indexKey, nValue)); pcursor->Next(); @@ -584,20 +570,16 @@ bool CBlockTreeDB::ReadTimestampIndex(const unsigned int &high, const unsigned i boost::scoped_ptr pcursor(NewIterator()); - CDataStream ssKeySet(SER_DISK, CLIENT_VERSION); - ssKeySet << make_pair(DB_TIMESTAMPINDEX, CTimestampIndexIteratorKey(low)); - pcursor->Seek(ssKeySet.str()); + pcursor->Seek(make_pair(DB_TIMESTAMPINDEX, CTimestampIndexIteratorKey(low))); while (pcursor->Valid()) { boost::this_thread::interruption_point(); try { - std::vector slKey = std::vector(); - pcursor->GetKey(slKey); - CDataStream ssKey(slKey, SER_DISK, CLIENT_VERSION); - char chType; - CTimestampIndexKey indexKey; - ssKey >> chType; - ssKey >> indexKey; + pair keyObj; + pcursor->GetKey(keyObj); + char chType = keyObj.first; + CTimestampIndexKey indexKey = keyObj.second; + if (chType == DB_TIMESTAMPINDEX && indexKey.timestamp < high) { if (fActiveOnly) { if (blockOnchainActive(indexKey.blockHash)) { diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 0f588324a..c9b890169 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -134,63 +134,64 @@ void CTxMemPool::addAddressIndex(const CTxMemPoolEntry &entry, const CCoinsViewC for (unsigned int j = 0; j < tx.vin.size(); j++) { const CTxIn input = tx.vin[j]; const CTxOut &prevout = view.GetOutputFor(input); - if (prevout.scriptPubKey.IsPayToScriptHash()) { - vector hashBytes(prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22); - CMempoolAddressDeltaKey key(2, uint160(hashBytes), txhash, j, 1); - CMempoolAddressDelta delta(entry.GetTime(), prevout.nValue * -1, input.prevout.hash, input.prevout.n); - mapAddress.insert(make_pair(key, delta)); - inserted.push_back(key); + + vector> vSols; + txnouttype txType = TX_PUBKEYHASH; + int keyType = 1; + + CTxDestination vDest; + if (Solver(prevout.scriptPubKey, txType, vSols) || ExtractDestination(prevout.scriptPubKey, vDest)) + { + if (vDest.which()) + { + uint160 hashBytes; + if (CBitcoinAddress(vDest).GetIndexKey(hashBytes, keyType)) + { + vSols.push_back(vector(hashBytes.begin(), hashBytes.end())); + } + } + if (txType == TX_SCRIPTHASH) + { + keyType = 2; + } + for (auto addr : vSols) + { + CMempoolAddressDeltaKey key(keyType, addr.size() == 20 ? uint160(addr) : Hash160(addr), txhash, j, true); + CMempoolAddressDelta delta(entry.GetTime(), prevout.nValue * -1, input.prevout.hash, input.prevout.n); + mapAddress.insert(make_pair(key, delta)); + inserted.push_back(key); + } } - else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) { - vector hashBytes(prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23); - CMempoolAddressDeltaKey key(1, uint160(hashBytes), txhash, j, 1); - CMempoolAddressDelta delta(entry.GetTime(), prevout.nValue * -1, input.prevout.hash, input.prevout.n); - mapAddress.insert(make_pair(key, delta)); - inserted.push_back(key); - } - else if (prevout.scriptPubKey.IsPayToPublicKey()) { - vector hashBytes(prevout.scriptPubKey.begin()+1, prevout.scriptPubKey.begin()+34); - CMempoolAddressDeltaKey key(1, Hash160(hashBytes), txhash, j, 1); - CMempoolAddressDelta delta(entry.GetTime(), prevout.nValue * -1, input.prevout.hash, input.prevout.n); - mapAddress.insert(make_pair(key, delta)); - inserted.push_back(key); - } - else if (prevout.scriptPubKey.IsPayToCryptoCondition()) { - vector hashBytes(prevout.scriptPubKey.begin(), prevout.scriptPubKey.end()); - CMempoolAddressDeltaKey key(1, Hash160(hashBytes), txhash, j, 1); - CMempoolAddressDelta delta(entry.GetTime(), prevout.nValue * -1, input.prevout.hash, input.prevout.n); - mapAddress.insert(make_pair(key, delta)); - inserted.push_back(key); - } } + } for (unsigned int k = 0; k < tx.vout.size(); k++) { const CTxOut &out = tx.vout[k]; - if (out.scriptPubKey.IsPayToScriptHash()) { - vector hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22); - CMempoolAddressDeltaKey key(2, uint160(hashBytes), txhash, k, 0); - mapAddress.insert(make_pair(key, CMempoolAddressDelta(entry.GetTime(), out.nValue))); - inserted.push_back(key); - } - else if (out.scriptPubKey.IsPayToPublicKeyHash()) { - vector hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23); - std::pair ret; - CMempoolAddressDeltaKey key(1, uint160(hashBytes), txhash, k, 0); - mapAddress.insert(make_pair(key, CMempoolAddressDelta(entry.GetTime(), out.nValue))); - inserted.push_back(key); - } - else if (out.scriptPubKey.IsPayToPublicKey()) { - vector hashBytes(out.scriptPubKey.begin()+1, out.scriptPubKey.begin()+34); - std::pair ret; - CMempoolAddressDeltaKey key(1, Hash160(hashBytes), txhash, k, 0); - mapAddress.insert(make_pair(key, CMempoolAddressDelta(entry.GetTime(), out.nValue))); - inserted.push_back(key); - } - else if (out.scriptPubKey.IsPayToCryptoCondition()) { - vector hashBytes(out.scriptPubKey.begin(), out.scriptPubKey.end()); - std::pair ret; - CMempoolAddressDeltaKey key(1, Hash160(hashBytes), txhash, k, 0); - mapAddress.insert(make_pair(key, CMempoolAddressDelta(entry.GetTime(), out.nValue))); - inserted.push_back(key); + + vector> vSols; + CTxDestination vDest; + txnouttype txType = TX_PUBKEYHASH; + int keyType = 1; + if ((Solver(out.scriptPubKey, txType, vSols) || ExtractDestination(out.scriptPubKey, vDest)) && txType != TX_MULTISIG) + { + // if we failed to solve, and got a vDest, assume P2PKH or P2PK address returned + if (vDest.which()) + { + uint160 hashBytes; + if (CBitcoinAddress(vDest).GetIndexKey(hashBytes, keyType)) + { + vSols.push_back(vector(hashBytes.begin(), hashBytes.end())); + } + } + else if (txType == TX_SCRIPTHASH) + { + keyType = 2; + } + for (auto addr : vSols) + { + CMempoolAddressDeltaKey key(keyType, addr.size() == 20 ? uint160(addr) : Hash160(addr), txhash, k, 0); + mapAddress.insert(make_pair(key, CMempoolAddressDelta(entry.GetTime(), out.nValue))); + inserted.push_back(key); + } } } @@ -238,38 +239,46 @@ void CTxMemPool::addSpentIndex(const CTxMemPoolEntry &entry, const CCoinsViewCac for (unsigned int j = 0; j < tx.vin.size(); j++) { const CTxIn input = tx.vin[j]; const CTxOut &prevout = view.GetOutputFor(input); - uint160 addressHash; - int addressType; - if (prevout.scriptPubKey.IsPayToScriptHash()) { - addressHash = uint160(vector (prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22)); - addressType = 2; - } - else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) { - addressHash = uint160(vector (prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23)); - addressType = 1; - } - else if (prevout.scriptPubKey.IsPayToPublicKey()) { - addressHash = Hash160(vector (prevout.scriptPubKey.begin()+1, prevout.scriptPubKey.begin()+34)); - addressType = 1; - } - else if (prevout.scriptPubKey.IsPayToCryptoCondition()) { - addressHash = Hash160(vector (prevout.scriptPubKey.begin(), prevout.scriptPubKey.end())); - addressType = 1; - } - else { - addressHash.SetNull(); - addressType = 0; - } + vector> vSols; + CTxDestination vDest; + txnouttype txType = TX_PUBKEYHASH; + int keyType = 1; + // some non-standard types, like time lock coinbases, don't solve, but do extract + if ((Solver(prevout.scriptPubKey, txType, vSols) || ExtractDestination(prevout.scriptPubKey, vDest)) && txType != TX_MULTISIG) + { + // if we failed to solve, and got a vDest, assume P2PKH or P2PK address returned + if (vDest.which()) + { + CKeyID kid; + if (CBitcoinAddress(vDest).GetKeyID(kid)) + { + vSols.push_back(vector(kid.begin(), kid.end())); + } + } + else if (txType == TX_SCRIPTHASH) + { + keyType = 2; + } + for (auto addr : vSols) + { + CSpentIndexKey key = CSpentIndexKey(input.prevout.hash, input.prevout.n); + CSpentIndexValue value = CSpentIndexValue(txhash, j, -1, prevout.nValue, keyType, addr.size() == 20 ? uint160(addr) : Hash160(addr)); - CSpentIndexKey key = CSpentIndexKey(input.prevout.hash, input.prevout.n); - CSpentIndexValue value = CSpentIndexValue(txhash, j, -1, prevout.nValue, addressType, addressHash); - - mapSpent.insert(make_pair(key, value)); - inserted.push_back(key); + mapSpent.insert(make_pair(key, value)); + inserted.push_back(key); + } + } + else + { + // don't know exactly how, but it was spent + CSpentIndexKey key = CSpentIndexKey(input.prevout.hash, input.prevout.n); + CSpentIndexValue value = CSpentIndexValue(txhash, j, -1, prevout.nValue, 0, uint160()); + mapSpent.insert(make_pair(key, value)); + inserted.push_back(key); + } } - mapSpentInserted.insert(make_pair(txhash, inserted)); }