1. 概述

加密货币是一种安全且去中心化的价值存储方式。它采用点对点(P2P)网络进行交易传播和验证。

BitcoinJ 是一个 Java 库,能简化比特币应用的开发,让用户无缝执行加密货币交易。

本教程将深入探讨 BitcoinJ 的核心功能和组件,并演示如何创建钱包、充值钱包以及向其他钱包转账。

2. 什么是 BitcoinJ?

BitcoinJ 是一个简化比特币应用开发的 Java 库。它提供创建和管理比特币钱包、收发交易的工具,并支持与比特币主网(mainnet)、测试网(testnet)和回归测试网(regtest)的集成。

此外,它提供简化支付验证(SPV)功能,无需下载完整区块链即可与比特币网络交互

3. BitcoinJ 的核心功能

钱包管理:轻松创建比特币钱包,包括生成地址、管理公私钥和处理助记词恢复
交易处理:支持比特币交易的发送和接收
网络集成:支持比特币主网(真实交易)、测试网和回归测试网(测试环境)
事件监听:通过事件监听器响应交易到账或区块链变更等事件

4. 基础配置

pom.xml 中添加 bitcoinj-core 依赖:

<dependency>
    <groupId>org.bitcoinj</groupId>
    <artifactId>bitcoinj-core</artifactId>
    <version>0.17-alpha4</version>
</dependency>

添加日志依赖 slf4j-apislf4j-simple

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>2.1.0-alpha1</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>2.1.0-alpha1</version>
</dependency>

5. Wallet 类详解

钱包是加密货币的核心组件,BitcoinJ 通过 WalletWalletKitApp 类实现钱包管理。

5.1 创建钱包

创建钱包前需指定网络类型:主网(生产环境)、测试网(测试环境)或回归测试网(本地测试)。

NetworkParameters params = TestNet3Params.get();

创建 Wallet 实例:

void createWallet() throws IOException {
    Wallet wallet = Wallet.createDeterministic(params, Script.ScriptType.P2PKH);
    File walletFile = new File("baeldung.dat");
    wallet.saveToFile(walletFile);
}

⚠️ 关键点

  • 使用 P2PKH 脚本类型(Pay-to-Pubkey-Hash 地址,比特币常用地址类型)
  • 创建时自动生成地址、助记词、公私钥
  • 钱包保存为 baeldung.dat 文件

5.2 获取钱包信息

创建后可获取地址、公私钥、助记词等核心信息

Wallet loadWallet() throws IOException, UnreadableWalletException {
    File walletFile = new File("baeldung.dat");
    Wallet wallet = Wallet.loadFromFile(walletFile);
    logger.info("地址: " + wallet.currentReceiveAddress().toString());
    logger.info("助记词: " + wallet.getKeyChainSeed().getMnemonicString());
    logger.info("余额: " + wallet.getBalance().toFriendlyString());
    logger.info("公钥: " + wallet.findKeyFromAddress(wallet.currentReceiveAddress()).getPublicKeyAsHex());
    logger.info("私钥: " + wallet.findKeyFromAddress(wallet.currentReceiveAddress()).getPrivateKeyAsHex());
    return wallet;
}

5.3 恢复钱包

丢失钱包文件但保留助记词时,可通过助记词恢复钱包

Wallet loadUsingSeed(String seedWord) throws UnreadableWalletException {
    DeterministicSeed seed = new DeterministicSeed(seedWord, null, "", Utils.currentTimeSeconds());
    return Wallet.fromSeed(params, seed);
}

5.4 钱包加密

安全警告:私钥和助记词泄露 = 资产被盗!使用 encrypt() 加密钱包:

// 加密钱包
wallet.encrypt("your_strong_password");
wallet.saveToFile(walletFile);

// 解密钱包
Wallet wallet = Wallet.loadFromFile(walletFile);
wallet.decrypt("your_strong_password");

5.5 连接对等网络

孤立钱包无法同步交易,需连接对等网络

void connectWalletToPeer() throws BlockStoreException, UnreadableWalletException, IOException {
    Wallet wallet = loadWallet();
    BlockStore blockStore = new MemoryBlockStore(params);
    BlockChain chain = new BlockChain(params, wallet, blockStore);
    PeerGroup peerGroup = new PeerGroup(params, chain);
    peerGroup.addPeerDiscovery(new DnsDiscovery(params));
    peerGroup.addWallet(wallet);
    peerGroup.start();
    peerGroup.downloadBlockChain();
}

⚠️ 性能提示:完整区块链下载资源消耗大,WalletKitApp 默认使用 SPV 模式优化此过程。

6. WalletKitApp 类详解

WalletKitApp 类简化了钱包设置流程,自动处理 BlockStoreBlockChainPeerGroup 的创建

NetworkParameters params = TestNet3Params.get();

WalletAppKit kit = new WalletAppKit(params, new File("."), "baeldungkit") {
    @Override
    protected void onSetupCompleted() {
        logger.info("钱包创建加载成功");
        logger.info("接收地址: " + wallet().currentReceiveAddress());
        logger.info("助记词: " + wallet().getKeyChainSeed());
        logger.info("余额: " + wallet().getBalance().toFriendlyString());
        logger.info("公钥: " + wallet().findKeyFromAddress(wallet().currentReceiveAddress())
          .getPublicKeyAsHex());
        logger.info("私钥: " + wallet().findKeyFromAddress(wallet().currentReceiveAddress())
          .getPrivateKeyAsHex());
        wallet().encrypt("password");
    }
};
kit.startAsync();
kit.awaitRunning();
kit.setAutoSave(true);

输出示例:

[ STARTING] INFO com.baeldung.bitcoinj.Kit - 钱包创建加载成功
[ STARTING] INFO com.baeldung.bitcoinj.Kit - 接收地址: moqVLcdRFjyXehgRAK5bJBK6rDN2vq14Wc
[ STARTING] INFO com.baeldung.bitcoinj.Kit - 助记词: DeterministicSeed{unencrypted}
[ STARTING] INFO com.baeldung.bitcoinj.Kit - 余额: 0

6.1 添加事件监听器

监听交易到账事件

kit.wallet()
  .addCoinsReceivedEventListener((wallet, tx, prevBalance, newBalance) -> {
      logger.info("收到交易: " + tx.getValueSentToMe(wallet));
      logger.info("新余额: " + newBalance.toFriendlyString());
  });

监听转账事件

kit.wallet()
  .addCoinsSentEventListener((wallet, tx, prevBalance, newBalance) -> 
      logger.info("转账后余额: " + newBalance.toFriendlyString())
  );

6.2 接收比特币

通过比特币测试网水龙头获取测试币:

测试币水龙头

BlockCypher 验证交易:

交易记录

重启程序查看余额更新:

余额更新

6.3 发送比特币

创建 Coin 实例指定转账金额(单位:聪):

String receiveAddress = "n1vb1YZXyMQxvEjkc53VULi5KTiRtcAA9G";
Coin value = Coin.valueOf(200); // 200 聪
final Coin amountToSend = value.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE);
final Wallet.SendResult sendResult = kit.wallet()
  .sendCoins(kit.peerGroup(), Address.fromString(params, receiveAddress), amountToSend);

⚠️ 注意:转账金额需扣除矿工费(REFERENCE_DEFAULT_MIN_TX_FEE)。

7. 总结

本文通过比特币测试网演示了 BitcoinJ 的核心用法,涵盖:

  • 钱包创建/恢复/加密
  • 交易收发
  • 网络同步
  • 事件监听

完整源码见 GitHub


原始标题:Introduction to BitcoinJ | Baeldung