使用 sCrypt 实现一个简单的 NFT 合约

2023-11-11

我们之前的token方案针对的是可替换(fungible)的 token。这里来看看另一种方案如何实现 NFT(non-fungible token)合约。这类 token 可以代表独一无二的和不可分割的资产,比如房地产和收藏品。

概览

与可替换 token 类似,在每个 UTXO 中,token 合约的数据部分也有两个部分与 NFT 有关:

  1. 一个公钥:用于控制 token 的发行或转让。
  2. 一个整数:唯一标识一个 token。

同样,通过使用与公钥对应的私钥进行签名来对 UTXO 中的 token 进行转账。不同之处在于,在 NFT 的方案中每个UTXO只存储一个 token,而不象可替换 token 方案那样可以存储多个 token。

发行

token 发行 UTXO 是一个特殊的 UTXO 合约,只有发行者才可以运行该合约。发行者通过把该 UTXO 拆分成多个 UTXO 的方式来发行新的 token。下图是把 token 发行 UTXO 拆分成两个,这样就发行了一个新的 token i 给Alice。

在这里插入图片描述

下面是相关的代码:

 public function issue(Sig issuerSig, PubKey receiver, int satoshiAmount0, int satoshiAmount1, SigHashPreimage txPreimage) {
        // this ensures the preimage is for the current tx
        require(Tx.checkPreimage(txPreimage));

        // read previous locking script: codePart + OP_RETURN + currTokenId + issuer + matchAction
        bytes lockingScript = SigHash.scriptCode(txPreimage);
        int scriptLen = len(lockingScript);

        // constant part of locking script: upto op_return
        int constStart = scriptLen - DataLen - Constants.PubKeyLen - 1;
        bytes constPart = lockingScript[: constStart];

        bytes matchAction = lockingScript[scriptLen - 1 :];
        // action must be issue
        require(matchAction == NonFungibleToken.ISSUE);

        PubKey issuer = PubKey(lockingScript[constStart + DataLen : scriptLen - 1]);
        // authorize: only the issuer can mint new tokens
        require(checkSig(issuerSig, issuer));

        int currTokenId = unpack(lockingScript[constStart : constStart + DataLen]);

        // increment token ID to mint a new token
        bytes outputScript0 = constPart + num2bin(currTokenId + 1, DataLen) + issuer + NonFungibleToken.ISSUE;
        bytes output0 = Utils.buildOutput(outputScript0, satoshiAmount0);

        // transfer previous token to another receiver
        bytes outputScript1 = constPart + num2bin(currTokenId, DataLen) + receiver + NonFungibleToken.TRANSFER;
        bytes output1 = Utils.buildOutput(outputScript1, satoshiAmount1);

        // check outputs
        Sha256 hashOutputs = hash256(output0 + output1);
        require(hashOutputs == SigHash.hashOutputs(txPreimage));
    }

转移

UTXO 中的 token 可以如下图所示进行转移:

在这里插入图片描述

如下是相关代码:

    public function transfer(Sig senderSig, PubKey receiver, int satoshiAmount, SigHashPreimage txPreimage) {
        require(Tx.checkPreimage(txPreimage));

        // read previous locking script: codePart + OP_RETURN + tokenID + ownerPublicKey + matchAction
        bytes lockingScript = SigHash.scriptCode(txPreimage);
        int scriptLen = len(lockingScript);

        // constant part of locking script: upto tokenID
        int constStart = scriptLen - Constants.PubKeyLen - 1;
        bytes constPart = lockingScript[: constStart];

        bytes matchAction = lockingScript[scriptLen - 1 :];
        // action must be transfer
        require(matchAction == NonFungibleToken.TRANSFER);

        PubKey sender = PubKey(lockingScript[constStart : scriptLen - 1]);
        // authorize
        require(checkSig(senderSig, sender));

        // transfer
        bytes outputScript = constPart + receiver + NonFungibleToken.TRANSFER;

        bytes output = Utils.buildOutput(outputScript, satoshiAmount);
        require(hash256(output) == SigHash.hashOutputs(txPreimage));
    }

组合

下图展示了 NFT 的发行及转移的操作流程。

在这里插入图片描述

这里有完整的合约代码和使用示例

讨论

我们只展示了 NFT 的基本方案。它扩展起来也很简单,例如:

  • 在一个 Tx 中发行多个新 token
  • 在一个 Tx 中转移多个 token
  • 限制 token总量
  • 销毁 token
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 sCrypt 实现一个简单的 NFT 合约 的相关文章

  • 基于QT的串口调试助手制作

    目录 1 创建文件 2 串口界面制作 3 代码 4 结果 5 改进 6 百度链接 1 创建文件 创建带有ui界面的qt程序 可以点击文件 新建文件或项目就会出现上面的界面 选这Application 应用程序 创建项目 其中Qt Widge

随机推荐

  • 实验七 组合数据类型 Educoder

    实验七 组合数据类型 Educoder 组合数据类型是计算机编程中非常重要的概念之一 它允许我们将多个不同类型的数据组合在一起 形成一个新的数据类型 在本篇文章中 我将介绍组合数据类型的概念和用法 并通过一个示例源代码来展示它的应用 在讨论
  • “自顶向下,逐步求精”方法简要介绍

    什么是自顶向下 逐步求精 自顶向下 逐步求精 是结构化程序设计常见的思路 自顶向下 是将复杂 大的问题划分为小问题 找出问题的关键 重点所在 然后用精确的思维定性 定量地去描述问题 逐步求精 是将现实世界的问题经抽象转化为逻辑空间或求解空间
  • openwrt下crontab定时任务实现

    openwrt下crontab定时任务实现 我的需求是需要加个定时执行脚本来监控智能网关运行的进程 一旦网关进程异常关闭 就能立即把它拉起来 从而保证网关运行的可靠性 这里我们用到了crontab服务 OpenWRT系统默认已经加入了cro
  • 最大比例

    题目描述 解析 接下来就是求解k和p的过程 在这道题中很难使用欧几里得算法就求解最大公约数 因此尝试使用另一种方法 更相减损术 循环相减法 如果要使用欧几里得算法的话 就需要开一个非常复杂的根号 非常难算 代码 include
  • 【MyBatis】查询语句汇总

    定义一个Car类 封装汽车相关信息的 pojo类 public class Car 数据库表当中的字段应该和pojo类的属性一一对应 建议使用包装类 这样可以防止null的问题 private Long id private String
  • 大数据面试-07-大数据工程师面试题

    面试问题 1 从前到后从你教育背景 学过哪些课 到各个项目你负责的模块 问的很细 本以为他是物理学博士 但是所有的技术都懂 2 hadoop 的 namenode 宕机 怎么解决 先分析宕机后的损失 宕机后直接导致client无法访问 内存
  • Ubuntu暂停和恢复下载

    下载anaconda时用的官网地址 速度太慢 用ctrl c暂停了 从网上查找的恢复下载的方法有 wget c URL URL是下载网址 不是本地文件的路径 用本地路径时会出现Scheme missing
  • java ref out_ref与out之间的区别深入解析

    ref和out都是C 中的关键字 所实现的功能也差不多 都是指定一个参数按照引用传递 对于编译后的程序而言 它们之间没有任何区别 也就是说它们只有语法区别 总结起来 他们有如下语法区别 1 ref传进去的参数必须在调用前初始化 out不必
  • Github速度太慢全网最全方案

    Github速度太慢全网最全方案 近日 我在Github上下载源码 真的鸡肋 慢的一匹 通过以下方式 让我下载Github速度飞快 因为刚好有代理 就用的第一种方式 而后面几种方式参考自网上的一些方案 自己也尝试了一下 有点用 就贴出来 给
  • SpringBoot2+Netty+WebSocket(netty实现websocket)

    一 SpringBoot2 Netty WebSocket netty实现websocket 支持URL参数 原文链接 https zhengkai blog csdn net article details 91552993 思路 用ne
  • 基于springCloud的微服务架构设计

    Spring Cloud作为一套微服务治理的框架 几乎考虑到了微服务治理的方方面面 之前也写过一些关于Spring Cloud文章 主要偏重各组件的使用 本次分享主要解答这两个问题 Spring Cloud在微服务的架构中都做了哪些事情 S
  • MySQL导入生成ER模型

    概述 ER模型使用可视化了实体存储的信息 以及直观的呈现了实体与实体的关系 在我们实际的应用系统开发过程中新建ER模型可以更好的理解业务模型 为以后的开发维护工作起到归纳总结的作用 Freedgo Desgin是一款轻松 快速 协作地创建各
  • http状态码413,并提示Request Entity Too Large的解决办法

    使用wordpress的用户经常遇到的问题 就是在后台上传多媒体文件的时候 发现文件大小是有限制的 通常是2M 如图 如果上传的文件超过2M 服务端返回的状态码会是413 同时提示上传失败 实际上 这个限制是可以修改的 一般来说 出现htt
  • pandas 创建空csv并且插入和修改数据

    创建带有列名的空csv def create one day csv event date csv df empty pd DataFrame columns id natural language sql isSatisfied df e
  • Linux中./configure --prefix命令是什么意思?

    概念 源码的安装一般由3个步骤组成 配置 configure 编译 make 安装 make install Configure是一个可执行的脚本 它有很多选项 在待安装的源码路径下使用命令 configure help 输出详细的选项列表
  • 为什么越来越多的企业选择云计算?

    随着数字化转型的加速 越来越多的企业开始选择云计算作为信息技术应用的基础设施 那么 云计算究竟有哪些优势 未来发展趋势又是怎样的呢 让我们一起来探讨一下吧 一 前言 云计算作为一种新型的信息技术基础设施 正在逐渐改变着企业和个人的工作方式和
  • 华为OD机试真题- 服务失效判断-2023年OD统一考试(B卷)

    题目描述 某系统中有众多服务 每个服务用字符串 只包含字母和数字 长度 lt 10 唯一标识 服务间可能有依赖关系 如A依赖B 则当B故障时导致A也故障 依赖具有传递性 如A依赖B B依赖C 当C故障时导致B故障 也导致A故障 给出所有依赖
  • 显著性目标检测(一)——与图像分割、目标检测的区别

    这里写目录标题 显著性目标检测 定义 应用领域 存在的问题 目标检测 定义 图像分割 定义 应用领域 显著性目标检测与图像分割 目标检测的区别 显著性目标检测 定义 显著性目标检测 salient object detection SOD
  • Spring Cloud Sleuth+ZipKin+ELK服务链路追踪(七)

    序言 sleuth是spring cloud的分布式跟踪工具 主要记录链路调用数据 本身只支持内存存储 在业务量大的场景下 为拉提升系统性能也可通过http传输数据 也可换做rabbit或者kafka来传输数据 zipkin是Twitter
  • 使用 sCrypt 实现一个简单的 NFT 合约

    我们之前的token方案针对的是可替换 fungible 的 token 这里来看看另一种方案如何实现 NFT non fungible token 合约 这类 token 可以代表独一无二的和不可分割的资产 比如房地产和收藏品 概览 与可