forked from bitcoin/bitcoin
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add bitcoin-util command line utility
- Loading branch information
Showing
6 changed files
with
290 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#include <windows.h> // needed for VERSIONINFO | ||
#include "clientversion.h" // holds the needed client version information | ||
|
||
#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_BUILD | ||
#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_BUILD) | ||
#define VER_FILEVERSION VER_PRODUCTVERSION | ||
#define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR | ||
|
||
VS_VERSION_INFO VERSIONINFO | ||
FILEVERSION VER_FILEVERSION | ||
PRODUCTVERSION VER_PRODUCTVERSION | ||
FILEOS VOS_NT_WINDOWS32 | ||
FILETYPE VFT_APP | ||
BEGIN | ||
BLOCK "StringFileInfo" | ||
BEGIN | ||
BLOCK "040904E4" // U.S. English - multilingual (hex) | ||
BEGIN | ||
VALUE "CompanyName", "Bitcoin" | ||
VALUE "FileDescription", "bitcoin-util (CLI Bitcoin utility)" | ||
VALUE "FileVersion", VER_FILEVERSION_STR | ||
VALUE "InternalName", "bitcoin-util" | ||
VALUE "LegalCopyright", COPYRIGHT_STR | ||
VALUE "LegalTrademarks1", "Distributed under the MIT software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php." | ||
VALUE "OriginalFilename", "bitcoin-util.exe" | ||
VALUE "ProductName", "bitcoin-util" | ||
VALUE "ProductVersion", VER_PRODUCTVERSION_STR | ||
END | ||
END | ||
|
||
BLOCK "VarFileInfo" | ||
BEGIN | ||
VALUE "Translation", 0x0, 1252 // language neutral - multilingual (decimal) | ||
END | ||
END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
// Copyright (c) 2009-2020 The Bitcoin Core developers | ||
// Distributed under the MIT software license, see the accompanying | ||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||
|
||
#if defined(HAVE_CONFIG_H) | ||
#include <config/bitcoin-config.h> | ||
#endif | ||
|
||
#include <arith_uint256.h> | ||
#include <clientversion.h> | ||
#include <coins.h> | ||
#include <consensus/consensus.h> | ||
#include <core_io.h> | ||
#include <key_io.h> | ||
#include <policy/rbf.h> | ||
#include <primitives/transaction.h> | ||
#include <script/script.h> | ||
#include <script/sign.h> | ||
#include <script/signingprovider.h> | ||
#include <univalue.h> | ||
#include <util/moneystr.h> | ||
#include <util/rbf.h> | ||
#include <util/strencodings.h> | ||
#include <util/string.h> | ||
#include <util/system.h> | ||
#include <util/translation.h> | ||
|
||
#include <functional> | ||
#include <memory> | ||
#include <stdio.h> | ||
#include <thread> | ||
|
||
#include <boost/algorithm/string.hpp> | ||
|
||
static const int CONTINUE_EXECUTION=-1; | ||
|
||
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr; | ||
|
||
static void SetupBitcoinUtilArgs(ArgsManager &argsman) | ||
{ | ||
SetupHelpOptions(argsman); | ||
|
||
SetupChainParamsBaseOptions(argsman); | ||
} | ||
|
||
// This function returns either one of EXIT_ codes when it's expected to stop the process or | ||
// CONTINUE_EXECUTION when it's expected to continue further. | ||
static int AppInitUtil(int argc, char* argv[]) | ||
{ | ||
SetupBitcoinUtilArgs(gArgs); | ||
std::string error; | ||
if (!gArgs.ParseParameters(argc, argv, error)) { | ||
tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error); | ||
return EXIT_FAILURE; | ||
} | ||
|
||
// Check for chain settings (Params() calls are only valid after this clause) | ||
try { | ||
SelectParams(gArgs.GetChainName()); | ||
} catch (const std::exception& e) { | ||
tfm::format(std::cerr, "Error: %s\n", e.what()); | ||
return EXIT_FAILURE; | ||
} | ||
|
||
if (argc < 2 || HelpRequested(gArgs)) { | ||
// First part of help message is specific to this utility | ||
std::string strUsage = PACKAGE_NAME " bitcoin-util utility version " + FormatFullVersion() + "\n\n" + | ||
"Usage: bitcoin-util [options] [commands] Do stuff\n" + | ||
"\n"; | ||
strUsage += gArgs.GetHelpMessage(); | ||
|
||
tfm::format(std::cout, "%s", strUsage); | ||
|
||
if (argc < 2) { | ||
tfm::format(std::cerr, "Error: too few parameters\n"); | ||
return EXIT_FAILURE; | ||
} | ||
return EXIT_SUCCESS; | ||
} | ||
return CONTINUE_EXECUTION; | ||
} | ||
|
||
static void grind_task(uint32_t nBits, CBlockHeader& header_orig, uint32_t offset, uint32_t step, std::atomic<bool>& found) | ||
{ | ||
arith_uint256 target; | ||
bool neg, over; | ||
target.SetCompact(nBits, &neg, &over); | ||
if (target == 0 || neg || over) return; | ||
CBlockHeader header = header_orig; // working copy | ||
header.nNonce = offset; | ||
|
||
uint32_t finish = std::numeric_limits<uint32_t>::max() - step; | ||
finish = finish - (finish % step) + offset; | ||
|
||
while (!found && header.nNonce < finish) { | ||
const uint32_t next = (finish - header.nNonce < 5000*step) ? finish : header.nNonce + 5000*step; | ||
do { | ||
if (UintToArith256(header.GetHash()) <= target) { | ||
if (!found.exchange(true)) { | ||
header_orig.nNonce = header.nNonce; | ||
} | ||
return; | ||
} | ||
header.nNonce += step; | ||
} while(header.nNonce != next); | ||
} | ||
} | ||
|
||
static int Grind(int argc, char* argv[], std::string& strPrint) | ||
{ | ||
if (argc != 1) { | ||
strPrint = "Must specify block header to grind"; | ||
return 1; | ||
} | ||
|
||
CBlockHeader header; | ||
if (!DecodeHexBlockHeader(header, argv[0])) { | ||
strPrint = "Could not decode block header"; | ||
return 1; | ||
} | ||
|
||
uint32_t nBits = header.nBits; | ||
std::atomic<bool> found{false}; | ||
|
||
std::vector<std::thread> threads; | ||
int n_tasks = std::max(1u, std::thread::hardware_concurrency()); | ||
for (int i = 0; i < n_tasks; ++i) { | ||
threads.emplace_back( grind_task, nBits, std::ref(header), i, n_tasks, std::ref(found) ); | ||
} | ||
for (auto& t : threads) { | ||
t.join(); | ||
} | ||
if (!found) { | ||
strPrint = "Could not satisfy difficulty target"; | ||
return 1; | ||
} | ||
|
||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); | ||
ss << header; | ||
strPrint = HexStr(ss); | ||
return 0; | ||
} | ||
|
||
static int CommandLineUtil(int argc, char* argv[]) | ||
{ | ||
if (argc <= 1) return 1; | ||
|
||
std::string strPrint; | ||
int nRet = 0; | ||
|
||
try { | ||
while (argc > 1 && IsSwitchChar(argv[1][0]) && (argv[1][1] != 0)) { | ||
--argc; | ||
++argv; | ||
} | ||
|
||
char* command = argv[1]; | ||
if (strcmp(command, "grind") == 0) { | ||
nRet = Grind(argc-2, argv+2, strPrint); | ||
} else { | ||
strPrint = strprintf("Unknown command %s", command); | ||
nRet = 1; | ||
} | ||
} | ||
catch (const std::exception& e) { | ||
strPrint = std::string("error: ") + e.what(); | ||
nRet = EXIT_FAILURE; | ||
} | ||
catch (...) { | ||
PrintExceptionContinue(nullptr, "CommandLineUtil()"); | ||
throw; | ||
} | ||
|
||
if (strPrint != "") { | ||
tfm::format(nRet == 0 ? std::cout : std::cerr, "%s\n", strPrint); | ||
} | ||
return nRet; | ||
} | ||
|
||
int main(int argc, char* argv[]) | ||
{ | ||
SetupEnvironment(); | ||
|
||
try { | ||
int ret = AppInitUtil(argc, argv); | ||
if (ret != CONTINUE_EXECUTION) | ||
return ret; | ||
} | ||
catch (const std::exception& e) { | ||
PrintExceptionContinue(&e, "AppInitUtil()"); | ||
return EXIT_FAILURE; | ||
} catch (...) { | ||
PrintExceptionContinue(nullptr, "AppInitUtil()"); | ||
return EXIT_FAILURE; | ||
} | ||
|
||
int ret = EXIT_FAILURE; | ||
try { | ||
ret = CommandLineUtil(argc, argv); | ||
} | ||
catch (const std::exception& e) { | ||
PrintExceptionContinue(&e, "CommandLineUtil()"); | ||
} catch (...) { | ||
PrintExceptionContinue(nullptr, "CommandLineUtil()"); | ||
} | ||
return ret; | ||
} |