Atomical协议学习

  • maodaishan
  • 更新于 2024-03-12 10:23
  • 阅读 1274

本文主要来自Atomical官方文档的翻译和摘取,时间:2024.1

<!--StartFragment-->

本文主要来自Atomical官方文档的翻译和摘取,时间:2024.1

1. 协议基础

Atomicals协议文档:https://docs.atomicals.xyz/\ Indexer 解析器:https://github.com/atomicals/atomicals-electrumx\ 铸造工具:https://github.com/atomicals/atomicals-js\ 相关交易市场:\ https://atomicalmarket.com/\ [https://satsx.io/](https://satsx.io/marketplace/atomicals/ft/sort?page=1)\ https://bitatom.io/\ 社区的ElectrumX服务端点:https://docs.atomicals.xyz/reference-and-tools/electrumx-api-and-public-endpoints\ 简介:\ Atomical是基于UTXO的,比特币网络上的NFT,不需要indexer就可以工作。Atomicals 是可自证、易于验证的。\ Atomical的目标是描述数字对象(注意它是对象,不是特指NFT)。静态或动态对象都可以。\ Atomical的理念是把在传输时,验证UTXO的整个历史。即使一个atomical被转手了10000次,产生的数据大小也仅有2.5MB (250byte*10000)。所以它是自证明的,不依赖于第三方服务和indexer。\ "No transaction history, not your digital object"\ 常见用法:\

  • NFT
  • ARC20
  • Collections Container
  • Realm Names

标识\ Atomical的标识有3种:\

  • Atomical Number:从0开始的顺序字符,表示atomical铸造的顺序,是个短的简单的表达法。
  • Atomical ID:是Atomical的唯一标识符。是铸造它的txid和输出的序号, \<txid>i\<index> 例如:a14e65573ff32b95b91a0ed8367feec64125e5f4ff44d9901002b262da959e6di0 i不是16进制里的数字,所以一定不会认错。上面表示a14e65573ff32b95b91a0ed8367feec64125e5f4ff44d9901002b262da959e6d是txid,i是分隔符,0表示第一个output。
  • REF,是把Atomical ID用Crockford-base32 编码显示的结果,可以有更丰富的字符集。

动态对象\ 将一个或多个文件或变量添加Atomical的每次交易的 UTXO 的支出中,indexer会计算并展示最终的状态。\ 数据可以是key-value,也可以是文件,比如PDF,图片等。\ 针对每个Atomical,在转移,更新等操作时,都会验证它的全部历史,从而获得它的最新状态。\

  1. NFT

铸造:\ Atomical通过Taproot支出脚本的两步提交和揭示方案创建,通过Atomical信封+"m"表示的铸造操作来铸造。交易的输出中承诺了被提交的数据或文件。然后数据被包含在一个支出脚本中,以揭示内容,这可以是一个或多个文件,包括任何类型的内容,如图像、文本或任何媒体。\ 更新:\ 除了不可变的内容和文件之外,Atomicals 数字对象支持在使用由字母 "u" 表示的更新操作后的任何时间附加任意数量的文件和状态。方法与铸造类似。\ 由于不可变存储的特性,每个文件的修订历史都被永久存储,以便能够准确回放状态变化。\ 转移:\ 一旦铸造完成,Atomical 可以像普通比特币一样通过任何类型的交易进行转移,包括 Taproot (P2TR)、SegWit、Multisig 和传统地址 (P2PKH)。\ 强烈建议使用支持 Atomicals 的钱包,在使用不支持 Atomicals 识别的钱包时,用户如果不小心可能会将其发送给错误的接收方。\ 转移的规则:\

  • Atomical 的身份从交易中的第 i 个输入流向第 i 个相应的输出。如果交易中的输出少于 i 个,则 Atomical 的身份总是流向该交易中的第一个输出。
  • 如果在同一笔交易中花费了多个 Atomicals,并且每个 Atomical 花费都没有足够的相应输出(例如,有2个输入,但只有1个输出),那么会发生这样的情况:这些多个 Atomicals 将流向第一个输出,从而在同一UTXO上印刻了多个 Atomicals!这并不是一个大问题,实际上,这是一个有用的特性,可以将多个 Atomicals 关联到单个 UTXO 上。
  • 我们必须提供一种方法来"分裂"或提取任何单个 Atomical,通过 Atomical Id 进行引用。以下是为此目的提供的 'Splat' 协议操作。提取操作接受一个数组:将当前输入中的 Atomical Id 强制放入第一个输出。这就是能够从单个 UTXO 中拆分出任意数量的 Atomicals 所需的全部操作。如果携带的输入与 Atomical Id 不相关(由于开发者错误),那么它被视为"无操作"。

注意,转账规则也适用于最初铸造的 Atomical。例如,如果在输入位置 i 处铸造了一个 Atomical,那么该 Atomical 的标识将被印在第 i 个输出上,除非输出较少,或者碰到了一个无法花费的OP_RETURN,在这种情况下,标识始终将被印在第一个输出上。请注意,可以在单个交易中铸造多个Atomical,如果输出数量少于相对于输入数量所需的数量,则在没有匹配的第 i 个输出的情况下,Atomical将分配给第一个输出。\

\ SWAP\ 下面是一个swap的例子,input1是买家输入的,input2是卖家输入的,把7771卖给买家。\

\ Splat\ 注意分离出来的顺序。\

\

2 . ARC20

ARC20用聪来代表token,它们可以像普通比特币那样组合和拆散。\ ARC20的名字先到先得,一旦被注册,后续重名的就无效。\ ARC20的mint有直接mint和去中心化mint两种。\ 2.1 mint\ 2.1.1 去中心化mint\ 初始化\ 去中心化mint的初始化包括如下内容:\

  • ticker(名字)
  • per mint award (每次mint获得多少),
  • total mints allowed (总共可以执行多少次mint),
  • start block height(开始mint的块高),
  • metadata

例如:名字:myticker123,每次允许mint :1,000, mint次数总量:10,000,从块810,000开始mint,使用 image.jpg 甚至metadata(例如描述、链接).\ npm run cli init-dft &lt;tick> &lt;per_mint_amt> &lt;mint_count>\ &lt;start_height> metadata.json\ \ \ Optional flags:\ --mintbitworkc=&lt;prefix>\ --satsbyte=&lt;number>\ 初始化时还可以加一个可选的mintbitworkc参数。它要求minter提供一个工作量证明前缀,来表示自己付出了一定工作量。例如--mintbitworkc="777",表示minter要计算出开头为777的证明。\ --satsbyte=&lt;number>是为每byte愿意支付的gas fee(聪计价),不是Atomical协议的部分。\ mint\ npm run cli mint-dft &lt;tick>\ Optional flags:\ --satsbyte=&lt;number>\ 2.1.2 Direct Mint\ 在一次交易里把全部的都mint出来。每一聪代表一个币。\ npm run cli mint-ft &lt;tick> &lt;total_supply> metadata.json\ Optional flags:\ --satsbyte=&lt;number>\ 例如,要铸造供应量为 100,000,00000 的代币,只需创建一个恰好包含 1 个完整比特币的输出(因为 1 BTC = 100,000,00000 Satoshis)。使用直接铸造模式的一个优点是,必须提供所需数量的比特币来证实铸造的总供应量;这大大减少了不诚实的行为者凭空打印代币的情况。\ metadata可以直接写进铸币交易。可以用permanent-file-storage来保存图片,再把图片ref进去。\ { "name": "", "desc": "", "image": "atom:btc:dat:\<location of store-file data>/image.png", "decimals": 0, "links": { "x": { "v": "https://x.com/..." }, "website": { "v": "https://..." }, "realm": { "v": "atom:btc:realm:myrealmname.subrealm" }, "discord": { "v": "https://discord.gg/..." } }, "legal": { "terms": "" } }\ metadata里没有任何字段是必须的,也可以采用任何形式,只要是json就行。\ 2.2 转账\

  1. 所有的input应该完全,干净的进入到output。如果output不够,或者某个output过多会导致膨胀(比如多个输入,其中一个有atomical,其他的没有,就可能导致output膨胀),此时多余的余额会被烧掉。 例如下图,1932、7920、0542 Atomical,按FIFO顺序分配,同时跳过不可花费的输出 (OP_RETURN)。第一个输入 NFT 从输出 0 开始分配,然后每个后续 NFT 输入分配给下一个可用输出。 同一 UTXO 输入的多个 Atomical 按atomical_id 排序。由于“1932”在“7920”之前,因此它排在第一位。

\

  1. 在无法完全(或“干净”)分配输出的情况下,算法会尝试从输出 0 开始分配所有 ARC20 令牌,无论是否已分配另一个 ARC20。做出这一决定是为了在开发人员或钱包意外未能跟踪多个输入 ARC20 的情况下给予宽大处理 - 换句话说,将“尽最大努力”尝试进行补偿和分配 (没看懂,为什么7920不被分配进第2,3个output? 为什么第3个output没有包含600个0542?)\

\

\

\

  1. 当输出中没有足够数量的聪来容纳输入值时,原子分配不足。结果是多余的输入值被烧毁——或永久销毁。上面的例子显示 Atomical 86a1 的输入值为 2600,但输出中只有 1600 Satoshi,这实际上导致 1000 个单位的 Atomical 86a1 被销毁。

\

  1. 当预期输出中的 Satoshis 过多并且原子的输入没有足够的剩余余额时,原子的分配会被错误地分配。上面的例子显示 Atomical 86a1 的输入值为 2600,第一个输出有 600 个 Satoshi,但第二个输出有 2100 Satoshi,这无法与 Atomical 86a1 抗衡,因为只剩下 2600 - 600 = 2000 个单位的 Atomical 剩余分配。尝试分配会导致供应膨胀,因此被视为无效。结果是 2000 单位 Atomical 86a1 被永久摧毁

\ 2.3 swap\ 步骤 1. 卖方签署包含 ARC20 Atomical 9810 的第二个输入和第二个输出,以接收 5000 Satoshis。签名SIGHASH_SINGLE | ANYONECANPAY允许买方添加额外的资金输入以及接收 ARC20 代币的接收地址。\ 步骤 2. 买方在第一个输入中添加资金输入,并添加第一个输出以接收 ARC20 Atomical 9810 值。签署即表示SIGHASH_ALL买方承诺所有输入和输出。\

\ 2.4 指数\ 这个功能在文档里显示还未开发完。\ 由于粉尘限制,使用比特币在单个 UTXO 中传输少于 546 聪是不可能的,因此不可能以低于 546 面额的 ARC20 代币进行传输,这在实际种不太合适。\ 因此考虑通过ST操作符表示进行指数缩放(有放大也有缩小),表示10的几次方。\

\

\

\

\ 当没有SP操作符,但是有指数时,用最大的指数。\

\

3 . 容器(Collection containers)

这是一种特殊的Atomical对象,专门用来作为NFT的集合。容器名字可读,表示NFT和metadata的集合。容器名字以#开头。可以向容器里添加物品,也可以永久封住,不做任何改变。\ Collection的格式:大部分的field都是可选的。\ { "name": "Collection Name", "desc": "Collection description", "image": "atom:btc:dat:\<location of store-file data>/image.png", "legal": { //建议要有 "terms": "...", "license": "CC" }, "links": { "x": { "v": "https://x.com/..." }, "website": { "v": "https://..." }, "discord": { "v": "https://discord.gg/..." } }, "attrs": [ { "name": "bodyarmor", "desc": "Type of body armor", "type": "string", "values": [ "metal", "leather", "field" ] }, { "name": "headcovering", "desc": "The type of head covering", "type": "string", "values": [ "bandana", "helmet", "scarf", "baseball cap" ] }, { "name": "stamina", "desc": "The stamina of the hero", "type": "integer", "min": 0, "max": 10 } ], "items": { "0": { "id": "84718b469c40b1bcc7cb324b8e24e4e442f88cd913687ea2bc7b3e79d4fc4fdei0", //必须 "n": "Some Name", "a": [ //必填,代表attributes.它是一个数组,里面每个值代表“attrs”里定义的每一项的值。 0, 3, 8 ] }, "1": { "id": "1070d7c98304bf5ac9a5addceb13e0ce4e840641f82d71d84cebbdac427c1f4fi0", "n": "Another Name", "a": [ 1, 2, 10 ] }, "Signature Series 1": { "id": "14a0d7c98304bf5ac9a5addceb1de0ce4e840641f82d71d84cebbdac427c1fc3i0", "n": "Special", "a": [ 2, 3, 7 ] } } }\ 如果你的集合没有attr等复杂结构,可以用下面的最简单形式:\ { "name": "Collection Name", "image": "atom:btc:dat:\<location of store-file data>/image.png", "items": { "0": { "id": "84718b469c40b1bcc7cb324b8e24e4e442f88cd913687ea2bc7b3e79d4fc4fdei0" }, "1": { "id": "1070d7c98304bf5ac9a5addceb13e0ce4e840641f82d71d84cebbdac427c1f4fi0" }, "9999": { "id": "14a0d7c98304bf5ac9a5addceb1de0ce4e840641f82d71d84cebbdac427c1fc3i0" } } }\ 可以通过以下命令在链上存储图片,并生成Collections.\ // first store the desired main image on chain (see section below) npm run cli store-file ./path/to/image.png image.png --satsbyte=10 Success sent tx: db8a761ed493627138c5733071558c4caa65912c5cba3e1061c02d6d7933461f { "success": true, "data": { "commitTxid": "b57bad8c0b7f58a552574fafc16b6efbbb3bf966b9ccfb24f03580f9462b5997", "revealTxid": "db8a761ed493627138c5733071558c4caa65912c5cba3e1061c02d6d7933461f", "dataId": "db8a761ed493627138c5733071558c4caa65912c5cba3e1061c02d6d7933461fi0" } } // We will use the dataId above to reference the data on chain // ie: atom:btc:dat:db8a761ed493627138c5733071558c4caa65912c5cba3e1061c02d6d7933461fi0/image.png // Store the collection metadata with the following command: npm run cli set-container-data #mycollection-name collection.json --satsbyte=10\ 容器的一个常见用法是作为NFT集合的容器,进行DMINT(Decentralized Mint)。下面是DMINT的方法:\

4. DMINT

DMINT包含四个步骤:\

  1. 准备Collection的所有数据(各个NFT的数据,如图片等,会公开给社区)。
  2. 配置容器(Collection链上铭刻)。
  3. 验证 NFT item(是Mint NFT里的一个动作)。
  4. Mint NFT(用户操作)

项目方负责1-3, 要mint的用户最终把NFT mint出来。这样上传图片,验证NFT所需要消耗的gas fee,就都是由minter来承担。\ 整个过程挺常规的,不细说了。\

5 . Realm Names

就是域名,did\ 一个人类可读的名字,关联到地址或者某个资源,可以转让。\ Realm Names必须以"+"开头。\ 命令:\ npm run cli mint-realm "myrealmname"\ 5.1 支付\ 可以在支持Atomical的钱包里,通过Realm names进行转账。\ +[inbox]@[realm_name] + 总是出现,表示这是个Atomical Realm inbox: 表示该realm_name下的收款账号。一个realm_name可以有多个收款账号 @ 分隔符,必须有 realm_name: 注册的realm_name 例如: +hello\@samplerealm +main\@samplerealm +support\@samplerealm\ 关于inbox的定义:\ { "paynames": { "delegate": "atom:btc:id:\<atomical_id>/paynames", "hello": { "delegate": "atom:btc:id:\<atomical_id>/paynames/hello" }, "main": { "types": { "btc": { "value": "bitcoin btc address" }, "ltc": { "value": "litecoin ltc address", "notes": "optional notes", "instructions": "optional instructions" } } } } }\ 5.2 子领域\ 应用思考:https://news.marsbit.co/20231118130551840807.html\ 拥有realm name, 就可以在它下面注册子名字,跟ENS的概念一样。\

\ 在Realm,或subRealm的结构里,在“subrealms"名字空间里定义规则。\ 定义规则:\ Step1:定义规则:\ 规则如何定义的描述:https://docs.atomicals.xyz/rules-subrealms-and-dmint\ 下面是一个例子:这个文件命名为rules.json\ { "subrealms": { "rules": [ { "p": "^[a-z0-9]{6,64}$", "bitworkc": "8888.8" }, { "p": ".*", "o": { "0014383fb23c5b1b40025b0e1dd3e310d6e1ee6d316e": { "v": 1000 } } } ] } }\ 上面规则文件表示两条规则:\

  1. 任何人都可以在完成bitworkc:8888.8(大概1-2分钟cpu计算)的情况下,都可以免费mint 6-64长度的,包含a-z,0-9字符的sub realm.
  2. 发送给0014383fb23c5b1b40025b0e1dd3e310d6e1ee6d316e 1000 聪以上,就可以mint任意长度的sub realm。

Step2:\ 提交rules上链,使其active。下面的 +mycoolrealm是之前申请的realm。\ yarn cli enable-subrealms +mycoolrealm file.json --satsbyte=100\ Mint subrealm\

  1. 用以下命令查询要申请的subrealm是否存在,以及要申请的名字是否合法 yarn cli realm-info mycoolrealm.nicesubrealm
  2. 用以下命令完成subrealm的申请 yarn cli mint-subrealm +mycoolrealm.nicesubrealm --satsbyte=100
  3. 如果需要支付,用下面命令完成支付 yarn cli pending-subrealms

. Bitwork挖矿

就是不断换参数(nonce)生成新的交易hash,看交易hash的前几位是否达到了要求。\ 可以微调,例如要求前缀是 7777.10,这里7777就要求前面几位必须是7777,.后面的10表示第5位必须是第10个字符以上,即a,b,c,d,e,f\ 示例:\ https://mempool.space/testnet/tx/000005970d1d9ac218be8e6f78cfda667e4112a63f2fb0b7b000a8cb2d0dded0\ 他的难度就是00000为前缀,然后具体参数需要解码里面的P2TR 信息解码。比如61746f6d 用十六进制解码后则是 atom,646d74 解码后则是Operation 中的 dmt ,然后 payload 信息,需要使用 cbor方法解码,解出来是\ node cbor.js\ {\ "args": {\ "time": 1703318358,\ "nonce": 8083950,\ "bitworkc": "00000",\ "mint_ticker": "atom"\ }\

7. 其他

7.1 递归和引用\ { // Any Atomical data above... "ctx": { // Implied to always get the latest data for an atomical: "resourcename": "atom:btc:id:\<atomical_id>/mydata", // Gets permanent data file image.png at the dat_id "icon": "atom:btc:dat:\<dat_id>/image.png", // Gets the minted "name" property for a collection "collection-name": "atom:btc:container:\<dat_id>$name", // Gets the latest version of import.js located at a realm name "assetbuilder.js": "atom:btc:realm:\<realm_name>/import.js", }, // Another other Atomical data ... }\ Atomicals Universal Resource Name (URN) 定义是:\ atom:\<chain>:\<ref_type>:\<identifier>[$ or /[\<file>]]\ ref_type:"id", "container", "realm", and "dat"\ identifier,对不同ref_type来说,是不同的内容。如对dat来说,是reveal location of the immutable data,即不可变数据的地址。\ 其中:$表示mint时的data,/表示最新的data。注意对ref_type为dat的来说,无论用$还是/,返回内容都一样\ 例如:\

  • atom:btc:id:\<atomical_id> atom:btc:id:14a0d7c98304bf5ac9a5addceb1de0ce4e840641f82d71d84cebbdac427c1fc3i0 表示一个atomical id
  • atom:btc:id:\<atomical_id>$ 表示这个atomical_id最初mint时提供的json
  • atom:btc:id:\<atomical_id>$info.pdf 这个atomical_id最初mint时的info.pdf文件
  • atom:btc:id:\<atomical_id>/ 获取最新数据
  • atom:btc:id:\<atomical_id>/image.png@[txid or version number or blockheight] 获取某个版本的数据
  • atom:btc:container:\<containerName>$ 获取container在mint时的数据

...\ 7.2 链上永久保存图片\ // immutably store an image on-chain to reference in the container metadata npm run cli store-file ./path/to/image.png image.png --satsbyte=10 Success sent tx: db8a761ed493627138c5733071558c4caa65912c5cba3e1061c02d6d7933461f { "success": true, "data": { "commitTxid": "b57bad8c0b7f58a552574fafc16b6efbbb3bf966b9ccfb24f03580f9462b5997", "revealTxid": "db8a761ed493627138c5733071558c4caa65912c5cba3e1061c02d6d7933461f", "dataId": "db8a761ed493627138c5733071558c4caa65912c5cba3e1061c02d6d7933461fi0" } }\ 可以用db8a761ed493627138c5733071558c4caa65912c5cba3e1061c02d6d7933461fi0来引用到这种图片,这就是它的atomical id

<!--EndFragment-->

点赞 1
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
maodaishan
maodaishan
0xee37...1912
江湖只有他的大名,没有他的介绍。