specs
specs copied to clipboard
Consider disallowing bare send of value to singleton actors
From @raulk: Right now it's possible for account actors to perform naked sends (method num = 0) to singleton actors (e.g. system, market, power, etc.), from which the funds will never be rescued (unless a future fork/protocol change unlocks/returns them).
At least in Ethereum there is the minuscule chance that one can crack the private key for account 0x000000...00
But in Filecoin, singleton actors don't even have private keys associated to them. So these funds have nil chance of being released, ever.
Is there a use case behind allowing method_num = 0 messages to singleton actors? If not, I suggest we explicitly reject these messages.
Fun fact: account 0x000000....00 in Eth1 has 3M USD in balance from transfers made, most certainly, by mistake (or poor UX of wallets). Let's remove this footgun from our system.
There are various footguns possible, and we have a trade-off to make about how much complexity to add inside our systems in order to prevent avoidable misuse outside.In general, I would prefer to minimise complexity inside in order to maximise our chances of it being correct. But there are definitely some cases worth trading.
This proposal won't prevent value being sent to places from where it can't be retrieved in general, although since address 0x000..00 is an ID address of the system actor, it could prevent that particular case. There is not a specific use case for any of the current singleton actors receiving a bare send. Although if we simply re-addresses our singletons such that the burnt funds actors was ID 0, we could call it working as intended!
The burnt funds actor (ID 99) is a singleton account actor, but I presume we still wish to allow sending to it. So I think the predicate being proposed is to disallow method zero on actors with ID addresses between 0 and 98, inclusive. If we do this, we will preclude any future singleton actor that might have a legitimate use case for receiving value; such an actor would have to implement a no-op method other than 0 in order to receive value.
There's a question about what "prevent" means. This rule should probably apply to all sends (including internal, between actors, from multisigs, from payment channels, etc), which means it's not a syntactic or semantic validity check, but specific behaviour implemented inside the VM. So "prevent" means the VM checks against the receiver blacklist and aborts the call with some non-zero exit code.
A more flexible, but slightly more disruptive, approach would be to allow/require actors to "implement" method zero with code, in which case we could code all our singletons to reject sends without limiting future abilities.
In our current mode of convergence, we are declining all but the most necessary changes in behaviour. I don't think this is must have for mainnet, but could be convinced otherwise.
cc @wadealexc, @whyrusleeping, @ZenGround0
Ethereum's 0x00...00 address is often the recipient of mistakenly-sent funds, yes, but it's also widely used as a "burn" address. I think it's likely that, even with an explicitly-marked "burnt funds actor" at ID 99, people may still end up burning via 0 as they currently do in Ethereum.
I'm in favor of just making the burnt funds actor ID 0, and not changing anything else (for simplicity's sake).
If we do this, we will preclude any future singleton actor that might have a legitimate use case for receiving value; such an actor would have to implement a no-op method other than 0 in order to receive value.
Singleton system actors are meant to provide functionality to the system. I'd strongly argue that any value they receive should be in the context of a method invocation to a method that is not the implicit "bare send" method.
IMO, the cleanest way to achieve this would be to make method 0 part of actor-space, and not a special case in VM space.
All actors would then abort except for the account actor, which would just accept all callers and succeed.
I concur with your "cleanest way". I believe the special handling of 0 is part legacy (when account actors did not have any code at all) and part optimization for a common case. We need a @whyrusleeping directive to change this.