一、编程语言和开发环境
(1)Frutta语言
(2)操作系统windows(后续支持linux),chrome浏览器(需先安装Frutta谷歌浏览器插件)
(3)MPC应用部署
环境搭建(要求linux系统)
安装nginx
安装JDK,配置JDK环境变量
二、安装插件
使用JUGO-IDE之前,需要先安装Frutta谷歌浏览器插件。安装后可在JUGO-IDE中使用Frutta语言编写算法。
安装步骤:
第一步,请点击下载Frutta谷歌浏览器插件的安装包https://jugo.juzix.net/file/PLUGIN.tar.gz,并在本地解压。
第二步,在Chrome浏览器地址栏输入chrome://extensions/,启用开发者模式,然后点击按钮“加载已解压的扩展程序”,选择插件所在的文件夹即可。
注意:由于该插件暂未上传Google插件商店,所以只能以开发者模式运行。打开chrome://extensions/,如下图示开启开发者模式。由于是以开发者模式运行该插件的,Chrome浏览器会弹出“请停用以开发者模式运行的扩展程序”的提示,此时点击“取消”才可以继续使用Frutta谷歌浏览器插件。
- JUDO-IDE
结合Frutta谷歌浏览器插件,开发者无需搭建任何环境就可以快速编写、编译、运行和发布算法。
通过使用JUGO-IDE,开发者可使用Frutta语言编写算法,并通过JUGO-IDE编译成可在JUGO技术产品上执行的电路文件和java模板文件。详情https://jugo.juzix.net/api_document/jugoide/jugoide.html - Frutta语言
Frutta是矩阵元为安全多方计算的算法电路文件生成而专门定制的编程语言。它是一门类高级语言,也是一门面向过程的编程语言。Frutta支持大部分运算符、数据类型,表达方式灵活实用。目前只有矩阵元提供的在线ide可以进行编译运行。IDE可以把Frutta文件编译成可在JUGO平台上执行的电路文件。详情https://jugo.juzix.net/api_document/frutta/frutta.html
三、开发编程
(1)计算逻辑编程(在IDE中)
计算逻辑:为实现某个场景下的安全多方计算所编写的算法。
使用Frutta语言,在JUGO-IDE中可以快速完成计算逻辑的编程、验证和发布。
(2)JUDO-SDK
JUGO-SDK是JUGO技术产品面向开发者提供的安全多方计算应用开发工具包。
开发者通过使用JUGO-SDK与其他JUGO技术产品,可以高效快速的开发MPC(安全多方计算)应用。每个集成了SDK的应用将作为计算节点接入到计算网络中。应用调用SDK可以实现安全多方计算以满足业务需求。
支持语言:JAVA语言。
JDK版本:JDK1.8。
开发工具:推荐使用 IntelliJ IDEA。
开发环境:操作系统window/linux,ICE-3.6
调试环境:由于MPC算法库目前仅支持.so动态库(Linux平台运行),所以开发阶段部分功能可在window上进行调试,完整的计算流程需要在Linux环境上进行。
运行环境:目前仅支持运行在Linux环境,推荐:CentOS Linux release 7.2.1511 (Core)。
电路文件:后缀格式规定为:.gc
SDK使用步骤:
1.引入JUDO-SDK
SDK仓库地址:http://sdk.juzix.net/content/groups/public/
Maven:
-
<dependency>
-
<groupId>com.juzix.jugo</groupId>
-
<artifactId>mpc-node-sdk</artifactId>
-
<version>1.1.0-SNATSHOP</version>
-
</dependency>
Gradle
-
compile "com.juzix.jugo:mpc-node-sdk:1.1.0-SNATSHOP"
Jar包引用下载https://jugo.juzix.net/file/JAVA-SDK.zip
下载后会得到一个zip包,解包后将对应jar包全部拷贝到本地项目中依赖引用。
2.算法动态库
底层算法逻辑使用c/c++进行编写,JAVA使用JNI进行调用。目前仅提供了Linux环境下的动态库(.so),因此测试环节需在Linux完成。下载解压后会得到一个libjuzixmpc.so动态库文件,需要更改配置文件mpc-node-config.conf进行配置 。此操作是必须的,否则无法完成计算操作。
算法动态库 下载https://jugo.juzix.net/file/libjuzixmpc.zip
3.配置文件创建
JUGO-SDK使用默认方式获取电路文件时需要一些配置信息,如自定义实现了CircuitManager,则无需提供配置文件。此处规定,配置文件名为:mpc-node-config.conf,必须在目录config下。配置文件可位于classes源码目录或者
u
s
e
r
.
d
i
r
工
作
目
录
。
如
果
使
用
I
D
E
A
开
发
工
具
,
则
可
将
配
置
文
件
放
置
在
:
{user.dir}工作目录。如果使用IDEA开发工具,则可将配置文件放置在:
user.dir工作目录。如果使用IDEA开发工具,则可将配置文件放置在:{project.dir}/src/main/resources/config/mpc-node-config.conf。
文件内容如下
1. node {
2. isDebug=false
3. # 是否使用Glacier2进行消息路由 false 不使用, true 使用
4. isRouterModel=false
5. circuit {
6. # 电路文件下载地址,此处将IP和port更改为实际地址即可
7. download.url = "http://xxx:port/file_api/file/download?arithmeticId=%s&user=%s"
8. # 电路文件本地存储目录
9. local.dirPath = /home/test/developer/jugompc
10. }
11. jni {
12. # jni调用的动态库文件目录
13. library.path=/home/test/developer/jnilib
14. }
15. }
注:完成以上2步操作基本完成了对JUGO-SDK的集成。请务必注意算法库的文件路经配置正确。
4.配置节点为服务节点
在启动一个节点的时,可以将节点作为一个服务节点启动。可直接接收对端(计算比较端)的数据,而不需要通过JUGO代理服务回调传输。在调用API-初始化节点(initContext)时,如果参数mode传入SERVER,则必须进行配置操作。如果传入CALLBACK则可忽略此步骤。
当节点需要作为服务节点启动时,需提供服务配置文件,并在初始化时通过参数args传入。
服务配置文件:config.node-server
1. # 当前节点作为服务提供的Endpoints信息
2. NodeServer.Endpoints=tcp -p 12001
3. Server.Trace=1
4. Ice.ThreadPool.Server.Size=10
5. Ice.ThreadPool.Server.SizeMax=10
6. Ice.ThreadPool.Client.Size=10
7. Ice.ThreadPool.Client.SizeMax=10
注:在创建电路实例中的
args=new String[]{“–Ice.Config=config.node-server”}
5.配置节点Glacier2
注意:如果配置文件mpc-node-config中,isRouterModel=false, 则无需启动节点Glacier2,该模式标识仅使用节点直连进行消息传递而不需要Glacier2进行消息路由。
Glacier2是ICE特有的应用层防火墙和路由器,提供了安全校验、消息路由和事务管理等功能。这里为了防止网络造成数据传输阻碍,引入Glacier2进行网络穿透。将节点服务放置在Glacier2之后,由Glacier2进行消息接收并路由到目标服务。
Glacier2配置文件:config.glacier2-node-server
1. #Glacier2实例名
2. Glacier2.InstanceName=NodeGlacier2
3. # 客户端访问Endpoints信息
4. Glacier2.Client.Endpoints=tcp -h 0.0.0.0 -p 4503 -t 12000
5. Glacier2.Server.Endpoints=tcp
6. # 会话创建服务地址,此处连接到节点服务的EEndpoings
7. Glacier2.SessionManager=NodeSessionManager:tcp -h 192.168.7.168 -p 12001
8. # 权限校验服务地址,此处连接到节点服务的Endpoints
9. Glacier2.PermissionsVerifier=NodePermissionsVerifier:tcp -h 192.168.7.168 -p 12001
10. Glacier2.SessionTimeout=30
11. Glacier2.Server.Buffered=0
12. Glacier2.Client.Buffered=0
13. IceSSL.Trace.Security=1
14. Ice.Trace.Network=1
15. Ice.Warn.Connections=1
16. Ice.Trace.Protocol=1
17. Ice.ThreadPool.Server.Size=10
18. Ice.ThreadPool.Server.SizeMax=10
19. Ice.ThreadPool.Client.Size=10
20. Ice.ThreadPool.Client.SizeMax=10
注:配置中为基本的Glacier2信息配置,具体含义请参考ICE详细文档。https://jugo.juzix.net/file/Ice-3.6b.pdf
启动Glacier2之前请确保本地已安装Ice并可正常使用。
启动Glaicer2命令为:
glacier2router --Ice.Config=./config.glacier2-node-server
使用Glacier2后,在调用节点初始化(initContext)时的参数jugoEndpoint=NodeGlacier2/router:tcp -h 127.0.0.1 -p 4503 -t 12000。后续再计算过程中对端节点会通过该Endpoints信息直接调用Glacier2进行数据转发路由到目标服务。
集成流程:
- IDE上编写电路算法;
- 编译算法并生成电路文件JAVA包装类;示例查看
- 项目中引入步骤2中的JAVA包装类;
- 集成API,完成应用开发;
初始化结点:
1.引入JUGO平台SDK库;
2.初始化节点,启动节点监听(包括发起方节点和接收方节点);
3.JUGO的节点初始化是以异步形式进行返回。
结点启定任务:
1.如果是被邀请方,无需启动任务
2.如果是发起方,需要进行启动任务
JUGO的节点初始化是以异步形式进行返回
算法代码参考:
#parties 2
#input 1 uint32
#input 2 uint32
#output 1 uint32
function void main()
{
/* 数据比较电路 (output1=1 && input1>input2)*/
output1 = input1/input2;
if(output1>0)
{
output1 = 1;
}
}
初始化结点代码参考:
1. compare = new Compare(SystemProperties.getDefault().getCompare(), SystemProperties.getDefault().getNode1UserName(), SystemProperties.getDefault().getNode1Password(), mode,SystemProperties.getDefault().getNode1Endpoint(), null, argsAttach);
2. //设置返回的callback对象,处理结果返回数据
3. compare.setOutputCallback(new OutputCallback<Uint32>(Uint32.class){
4. @Override
5. public void onResult(String taskId, String algorithmId, int resultCode, Uint32 result) {
6. logger.debug("获取到结果:任务ID:{},算法ID:{},错误码:{},值:{}",
7. taskId, algorithmId, resultCode, result.getValue().toString());
8. //根据返回值进行判断结果
9. if(resultCode == 0){
10. resultMapper.insertData(id, "获取最终结果,返回数据结果:我方值大于等于对方值,任务id:" + taskId, new Date(),Const.getType_one());}
11. else{
12. resultMapper.insertData(id, "获取最终结果,返回数据结果:对方值较大,任务id:" + taskId ,new Date(), Const.getType_one());}
13. }
14. @Override
15. public void onFailure(Throwable e) {
16. e.printStackTrace();
17. }
18. });
19. // 邀请方定义输入参数。对于输入发起方调用setInputCallbackForORG方法,被邀请方调用setInputCallbackForDST方法。
20. compare.setInputCallbackForORG(new InputCallback<Uint32>() {
21. @Override
22. public Uint32 onInput(String taskId, String algorithmId, String[] args) {
23. resultMapper.insertData(id, "准备参与计算参数,发起计算,任务id:" + taskId, new Date(),Const.getType_one());
24. //初始化后台输入参数
25. return new Uint32(BigInteger.valueOf(3));
26. }
27. @Override
28. public void onFailure(Throwable e) {
29. e.printStackTrace();
30. }
31. });
结点启动任务代码参考:
1. //初始化计算双方
2. List<String> takerList = Arrays.asList(new String[] { "admin01", "admin02" });
3. //初始化接收结果的参与方
4. List<String> resulReceiverList = Arrays.asList(new String[] { "admin01" , "admin02"});
5. //启动节点任务
6. compare.doCompute(SystemProperties.getDefault().getRoomId(), argsAttach, takerList, resulReceiverList);
(3)应用部署
应用包含三大部分的代码。包括:1)算法代码、2)服务端应用代码、3)前端页面展示代码。
实现流程:
- MPC应用部署
环境搭建(要求linux系统)
安装nginx
安装JDK,配置JDK环境变量 - 项目打包
项目依赖gradle进行构建;
可通过gradle指令进行打包,文件输出在同级build目录下;
可通过JAVA IDE打包可执行文件;
gradle指令:
clean build
Copy
- 项目运行
在环境中执行以下指令进行监听;
后续可通过统计目录nohup.out查看输出日志
指令参考:
nohup java -jar MPCAcceptApp.jar &//启动接收方节点
nohup java -jar MPCStartApp.jar &//启动发起方节点
Copy
- 项目调试
在浏览器中输入http://ip:port/swagger-ui.html ,可调试发起方接口。
在浏览器中输入http://ip:port/swagger-ui.html ,可调试接收方接口。