主页 > imtoken钱包苹果手机怎么下载 > 什么是可升级的以太坊智能合约

什么是可升级的以太坊智能合约

可升级的以太坊智能合约

以太坊区块链上的智能合约是不可变的。 一旦部署了智能合约如何查看以太坊的智能合约,就无法更改合约地址的代码。 您可以完全删除合约,或者更准确地说,如果该功能最初是用代码编写的如何查看以太坊的智能合约,则智能合约可以自毁。 一方面解决了信任问题,用户可以确信一切完全由算法控制。 另一方面,现在修复错误是不可能的。

因此,可升级的以太坊智能合约来拯救我们。 等等,什么? 我们刚刚说过,以太坊中没有这样的合约(与 EOS 不同)。 但是,可以模拟可升级的智能合约。 这个想法是智能合约地址和代码保持不变,代码将执行转发给另一个合约,然后返回它的结果。 在此示例中,主智能合约称为代理。 在变量中保存另一个合约地址后,我们可以像更改合约状态一样轻松地更改它,而代码保持不变。 最终可以有多个智能合约版本; 迁移是通过记录新版本的地址来完成的。

存储可升级的智能合约状态

与任何其他软件类似,开发人员在发布新版本时必须解决数据迁移问题。 对于代理,智能合约应该存储在哪里? 我们有三种完全不同的方法。

单独存储每个版本

第一种方法意味着每个版本将其状态分别存储在自己的存储中。 这确保了最大程度的隔离和控制,排除了冲突,同时增加了将单个记录迁移到存储的复杂性和 gas 成本。 让我们假设正在开发一个基本的代币合约。 在这种情况下,核心数据是余额:

映射(地址=> uint256)私人余额;

新版balance无法直接调用; 为了实现它,必须首先从以前的版本迁移数据。 请注意,迁移只能执行一次。

以太坊智能合约编写_以太坊智能合约教程_如何查看以太坊的智能合约

映射(地址=> uint256)私人余额;

// 之前版本的代币智能合约

ERC20 私人 _previous;

// 标志表示执行了某些用户余额的迁移

映射(地址=>布尔)私有_migrated;

funcTIon balanceOf(address owner) public view returns (uint256) {

return_migrated[所有者]? _balances[所有者]: _previous.balanceOf(所有者);

以太坊智能合约教程_如何查看以太坊的智能合约_以太坊智能合约编写

}

funcTIon setBalance(address owner, uint256 new_balance) private {

_balances[owner] = new_balance;

如果 (!_migrated[所有者])

_migrated[所有者] = 真;

}

什么是可升级的以太坊智能合约

以太坊智能合约教程_以太坊智能合约编写_如何查看以太坊的智能合约

此时会出现其他问题:无法根据任何请求立即完成迁移,因为数据记录可能需要记录到存储中,并且数据记录不能仅用于视图功能。 因此,所有对余额的请求,甚至是内部请求,都必须通过 balanceOf 和 setBalance 函数来执行。

在最坏的情况下,调用仅查看函数将遍历整个令牌版本链,收集数据,但不会记录与最新版本相关的操作结果,因为它们没有修改权限。 从最新版本以外的版本调用这些函数是可能的,但意义不大。

同时,在最新的令牌代码版本中为当前用户迁移数据和记录操作结果需要调用可以改变最新版本状态的函数。 因此,对任何其他函数的进一步调用不需要经过整个令牌版本链。 代理合约只允许调用改变最新版本状态的函数。

作为数据库的合同

可以建议另一种存储方法。 让我们看看这在传统程序中是如何处理的。 数据与代码分离! 此外,当涉及到复杂的程序和系统时,数据存储在 SQL 或 NoSQL 存储中。

为此目的编写的特殊智能合约可以用作存储。 因此,无论当前的 tokencode 版本如何,数据将始终保存在该合约的存储中。 该合约的代码可以移至库中,但目前不在议事日程上。 无需将数据从一个商店迁移到另一个; 相反,商店访问权限从一个版本转移到另一个版本。 然而,使用这种类型的存储并非没有问题。 它将需要定义一个可以在任何版本的代币智能合约中使用的接口,例如 sql 或 WORD 文档。 说到此类存储的示例,请查看 EOS 表。

让我们将结构、字段名称和数据类型统一到数据模式中。 存储智能合约代码可以由静态部分(无论当前数据模式如何都不会改变的代码)和动态部分(依赖于模式的代码)组成。 动态部分包含大量样板代码,因此自动生成它很有意义,因为它是在 Protocol Buffers 或 Apache Thrift 中实现的。 我碰巧在 ETHBerlin 黑客马拉松上处理了类似的任务,开发了以太坊柱状数据存储的原型。

如何查看以太坊的智能合约_以太坊智能合约教程_以太坊智能合约编写

数据项描述结构如下:

结构咖啡馆{

字符串名称;

uint32纬度;

uint32 经度;

地址所有者;

}

如何查看以太坊的智能合约_以太坊智能合约教程_以太坊智能合约编写

我们为 GitHub 生成一个“驱动程序”。 驱动从Github调用静态代码,例如`CDF.writeString`、`CDF.chunkDataPosition`等函数。

正如我已经提到的,这个解决方案涵盖了其他问题,并作为外部存储操作的示例。 目前,据我所知,以太坊智能合约存储中没有 SQL/NoSQL 存储的有效实现。 对于可变智能合约中的数据存储问题,这似乎是一个有趣的解决方案。

什么是可升级的以太坊智能合约

状态存储在充当数据库的合约中,并通过调用而不是委托调用指令调用。 对写调用的访问应该受到保护,并且只用于代理协议。 此数据库合约的公共代码可以移至库中。

在代理合约中委托调用和存储数据

最后,第三种选择是将数据存储在代理合约存储中。 如果代理是一个独立的智能合约,特定的代码版本如何访问数据? EVM delegatecall 功能使这成为可能。 它在目标地址执行代码,但使用执行委托调用指令的合约的存储。

什么是可升级的以太坊智能合约

从以前的合约版本调用函数没有什么意义,因为它们只不过是所有状态都存储在代理合约中的“代码片段”。 Delegatecall 用于调用库合约。 库代码很容易通过指针定位到需要的数据。 但是,该指令可能对代理合同构成潜在威胁。 不幸的是,官方 Solidity 文档几乎没有警告我们:“如果通过低级委托访问状态变量,则两个合约的存储布局必须对齐,以便被调用合约可以通过名称正确访问调用合约的存储变量。。”

综上所述

我们研究了可扩展的智能合约开发并研究了 3 种数据存储方法。 下次我们将深入探讨委派任务和可能出现的问题。