| 1136 | } |
| 1137 | |
| 1138 | static RPCMethod submitheader() |
| 1139 | { |
| 1140 | return RPCMethod{ |
| 1141 | "submitheader", |
| 1142 | "Decode the given hexdata as a header and submit it as a candidate chain tip if valid." |
| 1143 | "\nThrows when the header is invalid.\n", |
| 1144 | { |
| 1145 | {"hexdata", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded block header data"}, |
| 1146 | }, |
| 1147 | RPCResult{ |
| 1148 | RPCResult::Type::NONE, "", "None"}, |
| 1149 | RPCExamples{ |
| 1150 | HelpExampleCli("submitheader", "\"aabbcc\"") + |
| 1151 | HelpExampleRpc("submitheader", "\"aabbcc\"") |
| 1152 | }, |
| 1153 | [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue |
| 1154 | { |
| 1155 | CBlockHeader h; |
| 1156 | if (!DecodeHexBlockHeader(h, request.params[0].get_str())) { |
| 1157 | throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block header decode failed"); |
| 1158 | } |
| 1159 | ChainstateManager& chainman = EnsureAnyChainman(request.context); |
| 1160 | { |
| 1161 | LOCK(cs_main); |
| 1162 | if (!chainman.m_blockman.LookupBlockIndex(h.hashPrevBlock)) { |
| 1163 | throw JSONRPCError(RPC_VERIFY_ERROR, "Must submit previous header (" + h.hashPrevBlock.GetHex() + ") first"); |
| 1164 | } |
| 1165 | } |
| 1166 | |
| 1167 | BlockValidationState state; |
| 1168 | chainman.ProcessNewBlockHeaders({{h}}, /*min_pow_checked=*/true, state); |
| 1169 | if (state.IsValid()) return UniValue::VNULL; |
| 1170 | if (state.IsError()) { |
| 1171 | throw JSONRPCError(RPC_VERIFY_ERROR, state.ToString()); |
| 1172 | } |
| 1173 | throw JSONRPCError(RPC_VERIFY_ERROR, state.GetRejectReason()); |
| 1174 | }, |
| 1175 | }; |
| 1176 | } |
| 1177 | |
| 1178 | void RegisterMiningRPCCommands(CRPCTable& t) |
| 1179 | { |
nothing calls this directly
no test coverage detected