在币圈中,使用自己的钱包给他人发币时,就跟平常的微信、支付宝扫码付款类似,输入BTC地址和金额,再输入支付密码,不管对方是否在地球的另一端,不需要任何银行的中介,10分钟到几小时之后,BTC就可以到账了。
发币需要支付少量的交易手续费,如果给许多人发币,上述操作就比较吃亏了。还好,许多钱包软件都支持给多人同时转账的功能,添加多个地址、金额,再输入支付口令,稍微麻烦一些,细心操作即可。
以Bitcoin Core为例,点击底部的“添加收款人”即可给多人发币。
但是如果同时给几百人发币呢?一般人遇不到这类问题,矿场老板需要面对这个棘手的问题。用手机版的钱包会把手指头划肿的,即使用电脑操作,也非常容易出错。这时必须用编程来解决,RPC调用是一种比较方便的解决办法。
以下内容是写给程序员的,如果不是程序员,请直接跳到最后,那里是炒币内容。
跑通RPC调用
1)配置bitcoin core
首先需要修改bitcoin core数据文件夹中的bitcoin.conf文件,加三行文字(请自行更换用户名和密码):
server=1 rpcuser=shenlongbin rpcpassword=申龙斌的程序人生
2)下载BitcoinLib
用我上一篇文章《Bitcoin Core钱包常用的命令行参数》的-datadir参数启动Bitcoin Core之后,我们就可以编程进行RPC调用了。网上现成的bitcoin RPC函数库很多,各种编程语言都支持,这里以C#为例,比较全的类库是BitcoinLib,下载地址:
https://github.com/GeorgeKimionis/BitcoinLib
3)加上引用
在VisualStudio中可以用nuget添加引用,再加上常用的using语句。
using BitcoinLib.ExceptionHandling.Rpc; using BitcoinLib.Requests.CreateRawTransaction; using BitcoinLib.Requests.SignRawTransaction; using BitcoinLib.Responses; using BitcoinLib.Services.Coins.Base; using BitcoinLib.Services.Coins.Bitcoin;
4)先声明一个rpc变量
ICoinService rpc = new BitcoinService(useTestnet: false);
这个类库不仅支持BTC,还支持其它竞争币,我曾经试过BCH,也一样可用。
5)用户名和密码要一致
程序默认从资源文件中读入RPC的用户名和密码,也可以在代码中直接修改:
rpc.Parameters.RpcUsername = "shenlongbin"; rpc.Parameters.RpcPassword = "申龙斌的程序人生"
6)测试rpc是否连通
rpc.Ping();
如果这条语句抛出异常,说明RPC连接中存在问题,请依次检查bitcoin core是否启动,配置的用户名和密码是否正确等等。
如果以上过程都通过,则说明RPC功能已经可以工作,下面的任务就是构造交易数据,签名和广播消息了。
读出钱包中的UTXO
UTXO就是指钱包中的未花费的交易记录。
List<ListUnspentResponse> utxos = rpc.ListUnspent(0);
最后的一个参数0表示零确认的记录也不放过,这个功能可以用于交易加速,请参考以前写的文章《交易被堵?试试这几种办法》。
每一笔未花费记录的挖矿时间、数量、确认数、地址都可以查到。
for (int i = 0; i < utxos.Count; i ) { ListUnspentResponse uns = utxos[i]; GetTransactionResponse response = rpc.GetTransaction(uns.TxId); // response.BlockTime // uns.Amount.ToString("0.00000000") // uns.Confirmations // uns.Address }
构建交易
比特币的一条交易由输入和输出构成,用下面语句构成:
CreateRawTransactionRequest req = new CreateRawTransactionRequest(); req.AddInput(utxos[0].TxId, utxos[0].Vout); req.AddInput(utxos[1].TxId, utxos[1].Vout); ... ...
选择哪几笔UTXO,是你自己的责任,以前都是Bitcoin Core钱包帮你做了,现在是自己编程来解决。
添加输出项:
req.AddOutput("1BPCVbLf7Xz6Y9cKQn7WbuBbDLX6nAhtLr", (decimal)0.002); req.AddOutput("15H6LPBMEx46U6ryDUnKJoZDAqmmBMpNV6", (decimal)0.002); req.AddOutput("1DqvWgjp5i9QUzkg1B44crHUkdoRrdrrww", (decimal)0.002); req.AddOutput("19DBjYq1mgMz63axBfbViqPxWyR5vXd9Zf", (decimal)0.002); req.AddOutput("3JvYRhX3fghSqFPM4kQ3a7i8bbbaHa8Pnn", (decimal)0.002);
如果有找零地址,也需要程序员自己添加AddOutput()语句来解决,否则就当手续费被矿工赚走了,这点编程时务必要注意。
现在可以生成交易数据了,这里的raw是指未经过加工的数据,也就是未签名的交易数据。
string rawTX = rpc.CreateRawTransaction(req);
构建出来的交易是否有问题,可以用解码功能来验证,涉及成千上万元的转账操作,得谨慎一些。
DecodeRawTransactionResponse response = rpc.DecodeRawTransaction(rawTX);
签名交易
这里需要取出钱包里的私钥对你构建好的交易数据进行签名,先要用钱包密码解锁钱包。
rpc.WalletPassphrase(bitcoin_core_wallet_password, 20);
为了安全,20秒之后钱包自动重新锁住 。
签名操作很简单:
SignRawTransactionResponse response = rpc.SignRawTransaction(new SignRawTransactionRequest(rawTX)); string signedTX = response.Hex
发送交易
签名之后的交易数据就可以拿到全网进行广播了,返回的字符串就是交易ID。
string txid = rpc.SendRawTransaction(signedTX);
如果交易成功,马上在blockchain.info网站上可以查到刚才的TXID。
声明:本文只是介绍了BitcoinLib编程中的主要步骤,省略了大量有关异常处理的代码。利用BitcoinLib不仅可以发币,还可以完成Bitcoin Core的几乎所有功能,这里不细述了。
我以前完成的发币程序的主界面是这样的: