10

我想以编程方式检测何时有人将比特币发送到某个地址。这发生在我开始使用这个docker-compose.yml文件的本地测试网上。

一旦本地测试网运行,我使用创建一个新地址

docker exec -it minimal-crypto-exchange_node_1 bitcoin-cli getnewaddress

假设它返回2N23tWAFEtBtTgxNjBNmnwzsiPdLcNek181

我将此地址放入以下​​Java 代码中:

import org.bitcoinj.core.Address;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.wallet.Wallet;
import org.bitcoinj.wallet.listeners.WalletCoinsReceivedEventListener;

public class WalletObserver {
    public void init() {
        final NetworkParameters netParams = NetworkParameters.fromID(NetworkParameters.ID_REGTEST);

        try {
            final Wallet wallet = Wallet.createBasic(netParams);

            wallet.addWatchedAddress(Address.fromString(netParams, "2N23tWAFEtBtTgxNjBNmnwzsiPdLcNek181"));

            wallet.addCoinsReceivedEventListener(new WalletCoinsReceivedEventListener() {
                @Override
                public void onCoinsReceived(final Wallet wallet, final Transaction transaction, final Coin prevBalance, final Coin newBalance) {
                    System.out.println("Heyo!");
                }
            });
        }
        catch (Exception exception) {
            exception.printStackTrace();
        }
    }
}

然后我用这个类启动 Java 应用程序。

然后我将一些测试比特币发送到相关地址:

% docker exec -it minimal-crypto-exchange_node_1 bitcoin-cli sendtoaddress 2N23tWAFEtBtTgxNjBNmnwzsiPdLcNek181 0.5
068c377bab961356ad9a3919229a764aa929711c68aefd5dbd4c7c348eef3406

如果我去http://localhost:3002/tx/068c377bab961356ad9a3919229a764aa929711c68aefd5dbd4c7c348eef3406,我会看到交易细节。

交易页面截图

但是,侦听器(onCoinsReceived方法)中的断点永远不会激活。

我如何需要修改我的代码和/或我用来发送测试 BTC 的命令,以便当该账户收到钱时,onCoinsReceived调用方法?有什么地方可以告诉我Wallet或者NetworkParameters我想连接到本地主机吗?

我正在使用 0.15.10 版的 bitcoinj-core。

更新1:

我修改了 docker-compose.yml并添加了以下端口映射:

    ports:
      - "51001:50001"
      - "51002:50002"
      - "19001:19001"
      - "19000:19000"
      - "28332:28332"

然后我重写了init方法,以便我可以连接到 localhost 并指定端口:

public class WalletObserver {
    public void init() {
        final LocalTestNetParams netParams = new LocalTestNetParams();
        netParams.setPort(50001);
        try {
            final WalletAppKit kit = new WalletAppKit(netParams, new File("."), "_minimalCryptoExchangeBtcWallet");
            kit.setAutoSave(true);
            kit.connectToLocalHost();

            kit.startAsync();
            kit.awaitRunning(); // I never get past this point
            kit.peerGroup().addPeerDiscovery(new DnsDiscovery(netParams));
            kit.wallet().addWatchedAddress(Address.fromString(netParams, "2N23tWAFEtBtTgxNjBNmnwzsiPdLcNek181"));

            kit.wallet().addCoinsReceivedEventListener(new WalletCoinsReceivedEventListener() {
                @Override
                public void onCoinsReceived(final Wallet wallet, final Transaction transaction, final Coin prevBalance, final Coin newBalance) {
                    System.out.println("Heyo!");
                }
            });
        }
        catch (Exception exception) {
            exception.printStackTrace();
        }
    }

LocalTestNetParams允许指定端口:

package com.dpisarenko.minimalcryptoexchange.logic.btc;

import org.bitcoinj.params.RegTestParams;

public class LocalTestNetParams extends RegTestParams {
    public void setPort(final int newPort) {
        this.port = newPort;
    }
}

我尝试了所有上述端口netParams.setPort(50001);

在所有情况下,我都会收到以下消息kit.awaitRunning();

22:16:34.245 [PeerGroup Thread] INFO  org.bitcoinj.core.PeerGroup - Attempting connection to [10.10.1.218]:50001     (0 connected, 1 pending, 1 max)
22:16:34.265 [NioClientManager] WARN  org.bitcoinj.net.NioClientManager - Failed to connect with exception: java.net.ConnectException: Connection refused
java.net.ConnectException: Connection refused
    at java.base/sun.nio.ch.Net.pollConnect(Native Method)
    at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:579)
    at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:820)
    at org.bitcoinj.net.NioClientManager.handleKey(NioClientManager.java:64)
    at org.bitcoinj.net.NioClientManager.run(NioClientManager.java:122)
    at com.google.common.util.concurrent.AbstractExecutionThreadService$1$2.run(AbstractExecutionThreadService.java:66)
    at com.google.common.util.concurrent.Callables$4.run(Callables.java:119)
    at org.bitcoinj.utils.ContextPropagatingThreadFactory$1.run(ContextPropagatingThreadFactory.java:51)
    at java.base/java.lang.Thread.run(Thread.java:830)
22:16:34.267 [NioClientManager] INFO  org.bitcoinj.core.PeerGroup - [10.10.1.218]:50001: Peer died      (0 connected, 0 pending, 1 max)
22:16:34.267 [PeerGroup Thread] INFO  org.bitcoinj.core.PeerGroup - Peer discovery took 21.84 μs and returned 0 items from 0 discoverers
22:16:34.269 [PeerGroup Thread] INFO  org.bitcoinj.core.PeerGroup - Waiting 1502 ms before next connect attempt to [10.10.1.218]:50001
22:16:35.776 [PeerGroup Thread] INFO  org.bitcoinj.core.PeerGroup - Attempting connection to [10.10.1.218]:50001     (0 connected, 1 pending, 1 max)
22:16:35.778 [NioClientManager] WARN  org.bitcoinj.net.NioClientManager - Failed to connect with exception: java.net.ConnectException: Connection refused
java.net.ConnectException: Connection refused
    at java.base/sun.nio.ch.Net.pollConnect(Native Method)
    at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:579)
    at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:820)
    at org.bitcoinj.net.NioClientManager.handleKey(NioClientManager.java:64)
    at org.bitcoinj.net.NioClientManager.run(NioClientManager.java:122)
    at com.google.common.util.concurrent.AbstractExecutionThreadService$1$2.run(AbstractExecutionThreadService.java:66)
    at com.google.common.util.concurrent.Callables$4.run(Callables.java:119)
    at org.bitcoinj.utils.ContextPropagatingThreadFactory$1.run(ContextPropagatingThreadFactory.java:51)
    at java.base/java.lang.Thread.run(Thread.java:830)
22:16:35.778 [NioClientManager] INFO  org.bitcoinj.core.PeerGroup - [10.10.1.218]:50001: Peer died      (0 connected, 0 pending, 1 max)
22:16:35.779 [PeerGroup Thread] INFO  org.bitcoinj.core.PeerGroup - Peer discovery took 8.752 μs and returned 0 items from 0 discoverers

10.10.1.218似乎是由InetAddress.getLocalHost()in生成的org.bitcoinj.kits.WalletAppKit#connectToLocalHost

    public WalletAppKit connectToLocalHost() {
        try {
            InetAddress localHost = InetAddress.getLocalHost();
            return this.setPeerNodes(new PeerAddress(this.params, localHost, this.params.getPort()));
        } catch (UnknownHostException var2) {
            throw new RuntimeException(var2);
        }
    }

更新1:

我尝试使用network_mode: "host".

如果我将它添加node

  node:
    image: ulamlabs/bitcoind-custom-regtest:latest
    network_mode: "host"

运行时出现以下错误docker-compose up -d

minimal-crypto-exchange % docker-compose up -d
Creating network "minimal-crypto-exchange_default" with the default driver
Creating minimal-crypto-exchange_postgres_1  ... done
Creating minimal-crypto-exchange_geth_1     ...
Creating minimal-crypto-exchange_node_1     ... done
Creating minimal-crypto-exchange_electrumx_1 ...
Creating minimal-crypto-exchange_electrumx_1 ... error

ERROR: for minimal-crypto-exchange_electrumx_1  Cannot start service electrumx: driver fail
Creating minimal-crypto-exchange_geth_1      ... done
f68d0f25a0512399877bc55434513def810649e4fcf31a5a88ca3292d34): Error starting userland proxy: listen tcp4 0.0.0.0:28332: bind: address already in use
Creating minimal-crypto-exchange_blockscout_1 ... done

ERROR: for electrumx  Cannot start service electrumx: driver failed programming external connectivity on endpoint minimal-crypto-exchange_electrumx_1 (8eaa4f68d0f25a0512399877bc55434513def810649e4fcf31a5a88ca3292d34): Error starting userland proxy: listen tcp4 0.0.0.0:28332: bind: address already in use
ERROR: Encountered errors while bringing up the project.

如果我将它添加到electrumx部分中

  electrumx:
    image: lukechilds/electrumx:latest
    network_mode: "host"

我得到另一个错误:

minimal-crypto-exchange % docker-compose up -d
minimal-crypto-exchange_postgres_1 is up-to-date
minimal-crypto-exchange_geth_1 is up-to-date
Recreating minimal-crypto-exchange_node_1 ...
Recreating minimal-crypto-exchange_node_1 ... done
Recreating minimal-crypto-exchange_electrumx_1 ...

ERROR: for minimal-crypto-exchange_electrumx_1  "host" network_mode is incompatible with port_bindings

ERROR: for electrumx  "host" network_mode is incompatible with port_bindings
Traceback (most recent call last):
  File "docker-compose", line 3, in <module>
  File "compose/cli/main.py", line 81, in main
  File "compose/cli/main.py", line 203, in perform_command
  File "compose/metrics/decorator.py", line 18, in wrapper
  File "compose/cli/main.py", line 1186, in up
  File "compose/cli/main.py", line 1166, in up
  File "compose/project.py", line 697, in up
  File "compose/parallel.py", line 108, in parallel_execute
  File "compose/parallel.py", line 206, in producer
  File "compose/project.py", line 679, in do
  File "compose/service.py", line 579, in execute_convergence_plan
  File "compose/service.py", line 499, in _execute_convergence_recreate
  File "compose/parallel.py", line 108, in parallel_execute
  File "compose/parallel.py", line 206, in producer
  File "compose/service.py", line 494, in recreate
  File "compose/service.py", line 612, in recreate_container
  File "compose/service.py", line 330, in create_container
  File "compose/service.py", line 939, in _get_container_create_options
  File "compose/service.py", line 1014, in _get_container_host_config
  File "docker/api/container.py", line 598, in create_host_config
  File "docker/types/containers.py", line 338, in __init__
docker.errors.InvalidArgument: "host" network_mode is incompatible with port_bindings
[44262] Failed to execute script docker-compose

更新 2:

如果我注释掉端口绑定,如

  electrumx:
    image: lukechilds/electrumx:latest
    network_mode: host
    links:
      - node
# Port settings see https://github.com/ulamlabs/bitcoind-custom-regtest
#    ports:
#      - "51001:50001"
#      - "51002:50002"
#      - "19001:19001"
#      - "19000:19000"
#      - "28332:28332"

然后跑docker-compose up -d我得到

 % docker-compose up -d
Creating network "minimal-crypto-exchange_default" with the default driver
Creating minimal-crypto-exchange_geth_1 ...
Creating minimal-crypto-exchange_postgres_1  ... done
Creating minimal-crypto-exchange_node_1     ... done
Creating minimal-crypto-exchange_electrumx_1 ... error
Creating minimal-crypto-exchange_geth_1      ... done
ERROR: for minimal-crypto-exchange_electrumx_1  Cannot create container for service electrumx: conflicting options: host type networking can't be used with links. This would result in undefined behavior
Creating minimal-crypto-exchange_blockscout_1 ... done

ERROR: for electrumx  Cannot create container for service electrumx: conflicting options: host type networking can't be used with links. This would result in undefined behavior
ERROR: Encountered errors while bringing up the project.

更新 3:我假设错误的根源是在我的 Java 代码中,我尝试连接到 ElectrumX 服务器而不是实际的比特币节点(nodein docker-compose.yml)。

更新 4:

我更改docker-compose.yml如下:

  node:
    image: ulamlabs/bitcoind-custom-regtest:latest
# For ports used by node see
# https://github.com/ulamlabs/bitcoind-custom-regtest/blob/master/bitcoin.conf
    ports:
      - "19001:19001"
      - "19000:19000"
      - "28332:28332"
  electrumx:
    image: lukechilds/electrumx:latest
    links:
      - node
# Port settings see https://github.com/ulamlabs/bitcoind-custom-regtest
    ports:
      - "51001:50001"
      - "51002:50002"
#      - "19001:19001"
#      - "19000:19000"
#      - "28332:28332"

现在我收到不同的错误(此处提供完整日志):

11:33:51.865 [NioClientManager] INFO  org.bitcoinj.core.PeerGroup - [192.168.10.208]:19000: Peer died      (0 connected, 0 pending, 1 max)
11:33:51.865 [NioClientManager] INFO  org.bitcoinj.core.PeerGroup - Not yet setting download peer because there is no clear candidate.
11:33:51.865 [NioClientManager] DEBUG org.bitcoinj.core.BitcoinSerializer - Received 168 byte 'alert' message: 60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50
11:33:51.866 [PeerGroup Thread] INFO  org.bitcoinj.core.PeerGroup - Waiting 999 ms before next connect attempt to [127.0.0.1]:19000
11:33:51.866 [NioClientManager] DEBUG org.bitcoinj.core.Peer - Received alert from peer Peer{[192.168.10.208]:19000, version=70015, subVer=/Satoshi:0.19.1(bitcore)/, services=1033 (NETWORK, WITNESS, NETWORK_LIMITED), time=2021-11-06 11:33:52, height=5}: URGENT: Alert key compromised, upgrade required
11:33:51.867 [NioClientManager] WARN  org.bitcoinj.net.ConnectionHandler - Error handling SelectionKey: java.nio.channels.CancelledKeyException 
java.nio.channels.CancelledKeyException: null
    at java.base/sun.nio.ch.SelectionKeyImpl.ensureValid(SelectionKeyImpl.java:71)
    at java.base/sun.nio.ch.SelectionKeyImpl.readyOps(SelectionKeyImpl.java:130)
    at java.base/java.nio.channels.SelectionKey.isWritable(SelectionKey.java:377)
    at org.bitcoinj.net.ConnectionHandler.handleKey(ConnectionHandler.java:244)
    at org.bitcoinj.net.NioClientManager.handleKey(NioClientManager.java:86)
    at org.bitcoinj.net.NioClientManager.run(NioClientManager.java:122)
    at com.google.common.util.concurrent.AbstractExecutionThreadService$1$2.run(AbstractExecutionThreadService.java:66)
    at com.google.common.util.concurrent.Callables$4.run(Callables.java:119)
    at org.bitcoinj.utils.ContextPropagatingThreadFactory$1.run(ContextPropagatingThreadFactory.java:51)
    at java.base/java.lang.Thread.run(Thread.java:830)

更新 5:

有人建议(在现在删除的评论中)在应用程序的输出中有以下Peer does not support bloom filtering消息:

11:32:43.482 [NioClientManager] INFO  org.bitcoinj.core.Peer - Peer{[127.0.0.1]:19000, version=70015, subVer=/Satoshi:0.19.1(bitcore)/, services=1033 (NETWORK, WITNESS, NETWORK_LIMITED), time=2021-11-06 11:32:43, height=4}: Peer does not support bloom filtering.

所以我尝试 fork 原始图像并更改bitcoin.conf文件以启用 Bloom 过滤:

peerbloomfilters=1

当我运行时,docker build -t mentiflectax/bitcoind-custom-regtest:latest .我收到以下错误消息(可以在此处找到部分剩余输出):

#13 922.4 g++: fatal error: Killed signal terminated program cc1plus
#13 922.4 compilation terminated.
#13 922.4 make[2]: *** [Makefile:8044: libbitcoin_server_a-init.o] Error 1
#13 922.4 make[2]: *** Waiting for unfinished jobs....
#13 965.8 make[2]: Leaving directory '/bitcoin-0.19.1/src'
#13 965.8 make[1]: *** [Makefile:13765: all-recursive] Error 1
#13 965.9 make[1]: Leaving directory '/bitcoin-0.19.1/src'
#13 965.9 make: *** [Makefile:776: all-recursive] Error 1
------
executor failed running [/bin/sh -c tar -xzf *.tar.gz     && cd bitcoin-${BITCOIN_VERSION}     && sed -i 's/consensus.nSubsidyHalvingInterval = 150/consensus.nSubsidyHalvingInterval = 210000/g' src/chainparams.cpp     && ./autogen.sh     && ./configure LDFLAGS=-L`ls -d /opt/db`/lib/ CPPFLAGS=-I`ls -d /opt/db`/include/     --prefix=/opt/bitcoin     --disable-man     --disable-tests     --disable-bench     --disable-ccache     --with-gui=no     --enable-util-cli     --with-daemon     && make -j4     && make install     && strip /opt/bitcoin/bin/bitcoin-cli     && strip /opt/bitcoin/bin/bitcoind]: exit code: 2

更新 6:正确的端口似乎是 19000。

如果我使用端口 19001,我会在之后收到以下错误kit.awaitRunning()

INFO  org.bitcoinj.core.PeerSocketHandler - [127.0.0.1]:19001: Timed out

完整的日志输出可在此处获得。

4

1 回答 1

2

我还没有测试您的完整设置electrumx以及文件中ethereum存在的内容docker-compose,但是关于您的问题,以下步骤可以正常工作,我认为在您的完整设置中也可以。

我使用 docker 运行了一个基于ulamlabs/bitcoind-custom-regtest:latest您提供的图像的比特币节点:

docker run -p 18444:19000 -d ulamlabs/bitcoind-custom-regtest:latest

如您所见,我将图像内部端口公开为,19000默认端口。从我们的客户端的角度来看,通过这种设置,基本上看起来就像我们在主机中运行比特币守护程序一样。使用您的课程并按照您的指示提供端口也应该可以解决问题。RegTestParams18444LocalTestNetParams19000

然后,根据你在问题中提供的反馈,我在/root/.bitcoin/bitcoin.confusing bashand中手动编辑了比特币节点的守护进程配置vi

docker exec -it 0aa2e863cd9927 bash

并包括以下配置:

peerbloomfilters=1

重启容器后,我得到了一个新地址:

docker exec -it 0aa2e863cd9927 bitcoin-cli -regtest getnewaddress

假设新地址是您在问题中提供的地址:

2N23tWAFEtBtTgxNjBNmnwzsiPdLcNek181

然后,按照比特币文档中的建议,为了避免资金不足错误,我生成101了块到这个地址:

docker exec -it 0aa2e863cd9927 bitcoin-cli -regtest generatetoaddress 101 2N23tWAFEtBtTgxNjBNmnwzsiPdLcNek181 

我使用generatetoaddress而不是generate因为自比特币 0.19.0 以来该选项不再有效

接下来,我根据您提供的信息和Bitcoinj 库文档中的示例准备了一个简单的 Java 程序:

import java.io.File;

import org.bitcoinj.core.Address;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.kits.WalletAppKit;
import org.bitcoinj.params.RegTestParams;

public class Kit {

  public static void main(String[] args) {
    Kit kit  = new Kit();
    kit.run();
  }

  private synchronized void run(){
    NetworkParameters params = RegTestParams.get();
    WalletAppKit kit = new WalletAppKit(params, new File("."), "walletappkit-example");
    kit.connectToLocalHost();

    kit.startAsync();
    kit.awaitRunning();

    kit.wallet().addWatchedAddress(Address.fromString(params, "2N23tWAFEtBtTgxNjBNmnwzsiPdLcNek181"));

    kit.wallet().addCoinsReceivedEventListener((wallet, tx, prevBalance, newBalance) -> {
      System.out.println("-----> coins resceived: " + tx.getTxId());
    });

    while (true) {
      try {
        this.wait(2000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
}

我使用了一个简单的 while 循环来保持问题的运行;当然,在实际设置中可能没有必要,因为您似乎正在使用 Spring Boot。

然后,如果你向这个地址发送一些比特币:

docker exec -it 0aa2e863cd9927 bitcoin-cli -regtest sendtoaddress 2N23tWAFEtBtTgxNjBNmnwzsiPdLcNek181 0.00001
0f972642713c72ae0fe03fe51818b9ea4d483720b69b90e795f35eb80a587c26

应该调用监听器:

2021-11-09 23:51:20.537 INFO  [NioClientManager][Wallet] Received a pending transaction 0f972642713c72ae0fe03fe51818b9ea4d483720b69b90e795f35eb80a587c26 that spends 0.00 BTC from our own wallet, and sends us 0.00001 BTC
2021-11-09 23:51:20.537 INFO  [NioClientManager][Wallet] commitTx of 0f972642713c72ae0fe03fe51818b9ea4d483720b69b90e795f35eb80a587c26
...
2021-11-09 23:51:20.537 INFO  [NioClientManager][Wallet] ->pending: 0f972642713c72ae0fe03fe51818b9ea4d483720b69b90e795f35eb80a587c26
2021-11-09 23:51:20.537 INFO  [NioClientManager][Wallet] Estimated balance is now: 0.00001 BTC
-----> coins resceived: 0f972642713c72ae0fe03fe51818b9ea4d483720b69b90e795f35eb80a587c26
2021-11-09 23:51:20.538 INFO  [NioClientManager][WalletFiles] Saving wallet; last seen block is height 165, date 2021-11-09T22:50:48Z, hash 23451521947bc5ff098c088ae0fc445becca8837d39ee8f6dd88f2c47ad5ac23
2021-11-09 23:51:20.543 INFO  [NioClientManager][WalletFiles] Save completed in 4.736 ms

你提到的还有一个问题,我还没有机会测试,它正在创建一个新的 Docker 镜像,在该镜像中peerbloomfilters配置将被正确配置,而无需修改实际容器状态。我认为您指出的编译问题可能与此问题有关,基本上,容器没有足够的资源来执行该过程。如果您使用的是 macOS 和 Docker for Mac,请尝试调整容器可用的内存量,这可能会有所帮助。使用的基本alpine图像的变化也可以激发问题。我也会尝试深入研究这个问题。

于 2021-11-09T23:03:29.657 回答