filecoin-project / specs-actors

DEPRECATED Specification of builtin actors, in the form of executable code.
Other
86 stars 102 forks source link

CheckBalanceInvariants loads state inconsistently across methods #1340

Open austinabell opened 3 years ago

austinabell commented 3 years ago

Most checks load state before checking invariants, for example:

https://github.com/filecoin-project/specs-actors/blob/2a6279534fab3e1fe818f9aeeda4ab27efd57af7/actors/builtin/miner/miner_actor.go#L477-L478

Where others do not and use the state from the transaction, such as: https://github.com/filecoin-project/specs-actors/blob/2a6279534fab3e1fe818f9aeeda4ab27efd57af7/actors/builtin/miner/miner_actor.go#L1710 https://github.com/filecoin-project/specs-actors/blob/2a6279534fab3e1fe818f9aeeda4ab27efd57af7/actors/builtin/miner/miner_actor.go#L1731

When it seems like it has the same side effects as the others. Maybe there is a reason for this inconsistency, so feel free to close issue if so, but opening in case there isn't.

anorth commented 3 years ago

Thanks for opening the question. There are some inconsistencies here and it would be nice to figure out a single way of doing it.

Most of the time, I think the rt.StateReadonly(&st) is unnecessary, and the transaction state could be used.

I think we can pick a policy that we can use almost everywhere, with the possible exception of the two prior places. So the question is do we want to always load state, redundantly, to be sure it's the correct one? Or trust in our patterns and use the post-transaction state without re-loading it?

Thoughts @Stebalien @ZenGround0 ?

ZenGround0 commented 3 years ago

Without investigating too deeply I prefer consistently re-loading state redundantly because

  1. Correctness >> Performance for invariant checking
  2. I am pessimistic invariant checking will ever be performant enough for this optimization to move the needle noticeably

It would be great to prioritize performance of invariant checking if we have the bandwidth at which point we could profile and revisit this question. But I expect working on parallelizing as in the migration to be much higher leverage.

Stebalien commented 3 years ago

Given that the only two cases where we don't currently reload the state are RepayDebt and WithdrawBalance, neither of which are performance critical, I'd just reload the state to be consistent (even though we know that burning funds, changing pledge, etc. are not reentrent).

ZenGround0 commented 3 years ago

From sync with other actors implementors the inconsistency here was explicitly called out as burdensome, making this now higher priority to do consistently.