Skip to content

Commit

Permalink
fix challenge & gistRoot inputs (v3 on-chain)
Browse files Browse the repository at this point in the history
  • Loading branch information
volodymyr-basiuk committed Dec 5, 2023
1 parent 0d0380b commit 18fe29e
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 21 deletions.
7 changes: 2 additions & 5 deletions src/circuits/atomic-query-v3-on-chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,9 @@ export class AtomicQueryV3OnChainInputs extends BaseConfig {

s.authClaimIncMtp = prepareSiblingsStr(new Proof(), this.getMTLevel());
s.authClaimNonRevMtp = prepareSiblingsStr(new Proof(), this.getMTLevel());
s.challenge = zero;
s.challengeSignatureR8x = zero;
s.challengeSignatureR8y = zero;
s.challengeSignatureS = zero;
s.gistRoot = ZERO_HASH.bigInt().toString();
s.gistMtp = prepareSiblingsStr(new Proof(), this.getMTLevelOnChain());

s.authClaimNonRevMtpAuxHi = ZERO_HASH.bigInt().toString();
Expand Down Expand Up @@ -211,6 +209,8 @@ export class AtomicQueryV3OnChainInputs extends BaseConfig {
isRevocationChecked: 1
};

s.challenge = this.challenge?.toString();
s.gistRoot = this.gistProof.root.bigInt().toString();
if (this.authEnabled === 1) {
s.authClaim = this.authClaim?.marshalJson();
s.userClaimsTreeRoot = this.treeState.claimsRoot?.bigInt().toString();
Expand All @@ -219,14 +219,11 @@ export class AtomicQueryV3OnChainInputs extends BaseConfig {
s.userState = this.treeState.state?.bigInt().toString();
s.authClaimIncMtp = prepareSiblingsStr(this.authClaimIncMtp, this.getMTLevel());
s.authClaimNonRevMtp = prepareSiblingsStr(this.authClaimNonRevMtp, this.getMTLevel());
s.challenge = this.challenge?.toString();
s.challengeSignatureR8x = this.signature.R8[0].toString();
s.challengeSignatureR8y = this.signature.R8[1].toString();
s.challengeSignatureS = this.signature.S.toString();
s.gistRoot = this.gistProof.root.bigInt().toString();
s.gistMtp =
this.gistProof && prepareSiblingsStr(this.gistProof.proof, this.getMTLevelOnChain());

const nodeAuxAuth = getNodeAuxValue(this.authClaimNonRevMtp);
s.authClaimNonRevMtpAuxHi = nodeAuxAuth.key.bigInt().toString();
s.authClaimNonRevMtpAuxHv = nodeAuxAuth.value.bigInt().toString();
Expand Down
3 changes: 2 additions & 1 deletion src/iden3comm/handlers/contract-request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ export type ContractInvokeHandlerOptions = {
export class ContractRequestHandler implements IContractRequestHandler {
private readonly _allowedCircuits = [
CircuitId.AtomicQueryMTPV2OnChain,
CircuitId.AtomicQuerySigV2OnChain
CircuitId.AtomicQuerySigV2OnChain,
CircuitId.AtomicQueryV3OnChain
];

/**
Expand Down
25 changes: 10 additions & 15 deletions src/proof/proof-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -696,38 +696,33 @@ export class ProofService implements IProofService {
circuitInputs.verifierSessionID = proofReq.query.verifierSessionID
? BigInt(proofReq.query.verifierSessionID?.toString())
: BigInt(0);
circuitInputs.authEnabled = params.authEnabled ?? 1;
circuitInputs.authEnabled = params.authEnabled ?? 0;

circuitInputs.challenge = BigInt(params.challenge ?? 0);
const { nonce: authProfileNonce, genesisDID } =
await this._identityWallet.getGenesisDIDMetadata(identifier);
const authPrepared = await this.prepareAuthBJJCredential(genesisDID);
const id = DID.idFromDID(genesisDID);
const stateProof = await this._stateStorage.getGISTProof(id.bigInt());
const gistProof = toGISTProof(stateProof);
circuitInputs.gistProof = gistProof;
// auth inputs
if (circuitInputs.authEnabled === 1) {
const { nonce: authProfileNonce, genesisDID } =
await this._identityWallet.getGenesisDIDMetadata(identifier);

const challenge = BigInt(params.challenge ?? 0);
const authPrepared = await this.prepareAuthBJJCredential(genesisDID);

const authClaimData = await this.newCircuitClaimData(
authPrepared.authCredential,
authPrepared.authCoreClaim
);

const signature = await this._identityWallet.signChallenge(
challenge,
circuitInputs.challenge,
authPrepared.authCredential
);
const id = DID.idFromDID(genesisDID);
const stateProof = await this._stateStorage.getGISTProof(id.bigInt());

const gistProof = toGISTProof(stateProof);

circuitInputs.profileNonce = BigInt(authProfileNonce);
circuitInputs.authClaim = authClaimData.claim;
circuitInputs.authClaimIncMtp = authClaimData.proof;
circuitInputs.authClaimNonRevMtp = authPrepared.nonRevProof.proof;
circuitInputs.treeState = authClaimData.treeState;
circuitInputs.signature = signature;
circuitInputs.challenge = challenge;
circuitInputs.gistProof = gistProof;
}
return { inputs: circuitInputs.inputsMarshal(), vp };
}
Expand Down
152 changes: 152 additions & 0 deletions tests/handlers/contract-request.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,158 @@ describe('contract-request', () => {
options
);

expect(ciResponse).not.be.undefined;
expect((ciResponse.values().next().value as ZeroKnowledgeProofResponse).id).to.be.equal(
proofReq.id
);
});
// V3 integration test
it.skip('contract request flow V3 - integration test', async () => {
const stateEthConfig = defaultEthConnectionConfig;
stateEthConfig.url = rpcUrl;
stateEthConfig.contractAddress = '0x134b1be34911e39a8397ec6289782989729807a4';

const memoryKeyStore = new InMemoryPrivateKeyStore();
const bjjProvider = new BjjProvider(KmsKeyType.BabyJubJub, memoryKeyStore);
const kms = new KMS();
kms.registerKeyProvider(KmsKeyType.BabyJubJub, bjjProvider);
dataStorage = {
credential: new CredentialStorage(new InMemoryDataSource<W3CCredential>()),
identity: new IdentityStorage(
new InMemoryDataSource<Identity>(),
new InMemoryDataSource<Profile>()
),
mt: new InMemoryMerkleTreeStorage(40),
states: new EthStateStorage(stateEthConfig)
};
const circuitStorage = new FSCircuitStorage({
dirname: path.join(__dirname, '../proofs/testdata')
});

const resolvers = new CredentialStatusResolverRegistry();
resolvers.register(
CredentialStatusType.Iden3ReverseSparseMerkleTreeProof,
new RHSResolver(dataStorage.states)
);
credWallet = new CredentialWallet(dataStorage, resolvers);
idWallet = new IdentityWallet(kms, dataStorage, credWallet);

proofService = new ProofService(idWallet, credWallet, circuitStorage, dataStorage.states, {
ipfsNodeURL
});
packageMgr = await getPackageMgr(
await circuitStorage.loadCircuitData(CircuitId.AuthV2),
proofService.generateAuthV2Inputs.bind(proofService),
proofService.verifyState.bind(proofService)
);
contractRequest = new ContractRequestHandler(packageMgr, proofService, mockZKPVerifier);

const { did: userDID, credential: cred } = await idWallet.createIdentity({
method: DidMethod.Iden3,
blockchain: Blockchain.Polygon,
networkId: NetworkId.Mumbai,
seed: seedPhrase,
revocationOpts: {
type: CredentialStatusType.Iden3ReverseSparseMerkleTreeProof,
id: rhsUrl
}
});

expect(cred).not.to.be.undefined;

const { did: issuerDID, credential: issuerAuthCredential } = await idWallet.createIdentity({
method: DidMethod.Iden3,
blockchain: Blockchain.Polygon,
networkId: NetworkId.Mumbai,
seed: seedPhraseIssuer,
revocationOpts: {
type: CredentialStatusType.Iden3ReverseSparseMerkleTreeProof,
id: rhsUrl
}
});
expect(issuerAuthCredential).not.to.be.undefined;

const claimReq: CredentialRequest = {
credentialSchema:
'https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json/KYCAgeCredential-v3.json',
type: 'KYCAgeCredential',
credentialSubject: {
id: userDID.string(),
birthday: 19960424,
documentType: 99
},
expiration: 2793526400,
revocationOpts: {
type: CredentialStatusType.Iden3ReverseSparseMerkleTreeProof,
id: rhsUrl
}
};
const issuerCred = await idWallet.issueCredential(issuerDID, claimReq);

await credWallet.save(issuerCred);

const proofReq: ZeroKnowledgeProofRequest = {
id: 1,
circuitId: CircuitId.AtomicQueryV3OnChain,
optional: false,
query: {
allowedIssuers: ['*'],
type: claimReq.type,
context:
'https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v3.json-ld',
credentialSubject: {
birthday: {
$lt: 20020101
}
}
}
};

const contractAddress = '0xEE6164690aBB9CCcBe9248D8eC0Da797f9F6C575';
const conf = defaultEthConnectionConfig;
conf.contractAddress = contractAddress;
conf.url = rpcUrl;
conf.chainId = 80001;

const zkpVerifier = new OnChainZKPVerifier([conf]);
contractRequest = new ContractRequestHandler(packageMgr, proofService, zkpVerifier);

const transactionData: ContractInvokeTransactionData = {
contract_address: contractAddress,
method_id: 'b68967e2',
chain_id: conf.chainId
};

const ciRequestBody: ContractInvokeRequestBody = {
reason: 'reason',
transaction_data: transactionData,
scope: [proofReq as ZeroKnowledgeProofRequest]
};

const id = uuid.v4();
const ciRequest: ContractInvokeRequest = {
id,
typ: MediaType.PlainMessage,
type: PROTOCOL_MESSAGE_TYPE.CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE,
thid: id,
body: ciRequestBody
};

const ethSigner = new ethers.Wallet(walletKey);

const challenge = BytesHelper.bytesToInt(hexToBytes(ethSigner.address));

const options: ContractInvokeHandlerOptions = {
ethSigner,
challenge
};
const msgBytes = byteEncoder.encode(JSON.stringify(ciRequest));
const ciResponse = await contractRequest.handleContractInvokeRequest(
userDID,
msgBytes,
options
);

expect(ciResponse).not.be.undefined;
expect((ciResponse.values().next().value as ZeroKnowledgeProofResponse).id).to.be.equal(
proofReq.id
Expand Down

0 comments on commit 18fe29e

Please sign in to comment.