geth-智能合约调用

| 笔记 | 5146 | 13分钟 | ERC以太坊区块链BlockchainSolidity智能合约论文

研究一下geth如何调用智能合约,如何拦截请求。

TEST_COIN: 0x258761046E2Bbf701cb1EEfdDA738EeF5F7e8bcB

StringTracker: 0x319b4b3b71398EABaDae47ccEA2e1e6be3e83056

RegulatoryContract:0x15bC1CE1Ef41D6B00D47693014BB3A8Bf83f4fc0

REG_COIN: 0xedbF11C56a3fAE725c6db115b903734dd0336E01

口头表述

现在我们监听以太坊上所有函数签名在敏感列表里的函数。但是这样仍有问题:

  1. 合约可以通过调用别的函数来触发交易,绕过敏感列表。
  2. 交易函数的参数各式各样,无法统一管理。(没有一个统一的办法返回交易函数的发送方、接收方、转账金额等)

所以决定按如下方法操作:

  1. 监管机构在区块链上发一个“监管合约”。监管合约的数据结构:
    • white_list: map[address => bool],对应地址为true表示该合约通过了监管部门审查,允许放行。不为true则禁止任何人调用对应的合约。
    • 敏感函数列表:一个合约地址对应一个数组,数组里存放该合约所有需要监管的敏感函数、和解析该函数的方式(如何根据参数推断出发送方、接收方、转账金额)。
      • 例如:合约0x1234…是一个兼容ERC20的合约,其函数transfer(to address, amount uint256)是一个敏感函数,“解析方式”可以设计一种编码,表示{from: msg.sender, to: to, amount: amount}.
    • riskScores: map[address => uint256],某个账户的风险指标。
    • owner:监管合约所有者(监管机构)
  2. 以后,任何人在以太坊上部署新的合约时,都必须主动到监管合约里“注册”。
    • 智能合约部署的时候,必须在构造函数里将自己的敏感函数列表和对应的解析方式发送给“监管合约”,存在监管合约的链上存储中。
    • 之后等待监管机构审核,审核通过后,由监管合约所有者修改white_list,将该合约设置为 true
  3. 修改geth的源码,拦截所有外部调用。首先执行如下检查:
    1. 查看调用的合约是否在监管合约的白名单里。如否,则禁止后续操作。
    2. 查看调用的函数是否为敏感函数。如否,直接执行。
    3. 如果是敏感函数,获取该函数的解析方式,解析本次调用的发送方、接收方、转账金额。如果发送方的风险指标不为零,则根据某个函数 _calculateRiskScore ,自动计算出一个新的风险指标给接收方记录上。(_calculateRiskScore的实现就写成接收方的score = max(0, 发送放的score - 1))
  4. 可以调用监管合约的 queryRisk() 函数查询某个账户的风险指标。(only Owner)

一句话概括

合约如果想在我们的私有链上有效,必须主动提交敏感函数注册表。监管机构审核通过后,合约才可以被调用。

敏感函数注册表的作用是:声明该合约中哪些函数涉及交易,以及如何根据参数解析出交易的发送者、接受者、金额。

所有合约都必须先到监管合约上进行注册。只有注册并通过审核的合约,才能在以太坊上执行。

注册时,合约将填写敏感函数表。以太坊evm在执行表中的敏感函数时,会自动解析交易的发送者、接受者、发送金额,用于后续风险传播计算。

重新整理的设计方案

监管架构概述

建立基于智能合约的去中心化监管体系,通过链上监管合约实现对所有合约交互的统一管控和风险评估。

  1. 监管合约数据结构
contract RegulatoryContract {
  // 白名单:合约审核状态
  mapping(address => bool) public whiteList;

  // 敏感函数注册表:合约地址 => 敏感函数配置数组
  mapping(address => SensitiveFunction[]) public sensitiveFunctions;

  // 风险评分:账户地址 => 风险指标
  mapping(address => uint256) public riskScores;

  // 监管机构地址
  address public owner;

  struct SensitiveFunction {
      bytes4 selector;           // 函数选择器
      string parseRule;          // 解析规则编码
  }

}
  1. 合约注册流程
  • 新合约强制注册:新合约部署时必须在构造函数中调用监管合约的注册接口
  • 信息提交:提交所有敏感函数的选择器和对应的参数解析规则
  • 等待审核:监管机构验证合约代码和提交信息的一致性
  • 白名单激活:审核通过后,监管机构将合约地址添加到白名单
  1. EVM层面拦截机制

在geth的EVM调用层面实现三级检查:

第一级:白名单验证

  • 检查目标合约是否在监管合约白名单中
  • 未通过审核的合约禁止被调用

第二级:敏感函数识别

  • 查询目标合约的敏感函数注册表
  • 普通函数直接放行,敏感函数进入风险评估

第三级:风险评估与传播

  • 根据注册的解析规则提取交易参数(发送方、接收方、金额)
  • 应用风险传播算法:接收方风险 = max(0, 发送方风险 - 1)
  • 更新监管合约中的风险评分
  1. 风险传播算法

  2. 监管查询接口

完善后的监管架构设计

1. 监管合约数据结构

contract RegulatoryContract {
    // 白名单:合约审核状态
    mapping(address => bool) public whiteList;

    // 敏感函数注册表:合约地址 => 敏感函数配置数组
    mapping(address => SensitiveFunction[]) public sensitiveFunctions;

    // 风险评分:账户地址 => 风险指标
    mapping(address => uint256) public riskScores;

    // 监管机构地址
    address public owner;

    struct SensitiveFunction {
        bytes4 selector;           // 函数选择器
        string parseRule;          // 解析规则编码
    }
}

2. 双重注册机制

A. 新合约自主注册

function registerSensitiveFunctions(
    SensitiveFunction[] calldata functions
) external {
    // 合约只能注册自己的敏感函数
    delete sensitiveFunctions[msg.sender];
    for (uint i = 0; i < functions.length; i++) {
        sensitiveFunctions[msg.sender].push(functions[i]);
    }
    emit SensitiveFunctionsRegistered(msg.sender, functions);
}

B. 监管机构手动注册(兼容历史合约)

function setSensitiveFunctions(
    address contractAddr,
    SensitiveFunction[] calldata functions
) external onlyOwner {
    // 监管机构可以为任何地址设置敏感函数
    delete sensitiveFunctions[contractAddr];
    for (uint i = 0; i < functions.length; i++) {
        sensitiveFunctions[contractAddr].push(functions[i]);
    }
    emit SensitiveFunctionsSet(contractAddr, functions);
}

3. 完整的注册流程

新合约注册流程

  1. 部署时注册:新合约在构造函数中调用 registerSensitiveFunctions()
  2. 等待审核:监管机构验证注册信息与合约代码的一致性
  3. 白名单激活:审核通过后调用 setWhiteList(contractAddr, true)

历史合约兼容流程

  1. 监管机构分析:监管机构分析已部署合约的源码和ABI
  2. 手动注册:监管机构调用 setSensitiveFunctions() 为历史合约注册敏感函数
  3. 直接审核:由于是监管机构直接操作,可以同时设置白名单状态

4. 权限控制矩阵

操作合约自身监管机构(Owner)其他地址
注册自己的敏感函数
注册其他地址的敏感函数
设置白名单
查询风险评分

5. 更新后的监管合约接口

  • 合约自主注册接口

    function registerSensitiveFunctions(SensitiveFunction[] calldata functions) external;
  • 监管机构管理接口

    function setSensitiveFunctions(address contractAddr, SensitiveFunction[] calldata functions) external onlyOwner;
    function setWhiteList(address contractAddr, bool status) external onlyOwner;
    function setRiskScore(address account, uint256 score) external onlyOwner;
  • 查询接口

    function isWhitelisted(address contractAddr) external view returns (bool);
    function getSensitiveFunctions(address contractAddr) external view returns (SensitiveFunction[] memory);
    function queryRisk(address account) external view onlyOwner returns (uint256);

6. 实施策略

渐进式部署

  1. Phase 1:部署监管合约,开始手动注册重要的历史合约(如主流DeFi协议)
  2. Phase 2:要求新部署的合约必须自主注册
  3. Phase 3:逐步扩大监管范围,覆盖更多历史合约

批量操作支持

function batchSetSensitiveFunctions(
    address[] calldata contracts,
    SensitiveFunction[][] calldata functions
) external onlyOwner {
    require(contracts.length == functions.length, "Length mismatch");
    for (uint i = 0; i < contracts.length; i++) {
        setSensitiveFunctions(contracts[i], functions[i]);
    }
}

7. 优势总结

  • 向后兼容:历史合约可通过监管机构手动注册接入系统
  • 自主性保持:新合约仍可自主注册,保持去中心化特性
  • 渐进部署:可以分阶段实施,降低系统性风险
  • 权限清晰:明确的权限控制,防止恶意操作
  • 批量操作:支持批量处理,提高管理效率

老师我改了一下,加了一个合约层面的限制。

在我们私有链上的合约,必须主动提交敏感函数注册表。监管机构审核通过后,把合约加入白名单,合约才可以被调用。

敏感函数注册表的作用:声明该合约中哪些函数涉及交易,以及如何根据参数解析出交易的发送者、接受者、转账金额。

简单画了两个流程图。

现在代码已经跑通了,整体思路没问题的话就看之后怎么跑实验了。

现在要求私有链上的合约,必须主动提交敏感函数注册表,由监管机构审核通过后

合约如果想在我们的私有链上有效,必须主动提交敏感函数注册表。监管机构审核通过后,合约才可以被调用。

敏感函数注册表的作用是:声明该合约中哪些函数涉及交易,以及如何根据参数解析出交易的发送者、接受者、金额。