Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ parameter_types! {
pub static MinerTxPriority: u64 = 100;
pub static SolutionImprovementThreshold: Perbill = Perbill::zero();
pub static OffchainRepeat: BlockNumber = 5;
pub static OffchainStorage: bool = true;
pub static MinerMaxLength: u32 = 256;
pub static MinerPages: u32 = 1;
pub static MaxVotesPerVoter: u32 = <TestNposSolution as NposSolution>::LIMIT as u32;
Expand Down Expand Up @@ -193,6 +194,7 @@ impl crate::verifier::Config for Runtime {
impl crate::unsigned::Config for Runtime {
type MinerPages = MinerPages;
type OffchainRepeat = OffchainRepeat;
type OffchainStorage = OffchainStorage;
type MinerTxPriority = MinerTxPriority;
type OffchainSolver = SequentialPhragmen<Self::AccountId, Perbill>;
type WeightInfo = ();
Expand Down Expand Up @@ -354,6 +356,10 @@ impl ExtBuilder {
MaxBackersPerWinnerFinal::set(c);
self
}
pub(crate) fn offchain_storage(self, s: bool) -> Self {
OffchainStorage::set(s);
self
}
pub(crate) fn miner_tx_priority(self, p: u64) -> Self {
MinerTxPriority::set(p);
self
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -746,12 +746,14 @@ impl<T: Config> OffchainWorkerMiner<T> {
Ok(call)
}

/// Mine a new checked solution, cache it, and submit it back to the chain as an unsigned
/// Mine a new checked solution, maybe cache it, and submit it back to the chain as an unsigned
/// transaction.
pub fn mine_check_save_submit() -> Result<(), OffchainMinerError<T>> {
pub(crate) fn mine_check_maybe_save_submit(save: bool) -> Result<(), OffchainMinerError<T>> {
sublog!(debug, "unsigned::ocw-miner", "miner attempting to compute an unsigned solution.");
let call = Self::mine_checked_call()?;
Self::save_solution(&call, crate::Snapshot::<T>::fingerprint())?;
if save {
Self::save_solution(&call, crate::Snapshot::<T>::fingerprint())?;
}
Self::submit_call(call)
}

Expand All @@ -762,7 +764,7 @@ impl<T: Config> OffchainWorkerMiner<T> {
/// 1. optionally feasibility check.
/// 2. snapshot-independent checks.
/// 1. optionally, snapshot fingerprint.
pub fn check_solution(
pub(crate) fn check_solution(
paged_solution: &PagedRawSolution<T::MinerConfig>,
maybe_snapshot_fingerprint: Option<T::Hash>,
do_feasibility: bool,
Expand Down Expand Up @@ -824,7 +826,7 @@ impl<T: Config> OffchainWorkerMiner<T> {

/// Attempt to restore a solution from cache. Otherwise, compute it fresh. Either way,
/// submit if our call's score is greater than that of the cached solution.
pub fn restore_or_compute_then_maybe_submit() -> Result<(), OffchainMinerError<T>> {
pub(crate) fn restore_or_compute_then_maybe_submit() -> Result<(), OffchainMinerError<T>> {
sublog!(
debug,
"unsigned::ocw-miner",
Expand Down Expand Up @@ -2231,9 +2233,32 @@ mod offchain_worker_miner {
});
}

#[test]
#[ignore]
fn multi_page_miner_on_remote_state() {
todo!();
mod no_storage {
Comment thread
kianenigma marked this conversation as resolved.
use super::*;
#[test]
fn initial_ocw_runs_and_does_not_save() {
// as per `T::OffchainStorage`.
let (mut ext, pool) = ExtBuilder::unsigned().offchain_storage(false).build_offchainify();
ext.execute_with_sanity_checks(|| {
roll_to_unsigned_open();

let last_block = StorageValueRef::persistent(
&OffchainWorkerMiner::<Runtime>::OFFCHAIN_LAST_BLOCK,
);
let cache = StorageValueRef::persistent(
&OffchainWorkerMiner::<Runtime>::OFFCHAIN_CACHED_CALL,
);

assert_eq!(last_block.get::<BlockNumber>(), Ok(None));
assert_eq!(cache.get::<crate::unsigned::Call<Runtime>>(), Ok(None));

// creates, submits without expecting previous cache value
UnsignedPallet::offchain_worker(25);

assert_eq!(pool.read().transactions.len(), 1);
assert_eq!(last_block.get::<BlockNumber>(), Ok(Some(25)));
assert_eq!(cache.get::<crate::unsigned::Call<Runtime>>(), Ok(None));
})
}
}
}
56 changes: 36 additions & 20 deletions substrate/frame/election-provider-multi-block/src/unsigned/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,20 @@ mod pallet {
pub trait Config: crate::Config + CreateBare<Call<Self>> {
/// The repeat threshold of the offchain worker.
///
/// For example, if it is 5, that means that at least 5 blocks will elapse between attempts
/// to submit the worker's solution.
/// For example, if it is `5`, that means that at least 5 blocks will elapse between
/// attempts to submit the worker's solution.
type OffchainRepeat: Get<BlockNumberFor<Self>>;

/// The solver used in hte offchain worker miner
type OffchainSolver: frame_election_provider_support::NposSolver<
AccountId = Self::AccountId,
>;

/// Whether the offchain worker miner would attempt to store the solutions in a local
/// database and reuse then. If set to `false`, it will try and re-mine solutions every
/// time.
type OffchainStorage: Get<bool>;

/// The priority of the unsigned transaction submitted in the unsigned-phase
type MinerTxPriority: Get<TransactionPriority>;

Expand Down Expand Up @@ -264,7 +269,7 @@ mod pallet {
},
Err(deadline) => {
sublog!(
debug,
trace,
"unsigned",
"offchain worker lock not released, deadline is {:?}",
deadline
Expand All @@ -279,33 +284,44 @@ mod pallet {
/// acquired with success.
fn do_synchronized_offchain_worker(now: BlockNumberFor<T>) {
use miner::OffchainWorkerMiner;

let current_phase = crate::Pallet::<T>::current_phase();
sublog!(
trace,
"unsigned",
"lock for offchain worker acquired. Phase = {:?}",
current_phase
);

// do the repeat frequency check just one, if we are in unsigned phase.
if current_phase.is_unsigned() {
if let Err(reason) = OffchainWorkerMiner::<T>::ensure_offchain_repeat_frequency(now)
{
sublog!(
debug,
"unsigned",
"offchain worker repeat frequency check failed: {:?}",
reason
);
return;
}
}

if current_phase.is_unsigned_opened_now() {
// Mine a new solution, cache it, and attempt to submit it
let initial_output =
OffchainWorkerMiner::<T>::ensure_offchain_repeat_frequency(now)
.and_then(|_| OffchainWorkerMiner::<T>::mine_check_save_submit());
// Mine a new solution, (maybe) cache it, and attempt to submit it
let initial_output = if T::OffchainStorage::get() {
OffchainWorkerMiner::<T>::mine_check_maybe_save_submit(true)
} else {
OffchainWorkerMiner::<T>::mine_check_maybe_save_submit(false)
};
sublog!(debug, "unsigned", "initial offchain worker output: {:?}", initial_output);
} else if current_phase.is_unsigned() {
// Try and resubmit the cached solution, and recompute ONLY if it is not
// feasible.
let resubmit_output = OffchainWorkerMiner::<T>::ensure_offchain_repeat_frequency(
now,
)
.and_then(|_| OffchainWorkerMiner::<T>::restore_or_compute_then_maybe_submit());
sublog!(
debug,
"unsigned",
"resubmit offchain worker output: {:?}",
resubmit_output
);
// Maybe resubmit the cached solution, else re-compute.
let resubmit_output = if T::OffchainStorage::get() {
OffchainWorkerMiner::<T>::restore_or_compute_then_maybe_submit()
} else {
OffchainWorkerMiner::<T>::mine_check_maybe_save_submit(false)
};
sublog!(debug, "unsigned", "later offchain worker output: {:?}", resubmit_output);
};
}

Expand Down