acme_chains/actors/blocks/
mod.rs1pub use block::*;
9pub use utils::*;
10
11mod block;
12
13pub type BoxedBlock = Box<dyn AbstractBlock>;
14
15pub trait AbstractBlock<Data = String, Index = u8, Hash = String, Nonce = u8, Ts = i64> {
16 fn constructor(
17 &self,
18 id: Index,
19 hash: Hash,
20 nonce: Nonce,
21 previous: Hash,
22 timestamp: Ts,
23 ) -> Self
24 where
25 Self: Sized;
26}
27
28pub trait BlockSpec<Dt = String, Id = u8, Hs = Vec<u8>, Nc = u8, Ts = i64> {
29 fn constructor(
30 &self,
31 id: Id,
32 hash: Hs,
33 nonce: Nc,
34 previous: Hs,
35 timestamp: Ts,
36 transactions: Vec<Dt>,
37 ) -> Self
38 where
39 Self: Sized;
40 fn consensus(
41 &self,
42 id: Id,
43 hash: Hs,
44 previous: Hs,
45 timestamp: Ts,
46 transactions: Vec<Dt>,
47 ) -> (Nc, Hs)
48 where
49 Self: Sized;
50}
51
52mod utils {
53 use crate::{BData, BHash, BId, BNonce, BTStamp, DIFFICULTY_PREFIX};
54 use log;
55 use sha2::Digest;
56
57 pub fn create_block(
58 data: BData,
59 id: BId,
60 previous: BHash,
61 timestamp: BTStamp,
62 ) -> (BNonce, BHash) {
63 log::info!("Creating a new block...");
64 let mut nonce = 0;
65 loop {
66 if nonce % 100000 == 0 {
67 log::info!("nonce: {}", nonce);
68 }
69 let hash = calculate_block_hash(id, data.clone(), nonce, previous.clone(), timestamp);
70 let binary_hash = convert_hash_into_binary(&hash);
71 if binary_hash.starts_with(DIFFICULTY_PREFIX.as_ref()) {
72 log::info!(
73 "mined! nonce: {}, hash: {}, binary hash: {:#?}",
74 nonce,
75 hex::encode(&hash),
76 binary_hash
77 );
78 return (nonce, hex::encode(hash).into());
79 }
80 nonce += 1;
81 }
82 }
83
84 pub fn convert_hash_into_binary(hash: &[u8]) -> Vec<u8> {
85 let mut res: String = String::default();
86 for c in hash {
87 res.push_str(&format!("{:b}", c));
88 }
89 res.into_bytes()
90 }
91
92 pub fn calculate_block_hash(
93 id: BId,
94 data: BData,
95 nonce: BNonce,
96 previous: BHash,
97 timestamp: BTStamp,
98 ) -> Vec<u8> {
99 let cache = serde_json::json!(
100 {
101 "id": id,
102 "data": data.clone(),
103 "nonce": nonce,
104 "previous": previous,
105 "timestamp": timestamp
106 }
107 );
108 let mut hasher = sha2::Sha256::new();
109 hasher.update(cache.to_string().as_bytes());
110 hasher.finalize().as_slice().to_owned()
111 }
112
113 #[cfg(test)]
114 mod tests {
115 use super::*;
116
117 #[test]
118 fn test_block_hash() {
119 let id: BId = 10;
120 let data = "test".to_string();
121 let nonce: BNonce = 890890;
122 let previous = "previous_hash".to_string();
123 let timestamp: BTStamp = crate::block_ts_utc();
124 let hash = calculate_block_hash(id, data.clone(), nonce, previous.clone(), timestamp);
125 assert_eq!(&hash, &hash)
126 }
127 }
128}