View in context in the libbitcoin Slack #general mirror.
// This script type is fabricated in witness::extract_taproot.
constexpr bool script::is_pay_taproot_key_path_pattern(
const operations& ops) NOEXCEPT
{
return ops.size() == 1
&& ops[0].code() == opcode::checksig;
}
constexpr bool script::is_pay_tapscript_single_pattern(
const operations& ops) NOEXCEPT
{
return ops.size() == 2
&& ops[0].data().size() == ec_xonly_size
&& ops[1].code() == opcode::checksig;
}
constexpr bool script::is_pay_tapscript_timelock_pattern(
const operations& ops) NOEXCEPT
{
return ops.size() == 5u
&& ops[0].is_nonnegative()
&& ops[1].is_timelock()
&& ops[2].code() == opcode::drop
&& ops[3].data().size() == ec_xonly_size
&& ops[4].code() == opcode::checksig;
}
constexpr bool script::is_pay_tapscript_inscription_pattern(
const operations& ops) NOEXCEPT
{
return ops.size() > 4u
&& ops[0].data().size() == ec_xonly_size
&& ops[1].code() == opcode::checksig
&& ops[2].code() == opcode::push_size_0
&& ops[3].code() == opcode::if_
&& ops.back().code() == opcode::endif;
}
constexpr bool script::is_pay_tapscript_threshold_pattern(
const operations& ops) NOEXCEPT
{
const auto size = ops.size();
if (is_zero(size))
return false;
// opcode::within requires an additional number in the script.
const auto within = (ops.back().code() == opcode::within);
if ((is_even(size) == within) ||
(size < (4u + to_int<uint8_t>(within))))
return false;
auto op = ops.begin();
if ((op++)->data().size() != ec_xonly_size)
return false;
if ((op++)->code() != opcode::checksig)
return false;
while (op != std::prev(ops.end(), 2 + to_int(within)))
{
if (((op++)->data().size() != ec_xonly_size) ||
((op++)->code() != opcode::checksigadd))
return false;
}
if (!(op++)->is_unsigned32() || (within &&
!(op++)->is_unsigned32()))
return false;
return op->is_threshold();
}
constexpr bool script::is_pay_tapscript_multisig_pattern(
const operations& ops) NOEXCEPT
{
if (ops.size() < 2u || !is_even(ops.size()))
return false;
auto op = ops.begin();
while (op != std::prev(ops.end(), 2))
{
if (((op++)->data().size() != ec_xonly_size) ||
((op++)->code() != opcode::checksigverify))
return false;
}
if (((op++)->data().size() != ec_xonly_size) ||
((op++)->code() != opcode::checksig))
return false;
return true;
}