Mikhail Kalinin
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # The Merge. Test coverage [toc] ## Engine API ### Field encoding * [ ] [EL mock] `QUANTITY` field values are big-endians ### `engine_newPayload` * Payload with invalid `block_hash` (not equal to `Keccak256(RLP(ExecutionBlockHeader))`), might be a payload with `block_hash` computed with `ommersHash`, `difficulty`, `nonce` and `mixHash` field values set to meaningful PoW values * [ ] [CL mock] EL client *isn't* `SYNCING` * a payload with invalid `block_hash` extends canonical chain * a payload with invalid `block_hash` extends a side chain * [ ] [CL mock] EL client *is* `SYNCING` * a payload with invalid `block_hash` extends canonical chain * a payload with invalid `block_hash` extends a side chain * [ ] [CL mock] in all cases the response is `{status: INVALID_BLOCK_HASH, latestValidHash: null, validationError: errorMessage | null}` * [ ] [EL mock] in all cases CL discards a block containing a payload having an invalid `block_hash` * Payload validation * [x] [[CL mock](https://github.com/ethereum/hive/blob/7d24e9bcf30dc6546fb821848ff0c8d279a80eaa/simulators/ethereum/engine/clmock.go#L244)] `VALID` payload extends canonical chain, the response is `{status: VALID, latestValidHash: payload.blockHash, validationError: null}` * `INVALID` payload extends canonical chain * [x] [[CL mock](https://github.com/ethereum/hive/blob/7d24e9bcf30dc6546fb821848ff0c8d279a80eaa/simulators/ethereum/engine/enginetests.go#L695)] the response is `{status: INVALID, latestValidHash: invalidPayload.parentHash, validationError: errorMessage | null}` * [ ] [CL mock] `INVALID` payload isn't available via JSON-RPC request * [ ] [CL mock + Network sim] `INVALID` payload isn't available via Eth network protocol requests * [ ] [EL mock] CL discarded a block with `INVALID` payload * while EL is `SYNCING` * send payloads `P0 <- INV_P <- P1` to EL, where `INV_P` is an `INVALID` payload from canonical chain, wait when `INV_P` is processed by EL and check the response to `newPayload(P1)`: * [ ] [[CL mock + Networking](https://github.com/ethereum/hive/blob/7d24e9bcf30dc6546fb821848ff0c8d279a80eaa/simulators/ethereum/engine/enginetests.go#L757)] the response MUST be `{status: INVALID, latestValidHash: P0.blockHash, validationError: errorMessage | null}` * [ ] [EL mock] CL discards a subchain starting from a block containing `INV_P`, and re-orgs to a valid chain, consider a test with multiple competing valid chains * [ ] [CL mock] re-org to already synced chain and send a valid payload that extends the synced chain, check that response is `{status: VALID, latestValidHash: payload.blockHash, validationError: null}` * [ ] [CL mock] The head isn't changed if `newPayload(P)` is successfully processed where `P` extends canonical chain ### `engine_forkchoiceUpdated` * `headBlockHash` refers to a payload from canonical chain * [ ] [CL mock] `headBlockHash` is updated * [ ] [CL mock] the response is `{payloadStatus: {status: VALID, latestValidHash: forkchoiceState.headBlockHash, validationError: null}, payloadId: null}` * `headBlockHash` refers to a payload from a side chain; wait for re-org to happen (might need polling if `engine_forkchoiceUpdated` has been responded with `SYNCING`) * [ ] [CL mock] `headBlockHash` is updated * [ ] [CL mock] the response is `{payloadStatus: {status: VALID, latestValidHash: forkchoiceState.headBlockHash, validationError: null}, payloadId: null}` * `safeBlockHash` is updated * [ ] [CL mock] when `safeBlockHash` refers to a payload from canonical chain * [ ] [CL mock] when `safeBlockHash` refers to a payload from side chain (re-org to a side chain happens) * [ ] [CL mock] `finalizedBlockHash` is updated * [ ] [[CL mock](https://github.com/ethereum/hive/pull/527)] `payloadAttributes.timestamp <= headBlock.timestamp` * forkchoice state is applied * error is returned * while EL is `SYNCING` * send payloads `P0 <- INV_P <- P1` to EL, where `INV_P` is an `INVALID` payload from canonical chain, wait when `INV_P` is processed by EL and check EL response to `forkchoiceUpdated(headBlockHash=P1.blockHash)`: * [ ] [CL mock + Networking] the response MUST be `{payloadStatus: {status: INVALID, latestValidHash: P0.blockHash, validationError: errorMessage | null}, payloadId: null}` * [ ] [EL mock] CL discards a subchain starting from a block containing `INV_P`, and re-orgs to a valid chain, consider a test with multiple competing valid chains * [ ] [CL mock] send a chain of payloads, wait for sync to finish by polling `forkchoiceUpdated` and check `finalized`, `safe` and `head` blocks are updated ### `engine_getPayload` * [ ] [CL mock] responds `-32001: Unknown payload` to the call with random `payloadId` * [[CL mock](https://github.com/ethereum/hive/blob/7d24e9bcf30dc6546fb821848ff0c8d279a80eaa/simulators/ethereum/engine/clmock.go#L295)] build process * [ ] initiate build process by sending `forkchoiceUpdated` with payload attributes and check that response is `{payloadStatus: {status: VALID, latestValidHash: forkchoiceState.headBlockHash, validationError: null}, payloadId: buildProcessId}`, remember `buildProcessId` * [ ] wait for a bit and send `getPayload(payloadId=buildProcessId)`, check that reponse contains a payload with expected field values (all from payload attributes: `timestamp`, `prevRandao`, `suggestedFeeRecipient` + `parentHash` and some other fields that make sense to check) * [ ] make `newPayload(P)` call where `P` is recently built payload, the response MUST be `{status: VALID, latestValidHash: payload.blockHash, validationError: null}` * [ ] [Engine API fuzzer] fuzz `getPayload` immediately followed by `forkchoiceUpdated` with initiated build process, `getPayload` MUST response correctly ### `engine_exchangeTransitionConfiguration` Less of a priority. * [ ] [CL mock] check `terminalTotalDifficulty` is correct * [ ] [CL mock] check `terminalBlockHash` override scenario (all three fields have correct values) ### Sync * [ ] [CL mock] `newPayload` is responsded with `{status: SYNCING, latestValidHash: null, validationError: null}` if the payload extends the canonical chain and requisite data for its validation is missing * `forkchoiceUpdated` is responded with `{payloadStatus: {status: SYNCING, latestValidHash: null, validationError: null}, payloadId: null}` if `forkchoiceState.headBlockHash` references: * [x] [[CL mock](https://github.com/ethereum/hive/blob/7d24e9bcf30dc6546fb821848ff0c8d279a80eaa/simulators/ethereum/engine/enginetests.go#L352)] an unknown payload * [ ] [CL mock] a payload that can't be validated because requisite data for the validation is missing ### Message ordering * [ ] [CL mock + Engine API fuzzer] Excectuion layer processes `forkchoiceUpdated` calls in the same order as they have been made -- might be better checked by fuzzer * [ ] [EL mock + CL fuzzer] Consensus layer makes `forkchoiceUpdated` calls respecting the order of fork choice updates in the fork choice store -- hard to test, less of a priority ### Timeouts * [ ] [EL mock] Method call timeout on CL side is as expected; for this check we need an agreement on the timeout, probably documented in the spec. May require calling to every method -- Not sure if it worth checking ### `eth` namespace Less of a priority. ### Authentication Less of a priority. ## Transition * TTD case * [[CL mock](https://github.com/ethereum/hive/blob/7d24e9bcf30dc6546fb821848ff0c8d279a80eaa/simulators/ethereum/engine/mergetests.go)] propose on top of a valid terminal block; send `engine_forkchoiceUpdated(headhBlockHash: TB.blockHash)` and run the following checks: * [x] EL left PoW and is in the transition mode * [x] EL's head is set to `headBlockHash` * [x] payload build process has begun * [ ] payload has been built successfully and is accepted by EL client, ensure that: * `ommersHash == 0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347` * `difficulty == 0` * `mixHash == prevRandao` * `nonce == 0x0000000000000000` * [[CL mock](https://github.com/ethereum/hive/blob/7d24e9bcf30dc6546fb821848ff0c8d279a80eaa/simulators/ethereum/engine/enginetests.go#L195)] propose on top of an invalid terminal block; send `engine_forkchoiceUpdated(headhBlockHash: INV_TB.blockHash)` * [x] EL responds with `{status: INVALID_TERMINAL_BLOCK, latestValidHash: null, validationError: errorMessage | null}` * [ ] EL didn't change its head to `INV_TB.blockHash` * [ ] EL didn't leave PoW * do all above checks when: * [x] `INV_TB.TD < TTD` * [ ] `INV_TB.parent.TD >= TTD` * do all above checks when: * [ ] `INV_TB`'s PoW seal is invalid * [ ] `INV_TB` is invalid according to EE rules * [x] [CL mock] transition on a valid chain in lock-step 1. send `newPayload(P)`, where `TB <- P` and `TB` is a valid terminal block, and `P` is a valid payload following Block structure, Block validity, Block and ommer rewards section of [EIP-3675](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3675.md) * [ ] EL responds with `{status: VALID, latestValidHash: payload.blockHash, validationError: null}` * [ ] EL hasn't left PoW * [ ] EL's head points to `TB` 1. send `forkchoiceUpdated(headBlockHash: P.blockHash)` * [ ] EL responds with `{payloadStatus: {status: VALID, latestValidHash: forkchoiceState.headBlockHash, validationError: null}, payloadId: null}` * [ ] EL left PoW * [ ] EL's head points to `P` * [ ] Get `safe` block responded with error * [ ] Get `finalized` block responded with error 1. Let the chain justify the first payload (beacon block that has a payload) * [ ] EL's head is as expected * [ ] `safe` block points to the justified payload * [ ] Get `finalized` block responds with error 1. Let the chain finalize the first payload (beacon block that has a payload) * [ ] EL's head is as expected * [ ] `safe` block is as expected * [ ] Get `finalized` block points to the finalized payload * [x] [[CL mock](https://github.com/ethereum/hive/blob/8e78b1e5803bd67f726d8e071bcb11155c2c8e7a/simulators/ethereum/engine/mergetests.go#L90)] Same scenario with two valid terminal blocks `A` and `B` where `A` is the head of the PoW chain according to EL's observation and `P` (a transition payload) is ancestor of `B`. * [x] [CL mock] Same scenario with missed `forkchoiceUpdated(P)` 1. Send `newPayload(P)` 1. Send `newPayload(P1)`, where `P <- P1` 1. Send `forkchoiceUpdated(P1)` * [x] [CL mock] Same scenario with two valid chains that goes beyond the transition and a re-org: `TB1 <- P0 <- P1` and `TB2 <- P0' <- P1'` * [x] [CL mock] Same scenario with `P` having a transaction deploying a contract that uses `PREVRANDAO` and a transaction that triggers this opcode call and stores the return value into the state 1. Make the transition happen on `P1`, i.e. `P1` must become the head 2. Send `newPayload(P0') + forkchoiceUpdated(P0')` 3. And so on, i.e. continue to build on top of `P1'` -- it must become canonical chain * [x] transition on an invalid chain in lock-step * send `newPayload(P)` where `INV_TB <- P` and `INV_TB` is an invalid terminal block * [x] [[CL mock](https://github.com/ethereum/hive/blob/7d24e9bcf30dc6546fb821848ff0c8d279a80eaa/simulators/ethereum/engine/enginetests.go#L230)] EL responds with `{status: INVALID_TERMINAL_BLOCK, latestValidHash: null, validationError: errorMessage | null}` * [CL mock] do the above check when: * [x] `INV_TB.TD < TTD` * [ ] `INV_TB.parent.TD >= TTD` * [CL mock] do the above check when: * [ ] `INV_TB`'s PoW seal is invalid * [ ] `INV_TB` is invalid according to EE rules * [x] [CL mock] transition on an invalid chain in lock-step with re-org 1. Send `newPayload(P)` where `TB <- P`, and `TB` is a valid terminal block 1. Send `forkchocieUpdated(P)` * [ ] check that transition has happened 1. Send `newPayload(P')` where `INV_TB <- P'` 1. Send `forkchoiceUpdated(P')` * [ ] the head must still point to `P` * run the above scenario when: * [ ] `INV_TB.TD < TTD` * [ ] `INV_TB.parent.TD >= TTD` * run the above scenario when: * [ ] `INV_TB`'s PoW seal is invalid * [ ] `INV_TB` is invalid according to EE rules * [x] [CL mock] Above scenario with invalid transition payload, i.e. there are two chain `TB <- P0 <- P1` and `TB <- INV_P0' <- P1'`, where `INV_P0'` is a payload that is invalid according to EE rules * [ ] after submitting an invalid chain to EL via `newPayload` and subsequent `forkchoiceUpdated(P1')` the head must still point to `P1` * [x] [CL mock + Networking] transition on a valid chain through `SYNCING` 1. Make EL `SYNCING` with `TB <- P0 <- P1 <- P2 <- ... <- Pn` by submitting `newPayload(Pn) + forkchoiceUpdated(Pn)`; EL must not know the chain starting from `TB` and must pull it from a remote peer 1. Wait until EL sync is done by polling `forkchoiceUpdated`, and check: * [ ] EL left PoW * [ ] EL's head points to `Pn` * [ ] Repeate the scenario with long enough chain that finalizes the transition and check: * [ ] EL left PoW * [ ] EL's head points to `Pn` * [ ] `safe` block is as expected * [ ] `finalized` block is as expected * [x] [CL mock + Networking] transition on an invalid chain through `SYNCING` 1. Make EL `SYNCING` with `INV_TB <- P0 <- P1 <- P2 <- ... <- Pn` by submitting `newPayload(Pn) + forkchoiceUpdated(Pn)`; EL must not know the chain starting from `INV_TB` and must pull it from a remote peer 1. Wait until EL sync is *stopped* by polling `forkchoiceUpdated`, and check: * [ ] EL responded with `{payloadStatus: {status: INVALID_TERMINAL_BLOCK, latestValidHash: null, validationError: errorMessage | null}, payloadId: null}` * [ ] EL didn't leave PoW * [ ] EL's head didn't change * run the above scenario when: * [ ] `INV_TB.TD < TTD` * [ ] `INV_TB.parent.TD >= TTD` * run the above scenario when: * [ ] `INV_TB`'s PoW seal is invalid * [ ] `INV_TB` is invalid according to EE rules * Above scenario with `TB <- INV_P0 <- P1 <- P2 <- ... <- Pn` chain, where `TB` is a valid terminal block, `INV_P0` is an invalid payload of a transition block, checks: * [ ] EL responded with `{payloadStatus: {status: INVALID, latestValidHash: ?????, validationError: errorMessage | null}, payloadId: null}` * [ ] EL didn't leave PoW * [ ] EL's head didn't change * Above scenario with `TB <- P0 <- INV_P1 <- P2 <- ... <- Pn` chain, where `TB` is a valid terminal block, `INV_P0` is an invalid payload of a transition block, checks: * [ ] EL responded with `{payloadStatus: {status: INVALID, latestValidHash: P0.blockHash, validationError: errorMessage | null}, payloadId: null}` * [ ] EL left PoW * [ ] EL's head points to `P0` * [x] [CL mock + Networking] transition on invalid chain through `SYNCING` and re-org 1. Make EL import a valid chain `A: TB <- P0 <- P1 <- P2 <- ... <- Pn` chain, check: * [ ] EL left PoW * [ ] EL's head points to `Pn` 1. Make EL `SYNCING` with `B: INV_TB <- P0 <- P1 <- P2 <- ... <- Pn` by submitting `newPayload(Pn) + forkchoiceUpdated(Pn)`; EL must not know the chain starting from `INV_TB` and must pull it from a remote peer 1. Wait until EL sync is *stopped* by polling `forkchoiceUpdated`, and check: * [ ] EL responded with `{payloadStatus: {status: INVALID_TERMINAL_BLOCK, latestValidHash: null, validationError: errorMessage | null}, payloadId: null}` * [ ] EL's head points to `A_Pn` * run the above scenario when: * [ ] `INV_TB.TD < TTD` * [ ] `INV_TB.parent.TD >= TTD` * run the above scenario when: * [ ] `INV_TB`'s PoW seal is invalid * [ ] `INV_TB` is invalid according to EE rules * Above scenario with `B: TB <- INV_P0 <- P1 <- P2 <- ... <- Pn` chain, where `B_TB` is a valid terminal block, `INV_P0` is an invalid payload of a transition block, checks: * [ ] EL responded with `{payloadStatus: {status: INVALID, latestValidHash: ?????, validationError: errorMessage | null}, payloadId: null}` * [ ] EL's head points to `A: Pn` * Above scenario with `B: TB <- P0 <- INV_P1 <- P2 <- ... <- Pn` chain, where `B_TB` is a valid terminal block, `INV_P0` is an invalid payload of a transition block, checks: * [ ] EL responded with `{payloadStatus: {status: INVALID, latestValidHash: B_P0.blockHash, validationError: errorMessage | null}, payloadId: null}` * [ ] EL's head points to `B_P0` * [x] [CL mock] All the above scenarios adopted to `TERMINAL_BLOCK_HASH` override * [x] Additionally, check that transition succeedes when a `TB` with `TERMINAL_BLOCK_HASH` is not the head of PoW chain according to the TD rule, i.e. there is another block that is heavier than the one with `TERMINAL_BLOCK_HASH` and even having a higher block number * [x] [EL mock] All the above scenarios checking CL client on real beacon chain and EL chain data * [ ] CL discards all blocks starting from a transition block if terminal block is invalid * [ ] `safe_block_hash == justified_payload.block_hash` * [ ] [EL mock] `TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH` * [ ] early proposal test case * [ ] processing early proposed block case during lock-step and while `SYNCING` * [x] [CL mock + Networking] EL stops processing descendants of a terminal block received from gossip. Consider a PoW chain: `Genesis <- B0 <- ... <- Bi <- TB <- TB0 <- TB1`, where `TB` is a valid terminal block * TTD case 1. Send all blocks up to and including `TB` to a peer via `NewBlock` ETH subprotocol messsages * [ ] the head points to `TB` 1. Send `NewBlock(TB0)` to a peer * [ ] the head points to `TB` 1. Repeat the same with `TERMINAL_BLOCK_HASH = TB.blockHash` * [x] [CL mock + Networking] `TERMINAL_BLOCK_HASH` case with longer chain: EL stops processing descendants of a terminal block received from gossip. Consider a PoW chain: `Genesis <- B0 <- ... <- Bi <- TB <- TB0 <- TB1`, where `TB` is a valid terminal block 1. Make client import the chain up to and including `TB0` 1. Restart a client with `TERMINAL_BLOCK_HASH = TB.blockHash`, `TTD = TB.totalDifficulty`, `TERMINAL_BLOCK_NUMBER` set accordingly 1. Send `NewBlock(TB1)` to a peer * [ ] the head doesn't point to `TB1` -- the override has been applied retroactively and clients may not remove previously imported but presently invalid `TB0` from the canonical chain * [x] [CL mock + Networking] EL stops processing descendants of a terminal block received while syncing. Consider a PoW chain: `Genesis <- B0 <- ... <- Bi <- TB <- TB0 <- TB1`, where `TB` is a valid terminal block 1. Make EL client sync with a remote peer advertising the above chain * [ ] the head points to `TB` * [x] [CL mock + Networking] `NewBlock` and `NewBlockHashes` checks 1. Start the transition by submitting a transition payload `P`, where `TB <- P` and `TB` is a valid terminal block 1. Send `NewBlock(TB')` to a peer, where `TB'` is also a valid terminal block * [ ] a peer propagates `NewBlock(TB')` 1. Send `NewBlock(TB0')`, where `TB' <- TB0'` * [ ] a peer does not propagate `NewBlock(TB0')` 1. Finalize transition 1. Send `NewBlock(TB')` to a peer, where `TB''` is yet another valid terminal block * [ ] a peer does not propagate `NewBlock(TB'')` * [x] [[CL mock](https://github.com/ethereum/hive/blob/7d24e9bcf30dc6546fb821848ff0c8d279a80eaa/simulators/ethereum/engine/enginetests.go#L1546)] Node is bootstrapped from scratch after the merge has happened and synced successfully ### Test scenarios by @matt and @marioevz * Network partitioning with different portions of stake * https://hackmd.io/@matt/HyH46iOhY * EL client disruption * https://github.com/marioevz/merge-testnet-testcases * https://notes.ethereum.org/0cZdht4sTW-EaoUIU_eF_A ### Raw checks from Engine API spec * `engine_newPayload` * terminal block is invalid * [x] [[hive test](https://github.com/ethereum/hive/blob/7d24e9bcf30dc6546fb821848ff0c8d279a80eaa/simulators/ethereum/engine/enginetests.go#L230)] a payload is a child of a terminal block that doesn't meet terminal block conditions * [ ] a payload is a child of a terminal block that is `INVALID` with respect to * [ ] PoW seal * [ ] EE rules * [ ] a payload of transition block is `INVALID` with respect to EE rules * [ ] EL was `SYNCING` and during the sync it's been fed with `INV_TB <- P1`, where `INV_TB` is invalid terminal block and `P1` is a transition payload built on top of this block. Then EL receives `newPayload(P2)`, where `P2` is a child of `P1` and MUST respond with `INVALID_TERMINAL_BLOCK` * [ ] check TTD condition * [ ] check `TERMINAL_BLOCK_HASH` override condition * [ ] is responded with `{status: INVALID_TERMINAL_BLOCK, latestValidHash: null, validationError: errorMessage | null}` * [ ] EL was `SYNCING` and during the sync it's been fed with `TB <- INV_P1`, where `INV_P1` is `INVALID` payload of a transition block. Then EL receives `forkchoiceUpdated(INV_P1)` -- transition MUST NOT happen * [ ] CL Discards blocks starting from a transition block if receives `INVALID_TERMINAL_BLOCK` * valid terminal block * [ ] no transition must happen until `forkchoiceUpdated` has been called * `engine_forkchoiceUpdated` * `safeBlockHash` is zeroes * [ ] `safe` block requested via JSON-RPC is responded with error * `finalizedBlockHash` is zeroes * [ ] `finalized` block requested via JSON-RPC is responded with error * references an invalid terminal block * [x] [[hive test](https://github.com/ethereum/hive/blob/7d24e9bcf30dc6546fb821848ff0c8d279a80eaa/simulators/ethereum/engine/enginetests.go#L195)] send `forkchoiceState.headBlockHash` that references a terminal block that doesn't satisfy terminal block conditions; EL must return `{payloadStatus: {status: INVALID_TERMINAL_BLOCK, latestValidHash: null, validationError: errorMessage | null}, payloadId: null}` * [ ] check that EL is still on PoW and transition hasn't begun * [ ] the same checks with `TERMINAL_BLOCK_HASH` override * [[hive test](https://github.com/ethereum/hive/blob/7d24e9bcf30dc6546fb821848ff0c8d279a80eaa/simulators/ethereum/engine/mergetests.go)] references a valid terminal block * [x] build process has begun * [x] EL started the transition and left PoW * [x] EL's head is set to `headBlockHash` * [ ] two terminal blocks: `A` is the head to EL node's observation (`A` has the biggest TD), `B` is not; after a call with `headBlockHash = A.block_hash`, the head points to `A` * [ ] check with `TERMINAL_BLOCK_HASH` override * payload validation * [ ] EL was `SYNCING` and during the sync it's been fed with `INV_TB <- P1`, where `INV_TB` is invalid terminal block and `P1` is a transition payload built on top of this block. Then EL receives `forkchoiceUpdated(P1)` and MUST respond with `INVALID_TERMINAL_BLOCK` * [ ] no transition must happen * [ ] CL discards blocks starting from a transition block if receives `INVALID_TERMINAL_BLOCK` ### Raw checks from EIP-3675 * PoW blocks that are descendants of any terminal PoW block MUST NOT be imported * Received from gossip * Received from a remote peer while syncing * Beginning with `TRANSITION_BLOCK` * a number of previously dynamic block fields are deprecated by enforcing these values to instead be constants * `ommersHash == 0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347` * `difficulty == 0` * `mixHash == prevRandao` * `nonce == 0x0000000000000000` * The length of the block's extraData MUST be less than or equal to `MAX_EXTRA_DATA_BYTES` bytes * PoW seal isn't verified anymore * As of the first `POS_FORKCHOICE_UPDATED` event, the fork choice rule MUST be altered in the following way: * Remove the existing PoW heaviest chain rule * Adhere to the new PoS LMD-GHOST rule * Consider the chain starting at genesis and ending with the head block nominated by the event as the canonical blockchain. * Set the head of the canonical blockchain to the corresponding block nominated by the event. * Beginning with the `FIRST_FINALIZED_BLOCK`, set the most recent finalized block to the corresponding block nominated by the event * Networking * Nodes MUST set the `FORK_NEXT` parameter to the `FORK_NEXT_VALUE` * Beginning with receiving the `FIRST_FINALIZED_BLOCK`, the networking stack MUST discard the following ingress messages: * NewBlockHashes (0x01) * NewBlock (0x07) * Security Considerations. Transition process * A scenario with long PoW chain having TB in the middle with `TERMINAL_BLOCK_HASH` override * Temporal network partitioning during transition with different portions of stake on each partition and two terminal blocks that the network jumps between ### Raw checks from EIP-4399 * Beginning with `TRANSITION_BLOCK`, client software MUST set the value of the `mixHash`, i.e. the field with the number 13 (0-indexed) in a block header, to the latest RANDAO mix of the post beacon state of the previous block * Beginning with `TRANSITION_BLOCK`, the `DIFFICULTY (0x44)` instruction MUST return the value of the `mixHash` field ### Raw checks from Consensus specs * `validate_merge_block` * `TERMINAL_BLOCK_HASH` + `TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH` * `is_valid_terminal_pow_block` * `block.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY` * `parent.total_difficulty < TERMINAL_TOTAL_DIFFICULTY` * ... ## EIP-3675 * Block structure and validity * [ ] PoS blocks with `ommersHash != Keccak256(RLP([]))`, `difficulty != 0`, `nonce != 0x0000000000000000`, `len(extraData) > MAX_EXTRA_DATA_BYTES` are considered invalid * [ ] Block rewards aren't added to `beneficiary` account starting with `TRANSITION_BLOCK` * [ ] Client software adheres to PoS LMD-GHOST rule * Head and finalized blocks are set according to the recent `POS_FORKCHOICE_UPDATED` event * No fork choice state is updated unless `POS_FORKCHOICE_UPDATED` event is received * [ ] Transition process * Client software doesn't process any PoW block beyond a terminal block * Beginning with `TRANSITION_BLOCK`, client software applies new block validity rules * Beginning with the first `POS_FORKCHOICE_UPDATED` client software switched its fork choice rule to PoS LMD-GHOST * `TRANSITION_BLOCK` must be a child of a terminal PoW block * `NewBlockHashes (0x01)` and `NewBlock (0x07)` network messages are discarded after receiving the `FIRST_FINALIZED_BLOCK` ## EIP-4399 * [ ] Main scenario * In one of ancestors of `TRANSITION_BLOCK` deploy a contract that stores return value of `DIFFICULTY (0x44)` to the state * Check that value returned by `DIFFICULTY (0x44)` in transaction executed within the parent of `TRANSITION_BLOCK` equals `difficulty` field value * Check that value returned by `PREVRANDAO (0x44)` in transaction executed within `TRANSITION_BLOCK` equals `prevRandao` field value ## Consensus specs * Beacon chain * [x] `is_merge_transition_complete` * [x] `is_merge_transition_block` * [x] `is_execution_enabled` * [x] if `is_execution_enabled` call to `process_execution_payload` * [x] `process_execution_payload` * [x] `notify_new_payload` is called * [x] `assert payload.parent_hash == ...` * [x] `assert payload.prev_randao == ...` * [x] `assert payload.timestamp == ...` * [x] `assert execution_engine.notify_new_payload(payload)` * [x] `state.latest_execution_payload_header = ExecutionPayloadHeader(...)` * [x] `compute_timestamp_at_slot` * Modified in Bellatrix * [x] `get_inactivity_penalty_deltas` * [x] `slash_validator` * [x] `process_slashings` * Fork choice * [x] `is_valid_terminal_pow_block` * [x] `validate_merge_block` * [x] [Covered by Transition test cases] `notify_forkchoice_updated` * `finalized_block_hash = Hash32()` before transition finalized * `finalized_block_hash = store.blocks[store.finalized_block_hash.root].body.execution_payload.block_hash` after transition finalized * `safe_block_hash = Hash32()` before transition justified * `safe_block_hash = store.blocks[store.justified_checkpoint.root].body.execution_payload.block_hash` after transition justified * [x] [Covered by Transition test cases] `on_block` * calls `validate_merge_block` if `is_merge_transition_block` * `notify_forkchoice_updated` is called * [x] Fork (network upgrade) * [x] [Covered by Transition test cases] Validator * `get_pow_block_at_terminal_total_difficulty` * `get_terminal_pow_block` * `prepare_execution_payload` * `get_execution_payload` ## Optimistic sync * [ ] [EL mock] `is_optimistic_candidate_block` * The parent of the block has execution enabled * The current slot (as per the system clock) is at least `SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY` ahead of the slot of the block being imported * [ ] [EL mock] When a "merge block" (i.e. the first block which enables execution in a chain) is declared to be `VALID` by an execution engine (either directly or indirectly), the full `validate_merge_block` MUST be run against the merge block. * [ ] A subtree of blocks starting from the merge block is discarded if merge block is invalid * [ ] [EL mock] If `TERMINAL_BLOCK_HASH` override is activated assertions from `validate_merge_block` MUST prevent an optimistic import * [ ] [EL mock] MUST not optimistically import `INVALID` blocks * [ ] [EL mock] MUST not optimistically import block if EL didn't respond to `newPayload` * [EL mock] Optimistic VC (may be tested via Validator API interface) * [ ] MUST NOT produce a block * [ ] MUST NOT participate in attestation * [ ] MUST NOT participate in sync committees * [EL mock] Optimistic BN * `execution_optimistic` flag is set in API in the response to queries over optimistic block

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully