| 1258 | } |
| 1259 | |
| 1260 | std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptContext ctx, const SigningProvider& provider) |
| 1261 | { |
| 1262 | if (ctx == ParseScriptContext::P2TR && script.size() == 34 && script[0] == 32 && script[33] == OP_CHECKSIG) { |
| 1263 | XOnlyPubKey key{Span{script}.subspan(1, 32)}; |
| 1264 | return std::make_unique<PKDescriptor>(InferXOnlyPubkey(key, ctx, provider), true); |
| 1265 | } |
| 1266 | |
| 1267 | std::vector<std::vector<unsigned char>> data; |
| 1268 | TxoutType txntype = Solver(script, data); |
| 1269 | |
| 1270 | if (txntype == TxoutType::PUBKEY && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) { |
| 1271 | CPubKey pubkey(data[0]); |
| 1272 | if (pubkey.IsValid()) { |
| 1273 | return std::make_unique<PKDescriptor>(InferPubkey(pubkey, ctx, provider)); |
| 1274 | } |
| 1275 | } |
| 1276 | if (txntype == TxoutType::PUBKEYHASH && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) { |
| 1277 | uint160 hash(data[0]); |
| 1278 | CKeyID keyid(hash); |
| 1279 | CPubKey pubkey; |
| 1280 | if (provider.GetPubKey(keyid, pubkey)) { |
| 1281 | return std::make_unique<PKHDescriptor>(InferPubkey(pubkey, ctx, provider)); |
| 1282 | } |
| 1283 | } |
| 1284 | if (txntype == TxoutType::WITNESS_V0_KEYHASH && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH)) { |
| 1285 | uint160 hash(data[0]); |
| 1286 | CKeyID keyid(hash); |
| 1287 | CPubKey pubkey; |
| 1288 | if (provider.GetPubKey(keyid, pubkey)) { |
| 1289 | return std::make_unique<WPKHDescriptor>(InferPubkey(pubkey, ctx, provider)); |
| 1290 | } |
| 1291 | } |
| 1292 | if (txntype == TxoutType::MULTISIG && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) { |
| 1293 | std::vector<std::unique_ptr<PubkeyProvider>> providers; |
| 1294 | for (size_t i = 1; i + 1 < data.size(); ++i) { |
| 1295 | CPubKey pubkey(data[i]); |
| 1296 | providers.push_back(InferPubkey(pubkey, ctx, provider)); |
| 1297 | } |
| 1298 | return std::make_unique<MultisigDescriptor>((int)data[0][0], std::move(providers)); |
| 1299 | } |
| 1300 | if (txntype == TxoutType::SCRIPTHASH && ctx == ParseScriptContext::TOP) { |
| 1301 | uint160 hash(data[0]); |
| 1302 | CScriptID scriptid(hash); |
| 1303 | CScript subscript; |
| 1304 | if (provider.GetCScript(scriptid, subscript)) { |
| 1305 | auto sub = InferScript(subscript, ParseScriptContext::P2SH, provider); |
| 1306 | if (sub) return std::make_unique<SHDescriptor>(std::move(sub)); |
| 1307 | } |
| 1308 | } |
| 1309 | if (txntype == TxoutType::WITNESS_V0_SCRIPTHASH && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH)) { |
| 1310 | CScriptID scriptid; |
| 1311 | CRIPEMD160().Write(data[0].data(), data[0].size()).Finalize(scriptid.begin()); |
| 1312 | CScript subscript; |
| 1313 | if (provider.GetCScript(scriptid, subscript)) { |
| 1314 | auto sub = InferScript(subscript, ParseScriptContext::P2WSH, provider); |
| 1315 | if (sub) return std::make_unique<WSHDescriptor>(std::move(sub)); |
| 1316 | } |
| 1317 | } |
no test coverage detected