import random
from test_framework import cashaddr
from .environment import on_bch, on_nex
from .script import OP_RETURN, CScript, OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG
if on_bch():
from .bch.nodemessages import CTxOut
elif on_nex():
from .bch.nodemessages import CTxOut
else:
raise NotImplementedError()
MIN_TX_SIZE = 65 if on_bch() else 0
MAX_TXOUT_PUBKEY_SCRIPT = 10000
def address2bin(btc_address):
addr = cashaddr.decode(btc_address)
return addr[2]
def p2pkh(btc_address):
ret = CScript(
[OP_DUP, OP_HASH160, address2bin(btc_address), OP_EQUALVERIFY, OP_CHECKSIG]
)
return ret
def pad_tx(tx, pad_to_size=MIN_TX_SIZE):
if MIN_TX_SIZE == 0:
return
curr_size = len(tx.serialize())
if curr_size >= pad_to_size:
return
extra_bytes = 8 + 1 + 1
required_padding = pad_to_size - curr_size
while required_padding > 0:
padding_len = min(required_padding, MAX_TXOUT_PUBKEY_SCRIPT - extra_bytes)
assert padding_len >= 0, "Can't pad less than 0 bytes, trying {padding_len}"
next_iteration_padding = required_padding - padding_len - extra_bytes
if next_iteration_padding > 0 < next_iteration_padding < extra_bytes:
padding_len += next_iteration_padding
if padding_len <= extra_bytes:
tx.vout.append(CTxOut(0, CScript([OP_RETURN])))
else:
padding_len -= extra_bytes
padding = random.randrange(
1 << 8 * padding_len - 2, 1 << 8 * padding_len - 1
)
tx.vout.append(CTxOut(0, CScript([OP_RETURN, padding])))
curr_size = len(tx.serialize())
required_padding = pad_to_size - curr_size
assert curr_size >= pad_to_size, f"{curr_size} !>= {pad_to_size}"
tx.rehash()