Skip to content
Draft
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions Cargo-minimal.lock
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ dependencies = [
"bitcoin",
"bitcoinkernel",
"env_logger",
"hex",
"log",
"secp256k1",
"silentpayments",
Expand Down
1 change: 1 addition & 0 deletions Cargo-recent.lock
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ dependencies = [
"bitcoin",
"bitcoinkernel",
"env_logger",
"hex",
"log",
"secp256k1",
"silentpayments",
Expand Down
7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,10 @@ members = [
"fuzz",
"libbitcoinkernel-sys"
]

[features]
script-trace = ["libbitcoinkernel-sys/script-trace"]

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
9 changes: 9 additions & 0 deletions examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,19 @@ publish = false
name = "silentpaymentscanner"
path = "src/silentpaymentscanner.rs"

[[bin]]
name = "scripttrace"
path = "src/scripttrace.rs"
required-features = ["script-trace"]

[dependencies]
silentpayments = "0.1"
bitcoin = "0.31"
secp256k1 = "0.28"
env_logger = "0.11"
log = "0.4"
bitcoinkernel = { path = ".." }
hex = "0.4"

[features]
script-trace = ["bitcoinkernel/script-trace"]
82 changes: 82 additions & 0 deletions examples/src/scripttrace.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
use bitcoin::Opcode;
use bitcoinkernel::{
verify, KernelError, PrecomputedTransactionData, ScriptPubkey, ScriptTraceFrameKind,
ScriptTraceFrameRef, ScriptTracer, Transaction, TxOut, VERIFY_ALL_PRE_TAPROOT,
};

fn main() {
let _tracer = ScriptTracer::new(trace).expect("failed to register the script tracer");

// A plain old-style P2PKH spend.
verify_test(
"76a9144bfbaf6afb76cc5771bc6404810d1cc041a6933988ac",
"02000000013f7cebd65c27431a90bba7f796914fe8cc2ddfc3f2cbd6f7e5f2fc854534da95000000006b483045022100de1ac3bcdfb0332207c4a91f3832bd2c2915840165f876ab47c5f8996b971c3602201c6c053d750fadde599e6f5c4e1963df0f01fc0d97815e8157e3d59fe09ca30d012103699b464d1d8bc9e47d4fb1cdaa89a1c5783d68363c4dbc4b524ed3d857148617feffffff02836d3c01000000001976a914fc25d6d5c94003bf5b0c7b640a248e2c637fcfb088ac7ada8202000000001976a914fbed3d9b11183209a57999d54d59f67c019e756c88ac6acb0700",
0,
0,
)
.expect("verification failed");

verify_test(
// last hash byte changed 39 -> 38, so OP_EQUALVERIFY will fail
"76a9144bfbaf6afb76cc5771bc6404810d1cc041a6933888ac",
"02000000013f7cebd65c27431a90bba7f796914fe8cc2ddfc3f2cbd6f7e5f2fc854534da95000000006b483045022100de1ac3bcdfb0332207c4a91f3832bd2c2915840165f876ab47c5f8996b971c3602201c6c053d750fadde599e6f5c4e1963df0f01fc0d97815e8157e3d59fe09ca30d012103699b464d1d8bc9e47d4fb1cdaa89a1c5783d68363c4dbc4b524ed3d857148617feffffff02836d3c01000000001976a914fc25d6d5c94003bf5b0c7b640a248e2c637fcfb088ac7ada8202000000001976a914fbed3d9b11183209a57999d54d59f67c019e756c88ac6acb0700",
0,
0,
)
.expect_err("expected a script verification error");
}

fn trace(frame: ScriptTraceFrameRef<'_>) {
match frame.kind() {
ScriptTraceFrameKind::Begin => {
let script_len = frame.script().map(|script| script.len()).unwrap_or(0);
println!(
"== begin: {} byte script, sig_version {:?} ==",
script_len,
frame.sig_version()
);
}
ScriptTraceFrameKind::Step => {
println!(
"[step {}] opcode=0x{:02x} ({:?}) exec={} op_count={} stack_depth={}",
frame.opcode_pos(),
frame.opcode(),
Opcode::from(frame.opcode()),
frame.exec(),
frame.op_count(),
frame.stack().len()
);

for (i, item) in frame.stack().iter().enumerate() {
match item.to_bytes() {
Ok(bytes) if bytes.is_empty() => println!(" stack[{i}]: <empty>"),
Ok(bytes) => println!(" stack[{i}]: {}", hex::encode(bytes)),
Err(err) => println!(" stack[{i}]: <unavailable: {err}>"),
}
}
}
ScriptTraceFrameKind::End => {
println!("== end: script_error={} ==", frame.script_error());
}
}
}

fn verify_test(
spent: &str,
spending: &str,
amount: i64,
input_index: usize,
) -> Result<(), KernelError> {
let spent_script_pubkey =
ScriptPubkey::try_from(hex::decode(spent).unwrap().as_slice()).unwrap();
let spending_tx = Transaction::new(hex::decode(spending).unwrap().as_slice()).unwrap();
let tx_data = PrecomputedTransactionData::new(&spending_tx, &Vec::<TxOut>::new()).unwrap();
verify(
&spent_script_pubkey,
Some(amount),
&spending_tx,
input_index,
Some(VERIFY_ALL_PRE_TAPROOT),
&tx_data,
)
}
3 changes: 3 additions & 0 deletions libbitcoinkernel-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,6 @@ publish = true

[build-dependencies]
cc = "1.2"

[features]
script-trace = []
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ runs:
shell: bash
run: |
echo "BASE_ROOT_DIR=${{ runner.temp }}" >> "$GITHUB_ENV"
echo "BASE_BUILD_DIR=${{ runner.temp }}/build" >> "$GITHUB_ENV"
# Space and non-ASCII symbols mimic BASE_SCRATCH_DIR in ci/test/00_setup_env.sh,
# to test word-splitting and UTF-8 path handling on CI.
echo "BASE_BUILD_DIR=${{ runner.temp }}/build_ ₿🧪_" >> "$GITHUB_ENV"
echo "CCACHE_DIR=${{ runner.temp }}/ccache_dir" >> $GITHUB_ENV
echo "DEPENDS_DIR=${{ runner.temp }}/depends" >> "$GITHUB_ENV"
echo "BASE_CACHE=${{ runner.temp }}/depends/built" >> $GITHUB_ENV
Expand Down
52 changes: 41 additions & 11 deletions libbitcoinkernel-sys/bitcoin/.github/ci-windows-cross.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import argparse
import os
import re
import shlex
import subprocess
import sys
Expand All @@ -28,6 +29,31 @@ def print_version():
run([str(bitcoind), "-version"])


def check_imports():
bitcoind = Path.cwd() / "bin" / "bitcoind.exe"
output = run(
["dumpbin.exe", "/imports", str(bitcoind)],
capture_output=True,
text=True,
).stdout
dlls = re.findall(r"^\s*(\S+\.dll)\s*$", output, re.IGNORECASE | re.MULTILINE)
print("\n".join(dlls))

# Ensure the executable is linked against the expected C runtime.
dlls = {name.lower() for name in dlls}
uses_msvcrt = "msvcrt.dll" in dlls
uses_ucrt = any(name.startswith("api-ms-win-crt-") for name in dlls)
crt = os.environ["CRT"]
if crt == "msvcrt":
crt_ok = uses_msvcrt and not uses_ucrt
elif crt == "ucrt":
crt_ok = uses_ucrt and not uses_msvcrt
else:
sys.exit(f"Unexpected CRT value: {crt!r}")
if not crt_ok:
sys.exit(f"Imported DLLs do not match the expected {crt!r} C runtime.")


def check_manifests():
release_dir = Path.cwd() / "bin"
manifest_path = release_dir / "bitcoind.manifest"
Expand Down Expand Up @@ -99,23 +125,26 @@ def run_functional_tests():
f"--tmpdirprefix={workspace / '_ _'}",
"--combinedlogslen=99999999",
*shlex.split(os.environ.get("TEST_RUNNER_EXTRA", "").strip()),
# feature_unsupported_utxo_db.py fails on Windows because of emojis in the test data directory.
# Tests using ancient releases fail on Windows because of emojis in the test data directory.
"--exclude",
"feature_unsupported_utxo_db.py",
"--exclude",
"wallet_ancient_migration.py",
]
run(test_runner_cmd)

# Run feature_unsupported_utxo_db sequentially in ASCII-only tmp dir,
# because it is excluded above due to lack of UTF-8 support in the
# Run ancient release tests sequentially in ASCII-only tmp dir,
# because they are excluded above due to lack of UTF-8 support in the
# ancient release.
cmd_feature_unsupported_db = [
sys.executable,
str(workspace / "test" / "functional" / "feature_unsupported_utxo_db.py"),
"--previous-releases",
"--tmpdir",
str(Path(workspace) / "test_feature_unsupported_utxo_db"),
]
run(cmd_feature_unsupported_db)
for test_name in ["feature_unsupported_utxo_db", "wallet_ancient_migration"]:
cmd = [
sys.executable,
str(workspace / "test" / "functional" / f"{test_name}.py"),
"--previous-releases",
"--tmpdir",
str(workspace / f"test_{test_name}"),
]
run(cmd)


def run_unit_tests():
Expand All @@ -140,6 +169,7 @@ def main():
parser = argparse.ArgumentParser(description="Utility to run Windows CI steps.")
steps = list(map(lambda f: f.__name__, [
print_version,
check_imports,
check_manifests,
prepare_tests,
run_unit_tests,
Expand Down
5 changes: 5 additions & 0 deletions libbitcoinkernel-sys/bitcoin/.github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,11 @@ jobs:

- *IMPORT_VS_ENV

- name: Check imported DLLs
env:
CRT: ${{ matrix.crt }}
run: py -3 .github/ci-windows-cross.py check_imports

- name: Check executable manifests
run: py -3 .github/ci-windows-cross.py check_manifests

Expand Down
6 changes: 3 additions & 3 deletions libbitcoinkernel-sys/bitcoin/.tx/config
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[main]
host = https://www.transifex.com

[o:bitcoin:p:bitcoin:r:qt-translation-031x]
file_filter = src/qt/locale/bitcoin_<lang>.xlf
source_file = src/qt/locale/bitcoin_en.xlf
[o:bitcoin:p:bitcoin:r:qt-translation-032x]
file_filter = src/qt/locale/bitcoin_<lang>.ts
source_file = src/qt/locale/bitcoin_en.ts
source_lang = en
6 changes: 1 addition & 5 deletions libbitcoinkernel-sys/bitcoin/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -330,10 +330,6 @@ if(WIN32)
/Zc:__cplusplus
/sdl
)
target_link_options(core_interface INTERFACE
# We embed our own manifests.
/MANIFEST:NO
)
# Improve parallelism in MSBuild.
# See: https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/.
list(APPEND CMAKE_VS_GLOBALS "UseMultiToolTask=true")
Expand Down Expand Up @@ -471,7 +467,6 @@ if(MSVC)
try_append_cxx_flags("/wd4805" TARGET warn_interface SKIP_LINK)
target_compile_definitions(warn_interface INTERFACE
_CRT_SECURE_NO_WARNINGS
_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
)
else()
try_append_cxx_flags("-Wall" TARGET warn_interface SKIP_LINK)
Expand Down Expand Up @@ -601,6 +596,7 @@ endif()

if(REDUCE_EXPORTS)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
try_append_linker_flag("-Wl,--exclude-libs,ALL" TARGET core_interface)
try_append_linker_flag("-Wl,-no_exported_symbols" VAR CMAKE_EXE_LINKER_FLAGS)
endif()
Expand Down
3 changes: 2 additions & 1 deletion libbitcoinkernel-sys/bitcoin/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ fixes or code moves with actual code changes.

Make sure each individual commit is hygienic: that it builds successfully on its
own without warnings, errors, regressions, or test failures.
This means tests must be updated in the same commit that changes the behavior.
See the [developer notes](doc/developer-notes.md#commit-structure-for-tests)
for guidance on where test coverage belongs in a commit stack.

Commit messages should be verbose by default consisting of a short subject line
(50 chars max), a blank line and detailed explanatory text as separate
Expand Down
5 changes: 3 additions & 2 deletions libbitcoinkernel-sys/bitcoin/ci/lint/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# lief version should match the version used in Guix
lief==0.17.5
mypy==2.3.0
pyzmq==27.1.0
mypy==2.3.1
pyzmq==27.2.0
2 changes: 1 addition & 1 deletion libbitcoinkernel-sys/bitcoin/ci/lint_imagefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ FROM mirror.gcr.io/ubuntu:26.04
# https://docs.astral.sh/uv/reference/policies/versioning/
# https://docs.astral.sh/ruff/versioning/
COPY --from=ghcr.io/astral-sh/uv:0.11 /uv /uvx /bin/
COPY --from=ghcr.io/astral-sh/ruff:0.15 /ruff /bin/
COPY --from=ghcr.io/astral-sh/ruff:0.16 /ruff /bin/

COPY ./ci/retry/retry /ci_retry
COPY ./.python-version /.python-version
Expand Down
4 changes: 3 additions & 1 deletion libbitcoinkernel-sys/bitcoin/ci/test/00_setup_env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ BASE_READ_ONLY_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )"/../../ >/dev/null 2>
export BASE_READ_ONLY_DIR
# The destination root dir inside the container.
# This folder will also hold any SDKs.
# This folder only exists on the ci guest and will be a copy of BASE_READ_ONLY_DIR
# This folder only exists on the ci guest and will be a copy of BASE_READ_ONLY_DIR.
# This value is embedded in the CI image at build time; changing it requires
# rebuilding the image.
export BASE_ROOT_DIR="${BASE_ROOT_DIR:-/ci_container_base}"
# The depends dir.
# This folder exists only on the ci guest, and on the ci host as a volume.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export APT_LLVM_V="22"
export HOST=x86_64-unknown-freebsd
export FREEBSD_VERSION=15.1
export FREEBSD_SDK_BASENAME="freebsd-${HOST}-${FREEBSD_VERSION}"
export FREEBSD_SDK_SHA256=3768988b151c20f965679062b065c63a977d6bbb9f47fd83695ec2c40790c18f
export PACKAGES="clang-${APT_LLVM_V} llvm-${APT_LLVM_V} lld-${APT_LLVM_V}"
export SYSROOT="--sysroot=${DEPENDS_DIR}/SDKs/${FREEBSD_SDK_BASENAME}"
export DEP_OPTS="build_CC=clang build_CXX=clang++ \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@

export LC_ALL=C.UTF-8

export HOST=i686-pc-linux-gnu
export HOST=i686-linux-gnu
export DPKG_ADD_ARCH="i386"
export CONTAINER_NAME=ci_i686_no_multiprocess
export CI_IMAGE_NAME_TAG="mirror.gcr.io/ubuntu:26.04"
export CI_IMAGE_PLATFORM="linux/amd64"
export CI_CONTAINER_CAP="--security-opt seccomp=unconfined"
export PACKAGES="g++-multilib"
export PACKAGES="g++-i686-linux-gnu binutils-i686-linux-gnu libstdc++6:i386 libatomic1:i386"
export DEP_OPTS="DEBUG=1 NO_IPC=1"
export GOAL="install"
export CI_LIMIT_STACK_SIZE=1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export HOST=arm64-apple-darwin
export PACKAGES="clang lld llvm zip"
export XCODE_VERSION=26.1.1
export XCODE_BUILD_ID=17B100
export OSX_SDK_SHA256=9600fa93644df674ee916b5e2c8a6ba8dacf631996a65dc922d003b98b5ea3b1
export RUN_UNIT_TESTS=false
export RUN_FUNCTIONAL_TESTS=false
export GOAL="deploy"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export HOST=x86_64-apple-darwin
export PACKAGES="clang lld llvm zip"
export XCODE_VERSION=26.1.1
export XCODE_BUILD_ID=17B100
export OSX_SDK_SHA256=9600fa93644df674ee916b5e2c8a6ba8dacf631996a65dc922d003b98b5ea3b1
export RUN_UNIT_TESTS=false
export RUN_FUNCTIONAL_TESTS=false
export GOAL="deploy"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ export CONTAINER_NAME=ci_netbsd_cross
export CI_IMAGE_NAME_TAG="mirror.gcr.io/ubuntu:26.04"
export APT_LLVM_V="22"
export HOST=x86_64-unknown-netbsd
export NETBSD_VERSION=11.0_RC6
export NETBSD_VERSION=11.0
export NETBSD_SDK_BASENAME="netbsd-${HOST}-${NETBSD_VERSION}"
export NETBSD_SDK_SHA512SUMS="\
e8871bbedb8c3e0f696cc2596ced0c1e6497939f725fb3495b8d2c168430325907550f5f840f4dd0e3c73e6090394747c5e54762f2737de81177b984403522a8 base.tar.xz\n\
d8df6c07e9142dd8189292b769ac312f86185a6a278a752c18c840f7cd3a8dd3c535f9b0c8e06b62d556b2c75b97a01d786184e8a18f5e080ccd213591c8628f comp.tar.xz"
export PACKAGES="clang-${APT_LLVM_V} llvm-${APT_LLVM_V} lld-${APT_LLVM_V}"
export SYSROOT="--sysroot=${DEPENDS_DIR}/SDKs/${NETBSD_SDK_BASENAME}"
export DEP_OPTS="build_CC=clang build_CXX=clang++ \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ export APT_LLVM_V="22"
export HOST=x86_64-unknown-openbsd
export OPENBSD_VERSION=7.9
export OPENBSD_SDK_BASENAME="openbsd-${HOST}-${OPENBSD_VERSION}"
export OPENBSD_SDK_SHA256SUMS="\
923d2e03f06408d50d4848334398c6d04b5514dcac7917badfc178a0eef248de base79.tgz\n\
21a67af20aebcabf85b09f4206fc95b4cae0a35d42b154b976f0159f457724f9 comp79.tgz"
export PACKAGES="clang-${APT_LLVM_V} llvm-${APT_LLVM_V} lld-${APT_LLVM_V}"
export SYSROOT="--sysroot=${DEPENDS_DIR}/SDKs/${OPENBSD_SDK_BASENAME}"
export DEP_OPTS="NO_QT=1 build_CC=clang build_CXX=clang++ \
Expand Down
4 changes: 2 additions & 2 deletions libbitcoinkernel-sys/bitcoin/ci/test/00_setup_env_win64.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
export LC_ALL=C.UTF-8

export CONTAINER_NAME=ci_win64
export CI_IMAGE_NAME_TAG="mirror.gcr.io/debian:trixie" # Check that https://packages.debian.org/trixie/g++-mingw-w64-ucrt64 can cross-compile
export CI_IMAGE_NAME_TAG="mirror.gcr.io/ubuntu:26.04"
export HOST=x86_64-w64-mingw32ucrt
export PACKAGES="g++-mingw-w64-ucrt64 nsis"
export PACKAGES="nix-bin nix-setup-systemd"
export RUN_UNIT_TESTS=false
export RUN_FUNCTIONAL_TESTS=false
export GOAL="deploy"
Expand Down
Loading
Loading