bitcoind服务安装及基本配置

      有的没的 2014-6-24 21:10:00

 来源:bitcoinmedia 编译:cnbtcnews 这篇指导介绍了比特币的商业开发,需要的知识涉及到Linux、Apache和PHP。 cnbtcnews注:下面的就不翻译了,技术帝的英文都还行,非技术帝对这个也不感兴趣。

After downloading bitcoin, you will find two binaries: bitcoin and bitcoind. bitcoin is the normal GUI client that everyone is familiar with. bitcoind is a bitcoin daemon- a type of program that runs silently in the background that you can interact with. They both are variants of the same code-base and one is getting the same program with both bitcoin and bitcoind, but they are for different situations.

Create a new directory ~/.bitcoin/ and edit the file bitcoin.conf:

% mkdir ~/.bitcoin/ % cd ~/.bitcoin/ % vi bitcoin.conf rpcuser=username rpcpassword=password 

To start the program, we run:

% bitcoind -daemon 

This makes bitcoin run in the background silently. By default it does not fork and fall to the background so developers can run it in a debugger. Technically bitcoind should automatically fork and there should be a -nofork switch, although it is not a big deal. Bitcoin will be doing its initialisation sequence. If this is your first run then it will be downloading the blockchain and seeding your address list. To see the activity, you can view the debug log:

% tail -f ~/.bitcoin/debug.log 

Now the daemon is running, you cannot run more instances. Re-running the daemon will result in an error.

% bitcoind -daemon Bitcoin: Cannot obtain a lock on data directory /home/genjix/.bitcoin. Bitcoin is probably already running. 

Once the server is running, we can start to send commands and interact with it. The getinfo command returns useful generic bitcoin information.

% bitcoind getinfo  {     "version" : 50100,     "balance" : 0.00000000,     "blocks" : 162180,     "connections" : 8,     "proxy" : "",     "generate" : false,     "genproclimit" : -1,     "difficulty" : 1250757.73927466,     "hashespersec" : 0,     "testnet" : false,     "keypoololdest" : 1324254362,     "keypoolsize" : 101,     "paytxfee" : 0.00000000,     "errors" : "" } 

Most of the information there is self explanatory. The useful fields (for us) are the number of blocks, number of connections and our balance. If you try to interact with the bitcoind after starting it, sometimes you will not get a response because the bitcoin daemon has not finished initialising.

% bitcoind getinfo error: no response from server 

If you wait a minute then retry, it should work. Otherwise check the debug.log file for errors. This is the RPC (Remove. Procedure. Call) interface. The bitcoin daemon runs in the background and you are able to interact with it by connecting to it on a local socket (8332). bitcoind uses JSON objects we are an easy way to represent data and are recognised in most common programming languages. The getinfo output we saw earlier is JSON. You can get a list of the RPC methods available by using bitcoind help.

PHP

To interact with bitcoind’s RPC interface, you will need the appropriate JSON-RPC library for your favourite programming language. In this tutorial we are working with PHP.

Download the JSON-RPC PHP library. Discard all the files except jsonRPCClient.php. Copy it over to our project.

% tar xzf JSON-RCP_PHP_light.tgz % ls jsonrpcphp/ 

htdocs includes

% ls jsonrpcphp/includes/  example.php            jsonRPCClient.php      jsonRPCServer.php      restrictedExample.php % mv jsonrpcphp/includes/jsonRPCClient.php /path/to/merchant-tutorial/ 

Directory layout:

  merchant-tutorial/     jsonRPCClient.php     test.php 

Copy this to test.php:

  <?php     require_once 'jsonRPCClient.php';        // Replace with the username and password you set in bitcoin.conf earlier       %bitcoin = new jsonRPCClient('http://username:password@127.0.0.1:8332/');       print_r(%bitcoin->getinfo()); 

Output:

Array (     [version] => 50100     [balance] => 0     [blocks] => 162199     [connections] => 8     [proxy] =>     [generate] =>     [genproclimit] => -1     [difficulty] => 1250757.7392747     [hashespersec] => 0     [testnet] =>     [keypoololdest] => 1324254362     [keypoolsize] => 101     [paytxfee] => 0     [errors] => ) 

print_r is a PHP function to print a data structure. Here in our program’s output, we see that the getinfo from earlier has been converted to a PHP array data structure. This allows us to work with bitcoin in an intuitive way through PHP.

Exercises:

Modify the program above to minus 4 from the number of blocks and echo the number.

Run bitcoind help and use the listsinceblock to list the transactions since 4 blocks ago.

Modify the program to use listsinceblock to show the transactions in the latest 4 blocks with print_r.

Accounts

  1. How can you tell who pays for what on a merchant site with bitcoin? By giving every user a unique bitcoin payment address.

John signs up to our service and when he wants to deposit bitcoin,

he sees:

Please deposit payment to: 19zYBQmJdV3p7hFRNfmLyN72Ugs6LuAVfA

Clarice sees:

Please deposit payment to: 14ZdWQ6byfxvXmxo4N4pBZ43vxppH68V8A

Dave sees:

Please deposit payment to: 194gjnoKutYZedaHsGCCKmfGRXSYuk6u6J

If the merchant site receives a payment to 14ZdWQ6byfxvXmxo4N4pBZ43vxppH68V8A and it has a fair number of confirms (6 is a good number), then we credit the payment to Clarice’s account on the website. We know she made the payment because we displayed that address to only her. Other users on the site were displayed different addresses for making deposits.

Transactions are public. Everyone has a copy of the blockchain and is able to examine money being shifted between these bitcoin addresses. To protect your users and maintain their privacy, good practice dictates you should use a new bitcoin address per payment.

bitcoind provides a facility for tracking these addresses called accounts. An account is essentially a group of bitcoin addresses.

% bitcoind listaccounts {     "" : 0.00000000 } 

Every new bitcoin wallet has a single default account with no name. To show the addresses in an account, run:

% bitcoind getaddressesbyaccount "" [     "1D5ke3sG7afAVXgvm6mvdnUswCnFBmDMLF",     "1PNNk5MVGKckhh13CEftenPwx1mHr9HP8A" ] 

Here we used “” because our account has no name. But you would normally replace “” with an accountname like foo. To make a new address use getnewaddress.

% bitcoind getnewaddress "" 1FFuWS45epfc2T9WeJhrJVJ8ahVtt4rXk 

The address returned is our new bitcoin address. If we run getaddressesbyaccount again, we should see this new address in the list. Our example had 3 users: John, Clarice and Dave. Your system may have unique usernames or user ID numbers. Replace them as needed in our example. John, Clarice and Dave will each have 3 unique bitcoin accounts, and each of those 3 accounts will have various numbers of unique bitcoin addresses. To create a new account, we use getnewaddress.

% bitcoind getnewaddress John 1MfHXZYY3Wyb6wLyCBe1jJY3aGDXksyxkb % bitcoind getnewaddress Clarice 1Avm2KQZ3ow34nMhn5jVFdLM2xPCmgiq3e % bitcoind getnewaddress Dave 159xcRj3KsXY3zKqECfKn7XTQNji3doAAp % bitcoind listaccounts {     "" : 0.00000000,     "Clarice" : 0.00000000,     "Dave" : 0.00000000,     "John" : 0.00000000 } 

In PHP, this may look like:

<?php   // Registration code...   %bitcoin->getnewaddress(%username); 

I do not recommend running getnewaddress on every page load as a wallet must store every bitcoin address. Very quickly you will get a wallet gigabytes in size. A good approach is to use PHP sessions to store a new bitcoin address when a user visits the site. This is a reasonable trade-off.

<?php     require_once('jsonRPCClient.php');     %bitcoin = new jsonRPCClient('http://username:password@127.0.0.1:8332/');     # now check for appropriate funds in user account     try {         %username = ...         if(isset(%_SESSION['sendaddress']))             %sendaddress = %_SESSION['sendaddress'];         else {             %sendaddress = %bitcoin->getnewaddress(%username);             %_SESSION['sendaddress'] = %sendaddress;         }         %balance = %bitcoin->getbalance(%username);     }     catch (Exception %e) {         die("<p>Server error! Please contact the admin.<p>");     } 

Another command is getaccountaddress which is similar to getnewaddress except that is returns an existing address rather than creating a new one. After Clarice has sent bitcoins to the address given to her, the site can check her balance using: bitcoind getbalance number-confirms.

User 6 confirmations before we accept their payment as valid
%user_balance = %bitcoin->getbalance(%username, 6); 
Mixers

A further anonymising step is what is termed mixing. Mixing involves obfuscating payments cross-matching transactions from unrelated sources. Example:

A wants to send 10 BTC to X B wants to send 10 BTC to Y C wants to send 10 BTC to Z 

A mixing service sits in the middle of these transactions and mixes them up. The result is still the same, but now the link in the blockchain has been lost.

A sends 10 BTC to Mixing service 'M' B sends 10 BTC to M C sends 10 BTC to M M sends 10 BTC to Z from A's payment M sends 10 BTC to X from B's payment M sends 10 BTC to Y from C's payment Anybody examing the history will now see a payment chain of: A -> M -> Z B -> M -> X C -> M -> Y 

Instead of:

A -> X B -> Y C -> Z 

This is relevant for sites where users make payments to each other like Silk Road, which has an inbuilt mixer. When a buyer pays a seller on Silk Road, the mixer obfuscates their transaction history.

Accounts suck!

Accounts are fine for small sites. But on a large scale, they are a nightmare and people should stay away. Our old exchange, Britcoin, had a particularly nasty problem when we needed to merge wallets and the accounting used in bitcoin accounts was out of sync. Costed many many hours trying to pick apart addresses. A large site needs that fine grained control which accounts do not offer.

Instead I recommend custom tracking of addresses. Intersango creates a new address per user periodically, storing them in the database.

Live and offline wallets

Sites with an active balance may observe that total site funds actively fluctuate within a small margin. It then makes sense to move the large proportion of the funds to a safely secured bitcoin wallet that is not reachable by the internet.

If ever you are compromised, then you can cover the lost funds from your own pocket while the vast majority of the site’s funds remain safe.

Say a site keeps 1000 BTC in an offline wallet, and 100 BTC in a live wallet. An attacker can only steal 100 BTC. If the 100 BTC is depleted then the site maintainer has to manually replenish the live wallet. Doing his due diligence, he becomes suspicious and discovers the attacker. Using subvertx, offline transactions can be used to ensure that the offline wallet never needs to come in contact with the internet for replenishing the live wallet.

Create new offline wallet
% priv new > offline-wallet.raw 

This is the address associated with that wallet

% priv address < offline-wallet.raw 14DDgj2r8WQEwfTDEjJFBn3wRnHmXzgB3z 

Encrypt our wallet using GPG This can also be done using (pipes) which is the recommended way since you never save the unencrypted file to disk

% gpg -o offline-wallet.enc -r genjix -e offline-wallet.raw % rm offline-wallet.raw 

Whenever you wish to take funds off the live wallet, you simply send to the address above. Sites like Block Explorer or blockchain.info are used to check your balance.

Offline & flyweight transactions for re-filling a live wallet

This is done in 2 steps: creating the transaction, then piping it to send the transaction somewhere. Pipes allow you to do really clever things like send to multiple nodes, send it over a network file share, buffer it to send later (like on USB stick with a different machine that doesn’t have your private key).

% mktx Usage: mktx COMMAND [ARGS]...  Commands:    create    Create a new transaction and output the binary data   send      Send a transaction to the network, reading from STDIN  Options:   -p, --previous-output  Previous output in the form NAME@OUT:INDEX  -k, --keypair      Load a keypair with an identifier NAME@FILE             A single dash - for FILE will load from STDIN  -r, --recipient    Specify a destination ADDRESS:AMOUNT             AMOUNT uses internal bitcoin values               0.1 BTC = 0.1 * 10^8 = 1000000  -H, --host     Host of bitcoin node  -P, --port     Port for bitcoin node  -h, --help     This help text 

Please email suggestions and questions to genjix@riseup.net.

There are 2 commands there. The ‘create’ actually constructs the transaction and then dumps its binary network format to STDOUT. ‘send’ reads from STDIN and sends it to the network. By default it sends to localhost:8333, but you can change it using the –host and –port options. A transaction consists of inputs. You can use Block Explorer or blockchain.info to look them up. Here are some examples.

1. We want to send from transaction

c524c555aad1932c24c26ec20439a9caefc49f7c0df6d6bccced890ef980b45c’s 0th output (which was sent to an address we own) to 2 addresses: 0.02 BTC to 12oabCifvHuxzXtYVGhkxVfWZDvKcU743s and 0.58 BTC to 14DDgj2r8WQEwfTDEjJFBn3wRnHmXzgB3z

There is 1 previous output:

00535291532821f2e4879cf670f61396be32b9579400ae1119497f36f268eb40:1

There are 2 recipients:

12oabCifvHuxzXtYVGhkxVfWZDvKcU743s:2000000 14DDgj2r8WQEwfTDEjJFBn3wRnHmXzgB3z:58000000

Note that we use internal BTC amounts (decimal value * 108 - see help text). Now to spend that output, it has to have been sent to an address you own, hopefully generated using the priv tool earlier.

% mktx create -p priv@c524c555aad1932c24c26ec20439a9caefc49f7c0df6d6bccced890ef980b45c:0 -k priv@keys/privkey -r 12oabCifvHuxzXtYVGhkxVfWZDvKcU743s:2000000 -r 14DDgj2r8WQEwfTDEjJFBn3wRnHmXzgB3z:58000000 

… funny binary output here … If we wish to store that output we can use a redirection > to save it. Maybe store it on your USB and take it to another computer. Or we can pipe it straight to the send command.

% mktx create -p priv@c524c555aad1932c24c26ec20439a9caefc49f7c0df6d6bccced890ef980b45c:0 -k priv@keys/privkey -r 12oabCifvHuxzXtYVGhkxVfWZDvKcU743s:2000000 -r 14DDgj2r8WQEwfTDEjJFBn3wRnHmXzgB3z:58000000 | mktx send 1 peers connected. s: version (85 bytes) r: version (85 bytes) s: verack (0 bytes) r: verack (0 bytes) Connected s: tx (258 bytes) c5 3e a3 b4 d4 4c cf 67 31 73 17 b2 bd 8d 0a 99 46 d8 2d 67 6c 02 d0 d1 13 2b 11 8f 95 d0 7f 57 

The hash at the end is your transaction hash. If you do: tail -f .bitcoin/debug.log, or you look it up on bitcoincharts.com/bitcoin you will see that hash without the spaces (i.e CTRL-F for c53ea3 to see your transaction).

If you noticed, I loaded several private keys there using -k (or –keypair) KEYPAIR-NAME@FILENAME. You then reference which keypair belongs to which input this way.

2. Sending from three, different outputs to 14DDgj2r8WQEwfTDEjJFBn3wRnHmXzgB3z.

Previous outputs:

00535291532821f2e4879cf670f61396be32b9579400ae1119497f36f268eb40:1 637f001eb4cbe165946c02a56bcb73822610f5886516169f98da6252266b7d8a:1 85b423b9c8c5c5277575b87d94dbcd4f87c1be578756eff6a9fde8b7d55749fb:1 

All the outputs (in this case) use a different private key: ./keys/foo, ./keys/bar and ./keys/abc.

We can load the keys and name them (to have a way to refer to them) using:

-k foo@keys/foo -k bar@keys/bar -k abc@keys/abc 

And then indicate to mktx which key belongs with which inputs from above:

foo@00535291532821f2e4879cf670f61396be32b9579400ae1119497f36f268eb40:1 bar@637f001eb4cbe165946c02a56bcb73822610f5886516169f98da6252266b7d8a:1 abc@85b423b9c8c5c5277575b87d94dbcd4f87c1be578756eff6a9fde8b7d55749fb:1 

1 recipient: 14DDgj2r8WQEwfTDEjJFBn3wRnHmXzgB3z:60000000

% mktx create -p foo@00535291532821f2e4879cf670f61396be32b9579400ae1119497f36f268eb40:1 -p bar@637f001eb4cbe165946c02a56bcb73822610f5886516169f98da6252266b7d8a:1 -p abc@85b423b9c8c5c5277575b87d94dbcd4f87c1be578756eff6a9fde8b7d55749fb:1 -k foo@keys/foo -k bar@keys/bar -k abc@keys/abc -r 14DDgj2r8WQEwfTDEjJFBn3wRnHmXzgB3z:60000000 | mktx send 1 peers connected. s: version (85 bytes) r: version (85 bytes) s: verack (0 bytes) r: verack (0 bytes) Connected s: tx (581 bytes) c5 24 c5 55 aa d1 93 2c 24 c2 6e c2 04 39 a9 ca ef c4 9f 7c 0d f6 d6 bc cc ed 89 0e f9 80 b4 5c 
Patching bitcoind for string ints

A problem in PHP is that bitcoind returns decimal amounts which PHP interprets as floats. This is really bad because floats have rounding errors. Using floats in any kind of financial activity is totally unacceptable and even illegal in some jurisdictions.

Patching the Satoshi bitcoin, we can turn 1.00000000 into “100000000” which is a string representation of the internal bitcoin amount, otherwise known as the ‘satoshi’ amount. In src/bitcoinrpc.cpp replace the functions AmountFromValue(…) and ValueFromAmount(…) to fix this.

int64 AmountFromValue(const Value& value) {     int64 nAmount = lexical_cast(value.get_str());     if (!MoneyRange(nAmount))         throw JSONRPCError(-3, "Invalid amount");     return nAmount; }  Value ValueFromAmount(int64 amount) {     return lexical_cast(amount); } And the last return statement for the function getreceivedbyaccount(...): Value getreceivedbyaccount(const Array& params, bool fHelp) {     // ...     // Replace this line:     // return (double)nAmount / (double)COIN;     // With this:     return ValueFromAmount(nAmount); } 

Now after re-compiling and re-running bitcoind, the JSON-RPC interface should be using string integers instead of floats. This is strongly recommended for sensitive financial services dealing with lots of bitcoins. Using floats can lead to tiny inperceptible errors that make precise accounting impossible.

Use listtransactions

If you are not using accounts, then you will need to be periodically polling listtransactions checking for new deposits. It is a good idea to keep all financial records available for auditing. Take the output from listtransactions, parse it into your own internal format. Then using the transaction hash as an identifier, check for any new transactions in our list. Mark the new payments and add this new transaction to the records.

Beware of blockchain re-organisations. However if you are requiring an appropriate amount of confirmations then the risk is low and it’s easier in terms of man-power cost vs situational risk/cost to absorb any loss. The longest blockchain fork on record was 6 blocks deep.

Reorganisations beyond 1 block deep are rare.

Lockup

bitcoind is notoriously buggy and unstable. In our examples we used JSON-RPC to interact with bitcoind directly. In practice this is a bad idea.

As bitcoind is unstable and frequently locks up or goes down- especially under high load, you will want to keep it on the backend. This means using your SQL database as a way to communicate with the backend.

For instance, on Intersango, any kind of action such as cancelling an order or making a withdrawal is a request. An event is pushed onto the queue. Then the market daemon is periodically checking that queue and executing the actions.

Meanwhile another daemon is continually monitoring bitcoind by repeatedly calling a low-latency RPC call like getgenerate. When bitcoind fails to respond within a timeout threshold, it is kill -9'ed and restarted.

0-confirm payments

Beware that if an attacker can withdraw from a site that allows 0-confirm deposits, then he can trivially discover the entire balance of the site by cycling through all the addresses. The fix is to disable withdrawals by the user until a certain number of confirms has been reached for their payment.

A transaction radar is a method of measuring a transaction’s propagation rate in the network. For small amounts we can take this as being the likelihood that their transaction will make it into the blockchain and be final.

Transaction radar’s work by connecting to a number of nodes and scoring a transaction for each node that notifies us of it. If we connect to 100 nodes, and 89 nodes notify us of a certain transaction, then we say it has 89% propagation. The more nodes you connect to, the better your sampling rate.

subvertx has a transaction radar utility called txrad it requires knowledge of C++ to operate and integrate into a service. Experienced developers will find it intuitive to use. Roundup

This is a starting point for merchant developers of all levels. Now the knowledge is out there, go create bitcoin services and make the market a vibrant place.

Our group, Bitcoin Consultancy offers professional services for merchants. It is very easy to get things wrong that can cost you dearly down the line, and we have experienced the common mistakes and situations repeatedly.

原文链接:http://bitcoinmedia.com/merchant-developer-tutorial/

标签集:TAGS:
回复Comments() 点击Count()
喜欢就顶一下

回复Comments

{commentauthor}
{commentauthor}
{commenttime}
{commentnum}
{commentcontent}
作者:
{commentrecontent}