Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install build-essential cmake pkgconf python3 libevent-dev libboost-dev capnproto libcapnp-dev
- name: Checkout Bitcoin Core v30.0
run: git clone --depth 1 --branch 30.x https://github.com/bitcoin/bitcoin.git
- name: Build and Install Bitcoin Core
run: cd bitcoin && cmake -B build -DENABLE_IPC=ON -DENABLE_WALLET=OFF && cmake --build build -j 16
- name: Checkout Bitcoin Core
run: git clone --depth 1 --branch master https://github.com/bitcoin/bitcoin.git
- name: Build Bitcoin Core
run: cd bitcoin && cmake -B build -DENABLE_WALLET=OFF -DBUILD_TESTS=OFF && cmake --build build -j 16
- name: Run Bitcoin Core Daemon
run: cd bitcoin && ./build/bin/bitcoin-node -chain=regtest -ipcbind=unix -debug=ipc -daemon
run: cd bitcoin && ./build/bin/bitcoin node -chain=regtest -ipcbind=unix -server -debug=ipc -daemon
- name: Generate Blocks
run: cd bitcoin && ./build/bin/bitcoin rpc -regtest -rpcwait generatetodescriptor 101 "raw(51)"
- name: Run Test Suite
run: cargo test
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ capnpc = "0.25.0"
[dev-dependencies]
capnp-rpc = "0.25.0"
futures = "0.3.0"
tokio = { version = "1", features = ["rt-multi-thread", "net", "macros", "io-util"] }
serial_test = "3"
tokio = { version = "1", features = ["rt-multi-thread", "net", "macros", "io-util", "time"] }
tokio-util = { version = "0.7.16", features = ["compat"] }
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,52 @@ This project auto-generates the client code to interact with Bitcoin Core in Rus

To compile this crate your project must use a Rust compiler of **1.85** or higher.

## Building

```sh
cargo build
```

## Running integration tests

The integration tests connect to a running bitcoin node via IPC.

### 1. Build Bitcoin Core

```sh
cd /path/to/bitcoin
cmake -B build -DENABLE_WALLET=OFF -DBUILD_TESTS=OFF
cmake --build build -j$(nproc)
```

### 2. Start bitcoin

```sh
./build/bin/bitcoin node -chain=regtest -ipcbind=unix -server -debug=ipc -daemon
```

### 3. Generate blocks

The mining tests require chain height > 16. At height <= 16, `createNewBlock`
fails with `bad-cb-length` because the BIP34 height push is too short for the
coinbase scriptSig minimum.

```sh
./build/bin/bitcoin rpc -regtest -rpcwait generatetodescriptor 101 "raw(51)"
```

### 4. Run tests

```sh
cargo test
```

### 5. Stop bitcoin

```sh
./build/bin/bitcoin rpc -regtest stop
```

## License

Creative Commons 1.0 Universal
3 changes: 2 additions & 1 deletion capnp/init.capnp
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ using Mining = import "mining.capnp";
interface Init $Proxy.wrap("interfaces::Init") {
construct @0 (threadMap: Proxy.ThreadMap) -> (threadMap :Proxy.ThreadMap);
makeEcho @1 (context :Proxy.Context) -> (result :Echo.Echo);
makeMining @2 (context :Proxy.Context) -> (result :Mining.Mining);
makeMiningOld2 @2 () -> ();
makeMining @3 (context :Proxy.Context) -> (result :Mining.Mining);
}
48 changes: 31 additions & 17 deletions capnp/mining.capnp
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,19 @@ $Cxx.namespace("ipc::capnp::messages");
using Common = import "common.capnp";
using Proxy = import "proxy.capnp";

const maxMoney :Int64 = 2100000000000000;
const maxDouble :Float64 = 1.7976931348623157e308;
const defaultBlockReservedWeight :UInt32 = 8000;
const defaultCoinbaseOutputMaxAdditionalSigops :UInt32 = 400;

interface Mining $Proxy.wrap("interfaces::Mining") {
isTestChain @0 (context :Proxy.Context) -> (result: Bool);
isInitialBlockDownload @1 (context :Proxy.Context) -> (result: Bool);
getTip @2 (context :Proxy.Context) -> (result: Common.BlockRef, hasResult: Bool);
waitTipChanged @3 (context :Proxy.Context, currentTip: Data, timeout: Float64) -> (result: Common.BlockRef);
createNewBlock @4 (options: BlockCreateOptions) -> (result: BlockTemplate);
checkBlock @5 (block: Data, options: BlockCheckOptions) -> (reason: Text, debug: Text, result: Bool);
waitTipChanged @3 (context :Proxy.Context, currentTip: Data, timeout: Float64 = .maxDouble) -> (result: Common.BlockRef);
createNewBlock @4 (context :Proxy.Context, options: BlockCreateOptions, cooldown: Bool = true) -> (result: BlockTemplate);
checkBlock @5 (context :Proxy.Context, block: Data, options: BlockCheckOptions) -> (reason: Text, debug: Text, result: Bool);
interrupt @6 () -> ();
}

interface BlockTemplate $Proxy.wrap("interfaces::BlockTemplate") {
Expand All @@ -25,27 +31,35 @@ interface BlockTemplate $Proxy.wrap("interfaces::BlockTemplate") {
getBlock @2 (context: Proxy.Context) -> (result: Data);
getTxFees @3 (context: Proxy.Context) -> (result: List(Int64));
getTxSigops @4 (context: Proxy.Context) -> (result: List(Int64));
getCoinbaseTx @5 (context: Proxy.Context) -> (result: Data);
getCoinbaseCommitment @6 (context: Proxy.Context) -> (result: Data);
getWitnessCommitmentIndex @7 (context: Proxy.Context) -> (result: Int32);
getCoinbaseMerklePath @8 (context: Proxy.Context) -> (result: List(Data));
submitSolution @9 (context: Proxy.Context, version: UInt32, timestamp: UInt32, nonce: UInt32, coinbase :Data) -> (result: Bool);
waitNext @10 (context: Proxy.Context, options: BlockWaitOptions) -> (result: BlockTemplate);
interruptWait @11() -> ();
getCoinbaseTx @5 (context: Proxy.Context) -> (result: CoinbaseTx);
getCoinbaseMerklePath @6 (context: Proxy.Context) -> (result: List(Data));
submitSolution @7 (context: Proxy.Context, version: UInt32, timestamp: UInt32, nonce: UInt32, coinbase :Data) -> (result: Bool);
waitNext @8 (context: Proxy.Context, options: BlockWaitOptions) -> (result: BlockTemplate);
interruptWait @9() -> ();
}

struct BlockCreateOptions $Proxy.wrap("node::BlockCreateOptions") {
useMempool @0 :Bool $Proxy.name("use_mempool");
blockReservedWeight @1 :UInt64 $Proxy.name("block_reserved_weight");
coinbaseOutputMaxAdditionalSigops @2 :UInt64 $Proxy.name("coinbase_output_max_additional_sigops");
useMempool @0 :Bool = true $Proxy.name("use_mempool");
blockReservedWeight @1 :UInt64 = .defaultBlockReservedWeight $Proxy.name("block_reserved_weight");
coinbaseOutputMaxAdditionalSigops @2 :UInt64 = .defaultCoinbaseOutputMaxAdditionalSigops $Proxy.name("coinbase_output_max_additional_sigops");
}

struct BlockWaitOptions $Proxy.wrap("node::BlockWaitOptions") {
timeout @0 : Float64 $Proxy.name("timeout");
feeThreshold @1 : Int64 $Proxy.name("fee_threshold");
timeout @0 : Float64 = .maxDouble $Proxy.name("timeout");
feeThreshold @1 : Int64 = .maxMoney $Proxy.name("fee_threshold");
}

struct BlockCheckOptions $Proxy.wrap("node::BlockCheckOptions") {
checkMerkleRoot @0 :Bool $Proxy.name("check_merkle_root");
checkPow @1 :Bool $Proxy.name("check_pow");
checkMerkleRoot @0 :Bool = true $Proxy.name("check_merkle_root");
checkPow @1 :Bool = true $Proxy.name("check_pow");
}

struct CoinbaseTx $Proxy.wrap("node::CoinbaseTx") {
version @0 :UInt32 $Proxy.name("version");
sequence @1 :UInt32 $Proxy.name("sequence");
scriptSigPrefix @2 :Data $Proxy.name("script_sig_prefix");
witness @3 :Data $Proxy.name("witness");
blockRewardRemaining @4 :Int64 $Proxy.name("block_reward_remaining");
requiredOutputs @5 :List(Data) $Proxy.name("required_outputs");
lockTime @6 :UInt32 $Proxy.name("lock_time");
}
Loading