Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
19 changes: 16 additions & 3 deletions .github/workflows/typescript-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,24 @@ jobs:
working-directory: ts-tests
run: pnpm install --frozen-lockfile

- name: Install lsof (dev foundation RPC port discovery)
if: matrix.test == 'dev'
- name: Install system dependencies
run: |
sudo DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a apt-get update
sudo DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a apt-get install -y --no-install-recommends lsof
sudo DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a apt-get install -y --no-install-recommends \
-o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" \
build-essential clang curl git make libssl-dev llvm libudev-dev protobuf-compiler pkg-config lsof

- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable

- name: Utilize Shared Rust Cache
uses: Swatinem/rust-cache@v2
with:
key: e2e-runtime-upgrade
cache-on-failure: true
workspaces: ". -> ts-tests/tmp/cargo-target"

- name: Run tests
run: |
Expand Down
67 changes: 64 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ pallet-subtensor = { path = "pallets/subtensor", default-features = false }
pallet-subtensor-swap = { path = "pallets/swap", default-features = false }
pallet-subtensor-swap-runtime-api = { path = "pallets/swap/runtime-api", default-features = false }
pallet-subtensor-swap-rpc = { path = "pallets/swap/rpc", default-features = false }
pallet-multi-collective = { path = "pallets/multi-collective", default-features = false }
pallet-signed-voting = { path = "pallets/signed-voting", default-features = false }
pallet-referenda = { path = "pallets/referenda", default-features = false }
procedural-fork = { path = "support/procedural-fork", default-features = false }
safe-bigmath = { package = "safe-bigmath", default-features = false, git = "https://github.com/sam0x17/safe-bigmath", rev = "013c49984910e1c9a23289e8c85e7a856e263a02" }
safe-math = { path = "primitives/safe-math", default-features = false }
Expand Down
3 changes: 3 additions & 0 deletions chain-extensions/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,9 @@ impl pallet_subtensor::Config for Test {
type CommitmentsInterface = CommitmentsI;
type EvmKeyAssociateRateLimit = EvmKeyAssociateRateLimit;
type AuthorshipProvider = MockAuthorshipProvider;
type OnRootRegistrationChange = ();
type RootRegisteredInspector = ();
type EmaValueProvider = ();
type SubtensorPalletId = SubtensorPalletId;
type BurnAccountId = BurnAccountId;
type InitialMaxEpochsPerBlock = MaxEpochsPerBlock;
Expand Down
1 change: 1 addition & 0 deletions common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
codec = { workspace = true, features = ["derive"] }
environmental.workspace = true
frame-support.workspace = true
impl-trait-for-tuples.workspace = true
num-traits = { workspace = true, features = ["libm"] }
scale-info.workspace = true
serde.workspace = true
Expand Down
43 changes: 42 additions & 1 deletion common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,19 @@ use runtime_common::prod_or_fast;
use scale_info::TypeInfo;
use serde::{Deserialize, Serialize};
use sp_runtime::{
MultiSignature, Vec,
MultiSignature, Perbill, Vec,
traits::{IdentifyAccount, Verify},
};
use subtensor_macros::freeze_struct;

pub use currency::*;
pub use evm_context::*;
pub use traits::*;
pub use transaction_error::*;

mod currency;
mod evm_context;
mod traits;
mod transaction_error;

/// Balance of an account.
Expand Down Expand Up @@ -47,6 +49,16 @@ pub type Nonce = u32;
pub const SMALL_TRANSFER_LIMIT: Balance = TaoBalance::new(500_000_000); // 0.5 TAO
pub const SMALL_ALPHA_TRANSFER_LIMIT: AlphaBalance = AlphaBalance::new(500_000_000); // 0.5 Alpha

/// Pad `s` into a fixed-width byte array, truncating if it exceeds `N`.
pub fn pad_name<const N: usize>(s: &[u8]) -> [u8; N] {
let mut out = [0u8; N];
let len = s.len().min(N);
if let (Some(dst), Some(src)) = (out.get_mut(..len), s.get(..len)) {
dst.copy_from_slice(src);
}
out
}

#[freeze_struct("c972489bff40ae48")]
#[repr(transparent)]
#[derive(
Expand Down Expand Up @@ -523,6 +535,35 @@ impl TypeInfo for NetUidStorageIndex {
}
}

#[derive(
Encode,
Decode,
DecodeWithMemTracking,
MaxEncodedLen,
PartialEq,
Eq,
Clone,
Copy,
TypeInfo,
Debug,
)]
#[freeze_struct("51505f4d98347bff")]
pub struct VoteTally {
pub approval: Perbill,
pub rejection: Perbill,
pub abstention: Perbill,
}

impl Default for VoteTally {
fn default() -> Self {
Self {
approval: Perbill::zero(),
rejection: Perbill::zero(),
abstention: Perbill::one(),
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
136 changes: 136 additions & 0 deletions common/src/traits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
use super::VoteTally;
use frame_support::pallet_prelude::*;
use sp_runtime::Vec;

pub trait SetLike<T> {
fn contains(&self, item: &T) -> bool;
fn len(&self) -> u32;
fn is_initialized(&self) -> bool;
fn is_empty(&self) -> bool {
self.len() == 0
}
/// Materialize the set as a `Vec`. Used by signed-voting to snapshot
/// the voter set at poll creation. Implementations must return each
/// distinct member exactly once; ordering is unspecified.
fn to_vec(&self) -> Vec<T>;
}

/// Poll provider seen from the voting pallet's side. Carries the
/// read-only queries plus the tally-update notification fired when a
/// vote moves the tally.
pub trait Polls<AccountId> {
type Index: Parameter + Copy + MaxEncodedLen;
type VotingScheme: PartialEq;
type VoterSet: SetLike<AccountId>;

fn is_ongoing(index: Self::Index) -> bool;
fn voting_scheme_of(index: Self::Index) -> Option<Self::VotingScheme>;
fn voter_set_of(index: Self::Index) -> Option<Self::VoterSet>;

fn on_tally_updated(index: Self::Index, tally: &VoteTally);
/// Worst-case upper bound on `on_tally_updated`'s weight.
fn on_tally_updated_weight() -> Weight;
}

/// Notification fired when a poll is created.
///
/// # Producer contract
///
/// Implementations are entitled to assume:
///
/// 1. `on_poll_created(p)` is called at most once per `(p, lifecycle)`,
/// where `lifecycle` is the span between this hook and the matching
/// `OnPollCompleted::on_poll_completed(p)`. A second call for the
/// same index without an intervening completion is a contract
/// violation: implementations should treat it as a no-op (so a buggy
/// producer cannot silently clobber tallies) but are not required to
/// detect every form of misuse.
/// 2. `Polls::is_ongoing(p)` and `Polls::voting_scheme_of(p)` return
/// consistent values for the duration of the lifecycle.
/// 3. `Polls::voter_set_of(p)` may be queried during this hook.
pub trait OnPollCreated<PollIndex> {
fn on_poll_created(poll_index: PollIndex);
/// Returns the worst-case upper bound on `on_poll_created`'s weight.
fn weight() -> Weight;
}

/// Notification fired when a poll reaches a terminal status.
///
/// # Producer contract
///
/// Implementations are entitled to assume:
///
/// 1. `on_poll_completed(p)` is called at most once per `(p, lifecycle)`.
/// 2. The producer may have already updated `p`'s status to a terminal
/// value before firing this hook, so `Polls::voting_scheme_of(p)` is
/// not required to return `Some` here. Implementations that need to
/// distinguish polls owned by a specific scheme should rely on
/// locally-stored state rather than re-querying the producer.
/// 3. `on_poll_completed` must not synchronously call back into the
/// producer in a way that would re-enter `OnPollCreated`.
pub trait OnPollCompleted<PollIndex> {
fn on_poll_completed(poll_index: PollIndex);
/// Returns the worst-case upper bound on `on_poll_completed`'s weight.
fn weight() -> Weight;
}

#[impl_trait_for_tuples::impl_for_tuples(10)]
impl<I: Copy> OnPollCreated<I> for Tuple {
fn on_poll_created(poll_index: I) {
for_tuples!( #( Tuple::on_poll_created(poll_index); )* );
}

fn weight() -> Weight {
#[allow(clippy::let_and_return)]
let mut weight = Weight::zero();
for_tuples!( #( weight.saturating_accrue(Tuple::weight()); )* );
weight
}
}

#[impl_trait_for_tuples::impl_for_tuples(10)]
impl<I: Copy> OnPollCompleted<I> for Tuple {
fn on_poll_completed(poll_index: I) {
for_tuples!( #( Tuple::on_poll_completed(poll_index); )* );
}

fn weight() -> Weight {
#[allow(clippy::let_and_return)]
let mut weight = Weight::zero();
for_tuples!( #( weight.saturating_accrue(Tuple::weight()); )* );
weight
}
}

/// Handler for when the members of a collective have changed.
pub trait OnMembersChanged<CollectiveId, AccountId> {
/// A collective's members have changed, `incoming` members have joined and
/// `outgoing` members have left.
fn on_members_changed(
collective_id: CollectiveId,
incoming: &[AccountId],
outgoing: &[AccountId],
);
/// Worst-case upper bound on `on_members_changed`'s weight. The
/// implementation is responsible for bounding its own iteration over
/// `incoming`/`outgoing` against the relevant `MaxMembers` constant.
fn weight() -> Weight;
}

#[impl_trait_for_tuples::impl_for_tuples(10)]
impl<CollectiveId: Clone, AccountId> OnMembersChanged<CollectiveId, AccountId> for Tuple {
fn on_members_changed(
collective_id: CollectiveId,
incoming: &[AccountId],
outgoing: &[AccountId],
) {
for_tuples!( #( Tuple::on_members_changed(collective_id.clone(), incoming, outgoing); )* );
}

fn weight() -> Weight {
#[allow(clippy::let_and_return)]
let mut weight = Weight::zero();
for_tuples!( #( weight.saturating_accrue(Tuple::weight()); )* );
weight
}
}
Loading