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
//! Bitcoin Node Event Timeline
//!
//! Captures sequence-ordered, cryptographically hashable events in the lifecycle
//! of a sovereign Bitcoin node for timeline reconciliation and forensic audit.
use crate::digest::{DigestAlgorithm, TypedDigest};
use alloc::vec::Vec;
/// Specific lifecycle events for a Bitcoin node.
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum BitcoinNodeEvent {
/// The node's secure boot and measured boot sequence was verified.
BootVerified {
sequence_number: u64,
firmware_digest: TypedDigest,
},
/// The runtime integrity of the node's bitcoind workload was verified.
RuntimeIntegrityVerified {
sequence_number: u64,
executable_hash: TypedDigest,
config_hash: TypedDigest,
},
/// The bitcoind executable was updated to a new version.
BinaryUpdated {
sequence_number: u64,
old_hash: TypedDigest,
new_hash: TypedDigest,
},
/// The bitcoin.conf configuration file was modified.
ConfigChanged {
sequence_number: u64,
old_hash: TypedDigest,
new_hash: TypedDigest,
},
/// A distributed verifier consensus decision was reached for this node.
VerifierConsensusReached {
sequence_number: u64,
consensus_hash: TypedDigest,
},
/// The governance policy applied to this node was updated.
GovernancePolicyUpdated { sequence_number: u64, epoch_id: u64 },
/// The node's trust state was successfully anchored to a transparency log or Bitcoin.
TransparencyAnchored {
sequence_number: u64,
anchor_hash: TypedDigest,
},
}
impl BitcoinNodeEvent {
/// Gets the monotonic sequence number of the event.
#[must_use]
pub fn sequence_number(&self) -> u64 {
match *self {
Self::BootVerified {
sequence_number, ..
}
| Self::RuntimeIntegrityVerified {
sequence_number, ..
}
| Self::BinaryUpdated {
sequence_number, ..
}
| Self::ConfigChanged {
sequence_number, ..
}
| Self::VerifierConsensusReached {
sequence_number, ..
}
| Self::GovernancePolicyUpdated {
sequence_number, ..
}
| Self::TransparencyAnchored {
sequence_number, ..
} => sequence_number,
}
}
/// Computes the cryptographic hash of the event for timeline anchoring.
#[must_use]
pub fn event_hash(&self) -> TypedDigest {
use sha2::{Digest, Sha256};
// In a real implementation, this would serialize the variant and hash it.
// For demonstration, we just create a dummy hash based on the sequence number.
let mut buf = Vec::new();
buf.extend_from_slice(&self.sequence_number().to_be_bytes());
match self {
Self::BootVerified {
firmware_digest, ..
} => buf.extend_from_slice(&firmware_digest.value),
Self::RuntimeIntegrityVerified {
executable_hash, ..
} => buf.extend_from_slice(&executable_hash.value),
Self::BinaryUpdated { new_hash, .. } | Self::ConfigChanged { new_hash, .. } => {
buf.extend_from_slice(&new_hash.value);
}
Self::VerifierConsensusReached { consensus_hash, .. } => {
buf.extend_from_slice(&consensus_hash.value);
}
Self::GovernancePolicyUpdated { epoch_id, .. } => {
buf.extend_from_slice(&epoch_id.to_be_bytes());
}
Self::TransparencyAnchored { anchor_hash, .. } => {
buf.extend_from_slice(&anchor_hash.value);
}
}
let mut hasher = Sha256::new();
hasher.update(&buf);
let result = hasher.finalize();
TypedDigest {
algorithm: DigestAlgorithm::Sha256,
value: result.into(),
}
}
}