The core functionality of the feature takes place at
`packages/relayer/src/services/privacyPoolRelayer.service.ts` in the
`validateWithdrawal` function. There we check in order:
1. Decode Withdrawal.data and check feeReceiver ==
CONFIGURED_FEE_RECEIVER && feeBPS == CONFIGURED_FEE_BPS
2. Hash (Withdrawal || Scope) and check hash == Proof.context
3. Verify proof with SDK.verifyProof(Proof)
4. Call Entrypoint.scopeToPool() to get asset pool
5. Call Pool.ASSET() to get withdrawn asset
6. Check proof.withdrawnAmount() >=
CONFIGURED_MINIMUM_AMOUNT[withdrawn_asset]
If everything is ok, we call the Entrypoint.relay() with the user's
proof.
I've added examples for the config files `env.example`,
`withdraw_amount.example.json`. The first one are environment variables
to be defined in the server's environment. The second one contains a
mapping of the mimimum withdraw limits for the different supported
assets. There's an env var that should contain a path to this file.
Added a `Dockerfile` and a `docker-compose.yml` to the relayer to test
it or use it in dev flows. The circuit artifacts are loaded as volumes,
so before starting the docker-compose, you should run `yarn present`
from the circuits package dir to group all the artifacts and make them
easily accesible.
Additionally added a small package in
`/packages/relayer/test/integration/relay` that can be built and run to
test the relayer.
There are a lot of TODOs related to code quality, mostly happy path
assumptions, input sanitization, error handling and tests. Feature wise
it's missing the contract interaction (should be straight forward once
it's implemented in the SDK) and the sqlite database for request
tracking.
Because the SDK is meant to run both in web and nodejs I focused
bundling for those two targets. I chose Rollup.js as a bundler because
it is commonly used for bundling libraries and achives a decent tradeoff
between speed and flexibility.
The nodejs bundle will have the artifacts embedded in the package, while
the web bundle will need to have the artifacts being hosted at
/artifacts/{artifact_name}. The API for the circuits has an async
initializer that abstracts away the platform and loads the binaries.
Once initialized, the `circuits` object is used to initialize the
`ZkOps` class that uses the loaded binaries under the hood.
Observation: ~~currently, to build the bundle, the scripts assume you
have all the circuits artifacts at `src/circuits/artifacts`. The PR was
getting too big so I'll relax that assumption later.~~
EDIT: Build will now succeed without the artifacts because building them
in the ci/cd was way out of scope. I provided a script to install the
artifacts to the bundle build for local testing.
Usage example:
```typescript
import { ZkOps, circuits } from "@privacy-pool-core/sdk";
; (async () => {
await circuits.downloadArtifacts("latest");
const zkOps = new ZkOps(circuits);
const input = {
value: "1",
label: BigInt("0"),
nullifier: BigInt("123"),
secret: BigInt("456"),
};
let r = await zkOps.proveCommitment(input);
console.log(r)
})()
```