Open eskimor opened 2 days ago
Nice proposal!
I expect that its not super very cheap to fetch information from this facade, so for Peer related info and generally operations that happen often, we would need to cache the list of participants locally for sure.
A pallet providing the locking mechanism: pallet-pod + runtime API
It's a dedicated lock, not an overlapping lock ala restaking? We've typically used overlapping locks ala restaking, but in general this really depends upon what your doing.
I expect that its not super very cheap to fetch information from this facade, so for Peer related info and generally operations that happen often, we would need to cache the list of participants locally for sure.
In the worse case, remove Merkle proofs would not necessarily be more expensive than the local Merkle proofs required by local state accesses, just depends how heavily used. In fact, the remove Merkle proofs could even become cheaper than local ones, assuming the majority of state accesses were remote.
It must be without overlap. Without an attack the amounts locked will stay low anyway, but if there is one, the economic pressure must go up for maximum effect.
I expect that its not super very cheap to fetch information from this facade, so for Peer related info and generally operations that happen often, we would need to cache the list of participants locally for sure.
Yes. This is one of the reasons for the unlock_period
. The idea is you only update once in a while. E.g. once per day/ once per session. Whatever makes sense for the application.
This ticket is about adding a generic sybil resistance functionality to Polkadot to be used permissionlessly by any protocol that might need it. This includes Polkadot native infrastructure, but given its permissionlessness, it can be used by any (p2p) protocol to enhance its resilience.
The idea is not new and rather simple: We use a proof of stake mechanism. With this we can prefer participants with stake over participants without. Acquiring stake becomes expensive very quickly if you want to attack. This mechanism can be added to any protocol in a backwards compatible way: Existing clients would still be served based on best-effort (same as they did before), but in addition, participants can lock up DOT for better quality of service, especially in attack scenarios.
Ingredients
pallet-pod
Interface:
Extrinsics
Register a new protocol you want to have sybil resiistance for, with a name and an expected number of participants.
origin can be any, including root or a chain. Some fee will be charged and some DOT locked for the lifetime of the registered protocol. The name must be unique.
Show intent to become a participant in the protocol, by registering some identifier (e.g. your PeerId). You can specify a maximum amount of DOT you are willing to have locked for this. Actual amount locked will be determined based on current occupation.
Leave the protocol: Your peer identifier will be removed and you get your funds unlocked after
unlock_period
blocks.Remove a protocol and claim back the storage deposit for the protocol. This call will fail if there are still participants in the network. Hence, when registering, you should deal with the possibility that you might never get your storage deposit back. The data stored for a protocol is only the configuration, thus that amount should be small. I believe this is acceptable and provides the benefit that the system is by default decentralized: Anybody can create a protocol, but the resulting system would still be decentralized, as nobody, not even that creator will be able to stop it.
View functions
The pallet will also expose the following functions, which should be exported as a runtime API:
MAX_PARTICIPANTS
should be constrained in a way, such that this call is feasible. We could use a cursor based accessor function, but given that this is supposed to be called from a runtime API, I don't think this complexity is necessary (For now. we can add that later if we actually have demand for networks that large).Implementation
Protocol registration will ensure that no other protocol with the same name exists. Then it will store the configuration under the protocol's name.
Participation is more interesting. We need to ensure that the system is not itself DOSable. In particular it must not be possible for an attacker to get honest nodes lose their spot, yet we still have limited capacity. We achieve this by setting a conceptual limit on the number of participants to
further we set the following:
Then we calculate the deposit we take for the
n
th participant via:Example, at the time of registration there have been already 100 participants registered, assuming
limit = 1000
, then the deposit for theparticipate
call would be:0.1 * 2^(100/(1000/40)) = 1.6 DOT
Parameters have been picked such that you can not reach
limit
, as the amount of DOT, you would need to lock, exceed the entire DOT supply. (Economically bounded)Cost of censorship attacks are high and in favor of the defender. For doubling the price, the attacker would need to invest
step/2
times that doubled price. Trying to bring up the price by a factor of 8, will cost x ( step + 2 step + 4 step). Wherex
was the current price of the time of the attack. This results in 175 x for the attacker to pay, while the to be censored node will need to pay 8*x. (We assume limit to be 1000 and step size thus 25). For smaller limits the attacker would still need to pay at least the same as the to be censored node.For each participant we store in a
DoubleStorageMap<ProtocolName, PeerIdentifier, Participant>
theParticipant
data:For
leaving
we will remove the entry in above storage map and note inPendingRemoval
storage that the funds may be reclaimed atnow + unlocking_period
. We either check inon_initialize
for accounts that should get their funds back or we add an additional extrinsic for claiming back funds that passed the unlocking period.Provided Facade
To make all of this easily accessible we need to provide a Rust library with the following entry points:
So essentially the functionality provided by the pallet. With a few key differences:
PeerId
, while in the pallet we will use some BoundedVecThis will allow us to move the functionality around (if necessary), change implementation details and even allows for sharding if that ever became necessary. The Facade would just determine what shard to lookup a given protocol based on the name.