UNPKG

@polygon-hermez/vm

Version:
84 lines 3.25 kB
"use strict"; // packages/vm/src/evm/precompiles/p256verify.ts Object.defineProperty(exports, "__esModule", { value: true }); var ethereumjs_util_1 = require("ethereumjs-util"); var evm_1 = require("../evm"); var assert = require('assert'); var elliptic_1 = require("elliptic"); // Initialize the P-256 curve (secp256r1) var ec = new elliptic_1.ec('p256'); // 'p256' is equivalent to 'prime256v1' or 'secp256r1' function verifyP256Signature(pubKeyX, pubKeyY, r, s, msgHash) { // Check that all inputs have the correct length (32 bytes each) if (pubKeyX.length !== 32 || pubKeyY.length !== 32 || r.length !== 32 || s.length !== 32 || msgHash.length !== 32) { throw new Error('Invalid input lengths for P-256 signature verification'); } // Recreate the public key from the X and Y coordinates var key = ec.keyFromPublic({ x: pubKeyX.toString('hex'), y: pubKeyY.toString('hex'), }, 'hex'); // Create the signature object var signature = { r: r.toString('hex'), s: s.toString('hex'), }; // Verify the signature return key.verify(msgHash.toString('hex'), signature); } /** * Precompiled contract for P256 signature verification (RIP-7212). * It takes the public key, message hash, and signature, and verifies if the signature is valid. * * Input: * - publicKey: 64 bytes (32 bytes for X coordinate, 32 bytes for Y coordinate) * - signature: 64 bytes (32 bytes for R, 32 bytes for S) * - message: 32 bytes (hash of the message) */ function default_1(opts) { assert(opts.data); // Gas cost is 3450 var gasUsed = new ethereumjs_util_1.BN(opts._common.param('gasPrices', 'p256verify')); // Check if there is enough gas to run this precompile if (opts.gasLimit.lt(gasUsed)) { return (0, evm_1.OOGResult)(opts.gasLimit); } // Ensure the data is the correct length for P256VERIFY // Input should be 128 bytes: 64 bytes for public key, 64 bytes for signature var data = (0, ethereumjs_util_1.setLengthRight)(opts.data, 160); var msg = data.slice(0, 32); var r = data.slice(32, 64); var s = data.slice(64, 96); var pubKeyX = data.slice(96, 128); var pubKeyY = data.slice(128, 160); // Assuming a 32-byte message hash // Reduce counters opts._VM.vcm.computeFunctionCounters('preP256Verify', { pubKeyX: new ethereumjs_util_1.BN(pubKeyX).toString('hex'), pubKeyY: new ethereumjs_util_1.BN(pubKeyY).toString('hex'), r: new ethereumjs_util_1.BN(r).toString('hex'), s: new ethereumjs_util_1.BN(s).toString('hex'), }); // Verify the signature var isValid; try { isValid = verifyP256Signature(pubKeyX, pubKeyY, r, s, msg); } catch (e) { // If verification fails, return an empty buffer return { gasUsed: gasUsed, returnValue: Buffer.alloc(0), }; } // Return 1 for valid signature, 0 for invalid var returnValue = isValid ? (0, ethereumjs_util_1.setLengthLeft)(Buffer.from([1]), 32) : Buffer.alloc(0); return { gasUsed: gasUsed, returnValue: returnValue, }; } exports.default = default_1; //# sourceMappingURL=100-p256verify.js.map