Skip to content
GitLab
Explore
Sign in
parity
Mirrored projects
polkadot-sdk
Compare revisions
be1d7d05e5f32b1bfa67aec2f6344d2c6ff60f50 to aceda4659509d426d364188fa72555de58b887ba
Show whitespace changes
Inline
Side-by-side
substrate/frame/grandpa/src/mock.rs
View file @
aceda465
...
...
@@ -146,7 +146,6 @@ parameter_types! {
pub
const
SessionsPerEra
:
SessionIndex
=
3
;
pub
const
BondingDuration
:
EraIndex
=
3
;
pub
const
RewardCurve
:
&
'static
PiecewiseLinear
<
'static
>
=
&
REWARD_CURVE
;
pub
const
OffendingValidatorsThreshold
:
Perbill
=
Perbill
::
from_percent
(
17
);
pub
static
ElectionsBoundsOnChain
:
ElectionBounds
=
ElectionBoundsBuilder
::
default
()
.build
();
}
...
...
@@ -176,7 +175,6 @@ impl pallet_staking::Config for Test {
type
UnixTime
=
pallet_timestamp
::
Pallet
<
Test
>
;
type
EraPayout
=
pallet_staking
::
ConvertCurve
<
RewardCurve
>
;
type
MaxExposurePageSize
=
ConstU32
<
64
>
;
type
OffendingValidatorsThreshold
=
OffendingValidatorsThreshold
;
type
NextNewSession
=
Session
;
type
ElectionProvider
=
onchain
::
OnChainExecution
<
OnChainSeqPhragmen
>
;
type
GenesisElectionProvider
=
Self
::
ElectionProvider
;
...
...
@@ -189,6 +187,7 @@ impl pallet_staking::Config for Test {
type
EventListeners
=
();
type
BenchmarkingConfig
=
pallet_staking
::
TestBenchmarkingConfig
;
type
WeightInfo
=
();
type
DisablingStrategy
=
pallet_staking
::
UpToLimitDisablingStrategy
;
}
impl
pallet_offences
::
Config
for
Test
{
...
...
substrate/frame/im-online/src/lib.rs
View file @
aceda465
...
...
@@ -104,7 +104,7 @@ use sp_runtime::{
PerThing
,
Perbill
,
Permill
,
RuntimeDebug
,
SaturatedConversion
,
};
use
sp_staking
::{
offence
::{
DisableStrategy
,
Kind
,
Offence
,
ReportOffence
},
offence
::{
Kind
,
Offence
,
ReportOffence
},
SessionIndex
,
};
use
sp_std
::
prelude
::
*
;
...
...
@@ -847,10 +847,6 @@ impl<Offender: Clone> Offence<Offender> for UnresponsivenessOffence<Offender> {
self
.session_index
}
fn
disable_strategy
(
&
self
)
->
DisableStrategy
{
DisableStrategy
::
Never
}
fn
slash_fraction
(
&
self
,
offenders
:
u32
)
->
Perbill
{
// the formula is min((3 * (k - (n / 10 + 1))) / n, 1) * 0.07
// basically, 10% can be offline with no slash, but after that, it linearly climbs up to 7%
...
...
substrate/frame/im-online/src/tests.rs
View file @
aceda465
...
...
@@ -50,9 +50,6 @@ fn test_unresponsiveness_slash_fraction() {
dummy_offence
.slash_fraction
(
17
),
Perbill
::
from_parts
(
46200000
),
// 4.62%
);
// Offline offences should never lead to being disabled.
assert_eq!
(
dummy_offence
.disable_strategy
(),
DisableStrategy
::
Never
);
}
#[test]
...
...
substrate/frame/message-queue/src/lib.rs
View file @
aceda465
...
...
@@ -765,6 +765,13 @@ enum MessageExecutionStatus {
Processed
,
/// The message was processed and resulted in a, possibly permanent, error.
Unprocessable
{
permanent
:
bool
},
/// The stack depth limit was reached.
///
/// We cannot just return `Unprocessable` in this case, because the processability of the
/// message depends on how the function was called. This may be a permanent error if it was
/// called by a top-level function, or a transient error if it was already called in a nested
/// function.
StackLimitReached
,
}
impl
<
T
:
Config
>
Pallet
<
T
>
{
...
...
@@ -984,7 +991,8 @@ impl<T: Config> Pallet<T> {
// additional overweight event being deposited.
)
{
Overweight
|
InsufficientWeight
=>
Err
(
Error
::
<
T
>
::
InsufficientWeight
),
Unprocessable
{
permanent
:
false
}
=>
Err
(
Error
::
<
T
>
::
TemporarilyUnprocessable
),
StackLimitReached
|
Unprocessable
{
permanent
:
false
}
=>
Err
(
Error
::
<
T
>
::
TemporarilyUnprocessable
),
Unprocessable
{
permanent
:
true
}
|
Processed
=>
{
page
.note_processed_at_pos
(
pos
);
book_state
.message_count
.saturating_dec
();
...
...
@@ -1250,7 +1258,7 @@ impl<T: Config> Pallet<T> {
let
is_processed
=
match
res
{
InsufficientWeight
=>
return
ItemExecutionStatus
::
Bailed
,
Unprocessable
{
permanent
:
false
}
=>
return
ItemExecutionStatus
::
NoProgress
,
Processed
|
Unprocessable
{
permanent
:
true
}
=>
true
,
Processed
|
Unprocessable
{
permanent
:
true
}
|
StackLimitReached
=>
true
,
Overweight
=>
false
,
};
...
...
@@ -1461,6 +1469,10 @@ impl<T: Config> Pallet<T> {
Self
::
deposit_event
(
Event
::
<
T
>
::
ProcessingFailed
{
id
:
id
.into
(),
origin
,
error
});
MessageExecutionStatus
::
Unprocessable
{
permanent
:
true
}
},
Err
(
error
@
StackLimitReached
)
=>
{
Self
::
deposit_event
(
Event
::
<
T
>
::
ProcessingFailed
{
id
:
id
.into
(),
origin
,
error
});
MessageExecutionStatus
::
StackLimitReached
},
Ok
(
success
)
=>
{
// Success
let
weight_used
=
meter
.consumed
()
.saturating_sub
(
prev_consumed
);
...
...
substrate/frame/message-queue/src/mock.rs
View file @
aceda465
...
...
@@ -198,6 +198,7 @@ impl ProcessMessage for RecordingMessageProcessor {
parameter_types!
{
pub
static
Callback
:
Box
<
fn
(
&
MessageOrigin
,
u32
)
>
=
Box
::
new
(|
_
,
_
|
{});
pub
static
IgnoreStackOvError
:
bool
=
false
;
}
/// Processed a mocked message. Messages that end with `badformat`, `corrupt`, `unsupported` or
...
...
@@ -216,6 +217,8 @@ fn processing_message(msg: &[u8], origin: &MessageOrigin) -> Result<(), ProcessM
Err
(
ProcessMessageError
::
Unsupported
)
}
else
if
msg
.ends_with
(
"yield"
)
{
Err
(
ProcessMessageError
::
Yield
)
}
else
if
msg
.ends_with
(
"stacklimitreached"
)
&&
!
IgnoreStackOvError
::
get
()
{
Err
(
ProcessMessageError
::
StackLimitReached
)
}
else
{
Ok
(())
}
...
...
substrate/frame/message-queue/src/tests.rs
View file @
aceda465
...
...
@@ -174,9 +174,10 @@ fn service_queues_failing_messages_works() {
MessageQueue
::
enqueue_message
(
msg
(
"badformat"
),
Here
);
MessageQueue
::
enqueue_message
(
msg
(
"corrupt"
),
Here
);
MessageQueue
::
enqueue_message
(
msg
(
"unsupported"
),
Here
);
MessageQueue
::
enqueue_message
(
msg
(
"stacklimitreached"
),
Here
);
MessageQueue
::
enqueue_message
(
msg
(
"yield"
),
Here
);
// Starts with four pages.
assert_pages
(
&
[
0
,
1
,
2
,
3
]);
assert_pages
(
&
[
0
,
1
,
2
,
3
,
4
]);
assert_eq!
(
MessageQueue
::
service_queues
(
1
.into_weight
()),
1
.into_weight
());
assert_last_event
::
<
Test
>
(
...
...
@@ -206,9 +207,9 @@ fn service_queues_failing_messages_works() {
.into
(),
);
assert_eq!
(
MessageQueue
::
service_queues
(
1
.into_weight
()),
1
.into_weight
());
assert_eq!
(
System
::
events
()
.len
(),
3
);
assert_eq!
(
System
::
events
()
.len
(),
4
);
// Last page with the `yield` stays in.
assert_pages
(
&
[
3
]);
assert_pages
(
&
[
4
]);
});
}
...
...
@@ -1880,3 +1881,97 @@ fn process_enqueued_on_idle_requires_enough_weight() {
assert_eq!
(
MessagesProcessed
::
take
(),
vec!
[]);
})
}
/// A message that reports `StackLimitReached` will not be put into the overweight queue when
/// executed from the top level.
#[test]
fn
process_discards_stack_ov_message
()
{
use
MessageOrigin
::
*
;
build_and_execute
::
<
Test
>
(||
{
MessageQueue
::
enqueue_message
(
msg
(
"stacklimitreached"
),
Here
);
MessageQueue
::
service_queues
(
10
.into_weight
());
assert_last_event
::
<
Test
>
(
Event
::
ProcessingFailed
{
id
:
blake2_256
(
b"stacklimitreached"
)
.into
(),
origin
:
MessageOrigin
::
Here
,
error
:
ProcessMessageError
::
StackLimitReached
,
}
.into
(),
);
assert!
(
MessagesProcessed
::
take
()
.is_empty
());
// Message is gone and not overweight:
assert_pages
(
&
[]);
});
}
/// A message that reports `StackLimitReached` will stay in the overweight queue when it is executed
/// by `execute_overweight`.
#[test]
fn
execute_overweight_keeps_stack_ov_message
()
{
use
MessageOrigin
::
*
;
build_and_execute
::
<
Test
>
(||
{
// We need to create a mocked message that first reports insufficient weight, and then
// `StackLimitReached`:
IgnoreStackOvError
::
set
(
true
);
MessageQueue
::
enqueue_message
(
msg
(
"stacklimitreached"
),
Here
);
MessageQueue
::
service_queues
(
0
.into_weight
());
assert_last_event
::
<
Test
>
(
Event
::
OverweightEnqueued
{
id
:
blake2_256
(
b"stacklimitreached"
),
origin
:
MessageOrigin
::
Here
,
message_index
:
0
,
page_index
:
0
,
}
.into
(),
);
// Does not count as 'processed':
assert!
(
MessagesProcessed
::
take
()
.is_empty
());
assert_pages
(
&
[
0
]);
// Now let it return `StackLimitReached`. Note that this case would normally not happen,
// since we assume that the top-level execution is the one with the most remaining stack
// depth.
IgnoreStackOvError
::
set
(
false
);
// Ensure that trying to execute the message does not change any state (besides events).
System
::
reset_events
();
let
storage_noop
=
StorageNoopGuard
::
new
();
assert_eq!
(
<
MessageQueue
as
ServiceQueues
>
::
execute_overweight
(
3
.into_weight
(),
(
Here
,
0
,
0
)),
Err
(
ExecuteOverweightError
::
Other
)
);
assert_last_event
::
<
Test
>
(
Event
::
ProcessingFailed
{
id
:
blake2_256
(
b"stacklimitreached"
)
.into
(),
origin
:
MessageOrigin
::
Here
,
error
:
ProcessMessageError
::
StackLimitReached
,
}
.into
(),
);
System
::
reset_events
();
drop
(
storage_noop
);
// Now let's process it normally:
IgnoreStackOvError
::
set
(
true
);
assert_eq!
(
<
MessageQueue
as
ServiceQueues
>
::
execute_overweight
(
1
.into_weight
(),
(
Here
,
0
,
0
))
.unwrap
(),
1
.into_weight
()
);
assert_last_event
::
<
Test
>
(
Event
::
Processed
{
id
:
blake2_256
(
b"stacklimitreached"
)
.into
(),
origin
:
MessageOrigin
::
Here
,
weight_used
:
1
.into_weight
(),
success
:
true
,
}
.into
(),
);
assert_pages
(
&
[]);
System
::
reset_events
();
});
}
substrate/frame/nomination-pools/benchmarking/src/mock.rs
View file @
aceda465
...
...
@@ -111,7 +111,6 @@ impl pallet_staking::Config for Runtime {
type
EraPayout
=
pallet_staking
::
ConvertCurve
<
RewardCurve
>
;
type
NextNewSession
=
();
type
MaxExposurePageSize
=
ConstU32
<
64
>
;
type
OffendingValidatorsThreshold
=
();
type
ElectionProvider
=
frame_election_provider_support
::
NoElection
<
(
AccountId
,
BlockNumber
,
Staking
,
())
>
;
type
GenesisElectionProvider
=
Self
::
ElectionProvider
;
...
...
@@ -124,6 +123,7 @@ impl pallet_staking::Config for Runtime {
type
EventListeners
=
Pools
;
type
BenchmarkingConfig
=
pallet_staking
::
TestBenchmarkingConfig
;
type
WeightInfo
=
();
type
DisablingStrategy
=
pallet_staking
::
UpToLimitDisablingStrategy
;
}
parameter_types!
{
...
...
substrate/frame/nomination-pools/test-staking/src/mock.rs
View file @
aceda465
...
...
@@ -125,7 +125,6 @@ impl pallet_staking::Config for Runtime {
type
EraPayout
=
pallet_staking
::
ConvertCurve
<
RewardCurve
>
;
type
NextNewSession
=
();
type
MaxExposurePageSize
=
ConstU32
<
64
>
;
type
OffendingValidatorsThreshold
=
();
type
ElectionProvider
=
frame_election_provider_support
::
NoElection
<
(
AccountId
,
BlockNumber
,
Staking
,
())
>
;
type
GenesisElectionProvider
=
Self
::
ElectionProvider
;
...
...
@@ -138,6 +137,7 @@ impl pallet_staking::Config for Runtime {
type
EventListeners
=
Pools
;
type
BenchmarkingConfig
=
pallet_staking
::
TestBenchmarkingConfig
;
type
WeightInfo
=
();
type
DisablingStrategy
=
pallet_staking
::
UpToLimitDisablingStrategy
;
}
parameter_types!
{
...
...
substrate/frame/offences/benchmarking/src/mock.rs
View file @
aceda465
...
...
@@ -174,7 +174,6 @@ impl pallet_staking::Config for Test {
type
EraPayout
=
pallet_staking
::
ConvertCurve
<
RewardCurve
>
;
type
NextNewSession
=
Session
;
type
MaxExposurePageSize
=
ConstU32
<
64
>
;
type
OffendingValidatorsThreshold
=
();
type
ElectionProvider
=
onchain
::
OnChainExecution
<
OnChainSeqPhragmen
>
;
type
GenesisElectionProvider
=
Self
::
ElectionProvider
;
type
VoterList
=
pallet_staking
::
UseNominatorsAndValidatorsMap
<
Self
>
;
...
...
@@ -186,6 +185,7 @@ impl pallet_staking::Config for Test {
type
EventListeners
=
();
type
BenchmarkingConfig
=
pallet_staking
::
TestBenchmarkingConfig
;
type
WeightInfo
=
();
type
DisablingStrategy
=
pallet_staking
::
UpToLimitDisablingStrategy
;
}
impl
pallet_im_online
::
Config
for
Test
{
...
...
substrate/frame/offences/src/lib.rs
View file @
aceda465
...
...
@@ -132,7 +132,6 @@ where
&
concurrent_offenders
,
&
slash_perbill
,
offence
.session_index
(),
offence
.disable_strategy
(),
);
// Deposit the event.
...
...
substrate/frame/offences/src/migration.rs
View file @
aceda465
...
...
@@ -23,7 +23,7 @@ use frame_support::{
weights
::
Weight
,
Twox64Concat
,
};
use
sp_staking
::
offence
::
{
DisableStrategy
,
OnOffenceHandler
}
;
use
sp_staking
::
offence
::
OnOffenceHandler
;
use
sp_std
::
vec
::
Vec
;
#[cfg(feature
=
"try-runtime"
)]
...
...
@@ -106,12 +106,7 @@ pub fn remove_deferred_storage<T: Config>() -> Weight {
let
deferred
=
<
DeferredOffences
<
T
>>
::
take
();
log
::
info!
(
target
:
LOG_TARGET
,
"have {} deferred offences, applying."
,
deferred
.len
());
for
(
offences
,
perbill
,
session
)
in
deferred
.iter
()
{
let
consumed
=
T
::
OnOffenceHandler
::
on_offence
(
offences
,
perbill
,
*
session
,
DisableStrategy
::
WhenSlashed
,
);
let
consumed
=
T
::
OnOffenceHandler
::
on_offence
(
offences
,
perbill
,
*
session
);
weight
=
weight
.saturating_add
(
consumed
);
}
...
...
substrate/frame/offences/src/mock.rs
View file @
aceda465
...
...
@@ -33,7 +33,7 @@ use sp_runtime::{
BuildStorage
,
Perbill
,
};
use
sp_staking
::{
offence
::{
self
,
DisableStrategy
,
Kind
,
OffenceDetails
},
offence
::{
self
,
Kind
,
OffenceDetails
},
SessionIndex
,
};
...
...
@@ -51,7 +51,6 @@ impl<Reporter, Offender> offence::OnOffenceHandler<Reporter, Offender, Weight>
_offenders
:
&
[
OffenceDetails
<
Reporter
,
Offender
>
],
slash_fraction
:
&
[
Perbill
],
_offence_session
:
SessionIndex
,
_disable_strategy
:
DisableStrategy
,
)
->
Weight
{
OnOffencePerbill
::
mutate
(|
f
|
{
*
f
=
slash_fraction
.to_vec
();
...
...
substrate/frame/root-offences/src/lib.rs
View file @
aceda465
...
...
@@ -33,7 +33,7 @@ use alloc::vec::Vec;
use
pallet_session
::
historical
::
IdentificationTuple
;
use
pallet_staking
::{
BalanceOf
,
Exposure
,
ExposureOf
,
Pallet
as
Staking
};
use
sp_runtime
::
Perbill
;
use
sp_staking
::
offence
::
{
DisableStrategy
,
OnOffenceHandler
}
;
use
sp_staking
::
offence
::
OnOffenceHandler
;
pub
use
pallet
::
*
;
...
...
@@ -128,7 +128,7 @@ pub mod pallet {
T
::
AccountId
,
IdentificationTuple
<
T
>
,
Weight
,
>>
::
on_offence
(
&
offenders
,
&
slash_fraction
,
session_index
,
DisableStrategy
::
WhenSlashed
);
>>
::
on_offence
(
&
offenders
,
&
slash_fraction
,
session_index
);
}
}
}
substrate/frame/root-offences/src/mock.rs
View file @
aceda465
...
...
@@ -133,7 +133,6 @@ parameter_types! {
pub
static
SlashDeferDuration
:
EraIndex
=
0
;
pub
const
BondingDuration
:
EraIndex
=
3
;
pub
static
LedgerSlashPerEra
:
(
BalanceOf
<
Test
>
,
BTreeMap
<
EraIndex
,
BalanceOf
<
Test
>>
)
=
(
Zero
::
zero
(),
BTreeMap
::
new
());
pub
const
OffendingValidatorsThreshold
:
Perbill
=
Perbill
::
from_percent
(
75
);
}
impl
pallet_staking
::
Config
for
Test
{
...
...
@@ -153,7 +152,6 @@ impl pallet_staking::Config for Test {
type
EraPayout
=
pallet_staking
::
ConvertCurve
<
RewardCurve
>
;
type
NextNewSession
=
Session
;
type
MaxExposurePageSize
=
ConstU32
<
64
>
;
type
OffendingValidatorsThreshold
=
OffendingValidatorsThreshold
;
type
ElectionProvider
=
onchain
::
OnChainExecution
<
OnChainSeqPhragmen
>
;
type
GenesisElectionProvider
=
Self
::
ElectionProvider
;
type
TargetList
=
pallet_staking
::
UseValidatorsMap
<
Self
>
;
...
...
@@ -165,6 +163,7 @@ impl pallet_staking::Config for Test {
type
EventListeners
=
();
type
BenchmarkingConfig
=
pallet_staking
::
TestBenchmarkingConfig
;
type
WeightInfo
=
();
type
DisablingStrategy
=
pallet_staking
::
UpToLimitDisablingStrategy
;
}
impl
pallet_session
::
historical
::
Config
for
Test
{
...
...
substrate/frame/session/benchmarking/src/mock.rs
View file @
aceda465
...
...
@@ -174,7 +174,6 @@ impl pallet_staking::Config for Test {
type
EraPayout
=
pallet_staking
::
ConvertCurve
<
RewardCurve
>
;
type
NextNewSession
=
Session
;
type
MaxExposurePageSize
=
ConstU32
<
64
>
;
type
OffendingValidatorsThreshold
=
();
type
ElectionProvider
=
onchain
::
OnChainExecution
<
OnChainSeqPhragmen
>
;
type
GenesisElectionProvider
=
Self
::
ElectionProvider
;
type
MaxUnlockingChunks
=
ConstU32
<
32
>
;
...
...
@@ -186,6 +185,7 @@ impl pallet_staking::Config for Test {
type
EventListeners
=
();
type
BenchmarkingConfig
=
pallet_staking
::
TestBenchmarkingConfig
;
type
WeightInfo
=
();
type
DisablingStrategy
=
pallet_staking
::
UpToLimitDisablingStrategy
;
}
impl
crate
::
Config
for
Test
{}
...
...
substrate/frame/session/src/lib.rs
View file @
aceda465
...
...
@@ -627,7 +627,7 @@ impl<T: Config> Pallet<T> {
Validators
::
<
T
>
::
put
(
&
validators
);
if
changed
{
// reset disabled validators
// reset disabled validators
if active set was changed
<
DisabledValidators
<
T
>>
::
take
();
}
...
...
substrate/frame/staking/CHANGELOG.md
View file @
aceda465
...
...
@@ -7,6 +7,25 @@ on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). We maintain a
single integer version number for staking pallet to keep track of all storage
migrations.
## [v15]
### Added
-
New trait
`DisablingStrategy`
which is responsible for making a decision which offenders should be
disabled on new offence.
-
Default implementation of
`DisablingStrategy`
-
`UpToLimitDisablingStrategy`
. It
disables each new offender up to a threshold (1/3 by default). Offenders are not runtime disabled for
offences in previous era(s). But they will be low-priority node-side disabled for dispute initiation.
-
`OffendingValidators`
storage item is replaced with
`DisabledValidators`
. The former keeps all
offenders and if they are disabled or not. The latter just keeps a list of all offenders as they
are disabled by default.
### Deprecated
-
`enum DisableStrategy`
is no longer needed because disabling is not related to the type of the
offence anymore. A decision if a offender is disabled or not is made by a
`DisablingStrategy`
implementation.
## [v14]
### Added
...
...
substrate/frame/staking/src/lib.rs
View file @
aceda465
...
...
@@ -1239,3 +1239,79 @@ impl BenchmarkingConfig for TestBenchmarkingConfig {
type
MaxValidators
=
frame_support
::
traits
::
ConstU32
<
100
>
;
type
MaxNominators
=
frame_support
::
traits
::
ConstU32
<
100
>
;
}
/// Controls validator disabling
pub
trait
DisablingStrategy
<
T
:
Config
>
{
/// Make a disabling decision. Returns the index of the validator to disable or `None` if no new
/// validator should be disabled.
fn
decision
(
offender_stash
:
&
T
::
AccountId
,
slash_era
:
EraIndex
,
currently_disabled
:
&
Vec
<
u32
>
,
)
->
Option
<
u32
>
;
}
/// Implementation of [`DisablingStrategy`] which disables validators from the active set up to a
/// threshold. `DISABLING_LIMIT_FACTOR` is the factor of the maximum disabled validators in the
/// active set. E.g. setting this value to `3` means no more than 1/3 of the validators in the
/// active set can be disabled in an era.
/// By default a factor of 3 is used which is the byzantine threshold.
pub
struct
UpToLimitDisablingStrategy
<
const
DISABLING_LIMIT_FACTOR
:
usize
=
3
>
;
impl
<
const
DISABLING_LIMIT_FACTOR
:
usize
>
UpToLimitDisablingStrategy
<
DISABLING_LIMIT_FACTOR
>
{
/// Disabling limit calculated from the total number of validators in the active set. When
/// reached no more validators will be disabled.
pub
fn
disable_limit
(
validators_len
:
usize
)
->
usize
{
validators_len
.saturating_sub
(
1
)
.checked_div
(
DISABLING_LIMIT_FACTOR
)
.unwrap_or_else
(||
{
defensive!
(
"DISABLING_LIMIT_FACTOR should not be 0"
);
0
})
}
}
impl
<
T
:
Config
,
const
DISABLING_LIMIT_FACTOR
:
usize
>
DisablingStrategy
<
T
>
for
UpToLimitDisablingStrategy
<
DISABLING_LIMIT_FACTOR
>
{
fn
decision
(
offender_stash
:
&
T
::
AccountId
,
slash_era
:
EraIndex
,
currently_disabled
:
&
Vec
<
u32
>
,
)
->
Option
<
u32
>
{
let
active_set
=
T
::
SessionInterface
::
validators
();
// We don't disable more than the limit
if
currently_disabled
.len
()
>=
Self
::
disable_limit
(
active_set
.len
())
{
log
!
(
debug
,
"Won't disable: reached disabling limit {:?}"
,
Self
::
disable_limit
(
active_set
.len
())
);
return
None
}
// We don't disable for offences in previous eras
if
ActiveEra
::
<
T
>
::
get
()
.map
(|
e
|
e
.index
)
.unwrap_or_default
()
>
slash_era
{
log
!
(
debug
,
"Won't disable: current_era {:?} > slash_era {:?}"
,
Pallet
::
<
T
>
::
current_era
()
.unwrap_or_default
(),
slash_era
);
return
None
}
let
offender_idx
=
if
let
Some
(
idx
)
=
active_set
.iter
()
.position
(|
i
|
i
==
offender_stash
)
{
idx
as
u32
}
else
{
log
!
(
debug
,
"Won't disable: offender not in active set"
,);
return
None
};
log
!
(
debug
,
"Will disable {:?}"
,
offender_idx
);
Some
(
offender_idx
)
}
}
substrate/frame/staking/src/migrations.rs
View file @
aceda465
...
...
@@ -20,9 +20,10 @@
use
super
::
*
;
use
frame_election_provider_support
::
SortedListProvider
;
use
frame_support
::{
migrations
::
VersionedMigration
,
pallet_prelude
::
ValueQuery
,
storage_alias
,
traits
::{
GetStorageVersion
,
OnRuntimeUpgrade
},
traits
::{
GetStorageVersion
,
OnRuntimeUpgrade
,
UncheckedOnRuntimeUpgrade
},
};
#[cfg(feature
=
"try-runtime"
)]
...
...
@@ -59,11 +60,61 @@ impl Default for ObsoleteReleases {
#[storage_alias]
type
StorageVersion
<
T
:
Config
>
=
StorageValue
<
Pallet
<
T
>
,
ObsoleteReleases
,
ValueQuery
>
;
/// Migrating `OffendingValidators` from `Vec<(u32, bool)>` to `Vec<u32>`
pub
mod
v15
{
use
super
::
*
;
// The disabling strategy used by staking pallet
type
DefaultDisablingStrategy
=
UpToLimitDisablingStrategy
;
pub
struct
VersionUncheckedMigrateV14ToV15
<
T
>
(
sp_std
::
marker
::
PhantomData
<
T
>
);
impl
<
T
:
Config
>
UncheckedOnRuntimeUpgrade
for
VersionUncheckedMigrateV14ToV15
<
T
>
{
fn
on_runtime_upgrade
()
->
Weight
{
let
mut
migrated
=
v14
::
OffendingValidators
::
<
T
>
::
take
()
.into_iter
()
.filter
(|
p
|
p
.1
)
// take only disabled validators
.map
(|
p
|
p
.0
)
.collect
::
<
Vec
<
_
>>
();
// Respect disabling limit
migrated
.truncate
(
DefaultDisablingStrategy
::
disable_limit
(
T
::
SessionInterface
::
validators
()
.len
(),
));
DisabledValidators
::
<
T
>
::
set
(
migrated
);
log
!
(
info
,
"v15 applied successfully."
);
T
::
DbWeight
::
get
()
.reads_writes
(
1
,
1
)
}
#[cfg(feature
=
"try-runtime"
)]
fn
post_upgrade
(
_state
:
Vec
<
u8
>
)
->
Result
<
(),
TryRuntimeError
>
{
frame_support
::
ensure!
(
v14
::
OffendingValidators
::
<
T
>
::
decode_len
()
.is_none
(),
"OffendingValidators is not empty after the migration"
);
Ok
(())
}
}
pub
type
MigrateV14ToV15
<
T
>
=
VersionedMigration
<
14
,
15
,
VersionUncheckedMigrateV14ToV15
<
T
>
,
Pallet
<
T
>
,
<
T
as
frame_system
::
Config
>
::
DbWeight
,
>
;
}
/// Migration of era exposure storage items to paged exposures.
/// Changelog: [v14.](https://github.com/paritytech/substrate/blob/ankan/paged-rewards-rebased2/frame/staking/CHANGELOG.md#14)
pub
mod
v14
{
use
super
::
*
;
#[frame_support::storage_alias]
pub
(
crate
)
type
OffendingValidators
<
T
:
Config
>
=
StorageValue
<
Pallet
<
T
>
,
Vec
<
(
u32
,
bool
)
>
,
ValueQuery
>
;
pub
struct
MigrateToV14
<
T
>
(
core
::
marker
::
PhantomData
<
T
>
);
impl
<
T
:
Config
>
OnRuntimeUpgrade
for
MigrateToV14
<
T
>
{
fn
on_runtime_upgrade
()
->
Weight
{
...
...
@@ -73,10 +124,10 @@ pub mod v14 {
if
in_code
==
14
&&
on_chain
==
13
{
in_code
.put
::
<
Pallet
<
T
>>
();
log
!
(
info
,
"v14 applied successfully."
);
log
!
(
info
,
"
staking
v14 applied successfully."
);
T
::
DbWeight
::
get
()
.reads_writes
(
1
,
1
)
}
else
{
log
!
(
warn
,
"v14 not applied."
);
log
!
(
warn
,
"
staking
v14 not applied."
);
T
::
DbWeight
::
get
()
.reads
(
1
)
}
}
...
...
substrate/frame/staking/src/mock.rs
View file @
aceda465
...
...
@@ -34,7 +34,7 @@ use frame_system::{EnsureRoot, EnsureSignedBy};
use
sp_io
;
use
sp_runtime
::{
curve
::
PiecewiseLinear
,
testing
::
UintAuthorityId
,
traits
::
Zero
,
BuildStorage
};
use
sp_staking
::{
offence
::{
DisableStrategy
,
OffenceDetails
,
OnOffenceHandler
},
offence
::{
OffenceDetails
,
OnOffenceHandler
},
OnStakingUpdate
,
};
...
...
@@ -186,7 +186,6 @@ pallet_staking_reward_curve::build! {
parameter_types!
{
pub
const
BondingDuration
:
EraIndex
=
3
;
pub
const
RewardCurve
:
&
'static
PiecewiseLinear
<
'static
>
=
&
I_NPOS
;
pub
const
OffendingValidatorsThreshold
:
Perbill
=
Perbill
::
from_percent
(
75
);
}
parameter_types!
{
...
...
@@ -267,6 +266,9 @@ impl OnStakingUpdate<AccountId, Balance> for EventListenerMock {
}
}
// Disabling threshold for `UpToLimitDisablingStrategy`
pub
(
crate
)
const
DISABLING_LIMIT_FACTOR
:
usize
=
3
;
impl
crate
::
pallet
::
pallet
::
Config
for
Test
{
type
Currency
=
Balances
;
type
CurrencyBalance
=
<
Self
as
pallet_balances
::
Config
>
::
Balance
;
...
...
@@ -284,7 +286,6 @@ impl crate::pallet::pallet::Config for Test {
type
EraPayout
=
ConvertCurve
<
RewardCurve
>
;
type
NextNewSession
=
Session
;
type
MaxExposurePageSize
=
MaxExposurePageSize
;
type
OffendingValidatorsThreshold
=
OffendingValidatorsThreshold
;
type
ElectionProvider
=
onchain
::
OnChainExecution
<
OnChainSeqPhragmen
>
;
type
GenesisElectionProvider
=
Self
::
ElectionProvider
;
// NOTE: consider a macro and use `UseNominatorsAndValidatorsMap<Self>` as well.
...
...
@@ -297,6 +298,7 @@ impl crate::pallet::pallet::Config for Test {
type
EventListeners
=
EventListenerMock
;
type
BenchmarkingConfig
=
TestBenchmarkingConfig
;
type
WeightInfo
=
();
type
DisablingStrategy
=
pallet_staking
::
UpToLimitDisablingStrategy
<
DISABLING_LIMIT_FACTOR
>
;
}
pub
struct
WeightedNominationsQuota
<
const
MAX
:
u32
>
;
...
...
@@ -461,6 +463,8 @@ impl ExtBuilder {
(
31
,
self
.balance_factor
*
2000
),
(
41
,
self
.balance_factor
*
2000
),
(
51
,
self
.balance_factor
*
2000
),
(
201
,
self
.balance_factor
*
2000
),
(
202
,
self
.balance_factor
*
2000
),
// optional nominator
(
100
,
self
.balance_factor
*
2000
),
(
101
,
self
.balance_factor
*
2000
),
...
...
@@ -488,8 +492,10 @@ impl ExtBuilder {
(
31
,
31
,
self
.balance_factor
*
500
,
StakerStatus
::
<
AccountId
>
::
Validator
),
// an idle validator
(
41
,
41
,
self
.balance_factor
*
1000
,
StakerStatus
::
<
AccountId
>
::
Idle
),
];
// optionally add a nominator
(
51
,
51
,
self
.balance_factor
*
1000
,
StakerStatus
::
<
AccountId
>
::
Idle
),
(
201
,
201
,
self
.balance_factor
*
1000
,
StakerStatus
::
<
AccountId
>
::
Idle
),
(
202
,
202
,
self
.balance_factor
*
1000
,
StakerStatus
::
<
AccountId
>
::
Idle
),
];
// optionally add a nominator
if
self
.nominate
{
stakers
.push
((
101
,
...
...
@@ -728,12 +734,11 @@ pub(crate) fn on_offence_in_era(
>
],
slash_fraction
:
&
[
Perbill
],
era
:
EraIndex
,
disable_strategy
:
DisableStrategy
,
)
{
let
bonded_eras
=
crate
::
BondedEras
::
<
Test
>
::
get
();
for
&
(
bonded_era
,
start_session
)
in
bonded_eras
.iter
()
{
if
bonded_era
==
era
{
let
_
=
Staking
::
on_offence
(
offenders
,
slash_fraction
,
start_session
,
disable_strategy
);
let
_
=
Staking
::
on_offence
(
offenders
,
slash_fraction
,
start_session
);
return
}
else
if
bonded_era
>
era
{
break
...
...
@@ -745,7 +750,6 @@ pub(crate) fn on_offence_in_era(
offenders
,
slash_fraction
,
Staking
::
eras_start_session_index
(
era
)
.unwrap
(),
disable_strategy
,
);
}
else
{
panic!
(
"cannot slash in era {}"
,
era
);
...
...
@@ -760,7 +764,7 @@ pub(crate) fn on_offence_now(
slash_fraction
:
&
[
Perbill
],
)
{
let
now
=
Staking
::
active_era
()
.unwrap
()
.index
;
on_offence_in_era
(
offenders
,
slash_fraction
,
now
,
DisableStrategy
::
WhenSlashed
)
on_offence_in_era
(
offenders
,
slash_fraction
,
now
)
}
pub
(
crate
)
fn
add_slash
(
who
:
&
AccountId
)
{
...
...
Prev
1
…
11
12
13
14
15
16
17
Next