backports

This commit is contained in:
tecnovert
2025-09-29 09:55:50 +02:00
parent 911ca189bc
commit 9d6e566c3b
13 changed files with 296 additions and 23 deletions

View File

@@ -17,7 +17,7 @@ import sqlite3
import traceback
from io import BytesIO
from typing import Dict, Optional
from typing import Dict, List, Optional
from basicswap.basicswap_util import (
getVoutByAddress,
@@ -77,17 +77,19 @@ from basicswap.contrib.test_framework.messages import (
from basicswap.contrib.test_framework.script import (
CScript,
CScriptOp,
OP_IF,
OP_ELSE,
OP_ENDIF,
OP_0,
OP_2,
OP_CHECKSIG,
OP_CHECKMULTISIG,
OP_CHECKSEQUENCEVERIFY,
OP_CHECKSIG,
OP_DROP,
OP_HASH160,
OP_DUP,
OP_ELSE,
OP_ENDIF,
OP_EQUAL,
OP_EQUALVERIFY,
OP_HASH160,
OP_IF,
OP_RETURN,
SIGHASH_ALL,
SegwitV0SignatureHash,
@@ -761,10 +763,11 @@ class BTCInterface(Secp256k1Interface):
# p2wpkh
return CScript([OP_0, pkh])
def loadTx(self, tx_bytes: bytes) -> CTransaction:
def loadTx(self, tx_bytes: bytes, allow_witness: bool = True) -> CTransaction:
# Load tx from bytes to internal representation
# Transactions with no inputs require allow_witness set to false to decode correctly
tx = CTransaction()
tx.deserialize(BytesIO(tx_bytes))
tx.deserialize(BytesIO(tx_bytes), allow_witness)
return tx
def createSCLockTx(
@@ -801,6 +804,35 @@ class BTCInterface(Secp256k1Interface):
CScriptOp(OP_ENDIF)])
# fmt: on
def isScriptP2PKH(self, script: bytes) -> bool:
if len(script) != 25:
return False
if script[0] != OP_DUP:
return False
if script[1] != OP_HASH160:
return False
if script[2] != 20:
return False
if script[23] != OP_EQUALVERIFY:
return False
if script[24] != OP_CHECKSIG:
return False
return True
def isScriptP2WPKH(self, script: bytes) -> bool:
if len(script) != 22:
return False
if script[0] != OP_0:
return False
if script[1] != 20:
return False
return True
def getScriptDummyWitness(self, script: bytes) -> List[bytes]:
if self.isScriptP2WPKH(script):
return [bytes(72), bytes(33)]
raise ValueError("Unknown script type")
def createSCLockRefundTx(
self,
tx_lock_bytes,
@@ -1959,6 +1991,9 @@ class BTCInterface(Secp256k1Interface):
def getBlockWithTxns(self, block_hash: str):
return self.rpc("getblock", [block_hash, 2])
def listUtxos(self):
return self.rpc_wallet("listunspent")
def getUnspentsByAddr(self):
unspent_addr = dict()
unspent = self.rpc_wallet("listunspent")

View File

@@ -521,7 +521,7 @@ class CTransaction(object):
self.hash = tx.hash
self.wit = copy.deepcopy(tx.wit)
def deserialize(self, f):
def deserialize(self, f, allow_witness: bool = True):
ver32bit = struct.unpack("<i", f.read(4))[0]
self.nVersion = ver32bit & 0xffff
self.nType = (ver32bit >> 16) & 0xffff

View File

@@ -455,12 +455,12 @@ class CTransaction(object):
self.wit = copy.deepcopy(tx.wit)
self.strDZeel = copy.deepcopy(tx.strDZeel)
def deserialize(self, f):
def deserialize(self, f, allow_witness: bool = True):
self.nVersion = struct.unpack("<i", f.read(4))[0]
self.nTime = struct.unpack("<i", f.read(4))[0]
self.vin = deser_vector(f, CTxIn)
flags = 0
if len(self.vin) == 0:
if len(self.vin) == 0 and allow_witness:
flags = struct.unpack("<B", f.read(1))[0]
# Not sure why flags can't be zero, but this
# matches the implementation in bitcoind

View File

@@ -505,7 +505,7 @@ class CTransaction:
self.sha256 = tx.sha256
self.hash = tx.hash
def deserialize(self, f):
def deserialize(self, f, allow_witness: bool = True):
self.nVersion = struct.unpack("<h", f.read(2))[0]
self.nType = struct.unpack("<h", f.read(2))[0]
self.vin = deser_vector(f, CTxIn)

View File

@@ -13,6 +13,8 @@ import logging
import random
import traceback
from typing import List
from basicswap.basicswap_util import getVoutByScriptPubKey, TxLockTypes
from basicswap.chainparams import Coins
from basicswap.contrib.test_framework.script import (
@@ -1609,11 +1611,11 @@ class DCRInterface(Secp256k1Interface):
script_pk = self.getScriptDest(script)
return findOutput(tx, script_pk)
def getScriptLockTxDummyWitness(self, script: bytes):
def getScriptLockTxDummyWitness(self, script: bytes) -> List[bytes]:
return [bytes(72), bytes(72), bytes(len(script))]
def getScriptLockRefundSpendTxDummyWitness(self, script: bytes):
return [bytes(72), bytes(72), bytes((1,)), bytes(len(script))]
def getScriptLockRefundSpendTxDummyWitness(self, script: bytes) -> List[bytes]:
return [bytes(72), bytes(72), bytes(len(script))]
def extractLeaderSig(self, tx_bytes: bytes) -> bytes:
tx = self.loadTx(tx_bytes)

View File

@@ -89,7 +89,7 @@ class CTransaction:
self.locktime = tx.locktime
self.expiry = tx.expiry
def deserialize(self, data: bytes) -> None:
def deserialize(self, data: bytes, allow_witness: bool = True) -> None:
version = int.from_bytes(data[:4], "little")
self.version = version & 0xFFFF

View File

@@ -8,6 +8,7 @@
import hashlib
from enum import IntEnum
from typing import List
from basicswap.contrib.test_framework.messages import (
CTxOutPart,
@@ -134,6 +135,11 @@ class PARTInterface(BTCInterface):
def getScriptForPubkeyHash(self, pkh: bytes) -> CScript:
return CScript([OP_DUP, OP_HASH160, pkh, OP_EQUALVERIFY, OP_CHECKSIG])
def getScriptDummyWitness(self, script: bytes) -> List[bytes]:
if self.isScriptP2WPKH(script) or self.isScriptP2PKH(script):
return [bytes(72), bytes(33)]
raise ValueError("Unknown script type")
def formatStealthAddress(self, scan_pubkey, spend_pubkey) -> str:
prefix_byte = chainparams[self.coin_type()][self._network]["stealth_key_prefix"]