@polygon-hermez/vm
Version:
An Ethereum VM implementation
84 lines • 3.25 kB
JavaScript
;
// 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