Cryptographic equivocation slashing design

There’s another effect from the lack of evidence expiration discussed above. It could make some types of accidental double signings related to testnets more likely. It’s also somewhat of an edge case, and we don’t think that it’s a big problem, but I want to write it down here.

The scenario

In this hypothetical scenario, a testnet is run with Hub validators with the chainID pion-1 (we’ve really had this testnet). Years later, with great fanfare, the Pion blockchain (doesn’t actually exist, to my knowledge) joins the Cosmos Hub as a consumer chain. What’s Pion’s chainID? You guessed it, pion-1.

Alice validated on the pion-1 testnet using her production Cosmos Hub key (bad practice, but someone might do it), then later she validated on the pion-1 consumer chain using her Cosmos Hub key, without doing a key assignment transaction (also a bad practice). Now she could be slashed, since someone could dig up two blocks at the same height with the same chainID.

Alice signed two blocks with the same key, at the same height with the same chainID. This is the canonical definition of double-signing.

Can this happen in the single chain case, right now?

Note that this is also possible right now, if Pion was a standalone chain that had run a testnet with the same chainID as production, but due to expiration of evidence in the single-chain case, the risk will only exist for a short time (around 80 days by default).

How this can be mitigated

Simple validator best practices

First of all the slashing scenario above was due to several bad practices from the validator. It could have been prevented if they had used a different key for the testnet, or if they had used a different key for the consumer chain. Basically, if you run a validator, do not use the same key for chains with the same chainID, and do not use a key so many times you forget what chainIDs you have used it on! If you use a new key for every new consumer chain you validate on, this can never happen to you (even if you use the same keys for all testnets for convenience or something).

Simple testnet best practices

Another simple mitigation is to always give testnets a chainID with the word test in it. For example pion-test-1. This may not really be necessary if validators follow the simple best practices around key management above, but it could provide an extra measure of safety.

Check consumer chain spawnTime against evidence time

Another mitigation that we may be able to get into v13 is that the Hub will not slash for evidence with a timestamp before the consumer chain in question even existed. This is very easy to check and will prevent the scenario above. It will not prevent a similar scenario where the testnet is run after the consumer chain is started, but it will allow validators to apply the simple rule “never validate on a testnet with the same chainID as a consumer chain”.

1 Like