Parity-ethereum: Stage 1 block verification failed for c913…53da: Block(InvalidProofOfWork(OutOfBounds { min: Some(307293), max: None, found: 307292 }))

Created on 13 Apr 2018  ·  11Comments  ·  Source: openethereum/parity-ethereum

Parity node stops syncing with block verification error:

2018-04-12 19:28:23 UTC Imported #307711 1f51…966a (0 txs, 0.00 Mgas, 0.97 ms, 0.52 KiB)
2018-04-12 19:28:30 UTC Stage 1 block verification failed for c913…53da: Block(InvalidProofOfWork(OutOfBounds { min: Some(307293), max: None, found: 307292 }))
2018-04-12 19:28:33 UTC    2/25 peers      5 MiB chain   21 KiB db  0 bytes queue    3 MiB sync  RPC:  0 conn,  0 req/s, 275 µs

I'm running:

  • Which Parity version?: 1.9.5
  • Which operating system?: Linux
  • How installed?: official docker images
  • Are you fully synchronized?: yes
  • Which network are you connected to?: local network
  • Did you try to restart the node?: yes, after restart I still get:
2018-04-13 10:22:12 UTC Stage 1 block verification failed for c913…53da: Block(InvalidProofOfWork(OutOfBounds { min: Some(307293), max: None, found: 307292 }))

I got this issue two times with brand new local chains. First time it happened around 100000 block. Then I simply started new chain and it happend again on block 307711. Network runs a few latest stable version Geth nodes and a single latest stable Parity node (various stable versions of both Geth and Parity nodes as chains runs for a few months and I upgrade once new is released).

I don't know any easy way to reproduce it.

M2-config 📂 Z1-question 🙋‍♀️

Most helpful comment

Parity's PoW validation is wrong.

    /// Convert an Ethash boundary to its original difficulty. Basically just `f(x) = 2^256 / x`.
    pub fn boundary_to_difficulty(boundary: &H256) -> U256 {
        let d = U256::from(*boundary);
        if d <= U256::one() {
            U256::max_value()
        } else {
            ((U256::one() << 255) / d) << 1
        }
    }

    /// Convert an Ethash difficulty to the target boundary. Basically just `f(x) = 2^256 / x`.
    pub fn difficulty_to_boundary(difficulty: &U256) -> H256 {
        if *difficulty <= U256::one() {
            U256::max_value().into()
        } else {
            (((U256::one() << 255) / *difficulty) << 1).into()
        }
    }

Both these calculations truncate the last bit. This means, that blocks with odd difficulty values get validated by Parity as if the difficulty was one less. This is the reason why the blocks are rejected.

Go repro:

package main

import (
    "fmt"
    "math/big"
)

func main() {
    difficulty := int64(307293)
    fmt.Printf("Source difficulty: %v\n", difficulty)

    // Geth
    two256 := new(big.Int).Exp(big.NewInt(2), big.NewInt(256), big.NewInt(0))
    fmt.Printf("Geth diff->boundary->diff: %v\n", new(big.Int).Div(two256, new(big.Int).Div(two256, big.NewInt(difficulty))))

    // Parity
    boundary := big.NewInt(1)
    boundary.Lsh(boundary, 255)
    boundary.Div(boundary, big.NewInt(difficulty))
    boundary.Lsh(boundary, 1)

    diff := big.NewInt(1)
    diff.Lsh(diff, 255)
    diff.Div(diff, boundary)
    diff.Lsh(diff, 1)

    fmt.Printf("Parity diff->boundary->diff: %v\n", diff)
}
Source difficulty: 307293
Geth diff->boundary->diff: 307293
Parity diff->boundary->diff: 307292

Ping @5chdn @folsen

All 11 comments

That's clearly a consensus issue between Geth and Parity.

How did you configure the chains?

Thanks @5chdn , I used pretty much standard Puppeth setup. I believe if you try to setup it and leave it for prolonged periods sooner or later you should get the same problem.

BTW, only one Geth node was mining in the entire network.

I'm having this same issue as well. Using Parity/v1.10.2-beta OSX as well as 1.9.4 alpine in docker

geth genesis.json

{
    "config": {
        "chainId": 8675,
        "homesteadBlock": 0,
        "eip150Block": 0,
        "eip155Block": 0,
        "eip158Block": 0,
        "eip160Block": 0
    },
    "coinbase": "0x0000000000000000000000000000000000000000",
    "difficulty": "0x400",
    "extraData": "",
    "gasLimit": "0x2fefd8",
    "nonce": "0x0000000000000711",
    "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "timestamp": "0x00",
    "alloc": {}
}

parity genesis file

{
    "name": "Private TestNet",
    "engine": {
      "Ethash": {
        "params": {
          "gasLimitBoundDivisor": "0x400",
          "minimumDifficulty": "0x20000",
          "difficultyBoundDivisor": "0x800",
          "durationLimit": "0xd",
          "blockReward": "0x4563918244F40000",
          "registrar": "0x81a4b044831c4f12ba601adb9274516939e9b8a2",
          "homesteadTransition": 0,
          "eip150Transition": 0,
          "eip155Transition": 0,
          "eip160Transition": 0,
          "eip161abcTransition": 0,
          "eip161dTransition": 0
        }
      }
    },
    "params": {
      "accountStartNonce": "0x0",
      "maximumExtraDataSize": "0x20",
      "minGasLimit": "0x1388",
      "networkID": 8675,
      "chainID": 8675,
      "eip98Transition": 9223372036854775807,
      "gasLimitBoundDivisor": "0x0400"
    },
    "genesis": {
      "seal": {
        "ethereum": {
          "nonce": "0x0000000000000711",
          "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
        }
      },
      "difficulty": "0x400",
      "author": "0x0000000000000000000000000000000000000000",
      "timestamp": "0x00",
      "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
      "extraData": "",
      "gasLimit": "0x2fefd8"
    },
    "accounts": {}
  }

After I get the following message:

Stage 1 block verification failed for 50b9…77b4: Block(InvalidProofOfWork(OutOfBounds { min: Some(352003), max: None, found: 352002 }))

It'll keep trying to sync block #129258 and then drop peers.

@5chdn could you tell why is it closed? The problem is not with the setup (chains runs correctly for hundreds of thousands of blocks), but it stops at some point with the error described above.

It's a problem with the setup but it's only triggered with some transaction in a certain block. It's really hard to tell from my chair what can cause this. The best would be to cleanly setup a new network based on the learnings I shared in the article linked above.

Thanks @5chdn. It's interesting as the configs were generated with Puppeth. So it means we should open a ticket at go-ethereum project?

Sounds reasonable.

Parity's PoW validation is wrong.

    /// Convert an Ethash boundary to its original difficulty. Basically just `f(x) = 2^256 / x`.
    pub fn boundary_to_difficulty(boundary: &H256) -> U256 {
        let d = U256::from(*boundary);
        if d <= U256::one() {
            U256::max_value()
        } else {
            ((U256::one() << 255) / d) << 1
        }
    }

    /// Convert an Ethash difficulty to the target boundary. Basically just `f(x) = 2^256 / x`.
    pub fn difficulty_to_boundary(difficulty: &U256) -> H256 {
        if *difficulty <= U256::one() {
            U256::max_value().into()
        } else {
            (((U256::one() << 255) / *difficulty) << 1).into()
        }
    }

Both these calculations truncate the last bit. This means, that blocks with odd difficulty values get validated by Parity as if the difficulty was one less. This is the reason why the blocks are rejected.

Go repro:

package main

import (
    "fmt"
    "math/big"
)

func main() {
    difficulty := int64(307293)
    fmt.Printf("Source difficulty: %v\n", difficulty)

    // Geth
    two256 := new(big.Int).Exp(big.NewInt(2), big.NewInt(256), big.NewInt(0))
    fmt.Printf("Geth diff->boundary->diff: %v\n", new(big.Int).Div(two256, new(big.Int).Div(two256, big.NewInt(difficulty))))

    // Parity
    boundary := big.NewInt(1)
    boundary.Lsh(boundary, 255)
    boundary.Div(boundary, big.NewInt(difficulty))
    boundary.Lsh(boundary, 1)

    diff := big.NewInt(1)
    diff.Lsh(diff, 255)
    diff.Div(diff, boundary)
    diff.Lsh(diff, 1)

    fmt.Printf("Parity diff->boundary->diff: %v\n", diff)
}
Source difficulty: 307293
Geth diff->boundary->diff: 307293
Parity diff->boundary->diff: 307292

Ping @5chdn @folsen

Thanks for finding this @karalabe :+1:.

joshua-mir Opened issue similar to #10118 since couldn't respond to the closed ticket. Hope that was
right thing to do. Same issue on Parity ver2.1.10!!! I just checked!

Was this page helpful?
0 / 5 - 0 ratings