| 1325 | }; |
| 1326 | |
| 1327 | UniValue getchaintips(const UniValue& params, bool fHelp) |
| 1328 | { |
| 1329 | if (fHelp || params.size() != 0) |
| 1330 | throw runtime_error( |
| 1331 | "getchaintips\n" |
| 1332 | "Return information about all known tips in the block tree," |
| 1333 | " including the main chain as well as orphaned branches.\n" |
| 1334 | "\nResult:\n" |
| 1335 | "[\n" |
| 1336 | " {\n" |
| 1337 | " \"height\": xxxx, (numeric) height of the chain tip\n" |
| 1338 | " \"hash\": \"xxxx\", (string) block hash of the tip\n" |
| 1339 | " \"branchlen\": 0 (numeric) zero for main chain\n" |
| 1340 | " \"status\": \"active\" (string) \"active\" for the main chain\n" |
| 1341 | " },\n" |
| 1342 | " {\n" |
| 1343 | " \"height\": xxxx,\n" |
| 1344 | " \"hash\": \"xxxx\",\n" |
| 1345 | " \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n" |
| 1346 | " \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n" |
| 1347 | " }\n" |
| 1348 | "]\n" |
| 1349 | "Possible values for status:\n" |
| 1350 | "1. \"invalid\" This branch contains at least one invalid block\n" |
| 1351 | "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n" |
| 1352 | "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n" |
| 1353 | "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n" |
| 1354 | "5. \"active\" This is the tip of the active main chain, which is certainly valid\n" |
| 1355 | "\nExamples:\n" + |
| 1356 | HelpExampleCli("getchaintips", "") + HelpExampleRpc("getchaintips", "")); |
| 1357 | |
| 1358 | LOCK(cs_main); |
| 1359 | |
| 1360 | /* Build up a list of chain tips. We start with the list of all |
| 1361 | known blocks, and successively remove blocks that appear as pprev |
| 1362 | of another block. */ |
| 1363 | std::set<const CBlockIndex*, CompareBlocksByHeight> setTips; |
| 1364 | std::set<const CBlockIndex*> setOrphans; |
| 1365 | std::set<const CBlockIndex*> setPrevs; |
| 1366 | |
| 1367 | for (const PAIRTYPE(const uint256, CBlockIndex*)& item : mapBlockIndex) { |
| 1368 | if (!chainActive.Contains(item.second)) { |
| 1369 | setOrphans.insert(item.second); |
| 1370 | setPrevs.insert(item.second->pprev); |
| 1371 | } |
| 1372 | } |
| 1373 | |
| 1374 | for (std::set<const CBlockIndex*>::iterator it = setOrphans.begin(); it != setOrphans.end(); ++it) { |
| 1375 | if (setPrevs.erase(*it) == 0) { |
| 1376 | setTips.insert(*it); |
| 1377 | } |
| 1378 | } |
| 1379 | |
| 1380 | // Always report the currently active tip. |
| 1381 | setTips.insert(chainActive.Tip()); |
| 1382 | |
| 1383 | /* Construct the output array. */ |
| 1384 | UniValue res(UniValue::VARR); |
nothing calls this directly
no test coverage detected