txstore.rs 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. use sled::Batch;
  2. use crate::{
  3. tx::Transaction,
  4. util::serial::{deserialize, serialize},
  5. Error, Result,
  6. };
  7. const SLED_TX_TREE: &[u8] = b"_transactions";
  8. pub struct TxStore(sled::Tree);
  9. impl TxStore {
  10. /// Opens a new or existing `TxStore` on the given sled database.
  11. pub fn new(db: &sled::Db) -> Result<Self> {
  12. let tree = db.open_tree(SLED_TX_TREE)?;
  13. Ok(Self(tree))
  14. }
  15. /// Insert a slice of [`Transaction`] into the txstore. With sled, the
  16. /// operation is done as a batch.
  17. /// The transactions are hashed with BLAKE3 and this hash is
  18. /// used as the key, while value is the serialized tx itself.
  19. pub fn insert(&self, txs: &[Transaction]) -> Result<Vec<blake3::Hash>> {
  20. let mut ret = Vec::with_capacity(txs.len());
  21. let mut batch = Batch::default();
  22. for i in txs {
  23. let serialized = serialize(i);
  24. let txhash = blake3::hash(&serialized);
  25. batch.insert(txhash.as_bytes(), serialized);
  26. ret.push(txhash);
  27. }
  28. self.0.apply_batch(batch)?;
  29. Ok(ret)
  30. }
  31. /// Check if the txstore contains a given transaction.
  32. pub fn contains(&self, txid: blake3::Hash) -> Result<bool> {
  33. Ok(self.0.contains_key(txid.as_bytes())?)
  34. }
  35. /// Fetch requested transactions from the txstore. The `strict` param
  36. /// will make the function fail if a transaction has not been found.
  37. pub fn get(
  38. &self,
  39. tx_hashes: &[blake3::Hash],
  40. strict: bool,
  41. ) -> Result<Vec<Option<Transaction>>> {
  42. let mut ret: Vec<Option<Transaction>> = Vec::with_capacity(tx_hashes.len());
  43. for i in tx_hashes {
  44. if let Some(found) = self.0.get(i.as_bytes())? {
  45. let tx = deserialize(&found)?;
  46. ret.push(Some(tx));
  47. } else {
  48. if strict {
  49. let s = i.to_hex().as_str().to_string();
  50. return Err(Error::TransactionNotFound(s))
  51. }
  52. ret.push(None);
  53. }
  54. }
  55. Ok(ret)
  56. }
  57. /// Retrieve all transactions.
  58. /// Be careful as this will try to load everything in memory.
  59. pub fn get_all(&self) -> Result<Vec<Option<(blake3::Hash, Transaction)>>> {
  60. let mut txs = vec![];
  61. let iterator = self.0.into_iter().enumerate();
  62. for (_, r) in iterator {
  63. let (k, v) = r.unwrap();
  64. let hash_bytes: [u8; 32] = k.as_ref().try_into().unwrap();
  65. let tx = deserialize(&v)?;
  66. txs.push(Some((hash_bytes.into(), tx)));
  67. }
  68. Ok(txs)
  69. }
  70. }