牌类游戏可信存证链系统
2020-01-17苑陈娟孙国梓李华康王纪涛
苑陈娟,孙国梓,李华康,王纪涛
南京邮电大学计算机学院,南京210023
牌类游戏因其量级轻、配置友好、游戏内容丰富同时又具有一定的可挖掘性而在游戏市场中占据一席之地[1].然而,用户之间的信任问题一直得不到妥善解决,外挂等作弊手段层出不穷.
目前,游戏平台防止玩家篡改花色的方法是基于中心化节点的,即通过租赁第3 方网络服务器来备份存储玩家的数据,从而保证游戏的公平性,但该方法主要存在着以下几个问题:
1)数据在传输过程中遭到破坏的风险较大,容易出现瑕疵、断点、不完整等问题,且需要多方人员共同处理数据,以致增加了数据中转的次数,加大了数据被篡改的风险.
2)这种方法对第3 方网络服务器的依赖较大,一旦服务器遭受恶意入侵或者无法运转,则连同其所控制的若干服务器上的电子数据都将面临完整性、隐私性和可修复性等巨大安全隐患.
3)这种中心化的方法无法保证第3 方网络服务器是完全安全又绝对公平的,用户往往会对第3 方网络服务器的诚实程度产生质疑,担心自己所上传的数据泄露或者遭到恶意破坏,不利于系统与用户建立长期的信任关系,且可能导致用户与平台之间的信任危机,增加了双方建立可靠的信任机制所需要的时间.
4)这种方法需要租赁第3 方网络服务器,成本较高,经济负担较重.
区块链运用了分布式存储、共识机制、P2P 网络、加密算法等技术,与传统数据库将读写数据库权限完全交付给某公司或管理员的中心化方式不同,它以去中心化和去信任的方式允许所有节点享有同等的读写操作权利以保证区块链网络中所有数据的一致性和可靠性,使得参与者在无需任何外部强制约束的情况下即可自行形成相互牵制的可信环境.这种可信的环境建立在互不信任的基础之上,解决了信用与治安问题.
智能合约[2]是Nick Szabo 在90年代提出的概念,由主流的区块链系统Ethereum 率先进行开发.这种合约是图灵完备的编程语言,通过建立抽象的基础层能使任何人都能创建合约并实现去中心化应用的目的.它是一种可以部署在区块链上的交易协议,其触发条件、规则和事件信息可以预先设置.一旦部署在区块链中就会自动执行并根据触发条件提供相应的反馈信息,具有实时更新、准确执行、低人为干预和低运营成本的特点.从本质上来说,智能合约是传统合约的数字化版本,以计算机程序的方式运行在区块链系统上.当系统的状态满足源码中预先设定的条件时,自动触发预设的行为.智能合约一旦参与,达成协议写入区块链后就不可更改,这一点可以让用户对智能合约产生信任.
区块链系统具有公开透明、无法篡改、便于追溯的特点,规避了数据被篡改的风险,而可编程易操作的智能合约能使用户更方便直接地查看并验证电子数据.因此,本文在区块链基础之上提出了一种牌类游戏可信存证链系统,妥善解决了用户之间的信任问题.
传统的存证模式存在电子化程度较低、数据易丢失易篡改、法律服务过程低效的问题,而区块链特有的确保数据真实、不可篡改等特点就能有效解决上述问题.文献[3]用一个存证链框架来管理收集到的车辆数据,将车辆公钥管理整合到存证链中为会员们提供隐私保护,并设计分类帐存储车辆数据.该框架实现了无信任、可追踪和隐私感知事故后分析的目的,并将存储和处理开销降到最低.文献[4]提出了以区块链替代第3 方服务器,在固定地理区域内实现动态导航的同时确保用户匿名,只允许法律授权机构对分类帐进行取证分析,因此该方法能够保护用户的隐私.文献[5]将区块链与取证中的监管链相结合,保证了所收集证据的可审计完整性和所有者的可追溯性.文献[1]中将数据存证相关技术与区块链技术相结合,为用户提供更高效的数据存证服务.文献[2]提出一个基于智能合约的以太坊可信存证框架,与区块链存证相比,其数据管理功能更多样,区块存储成本更低,存证效率更高.
目前,将区块链存证应用在牌类游戏的可信存证方面的文献尚未查到.市场上仍然使用第3 方服务器备份玩家数据,这种中心化的模式具有极大的安全隐患,因此本文提出了一种牌类游戏可信存证链系统.采用区块链存证技术来保存牌类游戏中每个玩家在整个游戏流程中的牌面信息,这样牌面信息一旦上链就不可篡改.如果在游戏过程中有玩家换牌的事件发生,那么存证链上的玩家初始牌面信息将不同于游戏结束后玩家的出牌信息,此时系统就能及时发现玩家的作弊行为,大大提高了牌类游戏的可信任性.
1 基本原理
1.1 系统整体运行流程
牌类游戏可信链系统的详细流程图如图1所示.
图1 系统详细流程图Figure 1 System detailed flow chart
本系统首先通过API 接收玩家初始抽到的牌面信息即发牌信息,根据一定的随机算法选定一套数据库里的编码对牌类信息进行数据压缩;接着通过智能合约将数据上传并锚定至区块链侧链;然后从侧链上将可信数据拉取下来并用HuffMHT 算法对牌面信息进行处理压缩后生成摘要,再通过智能合约将其锚定在区块链主链上形成最终存证,同时智能合约也会反馈对局作弊情况至本地.另外,当游戏系统、玩家或是第3 方仲裁机构需要查询过往对局信息时,也只要提供牌局ID 与玩家ID 即可获取过往对局最终信息,或进一步从侧链上获取具体的牌局对战信息,以判定作弊情况.
1.2 系统整体框架
本框架设计将整个系统划分成3 层,从上至下依次是逻辑实现层、智能合约层、区块链层,如图2所示.
1.2.1 逻辑实现层
逻辑实现层是系统核心功能的实现层.首先,系统通过API 接入玩家初始抽到的牌面信息对牌面数据进行编码、压缩、编码排序、数据加密等一系列数据预处理;其次,当一局游戏结束以及当平台或用户对游戏对局存在异议时,需要证明对局数据信息是否可信,本系统将会收集平台或用户的异议信息,自动从区块链上取证验证信息比对Hash.
1.2.2 智能合约层
在智能合约层里有部署在以太坊平台的智能合约.智能合约层作为逻辑实现层和区块链层之间的桥梁,将逻辑实现层的处理数据,如牌局的ID、游戏平台发牌过程中的编码信息等锚定到区块链上,或从区块链上获取数据至逻辑实现层;同时智能合约也实现了一部分的逻辑函数,如CmprStr,这样可以方便地实现系统功能并统一系统输出API.
图2 系统架构图Figure 2 System architecture diagram
1.2.3 区块链层
区块链层作为系统去中心化的数据库,存储逻辑实现层产生的数据信息.其中,网络层承担验证交易信息、产生新区块、维护区块链网络稳定运行的工作;数据层保存着整个系统所有上传的关键信息.
2 系统实现方法
2.1 玩家信息接入
将游戏开始时各位玩家及其抽取牌的信息通过API 接入本插件.考虑到牌的花色信息需要在客户端以及后端系统之间进行传输,故借助Socket[6-7]实现两者之间数据的传输与控制.目前,可以使用的Socket 有两种方式:流式和数据报式.其中,前者基于TCP 传输,后者基于UDP 传输.经比较发现:流式Socket 能按序提供稳定的双向数据流通信服务,适合本系统需要传输牌面信息和网络之间数据的传输情况,故选择基于TCP 的Socket 来实现通信.
基于TCP 的Socket 通信主要分为下述4 个基本步骤:
步骤1在服务器端定义ServerSocket 对象实例,监听来自客户端的连接请求;
步骤2在客户端定义Socket 对象实例,向指定的服务器发起连接请求;
步骤3按照一定协议对Socket 进行读/写操作,完成数据的计算和交互;
步骤4关闭输入流、输出流、双方的Socket.
本文为每局游戏单独启动一个线程进行通信,所传输的数据有用户信息和牌类花色信息.
2.2 数据预处理
牌面信息数据量较大,为了减少系统处理时间和存储空间,需要对数据进行压缩.这里运用了Huffman 编码[8]和Merkle-tree[9]相结合的编码方法对HuffMHT 编码进行移位压缩,最终达到数据压缩的目的.本文将此方法称为Huffman Merkle Hash tree,简称HuffMHT.
2.2.1 HuffMHT 编码
HuffMHT 以牌面信息(牌的花色数字)的哈希值构建一个不平衡的哈希树.一个样例HuffMHT 如图3所示.
图3 HuffMHTFigure 3 HuffMHT
下面概述构建HuffMHT 的算法步骤.
步骤1本文将每张牌的花色数字转换成对应的哈希值并存放在一个数组中,这个数组就是哈希序列.
步骤2将哈希值序列以字典顺序进行排序.
步骤3选取排序后哈希序列中最末的两个哈希值作为孩子节点,将这两个节点的值进行双哈希运算Hash(左孩子哈希值,右孩子哈希值),从而生成了一个父节点.此时,在哈希序列中去掉刚刚相互组合的两个孩子节点,加入生成的父节点的值.
步骤4重复步骤2 和3,当哈希序列中的元素为0 时,HuffMHT构建完成.
2.2.2 移位压缩
2.2.1 节采用HuffMHT 编码方式将字符转变为编码,若用char 数组存储编码,则size并没有减少,因此本文考虑用移位压缩.编码完成后,码的形式是0 和1 组成的二进制编码串,因此按位存储更节省空间.由Huffman 编码性质可知:编码长的出现频率低,编码短的出现频率高.假设平均编码长度为5 位,则32 位4 个字节可以存储6.4 个字符,而char 只能存储4 个字符,显然数据得到了压缩.整个压缩执行过程图4所示.
2.2.3 编码排序
接入的游戏牌面信息(牌的花色数字)都是乱序状态,可见其对应的压缩编码串也是一个乱序的状态,于是本文按照牌面花色数字的大小规则将该编码串排序,以便后续的作弊判定.排序流程如图5所示:
图4 移位压缩Figure 4 Shift compression
图5 排序图示Figure 5 Sorting icon
对于图5中有着4 个键值对的映射,以花色数字作为键,以花色数字对应的压缩编码作为值,将花色数字由大到小排序后输出其对应的压缩编码值,这样就完成了压缩编码的排序.
2.3 数据加密
因为SHA1 算法的安全性较高,且加密运行时间较少[10],所以本文选择SHA1 算法进行加密.
2.4 数据上链
2.4.1 以太坊环境的搭建
以太坊环境的搭建步骤如下:
步骤1从官网上下载Windows 版本的Geth 安装包,完成安装后将软件目录添加到Windows 系统环境变量PATH 列表中.
步骤2右键点击任务栏上Windows 徽标,打开powershell,进入项目目录,如D:Ether,其命令为cd D:Ether
步骤3以开发人员模式新建Etherum 私有链,并开启rpc 模式,其命令为
geth-datadir data-dev-networkid 233-rpc
-datadir 参数为系统拟建立的私链数据目录,如data,此处路径表示为相对路径,其对应的绝对路径应为D:Gethdata.
-dev 参数为开启开发者模式.在开发者模式下,会自动生成一个创世区块,使用POA 共识网络并随之生成一个初始账户,其初始密码为空;在开发者模式下,一旦交易被提交至私链上时,初始账户便自动开始挖矿,将交易自动写入区块链.测试开发时使用开发者模式来模拟一条保持运行的成熟私链.
-networkid 参数表示选择的区块网络.若要搭建私链网络,则输入任意非一般常见网络ID 即可.
-rpc 参数为启用http 的rpc(远程过程调用)服务,系统采用了所有的默认参数.
-rpcaddr value HTTP-RPC 服务器监听地址(default: “localhost”)
-rpcport value HTTP-RPC 服务器监听端口(default: 8545)
-rpcapi value 指定需要调用的HTTP-RPC API 接口,默认只有eth,net,web3
步骤4保持步骤3 中powershell 运行,新建powershell,输入如下命令连接至运行的区块链节点:
geth attach ipc:\.pipegeth.ipc
其中attach 参数是通过rpc 或者ipc 与节点进行交互的.
步骤5新建测试用户
personal.newAccount(“test”)
这里新建了一个密码为test 的账户.
步骤6为了便于后续开发,将两个账户定义为变量m与n:
m=eth.accounts[1]
n=eth.accounts[0]
2.4.2 编写智能合约
将开始时的牌面Hash 和整局游戏结束时赢家的Hash 称为数据Hash,为了将这个数据Hash 值存入以太坊区块链,本文采用编写智能合约的方法将该值锚定在区块链上.
智能合约[11-13]最早是由Nick Szabo 于20世纪90年代提出的,但当时缺少可信的执行环境,因此并未应用于实际产业.Ethereum 作为主流的区块链系统,率先进行智能合约的开发.
智能合约本质上是传统合约的数字化版本,以计算机程序的方式运行于区块链系统.当系统的状态满足源码中预先设定的条件时,自动触发预设的行为.智能合约被写入Ethereum 区块链后便不可更改,这一点可以让用户对智能合约产生信任.
本文定义的智能合约包含4 个集合,分别为发牌集合cardsL、出牌集合cardsP、出牌结果集合resultL、发牌结果集合resultP,用以存储各个阶段的牌类信息.其中cardsL、cardsP 存放的是发牌、出牌阶段的详细牌类信息的编码,resultL、resultP 存放的是本系统对详细牌类信息处理后得到的HuffMHT 摘要的值.基于上述4 个变量,编写了上传数据模块函数、查询下载数据模块函数以及游戏对局结果查询函数.
智能合约简要算法流程图如图6与7 所示.
编写完智能合约后需要完成智能合约的部署,其大致步骤如下.
步骤1编译与调试
本文使用Remix 对智能合约进行编译与调试.首先选择与智能合约solidity 语言版本相符的编译器版本,如本系统的智能合约solidity 语言版本如下:
pragma solidity ^0.5.2;
意味着编译器需要采用兼容0.5.2 的编译器,如
version: 0.5.9+commit.e560f70d.Emscripten.clang
图6 对局信息编码交互流程图Figure 6 Flow chart for game information coding interaction
之后选择remix 自带的JavaScript VM 环境中进行调试.
步骤2获取智能合约的abi 与bytecode
编译与调试无误后,需要从remix 中获取智能合约的abi(应用程序二进制接口)与bytecode,当然也需要对这两个数据进行格式化处理.abi 需要用在线json 格式化工具去除空格,使其成为一行字符串;bytecode 中需要留下object 部分,并在其前加上“0x”十六进制标识符.
步骤3创建合约
进入已连接上节点的Geth 环境,将步骤2 中的abi 与bytecode 数据赋值给abi 与byte变量.
通过abi 变量在Geth 环境中重现智能合约,命令为
Contract =eth.contract(abi)
之后预估合约所需的gas,为部署智能合约预设的gas 上限需要大于预估值,其命令为
eth.estimateGas({data: byte})
命令行返回的结果即为智能合约部署所需要的gas,同时在部署之前需要解锁账户,以支付智能合约部署所需的gas,命令为
personal.unlockAccount(my)
此时需要输入m账户的密码test,注意此时输入没有回显.
之后部署智能合约,生成智能合约对象,并将其用变量fff 表示,命令为
fff=Contract.new({data:byte,gas:3000000,from:my})
图7 对局结果交互流程图Figure 7 Game result interaction flow chart
因为后面涉及到后端与区块链的交互,所以要保留智能合约对象的地址,其命令为
fff.address
步骤4Geth 中智能合约对象的方法调用
Solidity 的方法调用一般分为交易方法的调用与常量方法的调用.
常量方法的调用只需直接以类方法的格式调用.假设需要获取已上传至区块链的牌类信息,则调用getCardInfo.命令为
fff.getCardInfo(<参数>)
而交易方法的调用还需要额外进行sendTransaction 操作,即需要加入交易的发起者.假设需要调用uploadCardL方法,其命令为
demo.uploadCardL.sendTransaction(<参数>,<参数>, {from: my})
2.5 作弊判定
当平台或用户对游戏对局存在异议时,需要证明对局数据信息是否可信,本系统将收集平台或用户的异议信息,自动从区块链上验证信息的有效性.流程图如图8所示.
3 实 验
3.1 HuffMHT 编码测试与结果分析
本文提出了一种有效的编码实现方案HuffMHT,允许以一种最小化平均响应长度的方式分发包含牌面信息的叶节点HuffMHT,为状态检查中可以找到的所有类型的统计数据节省了较大的带宽[14-15].该编码方案能够保持良好的性能,比Huffman 树表现得更好.
当牌的数量不同时,比较HuffMHT 编码和Huffman 编码的编码耗时情况,如图9所示.
图8 数据仲裁流程图Figure 8 Data arbitration flow chart
从图9中可以看出,随着牌的数据规模的增大,HuffMHT 编码的性能越来越好.此外,HuffMHT 编码结合了加密算法,可防御Sybul 攻击,剥夺“睡眠”攻击等,与Huffman 编码相比安全性得到了大幅度的提高.从以上分析可以看出,HuffMHT 编码比Huffman 编码表现得更好.
图9 HuffMHT 编码速度Figure 9 HuffMHT encoding speed
3.2 编码压缩测试与结果分析
根据HuffMHT 编码原理可以知道,牌的花色数字采用的是定长编码(每种都是用一个字节表示),而HuffMHT 编码是紧致码[16].因此,牌的花色数字的编码串是具有压缩空间的,表1给出了压缩测试的结果.
表1 移位压缩测试结果Table 1 Shift compression test result
从测试结果来看,压缩后的文件小于源文件所占的空间,因此采取移位压缩的方法的确可以达到数据压缩的目的.从表1中可以看出:随着牌的数据量的上升,压缩率是不断下降的.这一点根据移位压缩的原理不难理解,一个字符占8 位,如果编码长度不超过8 位,就有压缩的空间;如果编码长度等于或超过8 位,移位压缩就不起作用了.本文只需要压缩54 张牌,显然移位压缩能够满足本系统的需求.
3.3 加密算法测试与结果分析
以一个108.0 字节的牌面花色数字信息为测试样本,测试1 000 次的平均值,3 种算法的运行时间见表2.
表2 3 种常见加密算法的运行时间Table 2 Time of three common encryption algorithms
由表2中信息可知:MD5[17]的加密运行时间最短,但比其他两种加密算法更容易碰撞,安全性较低;SHA256[18]的安全性最高,但其加密运行时间比MD5 和SHA1 大得多,因此SHA1 是这3 种加密算法中性能最好的一款加密算法,故本文采用了SHA1 算法生成Hash.
4 结 语
考虑到了区块链与游戏的结合点太少,本文改变应用场景,利用区块链去信任、去中心化的独特机制有效验证作弊行为.同时棋牌类小游戏数据并不复杂,运算时不会造成太大负担而产生拥堵现象.因此本文基于区块链的独特性质来设计防作弊系统,将牌类游戏中牌的花色作为电子数据存于区块链中,以保证数据的可验证性、不可篡改性和不可伪造性.花色等电子数据一旦存储在系统中,就可以供验证者调用并与待查证信息进行比对,以证明此待查证数据的真实性,防止玩家中途换牌等作弊行为.借助以太坊平台,通过API 接口接入游戏,从而防止用户更改花色、私自换牌等篡改、伪造游戏数据的作弊行为.