Skip to content

Commit ac782db

Browse files
committed
Add expelled and verify_reserved_state
1 parent c53c9f8 commit ac782db

File tree

4 files changed

+83
-37
lines changed

4 files changed

+83
-37
lines changed

Diff for: core/src/reserved.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ impl ReservedState {
2525
let validator_set = self
2626
.members
2727
.iter()
28+
.filter(|member| member.expelled == false)
2829
.map(|member| {
2930
let name = member
3031
.consensus_delegatee
@@ -55,6 +56,7 @@ impl ReservedState {
5556
let governance_set = self
5657
.members
5758
.iter()
59+
.filter(|member| member.expelled == false)
5860
.map(|member| {
5961
let name = member
6062
.governance_delegatee
@@ -92,7 +94,7 @@ impl ReservedState {
9294
return Err("delegation proof verification failed".to_string());
9395
}
9496
for delegator in &mut self.members {
95-
if delegator.name == tx.data.delegator {
97+
if delegator.name == tx.data.delegator && delegator.expelled == false {
9698
if tx.data.governance {
9799
delegator.governance_delegatee = Some(tx.data.delegatee.clone());
98100
delegator.consensus_delegatee = Some(tx.data.delegatee.clone());
@@ -110,7 +112,7 @@ impl ReservedState {
110112
return Err("delegation proof verification failed".to_string());
111113
}
112114
for delegator in &mut self.members {
113-
if delegator.name == tx.data.delegator {
115+
if delegator.name == tx.data.delegator && delegator.expelled == false {
114116
if delegator.consensus_delegatee.is_some() {
115117
delegator.consensus_delegatee = None;
116118
delegator.governance_delegatee = None;
@@ -157,6 +159,7 @@ mod tests {
157159
consensus_voting_power: 1,
158160
governance_delegatee: None,
159161
consensus_delegatee: None,
162+
expelled: false,
160163
}
161164
}
162165

@@ -172,6 +175,7 @@ mod tests {
172175
consensus_voting_power: 1,
173176
governance_delegatee: None,
174177
consensus_delegatee: Some(format!("member-{delegatee_member_num:04}")),
178+
expelled: false,
175179
}
176180
}
177181

@@ -187,6 +191,7 @@ mod tests {
187191
consensus_voting_power: 1,
188192
governance_delegatee: Some(format!("member-{delegatee_member_num:04}")),
189193
consensus_delegatee: None,
194+
expelled: false,
190195
}
191196
}
192197

Diff for: core/src/test_utils.rs

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub fn generate_standard_genesis(
1919
consensus_voting_power: 1,
2020
governance_delegatee: None,
2121
consensus_delegatee: None,
22+
expelled: false,
2223
})
2324
.collect::<Vec<_>>();
2425
let genesis_header = BlockHeader {
@@ -100,6 +101,7 @@ pub fn generate_delegated_genesis(
100101
} else {
101102
None
102103
},
104+
expelled: false,
103105
})
104106
.collect::<Vec<_>>();
105107
let genesis_header = BlockHeader {

Diff for: core/src/types.rs

+4
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ pub struct Member {
2828
// - Unlock-Automatically-After-T-Seconds
2929
// - Unlock-If-The-Delegatee-Is-Not-Active
3030
// - Unlock-If-The-Validator-Set-Changes
31+
/// If true, all voting powers are ignored.
32+
/// Note that once granted, Simperby keeps all members forever in the reserved state.
33+
/// If you want to remove a member, you must set this to true instead of removing the member.
34+
pub expelled: bool,
3135
}
3236

3337
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]

Diff for: core/src/verify.rs

+70-35
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,23 @@ pub fn verify_finalization_proof(
8787
Ok(())
8888
}
8989

90+
/// Verifies the version of input reserved state is valid.
91+
pub fn verify_version_syntax(s: &str) -> bool {
92+
let mut segments = s.split('.');
93+
94+
let is_valid_segment = |segment: &str| {
95+
segment.parse::<u32>().map_or(false, |number| number < 10)
96+
};
97+
98+
segments.next().map_or(false, is_valid_segment)
99+
&& segments.next().map_or(false, is_valid_segment)
100+
&& segments.next().map_or(false, is_valid_segment)
101+
&& segments.next().is_none()
102+
}
103+
90104
// Phases of the `CommitSequenceVerifier`.
91105
//
92-
// Note that `Phase::X` is agenda phase where `Commit::X` is the last commit.
106+
// Note that `Phase::X` is the phase where `Commit::X` is the last commit.
93107
#[derive(Debug, Clone, PartialEq, Eq)]
94108
enum Phase {
95109
// The transaction phase.
@@ -131,6 +145,9 @@ pub struct CommitSequenceVerifier {
131145
impl CommitSequenceVerifier {
132146
/// Creates a new `CommitSequenceVerifier` with the given block header.
133147
pub fn new(start_header: BlockHeader, reserved_state: ReservedState) -> Result<Self, Error> {
148+
// if verify_reserved_state(&self, reserved_state)? {
149+
// return Err(Error::InvalidArgument(format!("Reserved state is not valid")));
150+
// }
134151
Ok(Self {
135152
header: start_header.clone(),
136153
phase: Phase::Block,
@@ -173,21 +190,43 @@ impl CommitSequenceVerifier {
173190

174191
/// Verifies whether the given reserved state is valid from the current state.
175192
pub fn verify_reserved_state(&self, _rs: &ReservedState) -> Result<(), Error> {
176-
// TODO:
177-
// 1. Check that the number of members is at least 4.
178-
// 2. Check that the version advances correctly.
193+
if _rs.members.len() < 4 {
194+
return Err(Error::InvalidArgument(format!("Number of members is not over 4")));
195+
}
196+
if self.reserved_state.version != _rs.version {
197+
if !(self.reserved_state.version < _rs.version && verify_version_syntax(&_rs.version)) {
198+
return Err(Error::InvalidArgument(format!("Version advances is incorrect")));
199+
}
200+
}
179201
// 3. Check that `consensus_leader_order` is correct.
180-
// 4. Check that `genesis_info` stays the same.
202+
if self.reserved_state.consensus_leader_order != _rs.consensus_leader_order {
203+
return Err(Error::InvalidArgument(format!("Consensus leader order is incorrect")));
204+
}
205+
if self.reserved_state.genesis_info != _rs.genesis_info {
206+
return Err(Error::InvalidArgument(format!("Genesis_info is not stays the same")));
207+
}
181208
// 5. Check that the newly added (if exists) `Member::name` is unique.
182-
// 6. Check that `member` monotonicaly increases (refer to `Member::expelled`).
183-
// 7. Check that the delegation state doesn't change.
209+
if !self.reserved_state.members.iter().all(|m1| _rs.members.iter().any(|m2| m1.public_key == m2.public_key)) {
210+
return Err(Error::InvalidArgument(format!("New member set do not have all previous member")));
211+
}
212+
let public_key_set: HashSet<&PublicKey> = _rs.members.iter().map(|m| &m.public_key).collect();
213+
if public_key_set.len() != _rs.members.len() {
214+
return Err(Error::InvalidArgument(format!("Newly added member public keys are not unique")));
215+
}
216+
// 6. Check that `member` monotonic increases (refer to `Member::expelled`).
217+
if _rs.members.iter().any(|member| member.expelled) {
218+
return Err(Error::InvalidArgument(format!("Member expulsion time not monotonic increasing")));
219+
}
184220
Ok(())
185221
}
186222

187223
/// Verifies the given commit and updates the internal reserved_state of CommitSequenceVerifier.
188224
pub fn apply_commit(&mut self, commit: &Commit) -> Result<(), Error> {
189225
match (commit, &mut self.phase) {
190226
(Commit::Block(block_header), Phase::AgendaProof { agenda_proof: _ }) => {
227+
if self.reserved_state.version != block_header.version {
228+
return Err(Error::InvalidArgument(format!("Version of header is not match reserved_state")));
229+
}
191230
verify_header_to_header(&self.header, block_header)?;
192231
// Verify commit merkle root
193232
let commit_merkle_root =
@@ -202,12 +241,10 @@ impl CommitSequenceVerifier {
202241
self.phase = Phase::Block;
203242
self.commits_for_next_block = vec![];
204243
}
205-
(
206-
Commit::Block(block_header),
207-
Phase::ExtraAgendaTransaction {
208-
last_extra_agenda_timestamp,
209-
},
210-
) => {
244+
(Commit::Block(block_header), Phase::ExtraAgendaTransaction {last_extra_agenda_timestamp,}) => {
245+
if self.reserved_state.version != block_header.version {
246+
return Err(Error::InvalidArgument(format!("Version of header is not match reserved_state")));
247+
}
211248
verify_header_to_header(&self.header, block_header)?;
212249
// Check if the block contains all the extra-agenda transactions.
213250
if block_header.timestamp < *last_extra_agenda_timestamp {
@@ -232,20 +269,15 @@ impl CommitSequenceVerifier {
232269
(Commit::Transaction(tx), Phase::Block) => {
233270
// Update reserved_state for reserved-diff transactions.
234271
if let Diff::Reserved(rs) = &tx.diff {
272+
self.verify_reserved_state(rs)?;
235273
self.reserved_state = *rs.clone();
236274
}
237275
self.phase = Phase::Transaction {
238276
last_transaction: tx.clone(),
239277
preceding_transactions: vec![],
240278
};
241279
}
242-
(
243-
Commit::Transaction(tx),
244-
Phase::Transaction {
245-
last_transaction,
246-
preceding_transactions,
247-
},
248-
) => {
280+
(Commit::Transaction(tx), Phase::Transaction {last_transaction, preceding_transactions}) => {
249281
// Check if transactions are in chronological order
250282
if tx.timestamp < last_transaction.timestamp {
251283
return Err(Error::InvalidArgument(format!(
@@ -255,6 +287,7 @@ impl CommitSequenceVerifier {
255287
}
256288
// Update reserved_state for reserved-diff transactions.
257289
if let Diff::Reserved(rs) = &tx.diff {
290+
self.verify_reserved_state(rs)?;
258291
self.reserved_state = *rs.clone();
259292
}
260293
preceding_transactions.push(last_transaction.clone());
@@ -281,13 +314,7 @@ impl CommitSequenceVerifier {
281314
agenda: agenda.clone(),
282315
};
283316
}
284-
(
285-
Commit::Agenda(agenda),
286-
Phase::Transaction {
287-
last_transaction,
288-
preceding_transactions,
289-
},
290-
) => {
317+
(Commit::Agenda(agenda), Phase::Transaction {last_transaction, preceding_transactions}) => {
291318
// Check if agenda is associated with the current block sequence.
292319
if agenda.height != self.header.height + 1 {
293320
return Err(Error::InvalidArgument(format!(
@@ -398,12 +425,7 @@ impl CommitSequenceVerifier {
398425
ExtraAgendaTransaction::Report(_tx) => unimplemented!(),
399426
}
400427
}
401-
(
402-
Commit::ExtraAgendaTransaction(tx),
403-
Phase::ExtraAgendaTransaction {
404-
last_extra_agenda_timestamp,
405-
},
406-
) => {
428+
(Commit::ExtraAgendaTransaction(tx), Phase::ExtraAgendaTransaction {last_extra_agenda_timestamp}) => {
407429
match tx {
408430
ExtraAgendaTransaction::Delegate(tx) => {
409431
// Update reserved reserved_state by applying delegation
@@ -434,8 +456,7 @@ impl CommitSequenceVerifier {
434456
ExtraAgendaTransaction::Report(_tx) => unimplemented!(),
435457
}
436458
}
437-
(Commit::ChatLog(_chat_log), _) => unimplemented!(),
438-
(commit, phase) => {
459+
(Commit::ChatLog(_chat_log), _) => unimplemented!(), (commit, phase) => {
439460
return Err(Error::PhaseMismatch(
440461
format!("{commit:?}"),
441462
format!("{phase:?}"),
@@ -498,6 +519,7 @@ mod test {
498519
consensus_voting_power: *voting_power,
499520
governance_delegatee: None,
500521
consensus_delegatee: None,
522+
expelled: false,
501523
});
502524
}
503525
members
@@ -582,6 +604,7 @@ mod test {
582604
consensus_voting_power: 1,
583605
governance_delegatee: None,
584606
consensus_delegatee: None,
607+
expelled: false,
585608
});
586609
reserved_state
587610
.consensus_leader_order
@@ -1567,4 +1590,16 @@ mod test {
15671590

15681591
// TODO: add test cases where the `Report` extra-agenda transactions are invalid.
15691592
// These test cases are TODO because the `Report` extra-agenda transaction is not implemented yet.
1593+
1594+
//#[test]
1595+
// Test the case where check verify_reserved_state function run well
1596+
// fn check_verify_reserved_state_run() {
1597+
// let (validator_keypair, reserved_state, mut csv) = setup_test(3);
1598+
// csv.verify_reserved_state(&reserved_state).unwrap_err();
1599+
1600+
1601+
// //make wrong reserved_state
1602+
// //chech vrs function
1603+
1604+
// }
15701605
}

0 commit comments

Comments
 (0)