Skip to content

Commit 56cd368

Browse files
committed
Implement Encodable for Block
Trivial now everything else is done - LFG!
1 parent b33216c commit 56cd368

File tree

2 files changed

+143
-1
lines changed

2 files changed

+143
-1
lines changed

primitives/src/block.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use core::marker::PhantomData;
1313

1414
#[cfg(feature = "arbitrary")]
1515
use arbitrary::{Arbitrary, Unstructured};
16-
use encoding::Encodable;
16+
use encoding::{Encodable, Encoder2, SliceEncoder};
1717
use hashes::{sha256d, HashEngine as _};
1818

1919
#[cfg(feature = "alloc")]
@@ -165,6 +165,26 @@ mod sealed {
165165
impl Validation for super::Unchecked {}
166166
}
167167

168+
#[cfg(feature = "alloc")]
169+
encoding::encoder_newtype! {
170+
/// The encoder for the [`Block`] type.
171+
pub struct BlockEncoder<'e>(
172+
Encoder2<HeaderEncoder, SliceEncoder<'e, Transaction>>
173+
);
174+
}
175+
176+
#[cfg(feature = "alloc")]
177+
impl Encodable for Block {
178+
type Encoder<'e>
179+
= Encoder2<HeaderEncoder, SliceEncoder<'e, Transaction>>
180+
where
181+
Self: 'e;
182+
183+
fn encoder(&self) -> Self::Encoder<'_> {
184+
Encoder2::new(self.header.encoder(), SliceEncoder::with_length_prefix(&self.transactions))
185+
}
186+
}
187+
168188
/// Bitcoin block header.
169189
///
170190
/// Contains all the block's information except the actual transactions, but

primitives/src/transaction.rs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,4 +1318,126 @@ mod tests {
13181318
// Exhausted
13191319
assert_eq!(encoder.current_chunk(), None);
13201320
}
1321+
1322+
// FIXME: Move all these encoding tests to a single file in `primitives/tests/`.
1323+
#[test]
1324+
#[cfg(feature = "alloc")]
1325+
#[cfg(feature = "hex")]
1326+
fn encode_block() {
1327+
use crate::{
1328+
Block, BlockHash, BlockHeader, BlockTime, BlockVersion, CompactTarget, TxMerkleNode,
1329+
};
1330+
1331+
let seconds: u32 = 1_653_195_600; // Arbitrary timestamp: May 22nd, 5am UTC.
1332+
1333+
let header = BlockHeader {
1334+
version: BlockVersion::TWO,
1335+
prev_blockhash: BlockHash::from_byte_array([0xab; 32]),
1336+
merkle_root: TxMerkleNode::from_byte_array([0xcd; 32]),
1337+
time: BlockTime::from(seconds),
1338+
bits: CompactTarget::from_consensus(0xbeef),
1339+
nonce: 0xcafe,
1340+
};
1341+
1342+
let tx = Transaction {
1343+
version: Version::TWO,
1344+
lock_time: LockTime::ZERO,
1345+
inputs: vec![segwit_tx_in()],
1346+
outputs: vec![tx_out()],
1347+
};
1348+
1349+
let block = Block::new_unchecked(header, vec![tx]);
1350+
let mut encoder = block.encoder();
1351+
1352+
// The block header, 6 encoders, 1 chunk per encoder.
1353+
1354+
// The block version.
1355+
assert_eq!(encoder.current_chunk(), Some(&[2u8, 0, 0, 0][..]));
1356+
assert!(encoder.advance());
1357+
// The previous block's blockhash.
1358+
assert_eq!(
1359+
encoder.current_chunk(),
1360+
Some(
1361+
&[
1362+
171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171,
1363+
171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171
1364+
][..]
1365+
)
1366+
);
1367+
assert!(encoder.advance());
1368+
// The merkle root hash.
1369+
assert_eq!(
1370+
encoder.current_chunk(),
1371+
Some(
1372+
&[
1373+
205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
1374+
205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205
1375+
][..]
1376+
)
1377+
);
1378+
assert!(encoder.advance());
1379+
// The block time.
1380+
assert_eq!(encoder.current_chunk(), Some(&[80, 195, 137, 98][..]));
1381+
assert!(encoder.advance());
1382+
// The target (bits).
1383+
assert_eq!(encoder.current_chunk(), Some(&[239, 190, 0, 0][..]));
1384+
assert!(encoder.advance());
1385+
// The nonce.
1386+
assert_eq!(encoder.current_chunk(), Some(&[254, 202, 0, 0][..]));
1387+
assert!(encoder.advance());
1388+
1389+
// The transaction list length prefix.
1390+
assert_eq!(encoder.current_chunk(), Some(&[1u8][..]));
1391+
assert!(encoder.advance());
1392+
1393+
// The transaction (same as tested above).
1394+
1395+
// The version
1396+
assert_eq!(encoder.current_chunk(), Some(&[2u8, 0, 0, 0][..]));
1397+
assert!(encoder.advance());
1398+
// The segwit marker and flag
1399+
assert_eq!(encoder.current_chunk(), Some(&[0u8, 1][..]));
1400+
assert!(encoder.advance());
1401+
// The input (same as tested above) but with vec length prefix.
1402+
assert_eq!(encoder.current_chunk(), Some(&[1u8][..]));
1403+
assert!(encoder.advance());
1404+
assert_eq!(
1405+
encoder.current_chunk(),
1406+
Some(
1407+
&[
1408+
32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13,
1409+
12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
1410+
][..]
1411+
)
1412+
);
1413+
assert!(encoder.advance());
1414+
assert_eq!(encoder.current_chunk(), Some(&[1u8, 0, 0, 0][..]));
1415+
assert!(encoder.advance());
1416+
assert_eq!(encoder.current_chunk(), Some(&[3u8][..]));
1417+
assert!(encoder.advance());
1418+
assert_eq!(encoder.current_chunk(), Some(&[1u8, 2, 3][..]));
1419+
assert!(encoder.advance());
1420+
assert_eq!(encoder.current_chunk(), Some(&[0xffu8, 0xff, 0xff, 0xff][..]));
1421+
assert!(encoder.advance());
1422+
// The output (same as tested above) but with vec length prefix.
1423+
assert_eq!(encoder.current_chunk(), Some(&[1u8][..]));
1424+
assert!(encoder.advance());
1425+
assert_eq!(encoder.current_chunk(), Some(&[1, 0, 0, 0, 0, 0, 0, 0][..]));
1426+
assert!(encoder.advance());
1427+
assert_eq!(encoder.current_chunk(), Some(&[3u8][..]));
1428+
assert!(encoder.advance());
1429+
assert_eq!(encoder.current_chunk(), Some(&[1u8, 2, 3][..]));
1430+
assert!(encoder.advance());
1431+
// The witness
1432+
assert_eq!(encoder.current_chunk(), Some(&[1u8][..]));
1433+
assert!(encoder.advance());
1434+
assert_eq!(encoder.current_chunk(), Some(&[3u8, 1, 2, 3][..]));
1435+
assert!(encoder.advance());
1436+
// The lock time.
1437+
assert_eq!(encoder.current_chunk(), Some(&[0, 0, 0, 0][..]));
1438+
assert!(!encoder.advance());
1439+
1440+
// Exhausted
1441+
assert_eq!(encoder.current_chunk(), None);
1442+
}
13211443
}

0 commit comments

Comments
 (0)