get_utxo and select_utxo

pull/134/head
Andreas M. Antonopoulos 10 years ago
parent 8828882153
commit 08055ea163

@ -78,7 +78,6 @@ The UTXO consumed by a transaction are called transaction inputs, while the UTXO
The exception to the output and input chain is a special type of transaction called the _coinbase_ transaction, which is the first transaction in each block. This transaction is placed there by the "winning" miner and creates brand-new bitcoin payable to that miner as a reward for mining. This is how bitcoin's money supply is created during the mining process as we will see in <<mining>>.
[TIP]
====
What comes first? Inputs or outputs, the chicken or the egg? Strictly speaking, outputs come first because coinbase transactions, which generate new bitcoin, have no inputs and create outputs from nothing.
@ -108,6 +107,32 @@ The transaction scripting language, used in the locking script mentioned above,
| Variable | Locking-Script | A script defining the conditions needed to spend the output
|=======
In the example below, we use the blockchain.info API to find the unspent outputs (UTXO) of a specific address:
[[get_utxo]]
.A script that calls the blockchain.info API to find the UTXO related to an address
====
[source, python]
----
include::code/get-utxo.py[]
----
====
Running the script, we see a list of transaction IDs, a colon, the index number of the specific unspent transaction output (UTXO), and the value of that UTXO in Satoshis. The locking script is not shown in this output:
[[get_utxo_run]]
.Running the get-utxo.py script
====
[source,bash]
----
$ python get-utxo.py
ebadfaa92f1fd29e2fe296eda702c48bd11ffd52313e986e99ddad9084062167:1 - 8000000 Satoshis
6596fd070679de96e405d52b51b8e1d644029108ec4cbfe451454486796a1ecf:0 - 16050000 Satoshis
74d788804e2aae10891d72753d1520da1206e6f4f20481cc1555b7f2cb44aca0:0 - 5000000 Satoshis
b2affea89ff82557c60d635a2a3137b8f88f12ecec85082f7d0a1f82ee203ac4:0 - 10000000 Satoshis
...
----
====
===== Spending Conditions (Encumbrances)
Transaction outputs associate a specific amount (in satoshis) to a specific _encumbrance_ or locking-script that defines the condition that must be met to spend that amount. In most cases the locking script will lock the output to a specific bitcoin address, thereby transferring ownership of that amount to the new owner. When Alice paid Bob's Cafe for a cup of coffee, her transaction created a 0.015 bitcoin output _encumbered_ or locked to the Cafe's bitcoin address. That 0.015 bitcoin output was recorded on the blockchain and became part of the Unspent Transaction Output set, meaning it showed in Bob's wallet as part of the available balance. When Bob chooses to spend that amount, his transaction will release the encumbrance, unlocking the output by providing an unlocking script containing a signature from Bob's private key.
@ -117,7 +142,33 @@ Transaction outputs associate a specific amount (in satoshis) to a specific _enc
In simple terms, transaction inputs are pointers to UTXO. They point to a specific UTXO by reference to the transaction hash and sequence number where the UTXO is recorded in the blockchain. To spend UTXO, a transaction input also includes unlocking-scripts that satisfy the spending conditions set by the UTXO. The unlocking script is usually a signature proving ownership of the bitcoin address that is in the locking script.
When a user makes a payment, their wallet constructs a transaction by selecting from the available UTXO. For example, to make a 0.015 bitcoin payment, the wallet app may select a 0.01 UTXO and a 0.005 UTXO, using them both to add up to the desired payment amount. The wallet then produces unlocking scripts containing signatures for each of the UTXO, thereby making them spendable by satisfying their locking script conditions. The wallet adds these UTXO references and unlocking scripts as inputs to the transaction.
When a user makes a payment, their wallet constructs a transaction by selecting from the available UTXO. For example, to make a 0.015 bitcoin payment, the wallet app may select a 0.01 UTXO and a 0.005 UTXO, using them both to add up to the desired payment amount.
In the example below, we show the use of a "greedy" algorithm to select from available UTXO in order to make a specific payment amount. In the example, the available UTXO are provided as a constant array, but in reality, the available UTXO would be retrieved with an RPC call to Bitcoin Core, or to a third-party API as shown in <<get_utxo>>.
[[select_utxo]]
.A script for calculating how much total bitcoin will be issued
====
[source, python]
----
include::code/select-utxo.py[]
----
====
If we run the select-utxo.py script without a parameter it will attempt to construct a set of UTXO (and change) for a payment of 55000000 Satoshis (0.55 bitcoin). If you provide a target payment amount as a parameter, the script will select UTXO to make that target payment amount. Below, we run the script trying to make a payment of 0.5 bitcoin or 50000000 Satoshis:
[[select_utxo_run]]
.Running the select-utxo.py script
====
[source,bash]
----
$ python select-utxo.py 50000000
For transaction amount 50000000 Satoshis (0.500000 bitcoin) use:
([<7dbc497969c7475e45d952c4a872e213fb15d45e5cd3473c386a71a1b0c136a1:0 with 25000000 Satoshis>, <7f42eda67921ee92eae5f79bd37c68c9cb859b899ce70dba68c48338857b7818:0 with 16100000 Satoshis>, <6596fd070679de96e405d52b51b8e1d644029108ec4cbfe451454486796a1ecf:0 with 16050000 Satoshis>], 'Change: 7150000 Satoshis')
----
====
The wallet then produces unlocking scripts containing signatures for each of the UTXO, thereby making them spendable by satisfying their locking script conditions. The wallet adds these UTXO references and unlocking scripts as inputs to the transaction.
[[tx_in_structure]]
.The structure of a transaction input
@ -131,7 +182,7 @@ When a user makes a payment, their wallet constructs a transaction by selecting
| 4 bytes | Sequence Number | Currently-disabled Tx-replacement feature, set to 0xFFFFFFFF
|=======
Note: The sequence number is used to override a transaction prior to the expiration of the transaction locktime, which is a feature that is currently disabled in bitcoin. Most transactions set this value to the maximum integer value (0xFFFFFFFF) and it is ignored by the bitcoin network. If the transaction has a non-zero locktime, at least one of its inputs must have a sequence number below 0xFFFFFFFF in order to enable locktime.
Note: The sequence number is used to override a transaction prior to the expiration of the transaction locktime, which is a feature that is currently disabled in bitcoin. Most transactions set this value to the maximum integer value (0xFFFFFFFF) and it is ignored by the bitcoin network. If the transaction has a non-zero locktime, at least one of its inputs must have a sequence number below 0xFFFFFFFF in order to enable locktime.
[[tx_fees]]
==== Transaction Fees

@ -0,0 +1,28 @@
# get unspent outputs from blockchain API
import json
import requests
# example address
address = '1Dorian4RoXcnBv9hnQ4Y2C1an6NJ4UrjX'
# The API URL is https://blockchain.info/unspent?active=<address>
# It returns a JSON object with a list "unspent_outputs", containing UTXO, like this:
#{ "unspent_outputs":[
# {
# "tx_hash":"ebadfaa92f1fd29e2fe296eda702c48bd11ffd52313e986e99ddad9084062167",
# "tx_index":51919767,
# "tx_output_n": 1,
# "script":"76a9148c7e252f8d64b0b6e313985915110fcfefcf4a2d88ac",
# "value": 8000000,
# "value_hex": "7a1200",
# "confirmations":28691
# },
# ...
#]}
resp = requests.get('https://blockchain.info/unspent?active=%s' % address)
utxo_set = json.loads(resp.text)["unspent_outputs"]
for utxo in utxo_set:
print "%s:%d - %ld Satoshis" % (utxo['tx_hash'], utxo['tx_output_n'], utxo['value'])

@ -0,0 +1,68 @@
# Selects outputs from a UTXO list using a greedy algorithm.
from sys import argv
class OutputInfo:
def __init__(self, tx_hash, tx_index, value):
self.tx_hash = tx_hash
self.tx_index = tx_index
self.value = value
def __repr__(self):
return "<%s:%s with %s Satoshis>" % (self.tx_hash, self.tx_index,
self.value)
# Select optimal outputs for a send from unspent outputs list.
# Returns output list and remaining change to be sent to
# a change address.
def select_outputs_greedy(unspent, min_value):
# Fail if empty.
if not unspent:
return None
# Partition into 2 lists.
lessers = [utxo for utxo in unspent if utxo.value < min_value]
greaters = [utxo for utxo in unspent if utxo.value >= min_value]
key_func = lambda utxo: utxo.value
if greaters:
# Not-empty. Find the smallest greater.
min_greater = min(greaters)
change = min_greater.value - min_value
return [min_greater], change
# Not found in greaters. Try several lessers instead.
# Rearrange them from biggest to smallest. We want to use the least
# amount of inputs as possible.
lessers.sort(key=key_func, reverse=True)
result = []
accum = 0
for utxo in lessers:
result.append(utxo)
accum += utxo.value
if accum >= min_value:
change = accum - min_value
return result, "Change: %d Satoshis" % change
# No results found.
return None, 0
def main():
unspent = [
OutputInfo("ebadfaa92f1fd29e2fe296eda702c48bd11ffd52313e986e99ddad9084062167", 1, 8000000),
OutputInfo("6596fd070679de96e405d52b51b8e1d644029108ec4cbfe451454486796a1ecf", 0, 16050000),
OutputInfo("b2affea89ff82557c60d635a2a3137b8f88f12ecec85082f7d0a1f82ee203ac4", 0, 10000000),
OutputInfo("7dbc497969c7475e45d952c4a872e213fb15d45e5cd3473c386a71a1b0c136a1", 0, 25000000),
OutputInfo("55ea01bd7e9afd3d3ab9790199e777d62a0709cf0725e80a7350fdb22d7b8ec6", 17, 5470541),
OutputInfo("12b6a7934c1df821945ee9ee3b3326d07ca7a65fd6416ea44ce8c3db0c078c64", 0, 10000000),
OutputInfo("7f42eda67921ee92eae5f79bd37c68c9cb859b899ce70dba68c48338857b7818", 0, 16100000),
]
if len(argv) > 1:
target = long(argv[1])
else:
target = 55000000
print "For transaction amount %d Satoshis (%f bitcoin) use: " % (target, target/10.0**8)
print select_outputs_greedy(unspent, target)
if __name__ == "__main__":
main()
Loading…
Cancel
Save