Skip to content
lib.rs 111 KiB
Newer Older

			if let Err(e) = Self::pre_dispatch_checks(*score, *era) {
				debug::native::debug!(
					target: "staking",
					"validate unsigned failed due to {:?}.",
					e,
				);
				let invalid: InvalidTransaction = e.into();
				return invalid.into();
			}

			debug::native::debug!(
				target: "staking",
				"Validated an unsigned transaction from the local node for era {}.",
				era,
			);

			Ok(ValidTransaction {
				// The higher the score[0], the better a solution is.
				priority: score[0].saturated_into(),
				// no requires.
				requires: vec![],
				// Defensive only. A single solution can exist in the pool per era. Each validator
				// will run OCW at most once per era, hence there should never exist more than one
				// transaction anyhow.
				provides: vec![("StakingOffchain", era).encode()],
				// Note: this can be more accurate in the future. We do something like
				// `era_end_block - current_block` but that is not needed now as we eagerly run
				// offchain workers now and the above should be same as `T::ElectionLookahead`
				// without the need to query more storage in the validation phase. If we randomize
				// offchain worker, then we might re-consider this.
				longevity: TryInto::<u64>::try_into(T::ElectionLookahead::get()).unwrap_or(DEFAULT_LONGEVITY),
				// We don't propagate this. This can never the validated at a remote node.
				propagate: false,
			})
		} else {
			InvalidTransaction::Call.into()
		}
	}

	fn pre_dispatch(_: &Self::Call) -> Result<(), TransactionValidityError> {
		// IMPORTANT NOTE: By default, a sane `pre-dispatch` should always do the same checks as
		// `validate_unsigned` and overriding this should be done with care. this module has only
		// one unsigned entry point, in which we call into `<Module<T>>::pre_dispatch_checks()`
		// which is all the important checks that we do in `validate_unsigned`. Hence, we can safely
		// override this to save some time.
		Ok(())
	}
}

/// Check that list is sorted and has no duplicates.
fn is_sorted_and_unique(list: &[u32]) -> bool {
	list.windows(2).all(|w| w[0] < w[1])
}