block.rs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. use std::io;
  2. use darkfi::{
  3. crypto::{keypair::PublicKey, schnorr::Signature},
  4. impl_vec, net,
  5. util::serial::{
  6. deserialize, serialize, Decodable, Encodable, SerialDecodable, SerialEncodable, VarInt,
  7. },
  8. Result,
  9. };
  10. use super::{
  11. metadata::{Metadata, StreamletMetadata},
  12. tx::Tx,
  13. util::{Timestamp, EMPTY_HASH_BYTES},
  14. };
  15. const SLED_BLOCK_TREE: &[u8] = b"_blocks";
  16. const SLED_BLOCK_ORDER_TREE: &[u8] = b"_blocks_order";
  17. /// This struct represents a tuple of the form (st, sl, txs, metadata).
  18. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  19. pub struct Block {
  20. /// Previous block hash
  21. pub st: blake3::Hash,
  22. /// Slot uid, generated by the beacon
  23. pub sl: u64,
  24. /// Transaction hashes
  25. /// The actual transactions are in [`TxStore`]
  26. pub txs: Vec<blake3::Hash>,
  27. /// Additional block information
  28. pub metadata: Metadata,
  29. }
  30. impl Block {
  31. pub fn new(st: blake3::Hash, sl: u64, txs: Vec<blake3::Hash>, metadata: Metadata) -> Block {
  32. Block { st, sl, txs, metadata }
  33. }
  34. /// Generates the genesis block.
  35. pub fn genesis_block(genesis: i64) -> Block {
  36. let hash = blake3::Hash::from(EMPTY_HASH_BYTES);
  37. let metadata = Metadata::new(
  38. Timestamp(genesis),
  39. String::from("proof"),
  40. String::from("r"),
  41. String::from("s"),
  42. );
  43. Block::new(hash, 0, vec![], metadata)
  44. }
  45. }
  46. #[derive(Debug)]
  47. pub struct BlockStore(sled::Tree);
  48. impl BlockStore {
  49. /// Opens a new or existing blockstore tree given a sled database.
  50. pub fn new(db: &sled::Db, genesis: i64) -> Result<Self> {
  51. let tree = db.open_tree(SLED_BLOCK_TREE)?;
  52. let store = Self(tree);
  53. if store.0.is_empty() {
  54. // Genesis block is generated.
  55. store.insert(&Block::genesis_block(genesis))?;
  56. }
  57. Ok(store)
  58. }
  59. /// Insert a block into the blockstore.
  60. /// The block is hashed with blake3 and this blockhash is used as
  61. /// the key, where value is the serialized block itself.
  62. pub fn insert(&self, block: &Block) -> Result<blake3::Hash> {
  63. let serialized = serialize(block);
  64. let blockhash = blake3::hash(&serialized);
  65. self.0.insert(blockhash.as_bytes(), serialized)?;
  66. Ok(blockhash)
  67. }
  68. /// Fetch given blocks from the blockstore.
  69. /// The resulting vector contains `Option` which is `Some` if the block
  70. /// was found in the blockstore, and `None`, if it has not.
  71. pub fn get(&self, blockhashes: &[blake3::Hash]) -> Result<Vec<Option<(blake3::Hash, Block)>>> {
  72. let mut ret: Vec<Option<(blake3::Hash, Block)>> = Vec::with_capacity(blockhashes.len());
  73. for i in blockhashes {
  74. if let Some(found) = self.0.get(i.as_bytes())? {
  75. let block = deserialize(&found)?;
  76. ret.push(Some((i.clone(), block)));
  77. } else {
  78. ret.push(None);
  79. }
  80. }
  81. Ok(ret)
  82. }
  83. /// Retrieve all blocks.
  84. /// Be carefull as this will try to load everything in memory.
  85. pub fn get_all(&self) -> Result<Vec<Option<(blake3::Hash, Block)>>> {
  86. let mut blocks = Vec::new();
  87. let mut iterator = self.0.into_iter().enumerate();
  88. while let Some((_, r)) = iterator.next() {
  89. let (k, v) = r.unwrap();
  90. let hash_bytes: [u8; 32] = k.as_ref().try_into().unwrap();
  91. let block = deserialize(&v)?;
  92. blocks.push(Some((hash_bytes.into(), block)));
  93. }
  94. Ok(blocks)
  95. }
  96. }
  97. /// Auxilary structure used for blockchain syncing.
  98. #[derive(Debug, SerialEncodable, SerialDecodable)]
  99. pub struct BlockOrder {
  100. /// Slot uid
  101. pub sl: u64,
  102. /// Block hash of that slot
  103. pub block: blake3::Hash,
  104. }
  105. impl net::Message for BlockOrder {
  106. fn name() -> &'static str {
  107. "blockorder"
  108. }
  109. }
  110. /// Auxilary structure represending a full block data, used for blockchain syncing.
  111. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  112. pub struct BlockInfo {
  113. /// Previous block hash
  114. pub st: blake3::Hash,
  115. /// Slot uid, generated by the beacon
  116. pub sl: u64,
  117. /// Transactions payload
  118. pub txs: Vec<Tx>,
  119. /// Additional proposal information
  120. pub metadata: Metadata,
  121. /// Proposal information used by Streamlet consensus
  122. pub sm: StreamletMetadata,
  123. }
  124. impl BlockInfo {
  125. pub fn new(
  126. st: blake3::Hash,
  127. sl: u64,
  128. txs: Vec<Tx>,
  129. metadata: Metadata,
  130. sm: StreamletMetadata,
  131. ) -> BlockInfo {
  132. BlockInfo { st, sl, txs, metadata, sm }
  133. }
  134. }
  135. impl net::Message for BlockInfo {
  136. fn name() -> &'static str {
  137. "blockinfo"
  138. }
  139. }
  140. impl_vec!(BlockInfo);
  141. /// Auxilary structure used for blockchain syncing.
  142. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  143. pub struct BlockResponse {
  144. /// Response blocks.
  145. pub blocks: Vec<BlockInfo>,
  146. }
  147. impl net::Message for BlockResponse {
  148. fn name() -> &'static str {
  149. "blockresponse"
  150. }
  151. }
  152. #[derive(Debug)]
  153. pub struct BlockOrderStore(sled::Tree);
  154. impl BlockOrderStore {
  155. /// Opens a new or existing blockorderstore tree given a sled database.
  156. pub fn new(db: &sled::Db, genesis: i64) -> Result<Self> {
  157. let tree = db.open_tree(SLED_BLOCK_ORDER_TREE)?;
  158. let store = Self(tree);
  159. if store.0.is_empty() {
  160. // Genesis block record is generated.
  161. let block = Block::genesis_block(genesis);
  162. let blockhash = blake3::hash(&serialize(&block));
  163. store.insert(block.sl, blockhash)?;
  164. }
  165. Ok(store)
  166. }
  167. /// Insert a block hash into the blockorderstore.
  168. /// The block slot is used as the key, where value is the block hash.
  169. pub fn insert(&self, slot: u64, block: blake3::Hash) -> Result<()> {
  170. self.0.insert(slot.to_be_bytes(), serialize(&block))?;
  171. Ok(())
  172. }
  173. /// Fetch given slots block hashes from the blockstore.
  174. /// The resulting vector contains `Option` which is `Some` if the block
  175. /// was found in the blockstore, and `None`, if it has not.
  176. pub fn get(&self, slots: &[u64]) -> Result<Vec<Option<BlockOrder>>> {
  177. let mut ret: Vec<Option<BlockOrder>> = Vec::with_capacity(slots.len());
  178. for sl in slots {
  179. if let Some(found) = self.0.get(sl.to_be_bytes())? {
  180. let block = deserialize(&found)?;
  181. ret.push(Some(BlockOrder { sl: sl.clone(), block }));
  182. } else {
  183. ret.push(None);
  184. }
  185. }
  186. Ok(ret)
  187. }
  188. /// Retrieve the last block hash in the tree, based on the Ord implementation for Vec<u8>.
  189. pub fn get_last(&self) -> Result<Option<(u64, blake3::Hash)>> {
  190. if let Some(found) = self.0.last()? {
  191. let slot_bytes: [u8; 8] = found.0.as_ref().try_into().unwrap();
  192. let slot = u64::from_be_bytes(slot_bytes);
  193. let block_hash = deserialize(&found.1)?;
  194. return Ok(Some((slot, block_hash)))
  195. }
  196. Ok(None)
  197. }
  198. /// Retrieve n hashes after key.
  199. pub fn get_after(&self, mut key: u64, n: u64) -> Result<Vec<blake3::Hash>> {
  200. let mut hashes = Vec::new();
  201. let mut counter = 0;
  202. while counter <= n {
  203. if let Some(found) = self.0.get_gt(key.to_be_bytes())? {
  204. let key_bytes: [u8; 8] = found.0.as_ref().try_into().unwrap();
  205. key = u64::from_be_bytes(key_bytes);
  206. let block_hash = deserialize(&found.1)?;
  207. hashes.push(block_hash);
  208. counter = counter + 1;
  209. } else {
  210. break
  211. }
  212. }
  213. Ok(hashes)
  214. }
  215. /// Retrieve all blocks hashes.
  216. /// Be carefull as this will try to load everything in memory.
  217. pub fn get_all(&self) -> Result<Vec<Option<(u64, blake3::Hash)>>> {
  218. let mut block_hashes = Vec::new();
  219. let mut iterator = self.0.into_iter().enumerate();
  220. while let Some((_, r)) = iterator.next() {
  221. let (k, v) = r.unwrap();
  222. let slot_bytes: [u8; 8] = k.as_ref().try_into().unwrap();
  223. let slot = u64::from_be_bytes(slot_bytes);
  224. let block_hash = deserialize(&v)?;
  225. block_hashes.push(Some((slot, block_hash)));
  226. }
  227. Ok(block_hashes)
  228. }
  229. }
  230. /// This struct represents a Block proposal, used for consensus.
  231. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  232. pub struct BlockProposal {
  233. /// leader public key
  234. pub public_key: PublicKey,
  235. /// signed block
  236. pub signature: Signature,
  237. /// leader id
  238. pub id: u64,
  239. /// Previous block hash
  240. pub st: blake3::Hash,
  241. /// Slot uid, generated by the beacon
  242. pub sl: u64,
  243. /// Transactions payload
  244. pub txs: Vec<Tx>,
  245. /// Additional proposal information
  246. pub metadata: Metadata,
  247. /// Proposal information used by Streamlet consensus
  248. pub sm: StreamletMetadata,
  249. }
  250. impl BlockProposal {
  251. pub fn new(
  252. public_key: PublicKey,
  253. signature: Signature,
  254. id: u64,
  255. st: blake3::Hash,
  256. sl: u64,
  257. txs: Vec<Tx>,
  258. metadata: Metadata,
  259. sm: StreamletMetadata,
  260. ) -> BlockProposal {
  261. BlockProposal { public_key, signature, id, st, sl, txs, metadata, sm }
  262. }
  263. /// Produce proposal hash using st, sl, txs and metadata.
  264. pub fn hash(&self) -> blake3::Hash {
  265. Self::to_proposal_hash(self.st, self.sl, &self.txs, &self.metadata)
  266. }
  267. /// Util function generate a proposal hash using provided st, sl, txs and metadata.
  268. pub fn to_proposal_hash(
  269. st: blake3::Hash,
  270. sl: u64,
  271. transactions: &Vec<Tx>,
  272. metadata: &Metadata,
  273. ) -> blake3::Hash {
  274. let mut txs = Vec::new();
  275. for tx in transactions {
  276. let hash = blake3::hash(&serialize(tx));
  277. txs.push(hash);
  278. }
  279. blake3::hash(&serialize(&Block::new(st, sl, txs, metadata.clone())))
  280. }
  281. }
  282. impl PartialEq for BlockProposal {
  283. fn eq(&self, other: &Self) -> bool {
  284. self.public_key == other.public_key &&
  285. self.signature == other.signature &&
  286. self.id == other.id &&
  287. self.st == other.st &&
  288. self.sl == other.sl &&
  289. self.txs == other.txs &&
  290. self.metadata == other.metadata
  291. }
  292. }
  293. impl net::Message for BlockProposal {
  294. fn name() -> &'static str {
  295. "proposal"
  296. }
  297. }
  298. impl_vec!(BlockProposal);