Skip to content

[openzeppelin-revm] P256 tests failed #220

@sekisamu

Description

@sekisamu

Problem Description

P256 cryptographic verification tests fail on REVM (local network) with ProviderError: execution reverted when calling the P256 precompile contract. All P256 signature verification operations revert, indicating the P256 (secp256r1) precompile is not implemented or not accessible in the current REVM environment.

Environment

OpenZeppelin Contracts Repository:

Polkadot SDK (REVM Runtime):

How to Reproduce

  1. Start REVM node (torsten/gas-fixes branch)
  2. Run P256 tests:
    cd openzeppelin-contracts-revm
    git checkout test-local-revm
    npm installl
    npx hardhat test --network local --grep 'P256'

Test Results

 222 passing (45s)
  78 pending
  3 failing

  1) P256
       with signature
         verify valid signature:
     ProviderError: execution reverted
      at HttpProvider.request (/Users/suvi/Documents/paritytech/papermoon/code/openzeppelin-contracts-revm/node_modules/hardhat/src/internal/core/providers/http.ts:116:21)
      at processTicksAndRejections (node:internal/process/task_queues:105:5)
      at staticCallResult (/Users/suvi/Documents/paritytech/papermoon/code/openzeppelin-contracts-revm/node_modules/ethers/src.ts/contract/contract.ts:337:22)
      at staticCall (/Users/suvi/Documents/paritytech/papermoon/code/openzeppelin-contracts-revm/node_modules/ethers/src.ts/contract/contract.ts:303:24)
      at Proxy.$verifyNative (/Users/suvi/Documents/paritytech/papermoon/code/openzeppelin-contracts-revm/node_modules/ethers/src.ts/contract/contract.ts:351:41)
      at Context.<anonymous> (/Users/suvi/Documents/paritytech/papermoon/code/openzeppelin-contracts-revm/test/utils/cryptography/P256.test.js:50:7)

  2) P256
       with signature
         reject signature with flipped signature values ([r,s] >> [s,r]):
     ProviderError: execution reverted
      at HttpProvider.request (/Users/suvi/Documents/paritytech/papermoon/code/openzeppelin-contracts-revm/node_modules/hardhat/src/internal/core/providers/http.ts:116:21)
      at processTicksAndRejections (node:internal/process/task_queues:105:5)
      at staticCallResult (/Users/suvi/Documents/paritytech/papermoon/code/openzeppelin-contracts-revm/node_modules/ethers/src.ts/contract/contract.ts:337:22)
      at staticCall (/Users/suvi/Documents/paritytech/papermoon/code/openzeppelin-contracts-revm/node_modules/ethers/src.ts/contract/contract.ts:303:24)
      at Proxy.$verifyNative (/Users/suvi/Documents/paritytech/papermoon/code/openzeppelin-contracts-revm/node_modules/ethers/src.ts/contract/contract.ts:351:41)
      at Context.<anonymous> (/Users/suvi/Documents/paritytech/papermoon/code/openzeppelin-contracts-revm/test/utils/cryptography/P256.test.js:118:7)

  3) P256
       with signature
         reject signature with invalid message hash:
     ProviderError: execution reverted
      at HttpProvider.request (/Users/suvi/Documents/paritytech/papermoon/code/openzeppelin-contracts-revm/node_modules/hardhat/src/internal/core/providers/http.ts:116:21)
      at processTicksAndRejections (node:internal/process/task_queues:105:5)
      at staticCallResult (/Users/suvi/Documents/paritytech/papermoon/code/openzeppelin-contracts-revm/node_modules/ethers/src.ts/contract/contract.ts:337:22)
      at staticCall (/Users/suvi/Documents/paritytech/papermoon/code/openzeppelin-contracts-revm/node_modules/ethers/src.ts/contract/contract.ts:303:24)
      at Proxy.$verifyNative (/Users/suvi/Documents/paritytech/papermoon/code/openzeppelin-contracts-revm/node_modules/ethers/src.ts/contract/contract.ts:351:41)
      at Context.<anonymous> (/Users/suvi/Documents/paritytech/papermoon/code/openzeppelin-contracts-revm/test/utils/cryptography/P256.test.js:132:7)

Error Details

All three tests fail with the same error pattern:

ProviderError: execution reverted
  at HttpProvider.request (.../hardhat/src/internal/core/providers/http.ts:116:21)
  at staticCallResult (.../ethers/src.ts/contract/contract.ts:337:22)
  at staticCall (.../ethers/src.ts/contract/contract.ts:303:24)
  at Proxy.$verifyNative (.../ethers/src.ts/contract/contract.ts:351:41)
  at Context.<anonymous> (test/utils/cryptography/P256.test.js:50:7)

Failed Test Cases:

  1. verify valid signature (P256.test.js:50)
  2. reject signature with flipped signature values (P256.test.js:118)
  3. reject signature with invalid message hash (P256.test.js:132)

Root Cause Analysis

Contract Code Analysis

The P256 library (contracts/utils/cryptography/P256.sol) uses a precompile call at address 0x100:

function verifyNative(
    bytes32 digest,
    bytes32 r,
    bytes32 s,
    bytes32 qx,
    bytes32 qy
) internal view returns (bool valid) {
    assembly ("memory-safe") {
        // ...
        valid := staticcall(gas(), 0x100, 0x00, 0xa0, 0x00, 0x20)
        // ...
    }
}

Issue Identification

The staticcall to address 0x100 reverts, which indicates:

  1. P256 precompile (EIP-7212) is not implemented in the current REVM build
  2. Precompile address 0x100 is not registered in the REVM runtime
  3. Calls to non-existent precompiles revert rather than returning false

Invesigation

After investigating the code, I've noticed that secp256r1 feature was added in commit d15be1b2e3bcca98212d0cb7504535cdb72b8c98, but it seems not implemented correctly.

paritytech/polkadot-sdk@d15be1b#diff-4124d217f83781e8c9cde1df35619fb2b1797858debebfb27ebdab66dfab959fR38

This actually mapped the precompile function to address 100, which is 0x64, but it should be mapped to address 0x100. So it should be:

const MATCHER: BuiltinAddressMatcher = BuiltinAddressMatcher::Fixed(NonZero::new(0x100).unwrap());

After this fixed, all P256 test cases run well.

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions