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
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
/target
Cargo.lock
**/target
**/Cargo.lock
17 changes: 13 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
[workspace]
members = ["macro"]

[package]
name = "bitcoin-script"
version = "0.2.0"
authors = ["Matt Bell <mappum@gmail.com>", "Lukas George lukas@zerosync.org"]
version = "0.4.0"
authors = ["Lukas George <lukas@zerosync.org>"]
edition = "2021"
description = "Inline Bitcoin scripts"
license = "MIT"
repository = "https://github.com/FairgateLabs/rust-bitcoin-script"

[lib]
proc-macro = true
[features]
serde = ["dep:serde", "bitcoin/serde"]

[dependencies]
stdext = "0.3.3"
serde = { version = "1", features = ["derive"], optional = true }
bitcoin = "0.32.6"
quote = "1.0.30"
proc-macro-error = "1.0.4"
lazy_static = "1.4.0"
hex = "0.4.3"
proc-macro2 = "1.0.51"
script-macro = { path = "./macro" }
bitcoin-opcode-utils = { git = "https://github.com/FairgateLabs/rust-bitcoin-opcode-utils" }

[dev-dependencies]
bincode = "1.3.3"
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ SOFTWARE.
This project includes code with no license:

- Bitcoin scripts inline in Rust
- Original source: [bitcoin-script](https://github.com/BitVM/rust-bitcoin-script_old)
- License: None
- Original source: [bitcoin-script](https://github.com/BitVM/rust-bitcoin-script)
- License: MIT
38 changes: 25 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,14 @@
# bitcoin-script
# Bitvm Bitcoin Script

[![Rust](https://github.com/mappum/rust-bitcoin-script/workflows/Rust/badge.svg)](https://github.com/mappum/rust-bitcoin-script/actions?query=workflow%3ARust)
[![crates.io](https://img.shields.io/crates/v/bitcoin-script.svg)](https://crates.io/crates/bitcoin-script)
[![docs.rs](https://docs.rs/bitcoin-script/badge.svg)](https://docs.rs/bitcoin-script)

**Bitcoin scripts inline in Rust.**

---
Utilities used in the official [BitVM](https://github.com/BitVM/BitVM) implementation to generate Bitcoin Script. Heavily inspired by [rust-bitcoin-script's inline macro](https://github.com/mappum/rust-bitcoin-script).

## Usage

This crate exports a `script!` macro which can be used to build Bitcoin scripts. The macro returns the [`Script`](https://docs.rs/bitcoin/latest/bitcoin/struct.ScriptBuf.html) type from the [`bitcoin`](https://github.com/rust-bitcoin/rust-bitcoin) crate.
This crate exports a `script!` macro which can be used to build structured Bitcoin scripts and compiled to the [`Script`](https://docs.rs/bitcoin/latest/bitcoin/struct.ScriptBuf.html) type from the [`bitcoin`](https://github.com/rust-bitcoin/rust-bitcoin) crate.

**Example:**

```rust
#![feature(proc_macro_hygiene)]

use bitcoin_script::bitcoin_script;

let htlc_script = script! {
Expand All @@ -28,6 +20,8 @@ let htlc_script = script! {
OP_EQUALVERIFY
OP_CHECKSIG
};

let script_buf = htlc_script.compile();
```

### Syntax
Expand Down Expand Up @@ -77,6 +71,7 @@ Rust expressions of the following types are supported:
- [`bitcoin::PublicKey`](https://docs.rs/bitcoin/latest/bitcoin/struct.PublicKey.html)
- [`bitcoin::XOnlyPublicKey`](https://docs.rs/bitcoin/latest/bitcoin/struct.XOnlyPublicKey.html)
- [`bitcoin::ScriptBuf`](https://docs.rs/bitcoin/latest/bitcoin/struct.ScriptBuf.html)
- `StructuredScript`

```rust
let bytes = vec![1, 2, 3];
Expand All @@ -90,5 +85,22 @@ let script = script! {
};
```

### Optimality
Obsolete Opcodes are automatically removed when using the `optimal_opcodes` branch. E.g. a sequence of `OP_0 OP_ROLL` will be optimized away.
#### Conditional Scipt Generation

For-loops and if-else-statements are supported inside the script and will be unrolled when the scripts are generated.

```rust
let loop_count = 10;

let script = script! {
for i in 0..loop_count {
if i % 2 == 0 {
OP_ADD
} else {
OP_DUP
OP_ADD
}
}
};

```
16 changes: 16 additions & 0 deletions macro/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "script-macro"
version = "0.4.0"
authors = ["Lukas George lukas@zerosync.org"]
edition = "2021"
description = "Inline Bitcoin scripts proc_macro"
license = "MIT"

[lib]
proc-macro = true

[dependencies]
bitcoin = "0.32.5"
quote = "1.0.23"
proc-macro-error = "1.0.4"
proc-macro2 = "1.0.51"
7 changes: 4 additions & 3 deletions src/generate.rs → macro/src/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use proc_macro2::{Ident, Span, TokenStream};
use quote::{quote, quote_spanned};

pub fn generate(syntax: Vec<(Syntax, Span)>) -> TokenStream {
let mut tokens = quote!(pushable::Builder::new());
let mut tokens = quote!(::bitcoin_script::Script::new(
::bitcoin_script::function_name!()
));

for (item, span) in syntax {
let push = match item {
Expand All @@ -15,8 +17,7 @@ pub fn generate(syntax: Vec<(Syntax, Span)>) -> TokenStream {
};
tokens.extend(push);
}

tokens.extend(quote!(.0.into_script()));
// tokens.extend(quote! {.analyze_stack()}); // for debug
tokens
}

Expand Down
15 changes: 15 additions & 0 deletions macro/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
mod generate;
mod parse;

use generate::generate;
use parse::parse;
use proc_macro::TokenStream;
use proc_macro_error::{proc_macro_error, set_dummy};
use quote::quote;

#[proc_macro]
#[proc_macro_error]
pub fn script(tokens: TokenStream) -> TokenStream {
set_dummy(quote!((::bitcoin::Script::new())));
generate(parse(tokens.into())).into()
}
Loading
Loading