Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 15 additions & 45 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,7 @@ jobs:
run: 'cargo test --test integration -- --nocapture'

zk_prover_integration:
runs-on:
group: enclave-ci
labels: [enclave-ci-runner]
runs-on: 'ubuntu-latest'
steps:
- uses: actions/checkout@v6

Expand Down Expand Up @@ -112,9 +110,7 @@ jobs:
run: 'cargo test -p e3-zk-prover --features integration-tests --test integration_tests -- --nocapture'

build_e3_support_risc0:
runs-on:
group: enclave-ci
labels: [enclave-ci-runner]
runs-on: 'ubuntu-latest'
steps:
- uses: actions/checkout@v6
- name: Generate tags
Expand Down Expand Up @@ -151,9 +147,7 @@ jobs:
type=gha,mode=max,scope=e3-support

build_ciphernode_image:
runs-on:
group: enclave-ci
labels: [enclave-ci-runner]
runs-on: 'ubuntu-latest'
steps:
- uses: actions/checkout@v6

Expand Down Expand Up @@ -193,9 +187,7 @@ jobs:
type=gha,mode=max,scope=ciphernode

test_contracts:
runs-on:
group: enclave-ci
labels: [enclave-ci-runner]
runs-on: 'ubuntu-latest'
steps:
- name: 'Check out the repo'
uses: 'actions/checkout@v6'
Expand Down Expand Up @@ -230,9 +222,7 @@ jobs:
echo "✅ Passed" >> $GITHUB_STEP_SUMMARY

test_net:
runs-on:
group: enclave-ci
labels: [enclave-ci-runner]
runs-on: 'ubuntu-latest'
steps:
- name: 'Check out the repo'
uses: 'actions/checkout@v6'
Expand All @@ -245,9 +235,7 @@ jobs:
echo "✅ Passed" >> $GITHUB_STEP_SUMMARY

integration_prebuild:
runs-on:
group: enclave-ci
labels: [enclave-ci-runner]
runs-on: 'ubuntu-latest'
steps:
- name: 'Check out the repo'
uses: 'actions/checkout@v6'
Expand Down Expand Up @@ -368,9 +356,7 @@ jobs:
echo "✅ Passed" >> $GITHUB_STEP_SUMMARY

build_enclave_cli:
runs-on:
group: enclave-ci
labels: [enclave-ci-runner]
runs-on: 'ubuntu-latest'
steps:
- uses: actions/checkout@v6
with:
Expand Down Expand Up @@ -401,9 +387,7 @@ jobs:
retention-days: 1

crisp_unit:
runs-on:
group: enclave-ci
labels: [enclave-ci-runner]
runs-on: 'ubuntu-latest'
needs: [build_crisp_sdk]
steps:
- uses: actions/checkout@v6
Expand Down Expand Up @@ -589,9 +573,7 @@ jobs:
retention-days: 30

build_circuits:
runs-on:
group: enclave-ci
labels: [enclave-ci-runner]
runs-on: 'ubuntu-latest'
steps:
- uses: actions/checkout@v6
with:
Expand Down Expand Up @@ -644,9 +626,7 @@ jobs:
if-no-files-found: error

zk_prover_e2e:
runs-on:
group: enclave-ci
labels: [enclave-ci-runner]
runs-on: 'ubuntu-latest'
needs: [build_circuits]
steps:
- uses: actions/checkout@v6
Expand Down Expand Up @@ -685,9 +665,7 @@ jobs:
run: cargo test -p e3-zk-prover --test local_e2e_tests -- --nocapture

build_e3_support_dev:
runs-on:
group: enclave-ci
labels: [enclave-ci-runner]
runs-on: 'ubuntu-latest'
steps:
- uses: actions/checkout@v6
with:
Expand Down Expand Up @@ -716,9 +694,7 @@ jobs:
if-no-files-found: error

build_sdk:
runs-on:
group: enclave-ci
labels: [enclave-ci-runner]
runs-on: 'ubuntu-latest'
steps:
- uses: actions/checkout@v6
with:
Expand Down Expand Up @@ -774,9 +750,7 @@ jobs:
if-no-files-found: warn

build_crisp_sdk:
runs-on:
group: enclave-ci
labels: [enclave-ci-runner]
runs-on: 'ubuntu-latest'
steps:
- uses: actions/checkout@v6

Expand Down Expand Up @@ -897,9 +871,7 @@ jobs:
pnpm test:integration

test_enclave_init:
runs-on:
group: enclave-ci
labels: [enclave-ci-runner]
runs-on: 'ubuntu-latest'
needs: [build_enclave_cli, build_e3_support_dev]
steps:
- name: Install pnpm
Expand Down Expand Up @@ -936,9 +908,7 @@ jobs:
enclave init mycitest --verbose --template=${{ github.server_url }}/${{ github.repository }}.git#${BRANCH}:templates/default

contrib-readme-job:
runs-on:
group: enclave-ci
labels: [enclave-ci-runner]
runs-on: 'ubuntu-latest'
name: Populate Contributors List
# Only run on main branch to avoid branch conflicts
if: github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, 'contrib-readme-action')
Expand Down
136 changes: 60 additions & 76 deletions examples/CRISP/packages/crisp-contracts/tests/crisp.contracts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,78 @@ import {
generateMerkleTree,
SIGNATURE_MESSAGE_HASH,
generateMaskVoteProof,
destroyBBApi,
} from '@crisp-e3/sdk'
import type { ProofData } from '@crisp-e3/sdk'
import { expect } from 'chai'
import { deployCRISPProgram, deployHonkVerifier, deployMockEnclave, ethers } from './utils'
import type { CRISPProgram, HonkVerifier, MockEnclave } from '../types'

let keys = generateBFVKeys()
let publicKey = keys.publicKey

describe('CRISP Contracts', function () {
// Allow time for contract deployments + proof generation in before()
this.timeout(600000)

let honkVerifier: HonkVerifier
let mockEnclave: MockEnclave
let crispProgram: CRISPProgram
let signature: `0x${string}`
let address: string
let leaves: bigint[]
let voteProof: ProofData
let maskProof: ProofData
const balance = 100n
const vote = [10, 0]

before(async function () {
// Deploy contracts once
mockEnclave = await deployMockEnclave()
honkVerifier = await deployHonkVerifier()
crispProgram = await deployCRISPProgram({ mockEnclave, honkVerifier })

// Compute signature, address, and leaves once
const [signer] = await ethers.getSigners()
signature = (await signer.signMessage(SIGNATURE_MESSAGE)) as `0x${string}`
address = await getAddressFromSignature(signature, SIGNATURE_MESSAGE_HASH)
leaves = [...[10n, 20n, 30n], hashLeaf(address, balance)]

// Generate proofs once
voteProof = await generateVoteProof({
vote,
publicKey,
signature,
merkleLeaves: leaves,
balance,
messageHash: SIGNATURE_MESSAGE_HASH,
slotAddress: address,
})

maskProof = await generateMaskVoteProof({
publicKey,
merkleLeaves: leaves,
balance,
slotAddress: address,
numOptions: 2,
})
})
Comment thread
ctrlc03 marked this conversation as resolved.

after(() => {
destroyBBApi()
})

describe('decode tally', () => {
it('should decode a tally correctly', async () => {
const mockEnclave = await deployMockEnclave()
const crispProgram = await deployCRISPProgram({ mockEnclave })

const e3Id = await mockEnclave.nextE3Id()
await mockEnclave.request(await crispProgram.getAddress())

const tally =
'0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000300000000000000000000000000000003000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000030000000000000003000000000000000300000000000000030000000000000003000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'

await mockEnclave.setPlaintextOutput(tally)

const decodedTally1 = await crispProgram.decodeTally(0)
const decodedTally1 = await crispProgram.decodeTally(e3Id)

expect(decodedTally1[0]).to.equal(10000000000n)
expect(decodedTally1[1]).to.equal(30000000000n)
Expand All @@ -43,96 +94,29 @@ describe('CRISP Contracts', function () {

describe('validate input', () => {
it('should verify the proof correctly with the crisp verifier', async function () {
// It needs some time to generate the proof.
this.timeout(300000)

const honkVerifier = await deployHonkVerifier()
const [signer] = await ethers.getSigners()

const vote = [10, 0]
const balance = 100n
const signature = (await signer.signMessage(SIGNATURE_MESSAGE)) as `0x${string}`
const address = await getAddressFromSignature(signature, SIGNATURE_MESSAGE_HASH)
const leaves = [...[10n, 20n, 30n], hashLeaf(address, balance)]

const proof = await generateVoteProof({
vote,
publicKey,
signature,
merkleLeaves: leaves,
balance,
messageHash: SIGNATURE_MESSAGE_HASH,
slotAddress: address,
})

const isValid = await honkVerifier.verify(proof.proof, proof.publicInputs)
const isValid = await honkVerifier.verify(voteProof.proof, voteProof.publicInputs)

expect(isValid).to.be.true
})

it('should verify the proof for a vote mask', async function () {
// It needs some time to generate the proof.
this.timeout(300000)

const honkVerifier = await deployHonkVerifier()
const [signer] = await ethers.getSigners()

const balance = 100n
const signature = (await signer.signMessage(SIGNATURE_MESSAGE)) as `0x${string}`
const address = await getAddressFromSignature(signature, SIGNATURE_MESSAGE_HASH)
const leaves = [...[10n, 20n, 30n], hashLeaf(address, balance)]

const proof = await generateMaskVoteProof({
publicKey,
merkleLeaves: leaves,
balance,
slotAddress: address,
numOptions: 2,
})

const isValid = await honkVerifier.verify(proof.proof, proof.publicInputs)
const isValid = await honkVerifier.verify(maskProof.proof, maskProof.publicInputs)

expect(isValid).to.be.true
})

it('should validate input correctly', async function () {
// It needs some time to generate the proof.
this.timeout(300000)

const mockEnclave = await deployMockEnclave()
const crispProgram = await deployCRISPProgram({ mockEnclave })
const e3Id = await mockEnclave.nextE3Id()
await mockEnclave.request(await crispProgram.getAddress())
const [signer] = await ethers.getSigners()

const e3Id = 0n

await mockEnclave.request(await crispProgram.getAddress())

const vote = [10, 0]
const balance = 100n
const signature = (await signer.signMessage(SIGNATURE_MESSAGE)) as `0x${string}`
const address = await getAddressFromSignature(signature, SIGNATURE_MESSAGE_HASH)
const leaves = [...[10n, 20n, 30n], hashLeaf(address, balance)]
const merkleTree = generateMerkleTree(leaves)

const proof = await generateVoteProof({
vote,
publicKey,
signature,
merkleLeaves: leaves,
balance,
messageHash: SIGNATURE_MESSAGE_HASH,
slotAddress: address,
})

await mockEnclave.setCommitteePublicKey(proof.publicInputs[6])
await mockEnclave.setCommitteePublicKey(voteProof.publicInputs[6])

const encodedProof = encodeSolidityProof(proof)
const encodedProof = encodeSolidityProof(voteProof)

// Call next functions with fake data for testing.
await crispProgram.setMerkleRoot(e3Id, merkleTree.root)

// If it doesn't throw, the test is successful.
await crispProgram.publishInput(e3Id, encodedProof)
})
})
Expand Down
3 changes: 2 additions & 1 deletion examples/CRISP/packages/crisp-sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ export {
encryptVote,
encodeSolidityProof,
validateVote,
destroyBBApi,
} from './vote'
export { CrispSDK } from './sdk'

export type { RoundDetails, RoundDetailsResponse, TokenDetails, Vote, MaskVoteProofInputs, VoteProofInputs } from './types'
export type { RoundDetails, RoundDetailsResponse, TokenDetails, Vote, MaskVoteProofInputs, VoteProofInputs, ProofData } from './types'
export { CreditMode } from './types'
Loading
Loading