区块链-NFT 的实现原理
作者:林冠宏 / 指尖下的幽灵。转载者,请: 务必标明出处。
GitHub : https://github.com/af913337456/
出版的书籍:
NFT (Non-Fungible Token),这2年又火了起来,早在18年已经火过一波。
本文只从写代码实现NFT的技术方案
层面去介绍 NFT,不从其金融意义、案例,等层面去谈,因为这类内容可以随便在浏览器搜索到,而我接下来要谈的内容,浅层搜索下,数量不多。
第一步: 制作id
制作id,这是把物质制作成 NFT 的第一步。物质有哪些?一段文字、一张图片,一件衣服等,夸张的说,现实世界的物质,无论是虚拟的(游戏装备)或实质物质,都可以被通证化。
如何操作?
通过第三方技术手段
获取物质的唯一标志性中间产物。
因此制作 NFT 第一步,广义于下面等式:
- id = F(I)
- I = 输入的物质
- F = 处理函数,代表一种方法
- id 唯一标志性的中间产物
最简单的例子就是哈希函数,不考虑哈希碰撞,它就可以根据不同的内容输出不同的哈希值。思维在这里不要局限于哈希函数。
获取图片的唯一id
这里用图片代表一系列的文件类数据。
- 我们可以将图片转换成 []byte 字节数组,然后计算其哈希值。这种操作虽然比较简单,但是图片别人却不能访问,看不到;
- 如果我们想向外部任何人提供图片的读权限,在计算完 id 后,有两种做法:
- 上传图片到文件服务器,任何人可以通过 url 链接访问。这里的服务器是中心化的;
- 增加区块链属性。上传文件到 IPFS (ipfs是什么,自行搜索),如此一来,文件别人能访问,同时还具备了区块链的去中心化等属性。其中 IPFS 会在上传完文件后,会使用它的算法,帮你计算好哈希值返回,可以直接用它的作为id。
获取衣服的唯一id
这里用衣服来代表一系列的实际物质。如果获取它们的唯一id呢?做法可以放飞思维去思考,比如可以:
- 衣服的出厂信息、扫描内容、照片,等系列关于它的信息,数据化,然后用这些数据制作成文件,最后参考图片的做法。
第二步:通证化
第一步中获取了物质的id,现在要把它们通证化。切记一点:目前公认的 NFT 都是基于区块链公链的,那么以后是不是会一直这样呢?不一定,说不准出来了新的共识。
基于不同公链的流程
通证化的流程如下:
- 选择一条区块链公链。这里的选择会决定后面
智能合约
等系统组件的技术栈,这一点很核心; - 在所选的公链上开发智能合约;
- 所开发的智能合约需要遵循一些基础约定,比如至少能保证物质的id能达到验证去重,什么意思呢?意思是,如果 A 在今天上传了 id=1 到链上,明天 B 也上传同个 id=1 到链上,合约要能告诉 B,你不能上传了,id 已经存在;
- 部署智能合约到链上,此时它变成 DApp;
- 通过发交易的方式,调用该智能合约的方法,将id等相关数据存储到链上。
NFT 的智能合约
NFT 智能合约可以基于不同的公链开发,它不局限于任何一条公链。不同公链的智能合约方案实现也不同,下面以 以太坊 公链举例说明。
在以太坊上面,开发 NFT 智能合约,已经有很多标准,比如 ERC-721 \1155 \998,各有各的特点,但它们的特点是在基础属性上拓展而来的。(各标准文档: https://eips.ethereum.org/EIPS/eip-721)
如果选择 ERC-721 标准开发 NFT 智能合约,在元数据存储部分,就有 tokenUrl 这项,它相当于物质的唯一id,像下面的样子, _tokenURIs
存储的就是通证当前计数id与其对应的 tokenUrl,这里的tokenUrl 是字符串格式,一般是文件url,存储在 IPFS 或其他服务上面的文件的链接,但不局限于链接,也可以是其它的内容。
// 伪代码
contract MyERC721 is IERC721Metadata, ... {
...
mapping(uint256 => address) private _tokenOwner;
mapping(uint256 => string) private _tokenURIs;
uint256 public tokenCounter; // 计数,当前总的 NFT 的数量,累增
constructor () public ERC721 ("name", "symbol"){
tokenCounter = 0;
}
// 外部调用方,调用这个函数,传参数:tokenURI 即物质的id,tokenURI 唯一
function createNFT(string memory tokenURI) public returns (uint256) {
uint256 tokenId = tokenCounter;
_mint(msg.sender, tokenId); // 将交易发送者和当前的 tokenId 绑定
_setTokenURI(tokenId, tokenURI); // tokenId 映射到 tokenUrl
tokenCounter = tokenCounter + 1; // 累加
return tokenId;
}
// _exists 函数判断 tokenId 是否存在,_tokenOwner[tokenId]
// 根据 id 读取对应的 url
function tokenURI(uint256 tokenId) external view returns (string memory) {
require(_exists(tokenId));
return _tokenURIs[tokenId];
}
// 根据 tokenId 和 url 建立 map 数据关系
function _setTokenURI(uint256 tokenId, string memory uri) internal {
require(_exists(tokenId)); // _exists
_tokenURIs[tokenId] = uri;
}
... // 省略系列接口,包含读接口
}
上面的 tokenUrl 是标准要求的存储数据项。整个合约具备下面约束功能:
- NFT 持有者,即 msg.sender(owner) 和 tokenId 一对多关系,代表一个人可以拥有多个 NFT;
- tokenId 和 tokenUrl 一对一关系,代表每份数据一个链上的唯一id,同时 tokenUrl 没要求是唯一,但在调用方,一般会把 tokenUrl 设置唯一,即使不唯一也没关系,冲突的时候,tokenId 越小的,其当初被设置的时间就越早;
- NFT 持有者在将数据写入链上后,能够获取 NFT 的链上唯一 id,后续可以根据 id 进行系列的读写操作。
一般来说,我们常规的 NFT 有一个和数据建立关系的项就足够了,但并不局限于此,合约在实现了标准要求的接口后,完全可以自己添加自定义数据项及其读写函数。
第三步:展示与修改
展示 NFT 内容
所谓展示,就是对 NFT 的数据进行读取再展示。一般的流程如下:
- 根据当初设置 NFT 数据到链上时获得的 id 去智能合约读取信息;
- 将获得的信息通过某介质应用还原出原始的 NFT 数据。
比如将图片 NFT 展示出。(借助上面的 721 合约标准和 IPFS 结合为例)
- 假设调用合约存储数据时候得到的 tokenId 是 3,那么使用这个 tokenId 去调用合约的读数据方法;
- 执行完 1 步骤,可以得到 tokenUrl,即文件存储在 IPFS 中所得到的链接;
- 直接将 tokenUrl 链接在浏览器打开,看到图片。
修改 NFT 内容
修改是一项 NFT 智能合约的拓展功能,可有可无,具体是怎样的方式,完全看需求的实现。比如:
- 允许重置 tokenId 所对应的内容;
- 在 NFT 原数据中增加其他字段内容,再允许修改这些字段;
- 转让 NFT,可以把某 tokenId 对应的 NFT 信息转让给其他 owner,达到转让目的;
出售 NFT
、拍卖 NFT
等操作....
所有权共识
目前 NFT,非同质化通证。本质是想借助区块链的属性来标示一种资产的所有权证明。
比如曾拍卖出6000多万美金的数字作品(图片)《Everydays: The First 5000 Days》,中标者能获得原图 和 该图的 NFT。这两样东西,一样是实质的作品,一样是它的所有权者的证明。
我们假设下,如果持有某作品的人,是一位匿名者A,过了多年后,该作品本身不小心被盗并被找回。那么如何证明 A 是真正的拥有者,此时 A 只需要展示他对该作品的 NFT 拥有权,就可以证明。
那么 NFT 是不是类似于我们现实中的证书?不全是,分两点:
- NFT 和证书都能证明某资产的所有权;
- 对比的存储介质 与 永恒时效:
- 证书可能要找个保险柜保养放着,但它终究占据一方土地,仅受一方土地容纳的保险柜保证安全,在时过境迁的影响下,持续性存储下去的时间会较短;
- NFT 存储在区块链上,受整个互联网的链节点所保护。它能够存活到整个链网络垮掉那天,对于节点数量众多的公链来说,这个概率几乎等同于互联网终结那天。
第三方平台
现在已经有很多的第三方的 NFT 制作与发布平台。比如 opensea、rarible 等,这些平台自己实现了 NFT 的智能合约 和 NFT 展示应用(介质应用---网站),方便大众 0 代码基础体会 NFT。但也有一些门槛,需要具备钱包和发交易的油费。
区块链-NFT 的实现原理的更多相关文章
- 区块链轻松上手:原理、源码、搭建与应用pdf电子版下载
区块链轻松上手:原理.源码.搭建与应用pdf电子版下载 链接:https://pan.baidu.com/s/1rKF4U9wq612RMIChs0zv8w提取码:hquz <区块链轻松上手:原 ...
- 002/区块链核心概念与原理详解(Mooc)
1.课程介绍 (一).区块链前世今生 密码朋克--神秘组织(邮件组) 2.区块链核心概念与原理 (一)比特币是数字货币 为什么叫区块链? 因为比特币系统里面的数据是一个个的区块来存储,并且通过hash ...
- 40多行python代码开发一个区块链。
40多行python代码开发一个区块链?可信吗?我们将通过Python 2动手开发实现一个迷你区块链来帮你真正理解区块链技术的核心原理.python开发区块链的源代码保存在Github. 尽管有人认为 ...
- 未来-区块链-IBM:IBM 区块链技术开发社区
ylbtech-未来-区块链-IBM:IBM 区块链技术开发社区 1.返回顶部 1. 开始学习 IBM Blockchain 101:开发人员快速入门指南 这篇快速入门指南适合不熟悉区块链技术,希望快 ...
- 「About Blockchain(一)」达沃斯年会上的区块链
「About Blockchain(一)」 --达沃斯年会上的区块链 写在前面:1月23日到26日,在瑞士达沃斯召开了第48届世界经济论坛.这个新闻本没有引起我格外的关注,直到前两天张老师分享给我一篇 ...
- SHA-256算法和区块链原理初探
组内技术分享的内容,目前网上相关资料很多,但读起来都不太合自己的习惯,于是自己整理并编写一篇简洁并便于(自己)理解和分享的文章. 因为之前对密码学没有专门研究,自己的体会或理解会特别标注为" ...
- 通过blockchain_go分析区块链交易原理
原文链接-石匠的Blog 1.背景 在去中心化的区块链中进行交易(转账)是怎么实现的呢?本篇通过blockchain_go来分析一下.需要进行交易,首先就需要有交易的双方以及他们的认证机制,其次是各自 ...
- 【以太坊开发】区块链中的预言机:Oraclize原理介绍
智能合约的作用很多,但是很多数据还是要基于互联网,那么如何在合约中获取互联网中的数据?Oraclize就是为了这个目的而诞生的. 工作原理: 智能合约通过对Oraclize发布一个合约之间的调用请求来 ...
- 区块链原理、设计与应用pdf电子版下载
链接:https://pan.baidu.com/s/1koShkDjEYOXxLOewZJU2Rw 提取码:8ycx 内容简介 · · · · · · 本书由专业区块链开发者撰写,是区块链开发起步 ...
随机推荐
- SpringCloud:feign默认jackson解析'yyyy-MM-ddTHH:mm:ssZ'时间格式报错
Feign默认的使用jackson解析,所以时间传值时会报错,时间格式错误 解决办法: 修改feign解析方式为fastjson方式: @Configuration public class CxfC ...
- java 语言知识
1.javase 标准版主要用于桌面应用.控制台:javaee 企业版主要用于web应用:javame微缩版主要用于嵌入式. 2.jre是java程序的运行环境,包含jvm(java虚拟机).jdk是 ...
- 「CF1380G」 Circular Dungeon
CF1380G Circular Dungeon 看懂样例就能做. 虽然我瞪了 20 分钟 菜是原罪 首先可以将从每一个点出发所能获得的价值相加,再除以 \(n\) 就可以得到价值的期望. 所以问题转 ...
- ICMP、ARP协议介绍和ping命令
交换机工作原理和常用的简单命令 一.ICMP协议 1)ICMP协议的封装 二.ARP协议 1)什么是ARP协议 2)ARP相关命令 三.Ping命令的使 ...
- Spring Boot(三):Spring Boot中的事件的使用 与Spring Boot启动流程(Event 事件 和 Listeners监听器)
前言:在讲述内容之前 希望大家对设计模式有所了解 即使你学会了本片的内容 也不知道什么时候去使用 或者为什么要这样去用 观察者模式: 观察者模式是一种对象行为模式.它定义对象间的一种一对多的依赖关系, ...
- C语言:编译具体过程及隐藏
对于平常应用程序的开发,很少有人会关注编译和链接的过程,因为我们使用的工具一般都是流行的集成开发环境(IDE),比如 Visual Studio.Dev C++.C-Free 等.这些功能强大的 ID ...
- C++11 左值引用和右值引用与引用折叠和完美转发
1.左值与右值 最感性的认识. 当然,左值也是可以在右边的. 左值是可以被修改的,右值不能. 当然取地址也是. 生存周期一般左值会比右值的长,一般右值都计算时产生的无名临时对象,存在时间比较短. 下面 ...
- MapReduce学习总结之Combiner、Partitioner、Jobhistory
一.Combiner 在MapReduce编程模型中,在Mapper和Reducer之间有一个非常重要的组件,主要用于解决MR性能瓶颈问题 combiner其实属于优化方案,由于带宽限制,应该尽量ma ...
- 九九乘法表(Java版)
3.九九乘法表 //九九乘法表 public class MultiplicationTables { public static void main(String[] args){ for (int ...
- intouch 10.1出现暂停读取PLC数据问题及其解决
问题描述 雨水泵站经过3年运行,突发dasmbtcp驱动与施耐德M580系列PLC时断时连问题 原因分析 在经过现场软件重装修复,授权重装,网络通讯状态监视(一直ping PLC IP地址方式)重装d ...