<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[117082] users/anddam</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="https://trac.macports.org/changeset/117082">117082</a></dd>
<dt>Author</dt> <dd>and.damore@macports.org</dd>
<dt>Date</dt> <dd>2014-02-15 00:24:58 -0800 (Sat, 15 Feb 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>personal folder: working in progress patch for bitcoin port</pre>

<h3>Added Paths</h3>
<ul>
<li>users/anddam/bitcoin/</li>
<li><a href="#usersanddambitcoinpatch_bitcoinbitcoin_pullrequest_2802diff">users/anddam/bitcoin/patch_bitcoin-bitcoin_pull-request_2802.diff</a></li>
<li><a href="#usersanddambitcoinpatch_src_main_cppdiff">users/anddam/bitcoin/patch_src_main_cpp.diff</a></li>
<li><a href="#usersanddambitcoinpatch_src_main_hdiff">users/anddam/bitcoin/patch_src_main_h.diff</a></li>
<li><a href="#usersanddambitcoinpatch_src_src_serialize_hdiff">users/anddam/bitcoin/patch_src_src_serialize_h.diff</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="usersanddambitcoinpatch_bitcoinbitcoin_pullrequest_2802diff"></a>
<div class="addfile"><h4>Added: users/anddam/bitcoin/patch_bitcoin-bitcoin_pull-request_2802.diff (0 => 117082)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,411 @@
</span><ins>+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&amp; params, bool fHelp)
+     { &quot;importwallet&quot;,           &amp;importwallet,           false,     false },
+     { &quot;listunspent&quot;,            &amp;listunspent,            false,     false },
+     { &quot;getrawtransaction&quot;,      &amp;getrawtransaction,      false,     false },
++    { &quot;searchrawtransactions&quot;,  &amp;searchrawtransactions,  false,     false },
+     { &quot;createrawtransaction&quot;,   &amp;createrawtransaction,   false,     false },
+     { &quot;decoderawtransaction&quot;,   &amp;decoderawtransaction,   false,     false },
+     { &quot;signrawtransaction&quot;,     &amp;signrawtransaction,     false,     false },
+@@ -1189,6 +1190,9 @@ Array RPCConvertValues(const std::string &amp;strMethod, const std::vector&lt;std::stri
+     if (strMethod == &quot;listunspent&quot;            &amp;&amp; n &gt; 2) ConvertTo&lt;Array&gt;(params[2]);
+     if (strMethod == &quot;getblock&quot;               &amp;&amp; n &gt; 1) ConvertTo&lt;bool&gt;(params[1]);
+     if (strMethod == &quot;getrawtransaction&quot;      &amp;&amp; n &gt; 1) ConvertTo&lt;boost::int64_t&gt;(params[1]);
++    if (strMethod == &quot;searchrawtransactions&quot;  &amp;&amp; n &gt; 1) ConvertTo&lt;boost::int64_t&gt;(params[1]);
++    if (strMethod == &quot;searchrawtransactions&quot;  &amp;&amp; n &gt; 2) ConvertTo&lt;boost::int64_t&gt;(params[2]);
++    if (strMethod == &quot;searchrawtransactions&quot;  &amp;&amp; n &gt; 3) ConvertTo&lt;boost::int64_t&gt;(params[3]);
+     if (strMethod == &quot;createrawtransaction&quot;   &amp;&amp; n &gt; 0) ConvertTo&lt;Array&gt;(params[0]);
+     if (strMethod == &quot;createrawtransaction&quot;   &amp;&amp; n &gt; 1) ConvertTo&lt;Object&gt;(params[1]);
+     if (strMethod == &quot;signrawtransaction&quot;     &amp;&amp; n &gt; 1) ConvertTo&lt;Array&gt;(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&amp; params, bool fHelp);

+ extern json_spirit::Value getrawtransaction(const json_spirit::Array&amp; params, bool fHelp); // in rcprawtransaction.cpp
++extern json_spirit::Value searchrawtransactions(const json_spirit::Array&amp; params, bool fHelp);
+ extern json_spirit::Value listunspent(const json_spirit::Array&amp; params, bool fHelp);
+ extern json_spirit::Value lockunspent(const json_spirit::Array&amp; params, bool fHelp);
+ extern json_spirit::Value listlockunspent(const json_spirit::Array&amp; 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&amp; threadGroup)
+     if (nTotalCache &lt; (1 &lt;&lt; 22))
+         nTotalCache = (1 &lt;&lt; 22); // total cache cannot be less than 4 MiB
+     size_t nBlockTreeDBCache = nTotalCache / 8;
+-    if (nBlockTreeDBCache &gt; (1 &lt;&lt; 21) &amp;&amp; !GetBoolArg(&quot;-txindex&quot;, false))
++    if (nBlockTreeDBCache &gt; (1 &lt;&lt; 21) &amp;&amp; !GetBoolArg(&quot;-txindex&quot;, false) &amp;&amp; !GetBoolArg(&quot;-addrindex&quot;, false))
+         nBlockTreeDBCache = (1 &lt;&lt; 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&amp; threadGroup)
+                     break;
+                 }

++                // Check for changed -addrindex state
++                if (fAddrIndex != GetBoolArg(&quot;-addrindex&quot;, false)) {
++                    strLoadError = _(&quot;You need to rebuild the database using -reindex to change -addrindex&quot;);
++                    break;
++                }
++
+                 uiInterface.InitMessage(_(&quot;Verifying blocks...&quot;));
+                 if (!VerifyDB(GetArg(&quot;-checklevel&quot;, 3),
+                               GetArg( &quot;-checkblocks&quot;, 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-&gt;Valid(); }
++void CLevelDBIterator::SeekToFirst() { piter-&gt;SeekToFirst(); }
++void CLevelDBIterator::SeekToLast() { piter-&gt;SeekToLast(); }
++void CLevelDBIterator::Next() { piter-&gt;Next(); }
++void CLevelDBIterator::Prev() { piter-&gt;Prev(); }
++
+ CLevelDB::CLevelDB(const boost::filesystem::path &amp;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&lt;typename K&gt; void Seek(const K&amp; key) {
++        CDataStream ssKey(SER_DISK, CLIENT_VERSION);
++        ssKey.reserve(ssKey.GetSerializeSize(key));
++        ssKey &lt;&lt; key;
++        leveldb::Slice slKey(&amp;ssKey[0], ssKey.size());
++        piter-&gt;Seek(slKey);
++    }
++
++    void Next();
++    void Prev();
++
++    template&lt;typename K&gt; bool GetKey(K&amp; key) {
++        leveldb::Slice slKey = piter-&gt;key();
++        try {
++            CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
++            ssKey &gt;&gt; key;
++        } catch(std::exception &amp;e) {
++            return false;
++        }
++        return true;
++    }
++
++    unsigned int GetKeySize() {
++        return piter-&gt;key().size();
++    }
++
++    template&lt;typename V&gt; bool GetValue(V&amp; value) {
++        leveldb::Slice slValue = piter-&gt;value();
++        try {
++            CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
++            ssValue &gt;&gt; value;
++        } catch(std::exception &amp;e) {
++            return false;
++        }
++        return true;
++    }
++
++    unsigned int GetValueSize() {
++        return piter-&gt;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-&gt;NewIterator(iteroptions);
++    CLevelDBIterator *NewIterator() {
++        return new CLevelDBIterator(pdb-&gt;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&amp; tx, const uint256 hashBlock, Object&amp; entry)
+     }
+ }

++Value searchrawtransactions(const Array &amp;params, bool fHelp)
++{
++    if (fHelp || params.size() &lt; 1 || params.size() &gt; 4)
++        throw runtime_error(
++            &quot;searchrawtransactions &lt;address&gt; [verbose=1] [skip=0] [count=100]\n&quot;);
++
++    if (!fAddrIndex)
++        throw JSONRPCError(RPC_MISC_ERROR, &quot;Address index not enabled&quot;);
++
++    CBitcoinAddress address(params[0].get_str());
++    if (!address.IsValid())
++        throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, &quot;Invalid Bitcoin address&quot;);
++    CTxDestination dest = address.Get();
++
++    std::set&lt;CExtDiskTxPos&gt; setpos;
++    if (!FindTransactionsByDestination(dest, setpos))
++        throw JSONRPCError(RPC_DATABASE_ERROR, &quot;Cannot search for address&quot;);
++
++    int nSkip = 0;
++    int nCount = 100;
++    bool fVerbose = true;
++    if (params.size() &gt; 1)
++        fVerbose = (params[1].get_int() != 0);
++    if (params.size() &gt; 2)
++        nSkip = params[2].get_int();
++    if (params.size() &gt; 3)
++        nCount = params[3].get_int();
++
++    if (nSkip &lt; 0)
++        nSkip += setpos.size();
++    if (nSkip &lt; 0)
++        nSkip = 0;
++    if (nCount &lt; 0)
++        nCount = 0;
++
++    std::set&lt;CExtDiskTxPos&gt;::const_iterator it = setpos.begin();
++    while (it != setpos.end() &amp;&amp; nSkip--) it++;
++
++    Array result;
++    while (it != setpos.end() &amp;&amp; nCount--) {
++        CTransaction tx;
++        uint256 hashBlock;
++        if (!ReadTransaction(tx, *it, hashBlock))
++            throw JSONRPCError(RPC_DESERIALIZATION_ERROR, &quot;Cannot read transaction from disk&quot;);
++        CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
++        ssTx &lt;&lt; tx;
++        string strHex = HexStr(ssTx.begin(), ssTx.end());
++        if (fVerbose) {
++            Object object;
++            TxToJSON(tx, hashBlock, object);
++            object.push_back(Pair(&quot;hex&quot;, strHex));
++            result.push_back(object);
++        } else {
++            result.push_back(strHex);
++        }
++        it++;
++    }
++    return result;
++}
++
+ Value getrawtransaction(const Array&amp; params, bool fHelp)
+ {
+     if (fHelp || params.size() &lt; 1 || params.size() &gt; 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&lt;uint256, CCoins&gt; &amp;mapCoins, CBlockI
+ }

+ CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDB(GetDataDir() / &quot;blocks&quot; / &quot;index&quot;, nCacheSize, fMemory, fWipe) {
++    if (!Read('S', salt)) {
++        salt = GetRandHash();
++        Write('S', salt);
++    }
+ }

+ bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex&amp; blockindex)
+@@ -113,8 +117,8 @@ bool CBlockTreeDB::ReadLastBlockFile(int &amp;nFile) {
+ }

+ bool CCoinsViewDB::GetStats(CCoinsStats &amp;stats) {
+-    leveldb::Iterator *pcursor = db.NewIterator();
+-    pcursor-&gt;SeekToFirst();
++    CLevelDBIterator *pcursor = db.NewIterator();
++    pcursor-&gt;Seek('c');

+     CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
+     stats.hashBlock = GetBestBlock()-&gt;GetBlockHash();
+@@ -122,22 +126,10 @@ bool CCoinsViewDB::GetStats(CCoinsStats &amp;stats) {
+     int64 nTotalAmount = 0;
+     while (pcursor-&gt;Valid()) {
+         boost::this_thread::interruption_point();
+-        try {
+-            leveldb::Slice slKey = pcursor-&gt;key();
+-            CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
+-            char chType;
+-            ssKey &gt;&gt; chType;
+-            if (chType == 'c') {
+-                leveldb::Slice slValue = pcursor-&gt;value();
+-                CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
+-                CCoins coins;
+-                ssValue &gt;&gt; coins;
+-                uint256 txhash;
+-                ssKey &gt;&gt; txhash;
+-                ss &lt;&lt; txhash;
+-                ss &lt;&lt; VARINT(coins.nVersion);
+-                ss &lt;&lt; (coins.fCoinBase ? 'c' : 'n'); 
+-                ss &lt;&lt; VARINT(coins.nHeight);
++        std::pair&lt;char, uint256&gt; key;
++        CCoins coins;
++        if (pcursor-&gt;GetKey(key) &amp;&amp; key.first == 'c') {
++            if (pcursor-&gt;GetValue(coins)) {
+                 stats.nTransactions++;
+                 for (unsigned int i=0; i&lt;coins.vout.size(); i++) {
+                     const CTxOut &amp;out = coins.vout[i];
+@@ -148,13 +140,15 @@ bool CCoinsViewDB::GetStats(CCoinsStats &amp;stats) {
+                         nTotalAmount += out.nValue;
+                     }
+                 }
+-                stats.nSerializedSize += 32 + slValue.size();
++                stats.nSerializedSize += 32 + pcursor-&gt;GetKeySize();
+                 ss &lt;&lt; VARINT(0);
++            } else {
++                return error(&quot;CCoinsViewDB::GetStats() : unable to read value&quot;);
+             }
+-            pcursor-&gt;Next();
+-        } catch (std::exception &amp;e) {
+-            return error(&quot;%s() : deserialize error&quot;, __PRETTY_FUNCTION__);
++        } else {
++            break;
+         }
++        pcursor-&gt;Next();
+     }
+     delete pcursor;
+     stats.nHeight = GetBestBlock()-&gt;nHeight;
+@@ -174,6 +168,40 @@ bool CBlockTreeDB::WriteTxIndex(const std::vector&lt;std::pair&lt;uint256, CDiskTxPos&gt;
+     return WriteBatch(batch);
+ }

++bool CBlockTreeDB::ReadAddrIndex(uint160 addrid, std::vector&lt;CExtDiskTxPos&gt; &amp;list) {
++    CLevelDBIterator *iter = NewIterator();
++    uint64 lookupid;
++    {
++        CHashWriter ss(SER_GETHASH, 0);
++        ss &lt;&lt; salt;
++        ss &lt;&lt; addrid;
++        lookupid = ss.GetHash().Get64(0);
++    }
++    iter-&gt;Seek(make_pair('a', lookupid));
++    while (iter-&gt;Valid()) {
++        std::pair&lt;std::pair&lt;char, uint64&gt;, CExtDiskTxPos&gt; key;
++        if (iter-&gt;GetKey(key) &amp;&amp; key.first.first == 'a' &amp;&amp; key.first.second == lookupid) {
++            list.push_back(key.second);
++        } else {
++            break;
++        }
++        iter-&gt;Next();
++    }
++    return true;
++}
++
++bool CBlockTreeDB::AddAddrIndex(const std::vector&lt;std::pair&lt;uint160, CExtDiskTxPos&gt; &gt; &amp;list) {
++    unsigned char foo[0];
++    CLevelDBBatch batch;
++    for (std::vector&lt;std::pair&lt;uint160, CExtDiskTxPos&gt; &gt;::const_iterator it=list.begin(); it!=list.end(); it++) {
++        CHashWriter ss(SER_GETHASH, 0);
++        ss &lt;&lt; salt;
++        ss &lt;&lt; it-&gt;first;
++        batch.Write(make_pair(make_pair('a', ss.GetHash().Get64(0)), it-&gt;second), FLATDATA(foo));
++    }
++    return WriteBatch(batch);
++}
++
+ bool CBlockTreeDB::WriteFlag(const std::string &amp;name, bool fValue) {
+     return Write(std::make_pair('F', name), fValue ? '1' : '0');
+ }
+@@ -188,26 +216,17 @@ bool CBlockTreeDB::ReadFlag(const std::string &amp;name, bool &amp;fValue) {

+ bool CBlockTreeDB::LoadBlockIndexGuts()
+ {
+-    leveldb::Iterator *pcursor = NewIterator();
++    CLevelDBIterator *pcursor = NewIterator();

+-    CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
+-    ssKeySet &lt;&lt; make_pair('b', uint256(0));
+-    pcursor-&gt;Seek(ssKeySet.str());
++    pcursor-&gt;Seek(make_pair('b', uint256(0)));

+     // Load mapBlockIndex
+     while (pcursor-&gt;Valid()) {
+         boost::this_thread::interruption_point();
+-        try {
+-            leveldb::Slice slKey = pcursor-&gt;key();
+-            CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
+-            char chType;
+-            ssKey &gt;&gt; chType;
+-            if (chType == 'b') {
+-                leveldb::Slice slValue = pcursor-&gt;value();
+-                CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
+-                CDiskBlockIndex diskindex;
+-                ssValue &gt;&gt; diskindex;
+-
++        std::pair&lt;char, uint256&gt; key;
++        if (pcursor-&gt;GetKey(key) &amp;&amp; key.first == 'b') {
++            CDiskBlockIndex diskindex;
++            if (pcursor-&gt;GetValue(diskindex)) {
+                 // Construct block index object
+                 CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
+                 pindexNew-&gt;pprev          = InsertBlockIndex(diskindex.hashPrev);
+@@ -232,10 +251,10 @@ bool CBlockTreeDB::LoadBlockIndexGuts()

+                 pcursor-&gt;Next();
+             } else {
+-                break; // if shutdown requested or finished loading block index
++                return error(&quot;LoadBlockIndex() : failed to read value&quot;);
+             }
+-        } catch (std::exception &amp;e) {
+-            return error(&quot;%s() : deserialize error&quot;, __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&amp;);
+     void operator=(const CBlockTreeDB&amp;);
+ public:
+@@ -45,6 +46,8 @@ class CBlockTreeDB : public CLevelDB
+     bool ReadReindexing(bool &amp;fReindex);
+     bool ReadTxIndex(const uint256 &amp;txid, CDiskTxPos &amp;pos);
+     bool WriteTxIndex(const std::vector&lt;std::pair&lt;uint256, CDiskTxPos&gt; &gt; &amp;list);
++    bool ReadAddrIndex(uint160 addrid, std::vector&lt;CExtDiskTxPos&gt; &amp;list);
++    bool AddAddrIndex(const std::vector&lt;std::pair&lt;uint160, CExtDiskTxPos&gt; &gt; &amp;list);
+     bool WriteFlag(const std::string &amp;name, bool fValue);
+     bool ReadFlag(const std::string &amp;name, bool &amp;fValue);
+     bool LoadBlockIndexGuts();
</ins></span></pre></div>
<a id="usersanddambitcoinpatch_src_main_cppdiff"></a>
<div class="addfile"><h4>Added: users/anddam/bitcoin/patch_src_main_cpp.diff (0 => 117082)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,180 @@
</span><ins>+--- 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&amp; tx, const CDiskTxPos &amp;pos, uint256 &amp;hashBlock) {
++    CAutoFile file(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION);
++    CBlockHeader header;
++    try {
++        file &gt;&gt; header;
++        fseek(file, pos.nTxOffset, SEEK_CUR);
++        file &gt;&gt; tx;
++    } catch (std::exception &amp;e) {
++        return error(&quot;%s() : deserialize or I/O error&quot;, __PRETTY_FUNCTION__);
++    }
++    hashBlock = header.GetHash();
++    return true;
++}
++
++bool FindTransactionsByDestination(const CTxDestination &amp;dest, std::set&lt;CExtDiskTxPos&gt; &amp;setpos) {
++    uint160 addrid = 0;
++    const CKeyID *pkeyid = boost::get&lt;CKeyID&gt;(&amp;dest);
++    if (pkeyid)
++        addrid = static_cast&lt;uint160&gt;(*pkeyid);
++    if (!addrid) {
++        const CScriptID *pscriptid = boost::get&lt;CScriptID&gt;(&amp;dest);
++        if (pscriptid)
++            addrid = static_cast&lt;uint160&gt;(*pscriptid);
++    }
++    if (!addrid)
++        return false;
++
++    LOCK(cs_main);
++    if (!fAddrIndex)
++        return false;
++    std::vector&lt;CExtDiskTxPos&gt; vPos;
++    if (!pblocktree-&gt;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 &amp;hash, CTransaction &amp;txOut, uint256 &amp;hashBlock, bool fAllowSlow)
+@@ -981,16 +1018,8 @@
+         if (fTxIndex) {
+             CDiskTxPos postx;
+             if (pblocktree-&gt;ReadTxIndex(hash, postx)) {
+-                CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION);
+-                CBlockHeader header;
+-                try {
+-                    file &gt;&gt; header;
+-                    fseek(file, postx.nTxOffset, SEEK_CUR);
+-                    file &gt;&gt; txOut;
+-                } catch (std::exception &amp;e) {
+-                    return error(&quot;%s() : deserialize or I/O error&quot;, __PRETTY_FUNCTION__);
+-                }
+-                hashBlock = header.GetHash();
++                if (!ReadTransaction(txOut, postx, hashBlock))
++                    return false;
+                 if (txOut.GetHash() != hash)
+                     return error(&quot;%s() : txid mismatch&quot;, __PRETTY_FUNCTION__);
+                 return true;
+@@ -1596,6 +1625,32 @@
+     scriptcheckqueue.Thread();
+ }

++// Index either: a) every data push &gt;=8 bytes,  b) if no such pushes, the entire script
++void static BuildAddrIndex(const CScript &amp;script, const CExtDiskTxPos &amp;pos, std::vector&lt;std::pair&lt;uint160, CExtDiskTxPos&gt; &gt; &amp;out) {
++    CScript::const_iterator pc = script.begin();
++    CScript::const_iterator pend = script.end();
++    std::vector&lt;unsigned char&gt; data;
++    opcodetype opcode;
++    bool fHaveData = false;
++    while (pc &lt; pend) {
++        script.GetOp(pc, opcode, data);
++        if (0 &lt;= opcode &amp;&amp; opcode &lt;= OP_PUSHDATA4 &amp;&amp; data.size() &gt;= 8) { // data element
++            uint160 addrid = 0;
++            if (data.size() &lt;= 20) {
++                memcpy(&amp;addrid, &amp;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 &amp;state, CBlockIndex* pindex, CCoinsViewCache &amp;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-&gt;GetBlockPos(), GetSizeOfCompactSize(vtx.size()));
+-    std::vector&lt;std::pair&lt;uint256, CDiskTxPos&gt; &gt; vPos;
+-    vPos.reserve(vtx.size());
++    CExtDiskTxPos pos(CDiskTxPos(pindex-&gt;GetBlockPos(), GetSizeOfCompactSize(vtx.size())), pindex-&gt;nHeight);
++    std::vector&lt;std::pair&lt;uint256, CDiskTxPos&gt; &gt; vPosTxid;
++    std::vector&lt;std::pair&lt;uint160, CExtDiskTxPos&gt; &gt; vPosAddrid;
++    if (fTxIndex)
++        vPosTxid.reserve(vtx.size());
++    if (fAddrIndex)
++        vPosAddrid.reserve(4*vtx.size());
+     for (unsigned int i=0; i&lt;vtx.size(); i++)
+     {
+         const CTransaction &amp;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 &amp;txin, tx.vin) {
++                    const CCoins &amp;coins = view.GetCoins(txin.prevout.hash);
++                    BuildAddrIndex(coins.vout[txin.prevout.n].scriptPubKey, pos, vPosAddrid);
++                }
++            }
++            BOOST_FOREACH(const CTxOut &amp;txout, tx.vout)
++                BuildAddrIndex(txout.scriptPubKey, pos, vPosAddrid);
++        }

+         CTxUndo txundo;
+         tx.UpdateCoins(state, view, txundo, pindex-&gt;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-&gt;WriteTxIndex(vPos))
++        if (!pblocktree-&gt;WriteTxIndex(vPosTxid))
+             return state.Abort(_(&quot;Failed to write transaction index&quot;));
++    if (fAddrIndex)
++        if (!pblocktree-&gt;AddAddrIndex(vPosAddrid))
++            return state.Abort(_(&quot;Failed to write address index&quot;));

+     // add this block to the view's block chain
+     assert(view.SetBestBlock(pindex));
+@@ -2608,6 +2681,9 @@
+     pblocktree-&gt;ReadFlag(&quot;txindex&quot;, fTxIndex);
+     printf(&quot;LoadBlockIndexDB(): transaction index %s\n&quot;, fTxIndex ? &quot;enabled&quot; : &quot;disabled&quot;);

++    pblocktree-&gt;ReadFlag(&quot;addrindex&quot;, fAddrIndex);
++    printf(&quot;LoadBlockIndexDB(): address index %s\n&quot;, fAddrIndex ? &quot;enabled&quot; : &quot;disabled&quot;);
++
+     // Load hashBestChain pointer to end of best chain
+     pindexBest = pcoinsTip-&gt;GetBestBlock();
+     if (pindexBest == NULL)
+@@ -2745,6 +2821,8 @@
+     // Use the provided setting for -txindex in the new database
+     fTxIndex = GetBoolArg(&quot;-txindex&quot;, false);
+     pblocktree-&gt;WriteFlag(&quot;txindex&quot;, fTxIndex);
++    fAddrIndex = GetBoolArg(&quot;-addrindex&quot;, false);
++    pblocktree-&gt;WriteFlag(&quot;addrindex&quot;, fAddrIndex);
+     printf(&quot;Initializing databases...\n&quot;);

+     // Only add the genesis block if not reindexing (in which case we reuse the one already on disk)
</ins></span></pre></div>
<a id="usersanddambitcoinpatch_src_main_hdiff"></a>
<div class="addfile"><h4>Added: users/anddam/bitcoin/patch_src_main_h.diff (0 => 117082)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,77 @@
</span><ins>+--- 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 &amp;a, const CDiskTxPos &amp;b) {
++        return (a.nFile == b.nFile &amp;&amp; a.nPos == b.nPos &amp;&amp; a.nTxOffset == b.nTxOffset);
++    }
++
++    friend bool operator!=(const CDiskTxPos &amp;a, const CDiskTxPos &amp;b) {
++        return !(a == b);
++    }
++
++    friend bool operator&lt;(const CDiskTxPos &amp;a, const CDiskTxPos &amp;b) {
++        return  (a.nFile &lt; b.nFile || (
++                (a.nFile == b.nFile) &amp;&amp; (a.nPos &lt; b.nPos || (
++                                        (a.nPos == b.nPos) &amp;&amp; (a.nTxOffset &lt; b.nTxOffset)))));
++    }
+ };

++struct CExtDiskTxPos : public CDiskTxPos
++{
++    unsigned int nHeight;
++
++    IMPLEMENT_SERIALIZE(
++        READWRITE(*(CDiskTxPos*)this);
++        READWRITE(VARINT(nHeight));
++    )
++
++    CExtDiskTxPos(const CDiskTxPos &amp;pos, int nHeightIn) : CDiskTxPos(pos), nHeight(nHeightIn) {
++    }
++
++    CExtDiskTxPos() {
++        SetNull();
++    }
++
++    void SetNull() {
++        CDiskTxPos::SetNull();
++        nHeight = 0;
++    }
++
++    friend bool operator==(const CExtDiskTxPos &amp;a, const CExtDiskTxPos &amp;b) {
++        return (a.nHeight == b.nHeight &amp;&amp; a.nFile == b.nFile &amp;&amp; a.nPos == b.nPos &amp;&amp; a.nTxOffset == b.nTxOffset);
++    }
++ 
++    friend bool operator!=(const CExtDiskTxPos &amp;a, const CExtDiskTxPos &amp;b) {
++        return !(a == b);
++    }
++
++    friend bool operator&lt;(const CExtDiskTxPos &amp;a, const CExtDiskTxPos &amp;b) {
++        if (a.nHeight &lt; b.nHeight) return true;
++        if (a.nHeight &gt; b.nHeight) return false;
++        return ((const CDiskTxPos)a &lt; (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 &amp;&amp; n == (unsigned int) -1); }
+ };

++bool ReadTransaction(CTransaction&amp; tx, const CDiskTxPos &amp;pos, uint256 &amp;hashBlock);
++bool FindTransactionsByDestination(const CTxDestination &amp;dest, std::set&lt;CExtDiskTxPos&gt; &amp;setpos);


+ /** An outpoint - a combination of a transaction hash and an index n into its vout */
</ins></span></pre></div>
<a id="usersanddambitcoinpatch_src_src_serialize_hdiff"></a>
<div class="addfile"><h4>Added: users/anddam/bitcoin/patch_src_src_serialize_h.diff (0 => 117082)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,22 @@
</span><ins>+--- 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&amp; x=char()) { return vch.insert(it, x); }
+     void insert(iterator it, size_type n, const char&amp; x) { vch.insert(it, n, x); }

+-    void insert(iterator it, const_iterator first, const_iterator last)
+-    {
+-        assert(last - first &gt;= 0);
+-        if (it == vch.begin() + nReadPos &amp;&amp; (unsigned int)(last - first) &lt;= nReadPos)
+-        {
+-            // special case for inserting at the front when there's room
+-            nReadPos -= (last - first);
+-            memcpy(&amp;vch[nReadPos], &amp;first[0], last - first);
+-        }
+-        else
+-            vch.insert(it, first, last);
+-    }
+-
+     void insert(iterator it, std::vector&lt;char&gt;::const_iterator first, std::vector&lt;char&gt;::const_iterator last)
+     {
+         assert(last - first &gt;= 0);
</ins></span></pre>
</div>
</div>

</body>
</html>