Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
polkadot-sdk
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue 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
Mirrored projects
polkadot-sdk
Commits
9e4bca68
Commit
9e4bca68
authored
1 year ago
by
Tsvetomir Dimitrov
Committed by
GitHub
1 year ago
Browse files
Options
Downloads
Patches
Plain Diff
Freeze chain if there are byzantine threshold + 1 invalid votes against a local candidate (#7225)
parent
0759495c
Branches
Branches containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
polkadot/runtime/parachains/src/disputes.rs
+8
-2
8 additions, 2 deletions
polkadot/runtime/parachains/src/disputes.rs
polkadot/runtime/parachains/src/disputes/tests.rs
+168
-2
168 additions, 2 deletions
polkadot/runtime/parachains/src/disputes/tests.rs
with
176 additions
and
4 deletions
polkadot/runtime/parachains/src/disputes.rs
+
8
−
2
View file @
9e4bca68
...
...
@@ -560,6 +560,8 @@ bitflags::bitflags! {
const
FOR_SUPERMAJORITY
=
0b0010
;
/// Is the supermajority against the validity of the block reached.
const
AGAINST_SUPERMAJORITY
=
0b0100
;
/// Is there f+1 against the validity of the block reached
const
AGAINST_BYZANTINE
=
0b1000
;
}
}
...
...
@@ -582,6 +584,10 @@ impl DisputeStateFlags {
flags
|
=
DisputeStateFlags
::
FOR_SUPERMAJORITY
;
}
if
state
.validators_against
.count_ones
()
>
byzantine_threshold
{
flags
|
=
DisputeStateFlags
::
AGAINST_BYZANTINE
;
}
if
state
.validators_against
.count_ones
()
>=
supermajority_threshold
{
flags
|
=
DisputeStateFlags
::
AGAINST_SUPERMAJORITY
;
}
...
...
@@ -1243,8 +1249,8 @@ impl<T: Config> Pallet<T> {
<
Disputes
<
T
>>
::
insert
(
&
session
,
&
candidate_hash
,
&
summary
.state
);
// Freeze if
just concluded
against some local candidate
if
summary
.new_flags
.contains
(
DisputeStateFlags
::
AGAINST_
SUPERMAJORITY
)
{
// Freeze if
the INVALID votes
against some local candidate
are above the byzantine threshold
if
summary
.new_flags
.contains
(
DisputeStateFlags
::
AGAINST_
BYZANTINE
)
{
if
let
Some
(
revert_to
)
=
<
Included
<
T
>>
::
get
(
&
session
,
&
candidate_hash
)
{
Self
::
revert_and_freeze
(
revert_to
);
}
...
...
This diff is collapsed.
Click to expand it.
polkadot/runtime/parachains/src/disputes/tests.rs
+
168
−
2
View file @
9e4bca68
...
...
@@ -123,6 +123,16 @@ fn test_dispute_state_flag_from_state() {
DisputeStateFlags
::
FOR_SUPERMAJORITY
|
DisputeStateFlags
::
CONFIRMED
,
);
assert_eq!
(
DisputeStateFlags
::
from_state
(
&
DisputeState
{
validators_for
:
bitvec!
[
u8
,
BitOrderLsb0
;
0
,
0
,
0
,
0
,
0
,
0
,
0
],
validators_against
:
bitvec!
[
u8
,
BitOrderLsb0
;
1
,
1
,
1
,
0
,
0
,
0
,
0
],
start
:
0
,
concluded_at
:
None
,
}),
DisputeStateFlags
::
CONFIRMED
|
DisputeStateFlags
::
AGAINST_BYZANTINE
,
);
assert_eq!
(
DisputeStateFlags
::
from_state
(
&
DisputeState
{
validators_for
:
bitvec!
[
u8
,
BitOrderLsb0
;
0
,
0
,
0
,
0
,
0
,
0
,
0
],
...
...
@@ -130,7 +140,9 @@ fn test_dispute_state_flag_from_state() {
start
:
0
,
concluded_at
:
None
,
}),
DisputeStateFlags
::
AGAINST_SUPERMAJORITY
|
DisputeStateFlags
::
CONFIRMED
,
DisputeStateFlags
::
AGAINST_SUPERMAJORITY
|
DisputeStateFlags
::
CONFIRMED
|
DisputeStateFlags
::
AGAINST_BYZANTINE
,
);
}
...
...
@@ -248,7 +260,9 @@ fn test_import_prev_participant_confirmed_slash_for() {
assert_eq!
(
summary
.new_participants
,
bitvec!
[
u8
,
BitOrderLsb0
;
0
,
0
,
1
,
1
,
1
,
1
,
1
,
0
]);
assert_eq!
(
summary
.new_flags
,
DisputeStateFlags
::
CONFIRMED
|
DisputeStateFlags
::
AGAINST_SUPERMAJORITY
,
DisputeStateFlags
::
CONFIRMED
|
DisputeStateFlags
::
AGAINST_SUPERMAJORITY
|
DisputeStateFlags
::
AGAINST_BYZANTINE
,
);
}
...
...
@@ -674,6 +688,158 @@ fn test_freeze_provided_against_supermajority_for_included() {
});
}
#[test]
fn
test_freeze_provided_against_byzantine_threshold_for_included
()
{
new_test_ext
(
Default
::
default
())
.execute_with
(||
{
let
v0
=
<
ValidatorId
as
CryptoType
>
::
Pair
::
generate
()
.0
;
let
v1
=
<
ValidatorId
as
CryptoType
>
::
Pair
::
generate
()
.0
;
let
v2
=
<
ValidatorId
as
CryptoType
>
::
Pair
::
generate
()
.0
;
let
v3
=
<
ValidatorId
as
CryptoType
>
::
Pair
::
generate
()
.0
;
let
v4
=
<
ValidatorId
as
CryptoType
>
::
Pair
::
generate
()
.0
;
let
v5
=
<
ValidatorId
as
CryptoType
>
::
Pair
::
generate
()
.0
;
let
v6
=
<
ValidatorId
as
CryptoType
>
::
Pair
::
generate
()
.0
;
let
active_set
=
vec!
[
(
&
0
,
v0
.public
()),
(
&
1
,
v1
.public
()),
(
&
2
,
v2
.public
()),
(
&
3
,
v3
.public
()),
(
&
4
,
v4
.public
()),
(
&
5
,
v5
.public
()),
(
&
6
,
v6
.public
()),
];
run_to_block
(
6
,
|
b
|
Some
((
true
,
b
,
active_set
.clone
(),
Some
(
active_set
.clone
()))));
// A candidate which will be disputed
let
candidate_hash
=
CandidateHash
(
sp_core
::
H256
::
repeat_byte
(
1
));
let
inclusion_parent
=
sp_core
::
H256
::
repeat_byte
(
0xff
);
let
session
=
3
;
// A byzantine threshold of INVALID
let
stmts
=
vec!
[
DisputeStatementSet
{
candidate_hash
:
candidate_hash
.clone
(),
session
,
statements
:
vec!
[
(
DisputeStatement
::
Invalid
(
InvalidDisputeStatementKind
::
Explicit
),
ValidatorIndex
(
0
),
v0
.sign
(
&
ExplicitDisputeStatement
{
valid
:
false
,
candidate_hash
:
candidate_hash
.clone
(),
session
,
}
.signing_payload
(),
),
),
(
DisputeStatement
::
Invalid
(
InvalidDisputeStatementKind
::
Explicit
),
ValidatorIndex
(
1
),
v1
.sign
(
&
ExplicitDisputeStatement
{
valid
:
false
,
candidate_hash
:
candidate_hash
.clone
(),
session
,
}
.signing_payload
(),
),
),
(
DisputeStatement
::
Invalid
(
InvalidDisputeStatementKind
::
Explicit
),
ValidatorIndex
(
2
),
v2
.sign
(
&
ExplicitDisputeStatement
{
valid
:
false
,
candidate_hash
:
candidate_hash
.clone
(),
session
,
}
.signing_payload
(),
),
),
(
DisputeStatement
::
Valid
(
ValidDisputeStatementKind
::
BackingValid
(
inclusion_parent
,
)),
ValidatorIndex
(
1
),
v0
.sign
(
&
CompactStatement
::
Valid
(
candidate_hash
)
.signing_payload
(
&
SigningContext
{
session_index
:
session
,
parent_hash
:
inclusion_parent
},
)),
),
],
}];
// Include the candidate and import the votes
Pallet
::
<
Test
>
::
note_included
(
3
,
candidate_hash
.clone
(),
3
);
assert!
(
Pallet
::
<
Test
>
::
process_checked_multi_dispute_data
(
&
stmts
.into_iter
()
.map
(
CheckedDisputeStatementSet
::
unchecked_from_unchecked
)
.collect
()
)
.is_ok
());
// Successful import should freeze the chain
assert_eq!
(
Frozen
::
<
Test
>
::
get
(),
Some
(
2
));
// Now include one more block
run_to_block
(
7
,
|
b
|
Some
((
true
,
b
,
active_set
.clone
(),
Some
(
active_set
.clone
()))));
Pallet
::
<
Test
>
::
note_included
(
3
,
CandidateHash
(
sp_core
::
H256
::
repeat_byte
(
2
)),
3
);
// And generate enough votes to reach supermajority of invalid votes
let
stmts
=
vec!
[
DisputeStatementSet
{
candidate_hash
:
candidate_hash
.clone
(),
session
,
statements
:
vec!
[
(
DisputeStatement
::
Invalid
(
InvalidDisputeStatementKind
::
Explicit
),
ValidatorIndex
(
3
),
v3
.sign
(
&
ExplicitDisputeStatement
{
valid
:
false
,
candidate_hash
:
candidate_hash
.clone
(),
session
,
}
.signing_payload
(),
),
),
(
DisputeStatement
::
Invalid
(
InvalidDisputeStatementKind
::
Explicit
),
ValidatorIndex
(
4
),
v4
.sign
(
&
ExplicitDisputeStatement
{
valid
:
false
,
candidate_hash
:
candidate_hash
.clone
(),
session
,
}
.signing_payload
(),
),
),
(
DisputeStatement
::
Invalid
(
InvalidDisputeStatementKind
::
Explicit
),
ValidatorIndex
(
5
),
v5
.sign
(
&
ExplicitDisputeStatement
{
valid
:
false
,
candidate_hash
:
candidate_hash
.clone
(),
session
,
}
.signing_payload
(),
),
),
],
}];
assert!
(
Pallet
::
<
Test
>
::
process_checked_multi_dispute_data
(
&
stmts
.into_iter
()
.map
(
CheckedDisputeStatementSet
::
unchecked_from_unchecked
)
.collect
()
)
.is_ok
());
// Chain should still be frozen
assert_eq!
(
Frozen
::
<
Test
>
::
get
(),
Some
(
2
));
});
}
mod
unconfirmed_disputes
{
use
super
::
*
;
use
assert_matches
::
assert_matches
;
...
...
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