Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • nodes/rust/duniter-v2s
  • llaq/lc-core-substrate
  • pini-gh/duniter-v2s
  • vincentux/duniter-v2s
  • mildred/duniter-v2s
  • d0p1/duniter-v2s
  • bgallois/duniter-v2s
  • Nicolas80/duniter-v2s
8 results
Show changes
Showing
with 590 additions and 37 deletions
......@@ -40,6 +40,7 @@ pub mod pallet_identity;
pub mod pallet_preimage;
pub mod pallet_utility;
pub mod pallet_duniter_account;
pub mod pallet_quota;
pub mod pallet_oneshot_account;
pub mod pallet_certification_cert;
pub mod pallet_certification_smith_cert;
......
......@@ -48,6 +48,17 @@ use core::marker::PhantomData;
/// Weight functions for `pallet_duniter_account`.
pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> pallet_duniter_account::WeightInfo for WeightInfo<T> {
/// Storage: System Account (r:1 w:0)
/// Proof: System Account (max_values: None, max_size: Some(126), added: 2601, mode: MaxEncodedLen)
fn unlink_identity() -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `3591`
// Minimum execution time: 95_130_000 picoseconds.
Weight::from_parts(110_501_000, 0)
.saturating_add(Weight::from_parts(0, 3591))
.saturating_add(T::DbWeight::get().reads(1))
}
/// Storage: Account PendingNewAccounts (r:1 w:1)
/// Proof Skipped: Account PendingNewAccounts (max_values: None, max_size: None, mode: Measured)
/// Storage: ProvideRandomness RequestIdProvider (r:1 w:1)
......
......@@ -236,4 +236,20 @@ impl<T: frame_system::Config> pallet_identity::WeightInfo for WeightInfo<T> {
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: Identity IdentityIndexOf (r:1 w:0)
/// Proof Skipped: Identity IdentityIndexOf (max_values: None, max_size: None, mode: Measured)
/// Storage: System BlockHash (r:1 w:0)
/// Proof: System BlockHash (max_values: None, max_size: Some(44), added: 2519, mode: MaxEncodedLen)
/// Storage: System Account (r:1 w:1)
/// Proof: System Account (max_values: None, max_size: Some(126), added: 2601, mode: MaxEncodedLen)
fn link_account() -> Weight {
// Proof Size summary in bytes:
// Measured: `359`
// Estimated: `3824`
// Minimum execution time: 543_046_000 picoseconds.
Weight::from_parts(544_513_000, 0)
.saturating_add(Weight::from_parts(0, 3824))
.saturating_add(T::DbWeight::get().reads(3))
.saturating_add(T::DbWeight::get().writes(1))
}
}
// Copyright 2021-2022 Axiom-Team
//
// This file is part of Duniter-v2S.
//
// Duniter-v2S is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, version 3 of the License.
//
// Duniter-v2S is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>.
//! Autogenerated weights for `pallet_quota`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2023-10-26, STEPS: `5`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `Albatros`, CPU: `Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz`
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("gdev-benchmark"), DB CACHE: 1024
// Executed Command:
// ./target/debug/duniter
// benchmark
// pallet
// --chain=gdev-benchmark
// --steps=5
// --repeat=2
// --pallet=pallet_quota
// --extrinsic=*
// --execution=wasm
// --wasm-execution=compiled
// --heap-pages=4096
// --output=./
// --header=./file_header.txt
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(missing_docs)]
use frame_support::{traits::Get, weights::Weight};
use core::marker::PhantomData;
/// Weight functions for `pallet_quota`.
pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> pallet_quota::WeightInfo for WeightInfo<T> {
/// Storage: Quota RefundQueue (r:1 w:1)
/// Proof: Quota RefundQueue (max_values: Some(1), max_size: Some(11266), added: 11761, mode: MaxEncodedLen)
fn queue_refund() -> Weight {
// Proof Size summary in bytes:
// Measured: `42`
// Estimated: `12751`
// Minimum execution time: 73_265_000 picoseconds.
Weight::from_parts(77_698_000, 0)
.saturating_add(Weight::from_parts(0, 12751))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: Quota IdtyQuota (r:1 w:1)
/// Proof: Quota IdtyQuota (max_values: None, max_size: Some(24), added: 2499, mode: MaxEncodedLen)
fn spend_quota() -> Weight {
// Proof Size summary in bytes:
// Measured: `137`
// Estimated: `3489`
// Minimum execution time: 147_746_000 picoseconds.
Weight::from_parts(165_850_000, 0)
.saturating_add(Weight::from_parts(0, 3489))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: Quota IdtyQuota (r:1 w:1)
/// Proof: Quota IdtyQuota (max_values: None, max_size: Some(24), added: 2499, mode: MaxEncodedLen)
fn try_refund() -> Weight {
// Proof Size summary in bytes:
// Measured: `137`
// Estimated: `3489`
// Minimum execution time: 367_239_000 picoseconds.
Weight::from_parts(392_186_000, 0)
.saturating_add(Weight::from_parts(0, 3489))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
fn do_refund() -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 356_707_000 picoseconds.
Weight::from_parts(471_930_000, 0)
.saturating_add(Weight::from_parts(0, 0))
}
}
......@@ -46,6 +46,7 @@ std = [
'pallet-distance/std',
'pallet-duniter-test-parameters/std',
'pallet-duniter-account/std',
'pallet-quota/std',
'pallet-duniter-wot/std',
'pallet-grandpa/std',
'pallet-identity/std',
......@@ -115,6 +116,7 @@ pallet-certification = { path = '../../pallets/certification', default-features
pallet-distance = { path = "../../pallets/distance", default-features = false }
pallet-duniter-test-parameters = { path = '../../pallets/duniter-test-parameters', default-features = false }
pallet-duniter-account = { path = '../../pallets/duniter-account', default-features = false }
pallet-quota = { path = '../../pallets/quota', default-features = false }
pallet-duniter-wot = { path = '../../pallets/duniter-wot', default-features = false }
pallet-identity = { path = '../../pallets/identity', default-features = false }
pallet-membership = { path = '../../pallets/membership', default-features = false }
......
......@@ -48,7 +48,9 @@ use pallet_grandpa::fg_primitives;
use pallet_grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList};
use sp_api::impl_runtime_apis;
use sp_core::OpaqueMetadata;
use sp_runtime::traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, NumberFor, OpaqueKeys};
use sp_runtime::traits::{
AccountIdLookup, BlakeTwo256, Block as BlockT, NumberFor, One, OpaqueKeys,
};
use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
transaction_validity::{TransactionSource, TransactionValidity},
......@@ -253,6 +255,7 @@ construct_runtime!(
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 6,
TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event<T>} = 32,
OneshotAccount: pallet_oneshot_account::{Pallet, Call, Storage, Event<T>} = 7,
Quota: pallet_quota::{Pallet, Storage, Config<T>, Event<T>} = 66,
// Consensus support.
AuthorityMembers: pallet_authority_members::{Pallet, Call, Storage, Config<T>, Event<T>} = 10,
......
......@@ -29,6 +29,7 @@ runtime-benchmarks = [
'pallet-collective/runtime-benchmarks',
'pallet-duniter-test-parameters/runtime-benchmarks',
'pallet-duniter-account/runtime-benchmarks',
'pallet-quota/runtime-benchmarks',
'pallet-duniter-wot/runtime-benchmarks',
'pallet-grandpa/runtime-benchmarks',
'pallet-identity/runtime-benchmarks',
......@@ -67,6 +68,7 @@ std = [
'pallet-distance/std',
'pallet-duniter-test-parameters/std',
'pallet-duniter-account/std',
'pallet-quota/std',
'pallet-duniter-wot/std',
'pallet-grandpa/std',
'pallet-identity/std',
......@@ -141,6 +143,7 @@ pallet-certification = { path = '../../pallets/certification', default-features
pallet-distance = { path = "../../pallets/distance", default-features = false }
pallet-duniter-test-parameters = { path = '../../pallets/duniter-test-parameters', default-features = false }
pallet-duniter-account = { path = '../../pallets/duniter-account', default-features = false }
pallet-quota = { path = '../../pallets/quota', default-features = false }
pallet-duniter-wot = { path = '../../pallets/duniter-wot', default-features = false }
pallet-identity = { path = '../../pallets/identity', default-features = false }
pallet-membership = { path = '../../pallets/membership', default-features = false }
......
......@@ -55,7 +55,9 @@ use pallet_grandpa::fg_primitives;
use pallet_grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList};
use sp_api::impl_runtime_apis;
use sp_core::OpaqueMetadata;
use sp_runtime::traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, NumberFor, OpaqueKeys};
use sp_runtime::traits::{
AccountIdLookup, BlakeTwo256, Block as BlockT, NumberFor, One, OpaqueKeys,
};
use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
transaction_validity::{TransactionSource, TransactionValidity},
......@@ -148,6 +150,7 @@ mod benches {
[pallet_provide_randomness, ProvideRandomness]
[pallet_upgrade_origin, UpgradeOrigin]
[pallet_duniter_account, Account]
[pallet_quota, Quota]
[pallet_identity, Identity]
[pallet_membership, Membership]
[pallet_membership, SmithMembership]
......@@ -296,7 +299,7 @@ construct_runtime!(
{
// Basic stuff
System: frame_system::{Pallet, Call, Config, Storage, Event<T>} = 0,
Account: pallet_duniter_account::{Pallet, Storage, Config<T>, Event<T>} = 1,
Account: pallet_duniter_account::{Pallet, Call, Storage, Config<T>, Event<T>} = 1,
Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event<T>} = 2,
// Block creation
......@@ -310,6 +313,7 @@ construct_runtime!(
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 6,
TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event<T>} = 32,
OneshotAccount: pallet_oneshot_account::{Pallet, Call, Storage, Event<T>} = 7,
Quota: pallet_quota::{Pallet, Storage, Config<T>, Event<T>} = 66,
// Consensus support
AuthorityMembers: pallet_authority_members::{Pallet, Call, Storage, Config<T>, Event<T>} = 10,
......
......@@ -71,7 +71,7 @@ parameter_types! {
// Balances
frame_support::parameter_types! {
pub const ExistentialDeposit: Balance = 200;
pub const ExistentialDeposit: Balance = 100;
pub const MaxLocks: u32 = 50;
}
......
......@@ -50,7 +50,7 @@ pub const NAMES: [&str; 6] = ["Alice", "Bob", "Charlie", "Dave", "Eve", "Ferdie"
pub struct ExtBuilder {
// endowed accounts with balances
initial_accounts: BTreeMap<AccountId, GenesisAccountData<Balance>>,
initial_accounts: BTreeMap<AccountId, GenesisAccountData<Balance, u32>>,
initial_authorities_len: usize,
initial_identities: BTreeMap<IdtyName, AccountId>,
initial_smiths: Vec<AuthorityKeys>,
......@@ -73,8 +73,8 @@ impl ExtBuilder {
get_account_id_from_seed::<sr25519::Public>(NAMES[i]),
GenesisAccountData {
balance: 0,
is_identity: true,
random_id: H256([i as u8; 32]),
idty_id: Some(i as u32 + 1),
},
)
})
......@@ -179,6 +179,7 @@ impl ExtBuilder {
pallet_duniter_account::GenesisConfig::<Runtime> {
accounts: initial_accounts.clone(),
treasury_balance: <Runtime as pallet_balances::Config>::ExistentialDeposit::get(),
}
.assimilate_storage(&mut t)
.unwrap();
......@@ -230,6 +231,16 @@ impl ExtBuilder {
.assimilate_storage(&mut t)
.unwrap();
pallet_quota::GenesisConfig::<Runtime> {
identities: initial_identities
.iter()
.enumerate()
.map(|(i, _)| i as u32 + 1)
.collect(),
}
.assimilate_storage(&mut t)
.unwrap();
pallet_membership::GenesisConfig::<Runtime, Instance1> {
memberships: (1..=initial_identities.len())
.map(|i| {
......
......@@ -17,10 +17,14 @@
mod common;
use common::*;
use frame_support::instances::Instance1;
use frame_support::traits::StoredMap;
use frame_support::traits::{Get, PalletInfo, StorageInfo, StorageInfoTrait};
use frame_support::{assert_noop, assert_ok};
use frame_support::{StorageHasher, Twox128};
use gdev_runtime::*;
use pallet_duniter_wot::IdtyRemovalWotReason;
use sp_core::Encode;
use sp_keyring::AccountKeyring;
use sp_runtime::MultiAddress;
......@@ -194,7 +198,7 @@ fn test_identity_below_ed() {
Balances::transfer(
frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
MultiAddress::Id(AccountKeyring::Bob.to_account_id()),
800
850
),
sp_runtime::TokenError::Frozen
);
......@@ -393,6 +397,31 @@ fn test_membership_expiry() {
});
}
#[test]
fn test_membership_expiry_with_identity_removal() {
ExtBuilder::new(1, 3, 4).build().execute_with(|| {
run_to_block(100);
System::assert_has_event(RuntimeEvent::Membership(
pallet_membership::Event::MembershipExpired(4),
));
// Trigger pending membership expiry
run_to_block(
100 + <Runtime as pallet_membership::Config<Instance1>>::PendingMembershipPeriod::get(),
);
System::assert_has_event(RuntimeEvent::Identity(
pallet_identity::Event::IdtyRemoved {
idty_index: 4,
reason: pallet_identity::IdtyRemovalReason::Other(
IdtyRemovalWotReason::MembershipExpired,
),
},
));
});
}
/// test membership renewal
#[test]
fn test_membership_renewal() {
......@@ -677,12 +706,15 @@ fn test_create_new_account_with_insufficient_balance() {
.build()
.execute_with(|| {
run_to_block(2);
// Treasury should start empty
// FIXME it actually starts with ED
assert_eq!(Balances::free_balance(Treasury::account_id()), 100);
// Should be able to transfer 4 units to a new account
assert_ok!(Balances::transfer(
frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
MultiAddress::Id(AccountKeyring::Eve.to_account_id()),
400
300
));
System::assert_has_event(RuntimeEvent::System(frame_system::Event::NewAccount {
......@@ -690,12 +722,12 @@ fn test_create_new_account_with_insufficient_balance() {
}));
System::assert_has_event(RuntimeEvent::Balances(pallet_balances::Event::Endowed {
account: AccountKeyring::Eve.to_account_id(),
free_balance: 400,
free_balance: 300,
}));
System::assert_has_event(RuntimeEvent::Balances(pallet_balances::Event::Transfer {
from: AccountKeyring::Alice.to_account_id(),
to: AccountKeyring::Eve.to_account_id(),
amount: 400,
amount: 300,
}));
// At next block, the new account must be reaped because its balance is not sufficient
......@@ -705,22 +737,23 @@ fn test_create_new_account_with_insufficient_balance() {
System::assert_has_event(RuntimeEvent::Account(
pallet_duniter_account::Event::ForceDestroy {
who: AccountKeyring::Eve.to_account_id(),
balance: 400,
balance: 300,
},
));
System::assert_has_event(RuntimeEvent::Balances(pallet_balances::Event::Deposit {
who: Treasury::account_id(),
amount: 400,
amount: 300,
}));
System::assert_has_event(RuntimeEvent::Treasury(pallet_treasury::Event::Deposit {
value: 400,
value: 300,
}));
assert_eq!(
Balances::free_balance(AccountKeyring::Eve.to_account_id()),
0
);
assert_eq!(Balances::free_balance(Treasury::account_id()), 600);
// 100 initial + 300 recycled from Eve account's destruction
assert_eq!(Balances::free_balance(Treasury::account_id()), 400);
});
}
......@@ -732,6 +765,7 @@ fn test_create_new_account() {
.build()
.execute_with(|| {
run_to_block(2);
assert_eq!(Balances::free_balance(Treasury::account_id()), 100);
// Should be able to transfer 5 units to a new account
assert_ok!(Balances::transfer(
......@@ -773,7 +807,8 @@ fn test_create_new_account() {
Balances::free_balance(AccountKeyring::Eve.to_account_id()),
200
);
assert_eq!(Balances::free_balance(Treasury::account_id()), 500);
// 100 initial + 300 deposit
assert_eq!(Balances::free_balance(Treasury::account_id()), 400);
// A random id request should be registered
assert_eq!(
......@@ -805,6 +840,7 @@ fn test_create_new_account() {
),
sp_runtime::DispatchError::ConsumerRemaining,
);
// Transfer failed, so free_balance remains the same
assert_eq!(
Balances::free_balance(AccountKeyring::Eve.to_account_id()),
200
......@@ -1088,3 +1124,135 @@ fn test_oneshot_accounts() {
);
});
}
/// test currency transfer
/// (does not take fees into account because it's only calls, not extrinsics)
#[test]
fn test_transfer() {
ExtBuilder::new(1, 3, 4)
.with_initial_balances(vec![
(AccountKeyring::Alice.to_account_id(), 10_000),
(AccountKeyring::Eve.to_account_id(), 10_000),
])
.build()
.execute_with(|| {
// Alice gives 500 to Eve
assert_ok!(Balances::transfer_allow_death(
frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
AccountKeyring::Eve.to_account_id().into(),
500
));
// check amounts
assert_eq!(
Balances::free_balance(AccountKeyring::Alice.to_account_id()),
10_000 - 500
);
assert_eq!(
Balances::free_balance(AccountKeyring::Eve.to_account_id()),
10_000 + 500
);
})
}
/// test linking account to identity
#[test]
fn test_link_account() {
ExtBuilder::new(1, 3, 4).build().execute_with(|| {
let genesis_hash = System::block_hash(0);
let alice = AccountKeyring::Alice.to_account_id();
let ferdie = AccountKeyring::Ferdie.to_account_id();
let payload = (b"link", genesis_hash, 1u32, ferdie.clone()).encode();
let signature = AccountKeyring::Ferdie.sign(&payload);
// Ferdie's account can be linked to Alice identity
assert_ok!(Identity::link_account(
frame_system::RawOrigin::Signed(alice).into(),
ferdie,
signature.into()
));
})
}
/// test change owner key
#[test]
fn test_change_owner_key() {
ExtBuilder::new(1, 3, 4).build().execute_with(|| {
let genesis_hash = System::block_hash(0);
let dave = AccountKeyring::Dave.to_account_id();
let ferdie = AccountKeyring::Ferdie.to_account_id();
let payload = (b"icok", genesis_hash, 4u32, dave.clone()).encode();
let signature = AccountKeyring::Ferdie.sign(&payload);
// Dave can change his owner key to Ferdie's
assert_ok!(Identity::change_owner_key(
frame_system::RawOrigin::Signed(dave).into(),
ferdie,
signature.into()
));
})
}
/// test genesis account of identity is linked to identity
// (and account without identity is not linked)
#[test]
fn test_genesis_account_of_identity_linked() {
ExtBuilder::new(1, 3, 4)
.with_initial_balances(vec![(AccountKeyring::Eve.to_account_id(), 8888)])
.build()
.execute_with(|| {
// Alice account
let account_id = AccountKeyring::Alice.to_account_id();
// Alice identity index is 1
assert_eq!(Identity::identity_index_of(&account_id), Some(1));
// get account data
let account_data = frame_system::Pallet::<Runtime>::get(&account_id);
assert_eq!(account_data.linked_idty, Some(1));
// Eve is not member, her account has no linked identity
assert_eq!(
frame_system::Pallet::<Runtime>::get(&AccountKeyring::Eve.to_account_id())
.linked_idty,
None
);
})
}
/// test unlink identity from account
#[test]
fn test_unlink_identity() {
ExtBuilder::new(1, 3, 4).build().execute_with(|| {
let alice_account = AccountKeyring::Alice.to_account_id();
// check that Alice is 1
assert_eq!(Identity::identity_index_of(&alice_account), Some(1));
// Alice can unlink her identity from her account
assert_ok!(Account::unlink_identity(
frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
));
// Alice account has been unlinked
assert_eq!(
frame_system::Pallet::<Runtime>::get(&alice_account).linked_idty,
None
);
})
}
/// test that the account of a newly created identity is linked to the identity
#[test]
fn test_new_account_linked() {
ExtBuilder::new(1, 3, 4).build().execute_with(|| {
let eve_account = AccountKeyring::Eve.to_account_id();
assert_eq!(
frame_system::Pallet::<Runtime>::get(&eve_account).linked_idty,
None
);
// Alice creates identity for Eve
assert_ok!(Identity::create_identity(
frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
eve_account.clone(),
));
// then eve account should be linked to her identity
assert_eq!(
frame_system::Pallet::<Runtime>::get(&eve_account).linked_idty,
Some(5)
);
})
}
// Copyright 2021 Axiom-Team
//
// This file is part of Duniter-v2S.
//
// Duniter-v2S is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, version 3 of the License.
//
// Duniter-v2S is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>.
// these integration tests aim to test fees and extrinsic-related externalities
mod common;
use common::*;
use frame_support::assert_ok;
use frame_support::inherent::Extrinsic;
use frame_support::traits::OnIdle;
use gdev_runtime::*;
use sp_core::Encode;
use sp_core::Pair;
use sp_keyring::AccountKeyring;
use sp_runtime::generic::SignedPayload;
/// get extrinsic for given call
fn get_unchecked_extrinsic(
call: RuntimeCall,
era: u64,
block: u64,
signer: AccountKeyring,
tip: Balance,
) -> UncheckedExtrinsic {
let extra: gdev_runtime::SignedExtra = (
frame_system::CheckNonZeroSender::<gdev_runtime::Runtime>::new(),
frame_system::CheckSpecVersion::<gdev_runtime::Runtime>::new(),
frame_system::CheckTxVersion::<gdev_runtime::Runtime>::new(),
frame_system::CheckGenesis::<gdev_runtime::Runtime>::new(),
frame_system::CheckMortality::<gdev_runtime::Runtime>::from(
sp_runtime::generic::Era::mortal(era, block),
),
frame_system::CheckNonce::<gdev_runtime::Runtime>::from(0u32).into(),
frame_system::CheckWeight::<gdev_runtime::Runtime>::new(),
pallet_transaction_payment::ChargeTransactionPayment::<gdev_runtime::Runtime>::from(tip),
);
let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap();
let origin = signer;
let sig = payload.using_encoded(|payload| origin.pair().sign(payload));
UncheckedExtrinsic::new(
call,
Some((origin.to_account_id().into(), sig.into(), extra)),
)
.unwrap()
}
/// test currency transfer with extrinsic
// the signer account should pay fees and a tip
// the treasury should get the fees
#[test]
fn test_transfer_xt() {
ExtBuilder::new(1, 3, 4)
.with_initial_balances(vec![
(AccountKeyring::Alice.to_account_id(), 10_000),
(AccountKeyring::Eve.to_account_id(), 10_000),
])
.build()
.execute_with(|| {
let call = RuntimeCall::Balances(BalancesCall::transfer_allow_death {
dest: AccountKeyring::Eve.to_account_id().into(),
value: 500,
});
// 1 cĞD of tip
let xt = get_unchecked_extrinsic(call, 4u64, 8u64, AccountKeyring::Alice, 1u64);
// let info = xt.get_dispatch_info();
// println!("dispatch info:\n\t {:?}\n", info);
assert_eq!(Balances::free_balance(Treasury::account_id()), 100);
// Alice gives 500 to Eve
assert_ok!(Executive::apply_extrinsic(xt));
// check amounts
assert_eq!(
Balances::free_balance(AccountKeyring::Alice.to_account_id()),
10_000 - 500 - 3 // initial - transfered - fees
);
assert_eq!(
Balances::free_balance(AccountKeyring::Eve.to_account_id()),
10_000 + 500 // initial + transfered
);
assert_eq!(Balances::free_balance(Treasury::account_id()), 100 + 3);
})
}
/// test that fees are added to the refund queue
#[test]
fn test_refund_queue() {
ExtBuilder::new(1, 3, 4)
.with_initial_balances(vec![
(AccountKeyring::Alice.to_account_id(), 10_000),
(AccountKeyring::Eve.to_account_id(), 10_000),
])
.build()
.execute_with(|| {
let call = RuntimeCall::Balances(BalancesCall::transfer_allow_death {
dest: AccountKeyring::Eve.to_account_id().into(),
value: 500,
});
// 1 cĞD of tip
let xt = get_unchecked_extrinsic(call, 4u64, 8u64, AccountKeyring::Alice, 1u64);
assert_ok!(Executive::apply_extrinsic(xt));
// check that refund was added to the queue
assert_eq!(
pallet_quota::RefundQueue::<Runtime>::get()
.first()
.expect("a refund should have been added to the queue"),
&pallet_quota::pallet::Refund {
account: AccountKeyring::Alice.to_account_id(),
identity: 1u32,
amount: 2u64
}
);
})
}
/// test refund on_idle
#[test]
fn test_refund_on_idle() {
ExtBuilder::new(1, 3, 4)
.with_initial_balances(vec![
(AccountKeyring::Alice.to_account_id(), 10_000),
(AccountKeyring::Eve.to_account_id(), 10_000),
])
.build()
.execute_with(|| {
let call = RuntimeCall::Balances(BalancesCall::transfer_allow_death {
dest: AccountKeyring::Eve.to_account_id().into(),
value: 500,
});
// 1 cĞD of tip
let xt = get_unchecked_extrinsic(call, 4u64, 8u64, AccountKeyring::Alice, 1u64);
assert_ok!(Executive::apply_extrinsic(xt));
// call on_idle to activate refund
Quota::on_idle(System::block_number(), Weight::from(1_000_000_000));
// check that refund event existed
System::assert_has_event(RuntimeEvent::Quota(pallet_quota::Event::Refunded {
who: AccountKeyring::Alice.to_account_id(),
identity: 1u32,
amount: 1u64,
}));
// check that refund queue is empty
assert!(pallet_quota::RefundQueue::<Runtime>::get().is_empty());
assert_eq!(
Balances::free_balance(AccountKeyring::Alice.to_account_id()),
10_000 - 500 - 1 - 2 + 1 // initial - transfered - tip - fees + refunded fees
);
})
}
/// test no refund when no identity linked
#[test]
fn test_no_refund() {
ExtBuilder::new(1, 3, 4)
.with_initial_balances(vec![
(AccountKeyring::Alice.to_account_id(), 10_000),
(AccountKeyring::Eve.to_account_id(), 10_000),
])
.build()
.execute_with(|| {
// Eve → Alice
let call = RuntimeCall::Balances(BalancesCall::transfer_allow_death {
dest: AccountKeyring::Alice.to_account_id().into(),
value: 500,
});
let xt = get_unchecked_extrinsic(call, 4u64, 8u64, AccountKeyring::Eve, 1u64);
assert_ok!(Executive::apply_extrinsic(xt));
// check that refund queue is empty
assert!(pallet_quota::RefundQueue::<Runtime>::get().is_empty());
assert_eq!(Balances::free_balance(Treasury::account_id()), 100 + 3);
})
}
......@@ -65,6 +65,7 @@ std = [
'pallet-collective/std',
'pallet-distance/std',
'pallet-duniter-account/std',
'pallet-quota/std',
'pallet-duniter-wot/std',
'pallet-grandpa/std',
'pallet-identity/std',
......@@ -94,6 +95,7 @@ std = [
'sp-block-builder/std',
'sp-consensus-babe/std',
'sp-core/std',
'sp-distance/std',
'sp-inherents/std',
'sp-offchain/std',
'sp-membership/std',
......@@ -137,16 +139,18 @@ pallet-authority-members = { path = '../../pallets/authority-members', default-f
pallet-certification = { path = '../../pallets/certification', default-features = false }
pallet-distance = { path = "../../pallets/distance", default-features = false }
pallet-duniter-account = { path = '../../pallets/duniter-account', default-features = false }
pallet-quota = { path = '../../pallets/quota', default-features = false }
pallet-duniter-wot = { path = '../../pallets/duniter-wot', default-features = false }
pallet-identity = { path = '../../pallets/identity', default-features = false }
pallet-membership = { path = '../../pallets/membership', default-features = false }
pallet-offences = { path = '../../pallets/offences', default-features = false }
pallet-oneshot-account = { path = '../../pallets/oneshot-account', default-features = false }
pallet-provide-randomness = { path = '../../pallets/provide-randomness', default-features = false }
pallet-universal-dividend = { path = '../../pallets/universal-dividend', default-features = false }
pallet-session-benchmarking = { path = '../../pallets/session-benchmarking', default-features = false }
pallet-upgrade-origin = { path = '../../pallets/upgrade-origin', default-features = false }
sp-distance = { path = '../../primitives/distance', default-features = false }
sp-membership = { path = '../../primitives/membership', default-features = false }
pallet-offences = { path = '../../pallets/offences', default-features = false }
# crates.io
codec = { package = "parity-scale-codec", version = "3.4.0", features = ["derive"], default-features = false }
......
......@@ -52,7 +52,9 @@ use pallet_grandpa::fg_primitives;
use pallet_grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList};
use sp_api::impl_runtime_apis;
use sp_core::OpaqueMetadata;
use sp_runtime::traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, NumberFor, OpaqueKeys};
use sp_runtime::traits::{
AccountIdLookup, BlakeTwo256, Block as BlockT, NumberFor, One, OpaqueKeys,
};
use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
transaction_validity::{TransactionSource, TransactionValidity},
......@@ -269,6 +271,7 @@ construct_runtime!(
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 6,
TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event<T>} = 32,
OneshotAccount: pallet_oneshot_account::{Pallet, Call, Storage, Event<T>} = 7,
Quota: pallet_quota::{Pallet, Storage, Config<T>, Event<T>} = 66,
// Consensus support
AuthorityMembers: pallet_authority_members::{Pallet, Call, Storage, Config<T>, Event<T>} = 10,
......
......@@ -6,4 +6,21 @@ We choose [`xtask`](https://github.com/matklad/cargo-xtask/) to run Rust scripts
cargo xtask # this will build the scripts and show the available commands
```
These scripts mainly deal with runtime operations.
\ No newline at end of file
These scripts mainly deal with runtime operations.
## Doc
```
Usage: xtask <COMMAND>
Commands:
build Build duniter binary
gen-calls-doc Generate calls documentation
inject-runtime-code Inject runtime code in raw specs
release-runtime Release a new runtime
test Execute unit tests and integration tests End2tests are skipped
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
```
mutation CreateReleaseAssetLinkMutation($tag: String!, $name: String!, $url: String!) {
releaseAssetLinkCreate(input: {
name: $name
url: $url,
tagName: $tag,
projectPath: "nodes/rust/duniter-v2s"
}) {
errors
}
}
mutation CreateReleaseMutation($branch: String!, $description: String!, $milestone: String!) {
mutation CreateReleaseMutation($branch: String!, $description: String!, $milestone: String!, $links: [ReleaseAssetLinkInput!]!) {
releaseCreate(input: {
clientMutationId: "duniter-v2s-xtask"
description: $description
......@@ -7,6 +7,9 @@ mutation CreateReleaseMutation($branch: String!, $description: String!, $milesto
projectPath: "nodes/rust/duniter-v2s"
ref: $branch
tagName: $milestone
assets: {
links: $links
}
}) {
errors
}
......
query GetIssuesQuery($milestone: String!) {
project(fullPath: "nodes/rust/duniter-v2s") {
issues(milestoneTitle: [$milestone], state: all) {
nodes {
iid
state
title
}
}
}
}
query GetReleaseOfProjectQuery($milestone: String!) {
project(fullPath: "nodes/rust/duniter-v2s") {
release(tagName: $milestone) {
id
tagName
assets {
links {
edges {
node {
directAssetUrl
}
}
}
}
}
}
}
# Runtimes
The runtimes have been built using [{srtool_version}](https://github.com/paritytech/srtool) and `{rustc_version}`.
## ĞDev
```
🏋️ Runtime Size: {runtime_human_size} ({runtime_size} bytes)
🔥 Core Version: {core_version}
🗜 Compressed: Yes: {compression_percent} %
🎁 Metadata version: {metadata_version}
🗳️ system.setCode hash: {proposal_hash}
#️⃣ Blake2-256 hash: {blake2_256}
```
# Changes
{changes}