mirror of
https://github.com/status-im/EIPs.git
synced 2025-01-27 07:05:47 +00:00
EIP 2124: add chain divergence special cases to the verifier (#2331)
This commit is contained in:
parent
ac1a50936c
commit
8b329558df
@ -60,39 +60,40 @@ The *fork identifier* is defined as `RLP([FORK_HASH, FORK_NEXT])`. This `forkid`
|
||||
|
||||
#### Validation rules
|
||||
|
||||
1) If local and remote `FORK_HASH` matches, connect.
|
||||
- The two nodes are in the same fork state currently. They might know of differing future forks, but that's not relevant until the fork triggers (might be postponed, nodes might be updated to match).
|
||||
2) If the remote `FORK_HASH` is a subset of the local past forks and the remote `FORK_NEXT` matches with the locally following fork block number, connect.
|
||||
- Remote node is currently syncing. It might eventually diverge from us, but at this current point in time we don't have enough information.
|
||||
3) If the remote `FORK_HASH` is a superset of the local past forks and can be completed with locally known future forks, connect.
|
||||
- Local node is currently syncing. It might eventually diverge from the remote, but at this current point in time we don't have enough information.
|
||||
4) Reject in all other cases.
|
||||
- 1) If local and remote `FORK_HASH` matches, compare local head to `FORK_NEXT`.
|
||||
- The two nodes are in the same fork state currently. They might know of differing future forks, but that's not relevant until the fork triggers (might be postponed, nodes might be updated to match).
|
||||
- 1a) A remotely announced but remotely not passed block is already passed locally, disconnect, since the chains are incompatible.
|
||||
- 1b) No remotely announced fork; or not yet passed locally, connect.
|
||||
|
||||
- 2) If the remote `FORK_HASH` is a subset of the local past forks and the remote `FORK_NEXT` matches with the locally following fork block number, connect.
|
||||
- Remote node is currently syncing. It might eventually diverge from us, but at this current point in time we don't have enough information.
|
||||
- 3) If the remote `FORK_HASH` is a superset of the local past forks and can be completed with locally known future forks, connect.
|
||||
- Local node is currently syncing. It might eventually diverge from the remote, but at this current point in time we don't have enough information.
|
||||
- 4) Reject in all other cases.
|
||||
|
||||
#### Stale software examples
|
||||
|
||||
The examples below try to exhaust the fork combination possibilities that arise when nodes do not run matching software versions, but otherwise follow the same chain (mainnet nodes, testnet nodes, etc).
|
||||
|
||||
| Past forks | Future forks | Remote `FORK_HASH` | Remote `FORK_NEXT` | Connect | Reason |
|
||||
|:---:|:---:|:---:|:---:|:---:|:---:|
|
||||
| A | | A | | Yes (1) | Same forks, same sync state. |
|
||||
| A | | A | B | Yes (1) | Remote is advertising a future fork, but that is uncertain. |
|
||||
| A | B | A | | Yes (1) | Local knows about a future fork, but that is uncertain. |
|
||||
| A | B | A | B | Yes (1) | Both know about a future fork, but that is uncertain. |
|
||||
| A | B1 | A | B2 | Yes (1) | Both know about differing future forks, but those are uncertain. |
|
||||
| [A,B] | | A | B | Yes (2) | Remote out of sync. |
|
||||
| [A,B,C] | | A | B | Yes¹ (2) | Remote out of sync. Remote will need a software update, but we don't know it yet. |
|
||||
| A | B | A ⊕ B | | Yes (3) | Local out of sync. |
|
||||
| A | B,C | A ⊕ B | | Yes (3) | Local out of sync. Local also knows about a future fork, but that is uncertain yet. |
|
||||
| A | | A ⊕ B | | No (4) | Local needs software update. |
|
||||
| A | B | A ⊕ B ⊕ C | | No² (4) | Local needs software update. |
|
||||
| [A,B] | | A | | No (4) | Remote needs software update. |
|
||||
| Past forks | Future forks | Head | Remote `FORK_HASH` | Remote `FORK_NEXT` | Connect | Reason |
|
||||
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|
||||
| A | | | A | | Yes (1b) | Same forks, same sync state. |
|
||||
| A | | < B | A | B | Yes (1b) | Remote is advertising a future fork, but that is uncertain. |
|
||||
| A | | >= B | A | B | No (1a) | Remote is advertising a future fork that passed locally. |
|
||||
| A | B | | A | | Yes (1b) | Local knows about a future fork, but that is uncertain. |
|
||||
| A | B | | A | B | Yes (1b) | Both know about a future fork, but that is uncertain. |
|
||||
| A | B1 | < B2 | A | B2 | Yes (1b) | Both know about differing future forks, but those are uncertain. |
|
||||
| A | B1 | >= B2 | A | B2 | No (1a) | Both know about differing future forks, but the remote one passed locally. |
|
||||
| [A,B] | | | A | B | Yes (2) | Remote out of sync. |
|
||||
| [A,B,C] | | | A | B | Yes¹ (2) | Remote out of sync. Remote will need a software update, but we don't know it yet. |
|
||||
| A | B | | A ⊕ B | | Yes (3) | Local out of sync. |
|
||||
| A | B,C | | A ⊕ B | | Yes (3) | Local out of sync. Local also knows about a future fork, but that is uncertain yet. |
|
||||
| A | | | A ⊕ B | | No (4) | Local needs software update. |
|
||||
| A | B | | A ⊕ B ⊕ C | | No² (4) | Local needs software update. |
|
||||
| [A,B] | | | A | | No (4) | Remote needs software update. |
|
||||
|
||||
*Note, there's one asymmetry in the table, marked with ¹ and ². Since we don't have access to a remote node's future fork list (just the next one), we can't detect that it's software is stale until it syncs up. This is acceptable as 1) the remote node will disconnect from us anyway, and 2) this is a temporary fluke during sync, not permanent with a leftover node.*
|
||||
|
||||
#### Mismatching chain examples (local perspective)
|
||||
|
||||
TODO: Give some examples as to what happens if the nodes follow different forks.
|
||||
|
||||
## Rationale
|
||||
|
||||
##### Why flatten `FORK_HASH` into 4 bytes? Why not share the entire genesis and fork list?
|
||||
@ -167,8 +168,10 @@ tests := []struct {
|
||||
{4229999, ID{Hash: 0x3ea159c7, Next: 4230000}}, // Last Byzantium block
|
||||
{4230000, ID{Hash: 0x97b544f3, Next: 4939394}}, // First Constantinople block
|
||||
{4939393, ID{Hash: 0x97b544f3, Next: 4939394}}, // Last Constantinople block
|
||||
{4939394, ID{Hash: 0xd6e2149b, Next: 0}}, // First Petersburg block
|
||||
{5822692, ID{Hash: 0xd6e2149b, Next: 0}}, // Today Petersburg block
|
||||
{4939394, ID{Hash: 0xd6e2149b, Next: 6485846}}, // First Petersburg block
|
||||
{6485845, ID{Hash: 0xd6e2149b, Next: 6485846}}, // Last Petersburg block
|
||||
{6485846, ID{Hash: 0x4bc66396, Next: 0}}, // First Istanbul block
|
||||
{7500000, ID{Hash: 0x4bc66396, Next: 0}}, // Future Istanbul block
|
||||
},
|
||||
},
|
||||
// Rinkeby test cases
|
||||
@ -185,8 +188,10 @@ tests := []struct {
|
||||
{3660662, ID{Hash: 0x8d748b57, Next: 3660663}}, // Last Byzantium block
|
||||
{3660663, ID{Hash: 0xe49cab14, Next: 4321234}}, // First Constantinople block
|
||||
{4321233, ID{Hash: 0xe49cab14, Next: 4321234}}, // Last Constantinople block
|
||||
{4321234, ID{Hash: 0xafec6b27, Next: 0}}, // First Petersburg block
|
||||
{4586649, ID{Hash: 0xafec6b27, Next: 0}}, // Today Petersburg block
|
||||
{4321234, ID{Hash: 0xafec6b27, Next: 5435345}}, // First Petersburg block
|
||||
{5435344, ID{Hash: 0xafec6b27, Next: 5435345}}, // Last Petersburg block
|
||||
{5435345, ID{Hash: 0xcbdb8838, Next: 0}}, // First Istanbul block
|
||||
{6000000, ID{Hash: 0xcbdb8838, Next: 0}}, // Future Istanbul block
|
||||
},
|
||||
},
|
||||
// Goerli test cases
|
||||
@ -194,8 +199,10 @@ tests := []struct {
|
||||
params.GoerliChainConfig,
|
||||
params.GoerliGenesisHash,
|
||||
[]testcase{
|
||||
{0, ID{Hash: 0xa3f5ab08, Next: 0}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople and first Petersburg block
|
||||
{795329, ID{Hash: 0xa3f5ab08, Next: 0}}, // Today Petersburg block
|
||||
{0, ID{Hash: 0xa3f5ab08, Next: 1561651}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople and first Petersburg block
|
||||
{1561650, ID{Hash: 0xa3f5ab08, Next: 1561651}}, // Last Petersburg block
|
||||
{1561651, ID{Hash: 0xc25efa5c, Next: 0}}, // First Istanbul block
|
||||
{2000000, ID{Hash: 0xc25efa5c, Next: 0}}, // Future Istanbul block
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -233,7 +240,7 @@ tests := []struct {
|
||||
|
||||
// Local is mainnet Petersburg, remote announces Byzantium + knowledge about Petersburg. Remote
|
||||
// is simply out of sync, accept.
|
||||
{7987396, ID{Hash: 0x668db0af, Next: 7280000}, nil},
|
||||
{7987396, ID{Hash: 0xa00bc324, Next: 7280000}, nil},
|
||||
|
||||
// Local is mainnet Petersburg, remote announces Spurious + knowledge about Byzantium. Remote
|
||||
// is definitely out of sync. It may or may not need the Petersburg update, we don't know yet.
|
||||
@ -260,6 +267,16 @@ tests := []struct {
|
||||
|
||||
// Local is mainnet Petersburg, remote is Rinkeby Petersburg.
|
||||
{7987396, ID{Hash: 0xafec6b27, Next: 0}, ErrLocalIncompatibleOrStale},
|
||||
|
||||
// Local is mainnet Petersburg, far in the future. Remote announces Gopherium (non existing fork)
|
||||
// at some future block 88888888, for itself, but past block for local. Local is incompatible.
|
||||
//
|
||||
// This case detects non-upgraded nodes with majority hash power (typical Ropsten mess).
|
||||
{88888888, ID{Hash: 0x668db0af, Next: 88888888}, ErrLocalIncompatibleOrStale},
|
||||
|
||||
// Local is mainnet Byzantium. Remote is also in Byzantium, but announces Gopherium (non existing
|
||||
// fork) at block 7279999, before Petersburg. Local is incompatible.
|
||||
{7279999, ID{Hash: 0xa00bc324, Next: 7279999}, ErrLocalIncompatibleOrStale},
|
||||
}
|
||||
```
|
||||
|
||||
@ -271,15 +288,15 @@ tests := []struct {
|
||||
want []byte
|
||||
}{
|
||||
{
|
||||
ID{Hash: checksumToBytes(0), Next: 0},
|
||||
ID{Hash: 0, Next: 0},
|
||||
common.Hex2Bytes("c6840000000080"),
|
||||
},
|
||||
{
|
||||
ID{Hash: checksumToBytes(0xdeadbeef), Next: 0xBADDCAFE},
|
||||
ID{Hash: 0xdeadbeef, Next: 0xBADDCAFE},
|
||||
common.Hex2Bytes("ca84deadbeef84baddcafe"),
|
||||
},
|
||||
{
|
||||
ID{Hash: checksumToBytes(math.MaxUint32), Next: math.MaxUint64},
|
||||
ID{Hash: math.MaxUint32, Next: math.MaxUint64},
|
||||
common.Hex2Bytes("ce84ffffffff88ffffffffffffffff"),
|
||||
},
|
||||
}
|
||||
@ -287,7 +304,7 @@ tests := []struct {
|
||||
|
||||
## Implementation
|
||||
|
||||
https://github.com/ethereum/go-ethereum/pull/19738
|
||||
Geth: https://github.com/ethereum/go-ethereum/tree/master/core/forkid
|
||||
|
||||
## Copyright
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user