block.rs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. use std::io;
  2. use crate::{
  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. /// This struct represents a tuple of the form (st, sl, txs, metadata).
  17. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  18. pub struct Block {
  19. /// Previous block hash
  20. pub st: blake3::Hash,
  21. /// Slot uid, generated by the beacon
  22. pub sl: u64,
  23. /// Transaction hashes
  24. /// The actual transactions are in [`TxStore`]
  25. pub txs: Vec<blake3::Hash>,
  26. /// Additional block information
  27. pub metadata: Metadata,
  28. }
  29. impl Block {
  30. pub fn new(st: blake3::Hash, sl: u64, txs: Vec<blake3::Hash>, metadata: Metadata) -> Block {
  31. Block { st, sl, txs, metadata }
  32. }
  33. /// Generates the genesis block.
  34. pub fn genesis_block(genesis: i64) -> Block {
  35. let hash = blake3::Hash::from(EMPTY_HASH_BYTES);
  36. let metadata = Metadata::new(
  37. Timestamp(genesis),
  38. String::from("proof"),
  39. String::from("r"),
  40. String::from("s"),
  41. );
  42. Block::new(hash, 0, vec![], metadata)
  43. }
  44. }
  45. #[derive(Debug)]
  46. pub struct BlockStore(sled::Tree);
  47. impl BlockStore {
  48. /// Opens a new or existing blockstore tree given a sled database.
  49. pub fn new(db: &sled::Db, genesis: i64) -> Result<Self> {
  50. let tree = db.open_tree(SLED_BLOCK_TREE)?;
  51. let store = Self(tree);
  52. if store.0.is_empty() {
  53. // Genesis block is generated.
  54. store.insert(&Block::genesis_block(genesis))?;
  55. }
  56. Ok(store)
  57. }
  58. /// Insert a block into the blockstore.
  59. /// The block is hashed with blake3 and this blockhash is used as
  60. /// the key, where value is the serialized block itself.
  61. pub fn insert(&self, block: &Block) -> Result<blake3::Hash> {
  62. let serialized = serialize(block);
  63. let blockhash = blake3::hash(&serialized);
  64. self.0.insert(blockhash.as_bytes(), serialized)?;
  65. Ok(blockhash)
  66. }
  67. /// Retrieve all blocks.
  68. /// Be carefull as this will try to load everything in memory.
  69. pub fn get_all(&self) -> Result<Vec<Option<(blake3::Hash, Block)>>> {
  70. let mut blocks = Vec::new();
  71. let mut iterator = self.0.into_iter().enumerate();
  72. while let Some((_, r)) = iterator.next() {
  73. let (k, v) = r.unwrap();
  74. let hash_bytes: [u8; 32] = k.as_ref().try_into().unwrap();
  75. let block = deserialize(&v)?;
  76. blocks.push(Some((hash_bytes.into(), block)));
  77. }
  78. Ok(blocks)
  79. }
  80. }
  81. /// This struct represents a Block proposal, used for consensus.
  82. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  83. pub struct BlockProposal {
  84. /// leader public key
  85. pub public_key: PublicKey,
  86. /// signed block
  87. pub signature: Signature,
  88. /// leader id
  89. pub id: u64,
  90. /// Previous block hash
  91. pub st: blake3::Hash,
  92. /// Slot uid, generated by the beacon
  93. pub sl: u64,
  94. /// Transactions payload
  95. pub txs: Vec<Tx>,
  96. /// Additional proposal information
  97. pub metadata: Metadata,
  98. /// Proposal information used by Streamlet consensus
  99. pub sm: StreamletMetadata,
  100. }
  101. impl BlockProposal {
  102. pub fn new(
  103. public_key: PublicKey,
  104. signature: Signature,
  105. id: u64,
  106. st: blake3::Hash,
  107. sl: u64,
  108. txs: Vec<Tx>,
  109. metadata: Metadata,
  110. sm: StreamletMetadata,
  111. ) -> BlockProposal {
  112. BlockProposal { public_key, signature, id, st, sl, txs, metadata, sm }
  113. }
  114. /// Produce proposal hash using st, sl, txs and metadata.
  115. pub fn hash(&self) -> blake3::Hash {
  116. Self::to_proposal_hash(self.st, self.sl, &self.txs, &self.metadata)
  117. }
  118. /// Util function generate a proposal hash using provided st, sl, txs and metadata.
  119. pub fn to_proposal_hash(
  120. st: blake3::Hash,
  121. sl: u64,
  122. transactions: &Vec<Tx>,
  123. metadata: &Metadata,
  124. ) -> blake3::Hash {
  125. let mut txs = Vec::new();
  126. for tx in transactions {
  127. let hash = blake3::hash(&serialize(tx));
  128. txs.push(hash);
  129. }
  130. blake3::hash(&serialize(&Block::new(st, sl, txs, metadata.clone())))
  131. }
  132. }
  133. impl PartialEq for BlockProposal {
  134. fn eq(&self, other: &Self) -> bool {
  135. self.public_key == other.public_key &&
  136. self.signature == other.signature &&
  137. self.id == other.id &&
  138. self.st == other.st &&
  139. self.sl == other.sl &&
  140. self.txs == other.txs &&
  141. self.metadata == other.metadata
  142. }
  143. }
  144. impl net::Message for BlockProposal {
  145. fn name() -> &'static str {
  146. "proposal"
  147. }
  148. }
  149. impl_vec!(BlockProposal);