block.rs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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,
  12. participant::Participant,
  13. tx::Tx,
  14. util::{Timestamp, GENESIS_HASH_BYTES},
  15. };
  16. const SLED_BLOCK_TREE: &[u8] = b"_blocks";
  17. /// This struct represents a tuple of the form (st, sl, txs).
  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. }
  28. impl Block {
  29. pub fn new(st: blake3::Hash, sl: u64, txs: Vec<blake3::Hash>) -> Block {
  30. Block { st, sl, txs }
  31. }
  32. }
  33. #[derive(Debug)]
  34. pub struct BlockStore(sled::Tree);
  35. impl BlockStore {
  36. /// Opens a new or existing blockstore tree given a sled database.
  37. pub fn new(db: &sled::Db) -> Result<Self> {
  38. let tree = db.open_tree(SLED_BLOCK_TREE)?;
  39. let store = Self(tree);
  40. if store.0.is_empty() {
  41. // Genesis block is generated.
  42. let hash = blake3::Hash::from(GENESIS_HASH_BYTES);
  43. let genesis_block = Block::new(hash, 0, vec![]);
  44. store.insert(&genesis_block)?;
  45. }
  46. Ok(store)
  47. }
  48. /// Insert a block into the blockstore.
  49. /// The block is hashed with blake3 and this blockhash is used as
  50. /// the key, where value is the serialized block itself.
  51. pub fn insert(&self, block: &Block) -> Result<blake3::Hash> {
  52. let serialized = serialize(block);
  53. let blockhash = blake3::hash(&serialized);
  54. self.0.insert(blockhash.as_bytes(), serialized)?;
  55. Ok(blockhash)
  56. }
  57. /// Retrieve all blocks.
  58. /// Be carefull as this will try to load everything in memory.
  59. pub fn get_all(&self) -> Result<Vec<Option<(blake3::Hash, Block)>>> {
  60. let mut blocks = Vec::new();
  61. let mut iterator = self.0.into_iter().enumerate();
  62. while let Some((_, r)) = iterator.next() {
  63. let (k, v) = r.unwrap();
  64. let hash_bytes: [u8; 32] = k.as_ref().try_into().unwrap();
  65. let block = deserialize(&v)?;
  66. blocks.push(Some((hash_bytes.into(), block)));
  67. }
  68. Ok(blocks)
  69. }
  70. }
  71. /// This struct represents a Block proposal, used for consensus.
  72. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  73. pub struct BlockProposal {
  74. /// leader public key
  75. pub public_key: PublicKey,
  76. /// signed block
  77. pub signature: Signature,
  78. /// leader id
  79. pub id: u64,
  80. /// Previous block hash
  81. pub st: blake3::Hash,
  82. /// Slot uid, generated by the beacon
  83. pub sl: u64,
  84. /// Transactions payload
  85. pub txs: Vec<Tx>,
  86. /// Additional proposal information
  87. pub metadata: Metadata,
  88. }
  89. impl BlockProposal {
  90. pub fn new(
  91. public_key: PublicKey,
  92. signature: Signature,
  93. id: u64,
  94. st: blake3::Hash,
  95. sl: u64,
  96. txs: Vec<Tx>,
  97. timestamp: Timestamp,
  98. proof: String,
  99. r: String,
  100. s: String,
  101. participants: Vec<Participant>,
  102. ) -> BlockProposal {
  103. BlockProposal {
  104. public_key,
  105. signature,
  106. id,
  107. st,
  108. sl,
  109. txs,
  110. metadata: Metadata::new(timestamp, proof, r, s, participants),
  111. }
  112. }
  113. }
  114. impl PartialEq for BlockProposal {
  115. fn eq(&self, other: &Self) -> bool {
  116. self.public_key == other.public_key &&
  117. self.signature == other.signature &&
  118. self.id == other.id &&
  119. self.st == other.st &&
  120. self.sl == other.sl &&
  121. self.txs == other.txs
  122. }
  123. }
  124. impl net::Message for BlockProposal {
  125. fn name() -> &'static str {
  126. "proposal"
  127. }
  128. }
  129. impl_vec!(BlockProposal);