基于区块链的健康链系统设计与实现

2021-01-19 11:00雷志伟李加福张桂刚邢春晓
计算机与数字工程 2020年12期
关键词:线程进程比特

雷志伟 李加福 张桂刚 赵 旭 张 勇 邢春晓

(1.清华大学行业可信区块链应用技术联合研究中心 北京 100084)(2.中国科学院自动化研究所 北京 100190)(3.清华大学信息国家研究中心,计算机系,互联网产业研究院 北京 100084)

1 引言

在抗击新冠肺炎疫情初期,各地各部门企业纷纷贡献己力,自主开发疫情防控信息系统。一方面能加强政府部门的管理,另一方面简化现实中人力物力消耗[1]。在人员进出公共场所的跟踪管理方面,相应有应用于广西地区的“扫码抗疫情”、云南地区的“云南抗疫情”等。它们都是基于微信小程序开发,其功能和使用方式大抵相同,群众以个人身份注册,另一个则是公共场所的工作人员以公共场所的身份进入系统并生成二维码进行张贴,进出人员手动扫码实现数据上传,从而减免了手工登记流程。

区块链作为一个分布式数据库,记录着区块链从创世块到当前块的所有交易,具有去中心化、不可更改性、匿名性和可审计性这几个特点。鉴于微信小程序基于微信平台拥有庞大用户量,不需要下载安装反复登录与卸载,对用户而言,大大简化了使用程序。因此使用微信小程序展现基于区块链的进出登记系统是一个不错的选择。与别的出入登记系统不同,健康链系统将由公共场所工作人员对出入人员进行扫码,并保存当前测量的温度值,以加强疫情工作的防控。

2 系统分析

2.1 微信小程序分析

微信小程序本质上是一种由原生APP和HTML5混合开发的HyBird App技术方案。即是一种在原生App里内置浏览器,采用网页的形式来呈现功能的系统架构。它既解决了原生App下载安装和更新、应用商店发布审核周期长的问题,又解决了纯Web App安全性相对较低,数据容易泄露或者被劫持的问题。

微信小程序的系统架构如图1,它以微信APP作为宿主进程,通过云端下载动态的Web资源文件到本地并动态渲染Web界面。在纯Web App中,界面渲染跟JavaScript的脚本执行在一个单线程中,这就容易导致一些逻辑任务抢占渲染的资源。因此微信小程序采用双线程模型,打开一个微信小程序,相当于进程启动了两个线程。其中一个线程用来渲染View视图,另外一个App Service逻辑线程动态执行JavaScript脚本,用来处理逻辑、数据请求和接口调用。

图1 小程序架构

在微信APP和Web模块之间有一个JSBridge跨语言双向通讯机制,这个通信层协调Web模块的视图线程与逻辑线程的数据和事件交互,逻辑线程把数据变化通知到视图线程,触发视图页面更新,视图线程把触发的事件通知到逻辑线程进行业务处理。更为重要的是,它不但负责传递Web模块对系统权限的相关功能调用,还包括传递Web视图渲染和JavaScript脚本执行[2]。在安卓系统里,渲染和脚本引擎都是调用基于开源Webkit库优化和扩展的腾讯X5浏览器。在iOS系统里,苹果基于Web-Kit开发了WKWebView组件来渲染视图,并基于WebKit的C/C++实现和包装实现了JavaScriptCore脚本执行框架。

JS-SDK就是对JSBridge的一个包装,它是一整套网页开发工具包,开放了拍摄、录音、语音识别、二维码、地图、支付、分享、卡券等几十个API。

最后,App Service线程运行在沙箱环境中,从而方便管控与安全,比如避免JavaScript脚本随意地跳转网页或者改变界面上的内容[3]。

2.2 区块链平台分析

Bitcoin(比特币)作为区块链技术的起源,是目前发展最成熟的开源区块链平台之一,拥有大量的开发人员和活跃的开发社区。Ethereum(以太坊)核心是支持智能合约的EVM(以太坊虚拟机),提供了大量方便接口便于开发者进行深度应用开发。Hyperledger Fabric(超级账本)使用诸如单节点共识、分布式队列共识等共识方式,并支持智能合约和外部组件扩展。但Ethereum和Fabric部署困难相对困难。EOS区块链采用DPOS共识机制,生成区块速度快、延迟低,能支持数百万级别用户。但EOS作为新兴的区块链平台发展还不成熟,同时开发社区及开发人员相对较少,进行开发研究较为困难[4]。

比特币作为一种以交易为模型的数字货币系统,其交易的数据结构如图2。交易由交易输入和交易输出组成,交易输入和交易输出可以有多个,表示一次交易可以将先前多个账户中的比特币合并后转给另外多个,每个输入主要由上笔交易的哈希PrevTxHash、上笔交易的输出索引Index和输入脚本ScriptSig组成,其中ScriptSig是持有者对当前交易的签名。通过对某个交易的输入可构成多条以交易为结点的链表,并一直向前追溯至源头的Coinbase交易(即挖矿所得的比特币)。如果一笔交易的输出没有任何另一笔交易的输入与之对应,则说明该输出中的比特币未被花费[5]。

图2 比特币的交易数据结构

区块是区块链的一个数据单元,它由区块头和区块体组成。比特币的区块数据架构如图3,区块体包含所有的交易内容,区块头包含版本号、时间戳、随机值和难度值等基本信息,并包含上一个区块的哈希值和交易的默克尔树根哈希值。区块的哈希值通过对区块头进行两次SHA256哈希运算得到。通过指向上一个区块的哈希值所有的区块构成一个链条,同时,区块的哈希值和对区块内的所有交易计算得到的默克尔树根哈希值都可以保证数据的不可篡改和完整[6]。

图3 比特币的区块数据架构

2.3 Web服务器分析

Nginx是一个跨平台的Web服务器,相比Apache、Tomcat和Jetty,它具备高扩展、热部署、单机支持10万以上的并发连接、低内存消耗和高可靠的特性。

Nginx提供了异步的、非阻塞的Web服务,它的系统架构如图4,它主要由一个Master主进程、多个Worker工作进程、一个可选的Cachemanager缓存索引管理进程以及一个可选的Cacheloader缓存索引进程组成。

Master主进程用来启动和管理Worker工作进程,使用管道机制与工作进程通信,并且通过信号机制与外界通信来实现重启、退出、停止等系统服务。Worker进程是提供Web服务的主体,它收到Web请求通过代理转发给后端服务器,由后端服务器进行数据处理和页面组织后返回数据。其中FastCGI是一个可伸缩地、高速地在Nginx服务器和动态脚本语言间通信的应用层通信协议,PHP作为一种服务端、跨平台的HTML嵌入式的脚本语言,它的PHP-FPM模块实现了FastCGI协议并负责处理PHP动态请求,从而分担了Nginx前端的压力,使Nginx专注处理静态请求[7]。

Cachemanager进程和Cacheloader进程主要是将历史应答数据进行本地缓存,从而提高请求的响应效率,降低网络压力。Cacheloader进程在Nginx服务启动一段之后(默认是1min)由主进程生成,在缓存元数据重建完成后就自动退出。Cachemanager进程存在于主进程的整个生命期,负责管理缓存索引,支持工作进程对缓存数据的快速查询。

多个Worker进程之间是对等的,它们同等竞争来自客户端的请求,通过互斥锁机制保证最终由一个Worker进程进行处理,从而做到资源的负载均衡[8]。

3 系统设计

3.1 系统整体设计

系统架构如图5,系统将搭建SDK接口服务器作为微信程序和区块链的通讯中介。微信程序通过Https协议与SDK接口进行数据交互,SDK接口与区块链系统通过JSON-RPC协议进行数据交互。SDK接口程序由进出人员的个人数据接口、公共场所的数据接口和进出人员记录的数据接口等等组成。系统配备传统数据库存储数据以避免区块链数据查询效率低下问题。

由于区块链平台的共识机制,数据上链有时间延迟,接口程序通过将采用定时查询机制来得到数据上链等其他数据操作结果。SDK接口与区块链系统的数据流程如图6。

在增强数据的隐私和安全方面,Https协议在Http协议的基础上加了一层SSL/TLS加密层,SSL/TLS通过将对称密码、公钥密码、单向散列函数、消息认证码,伪随机数生成器和数字签名等技术相结合来实现安全通信。此外,SSL/TLS还可以通过切换密码套件来使用强度更高的密码算法[9]。

图6 SDK接口与区块链系统的数据流程

鉴于数据的隐私和安全需求,比特币系统将采用私有链的方式布置节点。

3.2 传统数据库设计

MySQL作为一个关系型数据库管理系统,其体积小、速度快、源码开放,且对PHP有很好的支持。因此数据库基于MySQL开发,主要包含三个表:个人信息表、公共场所表和进出记录表。

表1 个人信息表

表2 公共场所表

3.3 微信小程序设计

代码主要通过微信开发者工具开发,开发者可以完成API和页面的开发调试、代码查看和编辑、小程序预览和发布等等功能。微信小程序1个Page页面对应本系统1个模块,1个page页面主要由4个文件构成,js脚本文件即是页面逻辑,wxml是页面结构展示,wxss是纯前端的页面样式表,用于辅助wxml展示,json则是页面配置文件[10]。

表3 进出记录表

小程序在使用HTTPS发起网络请求时只可以跟指定的域名与进行网络通信,因此需要在微信公众平台账号里对应的项目设置里面设置一个通讯域名,并将域名完成备案。

3.4 区块链设计

比特币加入了OP_RETURN脚本命令,它后面可以紧跟一定容量的数据,专门用于存储和交易逻辑无关的数据。这个交易输出不会加入UTXO集合,从而避免了UTXO数据库的大小不断“膨胀”[11]。另外,由于比特币基于LibEvent开源库实现了一个JSON-RPC的远程调用Server端,系统主要增加两个自定义的RPC API接口。一个是创建包含OPReturn数据的交易,一个是查询交易的OPReturn数据。

4 系统实现

4.1 SDK接口

SDK接口主要是基于PHP语言通过libcurl扩展库实现了基于Http的JSON-RPC客户端[12]。其主要函数代码如下。

//初始化一个CURL会话

$curl=curl_init("{$this->proto}://{$this->host}:{$this->port}/{$this->url}"

$options=array(CURLOPT_HTTPAUTH =>CURLAUTH_BASIC,

CURLOPT_USERPWD=>$this->username.':'. $this->pwd,

CURLOPT_RETURNTRANSFER=>true,

CURLOPT_FOLLOWLOCATION=>true,

CURLOPT_MAXREDIRS=>10,

CURLOPT_HTTPHEADER=>array('Content-type:application/json'),

CURLOPT_POST=>true,

CURLOPT_POSTFIELDS=>$request);

//设置选项

curl_setopt_array($curl,$options);

//执行并获取结果

$this->raw_response=curl_exec($curl);

//释放连接

curl_close($curl);

4.2 微信小程序

系统主要包括首页还有其他模块。图7是个人注册页面,图8是公共场所扫码页面,图9是个人进出记录页面,图10是公共场所进出记录页面。

图7 个人注册页面

图8 公共场所扫码页面

图9 个人进出记录

图10 公共场所进出记录

4.3 区块链主要功能

添加OPReturn数据到交易的API函数主要包含创建交易、交易签名和发送交易三个过程,此处展示创建交易的部分代码。

static void createCustomTransaction(const CTxDestination&dest,const CAmount&amount,const std::string&customdata,CMutableTransaction&rawTx){

//创建输入

uint32_t nSeq=td::numeric_limits::max();

CTxIn in(outpoint,CScript(),nSeq);

rawTx.vin.push_back(in);

//创建OPReturn输出

std::vectordata;

for(size_t i=0;i

data.push_back(customdata[i]);

CTxOut out(0,CScript()<

rawTx.vout.push_back(out);

//创建一笔输出

CScript script PubKey=GetScriptForDestination(dest);

CAmount nAmount=amount-3000;//3000 fee is enough

CTxOut out1(nAmount,script PubKey);

rawTx.vout.push_back(out1);

Bitcoin-qt是一个基于Qt的GUI程序。Qt作为一个C++图形界面库,具备跨平台、易扩展、面向对象和开发文档丰富的特点[13]。图11是系统基于Windows平台的比特币版本,它基于Visual Studio上编译Bitcoin-qt,其过程包括安装Qt软件、安装vcpkg并调用相关命令下载软件库,安装Visual Studio Qt插件等其它设置[14]。

图11 基于Windows平台的比特币程序

系统对界面进行了功能扩展,能方便地查看交易的输入和输出内容。图12作为示例,其数据内容 为“南园食堂 雷志伟2020/05/12 14:54:54 36.4”,从而完成了对用户在某个地点进出的信息登记,并保存了温度值。另外,通过遍历区块的所有交易,可以得到所有人员的进出记录,从而达到数据的不可篡改和溯源。

图12 交易的OPReturn数据查看

4.4 区块链性能优化

通过更改相关参数和优化,交易性能在单节点的情况下能达到100个TPS以上。比如将生成块的时间由每10min改成10s,将调整难度时间由2周改成80s,将交易内存池扩大,并扩大交易最大容量大小等[15]。

在测试性能时,需要提前创建大量未花费的交易,并记录交易哈希值以备使用。创建交易的思路是将某个交易按固定数量生成多个输出,然后循环以上次的交易输出作为新的交易输入得到更多的交易。以1个CoinBase交易为例,其输入为50个比特币,将其按数量输出为80份。再对这80个交易输出进行操作,对每个输出作为新的交易输入又得到100个交易输出,以同样的步骤再次划分为100倍。最终得到800000个数量约为6000聪比特币的交易输出。以下为示例代码:

void createDivisionTransaction(const COutPoint& outpoint,const CAmount&amount,int nCount,CMutableTransaction&rawTx){

//创建多个交易输出

for(int i=0;i

CAmount nAmount=(amount-10000)*1.0f/nCount;

CTxOut out1(nAmount,scriptPubKey);

rawTx.vout.push_back(out1);

系统也对数据的存储优化进行了尝试。在比特币的文件存储系统中,blocks目录下blk开头的后缀为dat的文件表示当前的区块数据,rev开头的后缀为dat的文件是区块回滚数据。chainstate目录主要存储UTXO(Unspent Transaction Output)相关的数据,以Leveldb数据库存储,indexes目录存储的同样是基于Leveldb的交易索引数据。

当收到新的区块或者区块回滚时,系统代码以CChainState::ConnectTip和DisconnectTip为相应的入口。

数据分片在区块链的数据副本基础上进行,将相关数据分为100个区,具体分区根据交易在区块中的顺序而来,序号1、101、1001等序号除以100其模为1的交易组成第1个分区,依次类推。表4列出了第9个、19个...99个分区的数据。系统测试时将8,000,000个长度为100个字符的数据存储在区块链上,区块高度为21105,总区块大小为2825M,总的UTXO数据大小为588M,交易索引总大小为389M。A表示交易的顺序,B是每个分区下面的区块数据大小,D是分区后交易索引大小,F是分区后UTXO数据大小。C、E、G表示当前分区所占比例。

表4 数据分片存储表

由表可知,数据呈现正确态势,由于区块中交易个数不等,相对来说,交易序号越少,分区中的交易也相对集中,数据量也越大。

5 结语

通过本文基于区块链体系架构建立的健康链系统,有效地解决了现实生活中的人员进出登记流程的繁琐问题。但同时系统属于疫情防控和复工复产特殊形势下迅速推出的一项举措,由于时间紧迫,尚有很多问题和工作需要进行下一步的思考。在设计数据的加密模块方面、区块链的性能方面、通信模块的安全方面比如对SSL/TLS的FREAK攻击、SSL3.0的POODLE攻击和利用证书的时间差进行攻击等都需要考虑和防范。最后,底层区块链平台可以考虑基于以太坊来实现并可以开发智能合约来做到疫情报警。

猜你喜欢
线程进程比特
5G终端模拟系统随机接入过程的设计与实现
实时操作系统mbedOS 互斥量调度机制剖析
浅析体育赛事售票系统错票问题的对策研究
有效把握政治新形势 积极推动党建工作进程
债券市场对外开放的进程与展望
快速杀掉顽固进程
比特币还能投资吗
比特币分裂
比特币一年涨135%重回5530元
中外民主法制进程专题复习