1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use crate::blockdata::transaction::Transaction;
use crate::consensus::encode::VarInt;
use crate::cryptonote::hash;
#[cfg(feature = "serde_support")]
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
pub struct BlockHeader {
pub major_version: VarInt,
pub minor_version: VarInt,
pub timestamp: VarInt,
pub prev_id: hash::Hash,
pub nonce: u32,
}
impl fmt::Display for BlockHeader {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
writeln!(fmt, "Major version: {}", self.major_version,)?;
writeln!(fmt, "Minor version: {}", self.minor_version,)?;
writeln!(fmt, "Timestamp: {}", self.timestamp,)?;
writeln!(fmt, "Previous id: {}", self.prev_id,)?;
writeln!(fmt, "Nonce: {}", self.nonce,)
}
}
impl_consensus_encoding!(
BlockHeader,
major_version,
minor_version,
timestamp,
prev_id,
nonce
);
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
pub struct Block {
pub header: BlockHeader,
pub miner_tx: Transaction,
pub tx_hashes: Vec<hash::Hash>,
}
impl fmt::Display for Block {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
writeln!(fmt, "Block header: {}", self.header,)?;
writeln!(fmt, "Miner tx: {}", self.miner_tx)?;
for tx in &self.tx_hashes {
writeln!(fmt, "tx: {}", tx,)?;
}
Ok(())
}
}
impl_consensus_encoding!(Block, header, miner_tx, tx_hashes);
#[cfg(test)]
mod test {
use super::*;
use crate::consensus::encode::deserialize;
use crate::consensus::encode::serialize;
use crate::cryptonote::hash::Hashable;
#[test]
fn test_block_ser() {
let hex = "0c0c94debaf805beb3489c722a285c092a32e7c6893abfc7d069699c8326fc3445a749c5276b6200000000029b892201ffdf882201b699d4c8b1ec020223df524af2a2ef5f870adb6e1ceb03a475c39f8b9ef76aa50b46ddd2a18349402b012839bfa19b7524ec7488917714c216ca254b38ed0424ca65ae828a7c006aeaf10208f5316a7f6b99cca60000";
let hex_blockhash_blob="0c0c94debaf805beb3489c722a285c092a32e7c6893abfc7d069699c8326fc3445a749c5276b6200000000602d0d4710e2c2d38da0cce097accdf5dc18b1d34323880c1aae90ab8f6be6e201";
let bytes = hex::decode(hex).unwrap();
let block = deserialize::<Block>(&bytes[..]).unwrap();
let header = serialize::<BlockHeader>(&block.header);
let mut count = serialize::<VarInt>(&VarInt(1 + block.tx_hashes.len() as u64));
let mut root = block.miner_tx.hash().0.to_vec();
let mut encode2 = header;
encode2.append(&mut root);
encode2.append(&mut count);
assert_eq!(hex::encode(encode2), hex_blockhash_blob);
let bytes2 = serialize::<Block>(&block);
assert_eq!(bytes, bytes2);
let hex2 = hex::encode(bytes2);
assert_eq!(hex, hex2);
}
}