@ -27,7 +27,7 @@ _TXSIZE_INPUT = const(40)
_TXSIZE_OUTPUT = const ( 8 )
# size of a pubkey
_TXSIZE_PUBKEY = const ( 33 )
# size of a DER signature (3 type bytes, 3 len bytes, 33 R, 32 S, 1 sighash
# maximum size of a DER signature (3 type bytes, 3 len bytes, 33 R, 32 S, 1 sighash)
_TXSIZE_SIGNATURE = const ( 72 )
# size of a multiscript without pubkey (1 M, 1 N, 1 checksig)
_TXSIZE_MULTISIGSCRIPT = const ( 3 )
@ -38,32 +38,26 @@ _TXSIZE_WITNESSSCRIPT = const(34)
class TxWeightCalculator :
def __init__ ( self , inputs_count : int , outputs_count : int ) :
self . inputs_count = inputs_count
self . counter = 4 * (
_TXSIZE_HEADER
+ _TXSIZE_FOOTER
+ self . ser_length_size ( inputs_count )
+ self . ser_length_size ( outputs_count )
)
self . segwit = False
def add_witness_header ( self ) - > None :
if not self . segwit :
self . counter + = _TXSIZE_SEGWIT_OVERHEAD
self . counter + = self . ser_length_size ( self . inputs_count )
self . segwit = True
def __init__ ( self ) - > None :
self . inputs_count = 0
self . outputs_count = 0
self . counter = 4 * ( _TXSIZE_HEADER + _TXSIZE_FOOTER )
self . segwit_inputs_count = 0
def add_input ( self , i : TxInput ) - > None :
self . inputs_count + = 1
if i . multisig :
multisig_script_size = _TXSIZE_MULTISIGSCRIPT + len ( i . multisig . pubkeys ) * (
1 + _TXSIZE_PUBKEY
)
n = len ( i . multisig . nodes ) if i . multisig . nodes else len ( i . multisig . pubkeys )
multisig_script_size = _TXSIZE_MULTISIGSCRIPT + n * ( 1 + _TXSIZE_PUBKEY )
if i . script_type in common . SEGWIT_INPUT_SCRIPT_TYPES :
multisig_script_size + = self . varint_size ( multisig_script_size )
else :
multisig_script_size + = self . op_push_size ( multisig_script_size )
input_script_size = (
1
+ i . multisig . m * ( 1 + _TXSIZE_SIGNATURE ) # the OP_FALSE bug in multisig
+ self . op_push_size ( multisig_script_size )
1 # the OP_FALSE bug in multisig
+ i . multisig . m * ( 1 + _TXSIZE_SIGNATURE )
+ multisig_script_size
)
else :
@ -72,29 +66,38 @@ class TxWeightCalculator:
self . counter + = 4 * _TXSIZE_INPUT
if i . script_type in common . NONSEGWIT_INPUT_SCRIPT_TYPES :
input_script_size + = self . ser_length _size( input_script_size )
input_script_size + = self . varint _size( input_script_size )
self . counter + = 4 * input_script_size
elif i . script_type in common . SEGWIT_INPUT_SCRIPT_TYPES :
self . add_witness_header( )
self . segwit_inputs_count + = 1
if i . script_type == InputScriptType . SPENDP2SHWITNESS :
# add script_sig size
if i . multisig :
self . counter + = 4 * ( 2 + _TXSIZE_WITNESSSCRIPT )
else :
self . counter + = 4 * ( 2 + _TXSIZE_WITNESSPKHASH )
else :
self . counter + = 4 # empty
self . counter + = input_script_size # discounted witness
self . counter + = 4 # empty script_sig (1 byte)
self . counter + = 1 + input_script_size # discounted witness
def add_output ( self , script : bytes ) - > None :
size = len ( script ) + self . ser_length_size ( len ( script ) )
self . counter + = 4 * ( _TXSIZE_OUTPUT + size )
self . outputs_count + = 1
script_size = self . varint_size ( len ( script ) ) + len ( script )
self . counter + = 4 * ( _TXSIZE_OUTPUT + script_size )
def get_total ( self ) - > int :
return self . counter
total = self . counter
total + = 4 * self . varint_size ( self . inputs_count )
total + = 4 * self . varint_size ( self . outputs_count )
if self . segwit_inputs_count :
total + = _TXSIZE_SEGWIT_OVERHEAD
# add one byte of witness stack item count per non-segwit input
total + = self . inputs_count - self . segwit_inputs_count
return total
@staticmethod
def ser_length_size ( length : int ) - > int :
def varint _size( length : int ) - > int :
if length < 253 :
return 1
if length < 0x1_0000 :