pub(crate) struct TryElection<T: Config> {
pub by: T::Public,
pub at: BlockNumberFor<T>,
}Expand description
Operational context for election transaction execution.
This type represents the contextual information required to attempt authors election using an affidavit key during the routine lifecycle.
Election attempts are optimistic, sequential routines that may execute repeatedly as part of a looped execution model (e.g. via offchain workers). Although election typically follows the affidavit declaration phase, explicit looping of sequential routines allows this phase to run earlier. The routine remains safe, as successful election is gated by retrievable storage state, election window constraints, and eligibility checks.
§Notes
- This is not a transaction payload.
- This type is never submitted on-chain.
- It is used internally during:
- fetching the active-tagged affidavit key (storage-reference + keystore-pair)
- election payload signing using the affidavit key pair
- submission of the
electextrinsic - retry-driven OCW election execution
§Fork Awareness
- The
atfield captures the block number at which the election attempt begins. - When executed via offchain workers, this context must tolerate forks, re-orgs, and speculative execution.
- Implementors are responsible for ensuring idempotency and re-entrancy safety.
§Dependency: InitAffidavitKey
This routine depends on the affidavit key initialization phase.
It assumes that a active-tagged (offchain storage referenced) affidavit key
and its pair in crypto-store is available. Whenever this invariant is violated
(e.g. missing key, failed signing, or inconsistent state), control is redirected
to InitAffidavitKey to repair and re-validate the key before retrying the
election attempt.
§Election Flow
The routine fetches the active-tagged affidavit key-pair (referenced via offchain storage and retrieved through local keystore), then attempts author election. It short-circuits when outside the election window, when ineligible, or when already elected (to avoid redundancy). Failures or inconsistencies re-enter the affidavit initialization phase for re-validation and repair.
loop {
// Ensure active-tagged affidavit key is available
InitAffidavitKey::ensure_active_affidavit_key();
// Fetch affidavit key pair (offchain storage reference + keystore-pair)
let key_pair = fetch_affidavit_key_pair();
if !within_election_window()
|| !eligible_to_elect()
|| already_elected()
{
break; // proceed to declaration phase (no election required)
}
let payload = Default::default();
match sign_payload_with(key_pair)
.and_then(|payload| submit_elect_authors_extrinsic(payload))
{
Ok(_) => break, // elect-phase completed successfully
Err(_) => continue, // retry via initialization phase again
}
}§Guarantees
This routine proceeds to the affidavit declaration phase under exactly two conditions:
-
Initialization-only path: a active-tagged affidavit key-pair exists, but election constraints are not satisfied (outside window, ineligible, or already elected).
-
Election-complete path: a active-tagged affidavit key-pair exists, election constraints are satisfied, and the
electextrinsic is successfully submitted.
In all other cases, the routine retries by re-entering the affidavit key initialization phase to re-validate offchain storage and keystore consistency.
All behavior is supplied by trait implementations operating on this type.
§FlowChart
Fields§
§by: T::PublicPublic key authorized to sign election transactions.
at: BlockNumberFor<T>Block number at which election execution is initiated.
Trait Implementations§
Source§impl<T: Clone + Config> Clone for TryElection<T>where
T::Public: Clone,
impl<T: Clone + Config> Clone for TryElection<T>where
T::Public: Clone,
Source§fn clone(&self) -> TryElection<T>
fn clone(&self) -> TryElection<T>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<T> Debug for TryElection<T>
impl<T> Debug for TryElection<T>
Source§impl<T: Config> Decode for TryElection<T>where
T::Public: Decode,
BlockNumberFor<T>: Decode,
impl<T: Config> Decode for TryElection<T>where
T::Public: Decode,
BlockNumberFor<T>: Decode,
Source§fn decode<__CodecInputEdqy: Input>(
__codec_input_edqy: &mut __CodecInputEdqy,
) -> Result<Self, Error>
fn decode<__CodecInputEdqy: Input>( __codec_input_edqy: &mut __CodecInputEdqy, ) -> Result<Self, Error>
§fn decode_into<I>(
input: &mut I,
dst: &mut MaybeUninit<Self>,
) -> Result<DecodeFinished, Error>where
I: Input,
fn decode_into<I>(
input: &mut I,
dst: &mut MaybeUninit<Self>,
) -> Result<DecodeFinished, Error>where
I: Input,
§fn skip<I>(input: &mut I) -> Result<(), Error>where
I: Input,
fn skip<I>(input: &mut I) -> Result<(), Error>where
I: Input,
§fn encoded_fixed_size() -> Option<usize>
fn encoded_fixed_size() -> Option<usize>
Source§impl<T: Config> Encode for TryElection<T>where
T::Public: Encode,
BlockNumberFor<T>: Encode,
impl<T: Config> Encode for TryElection<T>where
T::Public: Encode,
BlockNumberFor<T>: Encode,
Source§fn size_hint(&self) -> usize
fn size_hint(&self) -> usize
Source§fn encode_to<__CodecOutputEdqy: Output + ?Sized>(
&self,
__codec_dest_edqy: &mut __CodecOutputEdqy,
)
fn encode_to<__CodecOutputEdqy: Output + ?Sized>( &self, __codec_dest_edqy: &mut __CodecOutputEdqy, )
§fn using_encoded<R, F>(&self, f: F) -> R
fn using_encoded<R, F>(&self, f: F) -> R
§fn encoded_size(&self) -> usize
fn encoded_size(&self) -> usize
Source§impl<T: Config> MaxEncodedLen for TryElection<T>where
T::Public: MaxEncodedLen,
BlockNumberFor<T>: MaxEncodedLen,
impl<T: Config> MaxEncodedLen for TryElection<T>where
T::Public: MaxEncodedLen,
BlockNumberFor<T>: MaxEncodedLen,
Source§fn max_encoded_len() -> usize
fn max_encoded_len() -> usize
Source§impl<T: Config> RoutineOf<<T as SigningTypes>::Public, <<<T as Config>::Block as HeaderProvider>::HeaderT as Header>::Number> for TryElection<T>
Authorization layer for the election execution routine.
impl<T: Config> RoutineOf<<T as SigningTypes>::Public, <<<T as Config>::Block as HeaderProvider>::HeaderT as Header>::Number> for TryElection<T>
Authorization layer for the election execution routine.
This implementation resolves the affidavit public key authorized
to run the election flow. It deliberately reuses the key-resolution
logic from DeclareAffidavit to enforce strict lifecycle ordering:
Affidavit Declaration -> Key Rotation -> ElectionBy delegating authorization instead of duplicating it, this layer guarantees that elections are executed only by authors who have successfully completed the affidavit and key-rotation process.
Source§fn who(at: &BlockNumberFor<T>) -> Result<T::Public, Self::Logger>
fn who(at: &BlockNumberFor<T>) -> Result<T::Public, Self::Logger>
Determines the affidavit public key authorized to run the election routine.
§Semantics
- Reuses the currently active affidavit key resolved by
DeclareAffidavit. - Ensures that election execution is authorized by the same operational key that is eligible for affidavit declaration.
§Rationale
Elections are permitted only after a successful affidavit
declaration and key-rotation cycle. By delegating to
DeclareAffidavit::who, this routine enforces a strict
lifecycle ordering without duplicating key-resolution logic.
§Key Resolution Note
Although this appears syntactically as the active affidavit key,
it semantically represents the recently rotated next affidavit key
that was promoted to active status by the previous OCW execution’s
final routine (RotateAffidavitKey).
Source§impl<T: Config> Routines<<<<T as Config>::Block as HeaderProvider>::HeaderT as Header>::Number> for TryElection<T>
Offchain routine responsible for opportunistic election execution.
impl<T: Config> Routines<<<<T as Config>::Block as HeaderProvider>::HeaderT as Header>::Number> for TryElection<T>
Offchain routine responsible for opportunistic election execution.
This routine attempts to submit the elect extrinsic for the
upcoming session using the currently active affidavit key.
It is intentionally designed to be:
- Non-blocking: exits silently when prerequisites are unmet.
- Idempotent: safe to run repeatedly across blocks and forks.
- Pre-emptive: elections may be attempted before the OCW pipeline fully converges, succeeding in later executions.
The routine participates in the OCW execution pipeline:
InitAffidavitKey -> TryElection -> DeclareAffidavit -> RotateAffidavitKeyand relies on repeated OCW invocations to eventually satisfy all temporal and state-dependent constraints.
Source§fn can_run(&self) -> Result<(), Self::Logger>
fn can_run(&self) -> Result<(), Self::Logger>
Checks whether an election can be processed in the current block.
§Semantics
- Delegates election window validation to
ElectAuthors::can_process_election. - Does not treat an unavailable election window as an error.
§Behavior
- If the election window is not open, the routine exits early with an informational log.
- Hard failures (e.g. invalid configuration) are surfaced as logged errors.
This design allows the OCW orchestrator to continue executing subsequent routines (e.g. affidavit declaration) in the same block.
Source§fn run_service(&self) -> Result<(), Self::Logger>
fn run_service(&self) -> Result<(), Self::Logger>
Attempts to submit the election transaction for the upcoming session.
§Execution Strategy
This routine is opportunistic and non-blocking:
- If the election window is not open, execution passes silently to next routine.
- If the author is not eligible, execution exits silently.
- If the author already acted as the election runner, execution exits silently.
This behavior is intentional and allows the OCW pipeline to be orchestrated in the following order:
InitAffidavitKey -> TryElection -> DeclareAffidavit -> RotateAffidavitKeyElections are therefore attempted pre-emptively and may succeed in a later OCW invocation once all prerequisites converge.
§Semantics
- Uses the currently active affidavit key to authorize the election.
- Submits an unsigned
electextrinsic signed offchain. - Ensures that each author runs the election at most once per session.
§Failure Handling
- All signing or submission failures are logged as errors.
- No retries are attempted in the same block.
- Subsequent OCW executions may retry automatically.
Source§fn on_ran_service(&self)
fn on_ran_service(&self)
Logs a info message on a successful TryElection routine.
Source§impl<T> TypeInfo for TryElection<T>where
T::Public: TypeInfo + 'static,
BlockNumberFor<T>: TypeInfo + 'static,
T: Config + 'static,
impl<T> TypeInfo for TryElection<T>where
T::Public: TypeInfo + 'static,
BlockNumberFor<T>: TypeInfo + 'static,
T: Config + 'static,
impl<T: Config> EncodeLike for TryElection<T>where
T::Public: Encode,
BlockNumberFor<T>: Encode,
impl<T: Eq + Config> Eq for TryElection<T>where
T::Public: Eq,
impl<T: Config> StructuralPartialEq for TryElection<T>
Auto Trait Implementations§
impl<T> Freeze for TryElection<T>
impl<T> RefUnwindSafe for TryElection<T>where
<T as SigningTypes>::Public: RefUnwindSafe,
<<<T as Config>::Block as Block>::Header as Header>::Number: RefUnwindSafe,
impl<T> Send for TryElection<T>where
<T as SigningTypes>::Public: Send,
impl<T> Sync for TryElection<T>where
<T as SigningTypes>::Public: Sync,
impl<T> Unpin for TryElection<T>
impl<T> UnwindSafe for TryElection<T>where
<T as SigningTypes>::Public: UnwindSafe,
<<<T as Config>::Block as Block>::Header as Header>::Number: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> CheckedConversion for T
impl<T> CheckedConversion for T
§fn checked_from<T>(t: T) -> Option<Self>where
Self: TryFrom<T>,
fn checked_from<T>(t: T) -> Option<Self>where
Self: TryFrom<T>,
§fn checked_into<T>(self) -> Option<T>where
Self: TryInto<T>,
fn checked_into<T>(self) -> Option<T>where
Self: TryInto<T>,
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> DecodeAll for Twhere
T: Decode,
impl<T> DecodeAll for Twhere
T: Decode,
§fn decode_all(input: &mut &[u8]) -> Result<T, Error>
fn decode_all(input: &mut &[u8]) -> Result<T, Error>
Self and consume all of the given input data. Read more§impl<T> DecodeLimit for Twhere
T: Decode,
impl<T> DecodeLimit for Twhere
T: Decode,
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<T> Hashable for Twhere
T: Codec,
impl<T> Hashable for Twhere
T: Codec,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T, U, Tag> IntoTag<U, Tag> for Twhere
U: FromTag<T, Tag>,
Tag: DiscriminantTag,
impl<T, U, Tag> IntoTag<U, Tag> for Twhere
U: FromTag<T, Tag>,
Tag: DiscriminantTag,
§impl<Src, Dest> IntoTuple<Dest> for Srcwhere
Dest: FromTuple<Src>,
impl<Src, Dest> IntoTuple<Dest> for Srcwhere
Dest: FromTuple<Src>,
fn into_tuple(self) -> Dest
§impl<T> IsType<T> for T
impl<T> IsType<T> for T
§impl<T, Outer> IsWrappedBy<Outer> for T
impl<T, Outer> IsWrappedBy<Outer> for T
§impl<T> KeyedVec for Twhere
T: Codec,
impl<T> KeyedVec for Twhere
T: Codec,
Source§impl<T, Time> Logging<Time> for Twhere
Time: Time,
impl<T, Time> Logging<Time> for Twhere
Time: Time,
Source§const FALLBACK_TARGET: &'static str = "routine"
const FALLBACK_TARGET: &'static str = "routine"
Default logging target if none is provided.
Most routines, especially offchain workers or background tasks, use this target for simplicity.
It allows a consistent place to look for routine logs without requiring every call to specify a target.
Note: This target is only a conveninence and may be somewhat vague. To ensure errors can still be traced accurately, the logged messages should include additional metadata (e.g., module name, error index, or contextual info) so that the source of the error can be identified even if the target is generic.
Source§type Logger = DispatchError
type Logger = DispatchError
The type taken and returned for logging.
We simply return the same [DispatchError] that was logged,
so logging does not change control flow or error propagation.
DispatchError is used because in Substrate it encompasses all
runtime errors - including module errors, token errors, arithmetic
issues, and transactional boundaries - making it the universal
substrate-side error representation.
Source§type Level = LogLevel
type Level = LogLevel
The log level type.
We use the LogLevel enum to standardize severity levels
(Info, Warn, Error, Debug) across all routine logs.
Source§fn log(
level: <T as Logging<Time>>::Level,
err: &<T as Logging<Time>>::Logger,
timestamp: Time,
target: Option<&str>,
fmt: Option<fn(Time, &<T as Logging<Time>>::Level, &str, &str) -> String>,
) -> <T as Logging<Time>>::Logger
fn log( level: <T as Logging<Time>>::Level, err: &<T as Logging<Time>>::Logger, timestamp: Time, target: Option<&str>, fmt: Option<fn(Time, &<T as Logging<Time>>::Level, &str, &str) -> String>, ) -> <T as Logging<Time>>::Logger
Source§fn info(
err: &Self::Logger,
timestamp: Timestamp,
target: Option<&str>,
fmt: Option<fn(Timestamp, &Self::Level, &str, &str) -> String>,
) -> Self::Loggerwhere
Self: Sized,
fn info(
err: &Self::Logger,
timestamp: Timestamp,
target: Option<&str>,
fmt: Option<fn(Timestamp, &Self::Level, &str, &str) -> String>,
) -> Self::Loggerwhere
Self: Sized,
Source§fn warn(
err: &Self::Logger,
timestamp: Timestamp,
target: Option<&str>,
fmt: Option<fn(Timestamp, &Self::Level, &str, &str) -> String>,
) -> Self::Loggerwhere
Self: Sized,
fn warn(
err: &Self::Logger,
timestamp: Timestamp,
target: Option<&str>,
fmt: Option<fn(Timestamp, &Self::Level, &str, &str) -> String>,
) -> Self::Loggerwhere
Self: Sized,
§impl<T> SaturatedConversion for T
impl<T> SaturatedConversion for T
§fn saturated_from<T>(t: T) -> Selfwhere
Self: UniqueSaturatedFrom<T>,
fn saturated_from<T>(t: T) -> Selfwhere
Self: UniqueSaturatedFrom<T>,
§fn saturated_into<T>(self) -> Twhere
Self: UniqueSaturatedInto<T>,
fn saturated_into<T>(self) -> Twhere
Self: UniqueSaturatedInto<T>,
T. Read more§impl<T, U> TryIntoKey<U> for Twhere
U: TryFromKey<T>,
impl<T, U> TryIntoKey<U> for Twhere
U: TryFromKey<T>,
type Error = <U as TryFromKey<T>>::Error
fn try_into_key(self) -> Result<U, <U as TryFromKey<T>>::Error>
§impl<S, T> UncheckedInto<T> for Swhere
T: UncheckedFrom<S>,
impl<S, T> UncheckedInto<T> for Swhere
T: UncheckedFrom<S>,
§fn unchecked_into(self) -> T
fn unchecked_into(self) -> T
unchecked_from.§impl<T, S> UniqueSaturatedInto<T> for S
impl<T, S> UniqueSaturatedInto<T> for S
§fn unique_saturated_into(self) -> T
fn unique_saturated_into(self) -> T
T.