mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-31 17:31:36 +00:00
lnpeer: cooperative close: verify scriptpubkey matches templates
This commit is contained in:
parent
c121230706
commit
aaf174ef3e
2 changed files with 36 additions and 24 deletions
|
@ -25,7 +25,8 @@ from . import ecc
|
|||
from .ecc import sig_string_from_r_and_s, get_r_and_s_from_sig_string, der_sig_from_sig_string
|
||||
from . import constants
|
||||
from .util import bh2u, bfh, log_exceptions, ignore_exceptions, chunks, SilentTaskGroup
|
||||
from .transaction import Transaction, TxOutput, PartialTxOutput
|
||||
from . import transaction
|
||||
from .transaction import Transaction, TxOutput, PartialTxOutput, match_script_against_template
|
||||
from .logging import Logger
|
||||
from .lnonion import (new_onion_packet, decode_onion_error, OnionFailureCode, calc_hops_data_for_payment,
|
||||
process_onion_packet, OnionPacket, construct_onion_error, OnionRoutingFailureMessage,
|
||||
|
@ -1357,9 +1358,12 @@ class Peer(Logger):
|
|||
|
||||
@log_exceptions
|
||||
async def on_shutdown(self, payload):
|
||||
# length of scripts allowed in BOLT-02
|
||||
if int.from_bytes(payload['len'], 'big') not in (3+20+2, 2+20+1, 2+20, 2+32):
|
||||
raise Exception('scriptpubkey length in received shutdown message invalid: ' + str(payload['len']))
|
||||
their_scriptpubkey = payload['scriptpubkey']
|
||||
# BOLT-02 restrict the scriptpubkey to some templates:
|
||||
if not (match_script_against_template(their_scriptpubkey, transaction.SCRIPTPUBKEY_TEMPLATE_WITNESS_V0)
|
||||
or match_script_against_template(their_scriptpubkey, transaction.SCRIPTPUBKEY_TEMPLATE_P2SH)
|
||||
or match_script_against_template(their_scriptpubkey, transaction.SCRIPTPUBKEY_TEMPLATE_P2PKH)):
|
||||
raise Exception(f'scriptpubkey in received shutdown message does not conform to any template: {their_scriptpubkey.hex()}')
|
||||
chan_id = payload['channel_id']
|
||||
if chan_id in self.shutdown_received:
|
||||
self.shutdown_received[chan_id].set_result(payload)
|
||||
|
|
|
@ -390,20 +390,32 @@ class OPPushDataGeneric:
|
|||
|
||||
|
||||
OPPushDataPubkey = OPPushDataGeneric(lambda x: x in (33, 65))
|
||||
# note that this does not include x_pubkeys !
|
||||
|
||||
SCRIPTPUBKEY_TEMPLATE_P2PKH = [opcodes.OP_DUP, opcodes.OP_HASH160,
|
||||
OPPushDataGeneric(lambda x: x == 20),
|
||||
opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG]
|
||||
SCRIPTPUBKEY_TEMPLATE_P2SH = [opcodes.OP_HASH160, OPPushDataGeneric(lambda x: x == 20), opcodes.OP_EQUAL]
|
||||
SCRIPTPUBKEY_TEMPLATE_WITNESS_V0 = [opcodes.OP_0, OPPushDataGeneric(lambda x: x in (20, 32))]
|
||||
|
||||
|
||||
def match_decoded(decoded, to_match):
|
||||
if decoded is None:
|
||||
def match_script_against_template(script, template) -> bool:
|
||||
"""Returns whether 'script' matches 'template'."""
|
||||
if script is None:
|
||||
return False
|
||||
if len(decoded) != len(to_match):
|
||||
# optionally decode script now:
|
||||
if isinstance(script, (bytes, bytearray)):
|
||||
try:
|
||||
script = [x for x in script_GetOp(script)]
|
||||
except MalformedBitcoinScript:
|
||||
return False
|
||||
for i in range(len(decoded)):
|
||||
to_match_item = to_match[i]
|
||||
decoded_item = decoded[i]
|
||||
if OPPushDataGeneric.is_instance(to_match_item) and to_match_item.check_data_len(decoded_item[0]):
|
||||
if len(script) != len(template):
|
||||
return False
|
||||
for i in range(len(script)):
|
||||
template_item = template[i]
|
||||
script_item = script[i]
|
||||
if OPPushDataGeneric.is_instance(template_item) and template_item.check_data_len(script_item[0]):
|
||||
continue
|
||||
if to_match_item != decoded_item[0]:
|
||||
if template_item != script_item[0]:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
@ -412,28 +424,25 @@ def get_address_from_output_script(_bytes: bytes, *, net=None) -> Optional[str]:
|
|||
try:
|
||||
decoded = [x for x in script_GetOp(_bytes)]
|
||||
except MalformedBitcoinScript:
|
||||
decoded = None
|
||||
return None
|
||||
|
||||
# p2pkh
|
||||
match = [opcodes.OP_DUP, opcodes.OP_HASH160, OPPushDataGeneric(lambda x: x == 20), opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG]
|
||||
if match_decoded(decoded, match):
|
||||
if match_script_against_template(decoded, SCRIPTPUBKEY_TEMPLATE_P2PKH):
|
||||
return hash160_to_p2pkh(decoded[2][1], net=net)
|
||||
|
||||
# p2sh
|
||||
match = [opcodes.OP_HASH160, OPPushDataGeneric(lambda x: x == 20), opcodes.OP_EQUAL]
|
||||
if match_decoded(decoded, match):
|
||||
if match_script_against_template(decoded, SCRIPTPUBKEY_TEMPLATE_P2SH):
|
||||
return hash160_to_p2sh(decoded[1][1], net=net)
|
||||
|
||||
# segwit address (version 0)
|
||||
match = [opcodes.OP_0, OPPushDataGeneric(lambda x: x in (20, 32))]
|
||||
if match_decoded(decoded, match):
|
||||
if match_script_against_template(decoded, SCRIPTPUBKEY_TEMPLATE_WITNESS_V0):
|
||||
return hash_to_segwit_addr(decoded[1][1], witver=0, net=net)
|
||||
|
||||
# segwit address (version 1-16)
|
||||
future_witness_versions = list(range(opcodes.OP_1, opcodes.OP_16 + 1))
|
||||
for witver, opcode in enumerate(future_witness_versions, start=1):
|
||||
match = [opcode, OPPushDataGeneric(lambda x: 2 <= x <= 40)]
|
||||
if match_decoded(decoded, match):
|
||||
if match_script_against_template(decoded, match):
|
||||
return hash_to_segwit_addr(decoded[1][1], witver=witver, net=net)
|
||||
|
||||
return None
|
||||
|
@ -1348,14 +1357,13 @@ class PartialTxInput(TxInput, PSBTSection):
|
|||
except MalformedBitcoinScript:
|
||||
decoded = None
|
||||
# witness version 0
|
||||
match = [opcodes.OP_0, OPPushDataGeneric(lambda x: x in (20, 32))]
|
||||
if match_decoded(decoded, match):
|
||||
if match_script_against_template(decoded, SCRIPTPUBKEY_TEMPLATE_WITNESS_V0):
|
||||
return True
|
||||
# witness version 1-16
|
||||
future_witness_versions = list(range(opcodes.OP_1, opcodes.OP_16 + 1))
|
||||
for witver, opcode in enumerate(future_witness_versions, start=1):
|
||||
match = [opcode, OPPushDataGeneric(lambda x: 2 <= x <= 40)]
|
||||
if match_decoded(decoded, match):
|
||||
if match_script_against_template(decoded, match):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue