lib.rs 37.7 KiB
Newer Older
	/// Maximum number of memory pages allowed for a contract.
	pub max_memory_pages: u32,
	/// Maximum allowed size of a declared table.
	pub max_table_size: u32,

	/// Whether the `ext_println` function is allowed to be used contracts.
	/// MUST only be enabled for `dev` chains, NOT for production chains
	pub enable_println: bool,

	/// The maximum length of a subject used for PRNG generation.
	pub max_subject_len: u32,
impl Default for Schedule {
	fn default() -> Schedule {
			version: 0,
			put_code_per_byte_cost: 1,
			grow_mem_cost: 1,
			regular_op_cost: 1,
			return_data_per_byte_cost: 1,
			event_data_per_byte_cost: 1,
			event_per_topic_cost: 1,
			event_base_cost: 1,
			call_base_cost: 135,
			instantiate_base_cost: 175,
			sandbox_data_read_cost: 1,
			sandbox_data_write_cost: 1,
			max_event_topics: 4,
			max_stack_height: 64 * 1024,
			max_memory_pages: 16,
			enable_println: false,
			max_subject_len: 32,

/// `SignedExtension` that checks if a transaction would exhausts the block gas limit.
#[derive(Encode, Decode, Clone, Eq, PartialEq)]
pub struct CheckBlockGasLimit<T: Trait + Send + Sync>(PhantomData<T>);

impl<T: Trait + Send + Sync> Default for CheckBlockGasLimit<T> {
	fn default() -> Self {
		Self(PhantomData)
	}
}

impl<T: Trait + Send + Sync> sp_std::fmt::Debug for CheckBlockGasLimit<T> {
	#[cfg(feature = "std")]
	fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
		write!(f, "CheckBlockGasLimit")
	}

	#[cfg(not(feature = "std"))]
	fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
		Ok(())
	}
}

impl<T: Trait + Send + Sync> SignedExtension for CheckBlockGasLimit<T> {
	type AccountId = T::AccountId;
	type Call = <T as Trait>::Call;
	type AdditionalSigned = ();
	type DispatchInfo = DispatchInfo;
	fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) }

	fn validate(
		&self,
		_: &Self::AccountId,
		call: &Self::Call,
		_: usize,
	) -> TransactionValidity {
		let call = match call.is_sub_type() {
			Some(call) => call,
			None => return Ok(ValidTransaction::default()),
		};

		match call {
			Call::claim_surcharge(_, _) | Call::update_schedule(_) =>
				Ok(ValidTransaction::default()),
			Call::put_code(gas_limit, _)
				| Call::call(_, _, gas_limit, _)
				| Call::instantiate(_, gas_limit, _, _)
			=> {
				// Check if the specified amount of gas is available in the current block.
				// This cannot underflow since `gas_spent` is never greater than `T::BlockGasLimit`.
				let gas_available = T::BlockGasLimit::get() - <Module<T>>::gas_spent();
				if *gas_limit > gas_available {
					// gas limit reached, revert the transaction and retry again in the future
					InvalidTransaction::ExhaustsResources.into()
				} else {
					Ok(ValidTransaction::default())
				}
			},
			Call::__PhantomItem(_, _)  => unreachable!("Variant is never constructed"),
		}
	}
}