Skip to content

Commit 6e77495

Browse files
committed
Implement report_double_vote custom action
1 parent 5977378 commit 6e77495

File tree

15 files changed

+211
-34
lines changed

15 files changed

+211
-34
lines changed

core/src/consensus/mod.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub use self::solo::Solo;
3434
pub use self::tendermint::{Tendermint, TendermintParams, TimeGapParams};
3535
pub use self::validator_set::validator_list::RoundRobinValidator;
3636
pub use self::validator_set::ValidatorSet;
37+
pub use self::vote_collector::Message;
3738

3839
use std::fmt;
3940
use std::sync::{Arc, Weak};
@@ -279,6 +280,10 @@ pub trait ConsensusEngine: Sync + Send {
279280
self.action_handlers().iter().find(|handler| handler.handler_id() == id).map(AsRef::as_ref)
280281
}
281282

283+
fn get_validator_set(&self) -> Option<Arc<ValidatorSet>> {
284+
None
285+
}
286+
282287
fn possible_authors(&self, block_number: Option<u64>) -> Result<Option<Vec<Address>>, EngineError>;
283288
}
284289

@@ -359,6 +364,7 @@ pub trait CodeChainEngine: ConsensusEngine {
359364
&self,
360365
tx: &UnverifiedTransaction,
361366
common_params: &CommonParams,
367+
parent: &H256,
362368
) -> Result<(), Error> {
363369
if let Action::Custom {
364370
handler_id,
@@ -368,7 +374,8 @@ pub trait CodeChainEngine: ConsensusEngine {
368374
let handler = self
369375
.find_action_handler_for(*handler_id)
370376
.ok_or_else(|| SyntaxError::InvalidCustomAction(format!("{} is an invalid handler id", handler_id)))?;
371-
handler.verify(bytes, common_params)?;
377+
let validators = self.get_validator_set().map(|set| set.get_whole_publics(parent));
378+
handler.verify(bytes, common_params, validators)?;
372379
}
373380
self.machine().verify_transaction_with_params(tx, common_params)
374381
}

core/src/consensus/solo/mod.rs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,18 @@ mod params;
1818

1919
use std::sync::Arc;
2020

21-
use ckey::Address;
21+
use ckey::{Address, SchnorrSignature};
22+
use primitives::{Bytes, H256};
2223
use cstate::{ActionHandler, HitHandler};
2324
use ctypes::{CommonParams, Header};
25+
use rlp::{Decodable, Encodable, UntrustedRlp, RlpStream, DecoderError};
2426

2527
use self::params::SoloParams;
2628
use super::stake;
2729
use super::{ConsensusEngine, Seal};
2830
use crate::block::{ExecutedBlock, IsBlock};
2931
use crate::codechain_machine::CodeChainMachine;
30-
use crate::consensus::{EngineError, EngineType};
32+
use crate::consensus::{EngineError, EngineType, Message};
3133
use crate::error::Error;
3234

3335
/// A consensus engine which does not provide any consensus mechanism.
@@ -37,14 +39,45 @@ pub struct Solo {
3739
action_handlers: Vec<Arc<ActionHandler>>,
3840
}
3941

42+
#[derive(Debug, PartialEq, Eq, Clone, Hash, Default)]
43+
pub struct SoloMessage {}
44+
45+
impl Encodable for SoloMessage {
46+
fn rlp_append(&self, s: &mut RlpStream) {
47+
s.append_empty_data();
48+
}
49+
}
50+
51+
impl Decodable for SoloMessage {
52+
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
53+
Ok(SoloMessage{})
54+
}
55+
}
56+
57+
impl Message for SoloMessage {
58+
type Round = bool;
59+
60+
fn signature(&self) -> SchnorrSignature {SchnorrSignature::random()}
61+
62+
fn signer_index(&self) -> usize {Default::default()}
63+
64+
fn block_hash(&self) -> Option<H256> {None}
65+
66+
fn round(&self) -> &bool {&false}
67+
68+
fn is_broadcastable(&self) -> bool {false}
69+
70+
fn message_for_signature(&self) -> Bytes {Default::default()}
71+
}
72+
4073
impl Solo {
4174
/// Returns new instance of Solo over the given state machine.
4275
pub fn new(params: SoloParams, machine: CodeChainMachine) -> Self {
4376
let mut action_handlers: Vec<Arc<ActionHandler>> = Vec::new();
4477
if params.enable_hit_handler {
4578
action_handlers.push(Arc::new(HitHandler::new()));
4679
}
47-
action_handlers.push(Arc::new(stake::Stake::new(params.genesis_stakes.clone())));
80+
action_handlers.push(Arc::new(stake::Stake::<SoloMessage>::new(params.genesis_stakes.clone())));
4881

4982
Solo {
5083
params,

core/src/consensus/stake/actions.rs

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,24 @@
1414
// You should have received a copy of the GNU Affero General Public License
1515
// along with this program. If not, see <https://www.gnu.org/licenses/>.
1616

17-
use ccrypto::Blake;
18-
use ckey::{recover, Address, Signature};
17+
use ccrypto::{blake256, Blake};
18+
use ckey::{recover, verify_schnorr, Address, Public, Signature};
1919
use ctypes::errors::SyntaxError;
2020
use ctypes::CommonParams;
2121
use primitives::{Bytes, H256};
2222
use rlp::{Decodable, DecoderError, Encodable, RlpStream, UntrustedRlp};
2323

24+
use consensus::vote_collector::Message;
25+
2426
const ACTION_TAG_TRANSFER_CCS: u8 = 1;
2527
const ACTION_TAG_DELEGATE_CCS: u8 = 2;
2628
const ACTION_TAG_REVOKE: u8 = 3;
2729
const ACTION_TAG_SELF_NOMINATE: u8 = 4;
30+
const ACTION_TAG_REPORT_DOUBLE_VOTE: u8 = 5;
2831
const ACTION_TAG_CHANGE_PARAMS: u8 = 0xFF;
2932

3033
#[derive(Debug, PartialEq)]
31-
pub enum Action {
34+
pub enum Action<M: Message> {
3235
TransferCCS {
3336
address: Address,
3437
quantity: u64,
@@ -50,10 +53,14 @@ pub enum Action {
5053
params: Box<CommonParams>,
5154
signatures: Vec<Signature>,
5255
},
56+
ReportDoubleVote {
57+
message1: M,
58+
message2: M,
59+
},
5360
}
5461

55-
impl Action {
56-
pub fn verify(&self, current_params: &CommonParams) -> Result<(), SyntaxError> {
62+
impl<M: Message> Action<M> {
63+
pub fn verify(&self, current_params: &CommonParams, signers: Option<Vec<Public>>) -> Result<(), SyntaxError> {
5764
match self {
5865
Action::TransferCCS {
5966
..
@@ -102,12 +109,40 @@ impl Action {
102109
})?;
103110
}
104111
}
112+
Action::ReportDoubleVote {
113+
message1,
114+
message2,
115+
} => {
116+
// what is the general verifying for general message?
117+
let message_for_signature = message1.message_for_signature();
118+
let message_hash = blake256(&message_for_signature);
119+
120+
let signature1 = message1.signature();
121+
let signature2 = message2.signature();
122+
123+
let signer_idx1 = message1.signer_index();
124+
let signer_idx2 = message2.signer_index();
125+
126+
let signers = signers.ok_or(SyntaxError::InvalidCustomAction(String::from(
127+
"ReportDoubleVote Custom action is invalid for consensus engines without validators",
128+
)))?;
129+
let signer1 = signers
130+
.get(signer_idx1)
131+
.ok_or(SyntaxError::InvalidCustomAction(String::from("Invalid signer index")))?;
132+
let signer2 = signers
133+
.get(signer_idx2)
134+
.ok_or(SyntaxError::InvalidCustomAction(String::from("Invalid signer index")))?;
135+
136+
verify_schnorr(signer1, &signature1, &message_hash)
137+
.and(verify_schnorr(signer2, &signature2, &message_hash))
138+
.map_err(|err| SyntaxError::InvalidCustomAction(format!("{}", err)));
139+
}
105140
}
106141
Ok(())
107142
}
108143
}
109144

110-
impl Encodable for Action {
145+
impl<M: Message> Encodable for Action<M> {
111146
fn rlp_append(&self, s: &mut RlpStream) {
112147
match self {
113148
Action::TransferCCS {
@@ -147,11 +182,17 @@ impl Encodable for Action {
147182
s.append(signature);
148183
}
149184
}
185+
Action::ReportDoubleVote {
186+
message1,
187+
message2,
188+
} => {
189+
s.begin_list(3).append(&ACTION_TAG_REPORT_DOUBLE_VOTE).append(message1).append(message2);
190+
}
150191
};
151192
}
152193
}
153194

154-
impl Decodable for Action {
195+
impl<M: Message> Decodable for Action<M> {
155196
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
156197
let tag = rlp.val_at(0)?;
157198
match tag {
@@ -224,6 +265,21 @@ impl Decodable for Action {
224265
signatures,
225266
})
226267
}
268+
ACTION_TAG_REPORT_DOUBLE_VOTE => {
269+
let item_count = rlp.item_count()?;
270+
if item_count != 3 {
271+
return Err(DecoderError::RlpIncorrectListLen {
272+
expected: 3,
273+
got: item_count,
274+
})
275+
}
276+
let message1 = rlp.val_at(1)?;
277+
let message2 = rlp.val_at(2)?;
278+
Ok(Action::ReportDoubleVote {
279+
message1,
280+
message2,
281+
})
282+
}
227283
_ => Err(DecoderError::Custom("Unexpected Tendermint Stake Action Type")),
228284
}
229285
}
@@ -247,7 +303,7 @@ mod tests {
247303
expected: 4,
248304
got: 3,
249305
}),
250-
UntrustedRlp::new(&rlp::encode(&action)).as_val::<Action>()
306+
UntrustedRlp::new(&rlp::encode(&action)).as_val::<Action>::<_>()
251307
);
252308
}
253309

core/src/consensus/stake/mod.rs

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,27 +30,31 @@ use ctypes::{CommonParams, Header};
3030
use primitives::{Bytes, H256};
3131
use rlp::{Decodable, UntrustedRlp};
3232

33+
pub use self::action_data::Banned;
3334
pub use self::action_data::Validators;
3435
use self::action_data::{Candidates, Delegation, IntermediateRewards, Jail, ReleaseResult, StakeAccount, Stakeholders};
3536
use self::actions::Action;
3637
pub use self::distribute::fee_distribute;
37-
use consensus::stake::action_data::Banned;
38+
use consensus::vote_collector::Message;
39+
use std::marker::PhantomData;
3840

3941
const CUSTOM_ACTION_HANDLER_ID: u64 = 2;
4042

41-
pub struct Stake {
43+
pub struct Stake<M> {
4244
genesis_stakes: HashMap<Address, u64>,
45+
phantom: PhantomData<M>,
4346
}
4447

45-
impl Stake {
46-
pub fn new(genesis_stakes: HashMap<Address, u64>) -> Stake {
48+
impl<M> Stake<M> {
49+
pub fn new(genesis_stakes: HashMap<Address, u64>) -> Stake<M> {
4750
Stake {
4851
genesis_stakes,
52+
phantom: PhantomData,
4953
}
5054
}
5155
}
5256

53-
impl ActionHandler for Stake {
57+
impl<M: Message> ActionHandler for Stake<M> {
5458
fn name(&self) -> &'static str {
5559
"stake handler"
5660
}
@@ -80,7 +84,7 @@ impl ActionHandler for Stake {
8084
sender: &Address,
8185
sender_public: &Public,
8286
) -> StateResult<()> {
83-
let action = Action::decode(&UntrustedRlp::new(bytes)).expect("Verification passed");
87+
let action = Action::<M>::decode(&UntrustedRlp::new(bytes)).expect("Verification passed");
8488
match action {
8589
Action::TransferCCS {
8690
address,
@@ -116,13 +120,22 @@ impl ActionHandler for Stake {
116120
params,
117121
signatures,
118122
} => change_params(state, metadata_seq, *params, &signatures),
123+
Action::ReportDoubleVote {
124+
message1,
125+
..
126+
} => ban_double_vote_account(state, sender_public, message1),
119127
}
120128
}
121129

122-
fn verify(&self, bytes: &[u8], current_params: &CommonParams) -> Result<(), SyntaxError> {
123-
let action = Action::decode(&UntrustedRlp::new(bytes))
130+
fn verify(
131+
&self,
132+
bytes: &[u8],
133+
current_params: &CommonParams,
134+
validators: Option<Vec<Public>>,
135+
) -> Result<(), SyntaxError> {
136+
let action = Action::<M>::decode(&UntrustedRlp::new(bytes))
124137
.map_err(|err| SyntaxError::InvalidCustomAction(err.to_string()))?;
125-
action.verify(current_params)
138+
action.verify(current_params, validators)
126139
}
127140

128141
fn on_close_block(
@@ -228,6 +241,19 @@ fn self_nominate(
228241
Ok(())
229242
}
230243

244+
pub fn ban_double_vote_account<M: Message>(
245+
state: &TopLevelState,
246+
sender_public: &Public,
247+
message: M,
248+
) -> StateResult<()> {
249+
let idx = message.signer_index();
250+
let validators = get_validators(state)?;
251+
let pubkey = validators.pubkeys().get(idx).expect("Index was verified");
252+
253+
ban(&mut state, sender_public, public_to_address(pubkey))?;
254+
Ok(())
255+
}
256+
231257
pub fn get_stakes(state: &TopLevelState) -> StateResult<HashMap<Address, u64>> {
232258
let stakeholders = Stakeholders::load_from_state(state)?;
233259
let mut result = HashMap::new();
@@ -243,6 +269,10 @@ pub fn get_validators(state: &TopLevelState) -> StateResult<Validators> {
243269
Validators::load_from_state(state)
244270
}
245271

272+
pub fn get_banned_accounts(state: &TopLevelState) -> StateResult<Banned> {
273+
Banned::load_from_state(state)
274+
}
275+
246276
pub fn add_intermediate_rewards(state: &mut TopLevelState, address: Address, reward: u64) -> StateResult<()> {
247277
let mut rewards = IntermediateRewards::load_from_state(state)?;
248278
rewards.add_quantity(address, reward);
@@ -284,7 +314,7 @@ fn change_params(
284314
// Update state first because the signature validation is more expensive.
285315
state.update_params(metadata_seq, params)?;
286316

287-
let action = Action::ChangeParams {
317+
let action = Action::<Message>::ChangeParams {
288318
metadata_seq,
289319
params: params.into(),
290320
signatures: vec![],
@@ -381,16 +411,24 @@ pub fn jail(state: &mut TopLevelState, address: &Address, custody_until: u64, ki
381411
Ok(())
382412
}
383413

384-
#[allow(dead_code)]
385-
pub fn ban(state: &mut TopLevelState, criminal: Address) -> StateResult<()> {
414+
pub fn ban(state: &mut TopLevelState, informant: &Public, criminal: Address) -> StateResult<()> {
386415
// TODO: remove pending rewards.
387-
// TODO: give criminal's deposits to the informant
388416
// TODO: give criminal's rewards to diligent validators
389417
let mut candidates = Candidates::load_from_state(state)?;
390418
let mut banned = Banned::load_from_state(state)?;
391419
let mut jailed = Jail::load_from_state(state)?;
392420
let mut validators = Validators::load_from_state(state)?;
393421

422+
// confiscate criminal's deposit and give the same deposit amount to the informant.
423+
let criminal_info = candidates.get_candidate(&criminal).expect("criminal is always a validator");
424+
let informant_info =
425+
candidates.get_candidate(&public_to_address(informant)).expect("informant is always a validator");
426+
candidates.add_deposit(
427+
informant,
428+
criminal_info.deposit,
429+
informant_info.nomination_ends_at,
430+
informant_info.metadata,
431+
);
394432
candidates.remove(&criminal);
395433
jailed.remove(&criminal);
396434
banned.add(criminal);

0 commit comments

Comments
 (0)