Flutter计算器插件circom_witnesscalc的使用
Flutter计算器插件circom_witnesscalc的使用
本库是circom-witnesscalc的Flutter封装。它用于为零知识证明计算见证文件,并用Rust编写。
平台支持
- iOS: 兼容任何具有64位架构的iOS设备。
- macOS: 兼容任何具有arm64位架构的macOS设备。
- Android: 兼容arm64-v8a和x86_64架构。
安装
在pubspec.yaml
文件中添加依赖:
flutter pub add circom_witnesscalc
使用
calculateWitness
函数接受输入的JSON字符串和图数据文件字节,并返回见证字节。
import 'package:circom_witnesscalc/circom_witnesscalc.dart';
// ...
final String inputs = await rootBundle.loadString("assets/authV2_inputs.json");
final Uint8List graphData = (await rootBundle.load("assets/authV2.wcd")).buffer.asUint8List();
final proof = await CircomWitnesscalc().calculateWitness(inputs, graphData);
示例应用
示例代码
以下是一个完整的示例代码,展示了如何使用circom_witnesscalc
插件生成见证文件和证明。
import 'dart:convert';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:circom_witnesscalc/circom_witnesscalc.dart';
import 'package:flutter_rapidsnark/flutter_rapidsnark.dart';
import 'package:share_plus/share_plus.dart';
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final _circomWitnesscalcPlugin = CircomWitnesscalc();
String? _inputsPath;
String? _graphWCDPath;
String? _zkeyFilePath;
String? _defaultInputsPath;
String? _defaultGraphWCDPath;
String? _defaultZkeyFilePath;
Uint8List? _witness;
int _witnessTimestamp = 0;
int _proofGenerationTimestamp = 0;
String? _proof;
String _errorMessage = "";
[@override](/user/override)
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
await copyAssetToDocumentsDirectory('assets/authV2_inputs.json');
await copyAssetToDocumentsDirectory('assets/authV2.wcd');
await copyAssetToDocumentsDirectory('assets/authV2.zkey');
final directory = await getApplicationDocumentsDirectory();
_defaultInputsPath = '${directory.path}/authV2_inputs.json';
_defaultGraphWCDPath = '${directory.path}/authV2.wcd';
_defaultZkeyFilePath = '${directory.path}/authV2.zkey';
resetData();
});
}
void resetData() {
setState(() {
_inputsPath = _defaultInputsPath;
_graphWCDPath = _defaultGraphWCDPath;
_zkeyFilePath = _defaultZkeyFilePath;
resetOutputs();
});
}
void resetOutputs() {
_witness = null;
_witnessTimestamp = 0;
_proofGenerationTimestamp = 0;
_proof = null;
_errorMessage = "";
}
Future<void> copyAssetToDocumentsDirectory(String asset) async {
final directory = await getApplicationDocumentsDirectory();
final fileName = asset.split('/').last;
final file = File('${directory.path}/$fileName');
if (!await file.exists()) {
final byteData = await rootBundle.load(asset);
await file.writeAsBytes(byteData.buffer.asUint8List(), flush: true);
}
}
[@override](/user/override)
Widget build(BuildContext context) {
final String witnessResult;
if (_errorMessage.isNotEmpty) {
witnessResult = "Error: $_errorMessage";
} else if (_witness != null) {
witnessResult = ("Witness generated in $_witnessTimestamp millis");
} else {
witnessResult = "Generate witness";
}
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
ElevatedButton(
onPressed: resetData,
child: const Text("Reset all inputs"),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.black,
foregroundColor: Colors.white,
),
),
const SizedBox(height: 16),
ListTile(
title: Text(
_defaultInputsPath != _inputsPath
? "Inputs json: ${basename(_inputsPath!)}"
: "Default authV2 inputs selected",
style: const TextStyle(fontSize: 16),
),
trailing: ElevatedButton.icon(
onPressed: () async {
final result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ["json"],
);
final file = result?.files.first;
if (file != null && file.path != null) {
setState(() {
_inputsPath = file.path!;
resetOutputs();
});
}
},
icon: const Icon(Icons.file_open),
label: const Text("Select"),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.black,
foregroundColor: Colors.white,
),
),
),
const SizedBox(height: 16),
ListTile(
title: Text(
_defaultGraphWCDPath != _graphWCDPath
? "Selected .wcd graph file: ${basename(_graphWCDPath!)}"
: "Default authV2.wcd graph selected",
style: const TextStyle(fontSize: 16),
),
trailing: ElevatedButton.icon(
onPressed: () async {
final result = await FilePicker.platform
.pickFiles(type: FileType.any);
final filePath = result?.files.first.path;
if (filePath != null) {
setState(() {
_graphWCDPath = filePath;
resetOutputs();
});
}
},
icon: const Icon(Icons.file_open),
label: const Text("Select"),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.black,
foregroundColor: Colors.white,
),
),
),
const SizedBox(height: 16),
ListTile(
title: Text(
_defaultZkeyFilePath != _zkeyFilePath
? "Selected .zkey File path: ${basename(_zkeyFilePath!)}"
: "Default authV2 zkey file selected",
style: const TextStyle(fontSize: 16),
),
trailing: ElevatedButton.icon(
onPressed: () async {
final result = await FilePicker.platform
.pickFiles(type: FileType.any);
final file = result?.files.first;
if (file?.path != null) {
setState(() {
_zkeyFilePath = file!.path!;
resetOutputs();
});
}
},
icon: const Icon(Icons.file_open),
label: const Text("Select"),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.black,
foregroundColor: Colors.white,
),
),
),
const SizedBox(height: 16),
Text(witnessResult, style: const TextStyle(fontSize: 16)),
const SizedBox(height: 16),
ElevatedButton.icon(
onPressed: onGenerateWitness,
icon: const Icon(Icons.play_arrow),
label: const Text("Generate witness"),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.black,
foregroundColor: Colors.white,
),
),
if (_witness != null) ...[
const SizedBox(height: 16),
ElevatedButton(
onPressed: onShare,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.black,
foregroundColor: Colors.white,
),
child: const Text("Share witness"),
),
const SizedBox(height: 16),
ElevatedButton.icon(
onPressed: onGenerateProof,
icon: const Icon(Icons.play_arrow),
label: const Text("Generate proof"),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.black,
foregroundColor: Colors.white,
),
),
],
if (_proof != null) ...[
const SizedBox(height: 16),
ElevatedButton(
onPressed: onShareProof,
child: const Text("Share proof"),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.black,
foregroundColor: Colors.white,
),
),
const SizedBox(height: 16),
Text("Proof generated in $_proofGenerationTimestamp millis",
style: const TextStyle(fontSize: 16)),
const SizedBox(height: 16),
Text(_proof!, style: const TextStyle(fontSize: 16)),
],
],
),
),
),
),
);
}
// Generate the witness
Future<void> onGenerateWitness() async {
final stopwatch = Stopwatch();
try {
if (_defaultInputsPath == null || _graphWCDPath == null) {
return;
}
final file = File(_inputsPath!);
final inputs = await file.readAsString();
final fileWCD = File(_graphWCDPath!);
final graphData = await fileWCD.readAsBytes();
stopwatch.start();
final witness = await _circomWitnesscalcPlugin.calculateWitness(
inputs: inputs,
graphData: graphData,
);
setState(() {
_witness = witness;
_witnessTimestamp = stopwatch.elapsedMilliseconds;
_errorMessage = "";
});
} on PlatformException catch (e) {
setState(() {
_errorMessage = e.message ?? "Unknown error";
});
} finally {
stopwatch.stop();
}
}
// Generate the proof
Future<void> onGenerateProof() async {
if (_witness == null) {
return;
}
final stopwatch = Stopwatch();
try {
stopwatch.start();
final zkProof = await Rapidsnark().groth16Prove(
zkeyPath: _zkeyFilePath!,
witness: _witness!,
);
_proofGenerationTimestamp = stopwatch.elapsedMilliseconds;
//console log the proof and public signals
final proofData = {
'proof': zkProof.proof,
'pubSignals': zkProof.publicSignals,
};
// Convert the map to a JSON string
final proofJson = jsonEncode(proofData);
setState(() {
_proof = proofJson;
_errorMessage = "";
});
} on PlatformException catch (e) {
setState(() {
_errorMessage = e.message ?? "Unknown error";
});
} finally {
stopwatch.stop();
}
}
void onShare() {
if (_witness == null) {
return;
}
Share.shareXFiles(
[
XFile.fromData(_witness!, name: "witness.wtns"),
],
text: "Witness generated in $_witnessTimestamp millis",
);
}
void onShareProof() {
if (_proof == null) {
return;
}
Share.shareXFiles(
[
XFile.fromData(Uint8List.fromList(utf8.encode(_proof!)),
name: "proof.json"),
],
text: "Proof generated in $_proofGenerationTimestamp millis",
);
}
}
更多关于Flutter计算器插件circom_witnesscalc的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter计算器插件circom_witnesscalc的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
circom_witnesscalc
是一个用于生成零知识证明(ZKP)的 Flutter 插件,特别是在使用 Circom 电路时。它可以帮助你从电路中计算出 Witness(见证)数据,这是生成 ZKP 的重要步骤。以下是如何在 Flutter 项目中使用 circom_witnesscalc
插件的基本指南。
1. 安装插件
首先,在 pubspec.yaml
文件中添加 circom_witnesscalc
插件依赖:
dependencies:
circom_witnesscalc: ^0.1.0 # 请根据实际情况使用最新版本
然后运行 flutter pub get
来安装依赖。
2. 导入插件
在你的 Dart 文件中导入插件:
import 'package:circom_witnesscalc/circom_witnesscalc.dart';
3. 加载电路
在使用 circom_witnesscalc
之前,你需要加载一个 Circom 电路。通常,电路会被编译为一个 .wasm
文件:
String circuitWasmPath = 'path/to/your/circuit.wasm';
final witnessCalculator = WitnessCalculator(circuitWasmPath);
4. 计算 Witness
接下来,你可以使用 calculateWitness
方法来计算 Witness。你需要传递一个包含输入的 JSON 字符串:
String inputJson = '''
{
"a": "123",
"b": "456"
}
''';
final witness = await witnessCalculator.calculateWitness(inputJson);
print('Witness: $witness');
5. 处理 Witness 数据
calculateWitness
方法返回的 witness
是一个包含 Witness 数据的数组。你可以根据需要进行进一步处理,比如将其用于生成零知识证明。
6. 错误处理
在使用过程中,可能会遇到一些错误,比如无效的输入或电路加载失败。确保添加适当的错误处理:
try {
final witness = await witnessCalculator.calculateWitness(inputJson);
print('Witness: $witness');
} catch (e) {
print('Error calculating witness: $e');
}
7. 示例代码
以下是一个完整的示例代码:
import 'package:circom_witnesscalc/circom_witnesscalc.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Circom Witness Calculator Example')),
body: Center(
child: ElevatedButton(
onPressed: () async {
try {
String circuitWasmPath = 'path/to/your/circuit.wasm';
final witnessCalculator = WitnessCalculator(circuitWasmPath);
String inputJson = '''
{
"a": "123",
"b": "456"
}
''';
final witness = await witnessCalculator.calculateWitness(inputJson);
print('Witness: $witness');
} catch (e) {
print('Error calculating witness: $e');
}
},
child: Text('Calculate Witness'),
),
),
),
);
}
}