mirror of
https://github.com/alexgo-io/stacks-puppet-node.git
synced 2026-04-23 19:31:00 +08:00
adds a dust_included flag to tell the tx serialization code not to add any more dust fees, because those fees are already included in txfee, this prevents double-adds of dust fees
This commit is contained in:
@@ -78,45 +78,48 @@ def build(name, script_pubkey, register_addr, consensus_hash, name_hash=None):
|
||||
return packaged_script
|
||||
|
||||
|
||||
def make_outputs( data, inputs, sender_addr, burn_addr, fee, tx_fee, pay_fee=True ):
|
||||
def make_outputs( data, inputs, sender_addr, burn_addr, fee, tx_fee, pay_fee=True, dust_included=False ):
|
||||
"""
|
||||
Make outputs for a name preorder:
|
||||
[0] OP_RETURN with the name
|
||||
[0] OP_RETURN with the name
|
||||
[1] address with the NAME_PREORDER sender's address
|
||||
[2] pay-to-address with the *burn address* with the fee
|
||||
Raise ValueError if there are not enough inputs to make the transaction
|
||||
"""
|
||||
|
||||
|
||||
op_fee = max(fee, DEFAULT_DUST_FEE)
|
||||
dust_fee = (len(inputs) + 2) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE + tx_fee
|
||||
total_tx_fee = tx_fee
|
||||
if not dust_included:
|
||||
total_tx_fee += (len(inputs) + 2) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE
|
||||
dust_value = DEFAULT_DUST_FEE
|
||||
|
||||
|
||||
bill = 0
|
||||
|
||||
if pay_fee:
|
||||
bill = op_fee
|
||||
|
||||
else:
|
||||
op_fee = 0
|
||||
bill = 0
|
||||
dust_fee = 0
|
||||
|
||||
total_tx_fee = 0
|
||||
|
||||
return [
|
||||
# main output
|
||||
{"script": virtualchain.make_data_script(str(data)),
|
||||
"value": 0},
|
||||
|
||||
|
||||
# change address (can be subsidy key)
|
||||
{"script": virtualchain.make_payment_script(str(sender_addr)),
|
||||
"value": virtualchain.calculate_change_amount(inputs, bill, dust_fee)},
|
||||
|
||||
"value": virtualchain.calculate_change_amount(inputs, bill, total_tx_fee)},
|
||||
|
||||
# burn address
|
||||
{"script": virtualchain.make_payment_script(str(burn_addr)),
|
||||
"value": op_fee}
|
||||
]
|
||||
|
||||
|
||||
def make_transaction(name, preorder_addr, register_addr, burn_addr, fee, consensus_hash, blockchain_client, tx_fee=0, subsidize=False, safety=True):
|
||||
def make_transaction(name, preorder_addr, register_addr, burn_addr, fee, consensus_hash,
|
||||
blockchain_client, tx_fee=0, subsidize=False, safety=True,
|
||||
dust_included=False):
|
||||
"""
|
||||
Builds and broadcasts a preorder transaction.
|
||||
"""
|
||||
@@ -134,7 +137,7 @@ def make_transaction(name, preorder_addr, register_addr, burn_addr, fee, consens
|
||||
inputs = None
|
||||
private_key_obj = None
|
||||
script_pubkey = None # to be mixed into preorder hash
|
||||
|
||||
|
||||
pay_fee = True
|
||||
if subsidize:
|
||||
pay_fee = False
|
||||
@@ -143,15 +146,15 @@ def make_transaction(name, preorder_addr, register_addr, burn_addr, fee, consens
|
||||
inputs = tx_get_unspents( preorder_addr, blockchain_client )
|
||||
if safety:
|
||||
assert len(inputs) > 0, "No UTXOs for {}".format(preorder_addr)
|
||||
|
||||
|
||||
script_pubkey = virtualchain.make_payment_script( preorder_addr )
|
||||
|
||||
nulldata = build( name, script_pubkey, register_addr, consensus_hash)
|
||||
outputs = make_outputs(nulldata, inputs, preorder_addr, burn_addr, fee, tx_fee, pay_fee=pay_fee)
|
||||
|
||||
outputs = make_outputs(nulldata, inputs, preorder_addr, burn_addr, fee, tx_fee, pay_fee=pay_fee,
|
||||
dust_included = dust_included)
|
||||
|
||||
return (inputs, outputs)
|
||||
|
||||
|
||||
def get_fees( inputs, outputs ):
|
||||
"""
|
||||
Given a transaction's outputs, look up its fees:
|
||||
|
||||
@@ -93,80 +93,78 @@ def build(name, value_hash=None):
|
||||
return packaged_script
|
||||
|
||||
|
||||
def make_outputs( data, change_inputs, register_addr, change_addr, tx_fee, renewal_fee=None, burn_address=BLOCKSTACK_BURN_ADDRESS, pay_fee=True):
|
||||
def make_outputs( data, change_inputs, register_addr, change_addr, tx_fee,
|
||||
renewal_fee=None, burn_address=BLOCKSTACK_BURN_ADDRESS, pay_fee=True,
|
||||
dust_included = False ):
|
||||
"""
|
||||
Make outputs for a register:
|
||||
[0] OP_RETURN with the name, and possibly a value hash
|
||||
[0] OP_RETURN with the name, and possibly a value hash
|
||||
[1] pay-to-address with the *register_addr*, not the sender's address. If renewing, this is the new owner address.
|
||||
[2] change address with the NAME_PREORDER or NAME_RENEWAL's subsidizer's sender's address
|
||||
[3] (OPTIONAL) renewal fee, sent to the burn address
|
||||
|
||||
Raise ValueError if there are not enough inputs to make the transaction
|
||||
"""
|
||||
|
||||
|
||||
dust_fee = None
|
||||
dust_value = DEFAULT_DUST_FEE
|
||||
op_fee = None
|
||||
bill = None
|
||||
|
||||
bill = None
|
||||
|
||||
if pay_fee:
|
||||
|
||||
# sender pays
|
||||
total_tx_fee = tx_fee
|
||||
if renewal_fee is not None:
|
||||
# renewing
|
||||
dust_fee = (len(change_inputs) + 3) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE + tx_fee
|
||||
dust_fee = (len(change_inputs) + 3) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE
|
||||
op_fee = max(renewal_fee, DEFAULT_DUST_FEE)
|
||||
bill = op_fee
|
||||
|
||||
else:
|
||||
# registering
|
||||
dust_fee = (len(change_inputs) + 2) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE + tx_fee
|
||||
dust_fee = (len(change_inputs) + 2) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE
|
||||
op_fee = 0
|
||||
bill = DEFAULT_DUST_FEE * 2
|
||||
|
||||
if not dust_included:
|
||||
total_tx_fee += dust_fee
|
||||
else:
|
||||
|
||||
# subsidized by another address
|
||||
bill = 0
|
||||
total_tx_fee = 0
|
||||
if renewal_fee is not None:
|
||||
# renewing
|
||||
dust_fee = 0
|
||||
op_fee = max(renewal_fee, DEFAULT_DUST_FEE)
|
||||
bill = 0
|
||||
|
||||
else:
|
||||
# registering
|
||||
dust_fee = 0
|
||||
op_fee = 0
|
||||
bill = 0
|
||||
|
||||
|
||||
payload = str(data)
|
||||
|
||||
outputs = [
|
||||
# main output
|
||||
{"script": virtualchain.make_data_script(payload),
|
||||
"value": 0},
|
||||
|
||||
|
||||
# register/new-owner address
|
||||
{"script": virtualchain.make_payment_script(str(register_addr)),
|
||||
"value": dust_value},
|
||||
|
||||
|
||||
# change address (can be the subsidy address)
|
||||
{"script": virtualchain.make_payment_script(str(change_addr)),
|
||||
"value": virtualchain.calculate_change_amount(change_inputs, bill, dust_fee)},
|
||||
"value": virtualchain.calculate_change_amount(change_inputs, bill, total_tx_fee)},
|
||||
]
|
||||
|
||||
|
||||
if renewal_fee is not None:
|
||||
outputs.append(
|
||||
|
||||
# burn address (when renewing)
|
||||
{"script": virtualchain.make_payment_script(str(burn_address)),
|
||||
"value": op_fee}
|
||||
)
|
||||
|
||||
return outputs
|
||||
|
||||
|
||||
def make_transaction(name, preorder_or_owner_addr, register_or_new_owner_addr, blockchain_client, tx_fee=0, burn_address=BLOCKSTACK_BURN_ADDRESS, renewal_fee=None, zonefile_hash=None, subsidize=False, safety=True):
|
||||
def make_transaction(name, preorder_or_owner_addr, register_or_new_owner_addr, blockchain_client,
|
||||
tx_fee=0, burn_address=BLOCKSTACK_BURN_ADDRESS, renewal_fee=None,
|
||||
zonefile_hash=None, subsidize=False, safety=True, dust_included=False):
|
||||
# register_or_new_owner_addr is the address of the recipient in NAME_PREORDER
|
||||
# register_or_new_owner_addr is the address of the current name owner in standard NAME_RENEWAL (pre F-day 2017)
|
||||
# register_or_new_owner_addr is the address of the current or new name owner, in the post-F-day 2017 NAME_RENEWAL
|
||||
@@ -176,7 +174,7 @@ def make_transaction(name, preorder_or_owner_addr, register_or_new_owner_addr, b
|
||||
register_or_new_owner_addr = str(register_or_new_owner_addr)
|
||||
name = str(name)
|
||||
tx_fee = int(tx_fee)
|
||||
|
||||
|
||||
assert is_name_valid(name)
|
||||
|
||||
if renewal_fee is not None:
|
||||
@@ -184,7 +182,7 @@ def make_transaction(name, preorder_or_owner_addr, register_or_new_owner_addr, b
|
||||
|
||||
change_inputs = None
|
||||
pay_fee = True
|
||||
|
||||
|
||||
change_inputs = tx_get_unspents( preorder_or_owner_addr, blockchain_client )
|
||||
if safety:
|
||||
assert len(change_inputs) > 0, "No UTXOs for {}".format(preorder_or_owner_addr)
|
||||
@@ -199,8 +197,10 @@ def make_transaction(name, preorder_or_owner_addr, register_or_new_owner_addr, b
|
||||
pay_fee = False
|
||||
|
||||
nulldata = build(name, value_hash=zonefile_hash)
|
||||
outputs = make_outputs(nulldata, change_inputs, register_or_new_owner_addr, preorder_or_owner_addr, tx_fee, burn_address=burn_address, renewal_fee=renewal_fee, pay_fee=pay_fee )
|
||||
|
||||
outputs = make_outputs(nulldata, change_inputs, register_or_new_owner_addr, preorder_or_owner_addr, tx_fee,
|
||||
burn_address=burn_address, renewal_fee=renewal_fee, pay_fee=pay_fee,
|
||||
dust_included = dust_included)
|
||||
|
||||
return (change_inputs, outputs)
|
||||
|
||||
|
||||
|
||||
@@ -96,24 +96,26 @@ def build(name, keepdata, consensus_hash):
|
||||
return packaged_script
|
||||
|
||||
|
||||
def make_outputs( data, inputs, new_name_owner_address, change_address, tx_fee=0, pay_fee=True):
|
||||
def make_outputs( data, inputs, new_name_owner_address, change_address, tx_fee=0, pay_fee=True,
|
||||
dust_included = False):
|
||||
"""
|
||||
Builds the outputs for a name transfer operation.
|
||||
Raise ValueError if there are not enough inputs to make the transaction
|
||||
"""
|
||||
|
||||
|
||||
dust_fee = None
|
||||
op_fee = None
|
||||
dust_value = DEFAULT_DUST_FEE
|
||||
|
||||
|
||||
if pay_fee:
|
||||
dust_fee = (len(inputs) + 2) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE + tx_fee
|
||||
total_tx_fee = tx_fee
|
||||
if not dust_included:
|
||||
total_tx_fee += (len(inputs) + 2) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE
|
||||
op_fee = DEFAULT_DUST_FEE
|
||||
|
||||
else:
|
||||
dust_fee = 0
|
||||
total_tx_fee = 0
|
||||
op_fee = 0
|
||||
|
||||
|
||||
return [
|
||||
# main output
|
||||
{"script": virtualchain.make_data_script(str(data)),
|
||||
@@ -123,35 +125,39 @@ def make_outputs( data, inputs, new_name_owner_address, change_address, tx_fee=0
|
||||
"value": dust_value},
|
||||
# change output
|
||||
{"script": virtualchain.make_payment_script(change_address),
|
||||
"value": virtualchain.calculate_change_amount(inputs, op_fee, dust_fee)}
|
||||
"value": virtualchain.calculate_change_amount(inputs, op_fee, total_tx_fee)}
|
||||
]
|
||||
|
||||
|
||||
def make_transaction(name, destination_address, keepdata, consensus_hash, old_owner_addr, blockchain_client, tx_fee=0, subsidize=False, safety=True):
|
||||
|
||||
def make_transaction(name, destination_address, keepdata, consensus_hash,
|
||||
old_owner_addr, blockchain_client, tx_fee=0, subsidize=False, safety=True,
|
||||
dust_included = False):
|
||||
|
||||
name = str(name)
|
||||
destination_address = str(destination_address)
|
||||
consensus_hash = str(consensus_hash)
|
||||
old_owner_addr = str(old_owner_addr)
|
||||
tx_fee = int(tx_fee)
|
||||
|
||||
assert len(consensus_hash) == LENGTH_CONSENSUS_HASH * 2
|
||||
assert len(consensus_hash) == LENGTH_CONSENSUS_HASH * 2
|
||||
assert is_name_valid(name)
|
||||
|
||||
# sanity check
|
||||
pay_fee = True
|
||||
if subsidize:
|
||||
pay_fee = False
|
||||
|
||||
|
||||
inputs = tx_get_unspents( old_owner_addr, blockchain_client )
|
||||
if safety:
|
||||
assert len(inputs) > 0, "No UTXOs for {}".format(old_owner_addr)
|
||||
|
||||
|
||||
nulldata = build(name, keepdata, consensus_hash)
|
||||
outputs = make_outputs(nulldata, inputs, destination_address, old_owner_addr, tx_fee, pay_fee=pay_fee)
|
||||
outputs = make_outputs(nulldata, inputs, destination_address,
|
||||
old_owner_addr, tx_fee, pay_fee=pay_fee,
|
||||
dust_included = dust_included)
|
||||
|
||||
return (inputs, outputs)
|
||||
|
||||
|
||||
|
||||
def get_fees( inputs, outputs ):
|
||||
"""
|
||||
|
||||
@@ -95,31 +95,33 @@ def make_outputs( data, inputs, change_address, tx_fee, pay_fee=True ):
|
||||
|
||||
dust_fee = None
|
||||
op_fee = None
|
||||
dust_value = None
|
||||
|
||||
dust_value = None
|
||||
|
||||
total_tx_fee = tx_fee
|
||||
if pay_fee:
|
||||
dust_fee = (len(inputs) + 1) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE + tx_fee
|
||||
if not dust_included:
|
||||
total_tx_fee += (len(inputs) + 1) * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE
|
||||
op_fee = DEFAULT_DUST_FEE
|
||||
dust_value = DEFAULT_DUST_FEE
|
||||
|
||||
else:
|
||||
# will be subsidized
|
||||
dust_fee = 0
|
||||
total_tx_fee = 0
|
||||
op_fee = 0
|
||||
dust_value = 0
|
||||
|
||||
|
||||
return [
|
||||
# main output
|
||||
{"script": virtualchain.make_data_script(str(data)),
|
||||
"value": 0},
|
||||
|
||||
|
||||
# change output
|
||||
{"script": virtualchain.make_payment_script(change_address),
|
||||
"value": virtualchain.calculate_change_amount(inputs, op_fee, dust_fee)}
|
||||
"value": virtualchain.calculate_change_amount(inputs, op_fee, total_tx_fee)}
|
||||
]
|
||||
|
||||
|
||||
def make_transaction(name, data_hash, consensus_hash, owner_addr, blockchain_client, tx_fee=0, subsidize=False, safety=True):
|
||||
def make_transaction(name, data_hash, consensus_hash, owner_addr, blockchain_client,
|
||||
tx_fee=0, subsidize=False, safety=True, dust_included = False):
|
||||
"""
|
||||
Write a name update into the blockchain.
|
||||
Returns a JSON object with 'data' set to the nulldata and 'transaction_hash' set to the transaction hash on success.
|
||||
@@ -133,8 +135,8 @@ def make_transaction(name, data_hash, consensus_hash, owner_addr, blockchain_cli
|
||||
|
||||
assert len(consensus_hash) == LENGTH_CONSENSUS_HASH * 2
|
||||
assert is_name_valid(name)
|
||||
|
||||
# sanity check
|
||||
|
||||
# sanity check
|
||||
pay_fee = True
|
||||
if subsidize:
|
||||
pay_fee = False
|
||||
@@ -144,8 +146,9 @@ def make_transaction(name, data_hash, consensus_hash, owner_addr, blockchain_cli
|
||||
assert len(inputs) > 0, "No UTXOs for {}".format(owner_addr)
|
||||
|
||||
nulldata = build(name, consensus_hash, data_hash=data_hash)
|
||||
outputs = make_outputs( nulldata, inputs, owner_addr, tx_fee, pay_fee=pay_fee )
|
||||
|
||||
outputs = make_outputs( nulldata, inputs, owner_addr, tx_fee, pay_fee=pay_fee,
|
||||
dust_included = dust_included )
|
||||
|
||||
return (inputs, outputs)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user