handle creating transactions where input is consumed by fees and there is no output by creating an additional input which will require some change output

This commit is contained in:
Lex Berezhny 2018-11-06 19:16:27 -05:00
parent ae8fece9bb
commit 268e599423

View file

@ -444,6 +444,8 @@ class BaseTransaction:
try: try:
for _ in range(2):
if payment < cost: if payment < cost:
deficit = cost - payment deficit = cost - payment
spendables = await ledger.get_spendable_utxos(deficit, funding_accounts) spendables = await ledger.get_spendable_utxos(deficit, funding_accounts)
@ -452,11 +454,11 @@ class BaseTransaction:
payment += sum(s.effective_amount for s in spendables) payment += sum(s.effective_amount for s in spendables)
tx.add_inputs(s.txi for s in spendables) tx.add_inputs(s.txi for s in spendables)
if payment > cost:
cost_of_change = ( cost_of_change = (
tx.get_base_fee(ledger) + tx.get_base_fee(ledger) +
cls.output_class.pay_pubkey_hash(COIN, NULL_HASH32).get_fee(ledger) cls.output_class.pay_pubkey_hash(COIN, NULL_HASH32).get_fee(ledger)
) )
if payment > cost:
change = payment - cost change = payment - cost
if change > cost_of_change: if change > cost_of_change:
change_address = await change_account.change.get_or_create_usable_address() change_address = await change_account.change.get_or_create_usable_address()
@ -466,6 +468,19 @@ class BaseTransaction:
change_output.is_change = True change_output.is_change = True
tx.add_outputs([cls.output_class.pay_pubkey_hash(change_amount, change_hash160)]) tx.add_outputs([cls.output_class.pay_pubkey_hash(change_amount, change_hash160)])
if tx._outputs:
break
else:
# this condition and the outer range(2) loop cover an edge case
# whereby a single input is just enough to cover the fee and
# has some change left over, but the change left over is less
# than the cost_of_change: thus the input is completely
# consumed and no output is added, which is an invalid tx.
# to be able to spend this input we must increase the cost
# of the TX and run through the balance algorithm a second time
# adding an extra input and change output, making tx valid.
cost = cost + cost_of_change + 1
await tx.sign(funding_accounts) await tx.sign(funding_accounts)
except Exception as e: except Exception as e: