[117082] users/anddam
and.damore at macports.org
and.damore at macports.org
Sat Feb 15 00:24:58 PST 2014
Revision: 117082
https://trac.macports.org/changeset/117082
Author: and.damore at macports.org
Date: 2014-02-15 00:24:58 -0800 (Sat, 15 Feb 2014)
Log Message:
-----------
personal folder: working in progress patch for bitcoin port
Added Paths:
-----------
users/anddam/bitcoin/
users/anddam/bitcoin/patch_bitcoin-bitcoin_pull-request_2802.diff
users/anddam/bitcoin/patch_src_main_cpp.diff
users/anddam/bitcoin/patch_src_main_h.diff
users/anddam/bitcoin/patch_src_src_serialize_h.diff
Added: users/anddam/bitcoin/patch_bitcoin-bitcoin_pull-request_2802.diff
===================================================================
--- users/anddam/bitcoin/patch_bitcoin-bitcoin_pull-request_2802.diff (rev 0)
+++ users/anddam/bitcoin/patch_bitcoin-bitcoin_pull-request_2802.diff 2014-02-15 08:24:58 UTC (rev 117082)
@@ -0,0 +1,411 @@
+diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
+index 11fac42..a542470 100644
+--- src/bitcoinrpc.cpp
++++ src/bitcoinrpc.cpp
+@@ -249,6 +249,7 @@ Value stop(const Array& params, bool fHelp)
+ { "importwallet", &importwallet, false, false },
+ { "listunspent", &listunspent, false, false },
+ { "getrawtransaction", &getrawtransaction, false, false },
++ { "searchrawtransactions", &searchrawtransactions, false, false },
+ { "createrawtransaction", &createrawtransaction, false, false },
+ { "decoderawtransaction", &decoderawtransaction, false, false },
+ { "signrawtransaction", &signrawtransaction, false, false },
+@@ -1189,6 +1190,9 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
+ if (strMethod == "listunspent" && n > 2) ConvertTo<Array>(params[2]);
+ if (strMethod == "getblock" && n > 1) ConvertTo<bool>(params[1]);
+ if (strMethod == "getrawtransaction" && n > 1) ConvertTo<boost::int64_t>(params[1]);
++ if (strMethod == "searchrawtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
++ if (strMethod == "searchrawtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
++ if (strMethod == "searchrawtransactions" && n > 3) ConvertTo<boost::int64_t>(params[3]);
+ if (strMethod == "createrawtransaction" && n > 0) ConvertTo<Array>(params[0]);
+ if (strMethod == "createrawtransaction" && n > 1) ConvertTo<Object>(params[1]);
+ if (strMethod == "signrawtransaction" && n > 1) ConvertTo<Array>(params[1], true);
+diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h
+index 4d5599b..443bf98 100644
+--- src/bitcoinrpc.h
++++ src/bitcoinrpc.h
+@@ -192,6 +192,7 @@ class CRPCTable
+ extern json_spirit::Value getinfo(const json_spirit::Array& params, bool fHelp);
+
+ extern json_spirit::Value getrawtransaction(const json_spirit::Array& params, bool fHelp); // in rcprawtransaction.cpp
++extern json_spirit::Value searchrawtransactions(const json_spirit::Array& params, bool fHelp);
+ extern json_spirit::Value listunspent(const json_spirit::Array& params, bool fHelp);
+ extern json_spirit::Value lockunspent(const json_spirit::Array& params, bool fHelp);
+ extern json_spirit::Value listlockunspent(const json_spirit::Array& params, bool fHelp);
+diff --git a/src/init.cpp b/src/init.cpp
+index f6b2c91..a8a2379 100644
+--- src/init.cpp
++++ src/init.cpp
+@@ -710,7 +710,7 @@ bool AppInit2(boost::thread_group& threadGroup)
+ if (nTotalCache < (1 << 22))
+ nTotalCache = (1 << 22); // total cache cannot be less than 4 MiB
+ size_t nBlockTreeDBCache = nTotalCache / 8;
+- if (nBlockTreeDBCache > (1 << 21) && !GetBoolArg("-txindex", false))
++ if (nBlockTreeDBCache > (1 << 21) && !GetBoolArg("-txindex", false) && !GetBoolArg("-addrindex", false))
+ nBlockTreeDBCache = (1 << 21); // block tree db cache shouldn't be larger than 2 MiB
+ nTotalCache -= nBlockTreeDBCache;
+ size_t nCoinDBCache = nTotalCache / 2; // use half of the remaining cache for coindb cache
+@@ -761,6 +761,12 @@ bool AppInit2(boost::thread_group& threadGroup)
+ break;
+ }
+
++ // Check for changed -addrindex state
++ if (fAddrIndex != GetBoolArg("-addrindex", false)) {
++ strLoadError = _("You need to rebuild the database using -reindex to change -addrindex");
++ break;
++ }
++
+ uiInterface.InitMessage(_("Verifying blocks..."));
+ if (!VerifyDB(GetArg("-checklevel", 3),
+ GetArg( "-checkblocks", 288))) {
+diff --git a/src/leveldb.cpp b/src/leveldb.cpp
+index e66f851..ae8d00d 100644
+--- src/leveldb.cpp
++++ src/leveldb.cpp
+@@ -34,6 +34,13 @@ static leveldb::Options GetOptions(size_t nCacheSize) {
+ return options;
+ }
+
++CLevelDBIterator::~CLevelDBIterator() { delete piter; }
++bool CLevelDBIterator::Valid() { return piter->Valid(); }
++void CLevelDBIterator::SeekToFirst() { piter->SeekToFirst(); }
++void CLevelDBIterator::SeekToLast() { piter->SeekToLast(); }
++void CLevelDBIterator::Next() { piter->Next(); }
++void CLevelDBIterator::Prev() { piter->Prev(); }
++
+ CLevelDB::CLevelDB(const boost::filesystem::path &path, size_t nCacheSize, bool fMemory, bool fWipe) {
+ penv = NULL;
+ readoptions.verify_checksums = true;
+diff --git a/src/leveldb.h b/src/leveldb.h
+index 79262ed..3388504 100644
+--- src/leveldb.h
++++ src/leveldb.h
+@@ -52,6 +52,63 @@ class CLevelDBBatch
+ }
+ };
+
++class CLevelDBIterator
++{
++private:
++ leveldb::Iterator *piter;
++
++public:
++ CLevelDBIterator(leveldb::Iterator *piterIn) : piter(piterIn) {}
++ ~CLevelDBIterator();
++
++ bool Valid();
++
++ void SeekToFirst();
++ void SeekToLast();
++
++ template<typename K> void Seek(const K& key) {
++ CDataStream ssKey(SER_DISK, CLIENT_VERSION);
++ ssKey.reserve(ssKey.GetSerializeSize(key));
++ ssKey << key;
++ leveldb::Slice slKey(&ssKey[0], ssKey.size());
++ piter->Seek(slKey);
++ }
++
++ void Next();
++ void Prev();
++
++ template<typename K> bool GetKey(K& key) {
++ leveldb::Slice slKey = piter->key();
++ try {
++ CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
++ ssKey >> key;
++ } catch(std::exception &e) {
++ return false;
++ }
++ return true;
++ }
++
++ unsigned int GetKeySize() {
++ return piter->key().size();
++ }
++
++ template<typename V> bool GetValue(V& value) {
++ leveldb::Slice slValue = piter->value();
++ try {
++ CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
++ ssValue >> value;
++ } catch(std::exception &e) {
++ return false;
++ }
++ return true;
++ }
++
++ unsigned int GetValueSize() {
++ return piter->value().size();
++ }
++
++};
++
+ class CLevelDB
+ {
+ private:
+@@ -144,9 +201,8 @@ class CLevelDB
+ return WriteBatch(batch, true);
+ }
+
+- // not exactly clean encapsulation, but it's easiest for now
+- leveldb::Iterator *NewIterator() {
+- return pdb->NewIterator(iteroptions);
++ CLevelDBIterator *NewIterator() {
++ return new CLevelDBIterator(pdb->NewIterator(iteroptions));
+ }
+ };
+
+diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
+index f08688d..f7b88a1 100644
+--- src/rpcrawtransaction.cpp
++++ src/rpcrawtransaction.cpp
+@@ -131,6 +131,66 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
+ }
+ }
+
++Value searchrawtransactions(const Array ¶ms, bool fHelp)
++{
++ if (fHelp || params.size() < 1 || params.size() > 4)
++ throw runtime_error(
++ "searchrawtransactions <address> [verbose=1] [skip=0] [count=100]\n");
++
++ if (!fAddrIndex)
++ throw JSONRPCError(RPC_MISC_ERROR, "Address index not enabled");
++
++ CBitcoinAddress address(params[0].get_str());
++ if (!address.IsValid())
++ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
++ CTxDestination dest = address.Get();
++
++ std::set<CExtDiskTxPos> setpos;
++ if (!FindTransactionsByDestination(dest, setpos))
++ throw JSONRPCError(RPC_DATABASE_ERROR, "Cannot search for address");
++
++ int nSkip = 0;
++ int nCount = 100;
++ bool fVerbose = true;
++ if (params.size() > 1)
++ fVerbose = (params[1].get_int() != 0);
++ if (params.size() > 2)
++ nSkip = params[2].get_int();
++ if (params.size() > 3)
++ nCount = params[3].get_int();
++
++ if (nSkip < 0)
++ nSkip += setpos.size();
++ if (nSkip < 0)
++ nSkip = 0;
++ if (nCount < 0)
++ nCount = 0;
++
++ std::set<CExtDiskTxPos>::const_iterator it = setpos.begin();
++ while (it != setpos.end() && nSkip--) it++;
++
++ Array result;
++ while (it != setpos.end() && nCount--) {
++ CTransaction tx;
++ uint256 hashBlock;
++ if (!ReadTransaction(tx, *it, hashBlock))
++ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Cannot read transaction from disk");
++ CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
++ ssTx << tx;
++ string strHex = HexStr(ssTx.begin(), ssTx.end());
++ if (fVerbose) {
++ Object object;
++ TxToJSON(tx, hashBlock, object);
++ object.push_back(Pair("hex", strHex));
++ result.push_back(object);
++ } else {
++ result.push_back(strHex);
++ }
++ it++;
++ }
++ return result;
++}
++
+ Value getrawtransaction(const Array& params, bool fHelp)
+ {
+ if (fHelp || params.size() < 1 || params.size() > 2)
+diff --git a/src/txdb.cpp b/src/txdb.cpp
+index 34836ea..7b8b3a5 100644
+--- src/txdb.cpp
++++ src/txdb.cpp
+@@ -67,6 +67,10 @@ bool CCoinsViewDB::BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockI
+ }
+
+ CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDB(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
++ if (!Read('S', salt)) {
++ salt = GetRandHash();
++ Write('S', salt);
++ }
+ }
+
+ bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
+@@ -113,8 +117,8 @@ bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
+ }
+
+ bool CCoinsViewDB::GetStats(CCoinsStats &stats) {
+- leveldb::Iterator *pcursor = db.NewIterator();
+- pcursor->SeekToFirst();
++ CLevelDBIterator *pcursor = db.NewIterator();
++ pcursor->Seek('c');
+
+ CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
+ stats.hashBlock = GetBestBlock()->GetBlockHash();
+@@ -122,22 +126,10 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) {
+ int64 nTotalAmount = 0;
+ while (pcursor->Valid()) {
+ boost::this_thread::interruption_point();
+- try {
+- leveldb::Slice slKey = pcursor->key();
+- CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
+- char chType;
+- ssKey >> chType;
+- if (chType == 'c') {
+- leveldb::Slice slValue = pcursor->value();
+- CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
+- CCoins coins;
+- ssValue >> coins;
+- uint256 txhash;
+- ssKey >> txhash;
+- ss << txhash;
+- ss << VARINT(coins.nVersion);
+- ss << (coins.fCoinBase ? 'c' : 'n');
+- ss << VARINT(coins.nHeight);
++ std::pair<char, uint256> key;
++ CCoins coins;
++ if (pcursor->GetKey(key) && key.first == 'c') {
++ if (pcursor->GetValue(coins)) {
+ stats.nTransactions++;
+ for (unsigned int i=0; i<coins.vout.size(); i++) {
+ const CTxOut &out = coins.vout[i];
+@@ -148,13 +140,15 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) {
+ nTotalAmount += out.nValue;
+ }
+ }
+- stats.nSerializedSize += 32 + slValue.size();
++ stats.nSerializedSize += 32 + pcursor->GetKeySize();
+ ss << VARINT(0);
++ } else {
++ return error("CCoinsViewDB::GetStats() : unable to read value");
+ }
+- pcursor->Next();
+- } catch (std::exception &e) {
+- return error("%s() : deserialize error", __PRETTY_FUNCTION__);
++ } else {
++ break;
+ }
++ pcursor->Next();
+ }
+ delete pcursor;
+ stats.nHeight = GetBestBlock()->nHeight;
+@@ -174,6 +168,40 @@ bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos>
+ return WriteBatch(batch);
+ }
+
++bool CBlockTreeDB::ReadAddrIndex(uint160 addrid, std::vector<CExtDiskTxPos> &list) {
++ CLevelDBIterator *iter = NewIterator();
++ uint64 lookupid;
++ {
++ CHashWriter ss(SER_GETHASH, 0);
++ ss << salt;
++ ss << addrid;
++ lookupid = ss.GetHash().Get64(0);
++ }
++ iter->Seek(make_pair('a', lookupid));
++ while (iter->Valid()) {
++ std::pair<std::pair<char, uint64>, CExtDiskTxPos> key;
++ if (iter->GetKey(key) && key.first.first == 'a' && key.first.second == lookupid) {
++ list.push_back(key.second);
++ } else {
++ break;
++ }
++ iter->Next();
++ }
++ return true;
++}
++
++bool CBlockTreeDB::AddAddrIndex(const std::vector<std::pair<uint160, CExtDiskTxPos> > &list) {
++ unsigned char foo[0];
++ CLevelDBBatch batch;
++ for (std::vector<std::pair<uint160, CExtDiskTxPos> >::const_iterator it=list.begin(); it!=list.end(); it++) {
++ CHashWriter ss(SER_GETHASH, 0);
++ ss << salt;
++ ss << it->first;
++ batch.Write(make_pair(make_pair('a', ss.GetHash().Get64(0)), it->second), FLATDATA(foo));
++ }
++ return WriteBatch(batch);
++}
++
+ bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
+ return Write(std::make_pair('F', name), fValue ? '1' : '0');
+ }
+@@ -188,26 +216,17 @@ bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
+
+ bool CBlockTreeDB::LoadBlockIndexGuts()
+ {
+- leveldb::Iterator *pcursor = NewIterator();
++ CLevelDBIterator *pcursor = NewIterator();
+
+- CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
+- ssKeySet << make_pair('b', uint256(0));
+- pcursor->Seek(ssKeySet.str());
++ pcursor->Seek(make_pair('b', uint256(0)));
+
+ // Load mapBlockIndex
+ while (pcursor->Valid()) {
+ boost::this_thread::interruption_point();
+- try {
+- leveldb::Slice slKey = pcursor->key();
+- CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
+- char chType;
+- ssKey >> chType;
+- if (chType == 'b') {
+- leveldb::Slice slValue = pcursor->value();
+- CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
+- CDiskBlockIndex diskindex;
+- ssValue >> diskindex;
+-
++ std::pair<char, uint256> key;
++ if (pcursor->GetKey(key) && key.first == 'b') {
++ CDiskBlockIndex diskindex;
++ if (pcursor->GetValue(diskindex)) {
+ // Construct block index object
+ CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
+ pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev);
+@@ -232,10 +251,10 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
+
+ pcursor->Next();
+ } else {
+- break; // if shutdown requested or finished loading block index
++ return error("LoadBlockIndex() : failed to read value");
+ }
+- } catch (std::exception &e) {
+- return error("%s() : deserialize error", __PRETTY_FUNCTION__);
++ } else {
++ break;
+ }
+ }
+ delete pcursor;
+diff --git a/src/txdb.h b/src/txdb.h
+index f59fc5d..7f5c171 100644
+--- src/txdb.h
++++ src/txdb.h
+@@ -31,6 +31,7 @@ class CBlockTreeDB : public CLevelDB
+ public:
+ CBlockTreeDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false);
+ private:
++ uint256 salt;
+ CBlockTreeDB(const CBlockTreeDB&);
+ void operator=(const CBlockTreeDB&);
+ public:
+@@ -45,6 +46,8 @@ class CBlockTreeDB : public CLevelDB
+ bool ReadReindexing(bool &fReindex);
+ bool ReadTxIndex(const uint256 &txid, CDiskTxPos &pos);
+ bool WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> > &list);
++ bool ReadAddrIndex(uint160 addrid, std::vector<CExtDiskTxPos> &list);
++ bool AddAddrIndex(const std::vector<std::pair<uint160, CExtDiskTxPos> > &list);
+ bool WriteFlag(const std::string &name, bool fValue);
+ bool ReadFlag(const std::string &name, bool &fValue);
+ bool LoadBlockIndexGuts();
Added: users/anddam/bitcoin/patch_src_main_cpp.diff
===================================================================
--- users/anddam/bitcoin/patch_src_main_cpp.diff (rev 0)
+++ users/anddam/bitcoin/patch_src_main_cpp.diff 2014-02-15 08:24:58 UTC (rev 117082)
@@ -0,0 +1,180 @@
+--- src/main.cpp.original 2014-02-14 22:20:23.000000000 +0100
++++ src/main.cpp 2014-02-14 22:46:32.000000000 +0100
+@@ -46,6 +46,7 @@
+ bool fReindex = false;
+ bool fBenchmark = false;
+ bool fTxIndex = false;
++bool fAddrIndex = false;
+ unsigned int nCoinCacheSize = 5000;
+
+ /** Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) */
+@@ -962,6 +963,42 @@
+ return false;
+ }
+
++bool ReadTransaction(CTransaction& tx, const CDiskTxPos &pos, uint256 &hashBlock) {
++ CAutoFile file(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION);
++ CBlockHeader header;
++ try {
++ file >> header;
++ fseek(file, pos.nTxOffset, SEEK_CUR);
++ file >> tx;
++ } catch (std::exception &e) {
++ return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__);
++ }
++ hashBlock = header.GetHash();
++ return true;
++}
++
++bool FindTransactionsByDestination(const CTxDestination &dest, std::set<CExtDiskTxPos> &setpos) {
++ uint160 addrid = 0;
++ const CKeyID *pkeyid = boost::get<CKeyID>(&dest);
++ if (pkeyid)
++ addrid = static_cast<uint160>(*pkeyid);
++ if (!addrid) {
++ const CScriptID *pscriptid = boost::get<CScriptID>(&dest);
++ if (pscriptid)
++ addrid = static_cast<uint160>(*pscriptid);
++ }
++ if (!addrid)
++ return false;
++
++ LOCK(cs_main);
++ if (!fAddrIndex)
++ return false;
++ std::vector<CExtDiskTxPos> vPos;
++ if (!pblocktree->ReadAddrIndex(addrid, vPos))
++ return false;
++ setpos.insert(vPos.begin(), vPos.end());
++ return true;
++}
+
+ // Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock
+ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow)
+@@ -981,16 +1018,8 @@
+ if (fTxIndex) {
+ CDiskTxPos postx;
+ if (pblocktree->ReadTxIndex(hash, postx)) {
+- CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION);
+- CBlockHeader header;
+- try {
+- file >> header;
+- fseek(file, postx.nTxOffset, SEEK_CUR);
+- file >> txOut;
+- } catch (std::exception &e) {
+- return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__);
+- }
+- hashBlock = header.GetHash();
++ if (!ReadTransaction(txOut, postx, hashBlock))
++ return false;
+ if (txOut.GetHash() != hash)
+ return error("%s() : txid mismatch", __PRETTY_FUNCTION__);
+ return true;
+@@ -1596,6 +1625,32 @@
+ scriptcheckqueue.Thread();
+ }
+
++// Index either: a) every data push >=8 bytes, b) if no such pushes, the entire script
++void static BuildAddrIndex(const CScript &script, const CExtDiskTxPos &pos, std::vector<std::pair<uint160, CExtDiskTxPos> > &out) {
++ CScript::const_iterator pc = script.begin();
++ CScript::const_iterator pend = script.end();
++ std::vector<unsigned char> data;
++ opcodetype opcode;
++ bool fHaveData = false;
++ while (pc < pend) {
++ script.GetOp(pc, opcode, data);
++ if (0 <= opcode && opcode <= OP_PUSHDATA4 && data.size() >= 8) { // data element
++ uint160 addrid = 0;
++ if (data.size() <= 20) {
++ memcpy(&addrid, &data[0], data.size());
++ } else {
++ addrid = Hash160(data);
++ }
++ out.push_back(std::make_pair(addrid, pos));
++ fHaveData = true;
++ }
++ }
++ if (!fHaveData) {
++ uint160 addrid = Hash160(script);
++ out.push_back(std::make_pair(addrid, pos));
++ }
++}
++
+ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsViewCache &view, bool fJustCheck)
+ {
+ // Check it again in case a previous version let a bad block in
+@@ -1653,9 +1708,13 @@
+ int64 nFees = 0;
+ int nInputs = 0;
+ unsigned int nSigOps = 0;
+- CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(vtx.size()));
+- std::vector<std::pair<uint256, CDiskTxPos> > vPos;
+- vPos.reserve(vtx.size());
++ CExtDiskTxPos pos(CDiskTxPos(pindex->GetBlockPos(), GetSizeOfCompactSize(vtx.size())), pindex->nHeight);
++ std::vector<std::pair<uint256, CDiskTxPos> > vPosTxid;
++ std::vector<std::pair<uint160, CExtDiskTxPos> > vPosAddrid;
++ if (fTxIndex)
++ vPosTxid.reserve(vtx.size());
++ if (fAddrIndex)
++ vPosAddrid.reserve(4*vtx.size());
+ for (unsigned int i=0; i<vtx.size(); i++)
+ {
+ const CTransaction &tx = vtx[i];
+@@ -1687,13 +1746,24 @@
+ return false;
+ control.Add(vChecks);
+ }
++ if (fTxIndex)
++ vPosTxid.push_back(std::make_pair(GetTxHash(i), pos));
++ if (fAddrIndex) {
++ if (!tx.IsCoinBase()) {
++ BOOST_FOREACH(const CTxIn &txin, tx.vin) {
++ const CCoins &coins = view.GetCoins(txin.prevout.hash);
++ BuildAddrIndex(coins.vout[txin.prevout.n].scriptPubKey, pos, vPosAddrid);
++ }
++ }
++ BOOST_FOREACH(const CTxOut &txout, tx.vout)
++ BuildAddrIndex(txout.scriptPubKey, pos, vPosAddrid);
++ }
+
+ CTxUndo txundo;
+ tx.UpdateCoins(state, view, txundo, pindex->nHeight, GetTxHash(i));
+ if (!tx.IsCoinBase())
+ blockundo.vtxundo.push_back(txundo);
+
+- vPos.push_back(std::make_pair(GetTxHash(i), pos));
+ pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
+ }
+ int64 nTime = GetTimeMicros() - nStart;
+@@ -1735,8 +1805,11 @@
+ }
+
+ if (fTxIndex)
+- if (!pblocktree->WriteTxIndex(vPos))
++ if (!pblocktree->WriteTxIndex(vPosTxid))
+ return state.Abort(_("Failed to write transaction index"));
++ if (fAddrIndex)
++ if (!pblocktree->AddAddrIndex(vPosAddrid))
++ return state.Abort(_("Failed to write address index"));
+
+ // add this block to the view's block chain
+ assert(view.SetBestBlock(pindex));
+@@ -2608,6 +2681,9 @@
+ pblocktree->ReadFlag("txindex", fTxIndex);
+ printf("LoadBlockIndexDB(): transaction index %s\n", fTxIndex ? "enabled" : "disabled");
+
++ pblocktree->ReadFlag("addrindex", fAddrIndex);
++ printf("LoadBlockIndexDB(): address index %s\n", fAddrIndex ? "enabled" : "disabled");
++
+ // Load hashBestChain pointer to end of best chain
+ pindexBest = pcoinsTip->GetBestBlock();
+ if (pindexBest == NULL)
+@@ -2745,6 +2821,8 @@
+ // Use the provided setting for -txindex in the new database
+ fTxIndex = GetBoolArg("-txindex", false);
+ pblocktree->WriteFlag("txindex", fTxIndex);
++ fAddrIndex = GetBoolArg("-addrindex", false);
++ pblocktree->WriteFlag("addrindex", fAddrIndex);
+ printf("Initializing databases...\n");
+
+ // Only add the genesis block if not reindexing (in which case we reuse the one already on disk)
Added: users/anddam/bitcoin/patch_src_main_h.diff
===================================================================
--- users/anddam/bitcoin/patch_src_main_h.diff (rev 0)
+++ users/anddam/bitcoin/patch_src_main_h.diff 2014-02-15 08:24:58 UTC (rev 117082)
@@ -0,0 +1,77 @@
+--- src/main.h.orig 2014-02-15 08:19:57.000000000 +0100
++++ src/main.h 2014-02-15 08:20:42.000000000 +0100
+@@ -96,6 +96,7 @@
+ extern bool fBenchmark;
+ extern int nScriptCheckThreads;
+ extern bool fTxIndex;
++extern bool fAddrIndex;
+ extern unsigned int nCoinCacheSize;
+
+ // Settings
+@@ -248,8 +249,57 @@
+ CDiskBlockPos::SetNull();
+ nTxOffset = 0;
+ }
++
++ friend bool operator==(const CDiskTxPos &a, const CDiskTxPos &b) {
++ return (a.nFile == b.nFile && a.nPos == b.nPos && a.nTxOffset == b.nTxOffset);
++ }
++
++ friend bool operator!=(const CDiskTxPos &a, const CDiskTxPos &b) {
++ return !(a == b);
++ }
++
++ friend bool operator<(const CDiskTxPos &a, const CDiskTxPos &b) {
++ return (a.nFile < b.nFile || (
++ (a.nFile == b.nFile) && (a.nPos < b.nPos || (
++ (a.nPos == b.nPos) && (a.nTxOffset < b.nTxOffset)))));
++ }
+ };
+
++struct CExtDiskTxPos : public CDiskTxPos
++{
++ unsigned int nHeight;
++
++ IMPLEMENT_SERIALIZE(
++ READWRITE(*(CDiskTxPos*)this);
++ READWRITE(VARINT(nHeight));
++ )
++
++ CExtDiskTxPos(const CDiskTxPos &pos, int nHeightIn) : CDiskTxPos(pos), nHeight(nHeightIn) {
++ }
++
++ CExtDiskTxPos() {
++ SetNull();
++ }
++
++ void SetNull() {
++ CDiskTxPos::SetNull();
++ nHeight = 0;
++ }
++
++ friend bool operator==(const CExtDiskTxPos &a, const CExtDiskTxPos &b) {
++ return (a.nHeight == b.nHeight && a.nFile == b.nFile && a.nPos == b.nPos && a.nTxOffset == b.nTxOffset);
++ }
++
++ friend bool operator!=(const CExtDiskTxPos &a, const CExtDiskTxPos &b) {
++ return !(a == b);
++ }
++
++ friend bool operator<(const CExtDiskTxPos &a, const CExtDiskTxPos &b) {
++ if (a.nHeight < b.nHeight) return true;
++ if (a.nHeight > b.nHeight) return false;
++ return ((const CDiskTxPos)a < (const CDiskTxPos)b);
++ }
++};
+
+ /** An inpoint - a combination of a transaction and an index n into its vin */
+ class CInPoint
+@@ -264,6 +314,8 @@
+ bool IsNull() const { return (ptx == NULL && n == (unsigned int) -1); }
+ };
+
++bool ReadTransaction(CTransaction& tx, const CDiskTxPos &pos, uint256 &hashBlock);
++bool FindTransactionsByDestination(const CTxDestination &dest, std::set<CExtDiskTxPos> &setpos);
+
+
+ /** An outpoint - a combination of a transaction hash and an index n into its vout */
Added: users/anddam/bitcoin/patch_src_src_serialize_h.diff
===================================================================
--- users/anddam/bitcoin/patch_src_src_serialize_h.diff (rev 0)
+++ users/anddam/bitcoin/patch_src_src_serialize_h.diff 2014-02-15 08:24:58 UTC (rev 117082)
@@ -0,0 +1,22 @@
+--- src/serialize.h.orig 2014-02-13 19:17:19.000000000 +0100
++++ src/serialize.h 2014-02-13 19:19:00.000000000 +0100
+@@ -895,19 +895,6 @@
+ iterator insert(iterator it, const char& x=char()) { return vch.insert(it, x); }
+ void insert(iterator it, size_type n, const char& x) { vch.insert(it, n, x); }
+
+- void insert(iterator it, const_iterator first, const_iterator last)
+- {
+- assert(last - first >= 0);
+- if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos)
+- {
+- // special case for inserting at the front when there's room
+- nReadPos -= (last - first);
+- memcpy(&vch[nReadPos], &first[0], last - first);
+- }
+- else
+- vch.insert(it, first, last);
+- }
+-
+ void insert(iterator it, std::vector<char>::const_iterator first, std::vector<char>::const_iterator last)
+ {
+ assert(last - first >= 0);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/macports-changes/attachments/20140215/7c253a0e/attachment-0001.html>
More information about the macports-changes
mailing list