-
Notifications
You must be signed in to change notification settings - Fork 45
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
Update fendermint to match genesis changes in solidity #784
Conversation
…yard/ipc into init-staking-fendermint
…yard/ipc into init-staking-fendermint
…yard/ipc into init-staking-fendermint
fendermint/vm/genesis/src/lib.rs
Outdated
/// Convert from [LibStakingPower] to [Power] by specifying the number of significant | ||
/// decimal places per FIL that grant 1 power. | ||
/// | ||
/// For example: | ||
/// * with 3 decimal places, we get 1 power per milli FIL: 0.001 FIL => 1 power | ||
/// * with 0 decimal places, we get 1 power per whole FIL: 1 FIL => 1 power | ||
pub fn into_power(self: LibStakingPower, scale: PowerScale) -> Power { | ||
let atto_per_power = Collateral::atto_per_power(scale); | ||
let atto = self.federated_power.atto() + self.collateral.atto(); | ||
// Rounding away from zero, so with little collateral (e.g. in testing) | ||
// we don't end up with everyone having 0 power and then being unable | ||
// to produce a checkpoint because the threshold is 0. | ||
let power = atto.div_ceil(&atto_per_power); | ||
let power = power.min(BigInt::from(u64::MAX)); | ||
Power(power.try_into().expect("clipped to u64::MAX")) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There shouldn't be a need to copy-paste all this. The original is covered by tests, this isn't.
Since both federated_power
and collateral
are TokenAmount
, you can just add the together, wrap the result in Collateral
and call into_power
on it: Collateral(self.federated_power + self.collateral).into_power(scale)
.
ipc/api/src/validator.rs
Outdated
// .collect(); | ||
// | ||
// result | ||
// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need this commented code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will remove them
@@ -14,7 +14,7 @@ use ipc_actors_abis::{ | |||
subnet_actor_reward_facet, | |||
}; | |||
use ipc_api::evm::{fil_to_eth_amount, payload_to_evm_address, subnet_id_to_evm_addresses}; | |||
use ipc_api::validator::from_contract_validators; | |||
use ipc_api::validator::vec_try_from; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is a public and completely generic function, just a convenience for some library builtins, it would be worth moving it into a utility module. It's strange to see it being imported from validator
when it has nothing validator specific about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't even see it used anywhere else, so maybe just move it into this module as a private function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can see Maciej commenting here that it was never a requirement to support collateral and federation-assigned power at the same time. Your response, as I understand, is that this is implementation detail of LibStaking
, ie. the lower level component does the book keeping this way, but this is not visible to the user (or the SubnetActor
in your answer).
I don't know the details of LibStaking
, why it needs to separate the two concepts. Is it because if you have collateral
then if you leave
you get something back? But isn't that decided by the parent? Isn't collateral
just a label in the subnet? Couldn't the parent just look at the permission mode and decide whether to release tokens to the validator during unbonding or not?
In any case, in contrast to what I thought was an implementation detail, here the distinction proliferates through the API and the CLI, and now the user can assign both at the same time. I'm not sure if this is desirable. Maybe we just shouldn't call it collateral
, but keep it as a single field?
My problem is that voting power can come from many places: it could be a consensus where PoW+PoS gives you power, or it could be coming from delegations. What we I think know is that for a subnet, it comes from the parent (and for rootnet, well, we don't do rootnets outside tests). I totally agree that collateral
is misleading, but a proliferation of fields doesn't seem to be all that helpful to me.
On a different note, if we just wanted to make a distinction between tokens that can be returned to the users and other sources, we could perhaps call the fields funded
and unfunded
, with the latter being not backed by locked tokens.
Co-authored-by: Akosh Farkash <[email protected]>
I agree with @aakoshh. We do not need to track both collateral and weight. But the problem is deeper: these should NOT be used in conjunction. There should just be weight, which is either set explicitly ( The "hybrid" model that uses both both collateral and federated is very unsound. There is no unit enforced for manually-assigned weights. So if the user assigns equal weights of 1, 1, 1, an attacker could come in and deposit 10 FIL and take over the network in a clean sweep. |
c83762c
to
421aeea
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's unblock by doing the following.
- Parent subnet actor needs to track collateral and static power for every validator, before and after genesis.
- Remove the
GenesisValidator
type and simply useValidatorInfo
type; unless I'm missing something, these types are redundant. @aakoshh also pointed it out in his review. - That should allow us to get rid of weirdness like this:
- The subnet actor translates the combination of validator collateral and static power into a weight, depending on the
permissionMode
.- If
collateral
, use only collateral. - If
federated
, use only the static power. - If in the future we want to add a hybrid, we'll add the hybrid. But neither collateral nor federated should be hybrid.
- If
- The validator set we pull in genesis and we subsequently send as configuration changes MUST NOT include collateral nor static power, just the weight, i.e. it should be this type ideally, or something similar.
Actually, I just realised that the child gateway receives individual validator commands in the form of:
It also stores full ValidatorInfo objects including the power, collateral, etc. The child gateway then needs to reconcile all this info and recalculate the power locally based on the Ideally all this acccounting would be encapsulated in the source of truth: subnet actor at the parent. That actor would just emit new weights (computed based on its permissionMode) that propagate down to the child gateway to apply them in the subnet. Unfortunately all of this is going to require a more profound discussion/architectural change to adjust. Ideally we would've had this discussion before implementing federated validation (at that time we just had collateral, which directly translated into weight), but that ship has sailed. At this stage, we might be better off just biting the bullet and refactoring later. |
So I think we're just going to have the bullet and accept this change until we rearchitect to decouple the collateral and static power tracking at the parent, from their translation to a mere weight at the child. That said, we should implement (2), (3) and (4) from above before we merge this PR.
|
Merged in the interest of landing the fixes in the base branch onto main. Will discuss next steps with the team and @cryptoAtwill on Monday. |
Update fendermint to align with the changes in solidity contracts. Some key changes are:
GenesisValidator
parameter that matches that in the contract.LibStakingPower
for references.ipc
get genesis from parent to useGenesisValidator
.This PR is compilable and integration tested, but it's pending updates in unit tests.