|
|
|
|
@ -1,6 +1,7 @@
|
|
|
|
|
# note, only used for non-cryptographic randomness: |
|
|
|
|
import random |
|
|
|
|
import json |
|
|
|
|
from typing import List, Union, Tuple |
|
|
|
|
# needed for single sha256 evaluation, which is used |
|
|
|
|
# in bitcoin (p2wsh) but not exposed in python-bitcointx: |
|
|
|
|
import hashlib |
|
|
|
|
@ -18,31 +19,6 @@ from bitcointx.core.scripteval import (VerifyScript, SCRIPT_VERIFY_WITNESS,
|
|
|
|
|
SCRIPT_VERIFY_STRICTENC, |
|
|
|
|
SIGVERSION_WITNESS_V0) |
|
|
|
|
|
|
|
|
|
# for each transaction type, different output script pubkeys may result in |
|
|
|
|
# a difference in the number of bytes accounted for while estimating the |
|
|
|
|
# transaction size, this variable stores the difference and is factored in |
|
|
|
|
# when calculating the correct transaction size. For example, for a p2pkh |
|
|
|
|
# transaction, if one of the outputs is a p2wsh pubkey, then the transaction |
|
|
|
|
# would need 9 extra bytes to account for the difference in script pubkey |
|
|
|
|
# sizes |
|
|
|
|
OUTPUT_EXTRA_BYTES = { |
|
|
|
|
'p2pkh': { |
|
|
|
|
'p2wpkh': -3, |
|
|
|
|
'p2sh-p2wpkh': -2, |
|
|
|
|
'p2wsh': 9 |
|
|
|
|
}, |
|
|
|
|
'p2wpkh': { |
|
|
|
|
'p2pkh': 3, |
|
|
|
|
'p2sh-p2wpkh': 1, |
|
|
|
|
'p2wsh': 12 |
|
|
|
|
}, |
|
|
|
|
'p2sh-p2wpkh': { |
|
|
|
|
'p2pkh': 2, |
|
|
|
|
'p2wpkh': -1, |
|
|
|
|
'p2wsh': 11 |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
def human_readable_transaction(tx, jsonified=True): |
|
|
|
|
""" Given a CTransaction object, output a human |
|
|
|
|
readable json-formatted string (suitable for terminal |
|
|
|
|
@ -106,70 +82,97 @@ def human_readable_output(txoutput):
|
|
|
|
|
pass # non standard script |
|
|
|
|
return outdict |
|
|
|
|
|
|
|
|
|
def estimate_tx_size(ins, outs, txtype='p2pkh', outtype=None): |
|
|
|
|
def there_is_one_segwit_input(input_types: List[str]) -> bool: |
|
|
|
|
# note that we need separate input types for |
|
|
|
|
# any distinct types of scripthash inputs supported, |
|
|
|
|
# since each may have a different size of witness; in |
|
|
|
|
# that case, the internal list in this list comprehension |
|
|
|
|
# will need updating. |
|
|
|
|
# note that there is no support yet for paying *from* p2tr. |
|
|
|
|
return any(y in ["p2sh-p2wpkh", "p2wpkh", "p2wsh"] for y in input_types) |
|
|
|
|
|
|
|
|
|
def estimate_tx_size(ins: List[str], outs: List[str]) -> Union[int, Tuple[int]]: |
|
|
|
|
'''Estimate transaction size. |
|
|
|
|
The txtype field as detailed below is used to distinguish |
|
|
|
|
the type, but there is at least one source of meaningful roughness: |
|
|
|
|
we assume that the scriptPubKey type of all the outputs are the same as |
|
|
|
|
the input, unless `outtype` is specified, in which case *one* of |
|
|
|
|
the outputs is assumed to be that other type, with all of the other |
|
|
|
|
outputs being of the same type as before. |
|
|
|
|
This, combined with a few bytes variation in signature sizes means |
|
|
|
|
we will sometimes see small inaccuracies in this estimate. |
|
|
|
|
|
|
|
|
|
Assuming p2pkh: |
|
|
|
|
out: 8+1+3+20+2=34, in: 32+4+1+1+~72+1+33+4=148, |
|
|
|
|
ver: 4, locktime:4, +2 (len in,out) |
|
|
|
|
total = 34*len_out + 148*len_in + 10 (sig sizes vary slightly) |
|
|
|
|
|
|
|
|
|
Assuming p2sh M of N multisig: |
|
|
|
|
"ins" must contain M, N so ins= (numins, M, N) (crude assuming all same) |
|
|
|
|
73*M + 34*N + 45 per input, so total ins ~ len_ins * (45+73M+34N) |
|
|
|
|
so total ~ 32*len_out + (45+73M+34N)*len_in + 10 |
|
|
|
|
|
|
|
|
|
Assuming p2sh-p2wpkh: |
|
|
|
|
witness are roughly 1+1+~72+1+33 for each input |
|
|
|
|
(txid, vin, 4+20 for witness program encoded as scriptsig, 4 for sequence) |
|
|
|
|
non-witness input fields are roughly 32+4+4+20+4=64, so total becomes |
|
|
|
|
n_in * 64 + 4(ver) + 2(marker, flag) + 2(n_in, n_out) + 4(locktime) + n_out*32 |
|
|
|
|
|
|
|
|
|
Assuming p2wpkh native: |
|
|
|
|
witness as previous case |
|
|
|
|
non-witness loses the 24 witnessprogram, replaced with 1 zero, |
|
|
|
|
in the scriptSig, so becomes: |
|
|
|
|
4 + 1 + 1 + (n_in) + (vin) + (n_out) + (vout) + (witness) + (locktime) |
|
|
|
|
non-witness: 4(ver) +2 (marker, flag) + n_in*41 + 4(locktime) +2 (len in, out) + n_out*31 |
|
|
|
|
witness: 1 + 1 + 72 + 1 + 33 |
|
|
|
|
Both arguments `ins` and `outs` must be lists of script types, |
|
|
|
|
and they must be present in the keys of the dicts `inmults`, |
|
|
|
|
`outmults` defined here. |
|
|
|
|
Note that variation in ECDSA signature sizes means |
|
|
|
|
we will sometimes see small inaccuracies in this estimate, but |
|
|
|
|
that this is ameliorated by the existence of the witness discount, |
|
|
|
|
in actually estimating fees. |
|
|
|
|
The value '72' is used for the most-likely size of these ECDSA |
|
|
|
|
signatures, due to 30[1 byte] + len(rest)[1 byte] + type:02 [1 byte] + len(r)[1] + r[32 or 33] + type:02[1] + len(s)[1] + s[32] + sighash_all [1] |
|
|
|
|
... though as can be seen, 71 is also likely: |
|
|
|
|
r length 33 occurs when the value is 'negative' (>N/2) and a byte x80 is prepended, |
|
|
|
|
but shorter values for r are possible if rare. |
|
|
|
|
Returns: |
|
|
|
|
Either a single integer, if the transaction will be non-segwit, |
|
|
|
|
or a tuple (int, int) for witness and non-witness bytes respectively). |
|
|
|
|
''' |
|
|
|
|
if txtype == 'p2pkh': |
|
|
|
|
return 4 + 4 + 2 + ins*148 + 34*outs + ( |
|
|
|
|
OUTPUT_EXTRA_BYTES[txtype][outtype] |
|
|
|
|
if outtype and outtype in OUTPUT_EXTRA_BYTES[txtype] else 0) |
|
|
|
|
elif txtype == 'p2sh-p2wpkh': |
|
|
|
|
#return the estimate for the witness and non-witness |
|
|
|
|
#portions of the transaction, assuming that all the inputs |
|
|
|
|
#are of segwit type p2sh-p2wpkh |
|
|
|
|
# Note as of Jan19: this misses 2 bytes (trivial) for len in, out |
|
|
|
|
# and also overestimates output size by 2 bytes. |
|
|
|
|
witness_estimate = ins*108 |
|
|
|
|
non_witness_estimate = 4 + 4 + 4 + outs*32 + ins*64 + ( |
|
|
|
|
OUTPUT_EXTRA_BYTES[txtype][outtype] |
|
|
|
|
if outtype and outtype in OUTPUT_EXTRA_BYTES[txtype] else 0) |
|
|
|
|
return (witness_estimate, non_witness_estimate) |
|
|
|
|
elif txtype == 'p2wpkh': |
|
|
|
|
witness_estimate = ins*108 |
|
|
|
|
non_witness_estimate = 4 + 4 + 4 + outs*31 + ins*41 + ( |
|
|
|
|
OUTPUT_EXTRA_BYTES[txtype][outtype] |
|
|
|
|
if outtype and outtype in OUTPUT_EXTRA_BYTES[txtype] else 0) |
|
|
|
|
return (witness_estimate, non_witness_estimate) |
|
|
|
|
elif txtype == 'p2shMofN': |
|
|
|
|
ins, M, N = ins |
|
|
|
|
return 4 + 4 + 2 + (45 + 73*M + 34*N)*ins + outs*32 + ( |
|
|
|
|
OUTPUT_EXTRA_BYTES['p2sh-p2wpkh'][outtype] |
|
|
|
|
if outtype and outtype in OUTPUT_EXTRA_BYTES['p2sh-p2wpkh'] else 0) |
|
|
|
|
else: |
|
|
|
|
raise NotImplementedError("Transaction size estimation not" + |
|
|
|
|
"yet implemented for type: " + txtype) |
|
|
|
|
|
|
|
|
|
# All non-witness input sizes include: txid, index, sequence, |
|
|
|
|
# which is 32, 4 and 4; the remaining is scriptSig which is 1 |
|
|
|
|
# at minimum, for native segwit (the byte x00). Hence 41 is the minimum. |
|
|
|
|
# The witness field for p2wpkh consists of sig, pub so 72 + 33 + 1 byte |
|
|
|
|
# for the number of witness elements and 2 bytes for the size of each element, |
|
|
|
|
# hence 108. |
|
|
|
|
# For p2pkh, 148 comes from 32+4+1+1+~72+1+33+4 |
|
|
|
|
# For p2sh-p2wpkh there is an additional 23 bytes of witness for the redeemscript. |
|
|
|
|
# |
|
|
|
|
# Note that p2wsh here is specific to the script |
|
|
|
|
# we use for fidelity bonds; 43 is the bytes required for that |
|
|
|
|
# script's redeemscript field in the witness, but for arbitrary scripts, |
|
|
|
|
# the witness portion could be any other size. |
|
|
|
|
# Hence, we may need to modify this later. |
|
|
|
|
# |
|
|
|
|
# Note that there is no support yet for spending *from* p2tr: |
|
|
|
|
# we should fix this soon, since it is desirable to be able to support |
|
|
|
|
# coinjoins with counterparties sending taproot, but note, JM coinjoins |
|
|
|
|
# do not allow non-standard (usually v0 segwit) inputs, anyway. |
|
|
|
|
inmults = {"p2wsh": {"w": 1 + 72 + 43, "nw": 41}, |
|
|
|
|
"p2wpkh": {"w": 108, "nw": 41}, |
|
|
|
|
"p2sh-p2wpkh": {"w": 108, "nw": 64}, |
|
|
|
|
"p2pkh": {"w": 0, "nw": 148}} |
|
|
|
|
|
|
|
|
|
# Notes: in outputs, there is only 1 'scripthash' |
|
|
|
|
# type for either segwit/nonsegwit (hence "p2sh-p2wpkh" |
|
|
|
|
# is a bit misleading, but is kept to the same as inputs, |
|
|
|
|
# for simplicity. See notes on inputs above). |
|
|
|
|
# p2wsh has structure 8 bytes output, then: |
|
|
|
|
# x22,x00,x20,(32 byte hash), so 32 + 3 + 8 |
|
|
|
|
# note also there is no need to distinguish witness |
|
|
|
|
# here, outputs are always entirely nonwitness. |
|
|
|
|
# p2tr is also 32 byte hash with x01 instead of x00 version. |
|
|
|
|
outmults = {"p2wsh": 43, |
|
|
|
|
"p2wpkh": 31, |
|
|
|
|
"p2sh-p2wpkh": 32, |
|
|
|
|
"p2pkh": 34, |
|
|
|
|
"p2tr": 43} |
|
|
|
|
|
|
|
|
|
# nVersion, nLockTime, nins, nouts: |
|
|
|
|
nwsize = 4 + 4 + 2 |
|
|
|
|
wsize = 0 |
|
|
|
|
tx_is_segwit = there_is_one_segwit_input(ins) |
|
|
|
|
if tx_is_segwit: |
|
|
|
|
# flag and marker bytes are included in witness |
|
|
|
|
wsize += 2 |
|
|
|
|
|
|
|
|
|
for i in ins: |
|
|
|
|
if i not in inmults: |
|
|
|
|
raise NotImplementedError( |
|
|
|
|
f"Script type not supported for transaction size estimation: {i}") |
|
|
|
|
inmult = inmults[i] |
|
|
|
|
nwsize += inmult["nw"] |
|
|
|
|
wsize += inmult["w"] |
|
|
|
|
for o in outs: |
|
|
|
|
if o not in outmults: |
|
|
|
|
raise NotImplementedError( |
|
|
|
|
f"Script type not supported for transaction size estimation: {o}") |
|
|
|
|
nwsize += outmults[o] |
|
|
|
|
|
|
|
|
|
if not tx_is_segwit: |
|
|
|
|
return nwsize |
|
|
|
|
return (wsize, nwsize) |
|
|
|
|
|
|
|
|
|
def pubkey_to_p2pkh_script(pub, require_compressed=False): |
|
|
|
|
""" |
|
|
|
|
|