1use fastcrypto::traits::Signer;
5use std::mem;
6use sui_protocol_config::ProtocolConfig;
7use sui_types::base_types::{AuthorityName, VerifiedExecutionData};
8use sui_types::committee::Committee;
9use sui_types::crypto::{AuthoritySignInfo, AuthoritySignature, SuiAuthoritySignature};
10use sui_types::effects::{TransactionEffects, TransactionEffectsAPI};
11use sui_types::gas::GasCostSummary;
12use sui_types::messages_checkpoint::{
13 CertifiedCheckpointSummary, CheckpointContents, CheckpointSummary,
14 CheckpointVersionSpecificData, EndOfEpochData, FullCheckpointContents, VerifiedCheckpoint,
15 VerifiedCheckpointContents, VersionedFullCheckpointContents,
16};
17use sui_types::object::OBJECT_START_VERSION;
18use sui_types::transaction::{Transaction, VerifiedTransaction};
19
20use crate::accumulators::AccumulatorSettlementTxBuilder;
21
22pub trait ValidatorKeypairProvider {
23 fn get_validator_key(&self, name: &AuthorityName) -> &dyn Signer<AuthoritySignature>;
24 fn get_committee(&self) -> &Committee;
25}
26
27#[derive(Debug)]
30pub struct MockCheckpointBuilder {
31 previous_checkpoint: Option<VerifiedCheckpoint>,
32 transactions: Vec<VerifiedExecutionData>,
33 epoch_rolling_gas_cost_summary: GasCostSummary,
34 epoch: u64,
35}
36
37impl MockCheckpointBuilder {
38 pub fn new(previous_checkpoint: VerifiedCheckpoint) -> Self {
39 let epoch_rolling_gas_cost_summary =
40 previous_checkpoint.epoch_rolling_gas_cost_summary.clone();
41 let epoch = previous_checkpoint.epoch;
42
43 Self {
44 previous_checkpoint: Some(previous_checkpoint),
45 transactions: Vec::new(),
46 epoch_rolling_gas_cost_summary,
47 epoch,
48 }
49 }
50
51 pub fn size(&self) -> usize {
52 self.transactions.len()
53 }
54
55 pub fn epoch_rolling_gas_cost_summary(&self) -> &GasCostSummary {
56 &self.epoch_rolling_gas_cost_summary
57 }
58
59 pub fn push_transaction(
60 &mut self,
61 transaction: VerifiedTransaction,
62 effects: TransactionEffects,
63 ) {
64 self.epoch_rolling_gas_cost_summary += effects.gas_cost_summary();
65
66 self.transactions
67 .push(VerifiedExecutionData::new(transaction, effects))
68 }
69
70 pub fn get_next_checkpoint_number(&self) -> u64 {
71 self.previous_checkpoint
72 .as_ref()
73 .map(|c| c.sequence_number + 1)
74 .unwrap_or_default()
75 }
76
77 pub fn override_next_checkpoint_number(
80 &mut self,
81 checkpoint_number: u64,
82 validator_keys: &impl ValidatorKeypairProvider,
83 ) {
84 if checkpoint_number > 0 {
85 let mut summary = self.previous_checkpoint.as_ref().unwrap().data().clone();
86 summary.sequence_number = checkpoint_number - 1;
87 let checkpoint = Self::create_certified_checkpoint(validator_keys, summary);
88 self.previous_checkpoint = Some(checkpoint);
89 } else {
90 self.previous_checkpoint = None;
91 }
92 }
93
94 pub fn build(
96 &mut self,
97 validator_keys: &impl ValidatorKeypairProvider,
98 timestamp_ms: u64,
99 ) -> (
100 VerifiedCheckpoint,
101 CheckpointContents,
102 VerifiedCheckpointContents,
103 ) {
104 self.build_internal(validator_keys, timestamp_ms, None)
105 }
106
107 pub fn build_end_of_epoch(
108 &mut self,
109 validator_keys: &impl ValidatorKeypairProvider,
110 timestamp_ms: u64,
111 new_epoch: u64,
112 end_of_epoch_data: EndOfEpochData,
113 ) -> (
114 VerifiedCheckpoint,
115 CheckpointContents,
116 VerifiedCheckpointContents,
117 ) {
118 self.build_internal(
119 validator_keys,
120 timestamp_ms,
121 Some((new_epoch, end_of_epoch_data)),
122 )
123 }
124
125 pub fn get_settlement_txns(&self, protocol_config: &ProtocolConfig) -> Vec<Transaction> {
128 let effects: Vec<_> = self
129 .transactions
130 .iter()
131 .map(|e| e.effects.clone())
132 .collect();
133
134 let checkpoint_height = self.get_next_checkpoint_number();
135 let checkpoint_seq = checkpoint_height;
136
137 let builder = AccumulatorSettlementTxBuilder::new(None, &effects, checkpoint_seq, 0);
138
139 let (settlement_txns, barrier_tx) = builder.build_tx(
140 protocol_config,
141 self.epoch,
142 OBJECT_START_VERSION,
143 checkpoint_height,
144 checkpoint_seq,
145 );
146
147 settlement_txns
148 .into_iter()
149 .chain(std::iter::once(barrier_tx))
150 .map(|tx| VerifiedTransaction::new_system_transaction(tx).into_inner())
151 .collect()
152 }
153
154 fn build_internal(
155 &mut self,
156 validator_keys: &impl ValidatorKeypairProvider,
157 timestamp_ms: u64,
158 new_epoch_data: Option<(u64, EndOfEpochData)>,
159 ) -> (
160 VerifiedCheckpoint,
161 CheckpointContents,
162 VerifiedCheckpointContents,
163 ) {
164 let contents =
165 CheckpointContents::new_with_causally_ordered_execution_data(self.transactions.iter());
166 let full_contents =
167 VerifiedCheckpointContents::new_unchecked(VersionedFullCheckpointContents::V1(
168 FullCheckpointContents::new_with_causally_ordered_transactions(
169 mem::take(&mut self.transactions)
170 .into_iter()
171 .map(|e| e.into_inner()),
172 ),
173 ));
174
175 let (epoch, epoch_rolling_gas_cost_summary, end_of_epoch_data) =
176 if let Some((next_epoch, end_of_epoch_data)) = new_epoch_data {
177 let epoch = std::mem::replace(&mut self.epoch, next_epoch);
178 assert_eq!(next_epoch, epoch + 1);
179 let epoch_rolling_gas_cost_summary =
180 std::mem::take(&mut self.epoch_rolling_gas_cost_summary);
181
182 (
183 epoch,
184 epoch_rolling_gas_cost_summary,
185 Some(end_of_epoch_data),
186 )
187 } else {
188 (
189 self.epoch,
190 self.epoch_rolling_gas_cost_summary.clone(),
191 None,
192 )
193 };
194
195 let summary = CheckpointSummary {
196 epoch,
197 sequence_number: self
198 .previous_checkpoint
199 .as_ref()
200 .map(|c| c.sequence_number + 1)
201 .unwrap_or_default(),
202 network_total_transactions: self
203 .previous_checkpoint
204 .as_ref()
205 .map(|c| c.network_total_transactions)
206 .unwrap_or_default()
207 + contents.size() as u64,
208 content_digest: *contents.digest(),
209 previous_digest: self.previous_checkpoint.as_ref().map(|c| *c.digest()),
210 epoch_rolling_gas_cost_summary,
211 end_of_epoch_data,
212 timestamp_ms,
213 version_specific_data: bcs::to_bytes(&CheckpointVersionSpecificData::empty_for_tests())
214 .unwrap(),
215 checkpoint_commitments: Default::default(),
216 };
217
218 let checkpoint = Self::create_certified_checkpoint(validator_keys, summary);
219 self.previous_checkpoint = Some(checkpoint.clone());
220 (checkpoint, contents, full_contents)
221 }
222
223 fn create_certified_checkpoint(
224 validator_keys: &impl ValidatorKeypairProvider,
225 checkpoint: CheckpointSummary,
226 ) -> VerifiedCheckpoint {
227 let signatures = validator_keys
228 .get_committee()
229 .voting_rights
230 .iter()
231 .map(|(name, _)| {
232 let intent_msg = shared_crypto::intent::IntentMessage::new(
233 shared_crypto::intent::Intent::sui_app(
234 shared_crypto::intent::IntentScope::CheckpointSummary,
235 ),
236 &checkpoint,
237 );
238 let key = validator_keys.get_validator_key(name);
239 let signature = AuthoritySignature::new_secure(&intent_msg, &checkpoint.epoch, key);
240 AuthoritySignInfo {
241 epoch: checkpoint.epoch,
242 authority: *name,
243 signature,
244 }
245 })
246 .collect();
247
248 let checkpoint_cert =
249 CertifiedCheckpointSummary::new(checkpoint, signatures, validator_keys.get_committee())
250 .unwrap();
251 VerifiedCheckpoint::new_unchecked(checkpoint_cert)
252 }
253}