1. 链桨介绍

链桨(PaddleDTX)是一个基于去中心化存储的专注于分布式机器学习技术的解决方案,攻克海量隐私数据的安全存储问题,并且实现多方数据的安全交换,助其突破数据孤岛,共同建模,联合发挥数据的最大价值.
https://xuper.baidu.com/n/ps/paddleDTX
https://github.com/PaddlePaddle/PaddleDTX
https://paddledtx.readthedocs.io/zh_CN/latest/introduction/introduction.html

1.1 主要特征

链桨(PaddleDTX)的主要特征如下:

  • 支持多个学习过程并行运行的多方安全计算框架,集成多种横向联邦学习和纵向联邦学习算法
  • 安全存储高敏感数据,防止隐私泄漏,支持故障容错,抵御存储作弊
  • 去中心化管理存储节点,支持无上限数据纳管
  • 保证多方数据联合建模的全链路可信

1.2 节点和网络

链桨(PaddleDTX)中有五类节点:

  1. 计算需求节点(Requester)有训练模型和预测需求.
  2. 任务执行节点(Executor)拥有使用数据的权限,参与多方安全计算,进行模型训练和数据预测.
  3. 数据持有节点(DataOwner)是数据的归属方,有存储数据的需求.
  4. 存储节点(Storage Nodes)有丰富的闲置的存储资源,可以提供存储服务.
  5. 区块链节点 构成区块链网络(Blockchain Network),基于不同的区块链框架,他们有不同的定义.

计算需求节点、任务执行节点,以及数据持有节点组建了链桨的计算层.数据持有节点和存储节点组建了去中心化存储网络,负责数据的存取.训练任务和预测任务通过区块链网络广播到任务执行节点,后者继而执行训练任务和预测任务.数据持有节点和存储节点在副本保持证明、健康状态监控过程中,通过区块链网络实现信息交换.

1.3 架构概览

链桨(PaddleDTX)由多方安全计算网络、去中心化存储网络、区块链网络构建而成.

1.4 多方安全计算网络

有预测需求的一方为计算需求节点.可获取样本数据进行模型训练和预测的一方为任务执行节点,多个任务执行节点组成一个SMPC(多方安全计算)网络.计算需求节点将任务发布到区块链网络,任务执行节点确认后执行任务.数据持有节点对任务执行节点的计算数据做信任背书. SMPC是一个支持多个学习过程并行运行的框架,目前开源了纵向联邦学习算法,包括多元线性回归和多元逻辑回归.会陆续集成更多纵向联邦学习、横向联邦学习算法. 多方安全计算网络包含以下服务:

  • 计算需求节点(Requester),向区块链网络发布计算任务,从任务执行节点获取任务执行结果,并做可信性验证.
  • 任务执行节点(Executor),从区块链上获取要参与执行的任务,确认数据的使用权限后执行任务.做权限确认的过程也是数据持有节点对数据的可信性做背书的过程.

1.5 去中心化存储网络(XuperDB)

数据持有节点将自己的隐私数据进行加密、切分、副本复制后分发到存储节点,存储节点通过应答数据持有节点的挑战证明自己持有数据分片.通过这些机制,实现了在不泄漏隐私的前提下充分且安全地利用存储资源.
XuperDB 网络由三类节点构成:

  • 数据持有节点(DataOwner):数据的归属方,有存储需求,将自己的隐私数据进行加密、切分、副本制作后分发到存储节点;
  • 存储节点(Storage):有丰富的闲置的存储资源,可以提供存储服务,通过应答数据持有节点的挑战证明自己持有数据分片;
  • 区块链节点(Blockchain):构成区块链网络,支撑整个存储网络的去中心化治理,数据持有节点和存储节点在副本保持证明、健康状态监控过程中,通过区块链网络实现信息交换.

XuperDB 系统目前主要具备文件上传下载、链上存证、副本保持证明、系统健康状态监控和文件迁移、资源访问控制等功能.

  1. 文件多副本分片存储
    为保证数据的安全高可用,一个原始文件在系统中常采用多副本存储,用户可根据文件的安全级别为其设置副本数量. 文件经过持有方加密、切分和二次加密等操作,分散并乱序分发给不同存储节点,且同一文件分片在不同存储节点中的存储内容是不同的,以此抵御单副本攻击,防止节点串谋.
  2. 文件详情上链
    为便于网络监管和审计、保证数据完整性,文件成功上传后,需要将文件详情记录到区块链中,主要包括文件名称、文件ID、文件所有者身份、文件结构信息密文(切片顺序和哈希)、每个切片所在的存储节点、文件发布时间和过期时间等.
  3. 文件原文恢复
    系统支持数据持有方从多个存储节点恢复原始数据,主要步骤包括:从链上获取文件结构加密信息、解密结构信息得到文件对应的切片顺序和所在存储节点列表、分别从相应存储节点拉取切片、按顺序组装切片获得原始数据.
  4. 副本保持证明
    系统采用了副本保持证明挑战和应答机制,保证文件切片被安全存储.目前支持两种副本保持证明协议:基于梅克尔树的协议和基于双线性对映射的协议.前者空间复杂度高、计算复杂度低,后者空间复杂度低、计算复杂度高.
  5. 健康状态监控
    系统支持存储节点和文件的健康状态监控,存储节点健康状态根据节点的活跃度和副本保持证明应答成功比例来衡量,文件分发时会优先选择健康的存储节点;
    文件健康状态根据每个切片的健康状态来衡量,每个切片的健康状态由其所在的存储节点健康状态决定.
  6. 文件迁移
    为保证文件的安全和高可用,数据持有方会定期检查己方文件的健康状态,并将非健康的文件切片从不健康的存储节点迁移到健康节点,保证每个文件都处于健康且可随时恢复的状态.
  7. 资源访问控制
    系统设计了一套统一的数据访问授权方案,将数据使用需求方与持有方解耦.各需求方向数据持有节点发起使用授权申请,持有节点可选择通过或拒绝,授权通过的需求方可直接从存储节点获取数据并解密恢复.整个授权流程基于智能合约,最小化授权粒度,保证在数据持有方安全可信授权的基础上,各需求方便捷的使用数据.

2.编译安装

2.1 安装XuperChain

参照文档安装启动XuperChain,v3和v5版本都兼容,本文使用v5版本.
https://xuper.baidu.com/n/xuperdoc/quickstart/quickstart.html
https://www.jiagou.com/post/67-xuperchain

2.2 编译

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
### 下载源码
git clone https://github.com/PaddlePaddle/PaddleDTX.git

### 编译xdb
cd PaddleDTX/xdb
make

### 编译Distributed AI
cd ../dai
make

### 编译区块链合约 paddlempc,复制到xuperchain目录下
go build -o paddlempc ./blockchain/xchain/contract

2.3 部署合约

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
### 进入 xuperchain目录,生成 ukeys 账号
./bin/xchain-cli account newkeys --strength 1 -o ukeys

### 助忆词 后面会用到 # 缺 乎 根 敲 促 叶 诉 筛 碧 操 级 取
cat ./ukeys/mnemonic

### 获取生成的 address 
cat ./ukeys/address  # YHAJVqUtxLyeNtvf32PNrLFxQSbtUXPhY 
### 转账
./bin/xchain-cli transfer --to YHAJVqUtxLyeNtvf32PNrLFxQSbtUXPhY --amount 1000000000000

### 创建区块链合约账户, 并转 token
./bin/xchain-cli account new --account 1234567890123456 --fee 1000 --keys ./ukeys

### 给合约账户转 token
./bin/xchain-cli transfer --to XC1234567890123456@xuper --amount 100000000000 --keys ./ukeys

### 安装 paddlempc 合约
./bin/xchain-cli native deploy --account XC1234567890123456@xuper --runtime go -a '{"creator":"XC1234567890123456@xuper"}' --cname paddlempc ./paddlempc --fee 20967894 --keys ./ukeys

### 查询合约安装的状态
./bin/xchain-cli contract query paddlempc

2.4 修改xdb配置

进入 xdb 目录 PaddleDTX/xdb/output,修改 ./conf/config-dataowner.toml./conf/config-storage.toml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
### config-dataowner.toml 数据拥有节点的配置文件
type = "dataOwner"

[dataOwner]
### 节点名称
name = "dataOwnerNode1"
### 端口
listenAddress = ":8121"
keyPath = "./keys"
### 访问地址
publicAddress = "127.0.0.1:8121"

[dataOwner.slicer]
    type = "simpleSlicer"
    [dataOwner.slicer.simpleSlicer]
        blockSize = 4194304
        queueSize = 4
[dataOwner.encryptor]
    type = "softEncryptor"
    [dataOwner.encryptor.softEncryptor]
        password = "abcdefg"
[dataOwner.challenger]
    type = "pdp"
    [dataOwner.challenger.pdp]
        maxIndexNum = 5
        sk = "W4HyiC7kx+bafMftHrD7Mz4ff2/0Bb103fUIrbRVkFk="
        pk = "AVcT6JO4Ddcq+JjC2Vw/kGZSrCjEeCu1Lu1EFya9C96Nb/HtJkaHEJ4Ni89leAAaCbKu/oEFrfEpb3oAaEd2JqNuyBlWZ0MZk7PmFkaUlYaTVvQRUWRRSmiIZa+iNtJEIYC/AC5C88k1vRoXq3m7VonvJUFP95oLX3CSMMfSiUln"
        randu = "AfM3n7CzmkbVEBRPOYV8gH1qpyaQdTNA1MZ7PHYfmWs="
        randv = "TKOt9kE7m5O7fCztoyy1J+WpNugLxKPS3hweeUK+09Y="
    [dataOwner.challenger.merkle]
        leveldbRoot = "/home/data/challenger"
        shrinkSize = 500
        segmentSize = 5

[dataOwner.blockchain]
    ### 支持 xuperchain和fabric,默认使用xuperchain
    type = "xchain"
    [dataOwner.blockchain.xchain]
        ### xuperchain创建的 ukeys助忆词 cat ./ukeys/mnemonic
        mnemonic = "缺 乎 根 敲 促 叶 诉 筛 碧 操 级 取"
        ### 合约名称
        contractName = "paddlempc"
        ### 合约账户
        contractAccount = "XC1234567890123456@xuper"
        ###链地址
        chainAddress = "127.0.0.1:37101"
        chainName = "xuper"

    [dataOwner.blockchain.fabric]
        configFile = "./config/fabric/config.yaml"
        channelId = "mychannel"
        chaincode = "mycc"
        userName = "Admin"
        orgName = "org1"
[dataOwner.copier]
    type = "random-copier"
[dataOwner.monitor]
    challengingSwitch = "on"
    filemaintainerSwitch = "on"
    filemigrateInterval = 6
[log]
level = "debug"
path = "./logs"
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
### config-storage.toml 数据存储节点的配置文件
type = "storage"

[storage]
name = "storageNode1"
listenAddress = ":8122"
keyPath = "./keys"
publicAddress = "127.0.0.1:8122"

[storage.blockchain]
    ### 支持 xuperchain和fabric,默认使用xuperchain
    type = "xchain"

    [storage.blockchain.xchain]
        ### xuperchain 创建的 ukeys助忆词 cat ./ukeys/mnemonic
        mnemonic = "缺 乎 根 敲 促 叶 诉 筛 碧 操 级 取"
        ### 合约名称
        contractName = "paddlempc"
        ### 合约账户
        contractAccount = "XC1234567890123456@xuper"
        ###链地址
        chainAddress = "127.0.0.1:37101"
        chainName = "xuper"

    [storage.blockchain.fabric]
        configFile = "./config/fabric/config.yaml"
        channelId = "mychannel"
        chaincode = "mycc"
        userName = "Admin"
        orgName = "org1"
[storage.mode]
    type = "local"
    [storage.mode.local]
        rootPath = "./slices"
[storage.monitor]
    challengingSwitch = "on"
    nodemaintainerSwitch = "on"
    fileclearInterval = 24
[log]
level = "debug"
path = "./logs"

2.5 xdb上传文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
cd PaddleDTX/xdb/output
### 每一个 XuperDB 的节点都有一对公私钥,用来标识节点的账户
./xdb-cli key genkey -o ./keys

### 启动存储节点和数据拥有节点
nohup ./xdb -c conf/config-storage.toml > storage.log &
nohup ./xdb -c conf/config-dataowner.toml > dataowner.log &

### 查看存储节点
./xdb-cli nodes list --host http://127.0.0.1:8121


### 创建客户端账户
./xdb-cli key genkey -o ./ukeys
### 授权客户端帐号
./xdb-cli key addukey -o ./authkeys -u `cat ./ukeys/public.key`
### 创建命名空间 paddlempc
./xdb-cli files addns  --host http://127.0.0.1:8121 --keyPath './ukeys' -n paddlempc  -r 1
### 查看命名空间,返回paddlempc
./xdb-cli files listns  --host http://127.0.0.1:8121

### 复制测试数据vl目录到当前目录下
cp -rf PaddleDTX/dai/mpc/testdata/vl ./

### 发布 train_dataA.csv 测试数据,发布成功会返回FileID,例如:fc577ab6-4647-4ae7-93d1-915df7fdd43f
./xdb-cli --host http://127.0.0.1:8121 files upload -n paddlempc -m train_dataA.csv -i ./vl/linear_boston_housing/train_dataA.csv --ext '{"FileType":"csv","Features":"id,CRIM,ZN,INDUS,CHAS,NOX,RM", "TotalRows":457}'  -e '2022-12-10 12:00:00' -d 'train_dataA' --keyPath ./ukeys

### 发布 train_dataB.csv 测试数据,发布成功会返回FileID,例如:11f6b1d7-19dd-41f7-91ed-1104609dbb5c
./xdb-cli --host http://127.0.0.1:8121 files upload -n paddlempc -m train_dataB.csv -i ./vl/linear_boston_housing/train_dataB.csv --ext '{"FileType":"csv","Features":"id,AGE,DIS,RAD,TAX,PTRATIO,B,LSTAT,MEDV","TotalRows":457}'  -e '2022-12-10 12:00:00' -d 'train_dataB' --keyPath ./ukeys

### 查询文件
./xdb-cli files getbyid --host http://127.0.0.1:8121 -i 返回的FileID

2.6 修改executor执行器配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
cd PaddleDTX/dai
### 复制两个执行器
cp -r output executor1
cp -r output executor2

###分别进入两个执行器,生成各自的节点账户
cd PaddleDTX/dai/executor1
./executor-cli key genkey -o ./keys

cd PaddleDTX/dai/executor2
./executor-cli key genkey -o ./keys

修改两个执行器的配置文件./conf/config.toml./conf/config-cli.toml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
### 执行器的配置文件 ./conf/config.toml
[executor]
### 执行器1的名称,执行器2为executor2
name = "executor1"
###监听的端口,执行器2为 :8185
listenAddress = ":8184"
###监听的端口,执行器2为 127.0.0.1:8185
publicAddress = "127.0.0.1:8184"
keyPath = "./keys"

[executor.mpc]
    trainTaskLimit = 100
    predictTaskLimit = 100
    rpcTimeout = 3
    taskLimitTime = 3600
[executor.storage]
    localModelStoragePath = "./models"
    ### 使用本地存储
    type = 'Local'

    [executor.storage.XuperDB]
        keyPath = "./ukeys"
        host = "http://127.0.0.1:8121"
        namespace = "paddlempc"
        expiretime = 72
    [executor.storage.Local]
        localPredictStoragePath = "./predictions"

[executor.blockchain]
    ### 使用xuperchain
    type = 'xchain'
    [executor.blockchain.xchain]
        ### xuperchain创建的 ukeys助忆词 cat ./ukeys/mnemonic
        mnemonic = "缺 乎 根 敲 促 叶 诉 筛 碧 操 级 取"
        ### 合约名称
        contractName = "paddlempc"
        ### 合约账户
        contractAccount = "XC1234567890123456@xuper"
        ### 链地址
        chainAddress = "127.0.0.1:37101"
        chainName = "xuper"

[log]
level = "debug"
path = "./logs"
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
### 执行器cli的配置文件 ./conf/config-cli.toml

### 使用xuperchain
[blockchain]
type = 'xchain'
[blockchain.xchain]
    ### xuperchain创建的 ukeys助忆词 cat ./ukeys/mnemonic
    mnemonic = "缺 乎 根 敲 促 叶 诉 筛 碧 操 级 取"
    ### 合约名称
    contractName = "paddlempc"
    ### 合约账户
    contractAccount = "XC1234567890123456@xuper"
    ### 链地址
    chainAddress = "127.0.0.1:37101"
    chainName = "xuper"

2.7 发布任务

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
### 分别启动两个执行器executor1和executor2
nohup ./executor &

### 查询任务执行节点列表,正常返回两个节点, 127.0.0.1:8184 和 127.0.0.1:8185
./requester-cli nodes list

### 发布训练任务, -f 参数 是xdb上传的两个文件的ID.至少需要两个文件和两个执行器
### 发布成功,会返回任务的ID,例如:cfd9ec8b-b42a-4a02-927c-64a40f4245cd
./requester-cli task publish -a "linear-vl" -l "MEDV" --keyPath './keys' -t "train" -n "房价预测任务v3" -d "hahahha" -p "id,id" --conf ./conf/config.toml -f "fc577ab6-4647-4ae7-93d1-915df7fdd43f,11f6b1d7-19dd-41f7-91ed-1104609dbb5c" -e "executor1,executor2"

###任务发布后,会申请读取文件,xdb查询申请的AuthID,并授权同意
### 查询所有的授权
./xdb-cli --host http://localhost:8121 files listauth
### 根据任务执行者和数据拥有着查询授权申请的AuthID,例如: f24c0be2-ff39-4c8a-9c0e-dab85966b788 和 a30b1712-1af1-44bf-83cc-39eb5fd3624f
### 注意: -o 参数使用的是数据节点的公钥,不是用户ukeys的公钥,目前存在数据节点权限过大和所有权的问题,节点权力大于用户权力.
./xdb-cli --host http://127.0.0.1:8121 files listauth -a `cat ../../dai/executor1/keys/public.key` -o `cat ./keys/public.key`
./xdb-cli --host http://127.0.0.1:8121 files listauth -a `cat ../../dai/executor2/keys/public.key` -o `cat ./keys/public.key`
### 授权使用文件,使用 -key参数,节点是私钥也可以授权,,目前存在数据节点权限过大和所有权的问题,节点权力大于用户权力.
./xdb-cli files confirmauth --host http://127.0.0.1:8121 -e '2022-08-08 15:15:04' -i f24c0be2-ff39-4c8a-9c0e-dab85966b788 --keyPath ./ukeys
./xdb-cli files confirmauth --host http://127.0.0.1:8121 -e '2022-08-08 15:15:04' -i a30b1712-1af1-44bf-83cc-39eb5fd3624f --keyPath ./ukeys

### 启动训练任务 --id 是发布的训练任务ID
./requester-cli task start --id cfd9ec8b-b42a-4a02-927c-64a40f4245cd --keyPath './keys' --conf ./conf/config.toml

### 发布预测任务, -f 参数 是xdb上传的两个文件的ID ,-i 是训练任务的ID ,会返回预测任务的ID,例如: dc9b8c95-8381-4e4c-b005-9c56a235e4e2
./requester-cli task publish -a "linear-vl" --keyPath './keys' -t "predict" -n "房价任务v3" -d "hahahha" -p "id,id" --conf ./conf/config.toml -f "fc577ab6-4647-4ae7-93d1-915df7fdd43f,11f6b1d7-19dd-41f7-91ed-1104609dbb5c" -i cfd9ec8b-b42a-4a02-927c-64a40f4245cd  -e "executor1,executor2"

### 启动预测任务, --id 是预测任务的ID
./requester-cli task start --id dc9b8c95-8381-4e4c-b005-9c56a235e4e2 --keyPath './keys' --conf ./conf/config.toml

### 获取预测结果, --id 是预测任务的ID
./requester-cli task result --id dc9b8c95-8381-4e4c-b005-9c56a235e4e2 --keyPath './keys' --conf ./conf/config.toml  -o ./output.csv