2025-11-13 07:06:16 +00:00
|
|
|
import {
|
|
|
|
|
Injectable,
|
|
|
|
|
InternalServerErrorException,
|
|
|
|
|
NotFoundException,
|
|
|
|
|
} from '@nestjs/common';
|
2025-11-13 05:31:48 +00:00
|
|
|
import { PrismaService } from '../prisma/prisma.service';
|
|
|
|
|
import { RekammedisService } from '../rekammedis/rekammedis.service';
|
2025-11-13 07:06:16 +00:00
|
|
|
import { groth16, wtns } from 'snarkjs';
|
|
|
|
|
import path from 'path';
|
2025-11-13 09:18:29 +00:00
|
|
|
import { RequestProofDto } from './dto/request-proof.dto';
|
|
|
|
|
import { LogProofDto } from './dto/log-proof.dto';
|
|
|
|
|
import { sha256 } from '@api/common/crypto/hash';
|
|
|
|
|
import { LogService } from '../log/log.service';
|
2025-11-13 05:31:48 +00:00
|
|
|
|
|
|
|
|
@Injectable()
|
|
|
|
|
export class ProofService {
|
|
|
|
|
constructor(
|
|
|
|
|
private prismaService: PrismaService,
|
|
|
|
|
private rekamMedisService: RekammedisService,
|
2025-11-13 09:18:29 +00:00
|
|
|
private logService: LogService,
|
2025-11-13 05:31:48 +00:00
|
|
|
) {}
|
|
|
|
|
|
2025-11-13 07:06:16 +00:00
|
|
|
buildDir = path.join(__dirname, '../../../', 'dist');
|
|
|
|
|
publicDir = path.join(__dirname, '../../../../', '/api/public');
|
|
|
|
|
wasmPath = path.join(this.publicDir, 'circuit.wasm');
|
|
|
|
|
zkeyPath = path.join(this.publicDir, 'circuit_final.zkey');
|
|
|
|
|
vkeyPath = path.join(this.publicDir, 'verification_key.json');
|
|
|
|
|
witnessPath = path.join(this.buildDir, 'witness.wtns');
|
|
|
|
|
|
|
|
|
|
async calculateWitness(age: number) {
|
|
|
|
|
const inputs = {
|
|
|
|
|
age: age,
|
|
|
|
|
threshold: 18,
|
|
|
|
|
};
|
|
|
|
|
await wtns.calculate(inputs, this.wasmPath, this.witnessPath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async generateProof() {
|
|
|
|
|
const { proof, publicSignals } = await groth16.prove(
|
|
|
|
|
this.zkeyPath,
|
|
|
|
|
this.witnessPath,
|
|
|
|
|
);
|
|
|
|
|
return { proof, publicSignals };
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-13 09:18:29 +00:00
|
|
|
async getProof(requestProofDto: RequestProofDto) {
|
|
|
|
|
const age = await this.rekamMedisService.getAgeByIdVisit(
|
|
|
|
|
requestProofDto.id_visit,
|
|
|
|
|
);
|
2025-11-13 07:06:16 +00:00
|
|
|
if (!age) {
|
|
|
|
|
throw new NotFoundException('ID Visit tidak ditemukan');
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-13 09:18:29 +00:00
|
|
|
// try {
|
|
|
|
|
// await this.calculateWitness(age);
|
|
|
|
|
// } catch (error) {
|
|
|
|
|
// console.log('Error during witness calculation:', error);
|
|
|
|
|
// throw new InternalServerErrorException(
|
|
|
|
|
// "Can't generate proof from input based on constraint. Please check the input data and try again.",
|
|
|
|
|
// );
|
|
|
|
|
// }
|
2025-11-13 07:06:16 +00:00
|
|
|
|
2025-11-13 09:18:29 +00:00
|
|
|
// const { proof, publicSignals } = await this.generateProof();
|
|
|
|
|
|
|
|
|
|
const { proof, publicSignals } = await groth16.fullProve(
|
|
|
|
|
{
|
|
|
|
|
age: age,
|
|
|
|
|
threshold: 18,
|
|
|
|
|
},
|
|
|
|
|
this.wasmPath,
|
|
|
|
|
this.zkeyPath,
|
|
|
|
|
);
|
2025-11-13 07:06:16 +00:00
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
proof: proof,
|
|
|
|
|
publicSignals: publicSignals,
|
|
|
|
|
};
|
|
|
|
|
}
|
2025-11-13 09:18:29 +00:00
|
|
|
|
|
|
|
|
async logVerificationProof(logProofDto: LogProofDto) {
|
|
|
|
|
const payload = {
|
|
|
|
|
id_visit: logProofDto.id_visit || null,
|
|
|
|
|
proofHash: logProofDto.proofHash || null,
|
|
|
|
|
proofResult: logProofDto.proofResult || null,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const payloadHash = sha256(JSON.stringify(payload));
|
|
|
|
|
|
|
|
|
|
const response = {
|
|
|
|
|
id: `PROOF_${payload.id_visit}`,
|
|
|
|
|
event: 'proof_verification_logged',
|
|
|
|
|
user_id: 'External',
|
|
|
|
|
payload: payloadHash,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// const response = await this.logService.storeLog({
|
|
|
|
|
// id: `PROOF_${payload.id_visit}`,
|
|
|
|
|
// event: 'proof_verification_logged',
|
|
|
|
|
// user_id: 'External',
|
|
|
|
|
// payload: payloadHash,
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
return response;
|
|
|
|
|
}
|
2025-11-13 05:31:48 +00:00
|
|
|
}
|