-
Notifications
You must be signed in to change notification settings - Fork 771
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tokens: Revamp locking & reserving #236
Comments
would finally close #339 here as well. |
As a step in this direction, is it a useful endeavour if I rebase and bring back the asset-freezer pallet PR? paritytech/substrate#8476 |
It could help, but only after paritytech/substrate#12951 is sorted. |
Since we're going to have almost the same logic for both lock and hold reason/id, how about something like: // pallet-a
#[pallet::composable_enum]
enum HoldReason {
}
// pallet-b
#[pallet::composable_enum]
enum HoldReason {
}
// runtime amalgamator
enum RuntimeHoldReason {
PalletA(pallet_a::HoldReason),
PalletB(pallet_b::HoldReason),
} instead of |
@sam0x17 and I did a bit of brainstorming on this, here's the diff: diff --git a/frame/elections-phragmen/src/lib.rs b/frame/elections-phragmen/src/lib.rs
index 1cfdc25fd9..f262ada757 100644
--- a/frame/elections-phragmen/src/lib.rs
+++ b/frame/elections-phragmen/src/lib.rs
@@ -201,8 +201,15 @@ pub mod pallet {
#[pallet::constant]
type PalletId: Get<LockIdentifier>;
+ /// This will come from the outer runtime, and it will be the amalgamated lock ids.
+ type RuntimeLockIds: From<crate::pallet::LockIds>;
+
/// The currency that people are electing with.
- type Currency: LockableCurrency<Self::AccountId, Moment = Self::BlockNumber>
+ type Currency: LockableCurrency<
+ Self::AccountId,
+ Moment = Self::BlockNumber,
+ LockId = Self::RuntimeLockId
+ >
+ ReservableCurrency<Self::AccountId>;
/// What to do when the members change.
@@ -359,9 +366,20 @@ pub mod pallet {
},
};
+ // local lock id.
+ #[pallet::composite]
+ enum LockId {
+ CouncilVoting,
+ OtherReason,
+ }
+
+ let id: T::RuntimeLockIds = LockId::CouncilVoting.into();
+
// Amount to be locked up.
let locked_stake = value.min(T::Currency::free_balance(&who));
- T::Currency::set_lock(T::PalletId::get(), &who, locked_stake, WithdrawReasons::all());
+ // TODO: the currency implementations, whatever it might be, will know if this lock/hold
+ // operation is going to collide with collide with other existing locks or not.
+ T::Currency::set_lock(id, &who, locked_stake, WithdrawReasons::all());
Voting::<T>::insert(&who, Voter { votes, deposit: new_deposit, stake: locked_stake });
Ok(None::<Weight>.into())
diff --git a/frame/support/src/traits/tokens/currency/lockable.rs b/frame/support/src/traits/tokens/currency/lockable.rs
index a10edd6e3e..c804a99ea7 100644
--- a/frame/support/src/traits/tokens/currency/lockable.rs
+++ b/frame/support/src/traits/tokens/currency/lockable.rs
@@ -29,6 +29,10 @@ pub trait LockableCurrency<AccountId>: Currency<AccountId> {
/// The quantity used to denote time; usually just a `BlockNumber`.
type Moment;
+ /// Opaque Identifier for lock.
+ // TODO: can already be ported to master with LockIdentifier used everywhere.
+ type LockId;
+
/// The maximum number of locks a user should have on their account.
type MaxLocks: Get<u32>;
@@ -39,7 +43,7 @@ pub trait LockableCurrency<AccountId>: Currency<AccountId> {
///
/// If the lock `id` already exists, this will update it.
fn set_lock(
- id: LockIdentifier,
+ id: Self::LockId,
who: &AccountId,
amount: Self::Balance,
reasons: WithdrawReasons,
@@ -54,7 +58,7 @@ pub trait LockableCurrency<AccountId>: Currency<AccountId> {
/// - maximum `amount`
/// - bitwise mask of all `reasons`
fn extend_lock(
- id: LockIdentifier,
+ id: Self::LockId,
who: &AccountId,
amount: Self::Balance,
reasons: WithdrawReasons,
|
This diff looks like the right API. |
Benchmarking macro overhaul is wrapping up so have bandwidth to work on this actively now |
If this is just a normal enum, there is no need to have this attribute. What should this attribute do? |
If locked funds are non-slashable, but we can lock/freeze on the total balance including funds on hold. Doesn't this mean that we may can not slash because funds are locked that we have on hold? |
My understanding, but feel free to jump in @kianenigma, is that the idea here is to have a macro called |
Yeah your understanding is right, the point is just that you don't need this :P At the crate level you are just defining an enum and at the runtime level you combine them. I also know that @kianenigma wants to rework the |
@bkchr Are you suggesting the alternative that at the runtime level, we manually build the All in all, yes, ideally a new |
They can not shake hands that easily. The hand shaking they are doing is really limited and not that generic, aka that you can... While writing this, I had some ideas on how to maybe achieve this. But not sure it would be "less magic". Personally I'm more a fan of having fixed attributes that are telling the macro exactly what a certain type is. If we would use the |
@bkchr I like the sound of this, do you have some particular syntax in mind? |
I don't have further strong opinions yet. For the time being though, I can say that this line of work can progress my manually writing this part and without a macro. |
Not really, I mean we should use an enum and then just put some attribute above it. Something like:
|
No - anything using freezing (the new name for locks) would need to handle the possibility that the balance may have been reduced through a slash. The main guarantee freezing gets the caller is that the user will be unable to move funds easily or cheaply. For voting, this won't cause a big problem and I don't see many other use cases at this point. |
The first batch of work is pretty much complete now in paritytech/substrate#12951 |
Very nice to see fungibles getting soon hold(with reason) and freeze capabilities, have been following that for a long time and will be looking forward to migrate our payments pallet to use the fungibles traits :) |
(You can already vote with staked funds.) |
This issue has been mentioned on Polkadot Forum. There might be relevant details there: https://forum.polkadot.network/t/polkadot-release-analysis-v0-9-41-v0-9-42/2828/1 |
…ytech#236) * make receipts part of tx proof * is_successful_raw_receipt_with_empty_data * cargo fmt --all * clippy * fix everything
This PR updates litep2p to the latest release. - `KademliaEvent::PutRecordSucess` is renamed to fix word typo - `KademliaEvent::GetProvidersSuccess` and `KademliaEvent::IncomingProvider` are needed for bootnodes on DHT work and will be utilized later ### Added - kad: Providers part 8: unit, e2e, and `libp2p` conformance tests ([#258](paritytech/litep2p#258)) - kad: Providers part 7: better types and public API, public addresses & known providers ([#246](paritytech/litep2p#246)) - kad: Providers part 6: stop providing ([#245](paritytech/litep2p#245)) - kad: Providers part 5: `GET_PROVIDERS` query ([#236](paritytech/litep2p#236)) - kad: Providers part 4: refresh local providers ([#235](paritytech/litep2p#235)) - kad: Providers part 3: publish provider records (start providing) ([#234](paritytech/litep2p#234)) ### Changed - transport_service: Improve connection stability by downgrading connections on substream inactivity ([#260](paritytech/litep2p#260)) - transport: Abort canceled dial attempts for TCP, WebSocket and Quic ([#255](paritytech/litep2p#255)) - kad/executor: Add timeout for writting frames ([#277](paritytech/litep2p#277)) - kad: Avoid cloning the `KademliaMessage` and use reference for `RoutingTable::closest` ([#233](paritytech/litep2p#233)) - peer_state: Robust state machine transitions ([#251](paritytech/litep2p#251)) - address_store: Improve address tracking and add eviction algorithm ([#250](paritytech/litep2p#250)) - kad: Remove unused serde cfg ([#262](paritytech/litep2p#262)) - req-resp: Refactor to move functionality to dedicated methods ([#244](paritytech/litep2p#244)) - transport_service: Improve logs and move code from tokio::select macro ([#254](paritytech/litep2p#254)) ### Fixed - tcp/websocket/quic: Fix cancel memory leak ([#272](paritytech/litep2p#272)) - transport: Fix pending dials memory leak ([#271](paritytech/litep2p#271)) - ping: Fix memory leak of unremoved `pending_opens` ([#274](paritytech/litep2p#274)) - identify: Fix memory leak of unused `pending_opens` ([#273](paritytech/litep2p#273)) - kad: Fix not retrieving local records ([#221](paritytech/litep2p#221)) See release changelog for more details: https://github.com/paritytech/litep2p/releases/tag/v0.8.0 cc @paritytech/networking --------- Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> Co-authored-by: Dmitry Markin <dmitry@markin.tech>
This PR updates litep2p to the latest release. - `KademliaEvent::PutRecordSucess` is renamed to fix word typo - `KademliaEvent::GetProvidersSuccess` and `KademliaEvent::IncomingProvider` are needed for bootnodes on DHT work and will be utilized later - kad: Providers part 8: unit, e2e, and `libp2p` conformance tests ([#258](paritytech/litep2p#258)) - kad: Providers part 7: better types and public API, public addresses & known providers ([#246](paritytech/litep2p#246)) - kad: Providers part 6: stop providing ([#245](paritytech/litep2p#245)) - kad: Providers part 5: `GET_PROVIDERS` query ([#236](paritytech/litep2p#236)) - kad: Providers part 4: refresh local providers ([#235](paritytech/litep2p#235)) - kad: Providers part 3: publish provider records (start providing) ([#234](paritytech/litep2p#234)) - transport_service: Improve connection stability by downgrading connections on substream inactivity ([#260](paritytech/litep2p#260)) - transport: Abort canceled dial attempts for TCP, WebSocket and Quic ([#255](paritytech/litep2p#255)) - kad/executor: Add timeout for writting frames ([#277](paritytech/litep2p#277)) - kad: Avoid cloning the `KademliaMessage` and use reference for `RoutingTable::closest` ([#233](paritytech/litep2p#233)) - peer_state: Robust state machine transitions ([#251](paritytech/litep2p#251)) - address_store: Improve address tracking and add eviction algorithm ([#250](paritytech/litep2p#250)) - kad: Remove unused serde cfg ([#262](paritytech/litep2p#262)) - req-resp: Refactor to move functionality to dedicated methods ([#244](paritytech/litep2p#244)) - transport_service: Improve logs and move code from tokio::select macro ([#254](paritytech/litep2p#254)) - tcp/websocket/quic: Fix cancel memory leak ([#272](paritytech/litep2p#272)) - transport: Fix pending dials memory leak ([#271](paritytech/litep2p#271)) - ping: Fix memory leak of unremoved `pending_opens` ([#274](paritytech/litep2p#274)) - identify: Fix memory leak of unused `pending_opens` ([#273](paritytech/litep2p#273)) - kad: Fix not retrieving local records ([#221](paritytech/litep2p#221)) See release changelog for more details: https://github.com/paritytech/litep2p/releases/tag/v0.8.0 cc @paritytech/networking --------- Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> Co-authored-by: Dmitry Markin <dmitry@markin.tech> Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
We want to revisit the definitions of free, locked and reserved, especially with regards voting, auctions/crowdloans and staking. Staking and bidding should be mutually exclusive but either should be possible at the same time as (conviction) voting. No funds used for any of the three should be transferable. We should be aware that funds for staking may be slashed.
The reorganisation will be multifaceted. Terminologically, we will move away from "reserve" and instead use the word "hold"; "locking" will become "freezing". When placing a hold on funds, the caller must include a
HoldReason
value which is essentially equivalent to a name when using named reserves except that it is typesafe. Slashing will not be possible except on funds on hold. Freezing will be possible on the total balance, including any funds on hold. Finally, we will deprecate the old*Currency
traits and move all core pallets over to usefungible::*
traits.1. Typesafe reserve/hold identifier for the reasons for holding (reserving).
We should have proper reserve identifiers rather than just strings/blobs. Within a pallet which uses holds or slashes, you must do something like:
They'd be aggregated into a top-level type (like
Error
,Event
,Origin
, &c.), and that would be exposed in metadata. You'd then be required to provide a value of this type when callinghold
. This would make it basically impossible for one pallet toslash
orunreserve
another pallet's funds.Lock IDs, also...
In addition to an identifier for holds, there should be another one in parallel for identifying locks (right now it's just a blob).
2. Change lock/reserve/hold mechanics
hold
/reserve
and renamereserve_named
/hold_named
toreserve
/hold
; this makes a reason/name/ID be required for any funds placed on hold.slash
andslash_reserved
functions; free and locked funds are then non-slashable and all slashes must have a "reason".slash_reserved_named
toslash
; again, this cements the requirement that only segregated, pre-reserved funds are slashable. (If you just want to slash free funds which you know are there, then you can still reserve them and slash them.)Reserving funds basically becomes a "pre-slash lock" with a hard guarantee that until you unreserve them, they're definitely slashable.
3. Update usages
All non-deprecated pallets which use locks should have some unpermissioned dispatchable which allows the bookkeeping to be updated in case an account's reserved funds received a slash and there is no longer the expected funds locked. For now this would basically just be
conviction-voting
pallet.4. Move to
fungible::*
Deprecate
Currency
/LockableCurrency
/ReservableCurrency
traits to thefungible::*
traits. Doing all of this will need a migration to move staked funds from a lock to a named reserve, but it should be possible. Migrations will also need to happen for any pallets which usereserve
without a name. Migrations will also be needed for the PLA system (for the new system of holds) and the staking system (to move from locks to holds).5. Alter NIS
NIS doesn't really fit into this model. We should change it to allow the receipt-holder to retain the funds under a hold. If the receipt gets transferred then the underlying funds will also need to be transferred (not repatriated - we want to respect any locks such as for voting). If the funds transfer fails, then the receipt transfer should also fail.
The text was updated successfully, but these errors were encountered: