| 3484 | } |
| 3485 | |
| 3486 | static RPCMethod loadtxoutset() |
| 3487 | { |
| 3488 | return RPCMethod{ |
| 3489 | "loadtxoutset", |
| 3490 | "Load the serialized UTXO set from a file.\n" |
| 3491 | "Once this snapshot is loaded, its contents will be " |
| 3492 | "deserialized into a second chainstate data structure, which is then used to sync to " |
| 3493 | "the network's tip. " |
| 3494 | "Meanwhile, the original chainstate will complete the initial block download process in " |
| 3495 | "the background, eventually validating up to the block that the snapshot is based upon.\n\n" |
| 3496 | |
| 3497 | "The result is a usable bitcoind instance that is current with the network tip in a " |
| 3498 | "matter of minutes rather than hours. UTXO snapshot are typically obtained from " |
| 3499 | "third-party sources (HTTP, torrent, etc.) which is reasonable since their " |
| 3500 | "contents are always checked by hash.\n\n" |
| 3501 | |
| 3502 | "You can find more information on this process in the `assumeutxo` design " |
| 3503 | "document (<https://github.com/bitcoin/bitcoin/blob/master/doc/design/assumeutxo.md>).", |
| 3504 | { |
| 3505 | {"path", |
| 3506 | RPCArg::Type::STR, |
| 3507 | RPCArg::Optional::NO, |
| 3508 | "path to the snapshot file. If relative, will be prefixed by datadir."}, |
| 3509 | }, |
| 3510 | RPCResult{ |
| 3511 | RPCResult::Type::OBJ, "", "", |
| 3512 | { |
| 3513 | {RPCResult::Type::NUM, "coins_loaded", "the number of coins loaded from the snapshot"}, |
| 3514 | {RPCResult::Type::STR_HEX, "tip_hash", "the hash of the base of the snapshot"}, |
| 3515 | {RPCResult::Type::NUM, "base_height", "the height of the base of the snapshot"}, |
| 3516 | {RPCResult::Type::STR, "path", "the absolute path that the snapshot was loaded from"}, |
| 3517 | } |
| 3518 | }, |
| 3519 | RPCExamples{ |
| 3520 | HelpExampleCli("-rpcclienttimeout=0 loadtxoutset", "utxo.dat") |
| 3521 | }, |
| 3522 | [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue |
| 3523 | { |
| 3524 | NodeContext& node = EnsureAnyNodeContext(request.context); |
| 3525 | ChainstateManager& chainman = EnsureChainman(node); |
| 3526 | const fs::path path{AbsPathForConfigVal(EnsureArgsman(node), fs::u8path(self.Arg<std::string_view>("path")))}; |
| 3527 | |
| 3528 | FILE* file{fsbridge::fopen(path, "rb")}; |
| 3529 | AutoFile afile{file}; |
| 3530 | if (afile.IsNull()) { |
| 3531 | throw JSONRPCError( |
| 3532 | RPC_INVALID_PARAMETER, |
| 3533 | "Couldn't open file " + path.utf8string() + " for reading."); |
| 3534 | } |
| 3535 | |
| 3536 | SnapshotMetadata metadata{chainman.GetParams().MessageStart()}; |
| 3537 | try { |
| 3538 | afile >> metadata; |
| 3539 | } catch (const std::ios_base::failure& e) { |
| 3540 | throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("Unable to parse metadata: %s", e.what())); |
| 3541 | } |
| 3542 | |
| 3543 | auto activation_result{chainman.ActivateSnapshot(afile, metadata, false)}; |
nothing calls this directly
no test coverage detected