diff --git a/_autocrossref.yaml b/_autocrossref.yaml index c34bb6ba..24f4182e 100644 --- a/_autocrossref.yaml +++ b/_autocrossref.yaml @@ -127,14 +127,11 @@ parent key: parent private key: parent private and public keys: parent key parent public key: -Payment message: pp payment payment protocol: "payment protocol's": payment protocol -PaymentACK: PaymentDetails: PaymentRequest: PaymentRequests: paymentrequest -'`payment_url`': pp payment url peer: peers: peer peer-to-peer network: network @@ -160,7 +157,6 @@ recurrent rebilling: redeemScript: refund: refunds: refund -'`refund_to`': pp refund to root certificate: root seed: RPCs: rpc @@ -222,6 +218,8 @@ BIP21: BIP32: BIP39: BIP70: +BIP71: +BIP72: ## RPCs '`addmultisigaddress`': rpc addmultisigaddress diff --git a/_includes/example_payment_processing.md b/_includes/example_payment_processing.md new file mode 100644 index 00000000..5272b4fe --- /dev/null +++ b/_includes/example_payment_processing.md @@ -0,0 +1,455 @@ +## Payment Processing + +### Payment Protocol + +{% autocrossref %} + +To request payment using the payment protocol, you use an extended (but +backwards-compatible) `bitcoin:` URI. For example: + +~~~ +bitcoin:mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN\ +?amount=0.10\ +&label=Example+Merchant\ +&message=Order+of+flowers+%26+chocolates\ +&r=https://example.com/pay.php/invoice%3Dda39a3ee +~~~ + +The browser, QR code reader, or other program processing the URI opens +the spender's Bitcoin wallet program on the URI. If the wallet program is +aware of the payment protocol, it accesses the URL specified in the `r` +parameter, which should provide it with a serialized PaymentRequest +served with the [MIME][] type `application/bitcoin-paymentrequest`. + +**Resource:** Gavin Andresen's [Payment Request Generator][] generates +custom example URIs and payment requests for use with testnet. + +{% endautocrossref %} + +#### PaymentRequest & PaymentDetails + +{% autocrossref %} + +The [PaymentRequest][]{:#term-paymentrequest}{:.term} is created with data structures built using +Google's Protocol Buffers. BIP70 describes these data +structures in the non-sequential way they're defined in the payment +request protocol buffer code, but the text below will describe them in +a more linear order using a simple (but functional) Python CGI +program. (For brevity and clarity, many normal CGI best practices are +not used in this program.) + +The full sequence of events is illustrated below, starting with the +spender clicking a `bitcoin:` URI or scanning a `bitcoin:` QR code. + +![BIP70 Payment Protocol](/img/dev/en-payment-protocol.svg) + +For the script to use the protocol buffer, you will need a copy of +Google's Protocol Buffer compiler (`protoc`), which is available in most +modern Linux package managers and [directly from Google.][protobuf] Non-Google +protocol buffer compilers are available for a variety of +programming languages. You will also need a copy of the PaymentRequest +[Protocol Buffer description][core paymentrequest.proto] from the Bitcoin Core source code. + +{% endautocrossref %} + +##### Initialization Code + +{% autocrossref %} + +With the Python code generated by `protoc`, we can start our simple +CGI program. + +{% highlight python %} +#!/usr/bin/env python + +## This is the code generated by protoc --python_out=./ paymentrequest.proto +from paymentrequest_pb2 import * + +## Load some functions +from time import time +from sys import stdout +from OpenSSL.crypto import FILETYPE_PEM, load_privatekey, sign + +## Copy three of the classes created by protoc into objects we can use +details = PaymentDetails() +request = PaymentRequest() +x509 = X509Certificates() +{% endhighlight %} + +The startup code above is quite simple, requiring nothing but the epoch +(Unix date) time function, the standard out file descriptor, a few +functions from the OpenSSL library, and the data structures and +functions created by `protoc`. + +{% endautocrossref %} + +##### Configuration Code + +{% autocrossref %} + +Next, we'll set configuration settings which will typically only change +when the receiver wants to do something differently. The code pushes a +few settings into the `request` (PaymentRequest) and `details` +(PaymentDetails) objects. When we serialize them, +[PaymentDetails][]{:#term-paymentdetails}{:.term} will be contained +within the PaymentRequest. + +{% highlight python %} +## SSL Signature method +request.pki_type = "x509+sha256" ## Default: none + +## Mainnet or Testnet? +details.network = "test" ## Default: main + +## Postback URL +details.payment_url = "https://example.com/pay.py" + +## PaymentDetails version number +request.payment_details_version = 1 ## Default: 1 + +## Certificate chain +x509.certificate.append(file("/etc/apache2/example.com-cert.der", "r").read()) +#x509.certificate.append(file("/some/intermediate/cert.der", "r").read()) + +## Load private SSL key into memory for signing later +priv_key = "/etc/apache2/example.com-key.pem" +pw = "test" ## Key password +private_key = load_privatekey(FILETYPE_PEM, file(priv_key, "r").read(), pw) +{% endhighlight %} + +Each line is described below. + +{% highlight python %} +request.pki_type = "x509+sha256" ## Default: none +{% endhighlight %} + +`pki_type`: (optional) tell the receiving wallet program what [Public-Key +Infrastructure][PKI]{:#term-pki}{:.term} (PKI) type you're using to +cryptographically sign your PaymentRequest so that it can't be modified +by a man-in-the-middle attack. + +If you don't want to sign the PaymentRequest, you can choose a +[`pki_type`][pp pki type]{:#term-pp-pki-type}{:.term} of `none` +(the default). + +If you do choose the sign the PaymentRequest, you currently have two +options defined by BIP70: `x509+sha1` and `x509+sha256`. Both options +use the X.509 certificate system, the same system used for HTTP Secure +(HTTPS). To use either option, you will need a certificate signed by a +certificate authority or one of their intermediaries. (A self-signed +certificate will not work.) + +Each wallet program may choose which certificate authorities to trust, +but it's likely that they'll trust whatever certificate authorities their +operating system trusts. If the wallet program doesn't have a full +operating system, as might be the case for small hardware wallets, BIP70 +suggests they use the [Mozilla Root Certificate Store][mozrootstore]. In +general, if a certificate works in your web browser when you connect to +your webserver, it will work for your PaymentRequests. + +{% highlight python %} +details.network = "test" ## Default: main +{% endhighlight %} + +`network`: (optional) tell the spender's wallet program what Bitcoin network you're +using; BIP70 defines "main" for mainnet (actual payments) and "test" for +testnet (like mainnet, but fake satoshis are used). If the wallet +program doesn't run on the network you indicate, it will reject the +PaymentRequest. + +{% highlight python %} +details.payment_url = "https://example.com/pay.py" +{% endhighlight %} + +`payment_url`: (required) tell the spender's wallet program where to send the Payment +message (described later). This can be a static URL, as in this example, +or a variable URL such as `https://example.com/pay.py?invoice=123.` +It should usually be an HTTPS address to prevent man-in-the-middle +attacks from modifying the message. + +{% highlight python %} +request.payment_details_version = 1 ## Default: 1 +{% endhighlight %} + +`payment_details_version`: (optional) tell the spender's wallet program what version of the +PaymentDetails you're using. As of this writing, the only version is +version 1. + +{% highlight python %} +## This is the pubkey/certificate corresponding to the private SSL key +## that we'll use to sign: +x509.certificate.append(file("/etc/apache2/example.com-cert.der", "r").read()) +{% endhighlight %} + +`x509certificates`: (required for signed PaymentRequests) you must +provide the public SSL key/certificate corresponding to the private SSL +key you'll use to sign the PaymentRequest. The certificate must be in +ASN.1/DER format. + +{% highlight python %} +## If the pubkey/cert above didn't have the signature of a root +## certificate authority, we'd then append the intermediate certificate +## which signed it: +#x509.certificate.append(file("/some/intermediate/cert.der", "r").read()) +{% endhighlight %} + +You must also provide any intermediate certificates necessary to link +your certificate to the root certificate of a certificate authority +trusted by the spender's software, such as a certificate from the +Mozilla root store. + +The certificates must be provided in a specific order---the same order +used by Apache's `SSLCertificateFile` directive and other server +software. The figure below shows the [certificate chain][]{:#term-certificate-chain}{:.term} of the +www.bitcoin.org X.509 certificate and how each certificate (except the +root certificate) would be loaded into the [X509Certificates][]{:#term-x509certificates}{:.term} protocol +buffer message. + +![X509Certificates Loading Order](/img/dev/en-cert-order.svg) + +To be specific, the first certificate provided must be the +X.509 certificate corresponding to the private SSL key which will make the +signature, called the [leaf certificate][]{:#term-leaf-certificate}{:.term}. Any [intermediate +certificates][intermediate certificate]{:#term-intermediate-certificate}{:.term} necessary to link that signed public SSL +key to the [root +certificate][]{:#term-root-certificate}{:.term} (the certificate authority) are attached separately, with each +certificate in DER format bearing the signature of the certificate that +follows it all the way to (but not including) the root certificate. + +{% highlight python %} +priv_key = "/etc/apache2/example.com-key.pem" +pw = "test" ## Key password +private_key = load_privatekey(FILETYPE_PEM, file(priv_key, "r").read(), pw) +{% endhighlight %} + +(Required for signed PaymentRequests) you will need a private SSL key in +a format your SSL library supports (DER format is not required). In this +program, we'll load it from a PEM file. (Embedding your passphrase in +your CGI code, as done here, is obviously a bad idea in real life.) + +The private SSL key will not be transmitted with your request. We're +only loading it into memory here so we can use it to sign the request +later. + +{% endautocrossref %} + +##### Code Variables + +{% autocrossref %} + +Now let's look at the variables your CGI program will likely set for +each payment. + +{% highlight python %} +## Amount of the request +amount = 10000000 ## In satoshis + +## P2PKH pubkey hash +pubkey_hash = "2b14950b8d31620c6cc923c5408a701b1ec0a020" +## P2PKH output script entered as hex and converted to binary +# OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG +# 76 a9 14 88 ac +hex_script = "76" + "a9" + "14" + pubkey_hash + "88" + "ac" +serialized_script = hex_script.decode("hex") + +## Load amount and script into PaymentDetails +details.outputs.add(amount = amount, script = serialized_script) + +## Memo to display to the spender +details.memo = "Flowers & chocolates" + +## Data which should be returned to you with the payment +details.merchant_data = "Invoice #123" +{% endhighlight python %} + +Each line is described below. + +{% highlight python %} +amount = 10000000 ## In satoshis (=100 mBTC) +{% endhighlight %} + +`amount`: (optional) the [amount][pp amount]{:#term-pp-amount}{:.term} you want the spender to pay. You'll probably get + this value from your shopping cart application or fiat-to-BTC exchange + rate conversion tool. If you leave the amount blank, the wallet + program will prompt the spender how much to pay (which can be useful + for donations). + +{% highlight python %} +pubkey_hash = "2b14950b8d31620c6cc923c5408a701b1ec0a020" +# OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG +# 76 a9 14 88 ac +hex_script = "76" + "a9" + "14" + pubkey_hash + "88" + "ac" +serialized_script = hex_script.decode("hex") +{% endhighlight %} + +`script`: (required) You must specify the output script you want the spender to +pay---any valid script is acceptable. In this example, we'll request +payment to a P2PKH output script. + +First we get a pubkey hash. The hash above is the hash form of the +address used in the URI examples throughout this section, +mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN. + +Next, we plug that hash into the standard P2PKH output script using hex, +as illustrated by the code comments. + +Finally, we convert the output script from hex into its serialized form. + +{% highlight python %} +details.outputs.add(amount = amount, script = serialized_script) +{% endhighlight %} + +`outputs`: (required) add the output script and (optional) amount to the +PaymentDetails outputs array. + +It's possible to specify multiple [`scripts`][pp +script]{:#term-pp-script}{:.term} and `amounts` as part of a merge +avoidance strategy, described later in the [Merge Avoidance +subsection][]. However, effective merge avoidance is not possible under +the base BIP70 rules in which the spender pays each `script` the exact +amount specified by its paired `amount`. If the amounts are omitted from +all `amount`/`script` pairs, the spender will be prompted to choose an +amount to pay. + +{% highlight python %} +details.memo = "Flowers & chocolates" +{% endhighlight %} + +`memo`: (optional) add a memo which will be displayed to the spender as +plain UTF-8 text. Embedded HTML or other markup will not be processed. + +{% highlight python %} +details.merchant_data = "Invoice #123" +{% endhighlight %} + +`merchant_data`: (optional) add arbitrary data which should be sent back to the +receiver when the invoice is paid. You can use this to track your +invoices, although you can more reliably track payments by generating a +unique address for each payment and then tracking when it gets paid. + +The [`memo`][pp memo]{:#term-pp-memo}{:.term} field and the [`merchant_data`][pp merchant data]{:#term-pp-merchant-data}{:.term} field can be arbitrarily long, +but if you make them too long, you'll run into the 50,000 byte limit on +the entire PaymentRequest, which includes the often several kilobytes +given over to storing the certificate chain. As will be described in a +later subsection, the `memo` field can be used by the spender after +payment as part of a cryptographically-proven receipt. + +{% endautocrossref %} + +##### Derivable Data + +{% autocrossref %} + +Next, let's look at some information your CGI program can +automatically derive. + +{% highlight python %} +## Request creation time +details.time = int(time()) ## Current epoch (Unix) time + +## Request expiration time +details.expires = int(time()) + 60 * 10 ## 10 minutes from now + +## PaymentDetails is complete; serialize it and store it in PaymentRequest +request.serialized_payment_details = details.SerializeToString() + +## Serialized certificate chain +request.pki_data = x509.SerializeToString() + +## Initialize signature field so we can sign the full PaymentRequest +request.signature = "" + +## Sign PaymentRequest +request.signature = sign(private_key, request.SerializeToString(), "sha256") +{% endhighlight %} + +Each line is described below. + +{% highlight python %} +details.time = int(time()) ## Current epoch (Unix) time +{% endhighlight %} + +`time`: (required) PaymentRequests must indicate when they were created +in number of seconds elapsed since 1970-01-01T00:00 UTC (Unix +epoch time format). + +{% highlight python %} +details.expires = int(time()) + 60 * 10 ## 10 minutes from now +{% endhighlight %} + +`expires`: (optional) the PaymentRequest may also set an [`expires`][pp +expires]{:#term-pp-expires}{:.term} time after +which they're no longer valid. You probably want to give receivers +the ability to configure the expiration time delta; here we used the +reasonable choice of 10 minutes. If this request is tied to an order +total based on a fiat-to-satoshis exchange rate, you probably want to +base this on a delta from the time you got the exchange rate. + +{% highlight python %} +request.serialized_payment_details = details.SerializeToString() +{% endhighlight %} + +`serialized_payment_details`: (required) we've now set everything we need to create the +PaymentDetails, so we'll use the SerializeToString function from the +protocol buffer code to store the PaymentDetails in the appropriate +field of the PaymentRequest. + +{% highlight python %} +request.pki_data = x509.SerializeToString() +{% endhighlight %} + +`pki_data`: (required for signed PaymentRequests) serialize the certificate chain +[PKI data][pp PKI data]{:#term-pp-pki-data}{:.term} and store it in the +PaymentRequest + +{% highlight python %} +request.signature = "" +{% endhighlight %} + +We've filled out everything in the PaymentRequest except the signature, +but before we sign it, we have to initialize the signature field by +setting it to a zero-byte placeholder. + +{% highlight python %} +request.signature = sign(private_key, request.SerializeToString(), "sha256") +{% endhighlight %} + +`signature`: (required for signed PaymentRequests) now we +make the [signature][ssl signature]{:#term-ssl-signature}{:.term} by +signing the completed and serialized PaymentRequest. We'll use the +private key we stored in memory in the configuration section and the +same hashing formula we specified in `pki_type` (sha256 in this case) + +{% endautocrossref %} + +##### Output Code + +{% autocrossref %} + +Now that we have PaymentRequest all filled out, we can serialize it and +send it along with the HTTP headers, as shown in the code below. + +{% highlight python %} +print "Content-Type: application/bitcoin-paymentrequest" +print "Content-Transfer-Encoding: binary" +print "" +{% endhighlight %} + +(Required) BIP71 defines the content types for PaymentRequests, +Payments, and PaymentACKs. + +{% highlight python %} +file.write(stdout, request.SerializeToString()) +{% endhighlight %} + +`request`: (required) now, to finish, we just dump out the serialized +PaymentRequest (which contains the serialized PaymentDetails). The +serialized data is in binary, so we can't use Python's print() +because it would add an extraneous newline. + +The following screenshot shows how the authenticated PaymentDetails +created by the program above appears in the GUI from Bitcoin Core 0.9. + +![Bitcoin Core Showing Validated Payment Request](/img/dev/en-btcc-payment-request.png) + +{% endautocrossref %} diff --git a/_includes/example_transactions.md b/_includes/example_transactions.md new file mode 100644 index 00000000..62cc69e0 --- /dev/null +++ b/_includes/example_transactions.md @@ -0,0 +1,1270 @@ +## Transactions + +### Transaction Tutorial + +{% autocrossref %} + +Creating transactions is something most Bitcoin applications do. +This section describes how to use Bitcoin Core's RPC interface to +create transactions with various attributes. + +Your applications may use something besides Bitcoin Core to create +transactions, but in any system, you will need to provide the same kinds +of data to create transactions with the same attributes as those +described below. + +You are encouraged to try the following examples on your own using the +regtest mode described below. + +Note: as in other parts of the documentation, we wrap long strings with +"\\" and indicate omissions with "[...]". + +{% endautocrossref %} + +#### Regtest Mode + +{% autocrossref %} + +Bitcoin's testnet provides an excellent way to test Bitcoin +functionality without risking real satoshis. However, for situations +where interaction with random peers and blocks is unnecessary or +unwanted, Bitcoin Core's regression test (regtest) mode lets you +instantly create a brand-new private block chain with the same basic +rules as testnet---but one major difference: you choose when to create +new blocks, so you have complete control over the environment. + +Many developers consider regtest mode the preferred way to develop new +applications, and this tutorial will use it exclusively. + +{% highlight bash %} +> bitcoind -regtest -daemon +Bitcoin server starting +{% endhighlight %} + +Start `bitcoind` in regtest mode to create a private block chain. + +{% highlight bash %} +> bitcoin-cli -regtest getbalance +0.00000000 +{% endhighlight %} + +Check our starting balance with the `getbalance` RPC. Regtest wallets +and block chain state (chainstate) are saved in the `regtest` +subdirectory of the Bitcoin Core configuration directory. You can safely +delete the `regtest` subdirectory and restart Bitcoin Core to start a +new regtest. (See the [Guide Introduction][devguide] for default configuration +directory locations on various operating systems. Always back up mainnet +wallets before performing dangerous operations such as deleting.) + +~~~ +bitcoin-cli -regtest setgenerate true 101 +~~~ + +Generate 101 blocks using a special version of the `setgenerate` RPC +which is only available in regtest mode. This takes about 30 seconds on +a generic PC. Because this is a new block chain using Bitcoin's default +rules, the first 210,000 blocks pay a block reward of 50 bitcoins. +However, a block must have 100 confirmations before that reward can be +spent, so we generate 101 blocks to get access to the coinbase +transaction from block #1. + +{% highlight bash %} +bitcoin-cli -regtest getbalance +50.00000000 +{% endhighlight %} + +Verify that we now have 50 bitcoins available to spend. + +{% endautocrossref %} + + + + + + +#### Simple Spending + +{% autocrossref %} + +Bitcoin Core provides several RPCs which handle all the details of +spending, including creating change outputs and paying appropriate fees. +Even advanced users should use these RPCs whenever possible to decrease +the chance that satoshis will be lost by mistake. + +{% highlight bash %} +> bitcoin-cli -regtest getnewaddress +mvbnrCX3bg1cDRUu8pkecrvP6vQkSLDSou + +> NEW_ADDRESS=mvbnrCX3bg1cDRUu8pkecrvP6vQkSLDSou +{% endhighlight %} + +Get a new Bitcoin address and save it in the shell variable `$NEW_ADDRESS`. + +{% highlight bash %} +> bitcoin-cli -regtest sendtoaddress $NEW_ADDRESS 10.00 +263c018582731ff54dc72c7d67e858c002ae298835501d80200f05753de0edf0 +{% endhighlight %} + +Send 10 bitcoins to the address using the `sendtoaddress` RPC. The +returned hex string is the transaction identifier (txid). + +The `sendtoaddress` RPC automatically selects an unspent transaction +output (UTXO) from which to spend the satoshis. In this case, it +withdrew the satoshis from our only available UTXO, the coinbase +transaction for block #1 which matured with the creation of block #101. +To spend a specific UTXO, you could use the `sendfrom` RPC instead. + +{% highlight bash %} +> bitcoin-cli -regtest listunspent +[ +] +{% endhighlight %} + +Use the `listunspent` RPC to display the UTXOs belonging to this wallet. +The list is empty because it defaults to only showing confirmed +UTXOs and we just spent our only confirmed UTXO. + +
+{% highlight bash %} +> bitcoin-cli -regtest listunspent 0 +{% endhighlight %} +{% highlight json %} +[ + { + "txid" : "263c018582731ff54dc72c7d67e858c002ae298835501d\ + 80200f05753de0edf0", + "vout" : 0, + "address" : "muhtvdmsnbQEPFuEmxcChX58fGvXaaUoVt", + "scriptPubKey" : "76a9149ba386253ea698158b6d34802bb9b550\ + f5ce36dd88ac", + "amount" : 40.00000000, + "confirmations" : 0 + }, + { + "txid" : "263c018582731ff54dc72c7d67e858c002ae298835501d\ + 80200f05753de0edf0", + "vout" : 1, + "address" : "mvbnrCX3bg1cDRUu8pkecrvP6vQkSLDSou", + "account" : "", + "scriptPubKey" : "76a914a57414e5ffae9ef5074bacbe10a320bb\ + 2614e1f388ac", + "amount" : 10.00000000, + "confirmations" : 0 + } +] +{% endhighlight %} +
+ +Re-running the `listunspent` RPC with the argument "0" to also display +unconfirmed transactions shows that we have two UTXOs, both with the +same txid. The first UTXO shown is a change output that `sendtoaddress` +created using a new address from the key pool. The second UTXO shown is +the spend to the address we provided. If we had spent those satoshis to +someone else, that second transaction would not be displayed in our +list of UTXOs. + +~~~ +> bitcoin-cli -regtest setgenerate true 1 + +> unset NEW_ADDRESS +~~~ + +Create a new block to confirm the transaction above (takes less than a +second) and clear the shell variable. + +{% endautocrossref %} + + + + + + +#### Simple Raw Transaction + +{% autocrossref %} + +The raw transaction RPCs allow users to create custom transactions and +delay broadcasting those transactions. However, mistakes made in raw +transactions may not be detected by Bitcoin Core, and a number of raw +transaction users have permanently lost large numbers of satoshis, so +please be careful using raw transactions on mainnet. + +This subsection covers one of the simplest possible raw transactions. + +
+{% highlight bash %} +> bitcoin-cli -regtest listunspent +{% endhighlight %} +{% highlight json %} +[ + { + "txid" : "263c018582731ff54dc72c7d67e858c002ae298835501d\ + 80200f05753de0edf0", + "vout" : 0, + "address" : "muhtvdmsnbQEPFuEmxcChX58fGvXaaUoVt", + "scriptPubKey" : "76a9149ba386253ea698158b6d34802bb9b550\ + f5ce36dd88ac", + "amount" : 40.00000000, + "confirmations" : 1 + }, + { + "txid" : "263c018582731ff54dc72c7d67e858c002ae298835501d\ + 80200f05753de0edf0", + "vout" : 1, + "address" : "mvbnrCX3bg1cDRUu8pkecrvP6vQkSLDSou", + "account" : "", + "scriptPubKey" : "76a914a57414e5ffae9ef5074bacbe10a320bb\ + 2614e1f388ac", + "amount" : 10.00000000, + "confirmations" : 1 + }, + { + "txid" : "3f4fa19803dec4d6a84fae3821da7ac7577080ef754512\ + 94e71f9b20e0ab1e7b", + "vout" : 0, + "address" : "mwJTL1dZG8BAP6X7Be3CNNcuVKi7Qqt7Gk", + "scriptPubKey" : "210260a275cccf0f4b106220725be516adba27\ + 52db1bec8c5b7174c89c4c07891f88ac", + "amount" : 50.00000000, + "confirmations" : 101 + } +] +{% endhighlight %} +{% highlight bash %} + +> UTXO_TXID=3f4fa19803dec4d6a84fae3821da7ac7577080ef75451294e71f[...] +> UTXO_VOUT=0 +{% endhighlight %} +
+ +Re-rerun `listunspent`. We now have three UTXOs: the two transactions we +created before plus the coinbase transaction from block #2. We save the +txid and output index number (vout) of that coinbase UTXO to shell +variables. + +{% highlight bash %} +> bitcoin-cli -regtest getnewaddress +mz6KvC4aoUeo6wSxtiVQTo7FDwPnkp6URG + +> NEW_ADDRESS=mz6KvC4aoUeo6wSxtiVQTo7FDwPnkp6URG +{% endhighlight %} + +Get a new address to use in the raw transaction. + +{% highlight bash %} +## Outputs - inputs = transaction fee, so always double-check your math! +> bitcoin-cli -regtest createrawtransaction ''' + [ + { + "txid": "'$UTXO_TXID'", + "vout": '$UTXO_VOUT' + } + ] + ''' ''' + { + "'$NEW_ADDRESS'": 49.9999 + }''' +01000000017b1eabe0209b1fe794124575ef807057c77ada2138ae4fa8d6c4de\ +0398a14f3f0000000000ffffffff01f0ca052a010000001976a914cbc20a7664\ +f2f69e5355aa427045bc15e7c6c77288ac00000000 + +> RAW_TX=01000000017b1eabe0209b1fe794124575ef807057c77ada2138ae4[...] +{% endhighlight %} + +Using two arguments to the `createrawtransaction` RPC, we create a new +raw format transaction. The first argument (a JSON array) references +the txid of the coinbase transaction from block #2 and the index +number (0) of the output from that transaction we want to spend. The +second argument (a JSON object) creates the output with the address +(public key hash) and number of bitcoins we want to transfer. +We save the resulting raw format transaction to a shell variable. + +**Warning:** `createrawtransaction` does not automatically create change +outputs, so you can easily accidentally pay a large transaction fee. In +this example, our input had 50.0000 bitcoins and our output +(`$NEW_ADDRESS`) is being paid 49.9999 bitcoins, so the transaction will +include a fee of 0.0001 bitcoins. If we had paid `$NEW_ADDRESS` only 10 +bitcoins with no other changes to this transaction, the transaction fee +would be a whopping 40 bitcoins. See the Complex Raw Transaction +subsection below for how to create a transaction with multiple outputs so you +can send the change back to yourself. + + +
+{% highlight bash %} +> bitcoin-cli -regtest decoderawtransaction $RAW_TX +{% endhighlight %} +{% highlight json %} +{ + "txid" : "c80b343d2ce2b5d829c2de9854c7c8d423c0e33bda264c4013\ + 8d834aab4c0638", + "version" : 1, + "locktime" : 0, + "vin" : [ + { + "txid" : "3f4fa19803dec4d6a84fae3821da7ac7577080ef75\ + 451294e71f9b20e0ab1e7b", + "vout" : 0, + "scriptSig" : { + "asm" : "", + "hex" : "" + }, + "sequence" : 4294967295 + } + ], + "vout" : [ + { + "value" : 49.99990000, + "n" : 0, + "scriptPubKey" : { + "asm" : "OP_DUP OP_HASH160 cbc20a7664f2f69e5355a\ + a427045bc15e7c6c772 OP_EQUALVERIFY OP_CHECKSIG", + "hex" : "76a914cbc20a7664f2f69e5355aa427045bc15e\ + 7c6c77288ac", + "reqSigs" : 1, + "type" : "pubkeyhash", + "addresses" : [ + "mz6KvC4aoUeo6wSxtiVQTo7FDwPnkp6URG" + ] + } + } + ] +} +{% endhighlight %} +
+ +Use the `decoderawtransaction` RPC to see exactly what the transaction +we just created does. + +
+{% highlight bash %} +> bitcoin-cli -regtest signrawtransaction $RAW_TX +{% endhighlight %} +{% highlight json %} +{ + "hex" : "01000000017b1eabe0209b1fe794124575ef807057c77ada213\ + 8ae4fa8d6c4de0398a14f3f00000000494830450221008949f0\ + cb400094ad2b5eb399d59d01c14d73d8fe6e96df1a7150deb38\ + 8ab8935022079656090d7f6bac4c9a94e0aad311a4268e082a7\ + 25f8aeae0573fb12ff866a5f01ffffffff01f0ca052a0100000\ + 01976a914cbc20a7664f2f69e5355aa427045bc15e7c6c77288\ + ac00000000", + "complete" : true +} +{% endhighlight %} +{% highlight bash %} + +> SIGNED_RAW_TX=01000000017b1eabe0209b1fe794124575ef807057c77ada[...] +{% endhighlight %} +
+ +Use the `signrawtransaction` RPC to sign the transaction created by +`createrawtransaction` and save the returned "hex" raw format signed +transaction to a shell variable. + +Even though the transaction is now complete, the Bitcoin Core node we're +connected to doesn't know anything about the transaction, nor does any +other part of the network. We've created a spend, but we haven't +actually spent anything because we could simply unset the +`$SIGNED_RAW_TX` variable to eliminate the transaction. + +{% highlight bash %} +> bitcoin-cli -regtest sendrawtransaction $SIGNED_RAW_TX +c7736a0a0046d5a8cc61c8c3c2821d4d7517f5de2bc66a966011aaa79965ffba +{% endhighlight %} + +Send the signed transaction to the connected node using the +`sendrawtransaction` RPC. After accepting the transaction, the node +would usually then broadcast it to other peers, but we're not currently +connected to other peers because we started in regtest mode. + +~~~ +> bitcoin-cli -regtest setgenerate true 1 + +> unset UTXO_TXID UTXO_VOUT NEW_ADDRESS RAW_TX SIGNED_RAW_TX +~~~ + +Generate a block to confirm the transaction and clear our shell +variables. + +{% endautocrossref %} + + + + + +#### Complex Raw Transaction + +{% autocrossref %} + +In this example, we'll create a transaction with two inputs and two +outputs. We'll sign each of the inputs separately, as might happen if +the two inputs belonged to different people who agreed to create a +transaction together (such as a CoinJoin transaction). + +
+{% highlight bash %} +> bitcoin-cli -regtest listunspent +{% endhighlight %} +{% highlight json %} +[ + { + "txid" : "263c018582731ff54dc72c7d67e858c002ae298835501d\ + 80200f05753de0edf0", + "vout" : 0, + "address" : "muhtvdmsnbQEPFuEmxcChX58fGvXaaUoVt", + "scriptPubKey" : "76a9149ba386253ea698158b6d34802bb9b550\ + f5ce36dd88ac", + "amount" : 40.00000000, + "confirmations" : 2 + }, + { + "txid" : "263c018582731ff54dc72c7d67e858c002ae298835501d\ + 80200f05753de0edf0", + "vout" : 1, + "address" : "mvbnrCX3bg1cDRUu8pkecrvP6vQkSLDSou", + "account" : "", + "scriptPubKey" : "76a914a57414e5ffae9ef5074bacbe10a320bb\ + 2614e1f388ac", + "amount" : 10.00000000, + "confirmations" : 2 + }, + { + "txid" : "78203a8f6b529693759e1917a1b9f05670d036fbb12911\ + 0ed26be6a36de827f3", + "vout" : 0, + "address" : "n2KprMQm4z2vmZnPMENfbp2P1LLdAEFRjS", + "scriptPubKey" : "210229688a74abd0d5ad3b06ddff36fa9cd8ed\ + d181d97b9489a6adc40431fb56e1d8ac", + "amount" : 50.00000000, + "confirmations" : 101 + }, + { + "txid" : "c7736a0a0046d5a8cc61c8c3c2821d4d7517f5de2bc66a\ + 966011aaa79965ffba", + "vout" : 0, + "address" : "mz6KvC4aoUeo6wSxtiVQTo7FDwPnkp6URG", + "account" : "", + "scriptPubKey" : "76a914cbc20a7664f2f69e5355aa427045bc15\ + e7c6c77288ac", + "amount" : 49.99990000, + "confirmations" : 1 + } +] +{% endhighlight %} +{% highlight bash %} + +> UTXO1_TXID=78203a8f6b529693759e1917a1b9f05670d036fbb129110ed26[...] +> UTXO1_VOUT=0 +> UTXO1_ADDRESS=n2KprMQm4z2vmZnPMENfbp2P1LLdAEFRjS + +> UTXO2_TXID=263c018582731ff54dc72c7d67e858c002ae298835501d80200[...] +> UTXO2_VOUT=0 +> UTXO2_ADDRESS=muhtvdmsnbQEPFuEmxcChX58fGvXaaUoVt +{% endhighlight %} +
+ +For our two inputs, we select two UTXOs by placing the txid and output +index numbers (vouts) in shell variables. We also save the addresses +corresponding to the public keys (hashed or unhashed) used in those +transactions. We need the addresses so we can get the corresponding +private keys from our wallet. + +{% highlight bash %} +> bitcoin-cli -regtest dumpprivkey $UTXO1_ADDRESS +cSp57iWuu5APuzrPGyGc4PGUeCg23PjenZPBPoUs24HtJawccHPm + +> bitcoin-cli -regtest dumpprivkey $UTXO2_ADDRESS +cT26DX6Ctco7pxaUptJujRfbMS2PJvdqiSMaGaoSktHyon8kQUSg + +> UTXO1_PRIVATE_KEY=cSp57iWuu5APuzrPGyGc4PGUeCg23PjenZPBPoUs24Ht[...] + +> UTXO2_PRIVATE_KEY=cT26DX6Ctco7pxaUptJujRfbMS2PJvdqiSMaGaoSktHy[...] +{% endhighlight %} + +Use the `dumpprivkey` RPC to get the private keys corresponding to the +public keys used in the two UTXOs out inputs we will be spending. We need +the private keys so we can sign each of the inputs separately. + +{% highlight bash %} +> bitcoin-cli -regtest getnewaddress +n4puhBEeEWD2VvjdRC9kQuX2abKxSCMNqN +> bitcoin-cli -regtest getnewaddress +n4LWXU59yM5MzQev7Jx7VNeq1BqZ85ZbLj + +> NEW_ADDRESS1=n4puhBEeEWD2VvjdRC9kQuX2abKxSCMNqN +> NEW_ADDRESS2=n4LWXU59yM5MzQev7Jx7VNeq1BqZ85ZbLj +{% endhighlight %} + +For our two outputs, get two new addresses. + +{% highlight bash %} +## Outputs - inputs = transaction fee, so always double-check your math! +> bitcoin-cli -regtest createrawtransaction ''' + [ + { + "txid": "'$UTXO1_TXID'", + "vout": '$UTXO1_VOUT' + }, + { + "txid": "'$UTXO2_TXID'", + "vout": '$UTXO2_VOUT' + } + ] + ''' ''' + { + "'$NEW_ADDRESS1'": 79.9999, + "'$NEW_ADDRESS2'": 10 + }''' +0100000002f327e86da3e66bd20e1129b1fb36d07056f0b9a117199e75939652\ +6b8f3a20780000000000fffffffff0ede03d75050f20801d50358829ae02c058\ +e8677d2cc74df51f738285013c260000000000ffffffff02f028d6dc01000000\ +1976a914ffb035781c3c69e076d48b60c3d38592e7ce06a788ac00ca9a3b0000\ +00001976a914fa5139067622fd7e1e722a05c17c2bb7d5fd6df088ac00000000 + +> RAW_TX=0100000002f327e86da3e66bd20e1129b1fb36d07056f0b9a117199[...] +{% endhighlight %} + +Create the raw transaction using `createrawtransaction` much the same as +before, except now we have two inputs and two outputs. + + +
+{% highlight bash %} +> bitcoin-cli -regtest signrawtransaction $RAW_TX '[]' ''' + [ + "'$UTXO1_PRIVATE_KEY'" + ]''' +{% endhighlight %} +{% highlight json %} +{ + "hex" : "0100000002f327e86da3e66bd20e1129b1fb36d07056f0b9a11\ + 7199e759396526b8f3a20780000000049483045022100fce442\ + ec52aa2792efc27fd3ad0eaf7fa69f097fdcefab017ea56d179\ + 9b10b2102207a6ae3eb61e11ffaba0453f173d1792f1b7bb8e7\ + 422ea945101d68535c4b474801fffffffff0ede03d75050f208\ + 01d50358829ae02c058e8677d2cc74df51f738285013c260000\ + 000000ffffffff02f028d6dc010000001976a914ffb035781c3\ + c69e076d48b60c3d38592e7ce06a788ac00ca9a3b0000000019\ + 76a914fa5139067622fd7e1e722a05c17c2bb7d5fd6df088ac0\ + 0000000", + "complete" : false +} +{% endhighlight %} +{% highlight bash %} + +> PARTLY_SIGNED_RAW_TX=0100000002f327e86da3e66bd20e1129b1fb36d07[...] +{% endhighlight %} +
+ +Signing the raw transaction with `signrawtransaction` gets more +complicated as we now have three arguments: + +1. The unsigned raw transaction. + +2. An empty array. We don't do anything with this argument in this + operation, but some valid JSON must be provided to get access to the + later positional arguments. + +3. The private key we want to use to sign one of the inputs. + +The result is a raw transaction with only one input signed; the fact +that the transaction isn't fully signed is indicated by value of the +`complete` JSON field. We save the incomplete, partly-signed raw +transaction hex to a shell variable. + +
+{% highlight bash %} +> bitcoin-cli -regtest signrawtransaction $PARTLY_SIGNED_RAW_TX '[]' ''' + [ + "'$UTXO2_PRIVATE_KEY'" + ]''' +{% endhighlight %} +{% highlight json %} +{ + "hex" : "0100000002f327e86da3e66bd20e1129b1fb36d07056f0b9a11\ + 7199e759396526b8f3a20780000000049483045022100fce442\ + ec52aa2792efc27fd3ad0eaf7fa69f097fdcefab017ea56d179\ + 9b10b2102207a6ae3eb61e11ffaba0453f173d1792f1b7bb8e7\ + 422ea945101d68535c4b474801fffffffff0ede03d75050f208\ + 01d50358829ae02c058e8677d2cc74df51f738285013c260000\ + 00006b483045022100b77f935ff366a6f3c2fdeb83589c79026\ + 5d43b3d2cf5e5f0047da56c36de75f40220707ceda75d8dcf2c\ + caebc506f7293c3dcb910554560763d7659fb202f8ec324b012\ + 102240d7d3c7aad57b68aa0178f4c56f997d1bfab2ded3c2f94\ + 27686017c603a6d6ffffffff02f028d6dc010000001976a914f\ + fb035781c3c69e076d48b60c3d38592e7ce06a788ac00ca9a3b\ + 000000001976a914fa5139067622fd7e1e722a05c17c2bb7d5f\ + d6df088ac00000000", + "complete" : true +} +{% endhighlight %} +
+ +To sign the second input, we repeat the process we used to sign the +first input using the second private key. Now that both inputs are +signed, the `complete` result is *true*. + +{% highlight bash %} +> unset PARTLY_SIGNED_RAW_TX RAW_TX NEW_ADDRESS1 [...] +{% endhighlight %} + +Clean up the shell variables used. Unlike previous subsections, we're +not going to send this transaction to the connected node with +`sendrawtransaction`. This will allow us to illustrate in the Offline +Signing subsection below how to spend a transaction which is not yet in +the block chain or memory pool. + +{% endautocrossref %} + + + + + +#### Offline Signing + +{% autocrossref %} + +We will now spend the transaction created in the Complex Raw Transaction +subsection above without sending it to the local node first. This is the +same basic process used by wallet programs for offline +signing---which generally means signing a transaction without access +to the current UTXO set. + +Offline signing is safe. However, in this example we will also be +spending an output which is not part of the block chain because the +transaction containing it has never been broadcast. That can be unsafe: + +**Warning:** transactions which spend outputs from unconfirmed +transactions are vulnerable to transaction malleability. Be sure to read +about transaction malleability and adopt good practices before spending +unconfirmed transactions on mainnet. + +{% highlight bash %} +> OLD_SIGNED_RAW_TX=0100000002f327e86da3e66bd20e1129b1fb36d07056\ + f0b9a117199e759396526b8f3a20780000000049483045022100fce442\ + ec52aa2792efc27fd3ad0eaf7fa69f097fdcefab017ea56d1799b10b21\ + 02207a6ae3eb61e11ffaba0453f173d1792f1b7bb8e7422ea945101d68\ + 535c4b474801fffffffff0ede03d75050f20801d50358829ae02c058e8\ + 677d2cc74df51f738285013c26000000006b483045022100b77f935ff3\ + 66a6f3c2fdeb83589c790265d43b3d2cf5e5f0047da56c36de75f40220\ + 707ceda75d8dcf2ccaebc506f7293c3dcb910554560763d7659fb202f8\ + ec324b012102240d7d3c7aad57b68aa0178f4c56f997d1bfab2ded3c2f\ + 9427686017c603a6d6ffffffff02f028d6dc010000001976a914ffb035\ + 781c3c69e076d48b60c3d38592e7ce06a788ac00ca9a3b000000001976\ + a914fa5139067622fd7e1e722a05c17c2bb7d5fd6df088ac00000000 +{% endhighlight %} + +Put the previously signed (but not sent) transaction into a shell +variable. + +
+{% highlight bash %} +> bitcoin-cli -regtest decoderawtransaction $OLD_SIGNED_RAW_TX +{% endhighlight %} +{% highlight json %} +{ + "txid" : "682cad881df69cb9df8f0c996ce96ecad758357ded2da03bad\ + 40cf18ffbb8e09", + "version" : 1, + "locktime" : 0, + "vin" : [ + { + "txid" : "78203a8f6b529693759e1917a1b9f05670d036fbb1\ + 29110ed26be6a36de827f3", + "vout" : 0, + "scriptSig" : { + "asm" : "3045022100fce442ec52aa2792efc27fd3ad0ea\ + f7fa69f097fdcefab017ea56d1799b10b210220\ + 7a6ae3eb61e11ffaba0453f173d1792f1b7bb8e\ + 7422ea945101d68535c4b474801", + "hex" : "483045022100FCE442ec52aa2792efc27fd3ad0\ + eaf7fa69f097fdcefab017ea56d1799b10b2102\ + 207a6ae3eb61e11ffaba0453f173d1792f1b7bb\ + 8e7422ea945101d68535c4b474801" + }, + "sequence" : 4294967295 + }, + { + "txid" : "263c018582731ff54dc72c7d67e858c002ae298835\ + 501d80200f05753de0edf0", + "vout" : 0, + "scriptSig" : { + "asm" : "3045022100b77f935ff366a6f3c2fdeb83589c7\ + 90265d43b3d2cf5e5f0047da56c36de75f40220\ + 707ceda75d8dcf2ccaebc506f7293c3dcb91055\ + 4560763d7659fb202f8ec324b01 + 02240d7d3c7aad57b68aa0178f4c56f997d1bfa\ + b2ded3c2f9427686017c603a6d6", + "hex" : "483045022100b77f935ff366a6f3c2fdeb83589\ + c790265d43b3d2cf5e5f0047da56c36de75f402\ + 20707ceda75d8dcf2ccaebc506f7293c3dcb910\ + 554560763d7659fb202f8ec324b012102240d7d\ + 3c7aad57b68aa0178f4c56f997d1bfab2ded3c2\ + f9427686017c603a6d6" + }, + "sequence" : 4294967295 + } + ], + "vout" : [ + { + "value" : 79.99990000, + "n" : 0, + "scriptPubKey" : { + "asm" : "OP_DUP OP_HASH160 ffb035781c3c69e076d48\ + b60c3d38592e7ce06a7 OP_EQUALVERIFY OP_CHECKSIG", + "hex" : "76a914ffb035781c3c69e076d48b60c3d38592e\ + 7ce06a788ac", + "reqSigs" : 1, + "type" : "pubkeyhash", + "addresses" : [ + "n4puhBEeEWD2VvjdRC9kQuX2abKxSCMNqN" + ] + } + }, + { + "value" : 10.00000000, + "n" : 1, + "scriptPubKey" : { + "asm" : "OP_DUP OP_HASH160 fa5139067622fd7e1e722\ + a05c17c2bb7d5fd6df0 OP_EQUALVERIFY OP_CHECKSIG", + "hex" : "76a914fa5139067622fd7e1e722a05c17c2bb7d\ + 5fd6df088ac", + "reqSigs" : 1, + "type" : "pubkeyhash", + "addresses" : [ + "n4LWXU59yM5MzQev7Jx7VNeq1BqZ85ZbLj" + ] + } + } + ] +} +{% endhighlight %} +{% highlight bash %} + +> UTXO_TXID=682cad881df69cb9df8f0c996ce96ecad758357ded2da03bad40[...] +> UTXO_VOUT=1 +> UTXO_OUTPUT_SCRIPT=76a914fa5139067622fd7e1e722a05c17c2bb7d5fd6[...] +{% endhighlight %} +
+ + +Decode the signed raw transaction so we can get its txid. Also, choose a +specific one of its UTXOs to spend and save that UTXO's output index number +(vout) and hex output script (scriptPubKey) into shell variables. + +{% highlight bash %} +> bitcoin-cli -regtest getnewaddress +mfdCHEFL2tW9eEUpizk7XLZJcnFM4hrp78 + +> NEW_ADDRESS=mfdCHEFL2tW9eEUpizk7XLZJcnFM4hrp78 +{% endhighlight %} + +Get a new address to spend the satoshis to. + +{% highlight bash %} +## Outputs - inputs = transaction fee, so always double-check your math! +> bitcoin-cli -regtest createrawtransaction ''' + [ + { + "txid": "'$UTXO_TXID'", + "vout": '$UTXO_VOUT' + } + ] + ''' ''' + { + "'$NEW_ADDRESS'": 9.9999 + }''' +0100000001098ebbff18cf40ad3ba02ded7d3558d7ca6ee96c990c8fdfb99cf6\ +1d88ad2c680100000000ffffffff01f0a29a3b000000001976a914012e2ba6a0\ +51c033b03d712ca2ea00a35eac1e7988ac00000000 + +> RAW_TX=0100000001098ebbff18cf40ad3ba02ded7d3558d7ca6ee96c990c8[...] +{% endhighlight %} + +Create the raw transaction the same way we've done in the previous +subsections. + +
+{% highlight bash %} + > bitcoin-cli -regtest signrawtransaction $RAW_TX +{% endhighlight %} +{% highlight json %} + { + "hex" : "0100000001098ebbff18cf40ad3ba02ded7d3558d7ca6ee\ + 96c990c8fdfb99cf61d88ad2c680100000000ffffffff01\ + f0a29a3b000000001976a914012e2ba6a051c033b03d712\ + ca2ea00a35eac1e7988ac00000000", + "complete" : false + } +{% endhighlight %} +
+ +Attempt to sign the raw transaction without any special arguments, the +way we successfully signed the the raw transaction in the Simple Raw +Transaction subsection. If you've read the [Transaction section][transaction] of +the guide, you may know why the call fails and leaves the raw +transaction hex unchanged. + +![Old Transaction Data Required To Be Signed](/img/dev/en-signing-output-to-spend.svg) + +As illustrated above, the data that gets signed includes the txid and +vout from the previous transaction. That information is included in the +`createrawtransaction` raw transaction. But the data that gets signed +also includes the output script from the previous transaction, even +though it doesn't appear in either the unsigned or signed transaction. + +In the other raw transaction subsections above, the previous output was +part of the UTXO set known to the wallet, so the wallet was able to use +the txid and output index number to find the previous output script and +insert it automatically. + +In this case, you're spending an output which is unknown to the wallet, +so it can't automatically insert the previous output script. + +
+{% highlight bash %} +> bitcoin-cli -regtest signrawtransaction $RAW_TX ''' + [ + { + "txid": "'$UTXO_TXID'", + "vout": '$UTXO_VOUT', + "scriptPubKey": "'$UTXO_OUTPUT_SCRIPT'" + } + ]''' +{% endhighlight %} +{% highlight json %} +{ + "hex" : "0100000001098ebbff18cf40ad3ba02ded7d3558d7ca6ee96c9\ + 90c8fdfb99cf61d88ad2c68010000006b483045022100c3f92f\ + b74bfa687d76ebe75a654510bb291b8aab6f89ded4fe26777c2\ + eb233ad02207f779ce2a181cc4055cb0362aba7fd7a6f72d5db\ + b9bd863f4faaf47d8d6c4b500121028e4e62d25760709806131\ + b014e2572f7590e70be01f0ef16bfbd51ea5f389d4dffffffff\ + 01f0a29a3b000000001976a914012e2ba6a051c033b03d712ca\ + 2ea00a35eac1e7988ac00000000", + "complete" : true +} +{% endhighlight %} +{% highlight bash %} + +> SIGNED_RAW_TX=0100000001098ebbff18cf40ad3ba02ded7d3558d7ca6ee9[...] +{% endhighlight %} +
+ +Successfully sign the transaction by providing the previous output +script and other required input data. + +This specific operation is typically what offline signing wallets do. +The online wallet creates the raw transaction and gets the previous +output scripts for all the inputs. The user brings this information to +the offline wallet. After displaying the transaction details to the +user, the offline wallet signs the transaction as we did above. The +user takes the signed transaction back to the online wallet, which +broadcasts it. + +
+{% highlight bash %} +> bitcoin-cli -regtest sendrawtransaction $SIGNED_RAW_TX +{% endhighlight %} +{% highlight json %} +error: {"code":-22,"message":"TX rejected"} +{% endhighlight %} +
+ +Attempt to broadcast the second transaction before we've broadcast the +first transaction. The node rejects this attempt because the second +transaction spends an output which is not a UTXO the node knows about. + +{% highlight bash %} +> bitcoin-cli -regtest sendrawtransaction $OLD_SIGNED_RAW_TX +682cad881df69cb9df8f0c996ce96ecad758357ded2da03bad40cf18ffbb8e09 +> bitcoin-cli -regtest sendrawtransaction $SIGNED_RAW_TX +67d53afa1a8167ca093d30be7fb9dcb8a64a5fdecacec9d93396330c47052c57 +{% endhighlight %} + +Broadcast the first transaction, which succeeds, and then broadcast the +second transaction---which also now succeeds because the node now sees +the UTXO. + +
+{% highlight bash %} +> bitcoin-cli -regtest getrawmempool +{% endhighlight %} +{% highlight json %} +[ + "67d53afa1a8167ca093d30be7fb9dcb8a64a5fdecacec9d93396330c47052c57", + "682cad881df69cb9df8f0c996ce96ecad758357ded2da03bad40cf18ffbb8e09" +] +{% endhighlight %} +
+ +We have once again not generated an additional block, so the transactions +above have not yet become part of the regtest block chain. However, they +are part of the local node's memory pool. + +{% highlight bash %} +> unset OLD_SIGNED_RAW_TX SIGNED_RAW_TX RAW_TX [...] +{% endhighlight %} + +Remove old shell variables. + +{% endautocrossref %} + + + + + + +#### P2SH Multisig + +{% autocrossref %} + +In this subsection, we will create a P2SH multisig address, spend +satoshis to it, and then spend those satoshis from it to another +address. + +Creating a multisig address is easy. Multisig outputs have two +parameters, the *minimum* number of signatures required (*m*) and the +*number* of public keys to use to validate those signatures. This is +called m-of-n, and in this case we'll be using 2-of-3. + +{% highlight bash %} + > bitcoin-cli -regtest getnewaddress + mhAXF4Eq7iRyvbYk1mpDVBiGdLP3YbY6Dm + > bitcoin-cli -regtest getnewaddress + moaCrnRfP5zzyhW8k65f6Rf2z5QpvJzSKe + > bitcoin-cli -regtest getnewaddress + mk2QpYatsKicvFVuTAQLBryyccRXMUaGHP + + > NEW_ADDRESS1=mhAXF4Eq7iRyvbYk1mpDVBiGdLP3YbY6Dm + > NEW_ADDRESS2=moaCrnRfP5zzyhW8k65f6Rf2z5QpvJzSKe + > NEW_ADDRESS3=mk2QpYatsKicvFVuTAQLBryyccRXMUaGHP +{% endhighlight %} + +Generate three new P2PKH addresses. P2PKH addresses cannot be used with +the multisig redeemScript created below. (Hashing each public key is +unnecessary anyway---all the public keys are protected by a hash when +the redeemScript is hashed.) However, Bitcoin Core uses addresses as a +way to reference the underlying full (unhashed) public keys it knows +about, so we get the three new addresses above in order to use their +public keys. + +[Recall from the Guide][address] that the hashed public keys used in addresses +obfuscate the full public key, so you cannot give an address to another +person or device as part of creating a typical multisig output or P2SH multisig +redeemScript. You must give them a full public key. + +
+{% highlight bash %} +> bitcoin-cli -regtest validateaddress $NEW_ADDRESS3 +{% endhighlight %} +{% highlight json %} +{ + "isvalid" : true, + "address" : "mk2QpYatsKicvFVuTAQLBryyccRXMUaGHP", + "ismine" : true, + "isscript" : false, + "pubkey" : "029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a\ + 95c37e148f78c77255", + "iscompressed" : true, + "account" : "" +} +{% endhighlight %} +{% highlight bash %} + +> NEW_ADDRESS3_PUBLIC_KEY=029e03a901b85534ff1e92c43c74431f7ce720[...] +{% endhighlight %} +
+ +Use the `validateaddress` RPC to display the full (unhashed) public key +for one of the addresses. This is the information which will +actually be included in the multisig redeemScript. This is also the +information you would give another person or device as part of creating +a multisig output or P2SH multisig redeemScript. + +We save the address returned to a shell variable. + +
+{% highlight bash %} +> bitcoin-cli -regtest createmultisig 2 ''' + [ + "'$NEW_ADDRESS1'", + "'$NEW_ADDRESS2'", + "'$NEW_ADDRESS3_PUBLIC_KEY'" + ]''' +{% endhighlight %} +{% highlight json %} +{ + "address" : "2N7NaqSKYQUeM8VNgBy8D9xQQbiA8yiJayk", + "redeemScript" : "522103310188e911026cf18c3ce274e0ebb5f95b00\ + 7f230d8cb7d09879d96dbeab1aff210243930746e6ed6552e03359db521b\ + 088134652905bd2d1541fa9124303a41e95621029e03a901b85534ff1e92\ + c43c74431f7ce72046060fcf7a95c37e148f78c7725553ae" +} +{% endhighlight %} +{% highlight bash %} + +> P2SH_ADDRESS=2N7NaqSKYQUeM8VNgBy8D9xQQbiA8yiJayk +> P2SH_REDEEM_SCRIPT=522103310188e911026cf18c3ce274e0ebb5f95b007[...] +{% endhighlight %} +
+ +Use the `createmultisig` RPC with two arguments, the number (*n*) of +signatures required and a list of addresses or public keys. Because +P2PKH addresses can't be used in the multisig redeemScript created by this +RPC, the only addresses which can be provided are those belonging to a +public key in the wallet. In this case, we provide two addresses and +one public key---all of which will be converted to public keys in the +redeemScript. + +The P2SH address is returned along with the redeemScript which must be +provided when we spend satoshis sent to the P2SH address. + +**Warning:** You must not lose the redeemScript, especially if you +don't have a record of which public keys you used to create the P2SH +multisig address. You need the redeemScript to spend any bitcoins sent +to the P2SH address. If you lose the redeemScript, you can recreate it +by running the same command above, with the public keys listed in the +same order. However, if you lose both the redeemScript and even one of +the public keys, you will never be able to spend satoshis sent to that +P2SH address. + +Neither the address nor the redeemScript are stored in the wallet when +you use `createmultisig`. To store them in the wallet, use the +`addmultisigaddress` RPC instead. If you add an address to the wallet, +you should also make a new backup. + +{% highlight bash %} +> bitcoin-cli -regtest sendtoaddress $P2SH_ADDRESS 10.00 +7278d7d030f042ebe633732b512bcb31fff14a697675a1fe1884db139876e175 + +> UTXO_TXID=7278d7d030f042ebe633732b512bcb31fff14a697675a1fe1884[...] +{% endhighlight %} + +Paying the P2SH multisig address with Bitcoin Core is as simple as +paying a more common P2PKH address. Here we use the same command (but +different variable) we used in the Simple Spending subsection. As +before, this command automatically selects an UTXO, creates a change +output to a new one of our P2PKH addresses if necessary, and pays a +transaction fee if necessary. + +We save that txid to a shell variable as the txid of the UTXO we plan to spend next. + +
+{% highlight bash %} +> bitcoin-cli -regtest getrawtransaction $UTXO_TXID 1 +{% endhighlight %} +{% highlight json %} +{ + "hex" : "0100000001f0ede03d75050f20801d50358829ae02c058e8677\ + d2cc74df51f738285013c26010000006a47304402203c375959\ + 2bf608ab79c01596c4a417f3110dd6eb776270337e575cdafc6\ + 99af20220317ef140d596cc255a4067df8125db7f349ad94521\ + 2e9264a87fa8d777151937012102a92913b70f9fb15a7ea5c42\ + df44637f0de26e2dad97d6d54957690b94cf2cd05ffffffff01\ + 00ca9a3b0000000017a9149af61346ce0aa2dffcf697352b4b7\ + 04c84dcbaff8700000000", + "txid" : "7278d7d030f042ebe633732b512bcb31fff14a697675a1fe18\ + 84db139876e175", + "version" : 1, + "locktime" : 0, + "vin" : [ + { + "txid" : "263c018582731ff54dc72c7d67e858c002ae298835\ + 501d80200f05753de0edf0", + "vout" : 1, + "scriptSig" : { + "asm" : "304402203c3759592bf608ab79c01596c4a417f\ + 3110dd6eb776270337e575cdafc699af2022031\ + 7ef140d596cc255a4067df8125db7f349ad9452\ + 12e9264a87fa8d77715193701 + 02a92913b70f9fb15a7ea5c42df44637f0de26e\ + 2dad97d6d54957690b94cf2cd05", + "hex" : "47304402203c3759592bf608ab79c01596c4a41\ + 7f3110dd6eb776270337e575cdafc699af20220\ + 317ef140d596cc255a4067df8125db7f349ad94\ + 5212e9264a87fa8d777151937012102a92913b7\ + 0f9fb15a7ea5c42df44637f0de26e2dad97d6d5\ + 4957690b94cf2cd05" + }, + "sequence" : 4294967295 + } + ], + "vout" : [ + { + "value" : 10.00000000, + "n" : 0, + "scriptPubKey" : { + "asm" : "OP_HASH160 9af61346ce0aa2dffcf697352b4b\ + 704c84dcbaff OP_EQUAL", + "hex" : "a9149af61346ce0aa2dffcf697352b4b704c84d\ + cbaff87", + "reqSigs" : 1, + "type" : "scripthash", + "addresses" : [ + "2N7NaqSKYQUeM8VNgBy8D9xQQbiA8yiJayk" + ] + } + } + ] +} +{% endhighlight %} +{% highlight bash %} + +> UTXO_VOUT=0 +> UTXO_OUTPUT_SCRIPT=a9149af61346ce0aa2dffcf697352b4b704c84dcbaff87 +{% endhighlight %} +
+ +We use the `getrawtransaction` RPC with the optional second argument +(*true*) to get the decoded transaction we just created with +`spendtoaddress`. We choose one of the outputs to be our UTXO and get +its output index number (vout) and output script (scriptPubKey). + +{% highlight bash %} +> bitcoin-cli -regtest getnewaddress +mxCNLtKxzgjg8yyNHeuFSXvxCvagkWdfGU + +> NEW_ADDRESS4=mxCNLtKxzgjg8yyNHeuFSXvxCvagkWdfGU +{% endhighlight %} + +We generate a new P2PKH address to use in the output we're about to +create. + +{% highlight bash %} +## Outputs - inputs = transaction fee, so always double-check your math! +> bitcoin-cli -regtest createrawtransaction ''' + [ + { + "txid": "'$UTXO_TXID'", + "vout": '$UTXO_VOUT' + } + ] + ''' ''' + { + "'$NEW_ADDRESS4'": 9.998 + }''' + +010000000175e1769813db8418fea17576694af1ff31cb2b512b7333e6eb42f0\ +30d0d778720000000000ffffffff01c0bc973b000000001976a914b6f64f5bf3\ +e38f25ead28817df7929c06fe847ee88ac00000000 + +> RAW_TX=010000000175e1769813db8418fea17576694af1ff31cb2b512b733[...] +{% endhighlight %} + +We generate the raw transaction the same way we did in the Simple Raw +Transaction subsection. + +{% highlight bash %} +> bitcoin-cli -regtest dumpprivkey $NEW_ADDRESS1 +cVinshabsALz5Wg4tGDiBuqEGq4i6WCKWXRQdM8RFxLbALvNSHw7 +> bitcoin-cli -regtest dumpprivkey $NEW_ADDRESS3 +cNmbnwwGzEghMMe1vBwH34DFHShEj5bcXD1QpFRPHgG9Mj1xc5hq + +> NEW_ADDRESS1_PRIVATE_KEY=cVinshabsALz5Wg4tGDiBuqEGq4i6WCKWXRQd[...] +> NEW_ADDRESS3_PRIVATE_KEY=cNmbnwwGzEghMMe1vBwH34DFHShEj5bcXD1Qp[...] +{% endhighlight %} + +We get the private keys for two of the public keys we used to create the +transaction, the same way we got private keys in the Complex Raw +Transaction subsection. Recall that we created a 2-of-3 multisig script, +so signatures from two private keys are needed. + +
+{% highlight bash %} +> bitcoin-cli -regtest signrawtransaction $RAW_TX ''' + [ + { + "txid": "'$UTXO_TXID'", + "vout": '$UTXO_VOUT', + "scriptPubKey": "'$UTXO_OUTPUT_SCRIPT'", + "redeemScript": "'$P2SH_REDEEM_SCRIPT'" + } + ] + ''' ''' + [ + "'$NEW_ADDRESS1_PRIVATE_KEY'" + ]''' +{% endhighlight %} +{% highlight json %} +{ + "hex" : "010000000175e1769813db8418fea17576694af1ff31cb2b512\ + b7333e6eb42f030d0d7787200000000b5004830450221008d5e\ + c57d362ff6ef6602e4e756ef1bdeee12bd5c5c72697ef1455b3\ + 79c90531002202ef3ea04dfbeda043395e5bc701e4878c15baa\ + b9c6ba5808eb3d04c91f641a0c014c69522103310188e911026\ + cf18c3ce274e0ebb5f95b007f230d8cb7d09879d96dbeab1aff\ + 210243930746e6ed6552e03359db521b088134652905bd2d154\ + 1fa9124303a41e95621029e03a901b85534ff1e92c43c74431f\ + 7ce72046060fcf7a95c37e148f78c7725553aeffffffff01c0b\ + c973b000000001976a914b6f64f5bf3e38f25ead28817df7929\ + c06fe847ee88ac00000000", + "complete" : false +} +{% endhighlight %} +{% highlight bash %} + +> PARTLY_SIGNED_RAW_TX=010000000175e1769813db8418fea17576694af1f[...] +{% endhighlight %} +
+ +We make the first signature. The input argument (JSON object) takes the +additional redeemScript parameter so that it can append the redeemScript +to the scriptSig after the two signatures. + +
+{% highlight bash %} +> bitcoin-cli -regtest signrawtransaction $PARTLY_SIGNED_RAW_TX ''' + [ + { + "txid": "'$UTXO_TXID'", + "vout": '$UTXO_VOUT', + "scriptPubKey": "'$UTXO_OUTPUT_SCRIPT'", + "redeemScript": "'$P2SH_REDEEM_SCRIPT'" + } + ] + ''' ''' + [ + "'$NEW_ADDRESS3_PRIVATE_KEY'" + ]''' +{% endhighlight %} +{% highlight json %} +{ + "hex" : "010000000175e1769813db8418fea17576694af1ff31cb2b512\ + b7333e6eb42f030d0d7787200000000fdfd0000483045022100\ + 8d5ec57d362ff6ef6602e4e756ef1bdeee12bd5c5c72697ef14\ + 55b379c90531002202ef3ea04dfbeda043395e5bc701e4878c1\ + 5baab9c6ba5808eb3d04c91f641a0c0147304402200bd8c62b9\ + 38e02094021e481b149fd5e366a212cb823187149799a68cfa7\ + 652002203b52120c5cf25ceab5f0a6b5cdb8eca0fd2f386316c\ + 9721177b75ddca82a4ae8014c69522103310188e911026cf18c\ + 3ce274e0ebb5f95b007f230d8cb7d09879d96dbeab1aff21024\ + 3930746e6ed6552e03359db521b088134652905bd2d1541fa91\ + 24303a41e95621029e03a901b85534ff1e92c43c74431f7ce72\ + 046060fcf7a95c37e148f78c7725553aeffffffff01c0bc973b\ + 000000001976a914b6f64f5bf3e38f25ead28817df7929c06fe\ + 847ee88ac00000000", + "complete" : true +} +{% endhighlight %} +{% highlight bash %} + +> SIGNED_RAW_TX=010000000175e1769813db8418fea17576694af1ff31cb2b[...] +{% endhighlight %} +
+ +The `signrawtransaction` call used here is nearly identical to the one +used above. The only difference is the private key used. Now that the +two required signatures have been provided, the transaction is marked as +complete. + +{% highlight bash %} +> bitcoin-cli -regtest sendrawtransaction $SIGNED_RAW_TX +430a4cee3a55efb04cbb8718713cab18dea7f2521039aa660ffb5aae14ff3f50 +{% endhighlight %} + +We send the transaction spending the P2SH multisig output to the local +node, which accepts it. + +{% endautocrossref %} diff --git a/_includes/fragment_reviews_needed.md b/_includes/fragment_reviews_needed.md new file mode 100644 index 00000000..d6c1f774 --- /dev/null +++ b/_includes/fragment_reviews_needed.md @@ -0,0 +1,7 @@ + +
+BETA: This documentation has been written recently and still needs more reviews to ensure all content is covered correctly and accurately; if you find a mistake, please report an issue on GitHub. Click here to close this disclaimer. +X +
+ + diff --git a/_includes/guide_payment_processing.md b/_includes/guide_payment_processing.md index affea0f7..76799350 100644 --- a/_includes/guide_payment_processing.md +++ b/_includes/guide_payment_processing.md @@ -150,8 +150,6 @@ or [millibits][]{:#term-millibits}{:.term} (mBTC). Choosing between BTC and mBTC but other software also lets its users select denomination amounts from some or all of the following options: -{% endautocrossref %} - | Bitcoins | Unit (Abbreviation) | |-------------|---------------------| | 1.0 | bitcoin (BTC) | @@ -160,20 +158,8 @@ some or all of the following options: | 0.000001 | microbit (uBTC) | | 0.00000001 | [satoshi][]{:#term-satoshi}{:.term} | -{% autocrossref %} - -Because of the widespread popularity of BTC and mBTC, it may be more -useful to specify the amount in both denominations when the text is -meant to be copied and pasted. For example: - {% endautocrossref %} -~~~ -Pay: mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN -Amount: 100 BTC (100000 mBTC) -You must pay by: 2014-04-01 at 23:00 UTC -~~~ - #### bitcoin: URI {% autocrossref %} @@ -191,38 +177,23 @@ bitcoin:mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN?amount=100 {% autocrossref %} -Only the address is required, and if it is the only thing specified, -wallets will pre-fill a payment request with it and let the spender enter -an amount. +Only the address is required, and if it is the only thing +specified, wallets will pre-fill a payment request with it and let +the spender enter an amount. The amount specified is always in +decimal bitcoins (BTC). -The amount specified is always in decimal bitcoins (BTC), although requests -only for whole bitcoins (as in the example above), may omit the decimal -point. The amount field must not contain any commas. Fractional bitcoins -may be specified with or without a leading zero; for example, either of -the URIs below requesting one millibit are valid: - -{% endautocrossref %} - -~~~ -bitcoin:mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN?amount=.001 -bitcoin:mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN?amount=0.001 -~~~ - -{% autocrossref %} - -Two other parameters are widely supported. The [`label`][label]{:#term-label}{:.term} parameter is -generally used to provide wallet software with the recipient's name. The -[`message`][message]{:#term-message}{:.term} parameter is generally used to describe the payment request to -the spender. Both the label and the message are commonly stored by the -spender's wallet software---but they are never added to the actual -transaction, so other Bitcoin users cannot see them. Both the label and -the message must be [URI encoded][]. +Two other parameters are widely supported. The +[`label`][label]{:#term-label}{:.term} parameter is generally used to +provide wallet software with the recipient's name. The +[`message`][message]{:#term-message}{:.term} parameter is generally used +to describe the payment request to the spender. Both the label and the +message are commonly stored by the spender's wallet software---but they +are never added to the actual transaction, so other Bitcoin users cannot +see them. Both the label and the message must be [URI encoded][]. All four parameters used together, with appropriate URI encoding, can be seen in the line-wrapped example below. -{% endautocrossref %} - ~~~ bitcoin:mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN\ ?amount=0.10\ @@ -230,32 +201,6 @@ bitcoin:mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN\ &message=Order+of+flowers+%26+chocolates ~~~ -{% autocrossref %} - -The URI above could be encoded in HTML as follows, providing compatibility -with wallet software which can't accept URI links and allowing you to -specify an expiration date to the spender. - -{% endautocrossref %} - -~~~ -Order flowers & chocolate using Bitcoin -(Pay 0.10 BTC [100 mBTC] to mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN by 2014-04-01 at 23:00 UTC) -~~~ - -Which produces: - -> Order flowers & chocolates using Bitcoin (Pay 0.10 BTC [100 mBTC] to mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN by 2014-04-01 at 23:00 UTC) - -{% autocrossref %} - -Some payment processors use Javascript to display countdown timers -indicating the number of minutes and seconds until the offer expires. - The URI scheme can be extended, as will be seen in the payment protocol section below, with both new optional and required parameters. As of this writing, the only widely-used parameter besides the four described above @@ -276,27 +221,14 @@ images, or in videos. Most mobile Bitcoin wallet apps, and some desktop wallets, support scanning QR codes to pre-fill their payment screens. The figure below shows the same `bitcoin:` URI code encoded as four -different [Bitcoin QR codes][URI QR code]{:#term-uri-qr-code}{:.term} at different error correction levels (described -below the image). The QR code can include the `label` and `message` +different [Bitcoin QR codes][URI QR code]{:#term-uri-qr-code}{:.term} at four +different error correction levels. The QR code can include the `label` and `message` parameters---and any other optional parameters---but they were omitted here to keep the QR code small and easy to scan with unsteady or low-resolution mobile cameras. ![Bitcoin QR Codes](/img/dev/en-qr-code.svg) -QR encoders offer four possible levels of error correction: - -1. Low: corrects up to 7% damage - -2. Medium: corrects up to 15% damage but results in approximately 8% - larger images over low-level damage correction. - -3. Quartile: corrects corrects up to 25% damage but results in - approximately 20% larger images over low-level damage correction. - -4. High: corrects up to 30% damage but results in approximately 26% - larger images over low-level damage correction. - The error correction is combined with a checksum to ensure the Bitcoin QR code cannot be successfully decoded with data missing or accidentally altered, so your applications should choose the appropriate level of error @@ -332,662 +264,143 @@ as "www.bitcoin.org". To request payment using the payment protocol, you use an extended (but backwards-compatible) `bitcoin:` URI. For example: -{% endautocrossref %} - ~~~ bitcoin:mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN\ ?amount=0.10\ &label=Example+Merchant\ &message=Order+of+flowers+%26+chocolates\ -&r=http://example.com/pay.php/invoice%3Dda39a3ee +&r=https://example.com/pay/mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN ~~~ -{% autocrossref %} - None of the parameters provided above, except `r`, are required for the payment protocol---but your applications may include them for backwards compatibility with wallet programs which don't yet handle the payment protocol. The [`r`][r]{:#term-r-parameter}{:.term} parameter tells payment-protocol-aware wallet programs to ignore -the other parameters and fetch a PaymentRequest from the URL provided. If the -request will be signed, which is recommended but not required, it can be -fetched from an HTTP server---although fetching it from an HTTPS server -would still be preferable. - +the other parameters and fetch a PaymentRequest from the URL provided. The browser, QR code reader, or other program processing the URI opens -the spender's Bitcoin wallet program on the URI. If the wallet program is -aware of the payment protocol, it accesses the URL specified in the `r` -parameter, which should provide it with a serialized PaymentRequest -served with the [MIME][] type `application/bitcoin-paymentrequest`. - -**Resource:** Gavin Andresen's [Payment Request Generator][] generates -custom example URIs and payment requests for use with testnet. - -{% endautocrossref %} - -##### PaymentRequest & PaymentDetails - -{% autocrossref %} - -The [PaymentRequest][]{:#term-paymentrequest}{:.term} is created with data structures built using -Google's Protocol Buffers. BIP70 describes these data -structures in the non-sequential way they're defined in the payment -request protocol buffer code, but the text below will describe them in -a more linear order using a simple (but functional) Python CGI -program. (For brevity and clarity, many normal CGI best practices are -not used in this program.) - -The full sequence of events is illustrated below, starting with the -spender clicking a `bitcoin:` URI or scanning a `bitcoin:` QR code. +the spender's Bitcoin wallet program on the URI. ![BIP70 Payment Protocol](/img/dev/en-payment-protocol.svg) -For the script to use the protocol buffer, you will need a copy of -Google's Protocol Buffer compiler (`protoc`), which is available in most -modern Linux package managers and [directly from Google.][protobuf] Non-Google -protocol buffer compilers are available for a variety of -programming languages. You will also need a copy of the PaymentRequest -[Protocol Buffer description][core paymentrequest.proto] from the Bitcoin Core source code. - -###### Initialization Code - -With the Python code generated by `protoc`, we can start our simple -CGI program. - -{% endautocrossref %} - -{% highlight python %} -#!/usr/bin/env python - -## This is the code generated by protoc --python_out=./ paymentrequest.proto -from paymentrequest_pb2 import * - -## Load some functions -from time import time -from sys import stdout -from OpenSSL.crypto import FILETYPE_PEM, load_privatekey, sign - -## Copy three of the classes created by protoc into objects we can use -details = PaymentDetails() -request = PaymentRequest() -x509 = X509Certificates() -{% endhighlight %} - -{% autocrossref %} - -The startup code above is quite simple, requiring nothing but the epoch -(Unix date) time function, the standard out file descriptor, a few -functions from the OpenSSL library, and the data structures and -functions created by `protoc`. - -{% endautocrossref %} - -###### Configuration Code - -{% autocrossref %} - -Next, we'll set configuration settings which will typically only change -when the receiver wants to do something differently. The code pushes a -few settings into the `request` (PaymentRequest) and `details` -(PaymentDetails) objects. When we serialize them, -[PaymentDetails][]{:#term-paymentdetails}{:.term} will be contained -within the PaymentRequest. - -{% endautocrossref %} - -{% highlight python %} -## SSL Signature method -request.pki_type = "x509+sha256" ## Default: none - -## Mainnet or Testnet? -details.network = "test" ## Default: main - -## Postback URL -details.payment_url = "https://example.com/pay.py" - -## PaymentDetails version number -request.payment_details_version = 1 ## Default: 1 - -## Certificate chain -x509.certificate.append(file("/etc/apache2/example.com-cert.der", "r").read()) -#x509.certificate.append(file("/some/intermediate/cert.der", "r").read()) - -## Load private SSL key into memory for signing later -priv_key = "/etc/apache2/example.com-key.pem" -pw = "test" ## Key password -private_key = load_privatekey(FILETYPE_PEM, file(priv_key, "r").read(), pw) -{% endhighlight %} - -Each line is described below. - -{% highlight python %} -request.pki_type = "x509+sha256" ## Default: none -{% endhighlight %} - -{% autocrossref %} - -`pki_type`: (optional) tell the receiving wallet program what [Public-Key -Infrastructure][PKI]{:#term-pki}{:.term} (PKI) type you're using to -cryptographically sign your PaymentRequest so that it can't be modified -by a man-in-the-middle attack. - -If you don't want to sign the PaymentRequest, you can choose a -[`pki_type`][pp pki type]{:#term-pp-pki-type}{:.term} of `none` -(the default). - -If you do choose the sign the PaymentRequest, you currently have two -options defined by BIP70: `x509+sha1` and `x509+sha256`. Both options -use the X.509 certificate system, the same system used for HTTP Secure -(HTTPS). To use either option, you will need a certificate signed by a -certificate authority or one of their intermediaries. (A self-signed -certificate will not work.) - -Each wallet program may choose which certificate authorities to trust, -but it's likely that they'll trust whatever certificate authorities their -operating system trusts. If the wallet program doesn't have a full -operating system, as might be the case for small hardware wallets, BIP70 -suggests they use the [Mozilla Root Certificate Store][mozrootstore]. In -general, if a certificate works in your web browser when you connect to -your webserver, it will work for your PaymentRequests. - -{% endautocrossref %} - -{% highlight python %} -details.network = "test" ## Default: main -{% endhighlight %} - -{% autocrossref %} - -`network`: (optional) tell the spender's wallet program what Bitcoin network you're -using; BIP70 defines "main" for mainnet (actual payments) and "test" for -testnet (like mainnet, but fake satoshis are used). If the wallet -program doesn't run on the network you indicate, it will reject the -PaymentRequest. - -{% endautocrossref %} - -{% highlight python %} -details.payment_url = "https://example.com/pay.py" -{% endhighlight %} - -{% autocrossref %} - -`payment_url`: (required) tell the spender's wallet program where to send the Payment -message (described later). This can be a static URL, as in this example, -or a variable URL such as `https://example.com/pay.py?invoice=123.` -It should usually be an HTTPS address to prevent man-in-the-middle -attacks from modifying the message. - -{% endautocrossref %} - -{% highlight python %} -request.payment_details_version = 1 ## Default: 1 -{% endhighlight %} - -{% autocrossref %} - -`payment_details_version`: (optional) tell the spender's wallet program what version of the -PaymentDetails you're using. As of this writing, the only version is -version 1. - -{% endautocrossref %} - -{% highlight python %} -## This is the pubkey/certificate corresponding to the private SSL key -## that we'll use to sign: -x509.certificate.append(file("/etc/apache2/example.com-cert.der", "r").read()) -{% endhighlight %} - -{% autocrossref %} - -`x509certificates`: (required for signed PaymentRequests) you must -provide the public SSL key/certificate corresponding to the private SSL -key you'll use to sign the PaymentRequest. The certificate must be in -ASN.1/DER format. - -{% endautocrossref %} - -{% highlight python %} -## If the pubkey/cert above didn't have the signature of a root -## certificate authority, we'd then append the intermediate certificate -## which signed it: -#x509.certificate.append(file("/some/intermediate/cert.der", "r").read()) -{% endhighlight %} - -{% autocrossref %} - -You must also provide any intermediate certificates necessary to link -your certificate to the root certificate of a certificate authority -trusted by the spender's software, such as a certificate from the -Mozilla root store. - -The certificates must be provided in a specific order---the same order -used by Apache's `SSLCertificateFile` directive and other server -software. The figure below shows the [certificate chain][]{:#term-certificate-chain}{:.term} of the -www.bitcoin.org X.509 certificate and how each certificate (except the -root certificate) would be loaded into the [X509Certificates][]{:#term-x509certificates}{:.term} protocol -buffer message. - -![X509Certificates Loading Order](/img/dev/en-cert-order.svg) - -To be specific, the first certificate provided must be the -X.509 certificate corresponding to the private SSL key which will make the -signature, called the [leaf certificate][]{:#term-leaf-certificate}{:.term}. Any [intermediate -certificates][intermediate certificate]{:#term-intermediate-certificate}{:.term} necessary to link that signed public SSL -key to the [root -certificate][]{:#term-root-certificate}{:.term} (the certificate authority) are attached separately, with each -certificate in DER format bearing the signature of the certificate that -follows it all the way to (but not including) the root certificate. - -{% endautocrossref %} - -{% highlight python %} -priv_key = "/etc/apache2/example.com-key.pem" -pw = "test" ## Key password -private_key = load_privatekey(FILETYPE_PEM, file(priv_key, "r").read(), pw) -{% endhighlight %} - -{% autocrossref %} - -(Required for signed PaymentRequests) you will need a private SSL key in -a format your SSL library supports (DER format is not required). In this -program, we'll load it from a PEM file. (Embedding your passphrase in -your CGI code, as done here, is obviously a bad idea in real life.) - -The private SSL key will not be transmitted with your request. We're -only loading it into memory here so we can use it to sign the request -later. - -{% endautocrossref %} - -###### Code Variables - -{% autocrossref %} - -Now let's look at the variables your CGI program will likely set for -each payment. - -{% endautocrossref %} - -{% highlight python %} -## Amount of the request -amount = 10000000 ## In satoshis - -## P2PKH pubkey hash -pubkey_hash = "2b14950b8d31620c6cc923c5408a701b1ec0a020" -## P2PKH output script entered as hex and converted to binary -# OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG -# 76 a9 14 88 ac -hex_script = "76" + "a9" + "14" + pubkey_hash + "88" + "ac" -serialized_script = hex_script.decode("hex") - -## Load amount and script into PaymentDetails -details.outputs.add(amount = amount, script = serialized_script) - -## Memo to display to the spender -details.memo = "Flowers & chocolates" - -## Data which should be returned to you with the payment -details.merchant_data = "Invoice #123" -{% endhighlight python %} - -Each line is described below. - -{% highlight python %} -amount = 10000000 ## In satoshis (=100 mBTC) -{% endhighlight %} - -{% autocrossref %} - -`amount`: (optional) the [amount][pp amount]{:#term-pp-amount}{:.term} you want the spender to pay. You'll probably get - this value from your shopping cart application or fiat-to-BTC exchange - rate conversion tool. If you leave the amount blank, the wallet - program will prompt the spender how much to pay (which can be useful - for donations). - -{% endautocrossref %} - -{% highlight python %} -pubkey_hash = "2b14950b8d31620c6cc923c5408a701b1ec0a020" -# OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG -# 76 a9 14 88 ac -hex_script = "76" + "a9" + "14" + pubkey_hash + "88" + "ac" -serialized_script = hex_script.decode("hex") -{% endhighlight %} - -{% autocrossref %} - -`script`: (required) You must specify the output script you want the spender to -pay---any valid script is acceptable. In this example, we'll request -payment to a P2PKH output script. - -First we get a pubkey hash. The hash above is the hash form of the -address used in the URI examples throughout this section, -mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN. - -Next, we plug that hash into the standard P2PKH output script using hex, -as illustrated by the code comments. - -Finally, we convert the output script from hex into its serialized form. - -{% endautocrossref %} - -{% highlight python %} -details.outputs.add(amount = amount, script = serialized_script) -{% endhighlight %} - -{% autocrossref %} - -`outputs`: (required) add the output script and (optional) amount to the -PaymentDetails outputs array. - -It's possible to specify multiple [`scripts`][pp -script]{:#term-pp-script}{:.term} and `amounts` as part of a merge -avoidance strategy, described later in the [Merge Avoidance -subsection][]. However, effective merge avoidance is not possible under -the base BIP70 rules in which the spender pays each `script` the exact -amount specified by its paired `amount`. If the amounts are omitted from -all `amount`/`script` pairs, the spender will be prompted to choose an -amount to pay. - -{% endautocrossref %} - -{% highlight python %} -details.memo = "Flowers & chocolates" -{% endhighlight %} - -{% autocrossref %} - -`memo`: (optional) add a memo which will be displayed to the spender as -plain UTF-8 text. Embedded HTML or other markup will not be processed. - -{% endautocrossref %} - -{% highlight python %} -details.merchant_data = "Invoice #123" -{% endhighlight %} - -{% autocrossref %} - -`merchant_data`: (optional) add arbitrary data which should be sent back to the -receiver when the invoice is paid. You can use this to track your -invoices, although you can more reliably track payments by generating a -unique address for each payment and then tracking when it gets paid. - -The [`memo`][pp memo]{:#term-pp-memo}{:.term} field and the [`merchant_data`][pp merchant data]{:#term-pp-merchant-data}{:.term} field can be arbitrarily long, -but if you make them too long, you'll run into the 50,000 byte limit on -the entire PaymentRequest, which includes the often several kilobytes -given over to storing the certificate chain. As will be described in a -later subsection, the `memo` field can be used by the spender after -payment as part of a cryptographically-proven receipt. - -{% endautocrossref %} - -###### Derivable Data - -{% autocrossref %} - -Next, let's look at some information your CGI program can -automatically derive. - -{% endautocrossref %} - -{% highlight python %} -## Request creation time -details.time = int(time()) ## Current epoch (Unix) time - -## Request expiration time -details.expires = int(time()) + 60 * 10 ## 10 minutes from now - -## PaymentDetails is complete; serialize it and store it in PaymentRequest -request.serialized_payment_details = details.SerializeToString() - -## Serialized certificate chain -request.pki_data = x509.SerializeToString() - -## Initialize signature field so we can sign the full PaymentRequest -request.signature = "" - -## Sign PaymentRequest -request.signature = sign(private_key, request.SerializeToString(), "sha256") -{% endhighlight %} - -Each line is described below. - -{% highlight python %} -details.time = int(time()) ## Current epoch (Unix) time -{% endhighlight %} - -{% autocrossref %} - -`time`: (required) PaymentRequests must indicate when they were created -in number of seconds elapsed since 1970-01-01T00:00 UTC (Unix -epoch time format). - -{% endautocrossref %} - -{% highlight python %} -details.expires = int(time()) + 60 * 10 ## 10 minutes from now -{% endhighlight %} - -{% autocrossref %} - -`expires`: (optional) the PaymentRequest may also set an [`expires`][pp -expires]{:#term-pp-expires}{:.term} time after -which they're no longer valid. You probably want to give receivers -the ability to configure the expiration time delta; here we used the -reasonable choice of 10 minutes. If this request is tied to an order -total based on a fiat-to-satoshis exchange rate, you probably want to -base this on a delta from the time you got the exchange rate. - -{% endautocrossref %} - -{% highlight python %} -request.serialized_payment_details = details.SerializeToString() -{% endhighlight %} - -{% autocrossref %} - -`serialized_payment_details`: (required) we've now set everything we need to create the -PaymentDetails, so we'll use the SerializeToString function from the -protocol buffer code to store the PaymentDetails in the appropriate -field of the PaymentRequest. - -{% endautocrossref %} - -{% highlight python %} -request.pki_data = x509.SerializeToString() -{% endhighlight %} - -{% autocrossref %} - -`pki_data`: (required for signed PaymentRequests) serialize the certificate chain -[PKI data][pp PKI data]{:#term-pp-pki-data}{:.term} and store it in the -PaymentRequest - -{% endautocrossref %} - -{% highlight python %} -request.signature = "" -{% endhighlight %} - -{% autocrossref %} - -We've filled out everything in the PaymentRequest except the signature, -but before we sign it, we have to initialize the signature field by -setting it to a zero-byte placeholder. - -{% endautocrossref %} - -{% highlight python %} -request.signature = sign(private_key, request.SerializeToString(), "sha256") -{% endhighlight %} - -{% autocrossref %} - -`signature`: (required for signed PaymentRequests) now we -make the [signature][ssl signature]{:#term-ssl-signature}{:.term} by -signing the completed and serialized PaymentRequest. We'll use the -private key we stored in memory in the configuration section and the -same hashing formula we specified in `pki_type` (sha256 in this case) - -{% endautocrossref %} - -###### Output Code - -{% autocrossref %} - -Now that we have PaymentRequest all filled out, we can serialize it and -send it along with the HTTP headers, as shown in the code below. - -{% endautocrossref %} - -{% highlight python %} -print "Content-Type: application/bitcoin-paymentrequest" -print "Content-Transfer-Encoding: binary" -print "" -{% endhighlight %} - -{% autocrossref %} - -(Required) BIP71 defines the content types for PaymentRequests, -Payments, and PaymentACKs. - -{% endautocrossref %} - -{% highlight python %} -file.write(stdout, request.SerializeToString()) -{% endhighlight %} - -{% autocrossref %} - -`request`: (required) now, to finish, we just dump out the serialized -PaymentRequest (which contains the serialized PaymentDetails). The -serialized data is in binary, so we can't use Python's print() -because it would add an extraneous newline. - -The following screenshot shows how the authenticated PaymentDetails -created by the program above appears in the GUI from Bitcoin Core 0.9. +The Payment Protocol is described in depth in BIP70, BIP71, and BIP72. +An example CGI program and description of all the parameters which can +be used in the Payment Protocol is provided in the Developer Examples +[Payment Protocol][devex payment protocol] subsection. In this +subsection, we will briefly describe in story format how the Payment +Protocol is typically used. + +Charlie, the client, is shopping on a website run by Bob, the +businessman. Charlie adds a few items to his shopping cart and clicks +the "Checkout With Bitcoin" button. + +Bob's server automatically adds the following information to its +invoice database: + +* The details of Charlie's order, including items ordered and + shipping address. + +* An order total in satoshis, perhaps created by converting prices in + fiat to prices in satoshis. + +* An expiration time when that total will no longer be acceptable. + +* An output script to which Charlie should send payment. Typically this + will be a P2PKH or P2SH output script containing a unique (never + before used) public key. + +After adding all that information to the database, Bob's server displays +a `bitcoin:` URI for Charlie to click to pay. + +Charlie clicks on the `bitcoin:` URI in his browser. His browser's URI +handler sends the URI to his wallet program. The wallet is aware of the +Payment Protocol, so it parses the `r` parameter and sends an HTTP GET +to that URL looking for a PaymentRequest message. + +The PaymentRequest message returned may include private information, such as Charlie's +mailing address, but the wallet must be able to access it without using prior +authentication, such as HTTP cookies, so a publicly-accessible HTTPS URL +with a guess-resistant part is typically used. The +unique public key created for the payment request can be used to create +a unique identifier. This is why, in the example URI above, the PaymentRequest +URL contains the P2PKH address: +`https://example.com/pay/mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN` + +After receiving the HTTP GET to the URL above, the +PaymentRequest-generating CGI program on Bob's webserver takes the +unique identifier from the URL and looks up the corresponding details in +the database. It then creates a PaymentDetails message with the +following information: + +* The amount of the order in satoshis and the output script to be paid. + +* A memo containing the list of items ordered, so Charlie knows what + he's paying for. It may also include Charlie's mailing address so he can + double-check it. + +* The time the PaymentDetails message was created plus the time + it expires. + +* A URL to which Charlie's wallet should send its completed transaction. + +That PaymentDetails message is put inside a PaymentRequest message. +The payment request lets Bob's server sign the entire Request with the +server's X.509 SSL certificate. (The Payment Protocol has been designed +to allow other signing methods in the future.) Bob's server sends the +payment request to Charlie's wallet in the reply to the HTTP GET. ![Bitcoin Core Showing Validated Payment Request](/img/dev/en-btcc-payment-request.png) -{% endautocrossref %} +Charlie's wallet receives the PaymentRequest message, checks its signature, and +then displays the details from the PaymentDetails message to Charlie. Charlie +agrees to pay, so the wallet constructs a payment to the output script +Bob's server provided. Unlike a traditional Bitcoin payment, Charlie's +wallet doesn't necessarily automatically broadcast this payment to the +network. Instead, the wallet constructs a Payment message and sends it to +the URL provided in the PaymentDetails message as an HTTP POST. Among +other things, the Payment message contains: -##### Payment +* The signed transaction in which Charlie pays Bob. -{% autocrossref %} +* An optional memo Charlie can send to Bob. (There's no guarantee that + Bob will read it.) -If the spender declines to pay, the wallet program will not send any -further messages to the receiver's server unless the spender clicks -another URI pointing to that server. If the spender does decide to pay, -the wallet program will create at least one transaction paying each of -the outputs in the PaymentDetails section. The wallet may broadcast -the transaction or transactions, as Bitcoin Core 0.9 does, but it -doesn't need to. +* A refund address (output script) which Bob can pay if he needs to + return some or all of Charlie's satoshis. -Whether or not it broadcasts the transaction or transactions, the wallet -program composes a reply to the PaymentRequest; the reply is called the -Payment. [Payment][pp payment]{:#term-pp-payment}{:.term} contains four fields: +Bob's server receives the Payment message, verifies the transaction pays +the requested amount to the address provided, and then broadcasts the +transaction to the network. It also replies to the HTTP POSTed Payment +message with a PaymentACK message, which includes an optional memo +from Bob's server thanking Charlie for his patronage and providing other +information about the order, such as the expected arrival date. -* `merchant_data`: (optional) an exact copy of the - `merchant_data` from the PaymentDetails. This is - optional in the case that the PaymentDetails doesn't provide - `merchant_data`. Receivers should be aware that malicious spenders can - modify the merchant data before sending it back, so receivers may wish to - cryptographically sign it before giving it to the spender and then - validate it before relying on it. +Charlie's wallet sees the PaymentACK and tells Charlie that the payment +has been sent. The PaymentACK doesn't mean that Bob has verified +Charlie's payment---see the Verifying Payment subsection below---but it does mean +that Charlie can go do something else while the transaction gets confirmed. +After Bob's server verifies from the block chain that Charlie's +transaction has been suitably confirmed, it authorizes shipping +Charlie's order. -* [`transactions`][pp transactions]{:#term-pp-transactions}{:.term}: (required) one or more signed transactions which pay the outputs - specified in the PaymentDetails. +In the case of a dispute, Charlie can generate a cryptographically-proven +[receipt][]{:#term-receipt}{:.term} out of the various signed or +otherwise-proven information. - +* The PaymentDetails message signed by Bob's webserver proves Charlie + received an invoice to pay a specified output script for a specified + number of satoshis for goods specified in the memo field. -* [`refund_to`][pp refund to]{:#term-pp-refund-to}{:.term}: (required) one or more output scripts to which the - receiver can send a partial or complete refund. As of this writing, a - proposal is gaining traction to expire refund output scripts after a - certain amount of time (not defined yet) so spenders don't need to - worry about receiving refunds to addresses they no longer monitor. +* The Bitcoin block chain can prove that the output script specified by + Bob was paid the specified number of satoshis. -* `memo`: (optional) a plain UTF-8 text memo sent to the receiver. It - should not contain HTML or any other markup. Spenders should not depend - on receivers reading their memos. - -The Payment is sent to the [`payment_url`][pp payment -url]{:#term-pp-payment-url}{:.term} provided in the PaymentDetails. -The URL should be a HTTPS address to prevent a man-in-the-middle attack -from modifying the spender's `refund_to` output scripts. When sending the -Payment, the wallet program must set the following HTTP client headers: - -{% endautocrossref %} - -~~~ -Content-Type: application/bitcoin-payment -Accept: application/bitcoin-paymentack -~~~ - -##### PaymentACK -{% autocrossref %} - -The receiver's CGI program at the `payment_url` receives the Payment message and -decodes it using its Protocol Buffers code. The `transactions` are -checked to see if they pay the output scripts the receiver requested in -PaymentDetails and are then broadcast to the network (unless the network -already has them). - -The CGI program checks the `merchant_data` parameter if necessary and issues -a [PaymentACK][]{:#term-paymentack}{:.term} (acknowledgment) with the following HTTP headers: - -{% endautocrossref %} - -~~~ -Content-Type: application/bitcoin-paymentack -Content-Transfer-Encoding: binary -~~~ - -{% autocrossref %} - -Then it sends another Protocol-Buffers-encoded message with one or two -fields: - -* `payment`: (required) A copy of the the entire Payment message (in - serialized form) which is being acknowledged. - -* `memo`: (optional) A plain UTF-8 text memo displayed to the spender - informing them about the status of their payment. It should not - contain HTML or any other markup. Receivers should not depend on - spenders reading their memos. - -The PaymentACK does not mean that the payment is final; it just means -that everything seems to be correct. The payment is final once the -payment transactions are block-chain confirmed to the receiver's -satisfaction. - -However, the spender's wallet program should indicate to the spender that -the payment was accepted for processing so the spender can direct his or -her attention elsewhere. - -{% endautocrossref %} - -##### Receipts - -{% autocrossref %} - -Unlike PaymentRequest, PaymentDetails, [Payment][pp payment]{:.auto-link}, and PaymentACK, there is -no specific [receipt][]{:#term-receipt}{:.term} object. However, a cryptographically-verifiable -receipt can be derived from a signed PaymentDetails and one or more confirmed -transactions. - -A signed PaymentDetails indicates what output scripts should be paid -(`script`), how much they should be paid (`amount`), and by when -(`expires`). The Bitcoin block chain indicates whether those outputs -were paid the requested amount and can provide a rough idea of when the -transactions were generated. Together, this information provides -verifiable proof that the spender paid somebody with the -receiver's private SSL key. +If a refund needs to be issued, Bob's server can safely pay the +refund-to output script provided by Charlie. (Note: a proposal has been +discussed to give refund-to addresses an implicit expiration date so +users and software don't need to worry about payments being sent to +addresses which are no longer monitored.) See the Refunds section below +for more details. {% endautocrossref %} diff --git a/_includes/guide_wallets.md b/_includes/guide_wallets.md index 49da269e..74de211d 100644 --- a/_includes/guide_wallets.md +++ b/_includes/guide_wallets.md @@ -225,7 +225,7 @@ design these minimalist wallets: * Pre-populate a database with a number of public keys or addresses, and then distribute on request an output script or address using one of the database entries. To [avoid key reuse][devguide avoiding key - resuse], webservers should keep track + reuse], webservers should keep track of used keys and never run out of public keys. This can be made easier by using parent public keys as suggested in the next method. diff --git a/_includes/references.md b/_includes/references.md index 19122917..db42342f 100644 --- a/_includes/references.md +++ b/_includes/references.md @@ -17,7 +17,7 @@ [broadcast]: /en/developer-guide#transaction-broadcasting "Sending transactions or blocks to all other peers on the Bitcoin network (compare to privately transmitting to a single peer or partner" [broadcasts]: /en/developer-guide#transaction-broadcasting "Sending transactions or blocks to all other peers on the Bitcoin network (compare to privately transmitting to a single peer or partner" [broadcasting]: /en/developer-guide#transaction-broadcasting "Sending transactions or blocks to all other peers on the Bitcoin network (compare to privately transmitting to a single peer or partner)" -[certificate chain]: /en/developer-guide#term-certificate-chain "A chain of certificates connecting a individual's leaf certificate to the certificate authority's root certificate" +[certificate chain]: /en/developer-examples#term-certificate-chain "A chain of certificates connecting a individual's leaf certificate to the certificate authority's root certificate" [chain code]: /en/developer-guide#term-chain-code "In HD wallets, 256 bits of entropy added to the master public and private keys to help them generate secure child keys; the chain code is usually derived from a seed along with the master private key" [change address]: /en/developer-guide#term-change-output "An output used by a spender to send back to himself some of the satoshis from the inputs" [change output]: /en/developer-guide#term-change-output "An output used by a spender to send back to himself some of the satoshis from the inputs" @@ -45,11 +45,11 @@ [high-priority transactions]: /en/developer-guide#term-high-priority-transactions "Transactions which don't pay a transaction fee; only transactions spending long-idle outputs are eligible" [input]: /en/developer-guide#term-input "The input to a transaction linking to the output of a previous transaction which permits spending of satoshis" [inputs]: /en/developer-guide#term-input "The input to a transaction linking to the output of a previous transaction which permits spending of satoshis" -[intermediate certificate]: /en/developer-guide#term-intermediate-certificate "A intermediate certificate authority certificate which helps connect a leaf (receiver) certificate to a root certificate authority" +[intermediate certificate]: /en/developer-examples#term-intermediate-certificate "A intermediate certificate authority certificate which helps connect a leaf (receiver) certificate to a root certificate authority" [key index]: /en/developer-guide#term-key-index "An index number used in the HD wallet formula to generate child keys from a parent key" [key pair]: /en/developer-guide#term-key-pair "A private key and its derived public key" [label]: /en/developer-guide#term-label "The label parameter of a bitcoin: URI which provides the spender with the receiver's name (unauthenticated)" -[leaf certificate]: /en/developer-guide#term-leaf-certificate "The end-node in a certificate chain; in the payment protocol, it is the certificate belonging to the receiver of satoshis" +[leaf certificate]: /en/developer-examples#term-leaf-certificate "The end-node in a certificate chain; in the payment protocol, it is the certificate belonging to the receiver of satoshis" [locktime]: /en/developer-guide#term-locktime "Part of a transaction which indicates the earliest time or earliest block when that transaction can be added to the block chain" [long-term fork]: /en/developer-guide#term-long-term-fork "When a series of blocks have corresponding block heights, indicating a possibly serious problem" [mainnet]: /en/developer-guide#term-mainnet "The Bitcoin main network used to transfer satoshis (compare to testnet, the test network)" @@ -90,29 +90,24 @@ [parent private key]: /en/developer-guide#term-parent-private-key "A private key which has created child private keys" [parent public key]: /en/developer-guide#term-parent-public-key "A public key corresponding to a parent private key which has child private keys" [payment protocol]: /en/developer-guide#term-payment-protocol "The protocol defined in BIP70 which lets spenders get signed payment details from receivers" -[PaymentACK]: /en/developer-guide#term-paymentack "The PaymentACK of the payment protocol which allows the receiver to indicate to the spender that the payment is being processed" -[PaymentDetails]: /en/developer-guide#term-paymentdetails "The PaymentDetails of the payment protocol which allows the receiver to specify the payment details to the spender" -[PaymentRequest]: /en/developer-guide#term-paymentrequest "The PaymentRequest of the payment protocol which contains and allows signing of the PaymentDetails" -[PaymentRequests]: /en/developer-guide#term-paymentrequest "The PaymentRequest of the payment protocol which contains and allows signing of the PaymentDetails" +[PaymentDetails]: /en/developer-examples#term-paymentdetails "The PaymentDetails of the payment protocol which allows the receiver to specify the payment details to the spender" +[PaymentRequest]: /en/developer-examples#term-paymentrequest "The PaymentRequest of the payment protocol which contains and allows signing of the PaymentDetails" +[PaymentRequests]: /en/developer-examples#term-paymentrequest "The PaymentRequest of the payment protocol which contains and allows signing of the PaymentDetails" [peer]: /en/developer-guide#term-peer "Peer on the P2P network who receives and broadcasts transactions and blocks" [peers]: /en/developer-guide#term-peer "Peers on the P2P network who receive and broadcast transactions and blocks" -[PKI]: /en/developer-guide#term-pki "Public Key Infrastructure; usually meant to indicate the X.509 certificate system used for HTTP Secure (https)." +[PKI]: /en/developer-examples#term-pki "Public Key Infrastructure; usually meant to indicate the X.509 certificate system used for HTTP Secure (https)." [point function]: /en/developer-guide#term-point-function "The ECDSA function used to create a public key from a private key" [private key]: /en/developer-guide#term-private-key "The private portion of a keypair which can create signatures which other people can verify using the public key" [private keys]: /en/developer-guide#term-private-key "The private portion of a keypair which can create signatures which other people can verify using the public key" [pubkey hash]: /en/developer-guide#term-pubkey-hash "The hash of a public key which can be included in a P2PKH output" [public key]: /en/developer-guide#term-public-key "The public portion of a keypair which can be safely distributed to other people so they can verify a signature created with the corresponding private key" -[pp amount]: /en/developer-guide#term-pp-amount "Part of the Output part of the PaymentDetails part of a payment protocol where receivers can specify the amount of satoshis they want paid to a particular output script" -[pp expires]: /en/developer-guide#term-pp-expires "The expires field of a PaymentDetails where the receiver tells the spender when the PaymentDetails expires" -[pp memo]: /en/developer-guide#term-pp-memo "The memo fields of PaymentDetails, Payment, and PaymentACK which allow spenders and receivers to send each other memos" -[pp merchant data]: /en/developer-guide#term-pp-merchant-data "The merchant_data part of PaymentDetails and Payment which allows the receiver to send arbitrary data to the spender in PaymentDetails and receive it back in Payments" -[pp Payment]: /en/developer-guide#term-pp-payment "The Payment message of the PaymentProtocol which allows the spender to send payment details to the receiver" -[pp PKI data]: /en/developer-guide#term-pp-pki-data "The pki_data field of a PaymentRequest which provides details such as certificates necessary to validate the request" -[pp pki type]: /en/developer-guide#term-pp-pki-type "The PKI field of a PaymentRequest which tells spenders how to validate this request as being from a specific recipient" -[pp refund to]: /en/developer-guide#term-pp-refund-to "The refund_to field of a Payment where the spender tells the receiver what outputs to send refunds to" -[pp script]: /en/developer-guide#term-pp-script "The script field of a PaymentDetails where the receiver tells the spender what output scripts to pay" -[pp transactions]: /en/developer-guide#term-pp-transactions "The transactions field of a Payment where the spender provides copies of signed transactions to the receiver" -[pp payment url]: /en/developer-guide#term-pp-payment-url "The payment_url of the PaymentDetails which allows the receiver to specify where the sender should post payment" +[pp amount]: /en/developer-examples#term-pp-amount "Part of the Output part of the PaymentDetails part of a payment protocol where receivers can specify the amount of satoshis they want paid to a particular output script" +[pp expires]: /en/developer-examples#term-pp-expires "The expires field of a PaymentDetails where the receiver tells the spender when the PaymentDetails expires" +[pp memo]: /en/developer-examples#term-pp-memo "The memo fields of PaymentDetails, Payment, and PaymentACK which allow spenders and receivers to send each other memos" +[pp merchant data]: /en/developer-examples#term-pp-merchant-data "The merchant_data part of PaymentDetails and Payment which allows the receiver to send arbitrary data to the spender in PaymentDetails and receive it back in Payments" +[pp PKI data]: /en/developer-examples#term-pp-pki-data "The pki_data field of a PaymentRequest which provides details such as certificates necessary to validate the request" +[pp pki type]: /en/developer-examples#term-pp-pki-type "The PKI field of a PaymentRequest which tells spenders how to validate this request as being from a specific recipient" +[pp script]: /en/developer-examples#term-pp-script "The script field of a PaymentDetails where the receiver tells the spender what output scripts to pay" [proof of work]: /en/developer-guide#term-proof-of-work "Proof that computationally-difficult work was performed which helps secure blocks against modification, protecting transaction history" [Pubkey]: /en/developer-guide#term-pubkey "A standard output script which specifies the full public key to match a signature; used in coinbase transactions" [r]: /en/developer-guide#term-r-parameter "The payment request parameter in a bitcoin: URI" @@ -121,7 +116,7 @@ [recurrent rebilling]: /en/developer-guide#rebilling-recurring-payments "Billing a spender on a regular schedule" [redeemScript]: /en/developer-guide#term-redeemscript "A script created by the recipient, hashed, and given to the spender for use in a P2SH output" [refund]: /en/developer-guide#issuing-refunds "A transaction which refunds some or all satoshis received in a previous transaction" -[root certificate]: /en/developer-guide#term-root-certificate "A certificate belonging to a certificate authority (CA)" +[root certificate]: /en/developer-examples#term-root-certificate "A certificate belonging to a certificate authority (CA)" [root seed]: /en/developer-guide#term-root-seed "A potentially-short value used as a seed to generate a master private key and master chain code for an HD wallet" [satoshi]: /en/developer-guide#term-satoshi "The smallest unit of Bitcoin value; 0.00000001 bitcoins. Also used generically for any value of bitcoins" [satoshis]: /en/developer-guide#term-satoshi "The smallest unit of Bitcoin value; 0.00000001 bitcoins. Also used generically for any value of bitcoins" @@ -140,7 +135,7 @@ [signature]: /en/developer-guide#term-signature "The result of combining a private key and some data in an ECDSA signature operation which allows anyone with the corresponding public key to verify the signature" [signature hash]: /en/developer-guide#term-signature-hash "A byte appended onto signatures generated in Bitcoin which allows the signer to specify what data was signed, allowing modification of the unsigned data" [spv]: /en/developer-guide#simplified-payment-verification-spv "A method for verifying particular transactions were included in blocks without downloading the entire contents of the block chain" -[ssl signature]: /en/developer-guide#term-ssl-signature "Signatures created and recognized by major SSL implementations such as OpenSSL" +[ssl signature]: /en/developer-examples#term-ssl-signature "Signatures created and recognized by major SSL implementations such as OpenSSL" [stack]: /en/developer-guide#term-stack "An evaluation stack used in Bitcoin's script language" [standard script]: /en/developer-guide#standard-transactions "An output script which matches the isStandard() patterns specified in Bitcoin Core---or a transaction containing only standard outputs. Only standard transactions are mined or broadcast by peers running the default Bitcoin Core software" [target]: /en/developer-guide#term-target "The threshold below which a block header hash must be in order for the block to be added to the block chain" @@ -163,13 +158,15 @@ [wallet]: /en/developer-guide#wallets "Software which stores private keys to allow users to spend and receive satoshis" [Wallet Import Format]: /en/developer-guide#term-wallet-import-format "A private key specially formatted to allow easy import into a wallet" [wallets]: /en/developer-guide#wallets "Software which stores private keys to allow users to spend and receive satoshis" -[X509Certificates]: /en/developer-guide#term-x509certificates +[X509Certificates]: /en/developer-examples#term-x509certificates [BFGMiner]: https://github.com/luke-jr/bfgminer [BIP21]: https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki [BIP32]: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki [BIP39]: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki [BIP70]: https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki +[BIP71]: https://github.com/bitcoin/bips/blob/master/bip-0071.mediawiki +[BIP72]: https://github.com/bitcoin/bips/blob/master/bip-0072.mediawiki [bitcoin-documentation mailing list]: https://groups.google.com/forum/#!forum/bitcoin-documentation [bitcoinpdf]: https://bitcoin.org/bitcoin.pdf [block170]: http://blockexplorer.com/block/00000000d1145790a8694403d4063f323d499e655c83426834d4ce2f8dd4a2ee @@ -180,6 +177,8 @@ [core paymentrequest.proto]: https://github.com/bitcoin/bitcoin/blob/master/src/qt/paymentrequest.proto [core script.h]: https://github.com/bitcoin/bitcoin/blob/master/src/script.h [DER]: https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One +[devex payment protocol]: /en/developer-examples#payment-protocol +[devguide]: /en/developer-guide [devguide avoiding key reuse]: /en/developer-guide#avoiding-key-reuse [devguide payment processing]: /en/developer-guide#payment-processing [devguide wallets]: /en/developer-guide#wallets diff --git a/_less/ie.css b/_less/ie.css index f10974cb..b7337f71 100644 --- a/_less/ie.css +++ b/_less/ie.css @@ -198,7 +198,6 @@ body{ .docreference a{ zoom:1; display:inline; - width:200px; } .downloadbox{ diff --git a/_less/screen.less b/_less/screen.less index 0e73695b..3c2a2051 100644 --- a/_less/screen.less +++ b/_less/screen.less @@ -642,8 +642,9 @@ table td,table th{ } .docreference a{ display:inline-block; - margin:0 15px 40px 15px; + margin:0 0 40px 0; font-size:125%; + width:210px; } .docreference img{ display:block; @@ -782,6 +783,21 @@ table td,table th{ .toccontent a.term:visited code{ color:#646464; } +.toccontent .multicode{ + background-color:#f5f5f5; + overflow-y:auto; + padding:17px; + border:1px solid #ccc; + -webkit-border-radius:3px; + -moz-border-radius:3px; + border-radius:3px; +} +.toccontent .multicode pre{ + border:0px none; + padding:0; + margin:0; + overflow-y:visible; +} .anchorAf{ position:relative; diff --git a/_plugins/autocrossref.rb b/_plugins/autocrossref.rb index 5ddaa792..4e4a653c 100644 --- a/_plugins/autocrossref.rb +++ b/_plugins/autocrossref.rb @@ -63,6 +63,8 @@ require 'yaml' (?![^\[]*\]) ## No subst if key inside [brackets] (?![^\{]*\}) ## No subst if key inside {braces} (?![^\s]*) ## No subst if after key + (?![\S ]*<\/span>) ## No subst on a line with a close span. This + ## prevents matching in highlight blocks (?![^\(]*(\.svg|\.png)) ## No subst if key inside an image name. This ## simple regex has the side effect that we can't ## use .svg or .png in non-image base text; if that @@ -71,7 +73,7 @@ require 'yaml' (?!\w) ## Don't match inside words /xmi, "[\\&][#{term[1]}]{:.auto-link}") } - output.gsub!('','') ## Remove all comments + output.gsub!(//m,'') ## Remove all HTML comments output end diff --git a/en/developer-documentation.md b/en/developer-documentation.md index abadf682..590a8a75 100644 --- a/en/developer-documentation.md +++ b/en/developer-documentation.md @@ -10,8 +10,9 @@ title: "Developer Documentation - Bitcoin"

Find useful resources, guides and reference material for developers.

@@ -23,6 +24,7 @@ title: "Developer Documentation - Bitcoin"

IconTransactions

Transactions Guide

Transactions Reference

+

Transaction Examples

@@ -47,6 +49,7 @@ title: "Developer Documentation - Bitcoin"

IconPayment Processing

Payment Processing Guide

+

Payment Processing Examples

diff --git a/en/developer-examples.md b/en/developer-examples.md new file mode 100644 index 00000000..a3189948 --- /dev/null +++ b/en/developer-examples.md @@ -0,0 +1,34 @@ +--- +layout: base +lang: en +id: developer-examples +title: "Developer Examples - Bitcoin" +--- + +# Bitcoin Developer Examples + +

Find examples of how to build programs using Bitcoin.

+ +
+ +* Table of contents +{:toc} + + + + +
+
+ +{% include fragment_reviews_needed.md %} + +{% include example_transactions.md %} + +{% include example_payment_processing.md %} + +{% include references.md %} + +
+ + + diff --git a/en/developer-guide.md b/en/developer-guide.md index ee2790c0..99f1c591 100644 --- a/en/developer-guide.md +++ b/en/developer-guide.md @@ -21,18 +21,12 @@ title: "Developer Guide - Bitcoin"
- -
-BETA: This documentation has been written recently and still needs more reviews to ensure all content is covered correctly and accurately; if you find a mistake, please report an issue on GitHub. Click here to close this disclaimer. -X -
- - - +{% include fragment_reviews_needed.md %} + {% include guide_intro.md %} {% include guide_block_chain.md %} diff --git a/en/developer-reference.md b/en/developer-reference.md index 781032f3..43bd20a7 100644 --- a/en/developer-reference.md +++ b/en/developer-reference.md @@ -20,16 +20,12 @@ title: "Developer Reference - Bitcoin"
- -
-BETA: This documentation has been written recently and still needs more reviews to ensure all content is covered correctly and accurately; if you find a mistake, please report an issue on GitHub. Click here to close this disclaimer. -X -
- - +{% include fragment_reviews_needed.md %} {% include ref_block_chain.md %} + {% include ref_transactions.md %} + {% include ref_wallets.md %} ## Bitcoin Core APIs diff --git a/img/main_ico_compass.png b/img/main_ico_compass.png new file mode 100644 index 00000000..e13494a9 Binary files /dev/null and b/img/main_ico_compass.png differ diff --git a/img/main_ico_compass.svg b/img/main_ico_compass.svg new file mode 100644 index 00000000..dd5a9a43 --- /dev/null +++ b/img/main_ico_compass.svg @@ -0,0 +1,127 @@ + + + +image/svg+xml + + + + + diff --git a/img/main_ico_hash.png b/img/main_ico_hash.png new file mode 100644 index 00000000..e5267594 Binary files /dev/null and b/img/main_ico_hash.png differ diff --git a/img/main_ico_hash.svg b/img/main_ico_hash.svg new file mode 100644 index 00000000..2784eac0 --- /dev/null +++ b/img/main_ico_hash.svg @@ -0,0 +1,67 @@ + + + + + + + + + + image/svg+xml + + + + + + + # + +