1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4
5use std::ffi::{CString, NulError};
6use std::fmt;
7use std::marker::PhantomData;
8use std::os::raw::{c_char, c_void};
9use std::sync::Arc;
10
11use libbitcoinkernel_sys_covenants::*;
12
13#[allow(clippy::unnecessary_cast)]
14pub const VERIFY_NONE: u32 = kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_NONE as u32;
15#[allow(clippy::unnecessary_cast)]
16pub const VERIFY_P2SH: u32 = kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_P2SH as u32;
17#[allow(clippy::unnecessary_cast)]
18pub const VERIFY_DERSIG: u32 = kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_DERSIG as u32;
19#[allow(clippy::unnecessary_cast)]
20pub const VERIFY_NULLDUMMY: u32 = kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_NULLDUMMY as u32;
21#[allow(clippy::unnecessary_cast)]
22pub const VERIFY_CHECKLOCKTIMEVERIFY: u32 =
23 kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_CHECKLOCKTIMEVERIFY as u32;
24#[allow(clippy::unnecessary_cast)]
25pub const VERIFY_CHECKSEQUENCEVERIFY: u32 =
26 kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_CHECKSEQUENCEVERIFY as u32;
27#[allow(clippy::unnecessary_cast)]
28pub const VERIFY_OP_CAT: u32 = kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_OP_CAT as u32;
29#[allow(clippy::unnecessary_cast)]
30pub const VERIFY_CHECKSIGFROMSTACK: u32 =
31 kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_CHECKSIGFROMSTACK as u32;
32#[allow(clippy::unnecessary_cast)]
33pub const VERIFY_CHECKTEMPLATEVERIFY: u32 =
34 kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_CHECKTEMPLATEVERIFY as u32;
35#[allow(clippy::unnecessary_cast)]
36pub const VERIFY_WITNESS: u32 = kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_WITNESS as u32;
37#[allow(clippy::unnecessary_cast)]
38pub const VERIFY_TAPROOT: u32 = kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_TAPROOT as u32;
39#[allow(clippy::unnecessary_cast)]
40pub const VERIFY_ALL: u32 = kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_ALL as u32;
41pub const VERIFY_ALL_PRE_TAPROOT: u32 = VERIFY_P2SH
42 | VERIFY_DERSIG
43 | VERIFY_NULLDUMMY
44 | VERIFY_CHECKLOCKTIMEVERIFY
45 | VERIFY_CHECKSEQUENCEVERIFY
46 | VERIFY_WITNESS;
47
48pub fn verify(
62 script_pubkey: &ScriptPubkey,
63 amount: Option<i64>,
64 tx_to: &Transaction,
65 input_index: u32,
66 flags: Option<u32>,
67 spent_outputs: &[TxOut],
68) -> Result<(), KernelError> {
69 let kernel_flags = if let Some(flag) = flags {
70 flag
71 } else {
72 VERIFY_ALL
73 };
74 let mut status = kernel_ScriptVerifyStatus_kernel_SCRIPT_VERIFY_OK;
75 let kernel_amount = amount.unwrap_or_default();
76 let kernel_spent_outputs: Vec<*const kernel_TransactionOutput> = spent_outputs
77 .iter()
78 .map(|utxo| utxo.inner as *const kernel_TransactionOutput)
79 .collect();
80
81 let spent_outputs_ptr = if kernel_spent_outputs.is_empty() {
82 std::ptr::null_mut()
83 } else {
84 kernel_spent_outputs.as_ptr() as *mut *const kernel_TransactionOutput
85 };
86
87 let ret = unsafe {
88 kernel_verify_script(
89 script_pubkey.inner,
90 kernel_amount,
91 tx_to.inner,
92 spent_outputs_ptr,
93 spent_outputs.len(),
94 input_index,
95 kernel_flags,
96 &mut status,
97 )
98 };
99
100 if !ret {
101 let err = match status {
102 kernel_ScriptVerifyStatus_kernel_SCRIPT_VERIFY_ERROR_TX_INPUT_INDEX => {
103 ScriptVerifyError::TxInputIndex
104 }
105 kernel_ScriptVerifyStatus_kernel_SCRIPT_VERIFY_ERROR_INVALID_FLAGS => {
106 ScriptVerifyError::InvalidFlags
107 }
108 kernel_ScriptVerifyStatus_kernel_SCRIPT_VERIFY_ERROR_INVALID_FLAGS_COMBINATION => {
109 ScriptVerifyError::InvalidFlagsCombination
110 }
111 kernel_ScriptVerifyStatus_kernel_SCRIPT_VERIFY_ERROR_SPENT_OUTPUTS_REQUIRED => {
112 ScriptVerifyError::SpentOutputsRequired
113 }
114 kernel_ScriptVerifyStatus_kernel_SCRIPT_VERIFY_ERROR_SPENT_OUTPUTS_MISMATCH => {
115 ScriptVerifyError::SpentOutputsMismatch
116 }
117 _ => ScriptVerifyError::Invalid,
118 };
119 Err(KernelError::ScriptVerify(err))
120 } else {
121 Ok(())
122 }
123}
124
125unsafe fn cast_string(c_str: *const c_char, len: usize) -> String {
126 if !c_str.is_null() {
127 let slice = std::slice::from_raw_parts(c_str as *const u8, len);
128 String::from_utf8_lossy(slice).into_owned()
129 } else {
130 "".to_string()
131 }
132}
133
134#[derive(Debug)]
137pub enum SynchronizationState {
138 INIT_REINDEX,
139 INIT_DOWNLOAD,
140 POST_INIT,
141}
142
143impl From<kernel_SynchronizationState> for SynchronizationState {
144 fn from(state: kernel_SynchronizationState) -> SynchronizationState {
145 match state {
146 kernel_SynchronizationState_kernel_INIT_DOWNLOAD => SynchronizationState::INIT_DOWNLOAD,
147 kernel_SynchronizationState_kernel_INIT_REINDEX => SynchronizationState::INIT_REINDEX,
148 kernel_SynchronizationState_kernel_POST_INIT => SynchronizationState::POST_INIT,
149 _ => panic!("Unexpected Synchronization state"),
150 }
151 }
152}
153
154pub enum KernelWarning {
156 UNKNOWN_NEW_RULES_ACTIVATED,
157 LARGE_WORK_INVALID_CHAIN,
158}
159
160impl From<kernel_Warning> for KernelWarning {
161 fn from(warning: kernel_Warning) -> KernelWarning {
162 match warning {
163 kernel_Warning_kernel_UNKNOWN_NEW_RULES_ACTIVATED => {
164 KernelWarning::UNKNOWN_NEW_RULES_ACTIVATED
165 }
166 kernel_Warning_kernel_LARGE_WORK_INVALID_CHAIN => {
167 KernelWarning::LARGE_WORK_INVALID_CHAIN
168 }
169 _ => panic!("Unexpected kernel warning"),
170 }
171 }
172}
173
174pub enum ChainType {
176 MAINNET,
177 TESTNET,
178 SIGNET,
179 REGTEST,
180}
181
182impl From<ChainType> for kernel_ChainType {
183 fn from(chain: ChainType) -> kernel_ChainType {
184 match chain {
185 ChainType::MAINNET => kernel_ChainType_kernel_CHAIN_TYPE_MAINNET,
186 ChainType::TESTNET => kernel_ChainType_kernel_CHAIN_TYPE_TESTNET,
187 ChainType::SIGNET => kernel_ChainType_kernel_CHAIN_TYPE_SIGNET,
188 ChainType::REGTEST => kernel_ChainType_kernel_CHAIN_TYPE_REGTEST,
189 }
190 }
191}
192
193pub trait BlockTip: Fn(SynchronizationState, BlockHash, f64) {}
195impl<F: Fn(SynchronizationState, BlockHash, f64)> BlockTip for F {}
196
197pub trait HeaderTip: Fn(SynchronizationState, i64, i64, bool) {}
199impl<F: Fn(SynchronizationState, i64, i64, bool)> HeaderTip for F {}
200
201pub trait Progress: Fn(String, i32, bool) {}
203impl<F: Fn(String, i32, bool)> Progress for F {}
204
205pub trait WarningSet: Fn(KernelWarning, String) {}
207impl<F: Fn(KernelWarning, String)> WarningSet for F {}
208
209pub trait WarningUnset: Fn(KernelWarning) {}
211impl<F: Fn(KernelWarning)> WarningUnset for F {}
212
213pub trait FlushError: Fn(String) {}
215impl<F: Fn(String)> FlushError for F {}
216
217pub trait FatalError: Fn(String) {}
219impl<F: Fn(String)> FatalError for F {}
220
221pub struct KernelNotificationInterfaceCallbacks {
223 pub kn_block_tip: Box<dyn BlockTip>,
224 pub kn_header_tip: Box<dyn HeaderTip>,
225 pub kn_progress: Box<dyn Progress>,
226 pub kn_warning_set: Box<dyn WarningSet>,
227 pub kn_warning_unset: Box<dyn WarningUnset>,
228 pub kn_flush_error: Box<dyn FlushError>,
229 pub kn_fatal_error: Box<dyn FatalError>,
230}
231
232unsafe extern "C" fn kn_block_tip_wrapper(
233 user_data: *mut c_void,
234 state: kernel_SynchronizationState,
235 block_index: *const kernel_BlockIndex,
236 verification_progress: f64,
237) {
238 let holder = &*(user_data as *mut KernelNotificationInterfaceCallbacks);
239 let hash = kernel_block_index_get_block_hash(block_index);
240 let res = BlockHash { hash: (*hash).hash };
241 kernel_block_hash_destroy(hash);
242 (holder.kn_block_tip)(state.into(), res, verification_progress);
243}
244
245unsafe extern "C" fn kn_header_tip_wrapper(
246 user_data: *mut c_void,
247 state: kernel_SynchronizationState,
248 height: i64,
249 timestamp: i64,
250 presync: bool,
251) {
252 let holder = &*(user_data as *mut KernelNotificationInterfaceCallbacks);
253 (holder.kn_header_tip)(state.into(), height, timestamp, presync);
254}
255
256unsafe extern "C" fn kn_progress_wrapper(
257 user_data: *mut c_void,
258 title: *const c_char,
259 title_len: usize,
260 progress_percent: i32,
261 resume_possible: bool,
262) {
263 let holder = &*(user_data as *mut KernelNotificationInterfaceCallbacks);
264 (holder.kn_progress)(
265 cast_string(title, title_len),
266 progress_percent,
267 resume_possible,
268 );
269}
270
271unsafe extern "C" fn kn_warning_set_wrapper(
272 user_data: *mut c_void,
273 warning: kernel_Warning,
274 message: *const c_char,
275 message_len: usize,
276) {
277 let holder = &*(user_data as *mut KernelNotificationInterfaceCallbacks);
278 (holder.kn_warning_set)(warning.into(), cast_string(message, message_len));
279}
280
281unsafe extern "C" fn kn_warning_unset_wrapper(user_data: *mut c_void, warning: kernel_Warning) {
282 let holder = &*(user_data as *mut KernelNotificationInterfaceCallbacks);
283 (holder.kn_warning_unset)(warning.into());
284}
285
286unsafe extern "C" fn kn_flush_error_wrapper(
287 user_data: *mut c_void,
288 message: *const c_char,
289 message_len: usize,
290) {
291 let holder = &*(user_data as *mut KernelNotificationInterfaceCallbacks);
292 (holder.kn_flush_error)(cast_string(message, message_len));
293}
294
295unsafe extern "C" fn kn_fatal_error_wrapper(
296 user_data: *mut c_void,
297 message: *const c_char,
298 message_len: usize,
299) {
300 let holder = &*(user_data as *mut KernelNotificationInterfaceCallbacks);
301 (holder.kn_fatal_error)(cast_string(message, message_len));
302}
303
304pub struct ChainParams {
306 inner: *mut kernel_ChainParameters,
307}
308
309unsafe impl Send for ChainParams {}
310unsafe impl Sync for ChainParams {}
311
312impl ChainParams {
313 pub fn new(chain_type: ChainType) -> ChainParams {
314 let kernel_chain_type = chain_type.into();
315 ChainParams {
316 inner: unsafe { kernel_chain_parameters_create(kernel_chain_type) },
317 }
318 }
319}
320
321impl Drop for ChainParams {
322 fn drop(&mut self) {
323 unsafe {
324 kernel_chain_parameters_destroy(self.inner);
325 }
326 }
327}
328
329pub trait BlockChecked: Fn(UnownedBlock, ValidationMode, BlockValidationResult) {}
331impl<F: Fn(UnownedBlock, ValidationMode, BlockValidationResult)> BlockChecked for F {}
332
333pub struct ValidationInterfaceCallbacks {
335 pub block_checked: Box<dyn BlockChecked>,
337}
338
339unsafe extern "C" fn vi_block_checked_wrapper(
340 user_data: *mut c_void,
341 block: *const kernel_BlockPointer,
342 stateIn: *const kernel_BlockValidationState,
343) {
344 let holder = &*(user_data as *mut ValidationInterfaceCallbacks);
345 let result = kernel_block_validation_state_get_block_validation_result(stateIn);
346 let mode = kernel_block_validation_state_get_validation_mode(stateIn);
347 (holder.block_checked)(UnownedBlock::new(block), mode.into(), result.into());
348}
349
350pub struct Context {
355 inner: *mut kernel_Context,
356 #[allow(dead_code)]
358 kn_callbacks: Option<Box<KernelNotificationInterfaceCallbacks>>,
359 #[allow(dead_code)]
360 vi_callbacks: Option<Box<ValidationInterfaceCallbacks>>,
361}
362
363unsafe impl Send for Context {}
364unsafe impl Sync for Context {}
365
366impl Context {
367 pub fn interrupt(&self) -> bool {
368 unsafe { kernel_context_interrupt(self.inner) }
369 }
370}
371
372impl Drop for Context {
373 fn drop(&mut self) {
374 unsafe {
375 kernel_context_destroy(self.inner);
376 }
377 }
378}
379
380pub struct ContextBuilder {
385 inner: *mut kernel_ContextOptions,
386 kn_callbacks: Option<Box<KernelNotificationInterfaceCallbacks>>,
387 vi_callbacks: Option<Box<ValidationInterfaceCallbacks>>,
388}
389
390impl Default for ContextBuilder {
391 fn default() -> Self {
392 Self::new()
393 }
394}
395
396impl ContextBuilder {
397 pub fn new() -> ContextBuilder {
398 ContextBuilder {
399 inner: unsafe { kernel_context_options_create() },
400 kn_callbacks: None,
401 vi_callbacks: None,
402 }
403 }
404
405 pub fn build(self) -> Result<Context, KernelError> {
411 let inner = unsafe { kernel_context_create(self.inner) };
412 if inner.is_null() {
413 return Err(KernelError::Internal("Invalid context.".to_string()));
414 }
415 unsafe { kernel_context_options_destroy(self.inner) };
416 Ok(Context {
417 inner,
418 kn_callbacks: self.kn_callbacks,
419 vi_callbacks: self.vi_callbacks,
420 })
421 }
422
423 pub fn kn_callbacks(
425 mut self,
426 kn_callbacks: Box<KernelNotificationInterfaceCallbacks>,
427 ) -> ContextBuilder {
428 let kn_pointer = Box::into_raw(kn_callbacks);
429 unsafe {
430 let holder = kernel_NotificationInterfaceCallbacks {
431 user_data: kn_pointer as *mut c_void,
432 block_tip: Some(kn_block_tip_wrapper),
433 header_tip: Some(kn_header_tip_wrapper),
434 progress: Some(kn_progress_wrapper),
435 warning_set: Some(kn_warning_set_wrapper),
436 warning_unset: Some(kn_warning_unset_wrapper),
437 flush_error: Some(kn_flush_error_wrapper),
438 fatal_error: Some(kn_fatal_error_wrapper),
439 };
440 kernel_context_options_set_notifications(self.inner, holder);
441 };
442 self.kn_callbacks = unsafe { Some(Box::from_raw(kn_pointer)) };
443 self
444 }
445
446 pub fn chain_type(self, chain_type: ChainType) -> ContextBuilder {
448 let chain_params = ChainParams::new(chain_type);
449 unsafe { kernel_context_options_set_chainparams(self.inner, chain_params.inner) };
450 self
451 }
452
453 pub fn validation_interface(
455 mut self,
456 vi_callbacks: Box<ValidationInterfaceCallbacks>,
457 ) -> ContextBuilder {
458 let vi_pointer = Box::into_raw(vi_callbacks);
459 unsafe {
460 let holder = kernel_ValidationInterfaceCallbacks {
461 user_data: vi_pointer as *mut c_void,
462 block_checked: Some(vi_block_checked_wrapper),
463 };
464 kernel_context_options_set_validation_interface(self.inner, holder);
465 }
466 self.vi_callbacks = unsafe { Some(Box::from_raw(vi_pointer)) };
467 self
468 }
469}
470
471#[derive(Debug)]
473pub enum KernelError {
474 Internal(String),
475 CStringCreationFailed(String),
476 InvalidOptions(String),
477 OutOfBounds,
478 ScriptVerify(ScriptVerifyError),
479}
480
481#[derive(Debug)]
483pub enum ScriptVerifyError {
484 TxInputIndex,
485 TxSizeMismatch,
486 TxDeserialize,
487 InvalidFlags,
488 InvalidFlagsCombination,
489 SpentOutputsMismatch,
490 SpentOutputsRequired,
491 Invalid,
492}
493
494impl From<NulError> for KernelError {
495 fn from(err: NulError) -> Self {
496 KernelError::CStringCreationFailed(err.to_string())
497 }
498}
499
500impl fmt::Display for KernelError {
501 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
502 match self {
503 KernelError::Internal(msg)
504 | KernelError::CStringCreationFailed(msg)
505 | KernelError::InvalidOptions(msg) => write!(f, "{msg}"),
506 _ => write!(f, "Error!"),
507 }
508 }
509}
510
511pub enum ValidationMode {
514 VALID,
515 INVALID,
516 ERROR,
517}
518
519impl From<kernel_ValidationMode> for ValidationMode {
520 fn from(mode: kernel_ValidationMode) -> Self {
521 match mode {
522 kernel_ValidationMode_kernel_VALIDATION_STATE_VALID => Self::VALID,
523 kernel_ValidationMode_kernel_VALIDATION_STATE_INVALID => Self::INVALID,
524 kernel_ValidationMode_kernel_VALIDATION_STATE_ERROR => Self::ERROR,
525 _ => ValidationMode::ERROR, }
527 }
528}
529
530pub enum BlockValidationResult {
532 RESULT_UNSET = 0,
534 CONSENSUS,
536 CACHED_INVALID,
538 INVALID_HEADER,
540 MUTATED,
542 MISSING_PREV,
544 INVALID_PREV,
546 TIME_FUTURE,
548 HEADER_LOW_WORK,
550}
551
552impl From<kernel_BlockValidationResult> for BlockValidationResult {
553 fn from(res: kernel_BlockValidationResult) -> Self {
554 match res {
555 kernel_BlockValidationResult_kernel_BLOCK_RESULT_UNSET => Self::RESULT_UNSET,
556 kernel_BlockValidationResult_kernel_BLOCK_CONSENSUS => Self::CONSENSUS,
557 kernel_BlockValidationResult_kernel_BLOCK_CACHED_INVALID => Self::CACHED_INVALID,
558 kernel_BlockValidationResult_kernel_BLOCK_INVALID_HEADER => Self::INVALID_HEADER,
559 kernel_BlockValidationResult_kernel_BLOCK_MUTATED => Self::MUTATED,
560 kernel_BlockValidationResult_kernel_BLOCK_MISSING_PREV => Self::MISSING_PREV,
561 kernel_BlockValidationResult_kernel_BLOCK_INVALID_PREV => Self::INVALID_PREV,
562 kernel_BlockValidationResult_kernel_BLOCK_TIME_FUTURE => Self::TIME_FUTURE,
563 kernel_BlockValidationResult_kernel_BLOCK_HEADER_LOW_WORK => Self::HEADER_LOW_WORK,
564 _ => Self::CONSENSUS,
565 }
566 }
567}
568
569#[derive(Debug, Clone)]
571pub struct ScriptPubkey {
572 inner: *mut kernel_ScriptPubkey,
573}
574
575unsafe impl Send for ScriptPubkey {}
576unsafe impl Sync for ScriptPubkey {}
577
578impl ScriptPubkey {
579 pub fn get(&self) -> Vec<u8> {
580 let script_pubkey = unsafe { kernel_script_pubkey_copy_data(self.inner) };
581 let res =
582 unsafe { std::slice::from_raw_parts((*script_pubkey).data, (*script_pubkey).size) }
583 .to_vec();
584 unsafe { kernel_byte_array_destroy(script_pubkey) };
585 res
586 }
587}
588
589impl TryFrom<&[u8]> for ScriptPubkey {
590 type Error = KernelError;
591
592 fn try_from(raw_script_pubkey: &[u8]) -> Result<Self, Self::Error> {
593 let inner = unsafe {
594 kernel_script_pubkey_create(raw_script_pubkey.as_ptr(), raw_script_pubkey.len())
595 };
596 if inner.is_null() {
597 return Err(KernelError::Internal(
598 "Failed to decode raw transaction".to_string(),
599 ));
600 }
601 Ok(ScriptPubkey { inner })
602 }
603}
604
605impl Drop for ScriptPubkey {
606 fn drop(&mut self) {
607 unsafe { kernel_script_pubkey_destroy(self.inner) }
608 }
609}
610
611#[derive(Debug, Clone)]
616pub struct TxOut {
617 inner: *mut kernel_TransactionOutput,
618}
619
620unsafe impl Send for TxOut {}
621unsafe impl Sync for TxOut {}
622
623impl TxOut {
624 pub fn new(script_pubkey: &ScriptPubkey, amount: i64) -> TxOut {
625 TxOut {
626 inner: unsafe { kernel_transaction_output_create(script_pubkey.inner, amount) },
627 }
628 }
629
630 pub fn get_value(&self) -> i64 {
632 unsafe { kernel_transaction_output_get_amount(self.inner) }
633 }
634
635 pub fn get_script_pubkey(&self) -> ScriptPubkey {
637 ScriptPubkey {
638 inner: unsafe { kernel_transaction_output_copy_script_pubkey(self.inner) },
639 }
640 }
641}
642
643impl Drop for TxOut {
644 fn drop(&mut self) {
645 unsafe { kernel_transaction_output_destroy(self.inner) }
646 }
647}
648
649pub struct Transaction {
651 inner: *mut kernel_Transaction,
652}
653
654unsafe impl Send for Transaction {}
655unsafe impl Sync for Transaction {}
656
657impl TryFrom<&[u8]> for Transaction {
658 type Error = KernelError;
659
660 fn try_from(raw_transaction: &[u8]) -> Result<Self, Self::Error> {
661 let inner =
662 unsafe { kernel_transaction_create(raw_transaction.as_ptr(), raw_transaction.len()) };
663 if inner.is_null() {
664 return Err(KernelError::Internal(
665 "Failed to decode raw transaction.".to_string(),
666 ));
667 }
668 Ok(Transaction { inner })
669 }
670}
671
672impl Drop for Transaction {
673 fn drop(&mut self) {
674 unsafe { kernel_transaction_destroy(self.inner) }
675 }
676}
677
678pub struct UnownedBlock {
680 inner: *const kernel_BlockPointer,
681}
682
683impl UnownedBlock {
684 fn new(block: *const kernel_BlockPointer) -> UnownedBlock {
685 UnownedBlock { inner: block }
686 }
687
688 pub fn get_hash(&self) -> BlockHash {
689 let hash = unsafe { kernel_block_pointer_get_hash(self.inner) };
690 let res = BlockHash {
691 hash: unsafe { (&*hash).hash },
692 };
693 unsafe { kernel_block_hash_destroy(hash) };
694 res
695 }
696}
697
698impl From<UnownedBlock> for Vec<u8> {
699 fn from(block: UnownedBlock) -> Self {
700 let raw_block = unsafe { kernel_block_pointer_copy_data(block.inner) };
701 let vec =
702 unsafe { std::slice::from_raw_parts((*raw_block).data, (*raw_block).size) }.to_vec();
703 unsafe { kernel_byte_array_destroy(raw_block) };
704 vec
705 }
706}
707
708pub struct Block {
710 inner: *mut kernel_Block,
711}
712
713unsafe impl Send for Block {}
714unsafe impl Sync for Block {}
715
716impl Block {
717 pub fn get_hash(&self) -> BlockHash {
718 let hash = unsafe { kernel_block_get_hash(self.inner) };
719 let res = BlockHash {
720 hash: unsafe { (&*hash).hash },
721 };
722 unsafe { kernel_block_hash_destroy(hash) };
723 res
724 }
725}
726
727impl From<Block> for Vec<u8> {
728 fn from(block: Block) -> Vec<u8> {
729 let raw_block = unsafe { kernel_block_copy_data(block.inner) };
730 let vec =
731 unsafe { std::slice::from_raw_parts((*raw_block).data, (*raw_block).size) }.to_vec();
732 unsafe { kernel_byte_array_destroy(raw_block) };
733 vec
734 }
735}
736
737impl TryFrom<&[u8]> for Block {
738 type Error = KernelError;
739
740 fn try_from(raw_block: &[u8]) -> Result<Self, Self::Error> {
741 let inner = unsafe { kernel_block_create(raw_block.as_ptr(), raw_block.len()) };
742 if inner.is_null() {
743 return Err(KernelError::Internal(
744 "Failed to de-serialize Block.".to_string(),
745 ));
746 }
747 Ok(Block { inner })
748 }
749}
750
751impl Drop for Block {
752 fn drop(&mut self) {
753 unsafe { kernel_block_destroy(self.inner) };
754 }
755}
756
757pub struct BlockIndex {
764 inner: *mut kernel_BlockIndex,
765 marker: PhantomData<ChainstateManager>,
766}
767
768unsafe impl Send for BlockIndex {}
769unsafe impl Sync for BlockIndex {}
770
771#[derive(Debug, Clone, Hash, Eq, PartialEq)]
773pub struct BlockHash {
774 pub hash: [u8; 32],
775}
776
777impl BlockIndex {
778 pub fn prev(self) -> Result<BlockIndex, KernelError> {
781 let inner = unsafe { kernel_block_index_get_previous(self.inner) };
782 if inner.is_null() {
783 return Err(KernelError::OutOfBounds);
784 }
785 unsafe { kernel_block_index_destroy(self.inner) };
786 Ok(BlockIndex {
787 inner,
788 marker: self.marker,
789 })
790 }
791
792 pub fn height(&self) -> i32 {
794 unsafe { kernel_block_index_get_height(self.inner) }
795 }
796
797 pub fn block_hash(&self) -> BlockHash {
799 let hash = unsafe { kernel_block_index_get_block_hash(self.inner) };
800 let res = BlockHash {
801 hash: unsafe { (&*hash).hash },
802 };
803 unsafe { kernel_block_hash_destroy(hash) };
804 res
805 }
806}
807
808impl Drop for BlockIndex {
809 fn drop(&mut self) {
810 unsafe { kernel_block_index_destroy(self.inner) };
811 }
812}
813
814pub struct BlockUndo {
818 inner: *mut kernel_BlockUndo,
819 pub n_tx_undo: usize,
820}
821unsafe impl Send for BlockUndo {}
822unsafe impl Sync for BlockUndo {}
823
824impl BlockUndo {
825 pub fn get_transaction_undo_size(&self, transaction_index: u64) -> u64 {
828 unsafe { kernel_block_undo_get_transaction_undo_size(self.inner, transaction_index) }
829 }
830
831 pub fn get_prevout_height_by_index(
833 &self,
834 transaction_index: u64,
835 prevout_index: u64,
836 ) -> Result<u32, KernelError> {
837 let height = unsafe {
838 kernel_block_undo_get_transaction_output_height_by_index(
839 self.inner,
840 transaction_index,
841 prevout_index,
842 )
843 };
844 if height == 0 {
845 return Err(KernelError::OutOfBounds);
846 }
847 Ok(height)
848 }
849
850 pub fn get_prevout_by_index(
852 &self,
853 transaction_index: u64,
854 prevout_index: u64,
855 ) -> Result<TxOut, KernelError> {
856 let prev_out = unsafe {
857 kernel_block_undo_copy_transaction_output_by_index(
858 self.inner,
859 transaction_index,
860 prevout_index,
861 )
862 };
863 if prev_out.is_null() {
864 return Err(KernelError::OutOfBounds);
865 }
866 let res = TxOut { inner: prev_out };
867 Ok(res)
868 }
869}
870
871impl Drop for BlockUndo {
872 fn drop(&mut self) {
873 unsafe { kernel_block_undo_destroy(self.inner) };
874 }
875}
876
877pub struct ChainstateManagerOptions {
879 inner: *mut kernel_ChainstateManagerOptions,
880}
881
882impl ChainstateManagerOptions {
883 pub fn new(context: &Context, data_dir: &str, blocks_dir: &str) -> Result<Self, KernelError> {
889 let c_data_dir = CString::new(data_dir)?;
890 let c_blocks_dir = CString::new(blocks_dir)?;
891 let inner = unsafe {
892 kernel_chainstate_manager_options_create(
893 context.inner,
894 c_data_dir.as_ptr(),
895 c_data_dir.as_bytes().len(),
896 c_blocks_dir.as_ptr(),
897 c_blocks_dir.as_bytes().len(),
898 )
899 };
900 if inner.is_null() {
901 return Err(KernelError::Internal(
902 "Failed to create chainstate manager options.".to_string(),
903 ));
904 }
905 Ok(Self { inner })
906 }
907
908 pub fn set_worker_threads(&self, worker_threads: i32) {
910 unsafe {
911 kernel_chainstate_manager_options_set_worker_threads_num(self.inner, worker_threads);
912 }
913 }
914
915 pub fn set_wipe_db(self, wipe_block_tree: bool, wipe_chainstate: bool) -> Self {
919 unsafe {
920 kernel_chainstate_manager_options_set_wipe_dbs(
921 self.inner,
922 wipe_block_tree,
923 wipe_chainstate,
924 );
925 }
926 self
927 }
928
929 pub fn set_block_tree_db_in_memory(self, block_tree_db_in_memory: bool) -> Self {
931 unsafe {
932 kernel_chainstate_manager_options_set_block_tree_db_in_memory(
933 self.inner,
934 block_tree_db_in_memory,
935 );
936 }
937 self
938 }
939
940 pub fn set_chainstate_db_in_memory(self, chainstate_db_in_memory: bool) -> Self {
942 unsafe {
943 kernel_chainstate_manager_options_set_chainstate_db_in_memory(
944 self.inner,
945 chainstate_db_in_memory,
946 );
947 }
948 self
949 }
950}
951
952impl Drop for ChainstateManagerOptions {
953 fn drop(&mut self) {
954 unsafe {
955 kernel_chainstate_manager_options_destroy(self.inner);
956 }
957 }
958}
959
960pub struct ChainstateManager {
969 inner: *mut kernel_ChainstateManager,
970 context: Arc<Context>,
971}
972
973unsafe impl Send for ChainstateManager {}
974unsafe impl Sync for ChainstateManager {}
975
976impl ChainstateManager {
977 pub fn new(
978 chainman_opts: ChainstateManagerOptions,
979 context: Arc<Context>,
980 ) -> Result<Self, KernelError> {
981 let inner = unsafe { kernel_chainstate_manager_create(context.inner, chainman_opts.inner) };
982 if inner.is_null() {
983 return Err(KernelError::Internal(
984 "Failed to create chainstate manager.".to_string(),
985 ));
986 }
987 Ok(Self { inner, context })
988 }
989
990 pub fn process_block(&self, block: &Block) -> (bool , bool ) {
997 let mut new_block = true;
998 let accepted = unsafe {
999 kernel_chainstate_manager_process_block(
1000 self.context.inner,
1001 self.inner,
1002 block.inner,
1003 &mut new_block,
1004 )
1005 };
1006 (accepted, new_block)
1007 }
1008
1009 pub fn import_blocks(&self) -> Result<(), KernelError> {
1014 if !unsafe {
1015 kernel_chainstate_manager_import_blocks(
1016 self.context.inner,
1017 self.inner,
1018 std::ptr::null_mut(),
1019 std::ptr::null_mut(),
1020 0,
1021 )
1022 } {
1023 return Err(KernelError::Internal(
1024 "Failed to import blocks.".to_string(),
1025 ));
1026 }
1027 Ok(())
1028 }
1029
1030 pub fn get_block_index_tip(&self) -> BlockIndex {
1033 BlockIndex {
1034 inner: unsafe { kernel_block_index_get_tip(self.context.inner, self.inner) },
1035 marker: PhantomData,
1036 }
1037 }
1038
1039 pub fn get_block_index_genesis(&self) -> BlockIndex {
1041 BlockIndex {
1042 inner: unsafe { kernel_block_index_get_genesis(self.context.inner, self.inner) },
1043 marker: PhantomData,
1044 }
1045 }
1046
1047 pub fn get_block_index_by_height(&self, block_height: i32) -> Result<BlockIndex, KernelError> {
1050 let inner = unsafe {
1051 kernel_block_index_get_by_height(self.context.inner, self.inner, block_height)
1052 };
1053 if inner.is_null() {
1054 return Err(KernelError::OutOfBounds);
1055 }
1056 Ok(BlockIndex {
1057 inner,
1058 marker: PhantomData,
1059 })
1060 }
1061
1062 pub fn get_block_index_by_hash(&self, hash: BlockHash) -> Result<BlockIndex, KernelError> {
1064 let mut block_hash = kernel_BlockHash { hash: hash.hash };
1065 let inner = unsafe {
1066 kernel_block_index_get_by_hash(self.context.inner, self.inner, &mut block_hash)
1067 };
1068 if inner.is_null() {
1069 return Err(KernelError::Internal(
1070 "Block index for the given block hash not found.".to_string(),
1071 ));
1072 }
1073 Ok(BlockIndex {
1074 inner,
1075 marker: PhantomData,
1076 })
1077 }
1078
1079 pub fn get_next_block_index(&self, block_index: BlockIndex) -> Result<BlockIndex, KernelError> {
1082 let inner = unsafe {
1083 kernel_block_index_get_next(self.context.inner, self.inner, block_index.inner)
1084 };
1085 if inner.is_null() {
1086 return Err(KernelError::OutOfBounds);
1087 }
1088 Ok(BlockIndex {
1089 inner,
1090 marker: PhantomData,
1091 })
1092 }
1093
1094 pub fn read_block_data(&self, block_index: &BlockIndex) -> Result<Block, KernelError> {
1096 let inner = unsafe { kernel_block_read(self.context.inner, self.inner, block_index.inner) };
1097 if inner.is_null() {
1098 return Err(KernelError::Internal("Failed to read block.".to_string()));
1099 }
1100 Ok(Block { inner })
1101 }
1102
1103 pub fn read_undo_data(&self, block_index: &BlockIndex) -> Result<BlockUndo, KernelError> {
1105 let inner =
1106 unsafe { kernel_block_undo_read(self.context.inner, self.inner, block_index.inner) };
1107 if inner.is_null() {
1108 return Err(KernelError::Internal(
1109 "Failed to read undo data.".to_string(),
1110 ));
1111 }
1112 let n_tx_undo = unsafe { kernel_block_undo_size(inner) }.try_into().unwrap();
1113 Ok(BlockUndo { inner, n_tx_undo })
1114 }
1115}
1116
1117impl Drop for ChainstateManager {
1118 fn drop(&mut self) {
1119 unsafe {
1120 kernel_chainstate_manager_destroy(self.inner, self.context.inner);
1121 }
1122 }
1123}
1124
1125pub trait Log {
1127 fn log(&self, message: &str);
1128}
1129
1130unsafe extern "C" fn log_callback<T: Log + 'static>(
1131 user_data: *mut c_void,
1132 message: *const c_char,
1133 message_len: usize,
1134) {
1135 let message = unsafe { cast_string(message, message_len) };
1136 let log = user_data as *mut T;
1137 (*log).log(&message);
1138}
1139
1140pub struct Logger<T> {
1144 log: T,
1145 inner: *mut kernel_LoggingConnection,
1146}
1147
1148impl<T> Drop for Logger<T> {
1149 fn drop(&mut self) {
1150 unsafe {
1151 kernel_logging_connection_destroy(self.inner);
1152 }
1153 }
1154}
1155
1156pub fn disable_logging() {
1158 unsafe {
1159 kernel_logging_disable();
1160 }
1161}
1162
1163impl<T: Log + 'static> Logger<T> {
1164 pub fn new(mut log: T) -> Result<Logger<T>, KernelError> {
1166 let options = kernel_LoggingOptions {
1167 log_timestamps: true,
1168 log_time_micros: false,
1169 log_threadnames: false,
1170 log_sourcelocations: false,
1171 always_print_category_levels: false,
1172 };
1173
1174 let inner = unsafe {
1175 kernel_logging_connection_create(
1176 Some(log_callback::<T>),
1177 &mut log as *mut T as *mut c_void,
1178 options,
1179 )
1180 };
1181
1182 if inner.is_null() {
1183 return Err(KernelError::Internal(
1184 "Failed to create new logging connection.".to_string(),
1185 ));
1186 }
1187
1188 Ok(Logger { log, inner })
1189 }
1190
1191 pub fn log(&self, message: &str) {
1193 self.log.log(message);
1194 }
1195}