-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Some renaming + changes to the password tree program
- Loading branch information
adamczykm
committed
Oct 2, 2023
1 parent
33b3edb
commit 230514e
Showing
5 changed files
with
144 additions
and
102 deletions.
There are no files selected for viewing
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,58 +1,61 @@ | ||
// TODO requires changes | ||
import { Field, JsonProof } from "o1js"; | ||
import ProvePasswordInTreeProgram, { PasswordTreePublicInput, PasswordTreeWitness } from "../common/passwordTreeProgram"; | ||
import ProvePasswordInTreeProgram, { PasswordInTreeWitness } from "../common/passwordTreeProgram"; | ||
import { IMinAuthProver, IMinAuthProverFactory } from '../../../library/plugin/pluginType'; | ||
|
||
import axios from "axios"; | ||
|
||
export type SimplePasswordTreeProverConfiguration = { | ||
apiServer: URL, | ||
export type MemberSetProverConfiguration = { | ||
apiServer: URL, | ||
} | ||
|
||
export class SimplePasswordTreeProver implements | ||
IMinAuthProver<bigint, PasswordTreePublicInput, Field> | ||
|
||
// Prove that you belong to a set of user without revealing which user you are. | ||
export class MemberSetProver implements | ||
IMinAuthProver<bigint, PasswordInTreeWitness, Field> | ||
{ | ||
private readonly cfg: SimplePasswordTreeProverConfiguration; | ||
|
||
async prove(publicInput: PasswordTreePublicInput, secretInput: Field) | ||
: Promise<JsonProof> { | ||
const proof = await ProvePasswordInTreeProgram.baseCase( | ||
publicInput, Field.from(secretInput)); | ||
return proof.toJSON(); | ||
} | ||
|
||
async fetchPublicInputs(uid: bigint): Promise<PasswordTreePublicInput> { | ||
const mkUrl = (endpoint: string) => `${this.cfg.apiServer}/${endpoint}`; | ||
const getWitness = async (): Promise<PasswordTreeWitness> => { | ||
const resp = await axios.get(mkUrl(`/witness/${uid.toString()}`)); | ||
if (resp.status != 200) { | ||
throw `unable to fetch witness for ${uid.toString()}, error: ${(resp.data as { error: string }).error}`; | ||
} | ||
return PasswordTreeWitness.fromJSON(resp.data); | ||
}; | ||
const getRoot = async (): Promise<Field> => { | ||
const resp = await axios.get(mkUrl('/root')); | ||
return Field.fromJSON(resp.data); | ||
private readonly cfg: MemberSetProverConfiguration; | ||
|
||
async prove(publicInput: PasswordInTreeWitness, secretInput: Field) | ||
: Promise<JsonProof> { | ||
const proof = await ProvePasswordInTreeProgram.baseCase( | ||
publicInput, Field.from(secretInput)); | ||
return proof.toJSON(); | ||
} | ||
const witness = await getWitness(); | ||
const root = await getRoot(); | ||
|
||
return new PasswordTreePublicInput({ witness, root }); | ||
} | ||
async fetchPublicInputs(uid: bigint): Promise<PasswordInTreeWitness> { | ||
const mkUrl = (endpoint: string) => `${this.cfg.apiServer}/${endpoint}`; | ||
const getWitness = async (): Promise<PasswordInTreeWitness> => { | ||
const resp = await axios.get(mkUrl(`/witness/${uid.toString()}`)); | ||
if (resp.status != 200) { | ||
throw `unable to fetch witness for ${uid.toString()}, error: ${(resp.data as { error: string }).error}`; | ||
} | ||
return PasswordInTreeWitness.fromJSON(resp.data); | ||
}; | ||
const getRoot = async (): Promise<Field> => { | ||
const resp = await axios.get(mkUrl('/root')); | ||
return Field.fromJSON(resp.data); | ||
} | ||
const witness = await getWitness(); | ||
const root = await getRoot(); | ||
|
||
return new PasswordInTreeWitness({ witness, root }); | ||
} | ||
|
||
constructor(cfg: SimplePasswordTreeProverConfiguration) { | ||
this.cfg = cfg; | ||
} | ||
constructor(cfg: MemberSetProverConfiguration) { | ||
this.cfg = cfg; | ||
} | ||
|
||
static async initialize(cfg: SimplePasswordTreeProverConfiguration): | ||
Promise<SimplePasswordTreeProver> { | ||
return new SimplePasswordTreeProver(cfg); | ||
} | ||
static async initialize(cfg: MemberSetProverConfiguration): | ||
Promise<MemberSetProver> { | ||
return new MemberSetProver(cfg); | ||
} | ||
} | ||
|
||
SimplePasswordTreeProver satisfies IMinAuthProverFactory< | ||
SimplePasswordTreeProver, | ||
SimplePasswordTreeProverConfiguration, | ||
bigint, | ||
PasswordTreePublicInput, | ||
Field | ||
> | ||
MemberSetProver satisfies IMinAuthProverFactory< | ||
MemberSetProver, | ||
MemberSetProverConfiguration, | ||
bigint, | ||
PasswordInTreeWitness, | ||
Field | ||
> |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,57 @@ | ||
import { Experimental, Field, MerkleWitness, Poseidon, Struct } from "o1js"; | ||
import { Experimental, Field, MerkleWitness, Poseidon, SelfProof, Struct } from "o1js"; | ||
|
||
// TODO how can this be made dynamic | ||
export const PASSWORD_TREE_HEIGHT = 10; | ||
|
||
export class PasswordTreeWitness extends MerkleWitness(PASSWORD_TREE_HEIGHT) { } | ||
export class PasswordTreeWitness extends MerkleWitness(PASSWORD_TREE_HEIGHT) {} | ||
|
||
export class PasswordTreePublicInput extends Struct({ | ||
witness: PasswordTreeWitness, | ||
root: Field | ||
}) { }; | ||
export class PasswordInTreeWitness extends Struct({ | ||
witness: PasswordTreeWitness, | ||
preImage: Field | ||
}) {}; | ||
|
||
export class MerkleRoot extends Struct({ | ||
root: Field | ||
}) {}; | ||
|
||
|
||
export class ProvePasswordInTreeOutput extends Struct({ | ||
recursiveMekleRootHash: Field, | ||
}) {}; | ||
|
||
// Prove knowledge of a preimage of a hash in a merkle tree. | ||
// The proof does not reveal the preimage nor the hash. | ||
// The output contains a recursive hash of all the roots for which the preimage is known. | ||
// output = hash(lastRoot + hash(secondLastRoot, ... hash(xLastRoot, lastRoot) ...) | ||
// Therefore the order of the proofs matters. | ||
export const ProvePasswordInTreeProgram = Experimental.ZkProgram({ | ||
publicInput: PasswordTreePublicInput, | ||
publicOutput: Field, | ||
|
||
methods: { | ||
baseCase: { | ||
privateInputs: [Field], | ||
method(publicInput: PasswordTreePublicInput, privateInput: Field): Field { | ||
publicInput.witness | ||
.calculateRoot(Poseidon.hash([privateInput])) | ||
.assertEquals(publicInput.root); | ||
return publicInput.witness.calculateIndex(); | ||
} | ||
publicInput: MerkleRoot, | ||
publicOutput: ProvePasswordInTreeOutput, | ||
|
||
methods: { | ||
baseCase: { | ||
privateInputs: [PasswordInTreeWitness], | ||
method(publicInput: MerkleRoot, privateInput: PasswordInTreeWitness): ProvePasswordInTreeOutput { | ||
privateInput.witness | ||
.calculateRoot(Poseidon.hash([publicInput.root])) | ||
.assertEquals(publicInput.root); | ||
return new ProvePasswordInTreeOutput( | ||
{ recursiveMekleRootHash: publicInput.root }); | ||
} | ||
}, | ||
|
||
inductiveCase: { | ||
privateInputs: [SelfProof, PasswordInTreeWitness], | ||
method(publicInput: MerkleRoot, earlierProof: SelfProof<MerkleRoot, ProvePasswordInTreeOutput>, privateInput: PasswordInTreeWitness): ProvePasswordInTreeOutput { | ||
earlierProof.verify(); | ||
privateInput.witness | ||
.calculateRoot(Poseidon.hash([publicInput.root])) | ||
.assertEquals(publicInput.root); | ||
return new ProvePasswordInTreeOutput( | ||
{ recursiveMekleRootHash: Poseidon.hash([publicInput.root, earlierProof.publicOutput.recursiveMekleRootHash]) }); | ||
} | ||
} | ||
} | ||
} | ||
}); | ||
|
||
export default ProvePasswordInTreeProgram; | ||
export default ProvePasswordInTreeProgram; |
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