ZooBC 维基
数据与存储

数据集

数据集是把数据放到 ZooBC 上最简单的方式:一条小记录,即一个属性名及其值,由一个账户写在某个账户名下,通常是它自己的账户。每个节点都把这一行作为链状态的一部分保存,因此任何应用都可以通过任意节点的 API 读取它。应用用这些行来存放个人资料、设置、发布公告、发票和代币图标。

一行记录

一笔 SetupAccountDataset 交易(类型 3)写入一行,这一行以三样东西作为键:

  • 设置者,即发送该交易的账户;
  • 接收账户,即这一行所在的账户,通常就是设置者自己(空的接收账户也是有效的键);
  • 属性,一个 1 到 256 字节的名称,不能为空。

值最多容纳 4,096 字节,且整个交易体最多 65,536 字节。行带有版本:再次写入同一个键会替换当前行,而 RemoveAccountDataset(类型 259)会使一行变为非活跃。

一行数据集记录:谁写的、写在谁名下、属性及其值,都位于一个支付租金的对象之中。
一行数据集记录:谁写的、写在谁名下、属性及其值,都位于一个支付租金的对象之中。

行是公开的:任何人都能读取,因此数据集不是存放机密的地方。它也不是保存大文件的方式。小文件用 DFS 文件,大文件放进去中心化存储池。

由谁写入很重要

任何账户都可以在任何接收账户名下写入一行,而且无需征得接收账户同意,就像任何人都可以向任意地址付款一样。因此,一行记录是其设置者关于接收账户所做的一个陈述。链能证明是谁在何时说的,却无法知道这个陈述是否属实。

节点在 GET /api/v1/accounts/<address>/datasets 列出一个账户的行,可以用 ?property=<prefix> 进行筛选。列表返回该地址作为设置者或接收账户的每一行,并为每一行标注其 role:设置者、接收账户或两者兼具。在某个用户名下发现“verified = yes”的应用,必须只在设置者是它所信任的账户(例如它自己的验证账户)时才接受,而在不存在这样的行时必须回答“未验证”(链上数据是不可信的输入)。

两行都写着“verified = yes”;只有由受信任的设置者写入的那一行才算数。
两行都写着“verified = yes”;只有由受信任的设置者写入的那一行才算数。

对象与所有者

每一行都属于一个数据对象,以创建它的那笔交易的哈希命名。对象有一个所有者(最初是其创建者)、一个待定所有者和一种管理模式。

  • 转交分两步。所有者发送指定新所有者的 TransferDataset(类型 42),链只记录一个待定所有者。当该账户发送 AcceptDataset(类型 44)时,转交才完成。来自其他任何人的 AcceptDataset,或者针对没有待定所有者的对象的 AcceptDataset,都是付费空操作:手续费照收,什么都不改变。因此,没有人能把一个对象及其附带的租金硬塞给没有提出请求的账户,而原所有者在新所有者接受之前一直是所有者。
  • 删除。 由所有者发送的 DeleteDataset(类型 45)会停用该对象的每一行,对象的押金则被全部划入长效池。
  • 策略。 SetDatasetPolicy(类型 43)在对象上存储一种管理模式(仅所有者、白名单、黑名单或开放)和一份访问列表,但没有任何共识规则读取它们,因此它们不限制任何事情。

每个对象还有一个押金地址:一个类型为 10 的账户,写作 ZBS_…,其字节为 0A000000 后接对象 id。任何人都可以用一笔普通的 SendZBC 为它注资,因此一群用户可以一起让一条共享记录持续存在。它是一个普通的有资金账户,因此也要支付账户租金。GET /api/v1/dataset-address/<hash or ZBS_ address> 可以查看它。

租金

每个计费周期一次(mainnet 上为 172,800 个区块,约 30 天),链按每个对象活跃行的字节数向它收费:

bytes = sum of (property + value) over the object's active rows
rent  = ceil(bytes × price per MiB ÷ 1,048,576), then × storage multiplier, rounded up

起始价格为每 MiB 5,000,000 个原子单位(0.05 ZBC),存储乘数起始为 1.0。整整 1 MiB 的行每个周期恰好支付 0.05 ZBC。一行的属性为 14 字节、值为 300 字节,共 314 字节,支付 1,498 个单位:314 × 5,000,000 ÷ 1,048,576 等于 1,497.27,而计费的每一步都向上取整。

租金先从押金中扣取,再从所有者的余额中扣取。如果两者合计仍无法支付,该对象的每一行都会被停用,剩余的押金进入长效池。接收账户永远不会被收费。所有数据集租金都记入长效池,长效池在每个区块中向节点支付一部分;ZBC 从不销毁。

计费周期跟随快照间隔。价格由席位投票决定,可以低至一个原子单位;它每个快照周期调整一次,在限度之内调整为计入席位投票的平均值(价格投票)。

保留前缀

少数属性前缀是保留的,链在接受这些前缀下的行之前会先检查它们。检测比较的是属性开头的原始字节,因此 invoice: 不等于 inv:。

前缀规则
dfs: 和 dfs:dir:只能由三种 DFS 交易类型写入;在这里写入的 SetupAccountDataset 会被拒绝(链上文件(DFS))
tokenicon:一个 PNG 或 WebP 图像,声明的宽度和高度为 1 到 512 像素,长度为 16 到 4,096 字节
inv:一个任何位置都没有负数的 JSON 对象,因此发票不能携带负金额;从区块 0 起执行

因此,代币图标就保存在链上、在该行之内,而不是放在某个 URL 之后。这些检查都不涉及任何人的签名:每个节点都应用同一条规则。

另见