mirror of
https://github.com/bitcoin/bips.git
synced 2026-02-09 15:23:09 +00:00
43 lines
1.4 KiB
Python
43 lines
1.4 KiB
Python
|
|
"""Helpers for working with minimal SortedMulti descriptor templates."""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from dataclasses import dataclass
|
||
|
|
from typing import Sequence
|
||
|
|
|
||
|
|
|
||
|
|
@dataclass(frozen=True)
|
||
|
|
class SortedMultiDescriptorTemplate:
|
||
|
|
"""Minimal representation of a ``wsh(sortedmulti(m, ...))`` descriptor."""
|
||
|
|
|
||
|
|
threshold: int
|
||
|
|
|
||
|
|
def witness_script(self, tweaked_keys: Sequence[bytes]) -> bytes:
|
||
|
|
"""Return the witness script for ``wsh(sortedmulti(threshold, tweaked_keys))``."""
|
||
|
|
|
||
|
|
if not tweaked_keys:
|
||
|
|
raise ValueError("sortedmulti requires at least one key")
|
||
|
|
if not 1 <= self.threshold <= len(tweaked_keys):
|
||
|
|
raise ValueError("threshold must satisfy 1 <= m <= n")
|
||
|
|
|
||
|
|
for key in tweaked_keys:
|
||
|
|
if len(key) != 33:
|
||
|
|
raise ValueError("sortedmulti keys must be 33-byte compressed pubkeys")
|
||
|
|
|
||
|
|
sorted_keys = sorted(tweaked_keys)
|
||
|
|
script = bytearray()
|
||
|
|
script.append(_op_n(self.threshold))
|
||
|
|
for key in sorted_keys:
|
||
|
|
script.append(len(key))
|
||
|
|
script.extend(key)
|
||
|
|
script.append(_op_n(len(sorted_keys)))
|
||
|
|
script.append(0xAE) # OP_CHECKMULTISIG
|
||
|
|
return bytes(script)
|
||
|
|
|
||
|
|
def _op_n(value: int) -> int:
|
||
|
|
if not 0 <= value <= 16:
|
||
|
|
raise ValueError("OP_N value out of range")
|
||
|
|
if value == 0:
|
||
|
|
return 0x00
|
||
|
|
return 0x50 + value
|