Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
S
shasper
Manage
Activity
Members
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Environments
Terraform modules
Analyze
Contributor analytics
CI/CD analytics
Repository analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
parity
shasper
Commits
870f1307
Commit
870f1307
authored
5 years ago
by
Wei Tang
Browse files
Options
Downloads
Patches
Plain Diff
srml-casper: implement slashing conditions
parent
fcb48f3f
Branches
172
sp-slashing
Branches containing commit
No related merge requests found
Pipeline
#48806
passed with stage
Stage:
in 7 minutes and 36 seconds
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
substrate/casper/srml/src/lib.rs
+78
-7
78 additions, 7 deletions
substrate/casper/srml/src/lib.rs
substrate/casper/template/runtime/src/lib.rs
+1
-0
1 addition, 0 deletions
substrate/casper/template/runtime/src/lib.rs
with
79 additions
and
7 deletions
substrate/casper/srml/src/lib.rs
+
78
−
7
View file @
870f1307
...
...
@@ -22,11 +22,19 @@ use srml_support::{StorageValue, dispatch::Result, decl_module, decl_storage, de
use
system
::
ensure_none
;
use
sr_primitives
::{
traits
::{
One
,
MaybeDebug
,
Extrinsic
as
ExtrinsicT
,
ValidateUnsigned
},
weights
::
SimpleDispatchInfo
};
use
sr_primitives
::
transaction_validity
::{
TransactionValidity
,
TransactionLongevity
,
ValidTransaction
};
use
casper_primitives
::{
ValidatorId
,
ValidatorSignature
,
ValidatorWeight
,
ValidatorIndex
};
use
casper_primitives
::{
ValidatorId
,
ValidatorSignature
,
ValidatorWeight
};
use
codec
::{
Encode
,
Decode
};
use
app_crypto
::
RuntimeAppPublic
;
use
rstd
::
prelude
::
*
;
pub
trait
OnSlashing
{
fn
on_slashing
(
validator_id
:
&
ValidatorId
);
}
impl
OnSlashing
for
()
{
fn
on_slashing
(
_validator_id
:
&
ValidatorId
)
{
}
}
#[derive(Encode,
Decode,
Clone,
PartialEq,
Eq)]
#[cfg_attr(feature
=
"std"
,
derive(Debug))]
pub
struct
Checkpoint
<
T
:
Trait
>
{
...
...
@@ -37,7 +45,7 @@ pub struct Checkpoint<T: Trait> {
#[derive(Encode,
Decode,
Clone,
PartialEq,
Eq)]
#[cfg_attr(feature
=
"std"
,
derive(Debug))]
pub
struct
Attestation
<
T
:
Trait
>
{
pub
validator_i
ndex
:
ValidatorI
ndex
,
pub
validator_i
d
:
ValidatorI
d
,
pub
source
:
Checkpoint
<
T
>
,
pub
target
:
Checkpoint
<
T
>
,
}
...
...
@@ -51,6 +59,8 @@ pub trait Trait: session::Trait + MaybeDebug {
/// A extrinsic right from the external world. This is unchecked and so
/// can contain a signature.
type
UncheckedExtrinsic
:
ExtrinsicT
<
Call
=<
Self
as
Trait
>
::
Call
>
+
Encode
+
Decode
+
MaybeDebug
;
/// Triggers when slashing happens.
type
OnSlashing
:
OnSlashing
;
}
decl_storage!
{
...
...
@@ -100,12 +110,52 @@ decl_module! {
pub
struct
Module
<
T
:
Trait
>
for
enum
Call
where
origin
:
T
::
Origin
{
fn
deposit_event
<
T
>
()
=
default
;
#[weight
=
SimpleDispatchInfo::FixedNormal(
1_000_000
)]
fn
slash
(
origin
,
attestation_1
:
Attestation
<
T
>
,
signature_1
:
ValidatorSignature
,
attestation_2
:
Attestation
<
T
>
,
signature_2
:
ValidatorSignature
)
->
Result
{
ensure_none
(
origin
)
?
;
if
attestation_1
==
attestation_2
{
return
Err
(
"not slashable because it's the same attestation"
)
}
if
!
attestation_1
.validator_id
.verify
(
&
attestation_1
.encode
(),
&
signature_1
)
{
return
Err
(
"not slashable because attestation 1's signature is invalid"
)
}
if
!
attestation_2
.validator_id
.verify
(
&
attestation_2
.encode
(),
&
signature_2
)
{
return
Err
(
"not slashable because attestation 2's signature is invalid"
)
}
if
attestation_1
.validator_id
!=
attestation_2
.validator_id
{
return
Err
(
"not slashable because attestation not signed by the same validator"
)
}
let
slashable_cond
=
attestation_1
.target.number
==
attestation_2
.target.number
||
(
attestation_1
.source.number
<
attestation_2
.source.number
&&
attestation_2
.target.number
<
attestation_1
.target.number
);
if
!
slashable_cond
{
return
Err
(
"not slashable because it does not satisfy FFG's slashing conditions"
)
}
<
T
::
OnSlashing
>
::
on_slashing
(
&
attestation_1
.validator_id
);
Ok
(())
}
#[weight
=
SimpleDispatchInfo::FixedNormal(
5_000_000
)]
fn
attest
(
origin
,
attestation
:
Attestation
<
T
>
,
signature
:
ValidatorSignature
)
->
Result
{
ensure_none
(
origin
)
?
;
let
validators
=
Validators
::
get
();
let
validator_id
=
validators
[
attestation
.validator_index
as
usize
]
.0
.clone
();
let
validator_id
=
attestation
.validator_id
.clone
();
if
!
validators
.iter
()
.any
(|
v
|
v
.0
==
validator_id
)
{
return
Err
(
"validator not in session"
)
}
if
!
validator_id
.verify
(
&
attestation
.encode
(),
&
signature
)
{
return
Err
(
"invalid attestation signature"
)
}
...
...
@@ -170,7 +220,7 @@ impl<T: Trait> Module<T> {
let
mut
local_keys
=
ValidatorId
::
all
();
local_keys
.sort
();
for
(
validator_index
,
key
)
in
validators
.into_iter
()
for
(
_
validator_index
,
key
)
in
validators
.into_iter
()
.enumerate
()
.filter_map
(|(
index
,
validator
)|
{
local_keys
.binary_search
(
&
validator
.0
)
...
...
@@ -190,7 +240,7 @@ impl<T: Trait> Module<T> {
hash
:
<
system
::
Module
<
T
>>
::
block_hash
(
target_number
),
};
let
attestation
=
Attestation
::
<
T
>
{
validator_i
ndex
:
validator_index
as
u64
,
validator_i
d
:
key
.clone
()
,
source
,
target
};
let
signature
=
key
.sign
(
&
attestation
.encode
())
...
...
@@ -229,9 +279,23 @@ impl<T: Trait> session::OneSessionHandler<T::AccountId> for Module<T> {
let
validators
=
<
Validators
>
::
get
();
let
total_balance
=
validators
.iter
()
.fold
(
0
,
|
acc
,
v
|
acc
+
v
.1
);
let
previous_matching_target_balance
=
<
PreviousEpochAttestations
<
T
>>
::
get
()
.iter
()
.fold
(
0
,
|
acc
,
attestation
|
acc
+
validators
[
attestation
.validator_index
as
usize
]
.1
);
.fold
(
0
,
|
acc
,
attestation
|
{
let
validator_weight
=
validators
.iter
()
.find
(|
v
|
v
.0
==
attestation
.validator_id
)
.map
(|
v
|
v
.1
)
.unwrap_or
(
0
);
acc
+
validator_weight
});
let
current_matching_target_balance
=
<
CurrentEpochAttestations
<
T
>>
::
get
()
.iter
()
.fold
(
0
,
|
acc
,
attestation
|
acc
+
validators
[
attestation
.validator_index
as
usize
]
.1
);
.fold
(
0
,
|
acc
,
attestation
|
{
let
validator_weight
=
validators
.iter
()
.find
(|
v
|
v
.0
==
attestation
.validator_id
)
.map
(|
v
|
v
.1
)
.unwrap_or
(
0
);
acc
+
validator_weight
});
let
mut
justification_bits
=
<
JustificationBits
>
::
get
();
let
old_justification_bits
=
justification_bits
.clone
();
...
...
@@ -289,6 +353,13 @@ impl<T: Trait> ValidateUnsigned for Module<T> {
longevity
:
TransactionLongevity
::
max_value
(),
propagate
:
true
,
}),
Call
::
slash
(
a1
,
_
,
a2
,
_
)
=>
TransactionValidity
::
Valid
(
ValidTransaction
{
priority
:
0
,
requires
:
vec!
[],
provides
:
vec!
[(
a1
,
a2
)
.encode
()],
longevity
:
TransactionLongevity
::
max_value
(),
propagate
:
true
,
}),
_
=>
TransactionValidity
::
Invalid
(
0
),
}
}
...
...
This diff is collapsed.
Click to expand it.
substrate/casper/template/runtime/src/lib.rs
+
1
−
0
View file @
870f1307
...
...
@@ -181,6 +181,7 @@ impl casper::Trait for Runtime {
type
Event
=
Event
;
type
Call
=
Call
;
type
UncheckedExtrinsic
=
UncheckedExtrinsic
;
type
OnSlashing
=
();
}
parameter_types!
{
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment