Skip to content

Commit 7364d13

Browse files
committed
add bitcoin prover
1 parent b4c6a99 commit 7364d13

File tree

141 files changed

+13839
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

141 files changed

+13839
-0
lines changed

src/bitcoin-prover/.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
target/*
2+
.venv/*
3+
*dev*
4+
*__pycache__*
5+
venv
6+
*blocks.json

src/bitcoin-prover/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Distributed Lab
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

src/bitcoin-prover/Nargo.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[workspace]
2+
name = "wrapless-prover"
3+
members = [
4+
"crates/blocks",
5+
"crates/script",
6+
"crates/utils",
7+
"crates/crypto",
8+
"crates/bvm",
9+
"crates/sign",
10+
"app/p2sh",
11+
"app/p2tr",
12+
"app/p2tr_script",
13+
"app/p2ms",
14+
"app/p2pkh",
15+
"app/p2pk",
16+
"app/p2sh_p2wpkh",
17+
"app/p2sh_p2wsh",
18+
"app/blocks_recursive/recursive_base",
19+
"app/blocks_recursive/recursive",
20+
]

src/bitcoin-prover/README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Bitcoin prover
2+
3+
This project contains implementations in Noir and corresponding Python generators that allow proving the validity of the Bitcoin block header chain and the possibility of using the corresponding output as the input of a transaction.
4+
5+
## Overview
6+
7+
The typical workflow is as follows:
8+
1. Python generators create configuration files.
9+
2. Noir code in the `app/` directory is compiled and executed.
10+
3. Proofs are generated and verified using the `bb` tool.
11+
4. All outputs are stored in the `target/` directory.
12+
13+
## Requirements
14+
15+
- [Noir](https://noir-lang.org/) `1.0.0-beta.6`
16+
- Python `3.12.3`
17+
- [bb](https://github.com/AztecProtocol/barretenberg) `0.84.0`
18+
19+
## Usage
20+
21+
> [!IMPORTANT]
22+
> All commands must be run from the root directory of the repository.
23+
24+
After running any script, you need to install the Python dependencies.
25+
To do that, create a virtual environment and install the dependencies from `requirements.txt` using the following commands:
26+
27+
```bash
28+
python3 -m venv ./generators/venv
29+
source ./generators/venv/bin/activate
30+
pip install -r requirements.txt
31+
```
32+
33+
To create the blocks proof run this command:
34+
```bash
35+
./scripts/blocks.sh [--config ./config.json --address 0x0000000000000000000000000000000000000000]
36+
```
37+
| Parameter | Description | Default |
38+
|------------|-------------|----------|
39+
| `--config` | Path to the configuration JSON file (see example `./generators/blocks/config.json`). | `./generators/blocks/config.json` |
40+
| `--address` | Ethereum address that will receive award (if the default address is set, anyone can receive the reward) | `0x0000000000000000000000000000000000000000` |
41+
42+
To create any spending proof, edit [config](generators/general/config.json) and run:
43+
```bash
44+
python3 -m generators.general.main
45+
```
46+
47+
## License
48+
49+
This project is licensed under the [MIT License](LICENSE).
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "recursive"
3+
type = "bin"
4+
5+
[dependencies]
6+
blocks_lib = { path = "../../../crates/blocks" }
7+
utils = { path = "../../../crates/utils" }

src/bitcoin-prover/app/blocks_recursive/recursive/Prover.toml

Lines changed: 22 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pub global HONK_VK_SIZE: u32 = 128;
2+
pub global HONK_PROOF_SIZE: u32 = 456;
3+
pub global HONK_IDENTIFIER: u32 = 1;
4+
pub global PUBLIC_INPUTS: u32 = 879;
5+
6+
pub global MERKLE_ROOT_ARRAY_LEN: u32 = 25;
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
mod constants;
2+
3+
use dep::std;
4+
use blocks_lib::{
5+
block::{BlockHeader, calc_merkle_state, get_block_hash, tagged_sha256},
6+
chain::check_chain,
7+
};
8+
use constants::{
9+
HONK_IDENTIFIER, HONK_PROOF_SIZE, HONK_VK_SIZE, MERKLE_ROOT_ARRAY_LEN, PUBLIC_INPUTS,
10+
};
11+
use utils::convert::{bytes_to_hex, hex_to_bytes};
12+
13+
fn main(
14+
verification_key: [Field; HONK_VK_SIZE],
15+
proof: [Field; HONK_PROOF_SIZE],
16+
public_inputs: [Field; PUBLIC_INPUTS],
17+
block: BlockHeader,
18+
prev_block: BlockHeader,
19+
address: [u8; 20],
20+
) -> pub ([u8; 32], [u32; 11], u32, u32, Field, [[u8; 32]; MERKLE_ROOT_ARRAY_LEN], u32, [u8; 32]) {
21+
std::verify_proof_with_type(verification_key, proof, public_inputs, 0x0, HONK_IDENTIFIER);
22+
23+
let mut prev_block_hash = [0; 32];
24+
for i in 0..32 {
25+
prev_block_hash[i] = public_inputs[i] as u8;
26+
}
27+
28+
let mut timestamps = [0; 11];
29+
for i in 0..11 {
30+
timestamps[i] = public_inputs[32 + i] as u32;
31+
}
32+
33+
let time_idx = public_inputs[43] as u32;
34+
35+
let last_block_height = public_inputs[44] as u32;
36+
37+
let chainwork = public_inputs[45];
38+
39+
let mut idx = 46;
40+
41+
let mut merkle_state = [[0; 32]; MERKLE_ROOT_ARRAY_LEN];
42+
43+
for i in 0..MERKLE_ROOT_ARRAY_LEN {
44+
for j in 0..32 {
45+
merkle_state[i][j] = public_inputs[idx] as u8;
46+
idx += 1;
47+
}
48+
}
49+
50+
let prev_timestamp = public_inputs[idx] as u32;
51+
idx += 1;
52+
53+
assert(bytes_to_hex(prev_block_hash) == get_block_hash(prev_block));
54+
55+
let checked = check_chain(
56+
block,
57+
prev_block,
58+
timestamps,
59+
time_idx,
60+
last_block_height,
61+
chainwork,
62+
prev_timestamp,
63+
);
64+
65+
assert(checked.0);
66+
67+
let block_hash = hex_to_bytes(get_block_hash(block));
68+
let address_commitment = tagged_sha256(
69+
"address",
70+
block_hash.as_slice().append(address).as_array::<52>(),
71+
);
72+
73+
let merkle_branch = tagged_sha256("leaf1", block_hash);
74+
75+
merkle_state = calc_merkle_state(merkle_state, merkle_branch);
76+
77+
(
78+
block_hash, checked.1, checked.2, checked.3, checked.4, merkle_state, checked.5,
79+
address_commitment,
80+
)
81+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "recursive_base"
3+
type = "bin"
4+
5+
[dependencies]
6+
blocks_lib = { path = "../../../crates/blocks" }
7+
utils = { path = "../../../crates/utils" }
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
address = ["0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"]
2+
3+
[block]
4+
version = "1"
5+
prev_block = "0000000000000000000000000000000000000000000000000000000000000000"
6+
merkle_root = "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
7+
timestamp = "1231006505"
8+
bits = "486604799"
9+
nonce = "2083236893"

0 commit comments

Comments
 (0)