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::*;
12
13pub const VERIFY_NONE: u32 = kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_NONE;
14pub const VERIFY_P2SH: u32 = kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_P2SH;
15pub const VERIFY_DERSIG: u32 = kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_DERSIG;
16pub const VERIFY_NULLDUMMY: u32 = kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_NULLDUMMY;
17pub const VERIFY_CHECKLOCKTIMEVERIFY: u32 =
18 kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_CHECKLOCKTIMEVERIFY;
19pub const VERIFY_CHECKSEQUENCEVERIFY: u32 =
20 kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_CHECKSEQUENCEVERIFY;
21pub const VERIFY_WITNESS: u32 = kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_WITNESS;
22pub const VERIFY_TAPROOT: u32 = kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_TAPROOT;
23pub const VERIFY_ALL_PRE_TAPROOT: u32 = VERIFY_P2SH
24 | VERIFY_DERSIG
25 | VERIFY_NULLDUMMY
26 | VERIFY_CHECKLOCKTIMEVERIFY
27 | VERIFY_CHECKSEQUENCEVERIFY
28 | VERIFY_WITNESS;
29
30pub fn verify(
44 script_pubkey: &ScriptPubkey,
45 amount: Option<i64>,
46 tx_to: &Transaction,
47 input_index: u32,
48 flags: Option<u32>,
49 spent_outputs: &[TxOut],
50) -> Result<(), KernelError> {
51 let kernel_flags = if let Some(flag) = flags {
52 flag
53 } else {
54 kernel_ScriptFlags_kernel_SCRIPT_FLAGS_VERIFY_ALL
55 };
56 let mut status = kernel_ScriptVerifyStatus_kernel_SCRIPT_VERIFY_OK;
57 let kernel_amount = if let Some(a) = amount { a } else { 0 };
58 let kernel_spent_outputs: Vec<*const kernel_TransactionOutput> = spent_outputs
59 .iter()
60 .map(|utxo| utxo.inner as *const kernel_TransactionOutput)
61 .collect();
62
63 let spent_outputs_ptr = if kernel_spent_outputs.is_empty() {
64 std::ptr::null_mut()
65 } else {
66 kernel_spent_outputs.as_ptr() as *mut *const kernel_TransactionOutput
67 };
68
69 let ret = unsafe {
70 kernel_verify_script(
71 script_pubkey.inner,
72 kernel_amount,
73 tx_to.inner,
74 spent_outputs_ptr,
75 spent_outputs.len(),
76 input_index,
77 kernel_flags,
78 &mut status,
79 )
80 };
81
82 if !ret {
83 let err = match status {
84 kernel_ScriptVerifyStatus_kernel_SCRIPT_VERIFY_ERROR_TX_INPUT_INDEX => {
85 ScriptVerifyError::TxInputIndex
86 }
87 kernel_ScriptVerifyStatus_kernel_SCRIPT_VERIFY_ERROR_INVALID_FLAGS => {
88 ScriptVerifyError::InvalidFlags
89 }
90 kernel_ScriptVerifyStatus_kernel_SCRIPT_VERIFY_ERROR_INVALID_FLAGS_COMBINATION => {
91 ScriptVerifyError::InvalidFlagsCombination
92 }
93 kernel_ScriptVerifyStatus_kernel_SCRIPT_VERIFY_ERROR_SPENT_OUTPUTS_REQUIRED => {
94 ScriptVerifyError::SpentOutputsRequired
95 }
96 kernel_ScriptVerifyStatus_kernel_SCRIPT_VERIFY_ERROR_SPENT_OUTPUTS_MISMATCH => {
97 ScriptVerifyError::SpentOutputsMismatch
98 }
99 _ => ScriptVerifyError::Invalid,
100 };
101 Err(KernelError::ScriptVerify(err))
102 } else {
103 Ok(())
104 }
105}
106
107unsafe fn cast_string(c_str: *const c_char, len: usize) -> String {
108 if !c_str.is_null() {
109 let slice = std::slice::from_raw_parts(c_str as *const u8, len);
110 String::from_utf8_lossy(slice).into_owned()
111 } else {
112 "".to_string()
113 }
114}
115
116#[derive(Debug)]
119pub enum SynchronizationState {
120 INIT_REINDEX,
121 INIT_DOWNLOAD,
122 POST_INIT,
123}
124
125impl From<kernel_SynchronizationState> for SynchronizationState {
126 fn from(state: kernel_SynchronizationState) -> SynchronizationState {
127 match state {
128 kernel_SynchronizationState_kernel_INIT_DOWNLOAD => SynchronizationState::INIT_DOWNLOAD,
129 kernel_SynchronizationState_kernel_INIT_REINDEX => SynchronizationState::INIT_REINDEX,
130 kernel_SynchronizationState_kernel_POST_INIT => SynchronizationState::POST_INIT,
131 _ => panic!("Unexpected Synchronization state"),
132 }
133 }
134}
135
136pub enum KernelWarning {
138 UNKNOWN_NEW_RULES_ACTIVATED,
139 LARGE_WORK_INVALID_CHAIN,
140}
141
142impl From<kernel_Warning> for KernelWarning {
143 fn from(warning: kernel_Warning) -> KernelWarning {
144 match warning {
145 kernel_Warning_kernel_UNKNOWN_NEW_RULES_ACTIVATED => {
146 KernelWarning::UNKNOWN_NEW_RULES_ACTIVATED
147 }
148 kernel_Warning_kernel_LARGE_WORK_INVALID_CHAIN => {
149 KernelWarning::LARGE_WORK_INVALID_CHAIN
150 }
151 _ => panic!("Unexpected kernel warning"),
152 }
153 }
154}
155
156pub enum ChainType {
158 MAINNET,
159 TESTNET,
160 SIGNET,
161 REGTEST,
162}
163
164impl From<ChainType> for kernel_ChainType {
165 fn from(chain: ChainType) -> kernel_ChainType {
166 match chain {
167 ChainType::MAINNET => kernel_ChainType_kernel_CHAIN_TYPE_MAINNET,
168 ChainType::TESTNET => kernel_ChainType_kernel_CHAIN_TYPE_TESTNET,
169 ChainType::SIGNET => kernel_ChainType_kernel_CHAIN_TYPE_SIGNET,
170 ChainType::REGTEST => kernel_ChainType_kernel_CHAIN_TYPE_REGTEST,
171 }
172 }
173}
174
175pub trait BlockTip: Fn(SynchronizationState, BlockHash) {}
177impl<F: Fn(SynchronizationState, BlockHash)> BlockTip for F {}
178
179pub trait HeaderTip: Fn(SynchronizationState, i64, i64, bool) {}
181impl<F: Fn(SynchronizationState, i64, i64, bool)> HeaderTip for F {}
182
183pub trait Progress: Fn(String, i32, bool) {}
185impl<F: Fn(String, i32, bool)> Progress for F {}
186
187pub trait WarningSet: Fn(KernelWarning, String) {}
189impl<F: Fn(KernelWarning, String)> WarningSet for F {}
190
191pub trait WarningUnset: Fn(KernelWarning) {}
193impl<F: Fn(KernelWarning)> WarningUnset for F {}
194
195pub trait FlushError: Fn(String) {}
197impl<F: Fn(String)> FlushError for F {}
198
199pub trait FatalError: Fn(String) {}
201impl<F: Fn(String)> FatalError for F {}
202
203pub struct KernelNotificationInterfaceCallbacks {
205 pub kn_block_tip: Box<dyn BlockTip>,
206 pub kn_header_tip: Box<dyn HeaderTip>,
207 pub kn_progress: Box<dyn Progress>,
208 pub kn_warning_set: Box<dyn WarningSet>,
209 pub kn_warning_unset: Box<dyn WarningUnset>,
210 pub kn_flush_error: Box<dyn FlushError>,
211 pub kn_fatal_error: Box<dyn FatalError>,
212}
213
214unsafe extern "C" fn kn_block_tip_wrapper(
215 user_data: *mut c_void,
216 state: kernel_SynchronizationState,
217 block_index: *const kernel_BlockIndex,
218) {
219 let holder = &*(user_data as *mut KernelNotificationInterfaceCallbacks);
220 let hash = kernel_block_index_get_block_hash(block_index);
221 let res = BlockHash {
222 hash: (&*hash).hash,
223 };
224 kernel_block_hash_destroy(hash);
225 (holder.kn_block_tip)(state.into(), res);
226}
227
228unsafe extern "C" fn kn_header_tip_wrapper(
229 user_data: *mut c_void,
230 state: kernel_SynchronizationState,
231 height: i64,
232 timestamp: i64,
233 presync: bool,
234) {
235 let holder = &*(user_data as *mut KernelNotificationInterfaceCallbacks);
236 (holder.kn_header_tip)(state.into(), height, timestamp, presync);
237}
238
239unsafe extern "C" fn kn_progress_wrapper(
240 user_data: *mut c_void,
241 title: *const c_char,
242 title_len: usize,
243 progress_percent: i32,
244 resume_possible: bool,
245) {
246 let holder = &*(user_data as *mut KernelNotificationInterfaceCallbacks);
247 (holder.kn_progress)(
248 cast_string(title, title_len),
249 progress_percent,
250 resume_possible,
251 );
252}
253
254unsafe extern "C" fn kn_warning_set_wrapper(
255 user_data: *mut c_void,
256 warning: kernel_Warning,
257 message: *const c_char,
258 message_len: usize,
259) {
260 let holder = &*(user_data as *mut KernelNotificationInterfaceCallbacks);
261 (holder.kn_warning_set)(warning.into(), cast_string(message, message_len));
262}
263
264unsafe extern "C" fn kn_warning_unset_wrapper(user_data: *mut c_void, warning: kernel_Warning) {
265 let holder = &*(user_data as *mut KernelNotificationInterfaceCallbacks);
266 (holder.kn_warning_unset)(warning.into());
267}
268
269unsafe extern "C" fn kn_flush_error_wrapper(
270 user_data: *mut c_void,
271 message: *const c_char,
272 message_len: usize,
273) {
274 let holder = &*(user_data as *mut KernelNotificationInterfaceCallbacks);
275 (holder.kn_flush_error)(cast_string(message, message_len));
276}
277
278unsafe extern "C" fn kn_fatal_error_wrapper(
279 user_data: *mut c_void,
280 message: *const c_char,
281 message_len: usize,
282) {
283 let holder = &*(user_data as *mut KernelNotificationInterfaceCallbacks);
284 (holder.kn_fatal_error)(cast_string(message, message_len));
285}
286
287pub struct ChainParams {
289 inner: *mut kernel_ChainParameters,
290}
291
292unsafe impl Send for ChainParams {}
293unsafe impl Sync for ChainParams {}
294
295impl ChainParams {
296 pub fn new(chain_type: ChainType) -> ChainParams {
297 let kernel_chain_type = chain_type.into();
298 ChainParams {
299 inner: unsafe { kernel_chain_parameters_create(kernel_chain_type) },
300 }
301 }
302}
303
304impl Drop for ChainParams {
305 fn drop(&mut self) {
306 unsafe {
307 kernel_chain_parameters_destroy(self.inner);
308 }
309 }
310}
311
312pub trait BlockChecked: Fn(UnownedBlock, ValidationMode, BlockValidationResult) {}
314impl<F: Fn(UnownedBlock, ValidationMode, BlockValidationResult)> BlockChecked for F {}
315
316pub struct ValidationInterfaceCallbacks {
318 pub block_checked: Box<dyn BlockChecked>,
320}
321
322unsafe extern "C" fn vi_block_checked_wrapper(
323 user_data: *mut c_void,
324 block: *const kernel_BlockPointer,
325 stateIn: *const kernel_BlockValidationState,
326) {
327 let holder = &*(user_data as *mut ValidationInterfaceCallbacks);
328 let result = kernel_get_block_validation_result_from_block_validation_state(stateIn);
329 let mode = kernel_get_validation_mode_from_block_validation_state(stateIn);
330 (holder.block_checked)(UnownedBlock::new(block), mode.into(), result.into());
331}
332
333pub struct Context {
338 inner: *mut kernel_Context,
339 #[allow(dead_code)]
341 kn_callbacks: Option<Box<KernelNotificationInterfaceCallbacks>>,
342 #[allow(dead_code)]
343 vi_callbacks: Option<Box<ValidationInterfaceCallbacks>>,
344}
345
346unsafe impl Send for Context {}
347unsafe impl Sync for Context {}
348
349impl Context {
350 pub fn interrupt(&self) -> bool {
351 unsafe { kernel_context_interrupt(self.inner) }
352 }
353}
354
355impl Drop for Context {
356 fn drop(&mut self) {
357 unsafe {
358 kernel_context_destroy(self.inner);
359 }
360 }
361}
362
363pub struct ContextBuilder {
368 inner: *mut kernel_ContextOptions,
369 kn_callbacks: Option<Box<KernelNotificationInterfaceCallbacks>>,
370 vi_callbacks: Option<Box<ValidationInterfaceCallbacks>>,
371}
372
373impl ContextBuilder {
374 pub fn new() -> ContextBuilder {
375 let context = ContextBuilder {
376 inner: unsafe { kernel_context_options_create() },
377 kn_callbacks: None,
378 vi_callbacks: None,
379 };
380 context
381 }
382
383 pub fn build(self) -> Result<Context, KernelError> {
389 let inner = unsafe { kernel_context_create(self.inner) };
390 if inner.is_null() {
391 return Err(KernelError::Internal("Invalid context.".to_string()));
392 }
393 unsafe { kernel_context_options_destroy(self.inner) };
394 Ok(Context {
395 inner,
396 kn_callbacks: self.kn_callbacks,
397 vi_callbacks: self.vi_callbacks,
398 })
399 }
400
401 pub fn kn_callbacks(
403 mut self,
404 kn_callbacks: Box<KernelNotificationInterfaceCallbacks>,
405 ) -> ContextBuilder {
406 let kn_pointer = Box::into_raw(kn_callbacks);
407 unsafe {
408 let holder = kernel_NotificationInterfaceCallbacks {
409 user_data: kn_pointer as *mut c_void,
410 block_tip: Some(kn_block_tip_wrapper),
411 header_tip: Some(kn_header_tip_wrapper),
412 progress: Some(kn_progress_wrapper),
413 warning_set: Some(kn_warning_set_wrapper),
414 warning_unset: Some(kn_warning_unset_wrapper),
415 flush_error: Some(kn_flush_error_wrapper),
416 fatal_error: Some(kn_fatal_error_wrapper),
417 };
418 kernel_context_options_set_notifications(self.inner, holder);
419 };
420 self.kn_callbacks = unsafe { Some(Box::from_raw(kn_pointer)) };
421 self
422 }
423
424 pub fn chain_type(self, chain_type: ChainType) -> ContextBuilder {
426 let chain_params = ChainParams::new(chain_type);
427 unsafe { kernel_context_options_set_chainparams(self.inner, chain_params.inner) };
428 self
429 }
430
431 pub fn validation_interface(
433 mut self,
434 vi_callbacks: Box<ValidationInterfaceCallbacks>,
435 ) -> ContextBuilder {
436 let vi_pointer = Box::into_raw(vi_callbacks);
437 unsafe {
438 let holder = kernel_ValidationInterfaceCallbacks {
439 user_data: vi_pointer as *mut c_void,
440 block_checked: Some(vi_block_checked_wrapper),
441 };
442 kernel_context_options_set_validation_interface(self.inner, holder);
443 }
444 self.vi_callbacks = unsafe { Some(Box::from_raw(vi_pointer)) };
445 self
446 }
447}
448
449#[derive(Debug)]
451pub enum KernelError {
452 Internal(String),
453 CStringCreationFailed(String),
454 InvalidOptions(String),
455 OutOfBounds,
456 ScriptVerify(ScriptVerifyError),
457}
458
459#[derive(Debug)]
461pub enum ScriptVerifyError {
462 TxInputIndex,
463 TxSizeMismatch,
464 TxDeserialize,
465 InvalidFlags,
466 InvalidFlagsCombination,
467 SpentOutputsMismatch,
468 SpentOutputsRequired,
469 Invalid,
470}
471
472impl From<NulError> for KernelError {
473 fn from(err: NulError) -> Self {
474 KernelError::CStringCreationFailed(err.to_string())
475 }
476}
477
478impl fmt::Display for KernelError {
479 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
480 match self {
481 KernelError::Internal(msg)
482 | KernelError::CStringCreationFailed(msg)
483 | KernelError::InvalidOptions(msg) => write!(f, "{}", msg),
484 _ => write!(f, "Error!"),
485 }
486 }
487}
488
489pub enum ValidationMode {
492 VALID,
493 INVALID,
494 ERROR,
495}
496
497impl From<kernel_ValidationMode> for ValidationMode {
498 fn from(mode: kernel_ValidationMode) -> Self {
499 match mode {
500 kernel_ValidationMode_kernel_VALIDATION_STATE_VALID => Self::VALID,
501 kernel_ValidationMode_kernel_VALIDATION_STATE_INVALID => Self::INVALID,
502 kernel_ValidationMode_kernel_VALIDATION_STATE_ERROR => Self::ERROR,
503 _ => ValidationMode::ERROR, }
505 }
506}
507
508pub enum BlockValidationResult {
510 RESULT_UNSET = 0,
512 CONSENSUS,
514 CACHED_INVALID,
516 INVALID_HEADER,
518 MUTATED,
520 MISSING_PREV,
522 INVALID_PREV,
524 TIME_FUTURE,
526 HEADER_LOW_WORK,
528}
529
530impl From<kernel_BlockValidationResult> for BlockValidationResult {
531 fn from(res: kernel_BlockValidationResult) -> Self {
532 match res {
533 kernel_BlockValidationResult_kernel_BLOCK_RESULT_UNSET => Self::RESULT_UNSET,
534 kernel_BlockValidationResult_kernel_BLOCK_CONSENSUS => Self::CONSENSUS,
535 kernel_BlockValidationResult_kernel_BLOCK_CACHED_INVALID => Self::CACHED_INVALID,
536 kernel_BlockValidationResult_kernel_BLOCK_INVALID_HEADER => Self::INVALID_HEADER,
537 kernel_BlockValidationResult_kernel_BLOCK_MUTATED => Self::MUTATED,
538 kernel_BlockValidationResult_kernel_BLOCK_MISSING_PREV => Self::MISSING_PREV,
539 kernel_BlockValidationResult_kernel_BLOCK_INVALID_PREV => Self::INVALID_PREV,
540 kernel_BlockValidationResult_kernel_BLOCK_TIME_FUTURE => Self::TIME_FUTURE,
541 kernel_BlockValidationResult_kernel_BLOCK_HEADER_LOW_WORK => Self::HEADER_LOW_WORK,
542 _ => Self::CONSENSUS,
543 }
544 }
545}
546
547#[derive(Debug, Clone)]
549pub struct ScriptPubkey {
550 inner: *mut kernel_ScriptPubkey,
551}
552
553unsafe impl Send for ScriptPubkey {}
554unsafe impl Sync for ScriptPubkey {}
555
556impl ScriptPubkey {
557 pub fn get(&self) -> Vec<u8> {
558 let script_pubkey = unsafe { kernel_copy_script_pubkey_data(self.inner) };
559 let res = unsafe {
560 std::slice::from_raw_parts(
561 (*script_pubkey).data,
562 (*script_pubkey).size.try_into().unwrap(),
563 )
564 }
565 .to_vec();
566 unsafe { kernel_byte_array_destroy(script_pubkey) };
567 res
568 }
569}
570
571impl TryFrom<&[u8]> for ScriptPubkey {
572 type Error = KernelError;
573
574 fn try_from(raw_script_pubkey: &[u8]) -> Result<Self, Self::Error> {
575 let inner = unsafe {
576 kernel_script_pubkey_create(raw_script_pubkey.as_ptr(), raw_script_pubkey.len())
577 };
578 if inner.is_null() {
579 return Err(KernelError::Internal(
580 "Failed to decode raw transaction".to_string(),
581 ));
582 }
583 Ok(ScriptPubkey { inner })
584 }
585}
586
587impl Drop for ScriptPubkey {
588 fn drop(&mut self) {
589 unsafe { kernel_script_pubkey_destroy(self.inner) }
590 }
591}
592
593#[derive(Debug, Clone)]
598pub struct TxOut {
599 inner: *mut kernel_TransactionOutput,
600}
601
602unsafe impl Send for TxOut {}
603unsafe impl Sync for TxOut {}
604
605impl TxOut {
606 pub fn new(script_pubkey: &ScriptPubkey, amount: i64) -> TxOut {
607 TxOut {
608 inner: unsafe { kernel_transaction_output_create(script_pubkey.inner, amount) },
609 }
610 }
611
612 pub fn get_value(&self) -> i64 {
614 unsafe { kernel_get_transaction_output_amount(self.inner) }
615 }
616
617 pub fn get_script_pubkey(&self) -> ScriptPubkey {
619 ScriptPubkey {
620 inner: unsafe { kernel_copy_script_pubkey_from_output(self.inner) },
621 }
622 }
623}
624
625impl Drop for TxOut {
626 fn drop(&mut self) {
627 unsafe { kernel_transaction_output_destroy(self.inner) }
628 }
629}
630
631pub struct Transaction {
633 inner: *mut kernel_Transaction,
634}
635
636unsafe impl Send for Transaction {}
637unsafe impl Sync for Transaction {}
638
639impl TryFrom<&[u8]> for Transaction {
640 type Error = KernelError;
641
642 fn try_from(raw_transaction: &[u8]) -> Result<Self, Self::Error> {
643 let inner =
644 unsafe { kernel_transaction_create(raw_transaction.as_ptr(), raw_transaction.len()) };
645 if inner.is_null() {
646 return Err(KernelError::Internal(
647 "Failed to decode raw transaction.".to_string(),
648 ));
649 }
650 Ok(Transaction { inner })
651 }
652}
653
654impl Drop for Transaction {
655 fn drop(&mut self) {
656 unsafe { kernel_transaction_destroy(self.inner) }
657 }
658}
659
660pub struct UnownedBlock {
662 inner: *const kernel_BlockPointer,
663}
664
665impl UnownedBlock {
666 fn new(block: *const kernel_BlockPointer) -> UnownedBlock {
667 UnownedBlock { inner: block }
668 }
669
670 pub fn get_hash(&self) -> BlockHash {
671 let hash = unsafe { kernel_block_pointer_get_hash(self.inner) };
672 let res = BlockHash {
673 hash: unsafe { (&*hash).hash },
674 };
675 unsafe { kernel_block_hash_destroy(hash) };
676 return res;
677 }
678}
679
680impl Into<Vec<u8>> for UnownedBlock {
681 fn into(self) -> Vec<u8> {
682 let raw_block = unsafe { kernel_copy_block_pointer_data(self.inner) };
683 let vec = unsafe {
684 std::slice::from_raw_parts((*raw_block).data, (*raw_block).size.try_into().unwrap())
685 }
686 .to_vec();
687 unsafe { kernel_byte_array_destroy(raw_block) };
688 vec
689 }
690}
691
692pub struct Block {
694 inner: *mut kernel_Block,
695}
696
697unsafe impl Send for Block {}
698unsafe impl Sync for Block {}
699
700impl Block {
701 pub fn get_hash(&self) -> BlockHash {
702 let hash = unsafe { kernel_block_get_hash(self.inner) };
703 let res = BlockHash {
704 hash: unsafe { (&*hash).hash },
705 };
706 unsafe { kernel_block_hash_destroy(hash) };
707 return res;
708 }
709}
710
711impl Into<Vec<u8>> for Block {
712 fn into(self) -> Vec<u8> {
713 let raw_block = unsafe { kernel_copy_block_data(self.inner) };
714 let vec = unsafe {
715 std::slice::from_raw_parts((*raw_block).data, (*raw_block).size.try_into().unwrap())
716 }
717 .to_vec();
718 unsafe { kernel_byte_array_destroy(raw_block) };
719 vec
720 }
721}
722
723impl TryFrom<&[u8]> for Block {
724 type Error = KernelError;
725
726 fn try_from(raw_block: &[u8]) -> Result<Self, Self::Error> {
727 let inner = unsafe { kernel_block_create(raw_block.as_ptr(), raw_block.len()) };
728 if inner.is_null() {
729 return Err(KernelError::Internal(
730 "Failed to de-serialize Block.".to_string(),
731 ));
732 }
733 Ok(Block { inner })
734 }
735}
736
737impl Drop for Block {
738 fn drop(&mut self) {
739 unsafe { kernel_block_destroy(self.inner) };
740 }
741}
742
743pub struct BlockIndex {
750 inner: *mut kernel_BlockIndex,
751 marker: PhantomData<ChainstateManager>,
752}
753
754unsafe impl Send for BlockIndex {}
755unsafe impl Sync for BlockIndex {}
756
757#[derive(Debug, Clone, Hash, Eq, PartialEq)]
759pub struct BlockHash {
760 pub hash: [u8; 32],
761}
762
763impl BlockIndex {
764 pub fn prev(self) -> Result<BlockIndex, KernelError> {
767 let inner = unsafe { kernel_get_previous_block_index(self.inner) };
768 if inner.is_null() {
769 return Err(KernelError::OutOfBounds);
770 }
771 unsafe { kernel_block_index_destroy(self.inner) };
772 Ok(BlockIndex {
773 inner,
774 marker: self.marker,
775 })
776 }
777
778 pub fn height(&self) -> i32 {
780 unsafe { kernel_block_index_get_height(self.inner) }
781 }
782
783 pub fn block_hash(&self) -> BlockHash {
785 let hash = unsafe { kernel_block_index_get_block_hash(self.inner) };
786 let res = BlockHash {
787 hash: unsafe { (&*hash).hash },
788 };
789 unsafe { kernel_block_hash_destroy(hash) };
790 return res;
791 }
792}
793
794impl<'a> Drop for BlockIndex {
795 fn drop(&mut self) {
796 unsafe { kernel_block_index_destroy(self.inner) };
797 }
798}
799
800pub struct BlockUndo {
804 inner: *mut kernel_BlockUndo,
805 pub n_tx_undo: usize,
806}
807unsafe impl Send for BlockUndo {}
808unsafe impl Sync for BlockUndo {}
809
810impl BlockUndo {
811 pub fn get_transaction_undo_size(&self, transaction_index: u64) -> u64 {
814 unsafe { kernel_get_transaction_undo_size(self.inner, transaction_index) }
815 }
816
817 pub fn get_prevout_by_index(
819 &self,
820 transaction_index: u64,
821 prevout_index: u64,
822 ) -> Result<TxOut, KernelError> {
823 let prev_out = unsafe {
824 kernel_get_undo_output_by_index(self.inner, transaction_index, prevout_index)
825 };
826 if prev_out.is_null() {
827 return Err(KernelError::OutOfBounds);
828 }
829 let res = TxOut { inner: prev_out };
830 Ok(res)
831 }
832}
833
834impl Drop for BlockUndo {
835 fn drop(&mut self) {
836 unsafe { kernel_block_undo_destroy(self.inner) };
837 }
838}
839
840pub struct ChainstateManagerOptions {
842 inner: *mut kernel_ChainstateManagerOptions,
843}
844
845impl ChainstateManagerOptions {
846 pub fn new(context: &Context, data_dir: &str, blocks_dir: &str) -> Result<Self, KernelError> {
852 let c_data_dir = CString::new(data_dir)?;
853 let c_blocks_dir = CString::new(blocks_dir)?;
854 let inner = unsafe {
855 kernel_chainstate_manager_options_create(
856 context.inner,
857 c_data_dir.as_ptr().cast::<i8>(),
858 c_data_dir.as_bytes().len(),
859 c_blocks_dir.as_ptr().cast::<i8>(),
860 c_blocks_dir.as_bytes().len(),
861 )
862 };
863 if inner.is_null() {
864 return Err(KernelError::Internal(
865 "Failed to create chainstate manager options.".to_string(),
866 ));
867 }
868 Ok(Self { inner })
869 }
870
871 pub fn set_worker_threads(&self, worker_threads: i32) {
873 unsafe {
874 kernel_chainstate_manager_options_set_worker_threads_num(self.inner, worker_threads);
875 }
876 }
877
878 pub fn set_wipe_db(self, wipe_block_tree: bool, wipe_chainstate: bool) -> Self {
882 unsafe {
883 kernel_chainstate_manager_options_set_wipe_dbs(
884 self.inner,
885 wipe_block_tree,
886 wipe_chainstate,
887 );
888 }
889 self
890 }
891
892 pub fn set_block_tree_db_in_memory(self, block_tree_db_in_memory: bool) -> Self {
894 unsafe {
895 kernel_chainstate_manager_options_set_block_tree_db_in_memory(
896 self.inner,
897 block_tree_db_in_memory,
898 );
899 }
900 self
901 }
902
903 pub fn set_chainstate_db_in_memory(self, chainstate_db_in_memory: bool) -> Self {
905 unsafe {
906 kernel_chainstate_manager_options_set_chainstate_db_in_memory(
907 self.inner,
908 chainstate_db_in_memory,
909 );
910 }
911 self
912 }
913}
914
915impl Drop for ChainstateManagerOptions {
916 fn drop(&mut self) {
917 unsafe {
918 kernel_chainstate_manager_options_destroy(self.inner);
919 }
920 }
921}
922
923pub struct ChainstateManager {
932 inner: *mut kernel_ChainstateManager,
933 context: Arc<Context>,
934}
935
936unsafe impl Send for ChainstateManager {}
937unsafe impl Sync for ChainstateManager {}
938
939impl<'a> ChainstateManager {
940 pub fn new(
941 chainman_opts: ChainstateManagerOptions,
942 context: Arc<Context>,
943 ) -> Result<Self, KernelError> {
944 let inner = unsafe { kernel_chainstate_manager_create(context.inner, chainman_opts.inner) };
945 if inner.is_null() {
946 return Err(KernelError::Internal(
947 "Failed to create chainstate manager.".to_string(),
948 ));
949 }
950 Ok(Self { inner, context })
951 }
952
953 pub fn process_block(&self, block: &Block) -> (bool , bool ) {
960 let mut new_block = true.into();
961 let accepted = unsafe {
962 kernel_chainstate_manager_process_block(
963 self.context.inner,
964 self.inner,
965 block.inner,
966 &mut new_block,
967 )
968 };
969 (accepted, new_block)
970 }
971
972 pub fn import_blocks(&self) -> Result<(), KernelError> {
977 if !unsafe {
978 kernel_import_blocks(
979 self.context.inner,
980 self.inner,
981 std::ptr::null_mut(),
982 std::ptr::null_mut(),
983 0,
984 )
985 } {
986 return Err(KernelError::Internal(
987 "Failed to import blocks.".to_string(),
988 ));
989 }
990 Ok(())
991 }
992
993 pub fn get_block_index_tip(&self) -> BlockIndex {
996 BlockIndex {
997 inner: unsafe { kernel_get_block_index_from_tip(self.context.inner, self.inner) },
998 marker: PhantomData,
999 }
1000 }
1001
1002 pub fn get_block_index_genesis(&self) -> BlockIndex {
1004 BlockIndex {
1005 inner: unsafe { kernel_get_block_index_from_genesis(self.context.inner, self.inner) },
1006 marker: PhantomData,
1007 }
1008 }
1009
1010 pub fn get_block_index_by_height(&self, block_height: i32) -> Result<BlockIndex, KernelError> {
1013 let inner = unsafe {
1014 kernel_get_block_index_from_height(self.context.inner, self.inner, block_height)
1015 };
1016 if inner.is_null() {
1017 return Err(KernelError::OutOfBounds);
1018 }
1019 Ok(BlockIndex {
1020 inner,
1021 marker: PhantomData,
1022 })
1023 }
1024
1025 pub fn get_block_index_by_hash(&self, hash: BlockHash) -> Result<BlockIndex, KernelError> {
1027 let mut block_hash = kernel_BlockHash { hash: hash.hash };
1028 let inner = unsafe {
1029 kernel_get_block_index_from_hash(self.context.inner, self.inner, &mut block_hash)
1030 };
1031 if inner.is_null() {
1032 return Err(KernelError::Internal(
1033 "Block index for the given block hash not found.".to_string(),
1034 ));
1035 }
1036 Ok(BlockIndex {
1037 inner,
1038 marker: PhantomData,
1039 })
1040 }
1041
1042 pub fn get_next_block_index(&self, block_index: BlockIndex) -> Result<BlockIndex, KernelError> {
1045 let inner = unsafe {
1046 kernel_get_next_block_index(self.context.inner, self.inner, block_index.inner)
1047 };
1048 if inner.is_null() {
1049 return Err(KernelError::OutOfBounds);
1050 }
1051 Ok(BlockIndex {
1052 inner,
1053 marker: PhantomData,
1054 })
1055 }
1056
1057 pub fn read_block_data(&self, block_index: &BlockIndex) -> Result<Block, KernelError> {
1059 let inner = unsafe {
1060 kernel_read_block_from_disk(self.context.inner, self.inner, block_index.inner)
1061 };
1062 if inner.is_null() {
1063 return Err(KernelError::Internal("Failed to read block.".to_string()));
1064 }
1065 Ok(Block { inner })
1066 }
1067
1068 pub fn read_undo_data(&self, block_index: &BlockIndex) -> Result<BlockUndo, KernelError> {
1070 let inner = unsafe {
1071 kernel_read_block_undo_from_disk(self.context.inner, self.inner, block_index.inner)
1072 };
1073 if inner.is_null() {
1074 return Err(KernelError::Internal(
1075 "Failed to read undo data.".to_string(),
1076 ));
1077 }
1078 let n_tx_undo = unsafe { kernel_block_undo_size(inner) }.try_into().unwrap();
1079 Ok(BlockUndo { inner, n_tx_undo })
1080 }
1081}
1082
1083impl Drop for ChainstateManager {
1084 fn drop(&mut self) {
1085 unsafe {
1086 kernel_chainstate_manager_destroy(self.inner, self.context.inner);
1087 }
1088 }
1089}
1090
1091pub trait Log {
1093 fn log(&self, message: &str);
1094}
1095
1096unsafe extern "C" fn log_callback<T: Log + 'static>(
1097 user_data: *mut c_void,
1098 message: *const c_char,
1099 message_len: usize,
1100) {
1101 let message = unsafe { cast_string(message, message_len) };
1102 let log = user_data as *mut T;
1103 (*log).log(&message);
1104}
1105
1106pub struct Logger<T> {
1110 log: T,
1111 inner: *mut kernel_LoggingConnection,
1112}
1113
1114impl<T> Drop for Logger<T> {
1115 fn drop(&mut self) {
1116 unsafe {
1117 kernel_logging_connection_destroy(self.inner);
1118 }
1119 }
1120}
1121
1122pub fn disable_logging() {
1124 unsafe {
1125 kernel_disable_logging();
1126 }
1127}
1128
1129impl<T: Log + 'static> Logger<T> {
1130 pub fn new(mut log: T) -> Result<Logger<T>, KernelError> {
1132 let options = kernel_LoggingOptions {
1133 log_timestamps: true,
1134 log_time_micros: false,
1135 log_threadnames: false,
1136 log_sourcelocations: false,
1137 always_print_category_levels: false,
1138 };
1139
1140 let inner = unsafe {
1141 kernel_logging_connection_create(
1142 Some(log_callback::<T>),
1143 &mut log as *mut T as *mut c_void,
1144 options,
1145 )
1146 };
1147
1148 if inner.is_null() {
1149 return Err(KernelError::Internal(
1150 "Failed to create new logging connection.".to_string(),
1151 ));
1152 }
1153
1154 Ok(Logger { log, inner })
1155 }
1156
1157 pub fn log(&self, message: &str) {
1159 self.log.log(message);
1160 }
1161}