🐶原文: Preventing Content Cloning in NFT Collections
🐶写在前面: 这是一篇 2023 年的 CCF-C 类,本博客只记录其中提出的方法。
F C o l l N F T \mathbf{F_{CollNFT}} FCollNFT and ERC-721 NFTs
在以太坊这样的区块链上,NFT 是通过实现 ERC-721 标准的智能合约创建和交易的。
智能合约可以执行的主要操作有:
- 铸币 m i n t \mathsf{mint} mint:创建一个新的代币并将其分配给发行者;
- 转账 t r a n s f e r \mathsf{transfer} transfer:从当前所有者那里转移一个代币到一个指定的账户;
只有当发出交易的账户是智能合约的部署者时,铸币 m i n t \mathsf{mint} mint 操作才会成功。只有当发出交易的账户是 NFT 的当前所有者,或者是被所有者委托过的账户时,转账 t r a n s f e r \mathsf{transfer} transfer 操作才会成功。
因此,ERC-721 符合 P 1 \mathbf{P1} P1 和 P 2 \mathbf{P2} P2。
ERC-721 智能合约通过在智能合约实例的状态内维护一个键值对映射来追踪所生成的代币。当代币 t \mathsf{t} t 属于某个集合时,在该集合中 t . i d \mathsf{t.id} t.id 是键值对的键, ( t . o w n e r , t . d a t a ) \mathsf{(t.owner, t.data)} (t.owner,t.data) 是键值对的值。然而,ERC-721 标准并没有阻止映射中存在两个不同的键 t . i d \mathsf{t.id} t.id 和 t ′ . i d \mathsf{t'.id} t′.id,但是关联到相同的数据 t . d a t a = t ′ . d a t a \mathsf{t.data = t'.data} t.data=t′.data。
由此可见,ERC-721 智能合约通常不能安全地实现 F C o l l N F T \mathsf{F_{CollNFT}} FCollNFT 功能,因为 P 3 \mathbf{P3} P3 可能无法得到保证。因此,我们提出了一种不同的实现 ERC-721 智能合约的两步方法。
首先,我们要求
t
.
i
d
=
s
h
a
256
(
t
.
d
a
t
a
)
\mathsf{t.id = sha256(t.data)}
t.id=sha256(t.data)。然后,如果键尚未存在于键值对映射中,那么新创建的代币可以成功地添加到映射中。基于这一机制,调用 mint
函数创建一个克隆品
t
′
\mathsf{t'}
t′ 将会失败,因为
t
′
.
i
d
\mathsf{t'.id}
t′.id 已经存在于映射中。这保证了集合中数据的唯一性
P
3
\mathbf{P3}
P3,且仍处于 ERC-721 合约的要求之内。
Discussion on the Implementation of F C o l l N F T \mathbf{F_{CollNFT}} FCollNFT
这一小节探讨了如何具体实现与 F C o l l N F T \mathsf{F_{CollNFT}} FCollNFT 兼容的一组图像。
图像可以根据不同的编码方案表示。最常用的方案之一是 RGB 颜色模型,这是一个加色模型,其中红、绿和蓝三种光的原色以各种方式相加,以重现广泛的颜色。具体来说,图像中的每个像素都用一个表示红、黄和蓝分量的三个值的元组来表示。因此,一个 RGB 图像是一个宽度为 M \mathsf{M} M 像素、高度为 N \mathsf{N} N 像素的矩阵,每个单元格有 3 \mathsf{3} 3 个值。
作为一个玩具示例,我们考虑一个宽度为 16 \mathsf{16} 16 像素、高度为 9 \mathsf{9} 9 像素的图像集合,其中每个颜色分量的值可以设置在 0 \mathsf{0} 0 到 255 \mathsf{255} 255 之间。因此,每个图像是一个维度为 16 × 9 × 3 = 432 \mathsf{16 × 9 × 3 = 432} 16×9×3=432 的字节数组。
每个图像都与一个记录了创建时间的元数据相关联,该时间使用 U N I X \mathsf{UNIX} UNIX 时间戳表示,可以用 4 \mathsf{4} 4 字节的无符号整数表示。总的来说,这个集合中的每个收藏品 c \mathsf{c} c 都将包含一个 432 \mathsf{432} 432 字节的 c . a r t w o r k \mathsf{c.artwork} c.artwork 图像和 4 \mathsf{4} 4 字节的 c . m e t a \mathsf{c.meta} c.meta。
为了获得符合 F C o l l N F T \mathsf{F_{CollNFT}} FCollNFT 标准的集合,我们直接将 c \mathsf{c} c 上传到智能合约中,这将强制图像遵守 RGB 格式,即验证对于 M × N \mathsf{M × N} M×N 矩阵的每个单元格都有三个值在 [ 0 , 255 ] \mathsf{[0, 255]} [0,255] 的区间内,并且有指定的尺寸。然后,智能合约设置 t . d a t a = c \mathsf{t.data = c} t.data=c,计算 c \mathsf{c} c 的哈希值,并将其作为 t . i d \mathsf{t.id} t.id 的值。
这种方法的局限性在于它需要将 c \mathsf{c} c 完整上传。在我们的示例中,即使 c . a r t w o r k \mathsf{c.artwork} c.artwork 很小,但我们仍然需要 432 \mathsf{432} 432 字节来表示它。
请注意,微小的 NFT 也是存在的,甚至还有人提出的单比特 NFT 。
然而,图像通常具有更大的尺寸,宽度和高度达到数千像素。因此,图像在许多区块链中不能上链,即使可能的话,大文件也会影响交易费用。以下是解决这一问题的可能的方案。
1 方案一
一种常见的做法是依赖于在 IPFS 上上传收藏品 c \mathsf{c} c,IPFS 是一个点对点网络,用于通过计算在它们内容上的信息(即文件的 s h a 256 \mathsf{sha256} sha256)来共享文件。
对于代币 t \mathsf{t} t,我们设置:
t . i d = a d d r I P F S = s h a 256 ( c ) \mathsf{t.id = addr_{IPFS} = sha256(c)} t.id=addrIPFS=sha256(c)
我觉得原文的公式写错了,怎么可能让 t . d a t a \mathsf{t.data} t.data 也等于 s h a 256 ( c ) \mathsf{sha256(c)} sha256(c)。
然而,这并不能防止恶意铸币者铸造一个新的代币 t ′ \mathsf{t'} t′:
t ′ . i d = a d d r I P F S ′ = s h a 256 ( c ′ ) \mathsf{t'.id = addr'_{IPFS} = sha256(c')} t′.id=addrIPFS′=sha256(c′)
其中, c ′ . a r t w o r k = c . a r t w o r k \mathsf{c'.artwork = c.artwork} c′.artwork=c.artwork 和 c ′ . m e t a ≠ c . m e t a \mathsf{c'.meta \ne c.meta} c′.meta=c.meta。换句话说,数字艺术品 c ′ . a r t w o r k \mathsf{c'.artwork} c′.artwork 和 c . a r t w o r k \mathsf{c.artwork} c.artwork 相同,而关于它们的描述 c ′ . m e t a \mathsf{c'.meta} c′.meta 和 c . m e t a \mathsf{c.meta} c.meta 不同。因此,在 c . m e t a \mathsf{c.meta} c.meta 不是必填项的场景中,我们可以在设计的时候就去除元数据,使得这种攻击无法执行。
简而言之, c \mathsf{c} c 包含 c . a r t w o r k \mathsf{c.artwork} c.artwork 和 c . m e t a \mathsf{c.meta} c.meta 这两部分。只要 c . m e t a \mathsf{c.meta} c.meta 不同,那么都有 c ≠ c ′ \mathsf{c \ne c'} c=c′。因此,这可能会掩盖 c . a r t w o r k \mathsf{c.artwork} c.artwork 和 c ′ . a r t w o r k \mathsf{c'.artwork} c′.artwork 相同的事实,即数字艺术品惨遭克隆。
2 方案二
可以合理地假设数字资产在其生成时由其创作者 c r e a t o r \mathsf{creator} creator 签名,以保证其起源的真实性。
个人理解:创作者 c r e a t o r \mathsf{creator} creator 拥有一对私钥和公钥,使用私钥对资产进行签名,其他人通过公钥对签名进行验证。验签一是能够检验数据是否被篡改,二是能够检验数据是否是由密钥拥有者签署的。
创作者 c r e a t o r \mathsf{creator} creator 通过密码学对资产 c \mathsf{c} c 进行签名,生成 σ \mathsf{σ} σ 签名值。我们可以设置 t . i d = σ \mathsf{t.id = σ} t.id=σ,以保持代币的独特性。这是因为,同一创作者 c r e a t o r \mathsf{creator} creator 对相同的 t . d a t a = c \mathsf{t.data=c} t.data=c 进行签名,会生成相同的 σ \mathsf{σ} σ 签名值。
思考:由于其他创作者 c r e a t o r \mathsf{creator} creator 签署相同的 t . d a t a \mathsf{t.data} t.data 能够得到不同的 σ ′ \mathsf{σ'} σ′ 签名值,并且本文的查重方案只针对代币合约内部而非代币合约之间,因此其他创作者 c r e a t o r \mathsf{creator} creator 可以在自己部署的代币合约上为所欲为😇
然而,创作者 c r e a t o r \mathsf{creator} creator 始终可能被攻陷,例如:攻击者窃取创作者 c r e a t o r \mathsf{creator} creator 的私钥来生成 σ \mathsf{σ} σ 签名值。如前所述,攻击者可以在改变 c . m e t a \mathsf{c.meta} c.meta 后进行签名,得到 σ ′ \mathsf{σ'} σ′ 签名值,进而创建出一个资产 c \mathsf{c} c 的克隆体。
3 方案三
铸币 m i n t \mathsf{mint} mint 交易可以携带一个 p r o o f \mathsf{proof} proof 证明,证明 t . i d \mathsf{t.id} t.id 是资产 c . a r t w o r k \mathsf{c.artwork} c.artwork 的密码学哈希。这可以通过简洁的非交互式知识证明技术 S N A R K s \mathsf{SNARKs} SNARKs 来实现。
Zk-SNARK (Zero-Knowledge Succinct Non-Interactive Argument of Knowledge),简洁化、非交互式的零知识证明技术。
在我们的案例中,铸币者 m i n t e r \mathsf{minter} minter 需要上传一个密码学哈希 s \mathsf{s} s 和一个 S N A R K π \mathsf{SNARK\ \pi} SNARK π 证明。 s \mathsf{s} s 将作为 t . i d \mathsf{t.id} t.id,而 π \mathsf{\pi} π 用于证明铸币者 m i n t e r \mathsf{minter} minter 对 c . a r t w o r k \mathsf{c.artwork} c.artwork 的知识,使得:
s = s h a 256 ( c . a r t w o r k ) \mathsf{s = sha256(c.artwork)} s=sha256(c.artwork)
并且 c . a r t w o r k \mathsf{c.artwork} c.artwork 是一张使用 RGB 颜色模型的图片。
约束条件 π = s h a 256 ( c ) \mathsf{\pi = sha256(c)} π=sha256(c) 避免了恶意铸币者随意设置 c . m e t a \mathsf{c.meta} c.meta,正如方案一中讨论过的情况一样。智能合约验证 π \mathsf{\pi} π 是否正确,然后设置:
t . i d = s h a 256 ( c . a r t w o r k ) \mathsf{t.id = sha256(c.artwork)} t.id=sha256(c.artwork)
以确保 t . d a t a \mathsf{t.data} t.data 在集合中的独特性。
证明 s h a 256 \mathsf{sha256} sha256 的抗图像的 S N A R K s \mathsf{SNARKs} SNARKs 效率过于低效,但实际上可以考虑使用其他密码学哈希函数,如 P o s e i d o n \mathsf{Poseidon} Poseidon,这些函数旨在允许更高效地实例化证明此类声明的 S N A R K s \mathsf{SNARKs} SNARKs。