迅雷链文件系统文档

1. 文档说明

1.1 阅读对象

本文档适用于有高安全性、高隐私性、知识产权等数据存储、分发、商业化等需求的企业和个人。通过本文档,指导开发者使用迅雷链文件系统,进行数据的上传、下载、复制、删除、授权等行为,并基于此文档进行二次开发,使产品具备大数据分布式存储与信息上链等特性,让产品快速集成海量存储、不可篡改、可追溯、永不丢失、安全加密、授权转移等能力。

1.2 版本说明

v2.9(2018/8/13)

2. 专业术语

2.1 迅雷链文件系统

迅雷链文件系统(简称TCFS,全称为Thunder Chain File System)是迅雷在百万级共享计算节点的基础上,使用独创的分布式技术专为区块链打造的数据云存储与授权分发的开放式文件系统。开发者可使自己的产品具备文件数据分布式存储与信息上链等特性,从而快速集成公开透明、不可篡改、可追溯、高可靠、安全加密、海量存储、授权转移等能力。

主要有四个特性:

  1. 公开透明:数据使用安全加密哈希索引,修改后的文件是新的哈希,确保数据无法被篡改;基于merkle DAG结构独创的文件管理技术,保留文件的全部变更历史,公开可查询和追溯。
  2. 高安全性:数据使用安全切片存储,使用公私钥签名技术验证用户和文件的持有关系。独创的令牌授权机制,仅有授权的用户才可以访问数据。
  3. 高可靠性:数据使用FEC(前向纠删码)编码后,冗余存储在各个共享计算节点上,在系统级别采用了文件自动修复机制,数据具有超过15个9的可靠性。使用智能合约实现存储激励机制,确保参与节点稳定,使文件存储具有更高的可靠性。
  4. 海量数据存储:文件数据分布式存储在百万级的共享计算节点上,拥有高达数百PB且不断扩展的存储空间,可存储数百亿的文件量,充分满足业务需求。

3. 专业术语

3.1 APP ID

APP ID指开发者在开放平台注册时生成的用于标名所属应用的编号。

3.2 APP Key

APP Key指开发者APP ID对应的加密key,作为APP ID的令牌,不可外露。

3.3 Public Key/Private Key/Address

公钥(Public Key)与私钥(PrivateKey)是通过非对称加密算法得到的一个密钥对(即一个公钥和一个私钥)。地址(Address)是由公钥经过单向的加密哈希算法计算得到的编码值。在系统中,Address是用来标识用户, 标识文件的拥有者信息。Public Key/Private Key/Address是以keyjson的格式存储,生成方法见6.6.2节。

3.4 签名Sign

迅雷链文件系统所有的接口均需要用户对接口参数进行签名,用于验证Address身份是否合法。签名一般有以下几种获取方式:

  1. 调用链克口袋进行签名
  2. 通过服务器SDK进行签名
  3. 签名函数进行签名(具体生成算法,详见第5.7节签名详细说明)

3.5 TCFS Path

TCFS Path是基于授权的内容寻址规范,是将用户授权与merkle DAG目录结构结合的一种路径形式,格式定义如下: /tcfs/[owner]:[visitor]:[ts]:[sign]:[pathlength]/[newest/hash]/[path]/[filename]
详细见5.8节 TCFS Path详细说明

4. 开始使用

4.1 开发者注册登录

个人或者企业开发者要使用迅雷链文件系统前,必须先注册为开放平台的用户。手机号码是用户唯一标识。注册成功后,可以绑定邮箱,个人/企业认证,应用创建等操作,参见迅雷链新手指南

4.2 如何生成APP ID和APP Key

开发者完成应用创建并通过审核便会下发APP ID和App Key给到开发者,可在管理中心-应用中心-应用详情中查阅 APP ID指开发者在云存储注册时生成的用于标名所属业务的编号,App Key指开发者APP ID对应的加密key,作为APP ID的令牌,App Key需要开发者妥善保管。

4.3 如何计费

规格 购买12个月 当前优惠活动
100GB 优惠价99链克 满12个月返还99链克

说明:每次购买只能是100GB的整数倍。

5. 流程说明

5.1 使用迅雷链文件系统流程

avatar

5.2 APP ID验证流程

5.2.1 APP ID说明

企业和个人开发者需要进行注册,经过审批后,会得到一个APP ID以及对应的密钥Key。在调用接口时,需要传入APPID以及部分参数的md5值,迅雷链文件系统内部会校验两者是否匹配和合法,以验证身份。

5.2.2 APPID验证流程序列图

avatar
APPID/APPKey的验证逻辑在迅雷链文件系统的所有接口中均需要使用,key_md5的md5计算方式为: md5(APPID+APPKey+ts)。迅雷链文件系统要求ts的有效期不超过10分钟,如果迅雷链文件系统时间超过key_md5计算时间10分钟,则验证不通过。

5.2.3 举例说明

举例说明:

APPID=de61d625adef267d69d63ca711939d685ffc8007
APPKey= 4daa50d08a107185af2c015cba126575781f7b20
timestamp = 1529114930
md5_value=md5sum("de61d625adef267d69d63ca711939d685ffc80074daa50d08a107185af2c015cba126575781f7b201529114930")=2b2cface59cc85b0916a6c46b68f2f20

在 6.1参数结构定义中,传入的参数如下

TCFSAppCertification ac{
appid=”de61d625adef267d69d63ca711939d685ffc8007”
key_md5=”2b2cface59cc85b0916a6c46b68f2f20”
timestamp =1529114930
}

5.3 文件上传流程

5.3.1 上传说明

使用迅雷链文件系统中AddFile接口进行文件上传,需要进行APPID/APPKey的验证,以及Address的身份签名认证。验证通过后将读取本地文件,对文件进行编码切片,然后将切片分发到共享节点,并且将文件的文件信息写入迅雷链文件系统。

5.3.2 上传流程序列图

avatar

5.3.3 使用说明

第三方App在需要文件上传时,只需要完成如下步骤即可完成文件上传: 1, 通过第三方后台获取APPID+APPKey+ timestamp的md5值
2, 通过5.7节中描述的方式获取sign
3, 调用AddFile接口
4, 通过GetTaskStatus查询任务状态

5.4 文件下载

5.4.1 下载说明

使用迅雷链文件系统对文件进行下载时,是只能下载上传过的文件,没有上传过的文件以及没有权限的文件是不能进行下载的。下载文件需要进行APPID/APPKey的验证,以及Address的身份签名认证。

5.4.2 下载流程序列图

avatar

5.4.3 使用说明

第三方App在需要下载文件时,只需要完成如下步骤即可完成文件下载: 1, 通过第三方后台获取APPID+APPKey+ timestamp的md5值
2, 通过5.7节中描述的方式获取sign
3, 调用GetFile接口
4, 通过GetTaskStatus查询任务状态

5.5 文件复制

5.5.1 复制说明

迅雷链文件系统中的复制功能是用于将用户A(AddressA)所拥有的文件FA复制给用户B(AddressB),用户B的存储空间中也将拥有文件FA。

5.5.2 复制流程序列图

avatar

5.5.3 使用说明

第三方App在需要下复制文件时,只需要完成如下步骤即可完成文件复制:

  1. 通过第三方后台获取APPID+APPKey+ timestamp的md5值
  2. 通过5.7节中描述的方式获取sign,注意这里需要用户A(AddressA),用户B(AddressB)两者同时签名,并且签名需要增加filehash字段
  3. 调用CopyFile接口

5.5.4 复制功能使用示例

avatar 因为CopyFile是为了将文件由用户A复制给用户B,所以用户A与用户B均需要进行签名。

5.6 文件删除

5.6.1 删除说明

迅雷链文件系统中的删除功能是将用户A(addressA)的文件FA从最新的目录树中删除,该文件不再参与计费。系统定期清理未付费文件,所以删除后一段时间可能仍被成功访问,但文件的操作历史会一直保留。

5.6.2 删除流程序列图

avatar

5.6.3 使用说明

第三方App在删除文件时,只需要需要完成如下步骤即可完成文件删除:

  1. 通过第三方后台获取APPID+APPKey+timestamp的md5值
  2. 通过5.7节中描述的方式获取sign
  3. 调用DeleteFile接口

5.7 用户签名

5.7.1 签名说明

签名是指在接口中用于验证Address身份是否合法的认证信息。设计sign的目的是在用户的钱包用私钥进行签名时需要使用用户私钥,为了简化多次使用私钥,所以设计带有时限的签名用于一次签名后将签名保存起来,每次调用迅雷链文件系统SDK接口时将签名直接传入,以达到一次签名多次使用的目的。

5.7.2 签名生成方式

一般的,sign= UserSign (keyjson, passwd, data),其中keyjson为此用户钱包对应的keystore文件, passwd表示用户的密码。

签名sign获取,一般由以下三种获取方式:

  1. 调用链克口袋进行签名 avatar
  2. 通过服务器SDK进行签名 avatar
  3. 调用SDK用户签名接口UserSign avatar

5.8 TCFS Path详细说明

5.8.1 TCFS Path格式定义

/tcfs/[owner]:[visitor]:[ts]:[sign]:[pathlength]/[newest/hash]/[pathname]/[filename]
其中:
/为保留字符
tcfs为关键字,不可更改
owner为此路径的所有者
visitor为此路径的访问者
ts为sign的有效截止时间戳
sign表示文件所有者owner给访问者visitor此文件的授权签名,其中sign=UserSign(owner+visitor+ts+path[0:pathlength]),迅雷链文件系统会对签名进行验证,在有效时间戳时间内,签名一致,即可认为授权通过 pathlength表示文件路径中需要授权的文件路径长度
[newest/hash]/[pathname]/[filename]为文件路径的2种表示格式,newest/[pathname]/[filename]表示此文件对应的最新版本;hash/[pathname]/[filename]表示此文件对应的hash路径下的文件。

5.8.2 目录结构说明

文件路径的格式是基于目录结构的。并且目录结构需要支持newest与hash访问2种方式,在目录节点上,所有的节点都有版本信息,对应的hash值,以及newest指向当前目录结构的最新版本节点。
avatar
上图中,初始时newest指向空,添加f1结点后,newest指向version1。

avatar
上图中,添加d2/f2文件后,newest指针指向version2版本,并且所有的节点都有hash信息,用于提供hash目录查询功能。比如访问f1,采用hash的方式为/hash_v1/f1或者/hash_v2/f1均可以访问;采用newest的方式为/newest/f1。

5.8.3 格式举例说明

以下对格式进行详细举例说明:
格式1,带签名的newest格式
/tcfs/owner:visitor:ts:sign:pathlength/newest/[pathname]/[filename]
/tcfs/0x7eff122b94897ea5b0e2a9abf47b86337fafebdc:0xd5e51811fd8d4525aaa247e5d96800462b057db3:1535709360:0x052cb64baeeb12f49dd6c5d6db7ec93f0c5d45dc1bc1f728d0a2170bdd52af4f75fb02b4ed09825756dccdc55b8b09c6ab0ad11ccab441c9c9d0b7cb25e002b500:12/newest/abc/lib/
owner:0x7eff122b94897ea5b0e2a9abf47b86337fafebdc,表示此owner对目录/newest/abc/lib/的所有权
visitor: 0xd5e51811fd8d4525aaa247e5d96800462b057db3,表示此visitor需要访问/newest/abc/lib/目录
ts: 1535709360,表示owner对visitor访问owner所有目录/newest/abc/lib/的授权签名有效截止时间戳。
sign: 0x052cb64baeeb12f49dd6c5d6db7ec93f0c5d45dc1bc1f728d0a2170bdd52af4f75fb02b4ed09825756dccdc55b8b09c6ab0ad11ccab441c9c9d0b7cb25e002b500,表示此owner对visitor访问owner所有目录/newest/abc/lib/的授权签名。
pathlength:12。表示是对目录授权路径的长度,12表示是对/newest/abc/目录签名,并且规定对父路径签名之后,对子路径也拥有访问权。
path:/newest/abc/lib/,表示visitor需要访问的目录。

格式2,不带签名的newest格式
/tcfs/::::/newest/[pathname]/[filename]
/tcfs/::::/newest/中文目录3/abc/ddd
path: /newest/中文目录3/abc/ddd。表示owner需要访问的目录。注意没有签名sign字段时,只能是owner访问自己的目录。在6节接口列表中会由其它参数传递owner。

格式3,带签名的hash格式
/tcfs/0x7eff122b94897ea5b0e2a9abf47b86337fafebdc:0xd5e51811fd8d4525aaa247e5d96800462b057db3:1536148761:0xde2baffe959990d641be0aff1864fa27149212b2ccd774614c8a8bf63552d44c5bc9b334ded33722b52c7e53d91e68480574fe9342c2ad5e49f9f025af2348ce00:46/5415dc5c31c6e4849fb6063ba09ff18365c25a21/abc/
owner:0x7eff122b94897ea5b0e2a9abf47b86337fafebdc,表示此owner对目录/5415dc5c31c6e4849fb6063ba09ff18365c25a21/abc/的所有权
visitor: 0xd5e51811fd8d4525aaa247e5d96800462b057db3,表示此visitor需要访问/5415dc5c31c6e4849fb6063ba09ff18365c25a21/abc/目录
ts: 1536148761,表示owner对visitor访问owner所有目录授权签名有效截止时间戳。
sign: 0xde2baffe959990d641be0aff1864fa27149212b2ccd774614c8a8bf63552d44c5bc9b334ded33722b52c7e53d91e68480574fe9342c2ad5e49f9f025af2348ce00,表示此owner对visitor访问owner所有目录的授权签名。
pathlength:46。表示是对目录授权路径的长度,46表示是对/5415dc5c31c6e4849fb6063ba09ff18365c25a21/abc/目录签名,并且规定对父路径签名之后能够对子路径拥有访问权。
path: /5415dc5c31c6e4849fb6063ba09ff18365c25a21/abc/,表示visitor需要访问的目录。

格式4,不带签名的hash格式
/tcfs/::::/5415dc5c31c6e4849fb6063ba09ff18365c25a21/abc/
path: /5415dc5c31c6e4849fb6063ba09ff18365c25a21/abc/。表示owner需要访问的目录。注意没有签名sign字段时,只能是owner访问自己的目录

6. 接口列表

6.1 参数结构定义

定义两个结构体,作为通用参数,来简化后续的接口函数参数列表。

struct TCFSAppCertification { // 开发者签发的证书
char appid[64]; // 开发者标识
int64   timestamp; // sign的过期时间点(秒)
char sign[64];  // 对开发者身份的校验值 
};

struct TCFSUserCertification { // 用户签发的证书
char address[64]; // 用户身份标识
int64 timestamp; // 签名的过期时间点(秒)
char sign[128]; // 对结构体中成员的签名,用于对用户身份进行自校验
};

6.2 上传接口

int AddFile(TCFSAppCertification ac, TCFSUserCertification uc, const char srcPath, const char destPath, char* taskID, int length)

  • 功能说明:用于将文件加密后按切片上传存储到迅雷链文件系统
  • 参数
参数名 类型 说明
ac TCFSAppCertification* 用于传入开发者的appid以及key_md5信息
uc TCFSUserCertification* 用于传入文件拥有者钱包地址以及签名信息,其中sign= UserSign(keyjson, passwd, addr+appid+timestamp)
srcPath const char* 指需要上传的文件路径,只支持本地文件
destPath const char* 指目的TCFS目录,不带sign的newest格式
taskID char* 至少256字节的buffer,用于返回此次上传的任务id(以’\0’结尾)
length int taskID数组的长度
  • 返回值
参数名 类型 说明
ret int 如果上传任务添加成功返回0,失败返回-1

6.3 下载接口

int GetFile(TCFSAppCertification ac, TCFSUserCertification uc, const char tcfsPath, const char destLocalPath, char* taskID, int length)

  • 功能说明:将文件从迅雷链文件系统拉取并还原到本地文件
  • 参数
参数名 类型 说明
ac TCFSAppCertification* 用于传入开发者的appid以及key_md5信息
uc TCFSUserCertification* 用于传入文件拥有者钱包地址以及签名信息,其中sign= UserSign(keyjson, passwd, addr+appid+ timestamp)
tcfsPath const char* 指需要取回的文件TCFS路径,支持目录,访问他人目录时,必须为带sign的newest/hash的TCFS路径格式;访问自己目录时,使用不带sign的newest/hash的TCFS格式
destLocalPath const char* 用于指定取回文件存在的本地路径
taskID char* 至少256字节的buffer,用于返回此次下载的任务id(以’\0’结尾)
length int taskID数组的长度
  • 返回值
参数名 类型 说明
ret int 如果下载任务添加成功返回0,失败返回-1

6.4 删除接口

int DeleteFile(TCFSAppCertification ac, TCFSUserCertification uc, const char* needDeletePath)

  • 功能说明:将文件从迅雷链文件系统的目录树删除
  • 参数
参数名 类型 说明
ac TCFSAppCertification* 用于传入开发者的appid以及key_md5信息
uc TCFSUserCertification* 用于传入文件拥有者钱包地址以及签名信息,其中sign=UserSign(keyjson, passwd, addr+appid+timestamp)
needDeletePath const char* 指需要删除的文件路径,支持目录,必须为带sign的newest的TCFS路径格式
  • 返回值
参数名 类型 说明
ret int 如果删除成功返回0,失败返回-1

6.5 拷贝接口

int CopyFile(TCFSAppCertification ac, TCFSUserCertification uc, const char tcfsPath, const char destPath)

  • 功能说明:将文件从迅雷链文件系统tcfsPath拷贝到destPath
  • 参数
参数名 类型 说明
ac TCFSAppCertification* 用于开发者的appid以及key_md5信息
uc TCFSUserCertification* 用于传入文件拥有者钱包地址以及签名信息,其中sign=UserSign(keyjson, passwd, addr+appid+timestamp)
tcfsPath const char* 指需要拷贝的TCFS文件路径,支持目录,必须为带sign的newest/hash的TCFS路径格式
dstPath const char* 指目的TCFS目录,不带sign的newest格式
  • 返回值
参数名 类型 说明
ret int 如果拷贝成功返回0,失败返回-1

6.6 目录浏览接口

int Dir(TCFSAppCertification ac, TCFSUserCertification uc, const char tcfsPath, int start, int length, char node, int lengthNode)

  • 功能说明:浏览迅雷链文件系统目录结构
  • 参数
参数名 类型 说明
ac TCFSAppCertification* 用于开发者的appid以及key_md5信息
uc TCFSUserCertification* 用于传入文件拥有者钱包地址以及签名信息,其中sign=UserSign(keyjson, passwd, addr+appid+timestamp)
tcfsPath const char* 指目的TCFS目录,不带sign的newest/hash格式
start int 需要返回的起始的节点
length int 需要返回的节点个数
node char* 用以返回查询目录的节点信息,以json格式返回,举例: [{ "ctime": 1532422063, "hash":"25e6b30bc8d43a79cab45f69eeb54211c3c8dcf1", "name": "b", "size": 4096, "type": "dir" }, { "ctime":1532422068, "hash": "f457eb4e1d8a6dd52bceed4084e9082d900dc7e6", "name": "abc.txt", "size":4920904, "type": "file" }]
lengthNode int node数据的长度,需要尽可能传长字串,不够长度是字符串将会被截断
  • 返回值
参数名 类型 说明
ret int 如果成功返回0,失败返回-1

6.7 任务状态查询接口

int GetTaskStatus(TCFSAppCertification ac, TCFSUserCertification uc, const char taskID, char status, int length)

  • 功能说明:查询任务状态
  • 参数
参数名 类型 说明
ac TCFSAppCertification* 用于开发者的appid以及key_md5信息
uc TCFSUserCertification* 用于传入文件拥有者钱包地址以及签名信息,其中sign=UserSign(keyjson, passwd, addr+appid+timestamp)
taskID const char* 要查询的任务taskID
status char* 用以返回查询目录的节点信息,以json格式返回,举例:{"type":"GET_DENTRY","status":"PROCESSING","speed":614428,"progress":1,"file_count":2,"file_suc":0,"file_size":0,"start_time":1533289698,"dst_paths":["abc.txt.bak/libv4/abc.txt","abc.txt.bak/libv4/tcfs.go"]}
length int node数据的长度,需要尽可能传长字串,不够长度是字符串将会被截断
  • 返回值
参数名 类型 说明
ret int 如果成功返回0,失败返回-1

6.8 用户签名接口

int UserSign(const char keyjson, const char pwd, const chardata, char sign, int sign_length)

  • 功能说明:将data数据进行签名
  • 参数
参数名 类型 说明
keyjson const char* 用户的私钥文件串
pwd const char* 用户私钥文件对应的密码
data const char* 需要进行签名的数据
sign char* 用于返回得到的签名数据数组
sign_length int sign数组的长度
  • 返回值
参数名 类型 说明
ret int 如果成功返回0,失败返回-1

6.8.1 签名举例说明

const keyJson = `{
  "address":"7eff122b94897ea5b0e2a9abf47b86337fafebdc",
  "id":"f86a62b4-0621-4616-99af-c4b7f38fcc48","version":3,
  "crypto":{
    "cipher":"aes-128-ctr","ciphertext":"19de8a919e2f4cbdde2b7352ebd0be8ead2c87db35fc8e4c9acaf74aaaa57dad",
    "cipherparams":{"iv":"ba2bd370d6c9d5845e92fbc6f951c792"},
    "kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"c7cc2380a96adc9eb31d20bd8d8a7827199e8b16889582c0b9089da6a9f58e84"},
    "mac":"ff2c0caf051ca15d8c43b6f321ec10bd99bd654ddcf12dd1a28f730cc3c13730"
  }
}`
pwd := "1234"

appid := "de61d625adef267d69d63ca711939d685ffc8007"
address := "0x7eff122b94897ea5b0e2a9abf47b86337fafebdc"
ts := 1529216849
nonce := "abcdefgh"
filehash := ""
sign_str := appid + address + fmt.Sprintf("%d", ts)  + nonce + filehash
sign, err := UserSign (keyJson, pwd, sign_str)

其中:
sign_str= de61d625adef267d69d63ca711939d685ffc80070x7eff122b94897ea5b0e2a9abf47b86337fafebdc1529216849abcdefgh
sign= a54a4c369f608d3966dc531324795073585e288fd908e47c017302e514f8790a7bd41a2cb020230f14a48fb4d9d6f88eb33019b3b1f6ef097c486938324f593601

6.8.2 keyjson的生成示例

以下是使用链克口袋生成keyjson的步骤:

  1. 新建账户 avatar 点击右上角 新建账户,在新建页面输入 密码。

  2. 导出keystore文件 avatar 导出备份,就可以获取keystore文件, keystore文件内容即是keyjson。