mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-28 16:01:30 +00:00
bitcoin: implement construct_script and use it
This commit is contained in:
parent
89bd520185
commit
4c7a92f39c
4 changed files with 136 additions and 73 deletions
|
@ -28,7 +28,7 @@ from typing import List, Tuple, TYPE_CHECKING, Optional, Union, Sequence
|
||||||
import enum
|
import enum
|
||||||
from enum import IntEnum, Enum
|
from enum import IntEnum, Enum
|
||||||
|
|
||||||
from .util import bfh, bh2u, BitcoinException, assert_bytes, to_bytes, inv_dict
|
from .util import bfh, bh2u, BitcoinException, assert_bytes, to_bytes, inv_dict, is_hex_str
|
||||||
from . import version
|
from . import version
|
||||||
from . import segwit_addr
|
from . import segwit_addr
|
||||||
from . import constants
|
from . import constants
|
||||||
|
@ -307,10 +307,30 @@ def construct_witness(items: Sequence[Union[str, int, bytes]]) -> str:
|
||||||
item = script_num_to_hex(item)
|
item = script_num_to_hex(item)
|
||||||
elif isinstance(item, (bytes, bytearray)):
|
elif isinstance(item, (bytes, bytearray)):
|
||||||
item = bh2u(item)
|
item = bh2u(item)
|
||||||
|
else:
|
||||||
|
assert is_hex_str(item)
|
||||||
witness += witness_push(item)
|
witness += witness_push(item)
|
||||||
return witness
|
return witness
|
||||||
|
|
||||||
|
|
||||||
|
def construct_script(items: Sequence[Union[str, int, bytes, opcodes]]) -> str:
|
||||||
|
"""Constructs bitcoin script from given items."""
|
||||||
|
script = ''
|
||||||
|
for item in items:
|
||||||
|
if isinstance(item, opcodes):
|
||||||
|
script += item.hex()
|
||||||
|
elif type(item) is int:
|
||||||
|
script += add_number_to_script(item).hex()
|
||||||
|
elif isinstance(item, (bytes, bytearray)):
|
||||||
|
script += push_script(item.hex())
|
||||||
|
elif isinstance(item, str):
|
||||||
|
assert is_hex_str(item)
|
||||||
|
script += push_script(item)
|
||||||
|
else:
|
||||||
|
raise Exception(f'unexpected item for script: {item!r}')
|
||||||
|
return script
|
||||||
|
|
||||||
|
|
||||||
def relayfee(network: 'Network' = None) -> int:
|
def relayfee(network: 'Network' = None) -> int:
|
||||||
"""Returns feerate in sat/kbyte."""
|
"""Returns feerate in sat/kbyte."""
|
||||||
from .simple_config import FEERATE_DEFAULT_RELAY, FEERATE_MAX_RELAY
|
from .simple_config import FEERATE_DEFAULT_RELAY, FEERATE_MAX_RELAY
|
||||||
|
@ -386,12 +406,12 @@ def script_to_p2wsh(script: str, *, net=None) -> str:
|
||||||
return hash_to_segwit_addr(sha256(bfh(script)), witver=0, net=net)
|
return hash_to_segwit_addr(sha256(bfh(script)), witver=0, net=net)
|
||||||
|
|
||||||
def p2wpkh_nested_script(pubkey: str) -> str:
|
def p2wpkh_nested_script(pubkey: str) -> str:
|
||||||
pkh = bh2u(hash_160(bfh(pubkey)))
|
pkh = hash_160(bfh(pubkey))
|
||||||
return '00' + push_script(pkh)
|
return construct_script([0, pkh])
|
||||||
|
|
||||||
def p2wsh_nested_script(witness_script: str) -> str:
|
def p2wsh_nested_script(witness_script: str) -> str:
|
||||||
wsh = bh2u(sha256(bfh(witness_script)))
|
wsh = sha256(bfh(witness_script))
|
||||||
return '00' + push_script(wsh)
|
return construct_script([0, wsh])
|
||||||
|
|
||||||
def pubkey_to_address(txin_type: str, pubkey: str, *, net=None) -> str:
|
def pubkey_to_address(txin_type: str, pubkey: str, *, net=None) -> str:
|
||||||
if net is None: net = constants.net
|
if net is None: net = constants.net
|
||||||
|
@ -436,16 +456,12 @@ def address_to_script(addr: str, *, net=None) -> str:
|
||||||
if witprog is not None:
|
if witprog is not None:
|
||||||
if not (0 <= witver <= 16):
|
if not (0 <= witver <= 16):
|
||||||
raise BitcoinException(f'impossible witness version: {witver}')
|
raise BitcoinException(f'impossible witness version: {witver}')
|
||||||
script = bh2u(add_number_to_script(witver))
|
return construct_script([witver, bytes(witprog)])
|
||||||
script += push_script(bh2u(bytes(witprog)))
|
|
||||||
return script
|
|
||||||
addrtype, hash_160_ = b58_address_to_hash160(addr)
|
addrtype, hash_160_ = b58_address_to_hash160(addr)
|
||||||
if addrtype == net.ADDRTYPE_P2PKH:
|
if addrtype == net.ADDRTYPE_P2PKH:
|
||||||
script = pubkeyhash_to_p2pkh_script(bh2u(hash_160_))
|
script = pubkeyhash_to_p2pkh_script(bh2u(hash_160_))
|
||||||
elif addrtype == net.ADDRTYPE_P2SH:
|
elif addrtype == net.ADDRTYPE_P2SH:
|
||||||
script = opcodes.OP_HASH160.hex()
|
script = construct_script([opcodes.OP_HASH160, hash_160_, opcodes.OP_EQUAL])
|
||||||
script += push_script(bh2u(hash_160_))
|
|
||||||
script += opcodes.OP_EQUAL.hex()
|
|
||||||
else:
|
else:
|
||||||
raise BitcoinException(f'unknown address type: {addrtype}')
|
raise BitcoinException(f'unknown address type: {addrtype}')
|
||||||
return script
|
return script
|
||||||
|
@ -493,13 +509,16 @@ def script_to_scripthash(script: str) -> str:
|
||||||
return bh2u(bytes(reversed(h)))
|
return bh2u(bytes(reversed(h)))
|
||||||
|
|
||||||
def public_key_to_p2pk_script(pubkey: str) -> str:
|
def public_key_to_p2pk_script(pubkey: str) -> str:
|
||||||
return push_script(pubkey) + opcodes.OP_CHECKSIG.hex()
|
return construct_script([pubkey, opcodes.OP_CHECKSIG])
|
||||||
|
|
||||||
def pubkeyhash_to_p2pkh_script(pubkey_hash160: str) -> str:
|
def pubkeyhash_to_p2pkh_script(pubkey_hash160: str) -> str:
|
||||||
script = bytes([opcodes.OP_DUP, opcodes.OP_HASH160]).hex()
|
return construct_script([
|
||||||
script += push_script(pubkey_hash160)
|
opcodes.OP_DUP,
|
||||||
script += bytes([opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG]).hex()
|
opcodes.OP_HASH160,
|
||||||
return script
|
pubkey_hash160,
|
||||||
|
opcodes.OP_EQUALVERIFY,
|
||||||
|
opcodes.OP_CHECKSIG
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
__b58chars = b'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
|
__b58chars = b'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
|
||||||
|
|
|
@ -31,8 +31,8 @@ from PyQt5.QtGui import QFontMetrics, QFont
|
||||||
|
|
||||||
from electrum import bitcoin
|
from electrum import bitcoin
|
||||||
from electrum.util import bfh, maybe_extract_bolt11_invoice
|
from electrum.util import bfh, maybe_extract_bolt11_invoice
|
||||||
from electrum.transaction import push_script, PartialTxOutput
|
from electrum.transaction import PartialTxOutput
|
||||||
from electrum.bitcoin import opcodes
|
from electrum.bitcoin import opcodes, construct_script
|
||||||
from electrum.logging import Logger
|
from electrum.logging import Logger
|
||||||
from electrum.lnaddr import LnDecodeException
|
from electrum.lnaddr import LnDecodeException
|
||||||
|
|
||||||
|
@ -111,11 +111,10 @@ class PayToEdit(CompletionTextEdit, ScanQRTextEdit, Logger):
|
||||||
for word in x.split():
|
for word in x.split():
|
||||||
if word[0:3] == 'OP_':
|
if word[0:3] == 'OP_':
|
||||||
opcode_int = opcodes[word]
|
opcode_int = opcodes[word]
|
||||||
assert opcode_int < 256 # opcode is single-byte
|
script += construct_script([opcode_int])
|
||||||
script += bitcoin.int_to_hex(opcode_int)
|
|
||||||
else:
|
else:
|
||||||
bfh(word) # to test it is hex data
|
bfh(word) # to test it is hex data
|
||||||
script += push_script(word)
|
script += construct_script([word])
|
||||||
return script
|
return script
|
||||||
|
|
||||||
def parse_amount(self, x):
|
def parse_amount(self, x):
|
||||||
|
|
|
@ -19,7 +19,8 @@ from .transaction import (Transaction, PartialTransaction, PartialTxInput, TxOut
|
||||||
PartialTxOutput, opcodes, TxOutput)
|
PartialTxOutput, opcodes, TxOutput)
|
||||||
from .ecc import CURVE_ORDER, sig_string_from_der_sig, ECPubkey, string_to_number
|
from .ecc import CURVE_ORDER, sig_string_from_der_sig, ECPubkey, string_to_number
|
||||||
from . import ecc, bitcoin, crypto, transaction
|
from . import ecc, bitcoin, crypto, transaction
|
||||||
from .bitcoin import push_script, redeem_script_to_address, address_to_script, construct_witness
|
from .bitcoin import (push_script, redeem_script_to_address, address_to_script,
|
||||||
|
construct_witness, construct_script)
|
||||||
from . import segwit_addr
|
from . import segwit_addr
|
||||||
from .i18n import _
|
from .i18n import _
|
||||||
from .lnaddr import lndecode
|
from .lnaddr import lndecode
|
||||||
|
@ -452,13 +453,17 @@ def make_htlc_tx_output(amount_msat, local_feerate, revocationpubkey, local_dela
|
||||||
assert type(local_feerate) is int
|
assert type(local_feerate) is int
|
||||||
assert type(revocationpubkey) is bytes
|
assert type(revocationpubkey) is bytes
|
||||||
assert type(local_delayedpubkey) is bytes
|
assert type(local_delayedpubkey) is bytes
|
||||||
script = bytes([opcodes.OP_IF]) \
|
script = bfh(construct_script([
|
||||||
+ bfh(push_script(bh2u(revocationpubkey))) \
|
opcodes.OP_IF,
|
||||||
+ bytes([opcodes.OP_ELSE]) \
|
revocationpubkey,
|
||||||
+ bitcoin.add_number_to_script(to_self_delay) \
|
opcodes.OP_ELSE,
|
||||||
+ bytes([opcodes.OP_CHECKSEQUENCEVERIFY, opcodes.OP_DROP]) \
|
to_self_delay,
|
||||||
+ bfh(push_script(bh2u(local_delayedpubkey))) \
|
opcodes.OP_CHECKSEQUENCEVERIFY,
|
||||||
+ bytes([opcodes.OP_ENDIF, opcodes.OP_CHECKSIG])
|
opcodes.OP_DROP,
|
||||||
|
local_delayedpubkey,
|
||||||
|
opcodes.OP_ENDIF,
|
||||||
|
opcodes.OP_CHECKSIG,
|
||||||
|
]))
|
||||||
|
|
||||||
p2wsh = bitcoin.redeem_script_to_address('p2wsh', bh2u(script))
|
p2wsh = bitcoin.redeem_script_to_address('p2wsh', bh2u(script))
|
||||||
weight = HTLC_SUCCESS_WEIGHT if success else HTLC_TIMEOUT_WEIGHT
|
weight = HTLC_SUCCESS_WEIGHT if success else HTLC_TIMEOUT_WEIGHT
|
||||||
|
@ -503,13 +508,35 @@ def make_offered_htlc(revocation_pubkey: bytes, remote_htlcpubkey: bytes,
|
||||||
assert type(remote_htlcpubkey) is bytes
|
assert type(remote_htlcpubkey) is bytes
|
||||||
assert type(local_htlcpubkey) is bytes
|
assert type(local_htlcpubkey) is bytes
|
||||||
assert type(payment_hash) is bytes
|
assert type(payment_hash) is bytes
|
||||||
return bytes([opcodes.OP_DUP, opcodes.OP_HASH160]) + bfh(push_script(bh2u(bitcoin.hash_160(revocation_pubkey))))\
|
script = bfh(construct_script([
|
||||||
+ bytes([opcodes.OP_EQUAL, opcodes.OP_IF, opcodes.OP_CHECKSIG, opcodes.OP_ELSE]) \
|
opcodes.OP_DUP,
|
||||||
+ bfh(push_script(bh2u(remote_htlcpubkey)))\
|
opcodes.OP_HASH160,
|
||||||
+ bytes([opcodes.OP_SWAP, opcodes.OP_SIZE]) + bitcoin.add_number_to_script(32) + bytes([opcodes.OP_EQUAL, opcodes.OP_NOTIF, opcodes.OP_DROP])\
|
bitcoin.hash_160(revocation_pubkey),
|
||||||
+ bitcoin.add_number_to_script(2) + bytes([opcodes.OP_SWAP]) + bfh(push_script(bh2u(local_htlcpubkey))) + bitcoin.add_number_to_script(2)\
|
opcodes.OP_EQUAL,
|
||||||
+ bytes([opcodes.OP_CHECKMULTISIG, opcodes.OP_ELSE, opcodes.OP_HASH160])\
|
opcodes.OP_IF,
|
||||||
+ bfh(push_script(bh2u(crypto.ripemd(payment_hash)))) + bytes([opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG, opcodes.OP_ENDIF, opcodes.OP_ENDIF])
|
opcodes.OP_CHECKSIG,
|
||||||
|
opcodes.OP_ELSE,
|
||||||
|
remote_htlcpubkey,
|
||||||
|
opcodes.OP_SWAP,
|
||||||
|
opcodes.OP_SIZE,
|
||||||
|
32,
|
||||||
|
opcodes.OP_EQUAL,
|
||||||
|
opcodes.OP_NOTIF,
|
||||||
|
opcodes.OP_DROP,
|
||||||
|
2,
|
||||||
|
opcodes.OP_SWAP,
|
||||||
|
local_htlcpubkey,
|
||||||
|
2,
|
||||||
|
opcodes.OP_CHECKMULTISIG,
|
||||||
|
opcodes.OP_ELSE,
|
||||||
|
opcodes.OP_HASH160,
|
||||||
|
crypto.ripemd(payment_hash),
|
||||||
|
opcodes.OP_EQUALVERIFY,
|
||||||
|
opcodes.OP_CHECKSIG,
|
||||||
|
opcodes.OP_ENDIF,
|
||||||
|
opcodes.OP_ENDIF,
|
||||||
|
]))
|
||||||
|
return script
|
||||||
|
|
||||||
def make_received_htlc(revocation_pubkey: bytes, remote_htlcpubkey: bytes,
|
def make_received_htlc(revocation_pubkey: bytes, remote_htlcpubkey: bytes,
|
||||||
local_htlcpubkey: bytes, payment_hash: bytes, cltv_expiry: int) -> bytes:
|
local_htlcpubkey: bytes, payment_hash: bytes, cltv_expiry: int) -> bytes:
|
||||||
|
@ -517,22 +544,38 @@ def make_received_htlc(revocation_pubkey: bytes, remote_htlcpubkey: bytes,
|
||||||
assert type(i) is bytes
|
assert type(i) is bytes
|
||||||
assert type(cltv_expiry) is int
|
assert type(cltv_expiry) is int
|
||||||
|
|
||||||
return bytes([opcodes.OP_DUP, opcodes.OP_HASH160]) \
|
script = bfh(construct_script([
|
||||||
+ bfh(push_script(bh2u(bitcoin.hash_160(revocation_pubkey)))) \
|
opcodes.OP_DUP,
|
||||||
+ bytes([opcodes.OP_EQUAL, opcodes.OP_IF, opcodes.OP_CHECKSIG, opcodes.OP_ELSE]) \
|
opcodes.OP_HASH160,
|
||||||
+ bfh(push_script(bh2u(remote_htlcpubkey))) \
|
bitcoin.hash_160(revocation_pubkey),
|
||||||
+ bytes([opcodes.OP_SWAP, opcodes.OP_SIZE]) \
|
opcodes.OP_EQUAL,
|
||||||
+ bitcoin.add_number_to_script(32) \
|
opcodes.OP_IF,
|
||||||
+ bytes([opcodes.OP_EQUAL, opcodes.OP_IF, opcodes.OP_HASH160]) \
|
opcodes.OP_CHECKSIG,
|
||||||
+ bfh(push_script(bh2u(crypto.ripemd(payment_hash)))) \
|
opcodes.OP_ELSE,
|
||||||
+ bytes([opcodes.OP_EQUALVERIFY]) \
|
remote_htlcpubkey,
|
||||||
+ bitcoin.add_number_to_script(2) \
|
opcodes.OP_SWAP,
|
||||||
+ bytes([opcodes.OP_SWAP]) \
|
opcodes.OP_SIZE,
|
||||||
+ bfh(push_script(bh2u(local_htlcpubkey))) \
|
32,
|
||||||
+ bitcoin.add_number_to_script(2) \
|
opcodes.OP_EQUAL,
|
||||||
+ bytes([opcodes.OP_CHECKMULTISIG, opcodes.OP_ELSE, opcodes.OP_DROP]) \
|
opcodes.OP_IF,
|
||||||
+ bitcoin.add_number_to_script(cltv_expiry) \
|
opcodes.OP_HASH160,
|
||||||
+ bytes([opcodes.OP_CHECKLOCKTIMEVERIFY, opcodes.OP_DROP, opcodes.OP_CHECKSIG, opcodes.OP_ENDIF, opcodes.OP_ENDIF])
|
crypto.ripemd(payment_hash),
|
||||||
|
opcodes.OP_EQUALVERIFY,
|
||||||
|
2,
|
||||||
|
opcodes.OP_SWAP,
|
||||||
|
local_htlcpubkey,
|
||||||
|
2,
|
||||||
|
opcodes.OP_CHECKMULTISIG,
|
||||||
|
opcodes.OP_ELSE,
|
||||||
|
opcodes.OP_DROP,
|
||||||
|
cltv_expiry,
|
||||||
|
opcodes.OP_CHECKLOCKTIMEVERIFY,
|
||||||
|
opcodes.OP_DROP,
|
||||||
|
opcodes.OP_CHECKSIG,
|
||||||
|
opcodes.OP_ENDIF,
|
||||||
|
opcodes.OP_ENDIF,
|
||||||
|
]))
|
||||||
|
return script
|
||||||
|
|
||||||
def make_htlc_output_witness_script(is_received_htlc: bool, remote_revocation_pubkey: bytes, remote_htlc_pubkey: bytes,
|
def make_htlc_output_witness_script(is_received_htlc: bool, remote_revocation_pubkey: bytes, remote_htlc_pubkey: bytes,
|
||||||
local_htlc_pubkey: bytes, payment_hash: bytes, cltv_expiry: Optional[int]) -> bytes:
|
local_htlc_pubkey: bytes, payment_hash: bytes, cltv_expiry: Optional[int]) -> bytes:
|
||||||
|
@ -796,9 +839,18 @@ def make_commitment(
|
||||||
|
|
||||||
def make_commitment_output_to_local_witness_script(
|
def make_commitment_output_to_local_witness_script(
|
||||||
revocation_pubkey: bytes, to_self_delay: int, delayed_pubkey: bytes) -> bytes:
|
revocation_pubkey: bytes, to_self_delay: int, delayed_pubkey: bytes) -> bytes:
|
||||||
local_script = bytes([opcodes.OP_IF]) + bfh(push_script(bh2u(revocation_pubkey))) + bytes([opcodes.OP_ELSE]) + bitcoin.add_number_to_script(to_self_delay) \
|
script = bfh(construct_script([
|
||||||
+ bytes([opcodes.OP_CHECKSEQUENCEVERIFY, opcodes.OP_DROP]) + bfh(push_script(bh2u(delayed_pubkey))) + bytes([opcodes.OP_ENDIF, opcodes.OP_CHECKSIG])
|
opcodes.OP_IF,
|
||||||
return local_script
|
revocation_pubkey,
|
||||||
|
opcodes.OP_ELSE,
|
||||||
|
to_self_delay,
|
||||||
|
opcodes.OP_CHECKSEQUENCEVERIFY,
|
||||||
|
opcodes.OP_DROP,
|
||||||
|
delayed_pubkey,
|
||||||
|
opcodes.OP_ENDIF,
|
||||||
|
opcodes.OP_CHECKSIG,
|
||||||
|
]))
|
||||||
|
return script
|
||||||
|
|
||||||
def make_commitment_output_to_local_address(
|
def make_commitment_output_to_local_address(
|
||||||
revocation_pubkey: bytes, to_self_delay: int, delayed_pubkey: bytes) -> str:
|
revocation_pubkey: bytes, to_self_delay: int, delayed_pubkey: bytes) -> str:
|
||||||
|
|
|
@ -48,7 +48,7 @@ from .bitcoin import (TYPE_ADDRESS, TYPE_SCRIPT, hash_160,
|
||||||
var_int, TOTAL_COIN_SUPPLY_LIMIT_IN_BTC, COIN,
|
var_int, TOTAL_COIN_SUPPLY_LIMIT_IN_BTC, COIN,
|
||||||
int_to_hex, push_script, b58_address_to_hash160,
|
int_to_hex, push_script, b58_address_to_hash160,
|
||||||
opcodes, add_number_to_script, base_decode, is_segwit_script_type,
|
opcodes, add_number_to_script, base_decode, is_segwit_script_type,
|
||||||
base_encode, construct_witness)
|
base_encode, construct_witness, construct_script)
|
||||||
from .crypto import sha256d
|
from .crypto import sha256d
|
||||||
from .logging import get_logger
|
from .logging import get_logger
|
||||||
|
|
||||||
|
@ -500,10 +500,7 @@ def parse_output(vds: BCDataStream) -> TxOutput:
|
||||||
def multisig_script(public_keys: Sequence[str], m: int) -> str:
|
def multisig_script(public_keys: Sequence[str], m: int) -> str:
|
||||||
n = len(public_keys)
|
n = len(public_keys)
|
||||||
assert 1 <= m <= n <= 15, f'm {m}, n {n}'
|
assert 1 <= m <= n <= 15, f'm {m}, n {n}'
|
||||||
op_m = bh2u(add_number_to_script(m))
|
return construct_script([m, *public_keys, n, opcodes.OP_CHECKMULTISIG])
|
||||||
op_n = bh2u(add_number_to_script(n))
|
|
||||||
keylist = [push_script(k) for k in public_keys]
|
|
||||||
return op_m + ''.join(keylist) + op_n + opcodes.OP_CHECKMULTISIG.hex()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -639,7 +636,7 @@ class Transaction:
|
||||||
|
|
||||||
_type = txin.script_type
|
_type = txin.script_type
|
||||||
if not cls.is_segwit_input(txin):
|
if not cls.is_segwit_input(txin):
|
||||||
return '00'
|
return construct_witness([])
|
||||||
|
|
||||||
if _type in ('address', 'unknown') and estimate_size:
|
if _type in ('address', 'unknown') and estimate_size:
|
||||||
_type = cls.guess_txintype_from_address(txin.address)
|
_type = cls.guess_txintype_from_address(txin.address)
|
||||||
|
@ -648,9 +645,9 @@ class Transaction:
|
||||||
return construct_witness([sig_list[0], pubkeys[0]])
|
return construct_witness([sig_list[0], pubkeys[0]])
|
||||||
elif _type in ['p2wsh', 'p2wsh-p2sh']:
|
elif _type in ['p2wsh', 'p2wsh-p2sh']:
|
||||||
witness_script = multisig_script(pubkeys, txin.num_sig)
|
witness_script = multisig_script(pubkeys, txin.num_sig)
|
||||||
return construct_witness([0] + sig_list + [witness_script])
|
return construct_witness([0, *sig_list, witness_script])
|
||||||
elif _type in ['p2pk', 'p2pkh', 'p2sh']:
|
elif _type in ['p2pk', 'p2pkh', 'p2sh']:
|
||||||
return '00'
|
return construct_witness([])
|
||||||
raise UnknownTxinType(f'cannot construct witness for txin_type: {_type}')
|
raise UnknownTxinType(f'cannot construct witness for txin_type: {_type}')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -702,38 +699,34 @@ class Transaction:
|
||||||
assert isinstance(txin, PartialTxInput)
|
assert isinstance(txin, PartialTxInput)
|
||||||
|
|
||||||
if txin.is_p2sh_segwit() and txin.redeem_script:
|
if txin.is_p2sh_segwit() and txin.redeem_script:
|
||||||
return push_script(txin.redeem_script.hex())
|
return construct_script([txin.redeem_script])
|
||||||
if txin.is_native_segwit():
|
if txin.is_native_segwit():
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
_type = txin.script_type
|
_type = txin.script_type
|
||||||
pubkeys, sig_list = self.get_siglist(txin, estimate_size=estimate_size)
|
pubkeys, sig_list = self.get_siglist(txin, estimate_size=estimate_size)
|
||||||
script = ''.join(push_script(x) for x in sig_list)
|
|
||||||
if _type in ('address', 'unknown') and estimate_size:
|
if _type in ('address', 'unknown') and estimate_size:
|
||||||
_type = self.guess_txintype_from_address(txin.address)
|
_type = self.guess_txintype_from_address(txin.address)
|
||||||
if _type == 'p2pk':
|
if _type == 'p2pk':
|
||||||
return script
|
return construct_script([sig_list[0]])
|
||||||
elif _type == 'p2sh':
|
elif _type == 'p2sh':
|
||||||
# put op_0 before script
|
# put op_0 before script
|
||||||
script = '00' + script
|
|
||||||
redeem_script = multisig_script(pubkeys, txin.num_sig)
|
redeem_script = multisig_script(pubkeys, txin.num_sig)
|
||||||
script += push_script(redeem_script)
|
return construct_script([0, *sig_list, redeem_script])
|
||||||
return script
|
|
||||||
elif _type == 'p2pkh':
|
elif _type == 'p2pkh':
|
||||||
script += push_script(pubkeys[0])
|
return construct_script([sig_list[0], pubkeys[0]])
|
||||||
return script
|
|
||||||
elif _type in ['p2wpkh', 'p2wsh']:
|
elif _type in ['p2wpkh', 'p2wsh']:
|
||||||
return ''
|
return ''
|
||||||
elif _type == 'p2wpkh-p2sh':
|
elif _type == 'p2wpkh-p2sh':
|
||||||
redeem_script = bitcoin.p2wpkh_nested_script(pubkeys[0])
|
redeem_script = bitcoin.p2wpkh_nested_script(pubkeys[0])
|
||||||
return push_script(redeem_script)
|
return construct_script([redeem_script])
|
||||||
elif _type == 'p2wsh-p2sh':
|
elif _type == 'p2wsh-p2sh':
|
||||||
if estimate_size:
|
if estimate_size:
|
||||||
witness_script = ''
|
witness_script = ''
|
||||||
else:
|
else:
|
||||||
witness_script = self.get_preimage_script(txin)
|
witness_script = self.get_preimage_script(txin)
|
||||||
redeem_script = bitcoin.p2wsh_nested_script(witness_script)
|
redeem_script = bitcoin.p2wsh_nested_script(witness_script)
|
||||||
return push_script(redeem_script)
|
return construct_script([redeem_script])
|
||||||
raise UnknownTxinType(f'cannot construct scriptSig for txin_type: {_type}')
|
raise UnknownTxinType(f'cannot construct scriptSig for txin_type: {_type}')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
Loading…
Add table
Reference in a new issue