@exromany/lido-csm-sdk
Version:
[](https://github.com/lidofinance/lido-csm-sdk/blob/main/LICENSE.txt) [](h
101 lines • 3.98 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.verifyDepositSignature = void 0;
const ssz_1 = require("@chainsafe/ssz");
const bls_eth_wasm_1 = __importDefault(require("bls-eth-wasm"));
const viem_1 = require("viem");
const constants_js_1 = require("./constants.js");
const DepositMessageSSZ = new ssz_1.ContainerType({
pubkey: new ssz_1.ByteVectorType(48),
withdrawal_credentials: new ssz_1.ByteVectorType(32),
amount: new ssz_1.UintBigintType(8),
});
const ForkDataSSZ = new ssz_1.ContainerType({
current_version: new ssz_1.ByteVectorType(4),
genesis_validators_root: new ssz_1.ByteVectorType(32),
});
const SigningDataSSZ = new ssz_1.ContainerType({
object_root: new ssz_1.ByteVectorType(32),
domain: new ssz_1.ByteVectorType(32),
});
let blsInitialized = false;
const ensureBLSInit = async () => {
if (!blsInitialized) {
await bls_eth_wasm_1.default.init(bls_eth_wasm_1.default.BLS12_381);
blsInitialized = true;
}
};
const ensureHex = (value) => {
return (value.startsWith('0x') ? value : `0x${value}`);
};
const getForkVersion = (chainId) => {
const version = constants_js_1.FIXED_FORK_VERSION[chainId];
if (!version) {
throw new Error(`Fork version not found for chain ${chainId}`);
}
const hex = version.padStart(8, '0');
return (0, viem_1.hexToBytes)(ensureHex(hex));
};
const computeForkDataRoot = (currentVersion, genesisValidatorsRoot) => {
const forkData = {
current_version: currentVersion,
genesis_validators_root: genesisValidatorsRoot,
};
return ForkDataSSZ.hashTreeRoot(forkData);
};
const computeDomain = (domainType, forkVersion, genesisValidatorsRoot) => {
const forkDataRoot = computeForkDataRoot(forkVersion, genesisValidatorsRoot);
const domain = new Uint8Array(32);
domain.set(domainType, 0);
domain.set(forkDataRoot.slice(0, 28), 4);
return domain;
};
const computeSigningRoot = (objectRoot, domain) => {
const signingData = {
object_root: objectRoot,
domain: domain,
};
return SigningDataSSZ.hashTreeRoot(signingData);
};
const computeDepositMessageRoot = (message) => {
return DepositMessageSSZ.hashTreeRoot(message);
};
const verifyDepositSignature = async (data, chainId) => {
try {
await ensureBLSInit();
const pubkey = (0, viem_1.hexToBytes)(data.pubkey);
const signature = (0, viem_1.hexToBytes)(data.signature);
const withdrawalCredentials = (0, viem_1.hexToBytes)(data.withdrawal_credentials);
const amount = BigInt(data.amount);
if (pubkey.length !== 48 || signature.length !== 96 || withdrawalCredentials.length !== 32) {
return false;
}
const depositMessage = {
pubkey,
withdrawal_credentials: withdrawalCredentials,
amount,
};
const messageRoot = computeDepositMessageRoot(depositMessage);
if ((0, viem_1.toHex)(messageRoot).toLowerCase() !== data.deposit_message_root.toLowerCase()) {
return false;
}
const forkVersion = getForkVersion(chainId);
const genesisValidatorsRoot = new Uint8Array(32);
const domainType = (0, viem_1.hexToBytes)(constants_js_1.DOMAIN_DEPOSIT);
const domain = computeDomain(domainType, forkVersion, genesisValidatorsRoot);
const signingRoot = computeSigningRoot(messageRoot, domain);
const publicKey = new bls_eth_wasm_1.default.PublicKey();
publicKey.deserialize(pubkey);
const sig = new bls_eth_wasm_1.default.Signature();
sig.deserialize(signature);
return publicKey.verify(sig, signingRoot);
}
catch {
return false;
}
};
exports.verifyDepositSignature = verifyDepositSignature;
//# sourceMappingURL=signature.js.map