block.rs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. use std::fmt;
  2. use darkfi_sdk::crypto::{constants::MERKLE_DEPTH, MerkleNode};
  3. use darkfi_serial::{serialize, SerialDecodable, SerialEncodable};
  4. use incrementalmerkletree::{bridgetree::BridgeTree, Tree};
  5. use log::debug;
  6. use pasta_curves::pallas;
  7. use super::{Metadata, BLOCK_MAGIC_BYTES, BLOCK_VERSION};
  8. use crate::{net, tx::Transaction, util::time::Timestamp};
  9. /// This struct represents a tuple of the form (version, previous, epoch, slot, timestamp, merkle_root).
  10. #[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
  11. pub struct Header {
  12. /// Block version
  13. pub version: u8,
  14. /// Previous block hash
  15. pub previous: blake3::Hash,
  16. /// Epoch
  17. pub epoch: u64,
  18. /// Slot UID
  19. pub slot: u64,
  20. /// Block creation timestamp
  21. pub timestamp: Timestamp,
  22. /// Root of the transaction hashes merkle tree
  23. pub root: MerkleNode,
  24. }
  25. impl Header {
  26. pub fn new(
  27. previous: blake3::Hash,
  28. epoch: u64,
  29. slot: u64,
  30. timestamp: Timestamp,
  31. root: MerkleNode,
  32. ) -> Self {
  33. let version = *BLOCK_VERSION;
  34. Self { version, previous, epoch, slot, timestamp, root }
  35. }
  36. /// Generate the genesis block.
  37. pub fn genesis_header(genesis_ts: Timestamp, genesis_data: blake3::Hash) -> Self {
  38. let tree = BridgeTree::<MerkleNode, MERKLE_DEPTH>::new(100);
  39. let root = tree.root(0).unwrap();
  40. Self::new(genesis_data, 0, 0, genesis_ts, root)
  41. }
  42. /// Calculate the header hash
  43. pub fn headerhash(&self) -> blake3::Hash {
  44. blake3::hash(&serialize(self))
  45. }
  46. }
  47. impl Default for Header {
  48. fn default() -> Self {
  49. Header::new(
  50. blake3::hash(b""),
  51. 0,
  52. 0,
  53. Timestamp::current_time(),
  54. MerkleNode::from(pallas::Base::zero()),
  55. )
  56. }
  57. }
  58. /// This struct represents a tuple of the form (`magic`, `header`, `counter`, `txs`, `metadata`).
  59. /// The header and transactions are stored as hashes, serving as pointers to
  60. /// the actual data in the sled database.
  61. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  62. pub struct Block {
  63. /// Block magic bytes
  64. pub magic: [u8; 4],
  65. /// Block header
  66. pub header: blake3::Hash,
  67. /// Trasaction hashes
  68. pub txs: Vec<blake3::Hash>,
  69. /// Metadata
  70. pub metadata: Metadata,
  71. }
  72. impl net::Message for Block {
  73. fn name() -> &'static str {
  74. "block"
  75. }
  76. }
  77. impl Block {
  78. pub fn new(
  79. previous: blake3::Hash,
  80. epoch: u64,
  81. slot: u64,
  82. txs: Vec<blake3::Hash>,
  83. root: MerkleNode,
  84. metadata: Metadata,
  85. ) -> Self {
  86. let magic = *BLOCK_MAGIC_BYTES;
  87. let timestamp = Timestamp::current_time();
  88. let header = Header::new(previous, epoch, slot, timestamp, root);
  89. let header = header.headerhash();
  90. Self { magic, header, txs, metadata }
  91. }
  92. /// Generate the genesis block.
  93. pub fn genesis_block(genesis_ts: Timestamp, genesis_data: blake3::Hash) -> Self {
  94. let magic = *BLOCK_MAGIC_BYTES;
  95. let header = Header::genesis_header(genesis_ts, genesis_data);
  96. let header = header.headerhash();
  97. let metadata = Metadata::default();
  98. Self { magic, header, txs: vec![], metadata }
  99. }
  100. /// Calculate the block hash
  101. pub fn blockhash(&self) -> blake3::Hash {
  102. blake3::hash(&serialize(self))
  103. }
  104. }
  105. /// Auxiliary structure used for blockchain syncing.
  106. #[derive(Debug, SerialEncodable, SerialDecodable)]
  107. pub struct BlockOrder {
  108. /// Slot UID
  109. pub slot: u64,
  110. /// Block headerhash of that slot
  111. pub block: blake3::Hash,
  112. }
  113. impl net::Message for BlockOrder {
  114. fn name() -> &'static str {
  115. "blockorder"
  116. }
  117. }
  118. /// Structure representing full block data.
  119. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  120. pub struct BlockInfo {
  121. /// BlockInfo magic bytes
  122. pub magic: [u8; 4],
  123. /// Block header data
  124. pub header: Header,
  125. /// Transactions payload
  126. pub txs: Vec<Transaction>,
  127. /// Metadata,
  128. pub metadata: Metadata,
  129. }
  130. impl Default for BlockInfo {
  131. fn default() -> Self {
  132. let magic = *BLOCK_MAGIC_BYTES;
  133. Self { magic, header: Header::default(), txs: vec![], metadata: Metadata::default() }
  134. }
  135. }
  136. impl net::Message for BlockInfo {
  137. fn name() -> &'static str {
  138. "blockinfo"
  139. }
  140. }
  141. impl BlockInfo {
  142. pub fn new(header: Header, txs: Vec<Transaction>, metadata: Metadata) -> Self {
  143. let magic = *BLOCK_MAGIC_BYTES;
  144. Self { magic, header, txs, metadata }
  145. }
  146. /// Calculate the block hash
  147. pub fn blockhash(&self) -> blake3::Hash {
  148. let block: Block = self.clone().into();
  149. block.blockhash()
  150. }
  151. }
  152. impl From<BlockInfo> for Block {
  153. fn from(block_info: BlockInfo) -> Self {
  154. let txs = block_info.txs.iter().map(|x| blake3::hash(&serialize(x))).collect();
  155. Self {
  156. magic: block_info.magic,
  157. header: block_info.header.headerhash(),
  158. txs,
  159. metadata: block_info.metadata,
  160. }
  161. }
  162. }
  163. /// Auxiliary structure used for blockchain syncing
  164. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  165. pub struct BlockResponse {
  166. /// Response blocks.
  167. pub blocks: Vec<BlockInfo>,
  168. }
  169. impl net::Message for BlockResponse {
  170. fn name() -> &'static str {
  171. "blockresponse"
  172. }
  173. }
  174. /// This struct represents a block proposal, used for consensus.
  175. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  176. pub struct BlockProposal {
  177. /// Block data
  178. pub block: BlockInfo,
  179. }
  180. impl BlockProposal {
  181. #[allow(clippy::too_many_arguments)]
  182. pub fn new(header: Header, txs: Vec<Transaction>, metadata: Metadata) -> Self {
  183. let block = BlockInfo::new(header, txs, metadata);
  184. Self { block }
  185. }
  186. }
  187. impl PartialEq for BlockProposal {
  188. fn eq(&self, other: &Self) -> bool {
  189. self.block.header == other.block.header && self.block.txs == other.block.txs
  190. }
  191. }
  192. impl fmt::Display for BlockProposal {
  193. fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
  194. formatter.write_fmt(format_args!(
  195. "BlockProposal {{ leader addr: {}, hash: {}, epoch: {}, slot: {}, txs: {} }}",
  196. self.block.metadata.address,
  197. self.block.header.headerhash(),
  198. self.block.header.epoch,
  199. self.block.header.slot,
  200. self.block.txs.len()
  201. ))
  202. }
  203. }
  204. impl net::Message for BlockProposal {
  205. fn name() -> &'static str {
  206. "proposal"
  207. }
  208. }
  209. impl From<BlockProposal> for BlockInfo {
  210. fn from(block: BlockProposal) -> BlockInfo {
  211. block.block
  212. }
  213. }
  214. /// This struct represents a sequence of block proposals.
  215. #[derive(Debug, Clone, PartialEq, SerialEncodable, SerialDecodable)]
  216. pub struct ProposalChain {
  217. pub genesis_block: blake3::Hash,
  218. pub proposals: Vec<BlockProposal>,
  219. }
  220. impl ProposalChain {
  221. pub fn new(genesis_block: blake3::Hash, initial_proposal: BlockProposal) -> Self {
  222. Self { genesis_block, proposals: vec![initial_proposal] }
  223. }
  224. /// A proposal is considered valid when its parent hash is equal to the
  225. /// hash of the previous proposal and their slots are incremental,
  226. /// excluding the genesis block proposal.
  227. /// Additional validity rules can be applied.
  228. pub fn check_proposal(&self, proposal: &BlockProposal, previous: &BlockProposal) -> bool {
  229. if proposal.block.header.previous == self.genesis_block {
  230. debug!("check_proposal(): Genesis block proposal provided.");
  231. return false
  232. }
  233. let prev_hash = previous.block.header.headerhash();
  234. if proposal.block.header.previous != prev_hash ||
  235. proposal.block.header.slot <= previous.block.header.slot
  236. {
  237. debug!("check_proposal(): Provided proposal is invalid.");
  238. return false
  239. }
  240. true
  241. }
  242. /// A proposals chain is considered valid when every proposal is valid,
  243. /// based on the `check_proposal` function.
  244. pub fn check_chain(&self) -> bool {
  245. for (index, proposal) in self.proposals[1..].iter().enumerate() {
  246. if !self.check_proposal(proposal, &self.proposals[index]) {
  247. return false
  248. }
  249. }
  250. true
  251. }
  252. /// Insertion of a valid proposal.
  253. pub fn add(&mut self, proposal: &BlockProposal) {
  254. if self.check_proposal(proposal, self.proposals.last().unwrap()) {
  255. self.proposals.push(proposal.clone());
  256. }
  257. }
  258. }