| 558 | } |
| 559 | |
| 560 | Value getblockundo(const Array& params, bool fHelp) { |
| 561 | if (fHelp || params.size() < 1 || params.size() > 2) { |
| 562 | throw runtime_error( |
| 563 | "getblockundo \"hash or height\"\n" |
| 564 | "\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash'.\n" |
| 565 | "If verbose is true, returns an Object with information about block <hash>.\n" |
| 566 | "\nArguments:\n" |
| 567 | "1.\"hash or height\" (string or numeric, required) string for the block hash, or numeric for the block " |
| 568 | "height\n" |
| 569 | |
| 570 | "\nResult: block undo object\n" |
| 571 | "\nExamples:\n" + |
| 572 | HelpExampleCli("getblockundo", "\"d640d051704155b1fd3ec8d0331497448c259b0ab0499e109da7ae2bc7423bc2\"") + |
| 573 | "\nAs json rpc\n" + |
| 574 | HelpExampleRpc("getblockundo", "\"d640d051704155b1fd3ec8d0331497448c259b0ab0499e109da7ae2bc7423bc2\"")); |
| 575 | } |
| 576 | |
| 577 | // RPCTypeCheck(params, boost::assign::list_of(str_type)(bool_type)); disable this to allow either string or int argument |
| 578 | |
| 579 | std::string strHash; |
| 580 | if (int_type == params[0].type()) { |
| 581 | int height = params[0].get_int(); |
| 582 | if (height < 0 || height > chainActive.Height()) |
| 583 | throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range."); |
| 584 | |
| 585 | CBlockIndex* pBlockIndex = chainActive[height]; |
| 586 | strHash = pBlockIndex->GetBlockHash().GetHex(); |
| 587 | } else { |
| 588 | strHash = params[0].get_str(); |
| 589 | } |
| 590 | uint256 hash(uint256S(strHash)); |
| 591 | |
| 592 | auto mapIt = mapBlockIndex.find(hash); |
| 593 | if (mapIt == mapBlockIndex.end()) |
| 594 | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); |
| 595 | |
| 596 | CBlockIndex* pBlockIndex = mapIt->second; |
| 597 | |
| 598 | CBlockUndo blockUndo; |
| 599 | CDiskBlockPos pos = pBlockIndex->GetUndoPos(); |
| 600 | if (pos.IsNull()) |
| 601 | throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("no undo data available! block=%d:%s", |
| 602 | pBlockIndex->height, pBlockIndex->GetBlockHash().ToString())); |
| 603 | |
| 604 | if (!blockUndo.ReadFromDisk(pos, pBlockIndex->pprev->GetBlockHash())) |
| 605 | throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("read undo data failed! block=%d:%s", |
| 606 | pBlockIndex->height, pBlockIndex->GetBlockHash().ToString())); |
| 607 | |
| 608 | Object obj; |
| 609 | obj.push_back(Pair("block_height", pBlockIndex->height)); |
| 610 | obj.push_back(Pair("block_hash", pBlockIndex->pprev->GetBlockHash().ToString())); |
| 611 | obj.push_back(Pair("count", (int64_t)blockUndo.vtxundo.size())); |
| 612 | Array txArray; |
| 613 | for (size_t i = 0; i < blockUndo.vtxundo.size(); i++) { |
| 614 | CTxUndo txUndo = blockUndo.vtxundo[i]; |
| 615 | Object txObj; |
| 616 | txObj.push_back(Pair("index", (int64_t)i)); |
| 617 | txObj.push_back(Pair("tx_hash", txUndo.txid.ToString())); |
nothing calls this directly
no test coverage detected