Skip to content

Instantly share code, notes, and snippets.

@zac-williamson
Created April 6, 2019 14:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zac-williamson/f340e387f4f53a7a0623c4aa6b589da9 to your computer and use it in GitHub Desktop.
Save zac-williamson/f340e387f4f53a7a0623c4aa6b589da9 to your computer and use it in GitHub Desktop.
/* global expect, contract, beforeEach, web3, it:true */
const EC = require('elliptic');
const BN = require('bn.js');
const crypto = require('crypto');
const Weierstrudel = require('../out/Weierstrudel');
const Monty = require('../out/Monty');
const weierstrudelContract = new web3.eth.Contract(Weierstrudel.abi);
const montyContract = new web3.eth.Contract(Monty.abi);
// eslint-disable-next-line new-cap
const referenceCurve = new EC.curve.short({
a: '0',
b: '3',
p: '30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47',
n: '30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001',
gRed: false,
g: ['1', '2'],
});
const randomPoint = () => {
const x = new BN(crypto.randomBytes(32), 16).toRed(referenceCurve.red);
const xxx = x.redSqr().redMul(x);
const y2 = xxx.redAdd(referenceCurve.b);
const y = y2.redSqrt();
if (y.redSqr().fromRed().eq(xxx.redAdd(referenceCurve.b).fromRed())) {
return { x: x.fromRed(), y: y.fromRed(), z: new BN(1) };
}
return randomPoint();
};
const generatePointData = (numPoints) => {
const points = [...new Array(numPoints)].map(() => randomPoint());
const scalars = [...new Array(numPoints)].map(() => crypto.randomBytes(32));
const pointBuffer = Buffer.concat(points.map(({ x, y }) => Buffer.concat([x.toBuffer('be', 32), y.toBuffer('be', 32)])));
const scalarBuffer = Buffer.concat(scalars);
const calldata = Buffer.concat([pointBuffer, scalarBuffer]);
const expected = points.reduce((acc, { x, y }, i) => {
if (!acc) {
return referenceCurve.point(x, y).mul(scalars[i]);
}
return acc.add(referenceCurve.point(x, y).mul(scalars[i]));
}, null);
return { calldata, expected };
};
contract('Weierstrudel contract tests', (accounts) => {
let weierstrudel;
let weierstrudelAddress;
let monty;
let montyAddress;
beforeEach(async () => {
weierstrudel = await weierstrudelContract
.deploy({ data: Weierstrudel.bytecode })
.send({
from: accounts[0],
gas: 6000000,
});
monty = await montyContract
.deploy({ data: Monty.bytecode })
.send({
from: accounts[0],
gas: 6000000,
});
// eslint-disable-next-line no-underscore-dangle
weierstrudelAddress = weierstrudel._address;
// eslint-disable-next-line no-underscore-dangle
montyAddress = monty._address;
});
it('Weierstrudel performs scalar multiplication for 1-15 points and Monty normalizes to affine', async () => {
const transactionData = [...new Array(15)].map((_, i) => {
return generatePointData(i + 1);
});
const transactions = transactionData.map(({ calldata }) => {
return web3.eth.call({
from: accounts[0],
to: weierstrudelAddress,
data: `0x${calldata.toString('hex')}`,
});
});
const weierstrudelResultData = await Promise.all(transactions);
const montyTransactions = weierstrudelResultData.map((output) => {
return web3.eth.call({
from: accounts[0],
to: montyAddress,
data: output,
});
});
const resultData = await Promise.all(montyTransactions);
resultData.forEach((output, i) => {
const result = web3.eth.abi.decodeParameter('uint[2]', output);
const { expected } = transactionData[i];
expect(result[0]).to.equal(expected.x.fromRed().toString(10));
expect(result[1]).to.equal(expected.y.fromRed().toString(10));
});
}).timeout(100000);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment