sui_rpc_store/schema/
events.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4//! `tx_seq` → `StoredEvents`.
5
6use sui_consistent_store::Protobuf;
7use sui_consistent_store::error::DecodeError;
8use sui_consistent_store::error::Error;
9use sui_consistent_store::reader::Reader;
10use sui_types::effects::TransactionEvents;
11
12use crate::proto::StoredEvents;
13use crate::schema::primitives::U64Be;
14
15pub const NAME: &str = "events";
16
17pub type Key = U64Be;
18pub type Value = Protobuf<StoredEvents>;
19
20pub fn options(resolver: &sui_consistent_store::CfOptionsResolver) -> rocksdb::Options {
21    resolver.options(NAME)
22}
23
24/// Build a `StoredEvents` row from a transaction's events.
25///
26/// BCS-encode failures here would indicate either OOM or a bug in
27/// the type's `Serialize` impl; we panic rather than thread a
28/// `Result` through every call site.
29pub fn store(events: &TransactionEvents) -> Value {
30    let bcs = bcs::to_bytes(events).expect("bcs encode TransactionEvents");
31    Protobuf(StoredEvents { bcs: bcs.into() })
32}
33
34impl<R: Reader> super::RpcStoreSchema<R> {
35    /// Look up the events emitted by the transaction at the given
36    /// assigned `tx_seq`.
37    pub fn get_events(&self, tx_seq: u64) -> Result<Option<TransactionEvents>, Error> {
38        let Some(stored) = self.events.get(&U64Be(tx_seq))? else {
39            return Ok(None);
40        };
41        let events: TransactionEvents = bcs::from_bytes(&stored.into_inner().bcs)
42            .map_err(|e| DecodeError::with_source("bcs decode TransactionEvents", e))?;
43        Ok(Some(events))
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use sui_consistent_store::Db;
50    use sui_consistent_store::DbOptions;
51
52    use super::*;
53    use crate::RpcStoreSchema;
54
55    fn fresh_db() -> (tempfile::TempDir, sui_consistent_store::Db, RpcStoreSchema) {
56        let dir = tempfile::tempdir().unwrap();
57        let (db, schema) = Db::open::<RpcStoreSchema>(dir.path(), DbOptions::default()).unwrap();
58        (dir, db, schema)
59    }
60
61    #[test]
62    fn get_returns_none_for_unknown_seq() {
63        let (_dir, _db, schema) = fresh_db();
64        assert!(schema.get_events(7).unwrap().is_none());
65    }
66
67    #[test]
68    fn empty_events_round_trip() {
69        let (_dir, db, schema) = fresh_db();
70        let events = TransactionEvents::default();
71
72        let mut batch = db.batch();
73        batch
74            .put(&schema.events, &U64Be(42), &store(&events))
75            .unwrap();
76        batch.commit().unwrap();
77
78        let read = schema.get_events(42).unwrap().expect("events present");
79        assert_eq!(read, events);
80    }
81}