block.rs 9.3 KB

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