21static const std::string
DUMP_MAGIC =
"BITCOIN_CORE_WALLET_DUMP";
27 std::string dump_filename =
args.
GetArg(
"-dumpfile",
"");
28 if (dump_filename.empty()) {
29 error =
_(
"No dump file provided. To use dump, -dumpfile=<filename> must be provided.");
36 error =
strprintf(
_(
"File %s already exists. If you are sure this is what you want, move it out of the way first."),
fs::PathToString(path));
39 std::ofstream dump_file;
41 if (dump_file.fail()) {
48 std::unique_ptr<DatabaseBatch> batch = db.
MakeBatch();
51 std::unique_ptr<DatabaseCursor> cursor = batch->GetNewCursor();
53 error =
_(
"Error: Couldn't create cursor into database");
59 dump_file.write(line.data(), line.size());
70 dump_file.write(line.data(), line.size());
84 error =
_(
"Error reading next record from wallet database");
88 std::string key_str =
HexStr(ss_key);
89 std::string value_str =
HexStr(ss_value);
90 line =
strprintf(
"%s,%s\n", key_str, value_str);
91 dump_file.write(line.data(), line.size());
117 wallet->WalletLogPrintf(
"Releasing wallet\n");
125 std::string dump_filename =
args.
GetArg(
"-dumpfile",
"");
126 if (dump_filename.empty()) {
127 error =
_(
"No dump file provided. To use createfromdump, -dumpfile=<filename> must be provided.");
137 std::ifstream dump_file{dump_path};
144 std::string magic_key;
145 std::getline(dump_file, magic_key,
',');
146 std::string version_value;
147 std::getline(dump_file, version_value,
'\n');
149 error =
strprintf(
_(
"Error: Dumpfile identifier record is incorrect. Got \"%s\", expected \"%s\"."), magic_key,
DUMP_MAGIC);
156 error =
strprintf(
_(
"Error: Unable to parse version %u as a uint32_t"), version_value);
161 error =
strprintf(
_(
"Error: Dumpfile version is not supported. This version of bitcoin-wallet only supports version 1 dumpfiles. Got dumpfile with version %s"), version_value);
165 std::string magic_hasher_line =
strprintf(
"%s,%s\n", magic_key, version_value);
166 hasher <<
Span{magic_hasher_line};
169 std::string format_key;
170 std::getline(dump_file, format_key,
',');
171 std::string format_value;
172 std::getline(dump_file, format_value,
'\n');
173 if (format_key !=
"format") {
174 error =
strprintf(
_(
"Error: Dumpfile format record is incorrect. Got \"%s\", expected \"format\"."), format_key);
179 std::string file_format =
args.
GetArg(
"-format", format_value);
180 if (file_format.empty()) {
181 error =
_(
"No wallet file format provided. To use createfromdump, -format=<format> must be provided.");
185 if (file_format ==
"bdb") {
187 }
else if (file_format ==
"sqlite") {
189 }
else if (file_format ==
"bdb_swap") {
192 error =
strprintf(
_(
"Unknown wallet file format \"%s\" provided. Please provide one of \"bdb\" or \"sqlite\"."), file_format);
195 if (file_format != format_value) {
196 warnings.push_back(
strprintf(
_(
"Warning: Dumpfile wallet format \"%s\" does not match command line specified format \"%s\"."), format_value, file_format));
198 std::string format_hasher_line =
strprintf(
"%s,%s\n", format_key, format_value);
199 hasher <<
Span{format_hasher_line};
206 std::unique_ptr<WalletDatabase> database =
MakeDatabase(wallet_path, options, status, error);
207 if (!database)
return false;
222 std::unique_ptr<DatabaseBatch> batch = db.
MakeBatch();
226 while (dump_file.good()) {
228 std::getline(dump_file, key,
',');
230 std::getline(dump_file, value,
'\n');
232 if (key ==
"checksum") {
233 std::vector<unsigned char> parsed_checksum =
ParseHex(value);
234 if (parsed_checksum.size() != checksum.
size()) {
235 error =
Untranslated(
"Error: Checksum is not the correct size");
239 std::copy(parsed_checksum.begin(), parsed_checksum.end(), checksum.
begin());
243 std::string line =
strprintf(
"%s,%s\n", key, value);
244 hasher <<
Span{line};
246 if (key.empty() || value.empty()) {
251 error =
strprintf(
_(
"Error: Got key that was not hex: %s"), key);
256 error =
strprintf(
_(
"Error: Got value that was not hex: %s"), value);
261 std::vector<unsigned char>
k =
ParseHex(key);
262 std::vector<unsigned char> v =
ParseHex(value);
263 if (!batch->Write(
Span{k},
Span{v})) {
264 error =
strprintf(
_(
"Error: Unable to write record to new wallet"));
271 uint256 comp_checksum = hasher.GetHash();
273 error =
_(
"Error: Missing checksum");
275 }
else if (checksum != comp_checksum) {
276 error =
strprintf(
_(
"Error: Dumpfile checksum does not match. Computed %s, expected %s"),
HexStr(comp_checksum),
HexStr(checksum));
295 fs::remove_all(wallet_path);
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Double ended buffer combining vector and stream-like interfaces.
A writer stream (for serialization) that computes a 256-bit hash.
A Span is an object that can refer to a contiguous sequence of objects.
constexpr bool IsNull() const
static constexpr unsigned int size()
constexpr unsigned char * begin()
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
An instance of this class represents one database.
virtual std::string Format()=0
virtual std::unique_ptr< DatabaseBatch > MakeBatch(bool flush_on_close=true)=0
Make a DatabaseBatch connected to this database.
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
static path absolute(const path &p)
static bool exists(const path &p)
static std::string PathToString(const path &path)
Convert path object to a byte string.
static path PathFromString(const std::string &string)
Convert byte string to path object.
void ReadDatabaseArgs(const ArgsManager &args, DatabaseOptions &options)
static void WalletToolReleaseWallet(CWallet *wallet)
std::unique_ptr< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
DBErrors
Error statuses for the wallet database.
bool CreateFromDump(const ArgsManager &args, const std::string &name, const fs::path &wallet_path, bilingual_str &error, std::vector< bilingual_str > &warnings)
bool DumpWallet(const ArgsManager &args, WalletDatabase &db, bilingual_str &error)
static const std::string DUMP_MAGIC
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
std::optional< DatabaseFormat > require_format
bilingual_str _(ConstevalStringLiteral str)
Translation function.
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
bool IsHex(std::string_view str)
bool ParseUInt32(std::string_view str, uint32_t *out)
Convert decimal string to unsigned 32-bit integer with strict parse error feedback.