Skip to content

Commit cdfc65d

Browse files
committed
Add validation mode and result to block checked callback
1 parent c9a844a commit cdfc65d

File tree

2 files changed

+79
-7
lines changed

2 files changed

+79
-7
lines changed

libbitcoinkernel-sys/src/lib.rs

Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ unsafe extern "C" fn kn_block_tip_wrapper(
209209
block_index: *mut kernel_BlockIndex,
210210
) {
211211
let holder = &*(user_data as *mut KernelNotificationInterfaceCallbackHolder);
212-
let hash = kernel_block_index_get_block_hash(block_index) ;
212+
let hash = kernel_block_index_get_block_hash(block_index);
213213
let res = BlockHash {
214214
hash: (&*hash).hash,
215215
};
@@ -429,8 +429,78 @@ impl fmt::Display for KernelError {
429429
}
430430
}
431431

432-
pub trait VIBlockCheckedFn: Fn() {}
433-
impl<F: Fn()> VIBlockCheckedFn for F {}
432+
/// Whether a validated data structure is valid, invalid, or an error was
433+
/// encountered during processing.
434+
pub enum ValidationMode {
435+
VALID,
436+
INVALID,
437+
ERROR,
438+
}
439+
440+
impl From<kernel_ValidationMode> for ValidationMode {
441+
fn from(mode: kernel_ValidationMode) -> Self {
442+
match mode {
443+
kernel_ValidationMode_kernel_VALIDATION_STATE_VALID => Self::VALID,
444+
kernel_ValidationMode_kernel_VALIDATION_STATE_INVALID => Self::INVALID,
445+
kernel_ValidationMode_kernel_VALIDATION_STATE_ERROR => Self::ERROR,
446+
_ => ValidationMode::ERROR, // This should never happen
447+
}
448+
}
449+
}
450+
451+
/// A granular reason why a block was invalid.
452+
pub enum BlockValidationResult {
453+
/// initial value. Block has not yet been rejected
454+
RESULT_UNSET = 0,
455+
/// invalid by consensus rules (excluding any below reasons)
456+
CONSENSUS,
457+
/// Invalid by a change to consensus rules more recent than SegWit.
458+
/// Currently unused as there are no such consensus rule changes, and any download
459+
/// sources realistically need to support SegWit in order to provide useful data,
460+
/// so differentiating between always-invalid and invalid-by-pre-SegWit-soft-fork
461+
/// is uninteresting.
462+
RECENT_CONSENSUS_CHANGE,
463+
/// this block was cached as being invalid and we didn't store the reason why
464+
CACHED_INVALID,
465+
/// invalid proof of work or time too old
466+
INVALID_HEADER,
467+
/// the block's data didn't match the data committed to by the PoW
468+
MUTATED,
469+
/// We don't have the previous block the checked one is built on
470+
MISSING_PREV,
471+
/// A block this one builds on is invalid
472+
INVALID_PREV,
473+
/// block timestamp was > 2 hours in the future (or our clock is bad)
474+
TIME_FUTURE,
475+
/// the block failed to meet one of our checkpoints
476+
CHECKPOINT,
477+
/// the block header may be on a too-little-work chain
478+
HEADER_LOW_WORK,
479+
}
480+
481+
impl From<kernel_BlockValidationResult> for BlockValidationResult {
482+
fn from(res: kernel_BlockValidationResult) -> Self {
483+
match res {
484+
kernel_BlockValidationResult_kernel_BLOCK_RESULT_UNSET => Self::RESULT_UNSET,
485+
kernel_BlockValidationResult_kernel_BLOCK_CONSENSUS => Self::CONSENSUS,
486+
kernel_BlockValidationResult_kernel_BLOCK_RECENT_CONSENSUS_CHANGE => {
487+
Self::RECENT_CONSENSUS_CHANGE
488+
}
489+
kernel_BlockValidationResult_kernel_BLOCK_CACHED_INVALID => Self::CACHED_INVALID,
490+
kernel_BlockValidationResult_kernel_BLOCK_INVALID_HEADER => Self::INVALID_HEADER,
491+
kernel_BlockValidationResult_kernel_BLOCK_MUTATED => Self::MUTATED,
492+
kernel_BlockValidationResult_kernel_BLOCK_MISSING_PREV => Self::MISSING_PREV,
493+
kernel_BlockValidationResult_kernel_BLOCK_INVALID_PREV => Self::INVALID_PREV,
494+
kernel_BlockValidationResult_kernel_BLOCK_TIME_FUTURE => Self::TIME_FUTURE,
495+
kernel_BlockValidationResult_kernel_BLOCK_CHECKPOINT => Self::CHECKPOINT,
496+
kernel_BlockValidationResult_kernel_BLOCK_HEADER_LOW_WORK => Self::HEADER_LOW_WORK,
497+
_ => Self::RECENT_CONSENSUS_CHANGE,
498+
}
499+
}
500+
}
501+
502+
pub trait VIBlockCheckedFn: Fn(ValidationMode, BlockValidationResult) {}
503+
impl<F: Fn(ValidationMode, BlockValidationResult)> VIBlockCheckedFn for F {}
434504

435505
/// A holder struct for validation interface callbacks
436506
pub struct ValidationInterfaceCallbackHolder {
@@ -440,11 +510,13 @@ pub struct ValidationInterfaceCallbackHolder {
440510

441511
unsafe extern "C" fn vi_block_checked_wrapper(
442512
user_data: *mut c_void,
443-
_block: *const kernel_BlockPointer,
444-
_stateIn: *const kernel_BlockValidationState,
513+
_: *const kernel_BlockPointer,
514+
stateIn: *const kernel_BlockValidationState,
445515
) {
446516
let holder = &*(user_data as *mut ValidationInterfaceCallbackHolder);
447-
(holder.block_checked)();
517+
let result = kernel_get_block_validation_result_from_block_validation_state(stateIn);
518+
let mode = kernel_get_validation_mode_from_block_validation_state(stateIn);
519+
(holder.block_checked)(mode.into(), result.into());
448520
}
449521

450522
/// A wrapper for the validation interface. This is the struct that has to be

tests/test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ mod tests {
7070
fn setup_validation_interface(context: &Context) -> ValidationInterfaceWrapper {
7171
let validation_interface =
7272
ValidationInterfaceWrapper::new(Box::new(ValidationInterfaceCallbackHolder {
73-
block_checked: Box::new(|| {
73+
block_checked: Box::new(|_mode, _result| {
7474
log::info!("Block checked!");
7575
}),
7676
}));

0 commit comments

Comments
 (0)