前面我们理解 Aleo 的 Record 模型介绍过 Aleo 中的 Record 模型,当时只是介绍了 Record 模型和账户模型的优劣势以及在 Aleo 中的展现。这篇文章作为前面文章的进阶,将帮助我们对 Record 模型有更加深入的理解。
Record
Record 是用于表示用户资产和应用程序状态的基本数据结构。
在区块链中,主要有两种状态模型:UTXO(未花费交易输出)和账户模型(由以太坊引入)。 Aleo 中的记录模型是 UTXO 模型的变体。在继续讨论 Record 模型之前,我们先简要讨论一下 UTXO 模型,以便更好地理解。z比特币和其他区块链系统中使用的 UTXO 模型的工作原理是将每一种加密货币视为独特且未使用的数字货币“块”。当您想要发送代币时,这些块(本质上是您尚未花费的数字代币)将被收集以形成您的交易。这些代币被用作向某人付款的输入,一旦使用,它们就被视为已用。这种方法确保每个代币都可以被安全地追踪,从而防止两次使用相同代币的机会。
这和我们日常使用现金支付的时候特别像,A 想要向 B 付款。目前,A 在两个不同的 UTXO 中总共有 X 金额,每个 UTXO 包含不同的金额。 B 拥有一个起始值为 Y 的 UTXO。由于 A 的 UTXO 之一的金额已经足够支付给 B,因此我们只需要使用这一个 UTXO 进行付款。使用的UTXO将显示为红色,表示已花费,未花费的金额将返回到A的钱包,以绿色表示。付款金额也将发送到 B 的钱包(标记为绿色)。
最终 A 将获得一个金额为(X - 付款金额)的新 UTXO,B 将获得一个金额(Y)的新 UTXO。
Record 模型的优势
尽管帐户模型对于开发人员来说更容易,因为它使用帐户地址来管理全局状态,但它带来了隐私问题。私有账户模型可以保证交易的机密性,但不能完全保护用户隐私,因为账户地址本身无法加密。
Record 模型通过使用程序 ID 而不是帐户地址来管理数据,从而提高了隐私性。在这个模型中,程序负责维护自己的内部状态。这也意味着不需要为每笔交易读写整个 Aleo 网络的完整状态,这使得 Aleo 的设计更加高效。
Record 模型的运行过程
为了理解这个模型是如何工作的,让我们看一个例子,其中 Alice 想要向 Bob 发送一些代币。最初 Alice 有一条包含 50 个 token 的 record。
包含 50 个 token 的 record 被程序本身消耗,同时创建了 2 个新 record:一个将未花费的 token 返回给 Alice,另一个将 30 个 token 发送给 Bob。
现在 Alice 有一条包含 20 个 token 的 record,她决定再向 Bob 发送 5 个 token,这将消耗她之前拥有的 record 并创建两条新 record :一条包含 5 个 token 的 record 发送给 Bob,另一条包含 15 个 token 的 record 发送给 Alice。
这些 record 不会直接出现在 Alice 或 Bob 的钱包中,这些 record 的管理全是由使用的这个 token 程序。使用该程序作为参考,record 在程序中以下图的方式展现。
该示例可以通过创建多个 transitions 来扩展到更复杂的程序。每个交易可以包含 32 个transition,所有这些 transitions 都负责消费和创建新的 record。
每个 record 都包含指定记录所有者、其存储的值和其应用程序状态的信息。 Aleo 中的 record 是通过 transition 函数来消费和创建的。一个交易将包含多个 transition,每个 transition 负责其单独 record 的消耗和创建。如果 record 的可见性是私有的,则可以使用所有者的私钥对其进行加密。transition 不能消耗其他程序创建的 record,我们将在本节稍后讨论这一点。
Record 的组成
Aleo record 按以下格式序列化:
aleo1r0dry2tlhjt0yplctz85692kjpqsadn7xgxsmrehkasykjxynypqza3fpl
owner 是一个帐户地址,指定有权使用该 record 的地址。
data
[ RECORD BYTE MAP ]
data 可以对任意应用信息进行编码。
**nonce **
3024738992072387217402876176731225730589877991873828351104009809002984426287group
nonce 用于为每个 record 创建唯一标识,通过对 owner 的地址密钥询问和 record 的序列号进行 PRF 评估来计算。
下面可以通过从 token workshop 调用 mint_private transition 来展示一个示例记录:
{
owner: aleo13ssze66adjjkt795z9u5wpq8h6kn0y2657726h4h3e3wfnez4vqsm3008q.private,
amount: 100u64.private,
_nonce: 5861592911433819692697358191094794940442348980903696700646555355124091569429group.public
}
amount
字段是指 record 的数据字段,可以包含各种类型,例如小额积分、字段,甚至自定义字段。这为开发人员提供了构建各种 dApp 所需的灵活性和隐私性。
Record 加密
record 的私有数据被编码一个包含各个参数的列表,并使用 record 所有者的 viewKey 进行加密确保其完整性,然后记录在区块链分类账上。
Aleo 账户的 viewKey 源自其私钥,主要用于加密和解密 Aleo 区块链交易输入/输出。
此过程使用户能够通过网络安全、私密地传输数据。该系统的一个关键方面是,只有各自拥有各自 viewKey 的发送者和接收者才能解锁和访问这些 record 的内容。这种保护措施可确保敏感信息免受未经授权的访问,同时保持交易过程的透明度和信任,为安全通信提供坚实的基础。
加密和解密的代码可在 snarkVM 部分中找到,可以分别在加密和解密页面访问。
此外,用户可以通过 Aleo Tools 上提供的 Web 界面使用 viewKey 解密加密记录。此功能允许直接通过浏览器实际应用加解密过程。
消费 Record
生成交易涉及对创建新 record 的承诺,以及计算需要消费的 record 的唯一 nonce。
在上面的图中, ron 代表消耗的旧 record,而 rnn 代表创建的新 record。
transition 函数通过为每条 record 分配新的承诺来消耗旧 record,同时计算旧 transition 的序列号。
对 record 的每个承诺都需要记录新 record 所有者的地址和 nonce。要生成新 record 的序列号,需要旧 record 的 nonce 和 地址。
一般来说,要消费一条 record,必须以下几个参数:
-
record 类型必须由正在生成的程序定义。
-
record 的 owner 字段必须与尝试使用该 record 的 owner 匹配。
如何使用
为了进行开发,我们通过一个 Leo 示例来说明如何编写私有的转账函数。
Alice 的钱包是: aleo1mgfq6g40l6zkhsm063n3uhr43qk5e0zsua5aszeq5080dsvlcvxsn0rrau
Bob 的钱包是: aleo1r0dry2tlhjt0yplctz85692kjpqsadn7xgxsmrehkasykjxynypqza3fpl
我们必须首先定义我们record
命名的 token。
record token {
// The token owner.
owner: address,
// The token amount.
amount: u64,
}
然后,我们向 Alice 的钱包 mint 50 个 token。完整的 token 示例可以在 token workshop 中找到。我们看看 record 输出。
首先,alice 通过mint_private
转换 mint 50 个 token,并得到以下输出:
{
owner: aleo1mgfq6g40l6zkhsm063n3uhr43qk5e0zsua5aszeq5080dsvlcvxsn0rrau.private,
amount: 50u64.private,
_nonce: 3450106169496550617224595883750670565200268145577126679432992175407463806853group.public
}
此输出是 record 的未加密纯文本形式。
以下是该 record 的加密状态(公众可见):
record1qyqsp2cu6v5ve727k3rd66uwhpna7mk4vzxmjqf8sjej779ucxfd7lq2qyrxzmt0w4h8ggcqqgqsqu3phm8a8294dh0j74ag609uy26kcutekkvs326f0t3r668x23cps5m7y9d9hs0lttxq420ektrg0ef8vf9lhwpkdc57kxzrah4s5qrsvmgtpe
现在,她想私下向 Bob 发送 30 个 token。她必须向 transition 函数提供上面包含 50 个 token 的 record :
transition transfer_private(sender: token, receiver: address, amount: u64) -> (token, token) {
// `difference` holds the change amount to be returned to sender.
let difference: u64 = sender.amount - amount;
// Produce a token record with the change amount for the sender.
let remaining: token = token {
owner: sender.owner,
amount: difference,
};
// Produce a token record for the specified receiver.
let transferred: token = token {
owner: receiver,
amount: amount,
};
// Return the records
return (remaining, transferred);
}
transfer_private 函数将返回 2 条新的 record。一是包含Alice未花费的20个 token 的 record;另一条是Bob的 record,包含30个 token。
以下是 Alice 的新的 record:
// Alice's record which contains unspent tokens
{
owner: aleo1mgfq6g40l6zkhsm063n3uhr43qk5e0zsua5aszeq5080dsvlcvxsn0rrau.private,
amount: 20u64.private,
_nonce: 1971509502429758089141761286376144078821807406619550800004229996557640403164group.public
}
Alice 的 record 明文加密后的样式:
record1qyqsqqnmndy7k3nd5zedgywnufy724ztjvvr40re7njqf962upmdapq8qyrxzmt0w4h8ggcqqgqsq59hzqsp35hwvpk4658lsl6e7j7n3k3pa89wyywqam3m62pghjcvmsyys003v2ejkq4y9wxt5wjpekmun8dam9kzwpe6yzamnd74tvzq7qzqfu
在 Bob 的例子中,我们无法看到链上的明文,只能看到 record 加密之后的样子:
record1qyqspu23kewnpp9r9r7kwaav5d60yle6pzknghwvf6l56jzdga9fracrqyrxzmt0w4h8ggcqqgqsqtvde34ft8fwfsguva8ry2e628r7sx03jrl3f52s3r9n99tnuyc3ky94fd9dk0smq2syv733jffr0hwxhxee2x4a8wfvfm9sddaelupq6tumud
然而,Bob 可以查看其 record 明文,因为他拥有 viewKey:
// Bob's record which contains the payment
{
owner: aleo1r0dry2tlhjt0yplctz85692kjpqsadn7xgxsmrehkasykjxynypqza3fpl.private,
amount: 30u64.private,
_nonce: 290810109892178756853752382422038662093381719041473229751040430019433255981group.public
}
Aleo 官方链接:
评论 (0)