BETA: Dokumentasi ini belum banyak ditinjau oleh para ahli BitcoinV dan mungkin mengandung banyak kesalahan. Harap gunakan tautan Masalah dan Edit di menu kiri bawah untuk membantu kami meningkatkan. Untuk menutup disclaimer ini
BETA: Versi dokumentasi ini mungkin berisi bagian-bagian dalam ahasa Inggris (asli), jika Anda ingin berkontribusi menerjemahkan dokumen ini ke bahasa anda, silakan gunakan tautan yang sesuai di bawah judul, atau kunjungi
The following guide aims to provide examples to help you start
building BitcoinV-based applications. To make the best use of this document,
you may want to install the current version of BitcoinV Core, either from
source or from a pre-compiled executable.
Once installed, you’ll have access to three programs: bitcoinvd,
bitcoinv-qt, and bitcoinv-cli.
bitcoinv-qt provides a combination full BitcoinV peer and wallet
frontend. From the Help menu, you can access a console where you can
enter the RPC commands used throughout this document.
bitcoinvd is more useful for programming: it provides a full peer
which you can interact with through RPCs to port 9332 (or 18332
bitcoinv-cli allows you to send RPC commands to bitcoinvd from the
command line. For example, bitcoinv-cli help
All three programs get settings from bitcoinv.conf in the BitcoinV
OSX: $HOME/Library/Application Support/BitcoinV/
To use bitcoinvd and bitcoinv-cli, you will need to add a RPC password
to your bitcoinv.conf file. Both programs will read from the same file
if both run on the same system as the same user, so any long random
password will work:
You should also make the bitcoinv.conf file only readable to its
owner. On Linux, Mac OSX, and other Unix-like systems, this can be
accomplished by running the following command in the BitcoinV application
In the following documentation, some strings have been shortened or wrapped: “[…]”
indicates extra data was removed, and lines ending in a single backslash “\”
are continued below. If you hover your mouse over a paragraph, cross-reference
links will be shown in blue. If you hover over a cross-reference link, a brief
definition of the term will be displayed in a tooltip.
When run with no arguments, all BitcoinV Core programs default to BitcoinV’s main
network (mainnet). However, for development,
it’s safer and cheaper to use BitcoinV’s test network (testnet)
where the satoshis spent have no real-world value. Testnet also relaxes some
restrictions (such as standard transaction checks) so you can test functions
which might currently be disabled by default on mainnet.
where interaction with random peers and blocks is unnecessary or
unwanted, BitcoinV Core’s regression test mode (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.
Verify that we now have 50 bitcoinvs available to spend.
You can now use BitcoinV Core RPCs prefixed with bitcoinv-cli -regtest.
Regtestwallets and block chain state (chainstate) are saved in the regtest
subdirectory of the BitcoinV Core configuration directory. You can safely
delete the regtest subdirectory and restart BitcoinV Core to
start a new regtest. (See the Developer Examples Introduction for default
configuration directory locations on various operating systems. Always back up
mainnetwallets before performing dangerous operations such as deleting.)
Creating transactions is something most BitcoinV applications do.
This section describes how to use BitcoinV Core’s RPC interface to
create transactions with various attributes.
Your applications may use something besides BitcoinV 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
BitcoinV 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.
Get a new BitcoinV address and save it in the shell variable $NEW_ADDRESS.
Even though the transaction is now complete, the BitcoinV 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.
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).
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.
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.
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.
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:
As illustrated above, the data that gets signed includes the txid and
vout from the previous transaction. That information is included in the
createrawtransactionraw transaction. But the data that gets signed
also includes the pubkey script from the previous transaction, even
though it doesn’t appear in either the unsigned or signed transaction.
In this case, you’re spending an output which is unknown to the wallet,
so it can’t automatically insert the previous pubkey script.
Successfully sign the transaction by providing the previous pubkey
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
pubkey 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
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.
Broadcast the first transaction, which succeeds, and then broadcast the
second transaction—which also now succeeds because the node now sees
We have once again not generated an additional block, so the transactions
above have not yet become part of the regtestblock chain. However, they
are part of the local node’s memory pool.
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
Warning: The payment protocol is considered to be deprecated and will be removed in a later version of BitcoinV Core.
The protocol has multiple security design flaws and implementation flaws in some wallets.
Users will begin receiving deprecation warnings in BitcoinV Core version 0.18 when using BIP70 URI’s.
Merchants should transition away from BIP70 to more secure options such as BIP21.
Merchants should never require BIP70 payments and should provide BIP21 fallbacks.
The browser, QR code reader, or other program processing the URI opens
the spender’s BitcoinV 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/bitcoinv-paymentrequest.
The PaymentRequest 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
requestprotocol 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.
With the Python code generated by protoc, we can start our simple
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.
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 will be contained
within the PaymentRequest.
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. In
general, if a certificate works in your web browser when you connect to
your webserver, it will work for your PaymentRequests.
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.
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
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
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 of the
www.bitcoinv.org X.509 certificate and how each certificate (except the
root certificate) would be loaded into the X509Certificatesprotocol
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. Any intermediate
certificates necessary to link that signed public SSL
key to the root
certificate (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.
(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
Now let’s look at the variables your CGI program will likely set for
Each line is described below.
amount: (optional) the amount 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
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.
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 field and the merchant_data 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.
Next, let’s look at some information your CGI program can
Each line is described below.
time: (required) PaymentRequests must indicate when they were created
in number of seconds elapsed since 1970-01-01T00:00 UTC (Unix
epoch time format).
expires: (optional) the PaymentRequest may also set an expires 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.
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 BitcoinV Core 0.9.
We start by setting some maximum values defined in BIP37: the maximum
number of bytes allowed in a filter and the maximum number of hash
functions used to hash each piece of data. We also set nFlags to zero,
indicating we don’t want the remote node to update the filter for us.
(We won’t use nFlags again in the sample program, but real programs will
need to use it.)
We define the number (n) of elements we plan to insert into the filter
and the false positive rate (p) we want to help protect our privacy. For
this example, we will set n to one element and p to a rate of
1-in-10,000 to produce a small and precise filter for illustration
purposes. In actual use, your filters will probably be much larger.
Using the formula described in BIP37, we calculate the ideal size of the
filter (in bytes) and the ideal number of hash functions to use. Both
are truncated down to the nearest whole number and both are also
constrained to the maximum values we defined earlier. The results of
this particular fixed computation are 2 filter bytes and 11 hash
functions. We then use nFilterBytes to create a little-endian bit
array of the appropriate size.
We also should choose a value for nTweak. In this case, we’ll simply
We setup our hash function template using the formula and 0xfba4c795
constant set in BIP37. Note that we limit the size of the seed to four
bytes and that we’re returning the result of the hash modulo the size of
the filter in bits.
Now we use the hash function template to run a slightly different hash
function for nHashFuncs times. The result of each function being run
on the transaction is used as an index number: the bit at that index is
set to 1. We can see this in the printed debugging output:
Notice that in iterations 8 and 9, the filter did not change because the
corresponding bit was already set in a previous iteration (5 and 7,
respectively). This is a normal part of bloom filter operation.
We only added one element to the filter above, but we could repeat the
process with additional elements and continue to add them to the same
filter. (To maintain the same false-positive rate, you would need a
larger filter size as computed earlier.)
Note: for a more optimized Python implementation with fewer external
dependencies, see python-bitcoinvlib’sbloom filter
module which is based directly on BitcoinV Core’s C++ implementation.
Using the filterload message format, the complete filter created above
would be the binary form of the annotated hexdump shown below:
Using a bloom filter to find matching data is nearly identical to
constructing a bloom filter—except that at each step we check to see
if the calculated index bit is set in the existing filter.
Using the bloom filter created above, we import its various parameters.
Note, as indicated in the section above, we won’t actually use nFlags
to update the filter.
We define a function to check an element against the provided filter.
When checking whether the filter might contain an element, we test to
see whether a particular bit in the filter is already set to 1 (if it
isn’t, the match fails).
Testing the filter against the data element we previously added, we get
no output (indicating a possible match). Recall that bloom filters have
a zero false negative rate—so they should always match the inserted
Testing the filter against an arbitrary element, we get the failure
output below. Note: we created the filter with a 1-in-10,000 false
positive rate (which was rounded up somewhat when we truncated), so it
was possible this arbitrary string would’ve matched the filter anyway.
It is not possible to set a bloom filter to a false positive rate of
zero, so your program will always have to deal with false positives.
The output below shows us that one of the hash functions returned an
index number of 0x06, but that bit wasn’t set in the filter, causing the
We request a merkle block for transactions matching our filter,
completing our script.
To run the script, we simply pipe it to the Unix netcat
command or one of its many clones, one of which is available
for practically any platform. For example, with the original netcat and
using hexdump (hd) to display the output:
Part of the response is shown in the section below.
We parse the above merkleblock message using the following
instructions. Each illustration is described in the paragraph below it.
We start by building the structure of a merkle tree based on the number
of transactions in the block.
The first flag is a 1 and the merkle root is (as always) a non-TXIDnode, so we will need to compute the hash later based on this node’s
children. Accordingly, we descend into the merkle root’s left child and
look at the next flag for instructions.
The next flag in the example is a 0 and this is also a non-TXIDnode, so
we apply the first hash from the merkleblock message to this node. We
also don’t process any child nodes—according to the peer which created
the merkleblock message, none of those nodes will lead to TXIDs of
transactions that match our filter, so we don’t need them. We go back up
to the merkle root and then descend into its right child and look at the
next (third) flag for instructions.
The third flag in the example is another 1 on another non-TXIDnode, so
we descend into its left child.
The fourth flag is also a 1 on another non-TXIDnode, so we descend
again—we will always continue descending until we reach a TXIDnode or
a non-TXIDnode with a 0 flag (or we finish filling out the tree).
Finally, on the fifth flag in the example (a 1), we reach a TXIDnode.
The 1 flag indicates this TXID’s transaction matches our filter and
that we should take the next (second) hash and use it as this node’sTXID.
The sixth flag also applies to a TXID, but it’s a 0 flag, so this
TXID’s transaction doesn’t match our filter; still, we take the next
(third) hash and use it as this node’sTXID.
We now have enough information to compute the hash for the fourth node
we encountered—it’s the hash of the concatenated hashes of the two
TXIDs we filled out.
Moving to the right child of the third node we encountered, we fill it
out using the seventh flag and final hash—and discover there are no
more child nodes to process.
We hash as appropriate to fill out the tree. Note that the eighth flag is
not used—this is acceptable as it was required to pad out a flag byte.