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 #include @@ -1781,6 +1782,58 @@ } +Value makesnap(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 2) + throw runtime_error( + "makesnap \n" + "Write height-hash snapshot file of blocks up through , to ."); + + // 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 mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0])); @@ -2416,6 +2470,7 @@ if (strMethod == "walletpassphrase" && n > 1) ConvertTo(params[1]); if (strMethod == "listsinceblock" && n > 1) ConvertTo(params[1]); if (strMethod == "dumpblock" && n > 0) ConvertTo(params[0]); + if (strMethod == "makesnap" && n > 0) ConvertTo(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