本文来自作者 崔广斌 在 GitChat 上分享 「玩区块链游戏谜恋猫 CryptoKitties, 学习区块链技术赚 ETH」

编辑 | Mc Jin

便于读者更清晰阅读本文,先列出本文的内容大纲:

1.以太坊开发技术基础

2. 谜恋猫系统结构

3. 谜恋猫游戏规则

4. 使用 web3js 读写区块链上的谜恋猫数据

5. 使用 api.cryptokitties.co 读取数据

6. 通过程序赚 ETH

7. 谜恋猫的一些统计数据

8. 玩谜恋猫的一些启发

9. 开发时遇到问题怎么办?

1. 以太坊开发技术基础

1.1 以太坊概述

以太坊是可编程的区块链,是业内公认的区块链 2.0 代表项目。可以将以太坊理解为一个操作系统,使用 Solidity 等语言编写智能合约发布应用到链上,使用 Go、Java、Python、JavaScript 等语言在链下调用链上的智能合约读写区块链数据,通过这种方式实现各种各样的区块链应用。

比特币的总上限是2100万,而以太坊的内置代币以太币(Ether)没有确切的总量上限。目前以太坊大概每15秒出一个新块,一个新块奖励矿工 3 ETH 。

以太坊的设计者认为随着时间流逝总会发生因为粗心和死亡等原因带来的币的遗失,假设币的遗失是每年货币供应量的一个固定比例,则最终总的流通中的货币供应量会稳定在一个等于年货币发行量除以遗失率的值上,使得供应量会趋于稳定。

比特币缺少图灵完备性,尽管比特币脚本语言可以支持多种计算,但是它不能支持所有的计算,如不支持 for 循环。以太坊是准图灵完备的,之所以增加“准”,是因为智能合约在以太坊区块链上执行时是受限的。

在以太坊区块链上执行交易(转账、调用智能合约)需要消耗 Gas ,一般来说操作步骤越复杂需要的 Gas 越多,而一个块有 Gas 上限(目前约为 800万)。向普通账户做1次转账操作目前消耗 2.1 万 Gas。

在块 Gas 上限为 800 万时,假设调用一个智能合约中某个函数时会向400个账户转账,因为会至少消耗 400 * 2.1 万 = 820 万 Gas,超出块的 Gas 上限 800 万,合约调用会失败。

关于以太坊更详细的介绍可以参考:以太坊白皮书和以太坊黄皮书。

1.2 Solidity

Solidity 是一种在语法上类似 JavaScript 的高级语言,编译 Solidity 代码可以生成以太坊虚拟机代码。

Solidity 是静态类型语言,支持继承、库和复杂的用户定义类型等特性。

使用 Solidity 可以很容易创建投票、众筹、封闭拍卖、多重签名钱包、谜恋猫游戏之类的智能合约。

由于以太坊区块链的限制,在链上无法读取链下数据,使用 Solidity 你也无法来调用传统的 API,例如你无法调用某天气网站提供的天气 API。

另外在以太坊区块链上,无法让程序在指定时间自动运行。

谜恋猫游戏为了真实性,在猫怀孕后不是立即生出小猫,而是需要在满足一定条件后由外部来触发生猫函数为猫提供接生服务,一些开发者根据游戏的这个特性还可以赚猫的接生费,后文会有详细说明。

etherscan.io 提供了验证程序源码的服务。原理是使用公开的代码及指定的编译器版本再编译一次程序。

然后和发布到区块链的以太坊的二进制代码做比对,如果一致说明公开的代码就是在区块链上运行的那份代码。

下图是一份通过验证的代码截图。

可以访问这里,进一步了解 Solidity。

1.3 ERC-20 和 ERC-721

ERC-20 和 ERC-721 都是以太坊 EIP(Ethereum Improvement Proposal,以太坊改进协议),更多 EIP 见这里。

ERC-20 定义了一份代币标准,可以理解为定义了一个接口类,在实现具体的 ERC-20 代币时,要给出各个接口的具体实现,如获取代币名称、代币符号、总供应量、小数位数、转账等。

使用 ERC-20,可以大幅度降低发币成本,发币方无需开发钱包和区块链浏览器,交易所也可以轻松支持新的代币充值提现等操作。

ERC-20 币是同质的,你的一个币和我的一个币是等价的。ERC-721 是非同质代币(Non-fungible Tokens),每个 ERC-721 有唯一的 ID,转账时,不再是转多少币,而是转某个tokenId,如 transferFrom:

谜恋猫实现了 ERC-721 规范,每个猫有一个唯一的 ID,玩家花 ETH 买猫时,智能合约会调用 transferFrom 修改猫的所有者。

1.4 搭建以太坊全节点

我使用了以太坊 Go 客户端搭建的全节点,参考文档见(https://github.com/ethereum/go-ethereum),几个注意事项如下:

  • 电脑配置不能太低。我刚开始使用的是阿里云1核 CPU、2500 MHz 的 ECS,发现怎么也同步不到最新块,升级到了4核后同步正常了;

  • 第一次同步时使用 - -fast 选项,可以更快地同步到最新块,目前(2018-04-02)使用 - -fast 选项同步到最新块后预计占用 60G 空间;

  • geth 运行时间长了可能会有问题,我使用守护进程启动 geth,每 4 个小时 kill 掉 geth,目前基本上能一直同步到最新块;

  • 硬盘空间要足够大,建议至少1T以上。我3个月前使用 - -fast 同步完成后才占 40 多 G 空间,之后正常模式同步后硬盘占用空间快速增长,运行3个月左右已经 500G 了。

为了更方便、更快速的调用相关 API,建议在本地服务器上搭建一个以太坊全节点,并保持同步到最新区块高度。

如果想通过程序买卖猫但又不想自己搭建全节点,可以使用 MetaMask 的节点,API 地址请访问(mainnet.infura.io/metamask),使用 MetaMask 的节点 API,监听事件可能会受到影响,一个方法是遍历某个区块的所有交易信息,然后选择自己关注的交易信息再做相关处理。

2. 谜恋猫系统结构

如果你还没有在 www.cryptokitties.co 买过猫,建议先买只猫后再阅读后续内容。一些入门攻略见(http://www.maomao123.co/faq),遇到问题可通过谜恋猫 QQ 群(728507998)咨询。

2.1 谜恋猫 DApp

谜恋猫是一个 DApp(Decentralized Application),部分程序部署在区块链上,部分程序部署在中心化的服务器上,总体架构如下图:

2.2 谜恋猫智能合约

谜恋猫在以太坊区块链上一共有4个智能合约:

  • CryptoKittiesCore :核心代码,已开源,2016行代码;

  • CryptoKittiesSalesAuction :猫拍卖机制,已开源,604行代码;

  • CryptoKittiesSiringAuction :配种拍卖机制,已开源,589行代码;

  • geneScience :基因工程,未开源。

以玩家挂单卖猫为例,说明相关步骤:

  1. 玩家在自己某只猫的页面点击出售按钮,设置出售价格,通过 MetaMask 钱包操作后等待(页面上猫的状态是非在售;MetaMask 交易状态是 pending 中);

  2. MetaMask 将交易广播出去(页面上猫的状态是非在售;MetaMask 交易状态是 pending中);

  3. 交易被矿工打包到区块中(页面上猫的状态是非在售;MetaMask 交易状态是 pending中);

  4. 谜恋猫的以太坊节点监听到卖猫事件,更新数据库中猫的信息、更新缓存数据、更新搜索索引数据;MetaMask 的以太坊节点更新交易状态(页面上猫的状态是在售;MetaMask 交易状态是已完成);

用户卖猫后,在页面上不是立即可以看到猫处于在售中,而是需要等待一会儿才能看到,整个过程是异步的。

这也为懂技术的玩家留下机会,可以在猫刚开卖还未在页面上显示出售中就能立即买下猫,详细方法见后文。

3. 谜恋猫游戏规则

3.1 以太坊钱包就是用户的 ID

一般涉及到用户数据的网站或 App,都会要用户注册帐号,哪怕是使用第三方授权。

而对于谜恋猫游戏,即使你之前从未访问过网站,只要有你的以太坊钱包地址,其他人就可以给你送猫。

安装 MetaMask 插件后第一次登陆网站,需要你按提示点击一个消息签名按钮,以便验证当前用户身份。

原理是椭圆曲线加密算法,相关函数为 web3.eth.sign(address, dataToSign)、ecRecover,具体用法可以搜索下。

3.2 买猫

在谜恋猫页面,点击顶部导航“猫市”,默认就是待收养的猫猫。点击“筛选猫咪”可以通过多种方式做筛选,找到自己的目标猫咪。初期玩建议按价格从低到高排序,选两三只便宜的猫咪。

搜索功能并不是直接从区块链读取数据的,而是通过同步区块链数据后在中心化服务器中建立的索引。

点击一只猫咪后,进入单个猫咪页面,再点击“立即购买”就可以买猫了。

在点击“立即购买”按钮时,会调用 web3js,触发弹出 MetaMask 插件窗口。MetaMask 插件中会显示 Amount(转账额度)、GasLimit(燃料上限)、GasPrice(燃料价格)等参数,部分数据做了隐藏,如购买猫调用的是 bid(uint256 _tokenId) 函数。

点击“submit”按钮后,MetaMask 会将交易数据提交到以太坊网络,等待矿工打包确认,当矿工将交易数据打包到某个区块中才算真正完成相关函数执行。

但成功打包到区块中不一定能成功买到猫,因为交易过程是异步的,在这个过程中也可能有其他人购买同一只猫,如果他人的交易比你的交易优先被矿工打包,你就买不到猫了。另外,卖家也可以取消卖猫。

在此简单说下以太坊的 Gas 机制,在以太坊中涉及到任何写数据的操作都有消耗 Gas,矿工打包一般优先打包 gasPrice 高的交易。

gas * gasPrice 表示在操作过程中消耗的以太币,剩余的以太币 (gasLimit - gas)* gasPrice 会返回给用户。

一般来做操作越复杂,消耗的 Gas 越多,占用的存储空间越大,消耗的 Gas 越多。

3.3 卖猫和出租种猫

你买卖达成后后,平台会收取交易的 3.75% 作为手续费。因以太坊区块链上的数据对所有可见,卖猫不支持暗拍(备注: ENS支持安排,但相对复杂,不合适面向普通用户)。

为了让买家以相对和合适的价格找到相对合适的卖家,卖猫时,可以设置起始价、结束价、价格变化时间段(出售期限),价格变化时间段结束后,还会处于出售状态,价格保持为结束价。

当前价格的计算方法:

/// @dev Computes the current price of an auction. Factored out    ///  from _currentPrice so we can run extensive unit tests.    ///  When testing, make this function public and turn on    ///  `Current price computation` test suite.    function _computeCurrentPrice(        uint256 _startingPrice,        uint256 _endingPrice,        uint256 _duration,        uint256 _secondsPassed )    internal    pure    returns (uint256)    {        // NOTE: We don't use SafeMath (or similar) in this function because        //  all of our public functions carefully cap the maximum values for        //  time (at 64-bits) and currency (at 128-bits). _duration is        //  also known to be non-zero (see the require() statement in        //  _addAuction())        if (_secondsPassed >= _duration) {            // We've reached the end of the dynamic pricing portion            // of the auction, just return the end price.            return _endingPrice;        } else {            // Starting price can be higher than ending price (and often is!), so            // this delta can be negative.            int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice);            // This multiplication can't overflow, _secondsPassed will easily fit within            // 64-bits, and totalPriceChange will easily fit within 128-bits, their product            // will always fit within 256-bits.            int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration);            // currentPriceChange can be negative, but if so, will have a magnitude            // less that _startingPrice. Thus, this result will always end up positive.            int256 currentPrice = int256(_startingPrice) + currentPriceChange;            return uint256(currentPrice);        }    }

3.4 出租种猫

出租种猫和卖猫类似,可以通过出租种猫赚钱,但所有权还是原主人的。相关合约见 CryptoKittiesSiringAuction 。

3.5 生猫

生猫规则如下:

  • 任意猫都可以充当爸爸或妈妈的角色;

  • 交配时不能乱伦;

  • 每生育一次,恢复时间变长,直到需要7天时间恢复;

  • 孕期 = 怀孕后妈妈的恢复时间,想尽快生出小猫的话,应该使用休息时间短的猫做妈妈;

  • 小猫代数 = max(爸爸的代数,妈妈的代数) + 1;

  • 小猫恢复时间 cooldown_index = min( 小猫代数 / 2 ,13);

  • 不同 cooldonw_index 对应的时间见下面内容。

生猫函数如下:

.....

扫码阅读全文

并与作者交流

近期热文

《区块链在哪些案例上发挥着重大作用》

《区块链落地中的九大问题与解法》

《比特币和区块链基础》

《穷人入门区块链指南》

从区块链游戏 CryptoKitties 中,学习区块链技相关推荐

  1. 如何看待区块链游戏,避免陷入区块链游戏骗局

    元宇宙概念在即将过去的2021年,被越来越多的人所认识到,在这一年元宇宙概念迎来了更多社会人士的关注,不管是什么行业都蹭上了元宇宙的"热度",覆盖了各行各业.那么到底什么才是元宇宙 ...

  2. java责任链设计模式_Java中的责任链设计模式

    java责任链设计模式 在本教程中,我们将学习如何在Java中实现责任链模式. 责任链设计模式涉及到拥有一系列负责处理请求的对象链. 当客户端发送请求时,第一个处理程序将尝试处理该请求. 如果可以处理 ...

  3. 【原型链】JS中的原型链到底是什么

    1.构造函数 JS中的构造函数和普通函数没有本质区别,要用调用方式的不同来区分. 在调用构造函数时要用new Func()的方法来调用,此时函数会默认返回this 为了与普通函数区分,构造函数的函数名 ...

  4. 从失败中学习区块链实验

    分散的自治组织是一个失败的早期区块链实验.但它能教会我们很多关于组织未来的东西. 过去的6个月里,比特币和Ethereum等加密货币从全球经济的零头转向主流银行会议的中心舞台.目前的热潮主要是对加密货 ...

  5. C# 坦克游戏大战中学习相关类(Bitmap)

    C# 坦克游戏大战,爆炸类Blast代码如下: using System; using System.Collections.Generic; using System.Linq; using Sys ...

  6. C# 坦克游戏大战中学习相关类(Rectangle)

    C# 坦克游戏大战,老王类Boss代码如下: using System; using System.Collections.Generic; using System.Linq; using Syst ...

  7. C# 坦克游戏大战中学习相关类(Closing与Closed区别)

     C# 坦克游戏大战,窗体Form中Closing代码如下: private void Form1_FormClosing(object sender, FormClosingEventArgs e) ...

  8. java 职责链模式_Java中的责任链模式

    java 职责链模式 当应有几个处理器来执行某项操作并为这些处理器定义特定顺序时,就需要采用责任链设计模式. 在运行时处理器顺序的可变性也很重要.模式的UML表示如下: 处理程序定义处理器对象的一般结 ...

  9. 没用户、没技术,炒了这么久的区块链游戏似乎找到了一条新思路

    区块链已经火爆了大半年,这种全新分布式技术似乎和各行各业都可以结合,而当其瞄准了离钱最近的游戏业,"区块链游戏"这一新鲜名词应运而生,游戏从业者想必或多或少有所耳闻,但一知半解的也 ...

最新文章

  1. TCMalloc:线程缓存的Malloc
  2. 2013-12-2 学习笔记
  3. JVM-09自动内存管理机制【内存分配和回收策略】
  4. Jaspersoft Studio简介
  5. resolve fire在SAP UI5中的使用场景
  6. javaPNS进阶-高级推送技巧
  7. 马斯克又要搞事情,不锈钢材质的Space X“星际飞船”正式亮相
  8. SQL – 2.SQLServer的管理 + 3.SQL基础1 + 4.SQL基础2
  9. 基于JAVA+SpringMVC+MYSQL的小说管理系统
  10. 6.Docker技术入门与实战 --- Docker数据管理
  11. Android远程过程通讯,Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析(3)...
  12. Cesium加载GeoJson数据
  13. 戴尔笔记本计算机图标,戴尔笔记本原装桌面图标不见了怎么处理
  14. 【CSS】calc 函数(动态计算长度值)
  15. 送女朋友实用的七夕礼物、送女朋友七夕礼物最有意义排行榜
  16. python字体有哪些种类_Python的数据类型(字符串类型),python
  17. 快速查找参考文献影响因子——ScholarScope
  18. 图床云存储项目课程随堂笔记
  19. linux使用sts4,视听说sts4-4
  20. 学习线程安全队列ConcurrentQueue

热门文章

  1. BUUCTF:[MRCTF2020]Hello_ misc
  2. 进程控制--->进程终止
  3. 终止进程执行----杀死进程
  4. 在极点五笔中使用命令直通车
  5. MIUI13和MIUI12的录音存储位置
  6. 智慧社区(GIS+大数据+政府主导型智慧社区-完美的系统迭代更新至2.4版本)
  7. 贪吃蛇自动寻路HTML,html贪吃蛇
  8. OD 实验(九) - 对一个程序的破解
  9. 正方形隐藏呈三角形html,border三角形
  10. C语言程序——类型强制转换