Created
April 6, 2019 14:56
-
-
Save zac-williamson/f340e387f4f53a7a0623c4aa6b589da9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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