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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Implemented `Debug` for `BlockValidationResult`, `BlockValidationStateRef`, `ProcessBlockHeaderresult` and `BlockCheckResult`, enabling inspection via `{:?}` in logs and test output.
- Added `#[must_use]` to `BlockCheckResult` and `ProcessBlockHeaderResult` to warn when validation results are silently ignored.
- Added `ScriptPubkeyExt::as_bytes` to return a zero-copy slice into kernel-managed memory. Unlike `to_bytes`, this does not allocate.
- Added `ChainParams::new_signet` and `ContextBuilder::signet` to configure a custom signet from a user-provided challenge.

### Changed
- The `verify` function's `flags` parameter now uses `ScriptVerificationFlags` instead of `u32`, making the type explicit in the public API.
Expand Down
3 changes: 3 additions & 0 deletions libbitcoinkernel-sys/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- New `btck_chain_parameters_create_signet` for creating chain parameters for a custom signet from a user-provided challenge.

## [0.3.0] - 2026-05-20

### Added
Expand Down
10 changes: 10 additions & 0 deletions libbitcoinkernel-sys/bitcoin/src/kernel/bitcoinkernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include <functional>
#include <list>
#include <memory>
#include <optional>
#include <span>
#include <stdexcept>
#include <string>
Expand Down Expand Up @@ -823,6 +824,15 @@ btck_ChainParameters* btck_chain_parameters_create(const btck_ChainType chain_ty
assert(false);
}

btck_ChainParameters* btck_chain_parameters_create_signet(const void* challenge, size_t challenge_len)
{
const uint8_t* p = static_cast<const uint8_t*>(challenge);
CChainParams::SigNetOptions options{
.challenge = std::vector<uint8_t>{p, p + challenge_len},
};
return btck_ChainParameters::ref(const_cast<CChainParams*>(CChainParams::SigNet(options).release()));
}

btck_ChainParameters* btck_chain_parameters_copy(const btck_ChainParameters* chain_parameters)
{
return btck_ChainParameters::copy(chain_parameters);
Expand Down
11 changes: 11 additions & 0 deletions libbitcoinkernel-sys/bitcoin/src/kernel/bitcoinkernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,17 @@ BITCOINKERNEL_API void btck_logging_connection_destroy(btck_LoggingConnection* l
BITCOINKERNEL_API btck_ChainParameters* BITCOINKERNEL_WARN_UNUSED_RESULT btck_chain_parameters_create(
btck_ChainType chain_type);

/**
* @brief Create a signet chain parameters struct with a user-provided
* challenge.
*
* @param[in] challenge The signet challenge value. Blocks must satisfy it in
* order to be valid.
* @return An allocated chain parameters opaque struct.
*/
BITCOINKERNEL_API btck_ChainParameters* BITCOINKERNEL_WARN_UNUSED_RESULT btck_chain_parameters_create_signet(
const void* challenge, size_t challenge_len) BITCOINKERNEL_ARG_NONNULL(1);

/**
* Copy the chain parameters.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1019,6 +1019,9 @@ class ChainParams : public Handle<btck_ChainParameters, btck_chain_parameters_co
ChainParams(ChainType chain_type)
: Handle{btck_chain_parameters_create(static_cast<btck_ChainType>(chain_type))} {}

ChainParams(std::span<const std::byte> signet_challenge)
: Handle{btck_chain_parameters_create_signet(signet_challenge.data(), signet_challenge.size())} {}

ConsensusParamsView GetConsensusParams() const
{
return ConsensusParamsView{btck_chain_parameters_get_consensus_params(get())};
Expand Down
11 changes: 9 additions & 2 deletions libbitcoinkernel-sys/bitcoin/src/test/kernel/test_kernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,12 @@ class TestKernelNotifications : public KernelNotifications

void WarningSetHandler(Warning warning, std::string_view message) override
{
std::cout << "Kernel warning is set: " << message << std::endl;
BOOST_FAIL("Received unexpected warning");
}

void WarningUnsetHandler(Warning warning) override
{
std::cout << "Kernel warning was unset." << std::endl;
BOOST_CHECK_EQUAL(Warning::LARGE_WORK_INVALID_CHAIN, warning);
}

void FlushErrorHandler(std::string_view error) override
Expand Down Expand Up @@ -651,6 +651,13 @@ BOOST_AUTO_TEST_CASE(logging_tests)
Logger logger{std::make_unique<TestLog>()};
}

BOOST_AUTO_TEST_CASE(btck_chainparams_tests)
{
ChainParams params_regtest{ChainType::REGTEST};
ChainParams params_signet{hex_string_to_byte_vec("51")};
CheckHandle(params_regtest, params_signet);
}

BOOST_AUTO_TEST_CASE(btck_context_tests)
{
{ // test default context
Expand Down
5 changes: 5 additions & 0 deletions libbitcoinkernel-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,11 @@ extern "C" {

pub fn btck_chain_parameters_create(chain_type: btck_ChainType) -> *mut btck_ChainParameters;

pub fn btck_chain_parameters_create_signet(
challenge: *const c_void,
challenge_len: usize,
) -> *mut btck_ChainParameters;

pub fn btck_chain_parameters_copy(
chain_parameters: *const btck_ChainParameters,
) -> *mut btck_ChainParameters;
Expand Down
78 changes: 74 additions & 4 deletions src/state/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,11 @@ use libbitcoinkernel_sys::{
btck_ChainParameters, btck_ChainType, btck_ChainType_MAINNET, btck_ChainType_REGTEST,
btck_ChainType_SIGNET, btck_ChainType_TESTNET, btck_ChainType_TESTNET_4, btck_Context,
btck_ContextOptions, btck_NotificationInterfaceCallbacks, btck_ValidationInterfaceCallbacks,
btck_chain_parameters_create, btck_chain_parameters_destroy, btck_context_create,
btck_context_destroy, btck_context_interrupt, btck_context_options_create,
btck_context_options_destroy, btck_context_options_set_chainparams,
btck_context_options_set_notifications, btck_context_options_set_validation_interface,
btck_chain_parameters_create, btck_chain_parameters_create_signet,
btck_chain_parameters_destroy, btck_context_create, btck_context_destroy,
btck_context_interrupt, btck_context_options_create, btck_context_options_destroy,
btck_context_options_set_chainparams, btck_context_options_set_notifications,
btck_context_options_set_validation_interface,
};

use crate::{
Expand Down Expand Up @@ -133,6 +134,35 @@ impl ChainParams {
inner: unsafe { btck_chain_parameters_create(btck_chain_type) },
}
}

/// Creates chain parameters for a custom signet with a user-provided challenge.
///
/// The signet challenge is the script that blocks must satisfy in order to be
/// considered valid, allowing private signets with their own block signers.
///
/// # Arguments
/// * `challenge` - The signet challenge value (a serialized script).
///
/// # Returns
/// A new [`ChainParams`] instance configured for the custom signet.
///
/// # Example
/// ```no_run
/// use bitcoinkernel::ChainParams;
///
/// let challenge = [0x51]; // OP_TRUE
/// let params = ChainParams::new_signet(&challenge);
/// ```
pub fn new_signet(challenge: &[u8]) -> ChainParams {
ChainParams {
inner: unsafe {
btck_chain_parameters_create_signet(
challenge.as_ptr() as *const c_void,
challenge.len(),
)
},
}
}
}

impl Drop for ChainParams {
Expand Down Expand Up @@ -456,6 +486,33 @@ impl ContextBuilder {
self
}

/// Configures the context for a custom signet.
///
/// Sets the chain parameters to a signet defined by the given challenge,
/// the script that blocks must satisfy in order to be considered valid.
///
/// # Arguments
/// * `challenge` - The signet challenge value (a serialized script).
///
/// # Returns
/// The builder instance for method chaining.
///
/// # Example
/// ```no_run
/// use bitcoinkernel::{ContextBuilder, KernelError};
///
/// let challenge = [0x51]; // OP_TRUE
/// let context = ContextBuilder::new()
/// .signet(&challenge)
/// .build()?;
/// # Ok::<(), KernelError>(())
/// ```
pub fn signet(self, challenge: &[u8]) -> ContextBuilder {
let chain_params = ChainParams::new_signet(challenge);
unsafe { btck_context_options_set_chainparams(self.inner, chain_params.inner) };
self
}

/// Registers a callback for block tip notifications.
///
/// The callback is invoked when the chain's tip is updated to a new block.
Expand Down Expand Up @@ -1099,6 +1156,12 @@ mod tests {
let _regtest_params = ChainParams::new(ChainType::Regtest);
}

#[test]
fn test_signet_params_creation() {
// OP_TRUE challenge - blocks are trivially valid.
let _params = ChainParams::new_signet(&[0x51]);
}

// Context tests
#[test]
fn test_context_creation_default() {
Expand Down Expand Up @@ -1130,6 +1193,13 @@ mod tests {
assert!(regtest.is_ok());
}

#[test]
fn test_context_creation_with_signet() {
// OP_TRUE challenge - blocks are trivially valid.
let signet = ContextBuilder::new().signet(&[0x51]).build();
assert!(signet.is_ok());
}

#[test]
fn test_context_interrupt() {
let context = ContextBuilder::new()
Expand Down
Loading