diff -uNr a/bitcoin/manifest.txt b/bitcoin/manifest.txt
--- a/bitcoin/manifest.txt ee37022b25601010b55c574cdabfce67f0d60b1003490ac6b5e3e9bfca1d815b6856f865ad81423b42d87e4f631fd2d51192175fab9d958809ee21395aee3565
+++ b/bitcoin/manifest.txt dc28fa9b371ffce0f67fb8b1ff6c9c81a22efd0daf4d395757adf9e4b8e3696e0f3eb4b0c2e8d8b249e9fd276bcc3a71305d5a1cecf785c752280c8311588ca9
@@ -28,3 +28,4 @@
 542413 asciilifeform_aggressive_pushgetblocks asciilifeform Issue PushGetBlocks command to any peer that issues 'version' command
 542413 mod6_excise_hash_truncation mod6 Regrind of ben_vulpes original; removes truncation of hashes printed to TRB log file
 543661 asciilifeform_whogaveblox asciilifeform Record the origin of every incoming candidate block (whether accepted or rejected)
+546492 asciilifeform_makesnap asciilifeform Add a command that produces machine-readable hash snapshots of the main chain through a given height.
diff -uNr a/bitcoin/src/bitcoinrpc.cpp b/bitcoin/src/bitcoinrpc.cpp
--- a/bitcoin/src/bitcoinrpc.cpp ede2e19dd0ce3d03f54689cbeda30b4b36152f7e532b3d34f0f8c55bb292f7d25c149b88162d96a8208997237a32566d0e555aa7105bfed8175983d80ad892e6
+++ b/bitcoin/src/bitcoinrpc.cpp 2668e61cd2d503bdfab0f8d411803e48e7714308be1206b9090c0658ab37f1b0ded0071b5a357abc2b21e5ff7a812b7630251b0b14a5330401c61cb4341a0c21
@@ -7,6 +7,7 @@
 #include "db.h"
 #include "net.h"
 #include "init.h"
+#include "knobs.h"
 #undef printf
 #include <boost/asio.hpp>
 #include <boost/iostreams/concepts.hpp>
@@ -1781,6 +1782,58 @@
 }
 
 
+Value makesnap(const Array& params, bool fHelp)
+{
+    if (fHelp || params.size() != 2)
+        throw runtime_error(
+            "makesnap <height> <filename>\n"
+            "Write height-hash snapshot file of blocks up through <height>, to <filename>.");
+    
+    // Where to stop:
+    int stop_height = 0;
+    if (params.size() > 0)
+        stop_height = params[0].get_int();
+    
+    // Check that we actually have blocks to this height with safety margin:
+    if (stop_height > nBestHeight - SAFE_SNAPSHOT_MARGIN)
+      throw runtime_error(strprintf(_("Requested snapshot exceeds nBestHeight - %d!\n"),
+                                    SAFE_SNAPSHOT_MARGIN));
+    
+    // Path to dump snapshot file to:
+    string filename = params[1].get_str();
+    
+    // Open destination snapshot file
+    CAutoFile fileout = fopen(filename.c_str(), "w");
+    
+    // Starting at the genesis:
+    int height = 0;
+    CBlockIndex *pindex = pindexGenesisBlock;
+    
+    // Up through the desired height:
+    while (height <= stop_height) {
+        // Get current block height
+        height = pindex->nHeight;
+        
+        // Fetch the block itself
+        CBlock block;
+        block.ReadFromDisk(pindex);
+        
+        // Compute the block's header hash
+        uint256 hash = block.GetHash();
+
+        // Write block's height and header hash to the snapshot file
+        fprintf(fileout, "%d %s\n", height, hash.ToString().c_str());
+
+        // Advance to next block in main chain
+        pindex = pindex->pnext;
+    }
+    
+    // We're done:
+    printf("Snapshot written to %s.\n", filename.c_str());
+    return true;
+}
+
+
 Value dumpblock(const Array& params, bool fHelp)
 {
     if (fHelp || params.size() != 2)
@@ -1887,6 +1940,7 @@
     make_pair("listsinceblock",        &listsinceblock),
     make_pair("dumpblock",              &dumpblock),
     make_pair("eatblock",               &eatblock),
+    make_pair("makesnap",               &makesnap),
 };
 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
 
@@ -2416,6 +2470,7 @@
         if (strMethod == "walletpassphrase"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
         if (strMethod == "listsinceblock"         && n > 1) ConvertTo<boost::int64_t>(params[1]);
 	if (strMethod == "dumpblock"              && n > 0) ConvertTo<boost::int64_t>(params[0]);
+        if (strMethod == "makesnap"               && n > 0) ConvertTo<boost::int64_t>(params[0]);
         if (strMethod == "sendmany"               && n > 1)
         {
             string s = params[1].get_str();
diff -uNr a/bitcoin/src/knobs.h b/bitcoin/src/knobs.h
--- a/bitcoin/src/knobs.h 9b88b8f60d9a0ae98f9dd148dba06e132b6b1fc199719eacb3270fe6ce2af889422eee62c2cb08c3b93f22069aea880c657e771c4e4b4157a69c321550c8fc73
+++ b/bitcoin/src/knobs.h 807ded6d51652b1c52c64e03f6ed9516292201ed00fdca573a094d577bf085dd3ec0df2321302ef5dbdf301580fa4dbdf94cd9965250c9f6d790786bb0e72b40
@@ -4,4 +4,10 @@
 #define  DEFAULT_CLIENT_NAME       "therealbitcoin.org"
 #define  DEFAULT_CLIENT_VERSION    99999 /* 50400 */
 
+/****************************************************************************
+ * Safety margin for snapshots generated by 'makesnap' command:             *
+ * Must not risk snapshotting an orphaned chain at the current leading end. *
+ ****************************************************************************/
+#define  SAFE_SNAPSHOT_MARGIN      50
+
 #endif