Skip to content

Commit 6d54ffb

Browse files
committed
Validate blocks directly in ChainPoller
1 parent ffbdaa5 commit 6d54ffb

File tree

3 files changed

+55
-12
lines changed

3 files changed

+55
-12
lines changed

lightning-block-sync/src/lib.rs

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ pub trait Poll {
109109

110110
/// Returns the block associated with the given header.
111111
fn fetch_block<'a>(&'a mut self, header: &'a ValidatedBlockHeader) ->
112-
AsyncBlockSourceResult<'a, Block>;
112+
AsyncBlockSourceResult<'a, ValidatedBlock>;
113113
}
114114

115115
/// A chain tip relative to another chain tip in terms of block hash and chainwork.
@@ -126,8 +126,20 @@ pub enum ChainTip {
126126
Worse(ValidatedBlockHeader),
127127
}
128128

129-
impl BlockHeaderData {
130-
fn validate(self, block_hash: BlockHash) -> BlockSourceResult<ValidatedBlockHeader> {
129+
/// The `Validate` trait defines behavior for validating chain data.
130+
trait Validate {
131+
/// The validated data wrapper which can be dereferenced to obtain the validated data.
132+
type T: std::ops::Deref<Target = Self>;
133+
134+
/// Validates the chain data against the given block hash and any criteria needed to ensure that
135+
/// it is internally consistent.
136+
fn validate(self, block_hash: BlockHash) -> BlockSourceResult<Self::T>;
137+
}
138+
139+
impl Validate for BlockHeaderData {
140+
type T = ValidatedBlockHeader;
141+
142+
fn validate(self, block_hash: BlockHash) -> BlockSourceResult<Self::T> {
131143
self.header
132144
.validate_pow(&self.header.target())
133145
.or(Err(BlockSourceError::Persistent))?;
@@ -140,6 +152,22 @@ impl BlockHeaderData {
140152
}
141153
}
142154

155+
impl Validate for Block {
156+
type T = ValidatedBlock;
157+
158+
fn validate(self, block_hash: BlockHash) -> BlockSourceResult<Self::T> {
159+
if self.block_hash() != block_hash {
160+
return Err(BlockSourceError::Persistent);
161+
}
162+
163+
if !self.check_merkle_root() || !self.check_witness_commitment() {
164+
return Err(BlockSourceError::Persistent);
165+
}
166+
167+
Ok(ValidatedBlock { block_hash, inner: self })
168+
}
169+
}
170+
143171
/// A block header with validated proof of work and corresponding block hash.
144172
#[derive(Clone, Copy, Debug, PartialEq)]
145173
pub struct ValidatedBlockHeader {
@@ -187,6 +215,20 @@ impl ValidatedBlockHeader {
187215
}
188216
}
189217

218+
/// A block with validated data against its transaction list and corresponding block hash.
219+
pub struct ValidatedBlock {
220+
block_hash: BlockHash,
221+
inner: Block,
222+
}
223+
224+
impl std::ops::Deref for ValidatedBlock {
225+
type Target = Block;
226+
227+
fn deref(&self) -> &Self::Target {
228+
&self.inner
229+
}
230+
}
231+
190232
async fn look_up_prev_header<P: Poll>(chain_poller: &mut P, header: &ValidatedBlockHeader, cache: &HeaderCache) -> BlockSourceResult<ValidatedBlockHeader> {
191233
match cache.get(&header.header.prev_blockhash) {
192234
Some(prev_header) => Ok(*prev_header),
@@ -325,9 +367,7 @@ async fn sync_chain_monitor<CL: ChainListener + Sized, P: Poll>(new_header: Vali
325367
Err(e) => return Err((e, new_tip)),
326368
Ok(b) => b,
327369
};
328-
if block.header != header.header || !block.check_merkle_root() || !block.check_witness_commitment() {
329-
return Err((BlockSourceError::Persistent, new_tip));
330-
}
370+
debug_assert_eq!(block.block_hash, header.block_hash);
331371
println!("Connecting block {}", header.block_hash.to_hex());
332372
chain_notifier.block_connected(&block, header.height);
333373
header_cache.insert(header.block_hash, header);

lightning-block-sync/src/poller.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{AsyncBlockSourceResult, BlockHeaderData, BlockSource, BlockSourceError, ChainTip, Poll, ValidatedBlockHeader};
1+
use crate::{AsyncBlockSourceResult, BlockHeaderData, BlockSource, BlockSourceError, ChainTip, Poll, Validate, ValidatedBlock, ValidatedBlockHeader};
22

33
use bitcoin::blockdata::block::Block;
44
use bitcoin::hash_types::BlockHash;
@@ -62,10 +62,12 @@ impl<'b, B: DerefMut<Target=dyn BlockSource + 'b> + Sized + Sync + Send> Poll fo
6262
}
6363

6464
fn fetch_block<'a>(&'a mut self, header: &'a ValidatedBlockHeader) ->
65-
AsyncBlockSourceResult<'a, Block>
65+
AsyncBlockSourceResult<'a, ValidatedBlock>
6666
{
6767
Box::pin(async move {
68-
self.block_source.get_block(&header.block_hash).await
68+
self.block_source
69+
.get_block(&header.block_hash).await?
70+
.validate(header.block_hash)
6971
})
7072
}
7173
}
@@ -158,10 +160,11 @@ impl<'b, B: 'b + DerefMut<Target=dyn BlockSource + 'b> + Sized + Sync + Send> Po
158160
}
159161

160162
fn fetch_block<'a>(&'a mut self, header: &'a ValidatedBlockHeader) ->
161-
AsyncBlockSourceResult<'a, Block>
163+
AsyncBlockSourceResult<'a, ValidatedBlock>
162164
{
163165
Box::pin(async move {
164-
self.get_block(&header.block_hash).await
166+
self.get_block(&header.block_hash).await?
167+
.validate(header.block_hash)
165168
})
166169
}
167170
}

lightning-block-sync/src/test_utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{AsyncBlockSourceResult, BlockHeaderData, BlockSource, BlockSourceError, ChainListener, HeaderCache, ValidatedBlockHeader};
1+
use crate::{AsyncBlockSourceResult, BlockHeaderData, BlockSource, BlockSourceError, ChainListener, HeaderCache, Validate, ValidatedBlockHeader};
22
use bitcoin::blockdata::block::{Block, BlockHeader};
33
use bitcoin::blockdata::constants::genesis_block;
44
use bitcoin::hash_types::BlockHash;

0 commit comments

Comments
 (0)