Skip to content

Commit abf31cf

Browse files
committed
Implement report_double_vote custom action
1 parent 4b6bc12 commit abf31cf

File tree

14 files changed

+231
-32
lines changed

14 files changed

+231
-32
lines changed

core/src/consensus/mod.rs

Lines changed: 6 additions & 0 deletions
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};
@@ -273,6 +274,10 @@ pub trait ConsensusEngine: Sync + Send {
273274
self.action_handlers().iter().find(|handler| handler.handler_id() == id).map(AsRef::as_ref)
274275
}
275276

277+
fn get_validator_set(&self) -> Option<Arc<ValidatorSet>> {
278+
None
279+
}
280+
276281
fn possible_authors(&self, block_number: Option<u64>) -> Result<Option<Vec<Address>>, EngineError>;
277282
}
278283

@@ -353,6 +358,7 @@ pub trait CodeChainEngine: ConsensusEngine {
353358
&self,
354359
tx: &UnverifiedTransaction,
355360
common_params: &CommonParams,
361+
parent: &H256,
356362
) -> Result<(), Error> {
357363
if let Action::Custom {
358364
handler_id,

core/src/consensus/solo/mod.rs

Lines changed: 48 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};
2222
use cstate::{ActionHandler, HitHandler};
2323
use ctypes::{CommonParams, Header};
24+
use primitives::{Bytes, H256};
25+
use rlp::{Decodable, DecoderError, Encodable, RlpStream, UntrustedRlp};
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,57 @@ 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 {
61+
SchnorrSignature::random()
62+
}
63+
64+
fn signer_index(&self) -> usize {
65+
Default::default()
66+
}
67+
68+
fn block_hash(&self) -> Option<H256> {
69+
None
70+
}
71+
72+
fn round(&self) -> &bool {
73+
&false
74+
}
75+
76+
fn is_broadcastable(&self) -> bool {
77+
false
78+
}
79+
80+
fn message_for_signature(&self) -> Bytes {
81+
Default::default()
82+
}
83+
}
84+
4085
impl Solo {
4186
/// Returns new instance of Solo over the given state machine.
4287
pub fn new(params: SoloParams, machine: CodeChainMachine) -> Self {
4388
let mut action_handlers: Vec<Arc<ActionHandler>> = Vec::new();
4489
if params.enable_hit_handler {
4590
action_handlers.push(Arc::new(HitHandler::new()));
4691
}
47-
action_handlers.push(Arc::new(stake::Stake::new(params.genesis_stakes.clone())));
92+
action_handlers.push(Arc::new(stake::Stake::<SoloMessage>::new(params.genesis_stakes.clone())));
4893

4994
Solo {
5095
params,

core/src/consensus/stake/actions.rs

Lines changed: 93 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,28 @@
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 std::sync::{Arc, Weak};
18+
19+
use ccrypto::{blake256, Blake};
20+
use ckey::{recover, verify_schnorr, Address, Public, Signature};
21+
use client::ConsensusClient;
22+
use consensus::vote_collector::Message;
1923
use ctypes::errors::SyntaxError;
2024
use ctypes::CommonParams;
2125
use primitives::{Bytes, H256};
2226
use rlp::{Decodable, DecoderError, Encodable, RlpStream, UntrustedRlp};
2327

28+
use consensus::stake::get_validators;
29+
2430
const ACTION_TAG_TRANSFER_CCS: u8 = 1;
2531
const ACTION_TAG_DELEGATE_CCS: u8 = 2;
2632
const ACTION_TAG_REVOKE: u8 = 3;
2733
const ACTION_TAG_SELF_NOMINATE: u8 = 4;
34+
const ACTION_TAG_REPORT_DOUBLE_VOTE: u8 = 5;
2835
const ACTION_TAG_CHANGE_PARAMS: u8 = 0xFF;
2936

3037
#[derive(Debug, PartialEq)]
31-
pub enum Action {
38+
pub enum Action<M: Message> {
3239
TransferCCS {
3340
address: Address,
3441
quantity: u64,
@@ -50,10 +57,18 @@ pub enum Action {
5057
params: Box<CommonParams>,
5158
signatures: Vec<Signature>,
5259
},
60+
ReportDoubleVote {
61+
message1: M,
62+
message2: M,
63+
},
5364
}
5465

55-
impl Action {
56-
pub fn verify(&self, current_params: &CommonParams) -> Result<(), SyntaxError> {
66+
impl<M: Message> Action<M> {
67+
pub fn verify(
68+
&self,
69+
current_params: &CommonParams,
70+
client: Option<Weak<ConsensusClient>>,
71+
) -> Result<(), SyntaxError> {
5772
match self {
5873
Action::TransferCCS {
5974
..
@@ -89,7 +104,7 @@ impl Action {
89104
)))
90105
}
91106
params.verify().map_err(SyntaxError::InvalidCustomAction)?;
92-
let action = Action::ChangeParams {
107+
let action = Action::<M>::ChangeParams {
93108
metadata_seq: *metadata_seq,
94109
params: params.clone(),
95110
signatures: vec![],
@@ -102,12 +117,60 @@ impl Action {
102117
})?;
103118
}
104119
}
120+
Action::ReportDoubleVote {
121+
message1,
122+
message2,
123+
} => {
124+
// what is the general verifying for general message?
125+
let message_for_signature = message1.message_for_signature();
126+
let message_hash = blake256(&message_for_signature);
127+
128+
let signature1 = message1.signature();
129+
let signature2 = message2.signature();
130+
131+
let signer_idx1 = message1.signer_index();
132+
let signer_idx2 = message2.signer_index();
133+
134+
let signed_block_hash = message1.block_hash();
135+
let client: Arc<ConsensusClient> =
136+
client.as_ref().and_then(Weak::upgrade).expect("Client must be initialized");
137+
let parent_block_hash = signed_block_hash
138+
.and_then(|hash| client.block_header(&hash.into()))
139+
.ok_or_else(|| {
140+
SyntaxError::InvalidCustomAction(String::from(
141+
"Cannot get parent header from message's block_hash",
142+
))
143+
})?
144+
.parent_hash();
145+
146+
let parent_state = client.state_at(parent_block_hash.into()).ok_or_else(|| {
147+
SyntaxError::InvalidCustomAction(String::from(
148+
"Cannot read state from the given message's parent hash",
149+
))
150+
})?;
151+
let signers_vec: Vec<Public> = get_validators(&parent_state)
152+
.map(|validators| validators.into_iter().map(|val| *val.pubkey()).collect())
153+
.map_err(|_| {
154+
SyntaxError::InvalidCustomAction(String::from("Cannot get validators from parent_state"))
155+
})?;
156+
157+
let signer1 = signers_vec.get(signer_idx1).ok_or_else(|| {
158+
SyntaxError::InvalidCustomAction(String::from("Invalid signer index in message1"))
159+
})?;
160+
let signer2 = signers_vec.get(signer_idx2).ok_or_else(|| {
161+
SyntaxError::InvalidCustomAction(String::from("Invalid signer index in message2"))
162+
})?;
163+
164+
verify_schnorr(signer1, &signature1, &message_hash)
165+
.and(verify_schnorr(signer2, &signature2, &message_hash))
166+
.map_err(|err| SyntaxError::InvalidCustomAction(format!("{}", err)))?;
167+
}
105168
}
106169
Ok(())
107170
}
108171
}
109172

110-
impl Encodable for Action {
173+
impl<M: Message> Encodable for Action<M> {
111174
fn rlp_append(&self, s: &mut RlpStream) {
112175
match self {
113176
Action::TransferCCS {
@@ -147,11 +210,17 @@ impl Encodable for Action {
147210
s.append(signature);
148211
}
149212
}
213+
Action::ReportDoubleVote {
214+
message1,
215+
message2,
216+
} => {
217+
s.begin_list(3).append(&ACTION_TAG_REPORT_DOUBLE_VOTE).append(message1).append(message2);
218+
}
150219
};
151220
}
152221
}
153222

154-
impl Decodable for Action {
223+
impl<M: Message> Decodable for Action<M> {
155224
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
156225
let tag = rlp.val_at(0)?;
157226
match tag {
@@ -224,6 +293,21 @@ impl Decodable for Action {
224293
signatures,
225294
})
226295
}
296+
ACTION_TAG_REPORT_DOUBLE_VOTE => {
297+
let item_count = rlp.item_count()?;
298+
if item_count != 3 {
299+
return Err(DecoderError::RlpIncorrectListLen {
300+
expected: 3,
301+
got: item_count,
302+
})
303+
}
304+
let message1 = rlp.val_at(1)?;
305+
let message2 = rlp.val_at(2)?;
306+
Ok(Action::ReportDoubleVote {
307+
message1,
308+
message2,
309+
})
310+
}
227311
_ => Err(DecoderError::Custom("Unexpected Tendermint Stake Action Type")),
228312
}
229313
}
@@ -247,7 +331,7 @@ mod tests {
247331
expected: 4,
248332
got: 3,
249333
}),
250-
UntrustedRlp::new(&rlp::encode(&action)).as_val::<Action>()
334+
UntrustedRlp::new(&rlp::encode(&action)).as_val::<Action>::<_>()
251335
);
252336
}
253337

0 commit comments

Comments
 (0)