block.rs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2022 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::fmt;
  19. use darkfi_sdk::crypto::{constants::MERKLE_DEPTH, MerkleNode};
  20. use darkfi_serial::{serialize, SerialDecodable, SerialEncodable};
  21. use incrementalmerkletree::{bridgetree::BridgeTree, Tree};
  22. use pasta_curves::pallas;
  23. use super::{
  24. constants::{BLOCK_MAGIC_BYTES, BLOCK_VERSION},
  25. LeadInfo,
  26. };
  27. use crate::{net, tx::Transaction, util::time::Timestamp};
  28. /// This struct represents a tuple of the form (version, previous, epoch, slot, timestamp, merkle_root).
  29. #[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
  30. pub struct Header {
  31. /// Block version
  32. pub version: u8,
  33. /// Previous block hash
  34. pub previous: blake3::Hash,
  35. /// Epoch
  36. pub epoch: u64,
  37. /// Slot UID
  38. pub slot: u64,
  39. /// Block creation timestamp
  40. pub timestamp: Timestamp,
  41. /// Root of the transaction hashes merkle tree
  42. pub root: MerkleNode,
  43. }
  44. impl Header {
  45. pub fn new(
  46. previous: blake3::Hash,
  47. epoch: u64,
  48. slot: u64,
  49. timestamp: Timestamp,
  50. root: MerkleNode,
  51. ) -> Self {
  52. let version = BLOCK_VERSION;
  53. Self { version, previous, epoch, slot, timestamp, root }
  54. }
  55. /// Generate the genesis block.
  56. pub fn genesis_header(genesis_ts: Timestamp, genesis_data: blake3::Hash) -> Self {
  57. let tree = BridgeTree::<MerkleNode, MERKLE_DEPTH>::new(100);
  58. let root = tree.root(0).unwrap();
  59. Self::new(genesis_data, 0, 0, genesis_ts, root)
  60. }
  61. /// Calculate the header hash
  62. pub fn headerhash(&self) -> blake3::Hash {
  63. blake3::hash(&serialize(self))
  64. }
  65. }
  66. impl Default for Header {
  67. fn default() -> Self {
  68. Header::new(
  69. blake3::hash(b""),
  70. 0,
  71. 0,
  72. Timestamp::current_time(),
  73. MerkleNode::from(pallas::Base::zero()),
  74. )
  75. }
  76. }
  77. /// This struct represents a tuple of the form (`magic`, `header`, `counter`, `txs`, `lead_info`).
  78. /// The header and transactions are stored as hashes, serving as pointers to
  79. /// the actual data in the sled database.
  80. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  81. pub struct Block {
  82. /// Block magic bytes
  83. pub magic: [u8; 4],
  84. /// Block header
  85. pub header: blake3::Hash,
  86. /// Trasaction hashes
  87. pub txs: Vec<blake3::Hash>,
  88. /// Lead Info
  89. pub lead_info: LeadInfo,
  90. }
  91. impl net::Message for Block {
  92. fn name() -> &'static str {
  93. "block"
  94. }
  95. }
  96. impl Block {
  97. pub fn new(
  98. previous: blake3::Hash,
  99. epoch: u64,
  100. slot: u64,
  101. txs: Vec<blake3::Hash>,
  102. root: MerkleNode,
  103. lead_info: LeadInfo,
  104. ) -> Self {
  105. let magic = BLOCK_MAGIC_BYTES;
  106. let timestamp = Timestamp::current_time();
  107. let header = Header::new(previous, epoch, slot, timestamp, root);
  108. let header = header.headerhash();
  109. Self { magic, header, txs, lead_info }
  110. }
  111. /// Generate the genesis block.
  112. pub fn genesis_block(genesis_ts: Timestamp, genesis_data: blake3::Hash) -> Self {
  113. let magic = BLOCK_MAGIC_BYTES;
  114. let header = Header::genesis_header(genesis_ts, genesis_data);
  115. let header = header.headerhash();
  116. let lead_info = LeadInfo::default();
  117. Self { magic, header, txs: vec![], lead_info }
  118. }
  119. /// Calculate the block hash
  120. pub fn blockhash(&self) -> blake3::Hash {
  121. blake3::hash(&serialize(self))
  122. }
  123. }
  124. /// Auxiliary structure used for blockchain syncing.
  125. #[derive(Debug, SerialEncodable, SerialDecodable)]
  126. pub struct BlockOrder {
  127. /// Slot UID
  128. pub slot: u64,
  129. /// Block headerhash of that slot
  130. pub block: blake3::Hash,
  131. }
  132. impl net::Message for BlockOrder {
  133. fn name() -> &'static str {
  134. "blockorder"
  135. }
  136. }
  137. /// Structure representing full block data.
  138. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  139. pub struct BlockInfo {
  140. /// BlockInfo magic bytes
  141. pub magic: [u8; 4],
  142. /// Block header data
  143. pub header: Header,
  144. /// Transactions payload
  145. pub txs: Vec<Transaction>,
  146. /// Lead Info,
  147. pub lead_info: LeadInfo,
  148. }
  149. impl Default for BlockInfo {
  150. fn default() -> Self {
  151. let magic = BLOCK_MAGIC_BYTES;
  152. Self { magic, header: Header::default(), txs: vec![], lead_info: LeadInfo::default() }
  153. }
  154. }
  155. impl net::Message for BlockInfo {
  156. fn name() -> &'static str {
  157. "blockinfo"
  158. }
  159. }
  160. impl BlockInfo {
  161. pub fn new(header: Header, txs: Vec<Transaction>, lead_info: LeadInfo) -> Self {
  162. let magic = BLOCK_MAGIC_BYTES;
  163. Self { magic, header, txs, lead_info }
  164. }
  165. /// Calculate the block hash
  166. pub fn blockhash(&self) -> blake3::Hash {
  167. let block: Block = self.clone().into();
  168. block.blockhash()
  169. }
  170. }
  171. impl From<BlockInfo> for Block {
  172. fn from(block_info: BlockInfo) -> Self {
  173. let txs = block_info.txs.iter().map(|x| blake3::hash(&serialize(x))).collect();
  174. Self {
  175. magic: block_info.magic,
  176. header: block_info.header.headerhash(),
  177. txs,
  178. lead_info: block_info.lead_info,
  179. }
  180. }
  181. }
  182. /// Auxiliary structure used for blockchain syncing
  183. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  184. pub struct BlockResponse {
  185. /// Response blocks.
  186. pub blocks: Vec<BlockInfo>,
  187. }
  188. impl net::Message for BlockResponse {
  189. fn name() -> &'static str {
  190. "blockresponse"
  191. }
  192. }
  193. /// This struct represents a block proposal, used for consensus.
  194. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  195. pub struct BlockProposal {
  196. /// Block hash
  197. pub hash: blake3::Hash,
  198. /// Block header hash
  199. pub header: blake3::Hash,
  200. /// Block data
  201. pub block: BlockInfo,
  202. }
  203. impl BlockProposal {
  204. #[allow(clippy::too_many_arguments)]
  205. pub fn new(header: Header, txs: Vec<Transaction>, lead_info: LeadInfo) -> Self {
  206. let block = BlockInfo::new(header, txs, lead_info);
  207. let hash = block.blockhash();
  208. let header = block.header.headerhash();
  209. Self { hash, header, block }
  210. }
  211. }
  212. impl PartialEq for BlockProposal {
  213. fn eq(&self, other: &Self) -> bool {
  214. self.hash == other.hash &&
  215. self.header == other.header &&
  216. self.block.header == other.block.header &&
  217. self.block.txs == other.block.txs
  218. }
  219. }
  220. impl fmt::Display for BlockProposal {
  221. fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
  222. formatter.write_fmt(format_args!(
  223. "BlockProposal {{ leader public key: {}, hash: {}, header: {}, epoch: {}, slot: {}, txs: {} }}",
  224. self.block.lead_info.public_key,
  225. self.hash,
  226. self.header,
  227. self.block.header.epoch,
  228. self.block.header.slot,
  229. self.block.txs.len()
  230. ))
  231. }
  232. }
  233. impl net::Message for BlockProposal {
  234. fn name() -> &'static str {
  235. "proposal"
  236. }
  237. }
  238. impl From<BlockProposal> for BlockInfo {
  239. fn from(block: BlockProposal) -> BlockInfo {
  240. block.block
  241. }
  242. }