【学习专栏】如何在以太坊上编写自己的CryptoKitties风格游戏
CryptoKitties在展示区块链不仅可以用于简单的金融交易方面做得很好。
我希望将来我们会开始看到区块链在此类游戏中的更多创新用途,因此我想快速浏览一下 CryptoKitties 背后的代码,以展示它是如何在表面下实现的。
本文是为开发人员编写的,虽然它不是对 Solidity 的绝对初学者介绍,但我尝试包含指向文档的链接,以使所有级别的开发人员都可以访问它。
让我们开始……
加密猫源代码
几乎所有 CryptoKitties 代码都是开源的,因此了解其工作原理的最佳方法是通读源代码。
总共大约 2,000 行,所以在本文中,只介绍最重要的部分。
高级概述
如果你不熟悉 CryptoKitties 是什么,它基本上是一个购买、销售和繁殖数字猫的游戏。每只猫都有基因定义的独特外观,当 2 只猫一起繁殖时,它们的基因以独特的方式结合产生后代,然后您可以繁殖或出售后代。
CryptoKitties 的代码被拆分为多个较小的合约 ,以便将相关代码捆绑在一起,而不需要一个包含所有内容的巨型文件。
主 kitty 合约的分包继承如下所示:
合约KittyAccessControl
合约KittyBase是 KittyAccessControl
合约KittyOwnership是 KittyBase,ERC721
合约KittyBreeding是 KittyOwnership
合约KittyAuction是 KittyBreeding
合约KittyMinting是 KittyAuction
合约KittyCore是 KittyMinting
KittyCore应用程序最终指向的合约地址也是如此,它继承了之前合约的所有数据和方法。
让我们一一浏览这些合同。
1. KittyAccessControl: 谁控制合同?
该合约只能由特定角色执行操作的各种地址和约束来管理。即首席执行官、首席财务官和首席运营官。
这份合约是用来管理合约的,与游戏机制完全无关。它基本上具有“CEO”、“COO”和“CFO”的“setter”方法,它们是对合约的特定功能具有特殊所有权和控制权的以太坊地址。
KittyAccessControl 定义了一些函数修饰符,例如onlyCEO(它限制一个函数,以便只有 CEO 可以执行它),并添加方法来执行诸如暂停/取消暂停合约或提取资金之类的操作:
该pause()功能可能已添加,以便开发人员可以使用更新的版本对其进行更新,以防出现任何不可预见的错误……这实际上可以让开发人员完全冻结合约,使合约无人能转让、出售或繁殖他们的小猫!有趣的是,大多数人认为 DApp 完全去中心化只是因为它位于以太坊上。并不是。
继续…
2. KittyBase:能说清楚到底什么是小猫吗?
这是我们定义整个核心功能中最基本的共享代码的地方。这包括我们的主要数据存储、常量和数据类型,以及管理这些项目的内部函数。
KittyBase定义了很多应用的核心数据。首先,它将 Kitty 定义为struct:
struct Kitty {
uint256 基因;
uint64 出生时间;
uint64 冷却结束块;
uint32 matronId;
uint32 父亲身份;
uint32 siringWithId;
uint16 冷却指数;
uint16代;
}
所以一只小猫实际上只是一堆无符号整数......大概是这样。
分解每个部分:
genes— 一个 256 位整数,代表猫的遗传密码,决定猫长什么样的核心数据
birthTime— 猫出生时区块的时间戳
cooldownEndBlock— 这只猫可以再次进行繁殖的最小时间戳
matronId sireId——分别是猫的妈妈和爸爸的ID
siringWithId- 如果猫当前怀孕,则设置为父亲的 ID,否则设置为零
cooldownIndex- 这只猫的当前冷却时间(猫在繁殖后必须等待多长时间才能再次繁殖)
generation——这只猫的“世代号”。合约铸造的第一批猫有第 0 代;新猫的世代是它们父母世代中较大的一代,加1。
请注意,在 CryptoKitties 中,猫是无性的,任何 2 只猫都可以繁殖——因此猫没有性别。
然后KittyBaseKitty合约继续声明这些结构的数组:
这个数组保存了所有存在的 Kitties 的数据,所以它有点像一个 Master Kitty DB。每当创建一只新猫时,它就会被添加到这个数组中,它在数组中的索引成为猫的 ID,就像这里的Genesis的 ID 为“1”:
数组索引是“1”!
该合约还包含从猫的 ID 到其所有者地址的映射,以跟踪小猫的所有者:
映射(uint256 = 地址)公共kittyIndexToOwner;
还定义了一些其他映射,但为了使本文保持合理的长度,我不会详细介绍每个细节。
每当一只小猫从一个人转移到另一个人时,这个kittyIndexToOwner映射就会更新以反映新主人:
转移所有权会将 Kitty 的 ID 的 `kittyIndexToOwner` 设置为接收者的 `_to` 地址。
现在让我们看看创建新的小猫时会发生什么:
所以这个函数传递了父母的ID 、猫咪的代号、 256位的遗传密码和主人的地址。然后它创建小猫,将其推送到主Kitty阵列,然后调用_transfer()以将其分配给它的新所有者。
真的超酷的有没有——所以现在我们可以看到 CryptoKitties 如何将小猫定义为一种数据类型,它如何将所有小猫存储在区块链上,以及它如何跟踪谁拥有哪些小猫。
3. KittyOwnership:Kitties 作为代币
这部分内容提供了遵循 ERC721 规范草案的代币交易所需的基本方法。
CryptoKitties 符合ERC721 代币规范,这是一种不可替代的代币类型,非常适合跟踪数字收藏品的所有权,例如数字扑克牌或 MMORPG 中的稀有物品。
关于可替代性的注意事项:以太是可替代的,因为任何 5 ETH 都与任何其他 5 ETH 一样好。但是对于像 CryptoKitties 这样的不可替代代币,并非每只猫都是平等的,因此它们不能相互互换。
从它的合约定义可以看出,KittyOwnership 继承自 ERC721 合约:
合约 KittyOwnership 是 KittyBase,ERC721 {
并且所有 ERC721 代币都遵循相同的标准,因此KittyOwnership合约填写了以下功能的实现:
由于这些方法是公开的,这为用户与 CryptoKitties 代币进行交互提供了一种标准方式,就像他们与任何其他 ERC721 代币进行交互一样。您可以直接通过与以太坊区块链上的 CryptoKitties 合约进行交互来将您的代币转移给其他人,而无需通过他们的 Web 界面,因此从这个意义上说,您真正拥有您的小猫。(除非 CEO 暂停合同)。
4. KittyBreeding:猫开始混血
该文件包含将猫一起繁殖所需的方法,包括跟踪父亲的报价,并依赖于外部基因组合合同。
“外部基因组合合约”(geneScience)存储在单独的合约中,不是开源的。
KittyBreeding合约包含一个让 CEO 设置此外部合约地址的方法:
他们这样做是为了增加游戏难度——如果你能读懂一只小猫的 DNA 是如何确定的,就更容易知道要繁殖哪些猫才能得到一只“花哨的猫”。
这个外部geneScience合约稍后在giveBirth()函数中使用(我们稍后会看到)来确定新猫的 DNA。
现在让我们看看当两只猫一起繁殖时会发生什么:
所以这个函数获取母亲和父亲kitties的 ID,在主数组中查找它们,并将siringWithId母亲的 ID 设置为父亲的 ID。(当siringWithId非零时,表示母亲怀孕)。
它还让triggerCooldown对父母双方都执行,这使得他们在一定时间内无法再次繁殖。
接下来,我们有一个giveBirth()创建新猫的公共函数:
对代码的内嵌注释是不言自明的。基本上,代码首先执行一些检查以查看母亲是否准备好分娩。然后它使用 确定孩子的基因geneScience.mixGenes(),将新小猫的所有权分配给母亲的主人,然后调用_createKitty()我们在KittyBase中查看的函数。
请注意,该geneScience.mixGenes()函数是一个黑匣子,因为该合约是闭源的。所以我们实际上并不知道孩子的基因是如何决定的,但我们知道这是母亲基因、父亲基因和母亲基因的某种功能cooldownEndBlock。
5. KittyAuctions:猫的买卖和“配种”
在这里,我们有拍卖或竞标猫或“种公”父亲服务的方法。实际的拍卖功能在两个同级合同中处理(一个用于销售,一个用于分配),而拍卖创建和竞标主要通过核心合同的这一方面进行调解。
根据开发人员的说法,他们将此拍卖功能拆分为“兄弟”合约,因为“它们的逻辑有些复杂,并且总是存在细微错误的风险。通过将它们保留在自己的合同中,我们可以在不破坏跟踪小猫所有权的主合同的情况下对其进行升级。”
所以这个KittyAuctions合约包含了函数setSaleAuctionAddress()和setSiringAuctionAddress(),这些函数setGeneScienceAddress()只能由 CEO 调用,并设置了处理这些函数的外部合约的地址。
注意: “Siring”是指给你的猫“配种繁育”——把它拍卖,另一个用户可以用以太币支付给你,让你的猫和他们的猫一起繁殖。LOL。
这意味着即使 CryptoKitties 合约本身是不可变的,CEO 也可以灵活地更改这些拍卖合约的地址,这将改变拍卖规则。同样,这不一定是坏事,因为有时开发人员需要修复错误,但需要注意一些事情。
6. KittyMinting:Gen0 猫工厂
最后一个方面包含我们用于创建新的 gen0 猫的功能。我们最多可以制作 5000 只可以赠送的“促销”猫(当社区是新社区时尤其重要),而所有其他猫只能通过算法确定的起始价格创建并立即进行拍卖。无论它们是如何创建的,都有 50k gen0 猫的硬性限制。在那之后,一切都取决于社区来繁殖、繁殖、繁殖!
合约能够创建的促销猫和 gen0 猫的数量在这里是硬编码的:
uint256 公共常量 PROMO_CREATION_LIMIT = 5000;
uint256 公共常数 GEN0_CREATION_LIMIT = 45000;
下面是“COO”可以创建促销小猫和 gen0 小猫的代码:
因此createPromoKitty(),看起来首席运营官可以用他想要的任何基因创造一只新的小猫,并将它发送给他想要的任何人(最多 5000 只小猫)。我猜他们会将此用于早期的 beta 测试人员、朋友和家人,以免费赠送小猫进行促销等。
但这也意味着您的猫可能并不像您想象的那么独特,因为他可能会打印 5000 个相同的副本!
因为createGen0Auction(),首席运营官还提供了新小猫的遗传密码。但它并没有将其分配给特定人的地址,而是创建了一个拍卖,用户将竞标以太币购买这只小猫。
7. KittyCore:主合同
这是主要的 CryptoKitties 合约,它是在以太坊区块链上编译和运行的。这份合同将一切联系在一起。
由于继承结构,它继承了我们之前看到的所有合约,并添加了更多的 final 方法,例如使用它的 ID 获取所有 Kitty 数据的函数:
这个方法是公开的,它将从区块链返回特定小猫的所有数据。我想这是他们的网络服务器查询的内容,用于在网站上显示猫。
等等……我没有看到任何图像数据。是什么决定了小猫的长相?
正如我们从上面的代码中看到的那样,“小猫”基本上可以归结为一个 256 位的无符号整数,代表它的遗传密码。
Solidity 合约代码中没有任何内容可以存储猫的图像或其描述,或者确定 256 位整数的实际含义。该遗传密码的解释发生在 CryptoKitty 的网络服务器上。
因此,虽然这是一个非常聪明的区块链游戏演示,但它实际上并不是 100% 基于区块链的。如果将来他们的网站下线,除非有人备份了所有图像,否则您将只拥有一个毫无意义的 256 位整数。
在合约代码中,我确实找到了一个名为 的合约ERC721Metadata,但它永远不会被用于任何事情。所以我的猜测是他们最初计划将所有内容存储在区块链中,但后来决定反对它(在以太坊中存储大量数据成本太高?)因此他们最终需要将其存储在他们的网络服务器上。
综上所述
好的……总而言之,目前我们搞明白了:
小猫如何表示为数据
现有的所有小猫如何存储在一个智能合约中,以及它如何跟踪谁拥有什么
gen0 小猫是如何产生的
小猫如何繁殖形成新的小猫
这只是一个顶级概述。开始构建您自己的游戏吧,毫无疑问这是一个愉快的过程。
- 免责声明
- 世链财经作为开放的信息发布平台,所有资讯仅代表作者个人观点,与世链财经无关。如文章、图片、音频或视频出现侵权、违规及其他不当言论,请提供相关材料,发送到:2785592653@qq.com。
- 风险提示:本站所提供的资讯不代表任何投资暗示。投资有风险,入市须谨慎。
- 世链粉丝群:提供最新热点新闻,空投糖果、红包等福利,微信:juu3644。