在其他地方(在非以太坊应用程序中)持久化数据并使用 dapps 与之交互并验证数据完整性的教程

Tutorial for persist data somewhere else (in a non-ethereum app) and use dapps to interact with it and verify data integrity

构建区块链应用程序时,为了在网站上显示状态(例如后备 postgres 数据库),将数据保存在非以太坊应用程序中的最佳做法是什么。

一些具体问题:

  1. 为什么批量访问 lists/arrays/etc 在 Solidity 中被描述为痛苦?
  2. 捕获区块链事件和更新链下数据库的最佳方式是什么。
  3. 验证链下数据库完整性的最佳方法是什么(频率等)
  4. 你能避免使用后备数据库并直接查询区块链吗?

在松露宠物店教程中,他们认为 returns 整个链条 getAdopters() public view returns (address[16]) http://truffleframework.com/tutorials/pet-shop

Why is Bulk access to lists/arrays/etc is described as being painful in Solidity?

这有几个原因:

  1. Solidity 中没有内置的遍历集合的机制。您可以使用数组的长度对数组执行标准的 for 循环,但不能使用映射执行此操作。
  2. 返回复杂的对象很混乱。如果你的列表包含一个结构,你不能简单地 return 结构本身给你的客户。您必须 return 分解该项目。将结构转换为分解数组很丑陋:

    struct MyStruct {
      uint256 id;
      bytes32 name;
    }
    
    MyStruct[] _structs;
    
    function getAllStructs() public constant returns (uint256[], bytes32[]) {
        uint256[] memory ids = new uint256[](_structs.length);
        bytes32[] memory names = new bytes32[](_structs.length);
    
        for (uint i = 0; i < _structs.length; i++) {
            ids[i] = _structs[i].id;
            names[i] = _structs[i].name;
        }
    
        return (ids, names);
    }
    
  3. 遍历数组仍然需要 gas。即使您没有为 gas 付费(在 constant 函数中执行此操作),当您的数组变得非常大时,您仍然可能遇到 gas 异常。 Truffle pet shop 示例解决了这个问题,因为它明确地将数组限制为 16 个元素。

What is the best way to capture blockchain events and update an off-chain database.

"Best" 方式取决于您的业务目标和对陈旧数据的容忍度。但是,可能最常见的方法是设置一个 watch on contract events。当您收到一个事件时,您可以使用您填充到该事件中的自定义数据来更新您的数据库。但是,您还必须确保处理孤立块(元数据中有一个名为 removed 的字段,它会告诉您事件是否因块被孤立而不再有效)。当您收到孤立事件时,将其从数据库中删除。在 12 个后续块验证进来后,您可以放心地假设该事件不会被孤立。

What is the best way to verify the integrity of your off-chain database (how frequently etc.)

同样,这取决于您的业务需求的容忍程度。如果您可以延迟使用来自数据库的信息,直到您确定块验证,那么您只需保留块或时间戳信息,让您的应用程序知道您的数据库中的数据反映了区块链上验证的内容。如果您担心负责监视事件的客户端进程失败,您需要让故障转移监视客户端,或允许重复持久化(随后进行重复数据删除),或在进来时跟踪已验证的块号(或 3 的某种组合).我相信您还可以为此设计许多其他选项。

Can you avoid using a backing database and query the blockchain directly?

是的,有可能,假设您可以使用 constant 函数避免上述气体限制问题,并且您不必在合同中对您的数据进行任何复杂的 post 处理你的申请。由于 constant 在本地 EVM 中运行 运行,您只需要确保您的专用节点已启动并且 运行 正在运行。为此,您很可能需要多个服务器 运行ning 作为完全同步的节点。