sui_rpc_store/schema/
checkpoint_summary.rs1use sui_consistent_store::Protobuf;
12use sui_consistent_store::error::DecodeError;
13use sui_consistent_store::error::Error;
14use sui_consistent_store::reader::Reader;
15use sui_types::crypto::AuthorityStrongQuorumSignInfo;
16use sui_types::messages_checkpoint::CertifiedCheckpointSummary;
17use sui_types::messages_checkpoint::CheckpointSequenceNumber;
18use sui_types::messages_checkpoint::CheckpointSummary;
19use sui_types::messages_checkpoint::VerifiedCheckpoint;
20
21use crate::proto::StoredCheckpointSummary;
22use crate::schema::primitives::U64Be;
23
24pub const NAME: &str = "checkpoint_summary";
25
26pub type Key = U64Be;
27pub type Value = Protobuf<StoredCheckpointSummary>;
28
29pub fn options(resolver: &sui_consistent_store::CfOptionsResolver) -> rocksdb::Options {
30 resolver.options(NAME)
31}
32
33pub fn store(summary: &CheckpointSummary, signature: &AuthorityStrongQuorumSignInfo) -> Value {
40 let summary_bcs = bcs::to_bytes(summary).expect("bcs encode CheckpointSummary");
41 let signature_bcs = bcs::to_bytes(signature).expect("bcs encode AuthorityStrongQuorumSignInfo");
42 Protobuf(StoredCheckpointSummary {
43 summary_bcs: summary_bcs.into(),
44 signature_bcs: signature_bcs.into(),
45 })
46}
47
48impl<R: Reader> super::RpcStoreSchema<R> {
49 pub fn get_checkpoint_summary(
56 &self,
57 seq: CheckpointSequenceNumber,
58 ) -> Result<Option<VerifiedCheckpoint>, Error> {
59 let Some(stored) = self.checkpoint_summary.get(&U64Be(seq))? else {
60 return Ok(None);
61 };
62 let stored = stored.into_inner();
63 let summary: CheckpointSummary = bcs::from_bytes(&stored.summary_bcs)
64 .map_err(|e| DecodeError::with_source("bcs decode CheckpointSummary", e))?;
65 let signature: AuthorityStrongQuorumSignInfo = bcs::from_bytes(&stored.signature_bcs)
66 .map_err(|e| DecodeError::with_source("bcs decode AuthorityStrongQuorumSignInfo", e))?;
67 let certified = CertifiedCheckpointSummary::new_from_data_and_sig(summary, signature);
68 Ok(Some(VerifiedCheckpoint::new_unchecked(certified)))
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use sui_consistent_store::Db;
75 use sui_consistent_store::DbOptions;
76 use sui_types::crypto::AggregateAuthoritySignature;
77 use sui_types::digests::CheckpointContentsDigest;
78 use sui_types::gas::GasCostSummary;
79
80 use super::*;
81 use crate::RpcStoreSchema;
82
83 fn fresh_db() -> (tempfile::TempDir, sui_consistent_store::Db, RpcStoreSchema) {
84 let dir = tempfile::tempdir().unwrap();
85 let (db, schema) = Db::open::<RpcStoreSchema>(dir.path(), DbOptions::default()).unwrap();
86 (dir, db, schema)
87 }
88
89 fn dummy_summary(seq: CheckpointSequenceNumber) -> CheckpointSummary {
90 CheckpointSummary {
91 epoch: 0,
92 sequence_number: seq,
93 network_total_transactions: 0,
94 content_digest: CheckpointContentsDigest::random(),
95 previous_digest: None,
96 epoch_rolling_gas_cost_summary: GasCostSummary::default(),
97 timestamp_ms: 0,
98 checkpoint_commitments: Vec::new(),
99 end_of_epoch_data: None,
100 version_specific_data: Vec::new(),
101 }
102 }
103
104 fn dummy_sig() -> AuthorityStrongQuorumSignInfo {
105 AuthorityStrongQuorumSignInfo {
108 epoch: 0,
109 signature: AggregateAuthoritySignature::default(),
110 signers_map: Default::default(),
111 }
112 }
113
114 #[test]
115 fn get_returns_none_for_unknown_seq() {
116 let (_dir, _db, schema) = fresh_db();
117 assert!(schema.get_checkpoint_summary(7).unwrap().is_none());
118 }
119
120 #[test]
121 fn store_then_get_round_trips() {
122 let (_dir, db, schema) = fresh_db();
123 let summary = dummy_summary(42);
124 let sig = dummy_sig();
125
126 let mut batch = db.batch();
127 batch
128 .put(
129 &schema.checkpoint_summary,
130 &U64Be(42),
131 &store(&summary, &sig),
132 )
133 .unwrap();
134 batch.commit().unwrap();
135
136 let read = schema
137 .get_checkpoint_summary(42)
138 .unwrap()
139 .expect("checkpoint present");
140 assert_eq!(read.data(), &summary);
141 assert_eq!(read.auth_sig().epoch, sig.epoch);
142 let read_sig_bcs = bcs::to_bytes(read.auth_sig()).unwrap();
145 let expected_sig_bcs = bcs::to_bytes(&sig).unwrap();
146 assert_eq!(read_sig_bcs, expected_sig_bcs);
147 }
148
149 #[test]
150 fn overwrite_replaces_previous() {
151 let (_dir, db, schema) = fresh_db();
152 let first = dummy_summary(42);
153 let later = dummy_summary(42);
154 let later_digest = later.content_digest;
155 let sig = dummy_sig();
156
157 let mut batch = db.batch();
158 batch
159 .put(&schema.checkpoint_summary, &U64Be(42), &store(&first, &sig))
160 .unwrap();
161 batch
162 .put(&schema.checkpoint_summary, &U64Be(42), &store(&later, &sig))
163 .unwrap();
164 batch.commit().unwrap();
165
166 let read = schema
167 .get_checkpoint_summary(42)
168 .unwrap()
169 .expect("checkpoint present");
170 assert_eq!(read.data().content_digest, later_digest);
171 }
172}