Consensys / anonymous-zether

A private payment system for Ethereum-based blockchains, with no trusted setup.
Other
295 stars 73 forks source link

Transfer failing with reason Recovery failure for B^x * A. #12

Closed naddison36 closed 4 years ago

naddison36 commented 4 years ago

I've trying the example against a local Geth node but the transfer from Alice to Bob keeps failing in ZetherVerifier with reason Recovery failure for B^x * A.

Any ideas on what I'm doing wrong?

I can move what I'm doing into a public repo if it helps, but I'm essentially following the example of Alice depositing into the Anonymous Zether contract and then transferring to Bob.

panghalamit commented 4 years ago

As this is the 1st revert check in verification function, it could fail if you are pass wrong params during proof generation. Most likely cause of this would be different epochs during proof generation and verification AFAIK. I have encountered this many times while testing and Most of it was due to mismatch in epochs.

naddison36 commented 4 years ago

Thanks for your help @panghalamit

My proofs are taking over 400 seconds to create on my laptop so when I use and epoch of 6 second, the verification fails. It's taking over 60 seconds just to process this line in the Zether proof generator https://github.com/jpmorganchase/anonymous-zether/blob/master/packages/anonymous.js/src/prover/zether/zether.js#L63

My laptop is a MacBook Pro with a 2.7 GHz Intel Core i7 processor

naddison36 commented 4 years ago

Setting my epoch to 500 worked. I can now send a shielded transfer.

benediamond commented 4 years ago

My proofs are taking over 400 seconds to create on my laptop

Good Lord, seriously? for which anonset size? This is way, way too much—shouldn't be this long. Let's figure out what's going on.

benediamond commented 4 years ago

@naddison36

you're running this in NodeJS, yes? which version...? which calls exactly are you making to anonymous-zether, i.e. how are you invoking it? can you also report your bn.js and elliptic.js versions? thanks.

benediamond commented 4 years ago

also, importantly—try running this on your host box, not on a guest virtual machine.

naddison36 commented 4 years ago

I was running node v10.15.2. Dependency versions are:

It takes my MacBook pro around 60 seconds to run this line in zether.js proof.s = params.commit(sL, sR, rho); https://github.com/jpmorganchase/anonymous-zether/blob/master/packages/anonymous.js/src/prover/zether/zether.js#L63

It takes about 30 seconds each to run the following two for loops in the commit. These are looping over an array of 64 entries https://github.com/jpmorganchase/anonymous-zether/blob/master/packages/anonymous.js/src/prover/algebra.js#L40 https://github.com/jpmorganchase/anonymous-zether/blob/master/packages/anonymous.js/src/prover/algebra.js#L43

I've also tried node v12.11.1 and the proof generation was 10 seconds slower at 384 compared to 374 seconds of node 10. But the times vary +- 10 seconds or both versions.

These tests were done with no decoys: const receipt = await aliceClient.transfer("Bob", 9);

benediamond commented 4 years ago

this is bonkers. are you on running on an honest, i.e. host machine?

could you try some experiments—e.g., navigate to anonymous.js/src, open up a node console, and run:

const { GeneratorParams, FieldVector } = require('./prover/algebra.js');
const utils = require('./utils/utils.js')
const bn128 = require('./utils/bn128.js')
var params = new GeneratorParams();
params.extend(64);
var gExp = new FieldVector(Array.from({ length: 64 }).map(bn128.randomScalar));
var hExp = new FieldVector(Array.from({ length: 64 }).map(bn128.randomScalar));
params.commit(gExp, hExp, bn128.randomScalar());

for me, the last command takes just around 300 ms.

naddison36 commented 4 years ago

The last command in the above take just under 400 ms on my machine. That's a big improvement on a minute!

I was running the transfer in a Jest test on WebStorm. I'll experiment to see if that makes any difference.

naddison36 commented 4 years ago

The good news is I can replicate the problem. If I run the below Jest test written in TypeScript on WebStorm the last line takes 56 seconds

test("commit test", () => {
  const { GeneratorParams, FieldVector } = require("../prover/algebra.js");
  const bn128 = require("../utils/bn128.js");
  const params = new GeneratorParams();
  params.extend(64);
  const gExp = new FieldVector(Array.from({ length: 64 }).map(bn128.randomScalar));
  const hExp = new FieldVector(Array.from({ length: 64 }).map(bn128.randomScalar));

  const startTime = new Date();
  params.commit(gExp, hExp, bn128.randomScalar());
  const endTime = new Date();
  console.log(`End ${endTime - startTime}`);
});

Now to narrow in on what's causing the problem

naddison36 commented 4 years ago

The problem is Jest. The exact same JS code in a Jest test takes 60 seconds compared to 396 ms outside Jest. I'm using Jest 24.9.0 I'll play around with the Jest settings. If no luck I'll raise a Jest issue as this is crazy. This is definitely not an Anonymous Zether issue so I'll close this issue.

naddison36 commented 4 years ago

I've raised a Jest issue https://github.com/facebook/jest/issues/9006

naddison36 commented 4 years ago

Just to close this off for anyone else looking at this, adding the following Jest config gave me a 100x speed improvement when running the transfer proof in Jest. It now only takes 4 seconds compared to 400 seconds without this Jest config

    extraGlobals: ["Math"]
benediamond commented 4 years ago

@naddison36 wow. Big thanks for doing this digging, and glad we've gotten everything worked out!