Published
Edited
Nov 28, 2020
Insert cell
Insert cell
lodestarTypes = require(`https://wzrd.in/standalone/${encodeURIComponent('@chainsafe/lodestar-types/lib/ssz/presets/mainnet')}@latest`)
Insert cell
mainnetTypes = lodestarTypes.types
Insert cell
lodestarUtils = require(`https://wzrd.in/standalone/${encodeURIComponent('@chainsafe/lodestar-utils')}@latest`)
Insert cell
ssz = require(`https://wzrd.in/standalone/${encodeURIComponent('@chainsafe/ssz')}@0.6.13`)
Insert cell
BufferPolyfill = require('https://wzrd.in/standalone/buffer@6.0.3')
Insert cell
Buffer = BufferPolyfill.Buffer
Insert cell
function makeSigningRoot(
pubkey,
withdrawalCredentials,
amount
) {
const DomainType = {
DEPOSIT: 3,
};
const GENESIS_FORK_VERSION = '00000000'
const domainType = DomainType.DEPOSIT;
const ZERO_HASH = Buffer.alloc(32, 0);
const forkVersion = Buffer.from(GENESIS_FORK_VERSION, 'hex');
const genesisValidatorRoot = ZERO_HASH;
const forkData = {
currentVersion: forkVersion,
genesisValidatorsRoot: genesisValidatorRoot,
};
const forkDataRoot = mainnetTypes.ForkData.hashTreeRoot(forkData);
const domain = Buffer.concat([
lodestarUtils.intToBytes(domainType, 4),
Uint8Array.from(forkDataRoot.valueOf()).slice(0, 28),
]);
const depositData = {
pubkey,
withdrawalCredentials: withdrawalCredentials,
amount,
signature: Buffer.alloc(96),
};
return Buffer.from(
mainnetTypes.SigningData.hashTreeRoot({
objectRoot: mainnetTypes.DepositMessage.hashTreeRoot(depositData),
domain,
})
);
}
Insert cell
Number64 = new ssz.NumberUintType({byteLength: 8})
Insert cell
BigInt64 = new ssz.BigIntUintType({byteLength: 8})
Insert cell
Gwei = BigInt64
Insert cell
ethers = require('https://wzrd.in/standalone/ethers@5.0.23')
Insert cell
contractRawData = '0xc82655b7000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000003095cc8b005df61f5549dca1699a032aafb4b794afda073714aa77215cfabf49462b5b35acf7e230d8045e717a22378cab00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000f91a1bd67081568eec19af95bad48d08b8658fa14d87f7b2a803e350b95c8a0000000000000000000000000000000000000000000000000000000000000060b118ba171f6df70b11785f41c70e8e633985d653f526aba12aae895da98dd13c3537ef557c5a9aebba6a49e2d8a0160003430670e0b51624b390b0f35a69600fc4a293d219bf8c7e7da017c54b4dfe44edcb332b3090b358f9bcfd181e6cb4360000000000000000000000000000000000000000000000000000000000000001fa434b991f52d65ff5da5a91d90642c16a32cf9032171fbbeee0de16b84683a2'
Insert cell
depositContractABI = [
'event DepositEvent(bytes pubkey, bytes withdrawal_credentials, bytes amount, bytes signature, bytes index)',
'function deposit(' +
'bytes calldata pubkey, ' +
'bytes calldata withdrawal_credentials, ' +
'bytes calldata signature, ' +
'bytes32 deposit_data_root)',
'function batchDeposit(' +
'bytes calldata pubkeys, ' +
'bytes calldata withdrawal_credentials, ' +
'bytes calldata signatures, ' +
'bytes32[] calldata deposit_data_roots)',
]
Insert cell
depositContractInterface = new ethers.ethers.utils.Interface(depositContractABI)
Insert cell
import(`https://wzrd.in/standalone/${encodeURIComponent(
'@chainsafe/bls'
)}@4.0.0`)
Insert cell
bls = require(`https://wzrd.in/standalone/${encodeURIComponent(
'@chainsafe/bls'
)}@4.0.0`)
Insert cell
batchDepositArgs = depositContractInterface.decodeFunctionData('batchDeposit', contractRawData)
Insert cell
amount = '0x0040597307000000'
Insert cell
signingRoot = makeSigningRoot(Buffer.from(batchDepositArgs.pubkeys.slice(2), 'hex'), Buffer.from(batchDepositArgs.withdrawal_credentials.slice(2), 'hex'), BigInt('32000000000'))
Insert cell
async function* verifySignature() {
// var window.Module = {};
await bls.initBLS();

const pk = bls.PublicKey.fromBytes(
Buffer.from(batchDepositArgs.pubkeys.slice(2), 'hex')
);
const sig = bls.PublicKey.fromBytes(
Buffer.from(batchDepositArgs.signatures.slice(2), 'hex')
);
return pk.verifyMessage(sig, signingRoot);
}
Insert cell
verifySignature()
Insert cell
herumiBls = require('https://herumi.github.io/bls-eth-wasm/browser/bls.js')
Insert cell
herumiBls.init(herumiBls.BLS12_381)
Insert cell
{
const pk = herumiBls.deserializeHexStrToPublicKey(
batchDepositArgs.pubkeys.slice(2, 2 + 96)
);
const sig = herumiBls.deserializeHexStrToSignature(
batchDepositArgs.signatures.slice(2, 2 + 192)
);
console.log('pk', batchDepositArgs.pubkeys.slice(2, 2 + 96));
console.log('pk', Buffer.from(pk.serialize()).toString('hex'));
console.log('sig', batchDepositArgs.signatures.slice(2, 2 + 192));
console.log('sig', Buffer.from(sig.serialize()).toString('hex'));
console.log('signingRoot', Uint8Array.from(signingRoot));
return pk.verify(sig, Uint8Array.from(signingRoot));
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more