forked from ghostchain/ghost-node
		
	rate limit for the rpc endpoint based on network_id, storage guard lock for the current network_id and other minor improvements
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
This commit is contained in:
		
							parent
							
								
									0c3636fe79
								
							
						
					
					
						commit
						8464da831f
					
				@ -1,6 +1,6 @@
 | 
				
			|||||||
[package]
 | 
					[package]
 | 
				
			||||||
name = "ghost-slow-clap"
 | 
					name = "ghost-slow-clap"
 | 
				
			||||||
version = "0.3.30"
 | 
					version = "0.3.31"
 | 
				
			||||||
description = "Applause protocol for the EVM bridge"
 | 
					description = "Applause protocol for the EVM bridge"
 | 
				
			||||||
license.workspace = true
 | 
					license.workspace = true
 | 
				
			||||||
authors.workspace = true
 | 
					authors.workspace = true
 | 
				
			||||||
 | 
				
			|||||||
@ -27,6 +27,7 @@ use sp_runtime::{
 | 
				
			|||||||
    offchain::{
 | 
					    offchain::{
 | 
				
			||||||
        self as rt_offchain, HttpError,
 | 
					        self as rt_offchain, HttpError,
 | 
				
			||||||
        storage::{MutateStorageError, StorageRetrievalError, StorageValueRef},
 | 
					        storage::{MutateStorageError, StorageRetrievalError, StorageValueRef},
 | 
				
			||||||
 | 
					        storage_lock::{StorageLock, Time},
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    traits::{BlockNumberProvider, Convert, Saturating},
 | 
					    traits::{BlockNumberProvider, Convert, Saturating},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -204,10 +205,14 @@ enum OffchainErr<NetworkId> {
 | 
				
			|||||||
    RequestUncompleted,
 | 
					    RequestUncompleted,
 | 
				
			||||||
    HttpResponseNotOk(u16),
 | 
					    HttpResponseNotOk(u16),
 | 
				
			||||||
    ErrorInEvmResponse,
 | 
					    ErrorInEvmResponse,
 | 
				
			||||||
 | 
					    NoStoredNetworks,
 | 
				
			||||||
 | 
					    NotValidator,
 | 
				
			||||||
    StorageRetrievalError(NetworkId),
 | 
					    StorageRetrievalError(NetworkId),
 | 
				
			||||||
    ConcurrentModificationError(NetworkId),
 | 
					    ConcurrentModificationError(NetworkId),
 | 
				
			||||||
    UtxoNotImplemented(NetworkId),
 | 
					    UtxoNotImplemented(NetworkId),
 | 
				
			||||||
    UnknownNetworkType(NetworkId),
 | 
					    UnknownNetworkType(NetworkId),
 | 
				
			||||||
 | 
					    OffchainTimeoutPeriod(NetworkId),
 | 
				
			||||||
 | 
					    TooManyRequests(NetworkId),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<NetworkId: core::fmt::Debug> core::fmt::Debug for OffchainErr<NetworkId> {
 | 
					impl<NetworkId: core::fmt::Debug> core::fmt::Debug for OffchainErr<NetworkId> {
 | 
				
			||||||
@ -220,15 +225,20 @@ impl<NetworkId: core::fmt::Debug> core::fmt::Debug for OffchainErr<NetworkId> {
 | 
				
			|||||||
            OffchainErr::HttpRequestError(http_error) => match http_error {
 | 
					            OffchainErr::HttpRequestError(http_error) => match http_error {
 | 
				
			||||||
                HttpError::DeadlineReached => write!(fmt, "Requested action couldn't been completed within a deadline."),
 | 
					                HttpError::DeadlineReached => write!(fmt, "Requested action couldn't been completed within a deadline."),
 | 
				
			||||||
                HttpError::IoError => write!(fmt, "There was an IO error while processing the request."),
 | 
					                HttpError::IoError => write!(fmt, "There was an IO error while processing the request."),
 | 
				
			||||||
                HttpError::Invalid => write!(fmt, "The ID of the request is invalid in this context"),
 | 
					                HttpError::Invalid => write!(fmt, "The ID of the request is invalid in this context."),
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            OffchainErr::ConcurrentModificationError(ref network_id) => write!(fmt, "The underlying DB failed to update due to a concurrent modification for network #{:?}", network_id),
 | 
					            OffchainErr::ConcurrentModificationError(ref network_id) => write!(fmt, "The underlying DB failed to update due to a concurrent modification for network #{:?}.", network_id),
 | 
				
			||||||
            OffchainErr::StorageRetrievalError(ref network_id) => write!(fmt, "Storage value found for network #{:?} but it's undecodable", network_id),
 | 
					            OffchainErr::StorageRetrievalError(ref network_id) => write!(fmt, "Storage value found for network #{:?} but it's undecodable.", network_id),
 | 
				
			||||||
            OffchainErr::RequestUncompleted => write!(fmt, "Failed to complete request."),
 | 
					            OffchainErr::RequestUncompleted => write!(fmt, "Failed to complete request."),
 | 
				
			||||||
            OffchainErr::HttpResponseNotOk(code) => write!(fmt, "Http response returned code {:?}", code),
 | 
					            OffchainErr::HttpResponseNotOk(code) => write!(fmt, "Http response returned code {:?}.", code),
 | 
				
			||||||
            OffchainErr::ErrorInEvmResponse => write!(fmt, "Error in evm reponse."),
 | 
					            OffchainErr::ErrorInEvmResponse => write!(fmt, "Error in evm reponse."),
 | 
				
			||||||
 | 
					            OffchainErr::NoStoredNetworks => write!(fmt, "No networks stored for the offchain slow claps."),
 | 
				
			||||||
 | 
					            OffchainErr::NotValidator => write!(fmt, "Not a validator for slow clap, `--validator` flag needed."),
 | 
				
			||||||
            OffchainErr::UtxoNotImplemented(ref network_id) => write!(fmt, "Network #{:?} is marked as UTXO, which is not implemented yet.", network_id),
 | 
					            OffchainErr::UtxoNotImplemented(ref network_id) => write!(fmt, "Network #{:?} is marked as UTXO, which is not implemented yet.", network_id),
 | 
				
			||||||
            OffchainErr::UnknownNetworkType(ref network_id) => write!(fmt, "Unknown type for network #{:?}.", network_id),
 | 
					            OffchainErr::UnknownNetworkType(ref network_id) => write!(fmt, "Unknown type for network #{:?}.", network_id),
 | 
				
			||||||
 | 
					            OffchainErr::OffchainTimeoutPeriod(ref network_id) => write!(fmt, "Offchain request should be in-flight for network #{:?}.", network_id),
 | 
				
			||||||
 | 
					            OffchainErr::TooManyRequests(ref network_id) => write!(fmt, "Too many requests over RPC endpoint for network #{:?}.", network_id),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -438,33 +448,23 @@ pub mod pallet {
 | 
				
			|||||||
    #[pallet::hooks]
 | 
					    #[pallet::hooks]
 | 
				
			||||||
    impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
 | 
					    impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
 | 
				
			||||||
        fn offchain_worker(now: BlockNumberFor<T>) {
 | 
					        fn offchain_worker(now: BlockNumberFor<T>) {
 | 
				
			||||||
            // Only send messages of we are a potential validator.
 | 
					            match Self::start_slow_clapping(now) {
 | 
				
			||||||
            if sp_io::offchain::is_validator() {
 | 
					                Ok(iter) => for result in iter.into_iter() {
 | 
				
			||||||
                let networks_len = T::NetworkDataHandler::iter().count();
 | 
					 | 
				
			||||||
                if networks_len == 0 { 
 | 
					 | 
				
			||||||
                    log::info!(
 | 
					 | 
				
			||||||
                        target: LOG_TARGET,
 | 
					 | 
				
			||||||
                        "👏 Skipping slow clap at {:?}: no evm networks",
 | 
					 | 
				
			||||||
                        now,
 | 
					 | 
				
			||||||
                    );
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    for result in Self::start_slow_clapping(now, networks_len).into_iter().flatten() {
 | 
					 | 
				
			||||||
                    if let Err(e) = result {
 | 
					                    if let Err(e) = result {
 | 
				
			||||||
                        log::info!(
 | 
					                        log::info!(
 | 
				
			||||||
                            target: LOG_TARGET,
 | 
					                            target: LOG_TARGET,
 | 
				
			||||||
                            "👏 Skipping slow clap at {:?}: {:?}",
 | 
					                            "👏 Skipping slow clap at {:?}: {:?}",
 | 
				
			||||||
                            now,
 | 
					                            now,
 | 
				
			||||||
                            e,
 | 
					                            e,
 | 
				
			||||||
                            );
 | 
					                        )
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    }
 | 
					                },
 | 
				
			||||||
                }
 | 
					                Err(e) => log::info!(
 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                log::info!(
 | 
					 | 
				
			||||||
                    target: LOG_TARGET,
 | 
					                    target: LOG_TARGET,
 | 
				
			||||||
                    "🤥 Not a validator, skipping slow clap at {:?}.",
 | 
					                    "👏 Could not start slow clap at {:?}: {:?}",
 | 
				
			||||||
                    now,
 | 
					                    now,
 | 
				
			||||||
                );
 | 
					                    e,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -503,6 +503,21 @@ pub mod pallet {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<T: Config> Pallet<T> {
 | 
					impl<T: Config> Pallet<T> {
 | 
				
			||||||
 | 
					    fn create_storage_key(first: &[u8], second: &[u8]) -> Vec<u8> {
 | 
				
			||||||
 | 
					        let mut key = DB_PREFIX.to_vec();
 | 
				
			||||||
 | 
					        key.extend(first);
 | 
				
			||||||
 | 
					        key.extend(second);
 | 
				
			||||||
 | 
					        key
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn read_persistent_offchain_storage<R: codec::Decode>(storage_key: &[u8], default_value: R) -> R {
 | 
				
			||||||
 | 
					        StorageValueRef::persistent(&storage_key)
 | 
				
			||||||
 | 
					            .get::<R>()
 | 
				
			||||||
 | 
					            .ok()
 | 
				
			||||||
 | 
					            .flatten()
 | 
				
			||||||
 | 
					            .unwrap_or(default_value)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn generate_unique_hash(
 | 
					    fn generate_unique_hash(
 | 
				
			||||||
        receiver: &T::AccountId,
 | 
					        receiver: &T::AccountId,
 | 
				
			||||||
        amount: &BalanceOf<T>,
 | 
					        amount: &BalanceOf<T>,
 | 
				
			||||||
@ -515,6 +530,30 @@ impl<T: Config> Pallet<T> {
 | 
				
			|||||||
        H256::from_slice(&sp_io::hashing::keccak_256(&clap_args_str)[..])
 | 
					        H256::from_slice(&sp_io::hashing::keccak_256(&clap_args_str)[..])
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn u64_to_hexadecimal_bytes(value: u64) -> Vec<u8> {
 | 
				
			||||||
 | 
					        let mut hex_str = Vec::new();
 | 
				
			||||||
 | 
					        hex_str.push(b'0');
 | 
				
			||||||
 | 
					        hex_str.push(b'x');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if value == 0 {
 | 
				
			||||||
 | 
					            hex_str.push(b'0');
 | 
				
			||||||
 | 
					            return hex_str;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for i in (0..16).rev() {
 | 
				
			||||||
 | 
					            let nibble = (value >> (i * 4)) & 0xF;
 | 
				
			||||||
 | 
					            if nibble != 0 || hex_str.len() > 2 {
 | 
				
			||||||
 | 
					                hex_str.push(match nibble {
 | 
				
			||||||
 | 
					                    0..=9 => b'0' + nibble as u8,
 | 
				
			||||||
 | 
					                    10..=15 => b'a' + (nibble - 10) as u8,
 | 
				
			||||||
 | 
					                    _ => unreachable!(),
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        hex_str
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn try_slow_clap(clap: &Clap<T::AccountId, NetworkIdOf<T>, BalanceOf<T>>) -> DispatchResult {
 | 
					    fn try_slow_clap(clap: &Clap<T::AccountId, NetworkIdOf<T>, BalanceOf<T>>) -> DispatchResult {
 | 
				
			||||||
        let authorities = Authorities::<T>::get(&clap.session_index);
 | 
					        let authorities = Authorities::<T>::get(&clap.session_index);
 | 
				
			||||||
        ensure!(authorities.get(clap.authority_index as usize).is_some(), Error::<T>::NotAnAuthority);
 | 
					        ensure!(authorities.get(clap.authority_index as usize).is_some(), Error::<T>::NotAnAuthority);
 | 
				
			||||||
@ -565,13 +604,12 @@ impl<T: Config> Pallet<T> {
 | 
				
			|||||||
        ) > Perbill::from_percent(T::ApplauseThreshold::get());
 | 
					        ) > Perbill::from_percent(T::ApplauseThreshold::get());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if enough_authorities {
 | 
					        if enough_authorities {
 | 
				
			||||||
            if let Err(error_msg) = Self::try_applause(&clap, &received_claps_key) {
 | 
					            let _ = Self::try_applause(&clap, &received_claps_key)
 | 
				
			||||||
                log::info!(
 | 
					                .inspect_err(|error_msg| log::info!(
 | 
				
			||||||
                        target: LOG_TARGET,
 | 
					                        target: LOG_TARGET,
 | 
				
			||||||
                        "👏 Could not applause because of: {:?}",
 | 
					                        "👏 Could not applause because of: {:?}",
 | 
				
			||||||
                        error_msg,
 | 
					                        error_msg,
 | 
				
			||||||
                );
 | 
					                ));
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
@ -651,15 +689,57 @@ impl<T: Config> Pallet<T> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn start_slow_clapping(
 | 
					    fn start_slow_clapping(
 | 
				
			||||||
        block_number: BlockNumberFor<T>,
 | 
					        block_number: BlockNumberFor<T>
 | 
				
			||||||
        networks_len: usize,
 | 
					 | 
				
			||||||
    ) -> OffchainResult<T, impl Iterator<Item = OffchainResult<T, ()>>> {
 | 
					    ) -> OffchainResult<T, impl Iterator<Item = OffchainResult<T, ()>>> {
 | 
				
			||||||
        let session_index = T::ValidatorSet::session_index();
 | 
					        sp_io::offchain::is_validator()
 | 
				
			||||||
        let network_in_use = T::NetworkDataHandler::iter()
 | 
					            .then(|| ())
 | 
				
			||||||
            .nth(block_number.into().as_usize() % networks_len)
 | 
					            .ok_or(OffchainErr::NotValidator)?;
 | 
				
			||||||
            .expect("network should exist; qed");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(Self::local_authorities().map(move |(authority_index, authority_key)| {
 | 
					        let session_index = T::ValidatorSet::session_index();
 | 
				
			||||||
 | 
					        let networks_len = T::NetworkDataHandler::iter().count();
 | 
				
			||||||
 | 
					        let network_in_use = T::NetworkDataHandler::iter()
 | 
				
			||||||
 | 
					            .nth(block_number.into()
 | 
				
			||||||
 | 
					                .as_usize()
 | 
				
			||||||
 | 
					                .checked_rem(networks_len)
 | 
				
			||||||
 | 
					                .unwrap_or_default())
 | 
				
			||||||
 | 
					            .ok_or(OffchainErr::NoStoredNetworks)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let network_id_encoded = network_in_use.0.encode();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let last_timestamp_key = Self::create_storage_key(b"last-timestamp-", &network_id_encoded);
 | 
				
			||||||
 | 
					        let rate_limit_delay_key = Self::create_storage_key(b"rate-limit-", &network_id_encoded);
 | 
				
			||||||
 | 
					        let rate_limit_delay = Self::read_persistent_offchain_storage(
 | 
				
			||||||
 | 
					            &rate_limit_delay_key,
 | 
				
			||||||
 | 
					            network_in_use.1.rate_limit_delay,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let network_lock_key = Self::create_storage_key(b"network-lock-", &network_id_encoded);
 | 
				
			||||||
 | 
					        let block_until = rt_offchain::Duration::from_millis(networks_len as u64 * FETCH_TIMEOUT_PERIOD);
 | 
				
			||||||
 | 
					        let mut network_lock = StorageLock::<Time>::with_deadline(&network_lock_key, block_until);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        network_lock.try_lock().map_err(|_| {
 | 
				
			||||||
 | 
					            OffchainErr::OffchainTimeoutPeriod(network_in_use.0)
 | 
				
			||||||
 | 
					        })?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        StorageValueRef::persistent(&last_timestamp_key)
 | 
				
			||||||
 | 
					            .mutate(|result_timestamp: Result<Option<u64>, StorageRetrievalError>| {
 | 
				
			||||||
 | 
					                let current_timestmap = sp_io::offchain::timestamp().unix_millis();
 | 
				
			||||||
 | 
					                match result_timestamp {
 | 
				
			||||||
 | 
					                    Ok(option_timestamp) => match option_timestamp {
 | 
				
			||||||
 | 
					                        Some(stored_timestamp) if stored_timestamp > current_timestmap =>
 | 
				
			||||||
 | 
					                            Err(OffchainErr::TooManyRequests(network_in_use.0).into()),
 | 
				
			||||||
 | 
					                        _ => Ok(current_timestmap.saturating_add(rate_limit_delay)),
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    Err(_) => Err(OffchainErr::StorageRetrievalError(network_in_use.0).into()),
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .map_err(|error| match error {
 | 
				
			||||||
 | 
					                MutateStorageError::ValueFunctionFailed(offchain_error) => offchain_error,
 | 
				
			||||||
 | 
					                MutateStorageError::ConcurrentModification(_) =>
 | 
				
			||||||
 | 
					                    OffchainErr::ConcurrentModificationError(network_in_use.0).into(),
 | 
				
			||||||
 | 
					            })?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(Self::local_authorities(&session_index).map(move |(authority_index, authority_key)| {
 | 
				
			||||||
            Self::do_evm_claps_or_save_block(
 | 
					            Self::do_evm_claps_or_save_block(
 | 
				
			||||||
                authority_index, 
 | 
					                authority_index, 
 | 
				
			||||||
                authority_key, 
 | 
					                authority_key, 
 | 
				
			||||||
@ -670,13 +750,6 @@ impl<T: Config> Pallet<T> {
 | 
				
			|||||||
        }))
 | 
					        }))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn create_storage_key(first: &[u8], second: &[u8]) -> Vec<u8> {
 | 
					 | 
				
			||||||
        let mut key = DB_PREFIX.to_vec();
 | 
					 | 
				
			||||||
        key.extend(first);
 | 
					 | 
				
			||||||
        key.extend(second);
 | 
					 | 
				
			||||||
        key
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn do_evm_claps_or_save_block(
 | 
					    fn do_evm_claps_or_save_block(
 | 
				
			||||||
        authority_index: AuthIndex,
 | 
					        authority_index: AuthIndex,
 | 
				
			||||||
        authority_key: T::AuthorityId,
 | 
					        authority_key: T::AuthorityId,
 | 
				
			||||||
@ -690,19 +763,17 @@ impl<T: Config> Pallet<T> {
 | 
				
			|||||||
        let block_distance_key = Self::create_storage_key(b"block-distance-", &network_id_encoded);
 | 
					        let block_distance_key = Self::create_storage_key(b"block-distance-", &network_id_encoded);
 | 
				
			||||||
        let endpoint_key = Self::create_storage_key(b"endpoint-", &network_id_encoded);
 | 
					        let endpoint_key = Self::create_storage_key(b"endpoint-", &network_id_encoded);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let rpc_endpoint = StorageValueRef::persistent(&endpoint_key)
 | 
					        let rpc_endpoint = Self::read_persistent_offchain_storage(
 | 
				
			||||||
            .get()
 | 
					            &endpoint_key,
 | 
				
			||||||
            .ok()
 | 
					            network_data.default_endpoint.clone(),
 | 
				
			||||||
            .flatten()
 | 
					        );
 | 
				
			||||||
            .unwrap_or(network_data.default_endpoint.clone());
 | 
					        let max_block_distance = Self::read_persistent_offchain_storage(
 | 
				
			||||||
 | 
					            &block_distance_key,
 | 
				
			||||||
 | 
					            network_data.block_distance,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let max_block_distance = StorageValueRef::persistent(&block_distance_key)
 | 
					        StorageValueRef::persistent(&block_number_key)
 | 
				
			||||||
            .get()
 | 
					            .mutate(|result_block_range: Result<Option<(u64, u64)>, StorageRetrievalError>| {
 | 
				
			||||||
            .ok()
 | 
					 | 
				
			||||||
            .flatten()
 | 
					 | 
				
			||||||
            .unwrap_or(network_data.block_distance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let mutation_result = StorageValueRef::persistent(&block_number_key).mutate(|result_block_range: Result<Option<(u64, u64)>, StorageRetrievalError>| {
 | 
					 | 
				
			||||||
                match result_block_range {
 | 
					                match result_block_range {
 | 
				
			||||||
                    Ok(maybe_block_range) => {
 | 
					                    Ok(maybe_block_range) => {
 | 
				
			||||||
                        let request_body = match maybe_block_range {
 | 
					                        let request_body = match maybe_block_range {
 | 
				
			||||||
@ -747,13 +818,13 @@ impl<T: Config> Pallet<T> {
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    Err(_) => Err(OffchainErr::StorageRetrievalError(network_id).into())
 | 
					                    Err(_) => Err(OffchainErr::StorageRetrievalError(network_id).into())
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
        });
 | 
					            })
 | 
				
			||||||
 | 
					            .map_err(|error| match error {
 | 
				
			||||||
        match mutation_result {
 | 
					                MutateStorageError::ValueFunctionFailed(offchain_error) => offchain_error,
 | 
				
			||||||
            Ok(_) => Ok(()),
 | 
					                MutateStorageError::ConcurrentModification(_) =>
 | 
				
			||||||
            Err(MutateStorageError::ValueFunctionFailed(offchain_error)) => Err(offchain_error),
 | 
					                    OffchainErr::ConcurrentModificationError(network_id).into(),
 | 
				
			||||||
            Err(MutateStorageError::ConcurrentModification(_)) => Err(OffchainErr::ConcurrentModificationError(network_id).into()),
 | 
					            })
 | 
				
			||||||
        }
 | 
					            .map(|_| ())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn apply_evm_response(
 | 
					    fn apply_evm_response(
 | 
				
			||||||
@ -818,9 +889,8 @@ impl<T: Config> Pallet<T> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn local_authorities() -> impl Iterator<Item = (u32, T::AuthorityId)> {
 | 
					    fn local_authorities(session_index: &SessionIndex) -> impl Iterator<Item = (u32, T::AuthorityId)> {
 | 
				
			||||||
        let session_index = T::ValidatorSet::session_index();
 | 
					        let authorities = Authorities::<T>::get(session_index);
 | 
				
			||||||
        let authorities = Authorities::<T>::get(&session_index);
 | 
					 | 
				
			||||||
        let mut local_authorities = T::AuthorityId::all();
 | 
					        let mut local_authorities = T::AuthorityId::all();
 | 
				
			||||||
        local_authorities.sort();
 | 
					        local_authorities.sort();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -860,30 +930,6 @@ impl<T: Config> Pallet<T> {
 | 
				
			|||||||
        Ok(response.body().collect::<Vec<u8>>())
 | 
					        Ok(response.body().collect::<Vec<u8>>())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn u64_to_hexadecimal_bytes(value: u64) -> Vec<u8> {
 | 
					 | 
				
			||||||
        let mut hex_str = Vec::new();
 | 
					 | 
				
			||||||
        hex_str.push(b'0');
 | 
					 | 
				
			||||||
        hex_str.push(b'x');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if value == 0 {
 | 
					 | 
				
			||||||
            hex_str.push(b'0');
 | 
					 | 
				
			||||||
            return hex_str;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for i in (0..16).rev() {
 | 
					 | 
				
			||||||
            let nibble = (value >> (i * 4)) & 0xF;
 | 
					 | 
				
			||||||
            if nibble != 0 || hex_str.len() > 2 {
 | 
					 | 
				
			||||||
                hex_str.push(match nibble {
 | 
					 | 
				
			||||||
                    0..=9 => b'0' + nibble as u8,
 | 
					 | 
				
			||||||
                    10..=15 => b'a' + (nibble - 10) as u8,
 | 
					 | 
				
			||||||
                    _ => unreachable!(),
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        hex_str
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn prepare_request_body_for_latest_block(network_data: &NetworkData) -> Vec<u8> {
 | 
					    fn prepare_request_body_for_latest_block(network_data: &NetworkData) -> Vec<u8> {
 | 
				
			||||||
        match network_data.network_type {
 | 
					        match network_data.network_type {
 | 
				
			||||||
            NetworkType::Evm => b"{\"id\":0,\"jsonrpc\":\"2.0\",\"method\":\"eth_blockNumber\"}".to_vec(),
 | 
					            NetworkType::Evm => b"{\"id\":0,\"jsonrpc\":\"2.0\",\"method\":\"eth_blockNumber\"}".to_vec(),
 | 
				
			||||||
@ -924,6 +970,28 @@ impl<T: Config> Pallet<T> {
 | 
				
			|||||||
        Ok(response_result.result.ok_or(OffchainErr::ErrorInEvmResponse)?)
 | 
					        Ok(response_result.result.ok_or(OffchainErr::ErrorInEvmResponse)?)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn calculate_median_claps(session_index: &SessionIndex) -> u32 {
 | 
				
			||||||
 | 
					        let mut claps_in_session = ClapsInSession::<T>::get(session_index)
 | 
				
			||||||
 | 
					            .values()
 | 
				
			||||||
 | 
					            .filter_map(|value| (!value.disabled).then(|| value.claps))
 | 
				
			||||||
 | 
					            .collect::<Vec<_>>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if claps_in_session.is_empty() {
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        claps_in_session.sort();
 | 
				
			||||||
 | 
					        let number_of_claps = claps_in_session.len();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if number_of_claps % 2 == 0 {
 | 
				
			||||||
 | 
					            let mid_left = claps_in_session[number_of_claps / 2 - 1];
 | 
				
			||||||
 | 
					            let mid_right = claps_in_session[number_of_claps / 2];
 | 
				
			||||||
 | 
					            (mid_left + mid_right) / 2
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            claps_in_session[number_of_claps / 2]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn is_good_actor(
 | 
					    fn is_good_actor(
 | 
				
			||||||
        authority_index: usize, 
 | 
					        authority_index: usize, 
 | 
				
			||||||
        session_index: SessionIndex,
 | 
					        session_index: SessionIndex,
 | 
				
			||||||
@ -968,28 +1036,6 @@ impl<T: Config> Pallet<T> {
 | 
				
			|||||||
        debug_assert!(cursor.maybe_cursor.is_none());
 | 
					        debug_assert!(cursor.maybe_cursor.is_none());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn calculate_median_claps(session_index: &SessionIndex) -> u32 {
 | 
					 | 
				
			||||||
        let mut claps_in_session = ClapsInSession::<T>::get(session_index)
 | 
					 | 
				
			||||||
            .values()
 | 
					 | 
				
			||||||
            .filter_map(|value| (!value.disabled).then(|| value.claps))
 | 
					 | 
				
			||||||
            .collect::<Vec<_>>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if claps_in_session.is_empty() {
 | 
					 | 
				
			||||||
            return 0;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        claps_in_session.sort();
 | 
					 | 
				
			||||||
        let number_of_claps = claps_in_session.len();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if number_of_claps % 2 == 0 {
 | 
					 | 
				
			||||||
            let mid_left = claps_in_session[number_of_claps / 2 - 1];
 | 
					 | 
				
			||||||
            let mid_right = claps_in_session[number_of_claps / 2];
 | 
					 | 
				
			||||||
            (mid_left + mid_right) / 2
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            claps_in_session[number_of_claps / 2]
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[cfg(test)]
 | 
					    #[cfg(test)]
 | 
				
			||||||
    fn set_test_authorities(session_index: SessionIndex, authorities: Vec<T::AuthorityId>) {
 | 
					    fn set_test_authorities(session_index: SessionIndex, authorities: Vec<T::AuthorityId>) {
 | 
				
			||||||
        let bounded_authorities = WeakBoundedVec::<_, T::MaxAuthorities>::try_from(authorities)
 | 
					        let bounded_authorities = WeakBoundedVec::<_, T::MaxAuthorities>::try_from(authorities)
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user