当前位置:首页 > 物联网 > 区块链
[导读] 本文主要说明以太坊的注册表合约、代理合约、继承的存储可升级性,以及更多的可升级性方法。 在软件工程中,当发现新的bug和安全风险时,通常会对它们进行修补,并实时推送更新的版本。在智能合约

本文主要说明以太坊的注册表合约、代理合约、继承的存储可升级性,以及更多的可升级性方法。

在软件工程中,当发现新的bug和安全风险时,通常会对它们进行修补,并实时推送更新的版本。在智能合约开发中,可升级性并不是那么简单。因此,我们必须采取不同的做法。

以太坊仍处于起步阶段,关于如何升级智能合约版本的争议很多,但我们将介绍一些当今最好的选择。

注意:智能合约版本的可升级性仍然是研究的活跃领域。以下任何一种方法都可能由于滥用或新发现的漏洞而导致智能合约失败。

智能合约可升级性的基本方法

在这里,我们将介绍一些更平易近人但不太适合的智能合约可升级性解决方案。尽管这些不是最佳方法,但它们是当今使用的核心。

注册合约

注册表合约可能是最简单的可升级性方法,但是在这种方法,简单性带来了一些严重的缺陷。

它使用两个智能合约的工作:注册表合约和逻辑合约。注册表协定仅用于将用户指向逻辑协定的当前版本。每当逻辑合约被升级时,注册表合约的所有者就可以更新逻辑合约被升级的地址。

contract SomeRegister {

address backendContract;

address[] previousBackends;

address owner;

function SomeRegister() {

owner = msg.sender;

}

modifier onlyOwner() {

require(msg.sender == owner)

_;

}

funcTIon changeBackend(address newBackend) public

onlyOwner()

returns (bool)

{

if(newBackend != backendContract) {

previousBackends.push(backendContract);

backendContract = newBackend;

return true;

}

return false;

}

}

这种方法是非常不利的,因为当用户想要使用合约时,他们必须首先查找当前地址。否则可能导致资金损失。将数据迁移到新合约中也非常困难,因此必须仔细考虑此过程以避免失败。

代理合约

代理合约用于将数据和调用转发到逻辑合约。使用代理合约,用户可以始终调用相同的合约地址,并且将其简单地转发到当前逻辑合约。

这种方法通过使用DELEGATECALL操作码来工作。DELEGATECALL是EVM提供的用于程序集的操作码。它的工作方式与普通调用类似,只是目标地址的代码是在调用协定的上下文中执行的。这意味着像“msg.sender”和“msg.value”这样的值将被保留。实际上,DELEGATECALL允许目标协定代表被调用方进行调用。

contract Relay {

address public currentVersion;

address public owner;

modifier onlyOwner() {

require(msg.sender == owner);

_;

}

funcTIon Relay(address initAddr) {

currentVersion = initAddr;

owner = msg.sender; // this owner may be another contract with mulTIsig, not a single contract owner

}

funcTIon changeContract(address newVersion) public

onlyOwner()

{

currentVersion = newVersion;

}

function() {

require(currentVersion.delegatecall(msg.data));

}

}

尽管这种方法避免了与注册表合同有关的问题,但它也有其自身的问题。 例如如果管理不当,数据存储很容易失败。如果新合约的存储布局与以前的合约不同,则数据可能已损坏。此实现还防止您从函数接收返回值,从而限制了其用例。

储存合约

与以前的方法一样,此方法需要您的逻辑合约以及辅助合约。在这种情况下,辅助合约是永久存储合约。该技术通过分离逻辑和数据来起作用。逻辑合约可以随时升级,并且由于数据存储在外部,因此您的数据受到保护。

当然,这种方法也存在根本缺陷。如果在存储合约中发现错误或漏洞,则在不破坏当前数据存储的情况下无法对其进行升级。 这种方法的另一个问题是逻辑协定需要使用额外的气体来进行外部调用以查看或修改数据。

更合适的升级方法

现在让我们来看看一些更复杂、更合适的智能合约升级方法。

继承的存储可升级性

这种技术使用三种不同的合约:代理合约来委托调用并充当永久存储;逻辑合约将处理数据;还有存储合约。代理合约和逻辑合约都继承自存储合约,因此它们的存储引用是对齐的。

当逻辑合约更新时,我们只需要更改代理合约所指向的位置即可使用仅管理员功能。由于代理和逻辑协定具有相同的存储指针,因此无需进行外部调用即可查看和修改数据。

不幸的是,这种方法也有其自身的陷阱。由于代理合约和存储合约都是永恒的,因此,如果在任何一个合约中发现错误或漏洞,都无法修复。 因此务必仔细考虑您的代理和存储结构。

非结构化存储可升级性

非结构化存储可能是当前最大的可升级性方法,它使我们能够利用存储中状态变量的布局。此方法仅需要两个合约-代理合约和实施合约-实施合约包含数据和存储。

该技术的工作原理是将可升级性所需的数据保存在存储中的固定位置,以防止被新数据覆盖。我们可以使用SLOAD和SSTORE操作码进行汇编。由于存储插槽只是从0x0开始递增,因此我们使用很高的存储插槽来防止覆盖 我们可以通过对常量变量进行散列来生成存储槽。 由于恒定状态变量不会占用存储空间,因此我们不必担心它会被覆盖。

bytes32 private constant implementationPosition =

keccak256(“org.zeppelinos.proxy.implementation”);

由于代理不再从存储合约继承而来,因此我们现在也可以更新存储,从而防止存储错误/漏洞变成灾难性的。 但是在升级实施合约时,我们必须继承以前的合约。由于不需要更改实施合约,因此该方法甚至可以与现有合约一起使用。

尽管这可能是当前可升级性最好的方法,但也有不少批评。代理所有者拥有巨大的权力,并且需要一定程度的信任。对于更复杂的系统,这可能也不是合适的解决方案。

升级依赖于构造函数的合约

当使用依赖于构造函数的合约来设置一些初始状态时,与代理工作并不太简单。由于构造函数只运行一次,而代理不知道逻辑合约构造函数中设置的值,因此我们需要一种方法在代理中初始化其中的一些值。

创建逻辑合约后,EVM会丢弃构造函数,因此我们不能简单地重用代码。相反,我们必须采取独特的方法来解决此问题。

初始化函数

一种可能的替代方法是在常规函数中使用构造函数代码。我们只需确保这个函数(我们将调用初始化函数)只能运行一次。

contract Initializable {

/**

* @dev Indicates that the contract has been initialized.

*/

bool private initialized;

/**

* @dev Indicates that the contract is in the process of being initialized.

*/

bool private initializing;

/**

* @dev Modifier to use in the initializer function of a contract.

*/

modifier initializer() {

require(initializing || !initialized, “Contract instance has already been initialized”);

bool wasInitializing = initializing;

initializing = true;

initialized = true;

_;

initializing = wasInitializing;

}

}

在使用初始值设定项函数时,必须打起十二分精神。考虑逻辑合约继承的基本合约也很重要。这部分特别复杂,因为Solidity也支持多重继承。

结论

确保智能合约是可升级的,并仔细考虑可升级过程,这两点都很重要。虽然这并不是一个关于智能合约可升级性的选项的详尽列表,但这应该是关于这个主题的适当指南。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭