blockchain - 如何改进智能接触设计,以区分同一域对象的数据及其操作功能?

标签 blockchain ethereum solidity

我们在重新部署契约(Contract)时遇到问题。每次在新合约版本部署期间更改某些逻辑时,我们都会丢失所有合约相关数据(存储在数组、映射中)。然后我们需要执行数据加载过程,以便将环境恢复到所需状态,这是一个耗时的操作。我尝试将契约(Contract)拆分为两个契约(Contract)(AbcDataContract、AbcActionsContract),但面临访问映射的问题:错误:索引表达式必须是类型、映射或数组(是函数(bytes32)查看外部返回(uint256) )) 初始契约(Contract):

contract AbcContract {

EntityA[] public entities;
mapping (bytes32 => uint) public mapping1;
mapping (bytes32 => uint[]) public mapping2;
mapping (bytes32 => uint[]) public mapping3;

/* Events */
event Event1(uint id);
event Event2(uint id);

/* Structures */
struct EntityA {
    string field1;
    string field2;
    bool field3;
    uint field4;
    Status field5;
}

enum Status {PROPOSED, VOTED, CONFIRMED}

function function1(...) returns (...)
function function2(...) returns (...)
function function3(...) returns (...)
function function4(...) returns (...)
function function5(...) returns (...)

}

重构合约:

contract AbcDataContract {

EntityA[] public items;
mapping (bytes32 => uint) public mapping1;
mapping (bytes32 => uint[]) public mapping2;
mapping (bytes32 => uint[]) public mapping3;

/* Events */
event Event1(uint id);
event Event2(uint id);

/* Structures */
struct EntityA {
    string field1;
    string field2;
    bool field3;
    uint field4;
    Status proposalStatus;
}

enum Status {PROPOSED, VOTED, CONFIRMED}

}

contract AbcActionsContract {

AbcDataContract abcDataContract;

/* constructor */
function AbcActionsContract(address _AbcDataContract) {
    abcDataContract = AbcDataContract(_AbcDataContract);
}

/* accessing to the mapping like abcDataContract.mapping1[someId] will raise Solidity compile error  */
function function1(...) returns (...)
/* accessing to the mapping like abcDataContract.mapping2[someId] will raise Solidity compile error  */
function function2(...) returns (...)
/* accessing to the mapping like abcDataContract.mapping3[someId] will raise Solidity compile error  */
function function3(...) returns (...)
function function4(...) returns (...)
function function5(...) returns (...)

}

我们希望实现像数据库开发中那样的方法,存储过程/ View /其他非数据对象中的逻辑更改通常不会影响数据本身。这个问题的最佳设计解决方案是什么?

最佳答案

你问题的第一部分相当简单。要访问另一个合约中的公共(public)映射,只需使用 ():

abcDataContract.mapping1(someId)

当然,您也可以提供自己的对 AbcDataContract 的访问方法,而不是使用公共(public)映射。如果您走这条路,我建议您通过界面来访问您的数据合约

至于你问题的设计部分,看起来你走在正确的轨道上。将数据存储分离到自己的合约中具有巨大的好处。由于您不必担心迁移数据,因此不仅部署起来更加容易,而且部署新合约的成本也便宜得多。

话虽如此,我想在您发布的重构版本中指出一些事情。

  1. 很难判断您打算用 Struct1 做什么。您的伪代码中没有引用它。您无法从 Solidity 中的函数返回结构,除非它们是内部调用(或者您显式分解该结构)。
  2. 同样,您无法在合约之间返回字符串。如果您计划在 AbcActionsContract 中使用 Struct1.field1/2,则需要将它们转换为 bytes32
  3. 您可能希望将事件定义移至业务逻辑合约中。

将数据存储与业务逻辑分离是升级合约的关键组成部分。使用接口(interface)和库有助于解决这个问题。有几篇博客文章讨论了这个问题。我个人建议从 this one 开始以及后续here .

关于blockchain - 如何改进智能接触设计,以区分同一域对象的数据及其操作功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48065343/

相关文章:

blockchain - 动态添加参与者到corda状态?

rust - Substrate:如何与 session 模块集成

以太坊 Nonce 管理。错误随机数太低

bash - 与托管以太坊节点的操作系统交互

ethereum - 如何从外部资源将库连接到智能合约?

ethereum - 如何修复 'Truffle Migrate' 字节码未定义错误

node.js - 如何在本地查询区 block 链比特币

blockchain - Hyperledger 中的交易证书如何用于加强隐私保护?

ethereum - 在solidity中是否有类似null的东西

blockchain - ERC20代币合约: does approve function need to check caller balance?