是否可以仅从应用程序提供对智能合约的访问并阻止直接访问?

Posted

技术标签:

【中文标题】是否可以仅从应用程序提供对智能合约的访问并阻止直接访问?【英文标题】:Is it possible to provide access to the smart contract only from the application and block direct access? 【发布时间】:2020-05-18 11:43:40 【问题描述】:

例如,我有一个游戏,我希望玩家只能通过应用程序进行交互。但是只要复制ABI和联系地址就可以调用函数了。

是否有任何情况允许仅通过应用程序调用公共合约函数,使用某种秘密令牌?但是我不知道如何在公共区块链中制作这样一个秘密令牌。

【问题讨论】:

【参考方案1】:

(1) 处理此问题的一种方法是自己签署交易,而不是让用户这样做。您可以为函数添加修饰符,例如onlyAdmin,并将您的应用的帐户地址指定为管理员。然后,如果被其他人调用,这些函数将恢复。

这样做的问题是您必须支付 gas 费用并在游戏中设置机制来确保用户无法利用您的签名密钥。


function doSomething(bytes32 userId) public onlyAdmin 
  // ...

(2) 您可以做的另一件事是设置一个在函数中散列的值,然后验证该散列。在游戏中你可以给用户一个可以通过验证的值,缺点是你必须确保每次使用后更新哈希值。

为此,您可以发出一个事件并监听它,然后发送一个 tx 以更新 appHash,但这会消耗您的燃料,并且可能会使您面临定时攻击,具体取决于您实现的其余部分。

您也可以将功能设置为锁定状态,然后通过重置 appHash 来解锁,但这同样需要您的工作和加油。

bytes32 public appHash = '1s2a3d4g';

function doSomething(appSecret bytes32) public 
  require(keccak256(appSecret) == appHash);
  // ...
  emit didSomething(msg.sender, appSecret);

带锁

bytes32 public appHash = '1s2a3d4g';
bool public locked = false;

function doSomething(bytes32 appSecret) public 
  require(keccak256(appSecret) == appHash);
  require(locked == false);
  // ...
  locked = true;


function unlock(bytes32 nextAppHash) public onlyAdmin 
  appHash = nextAppHash;
  locked = false;

【讨论】:

【参考方案2】:

如果合约中包含秘密代币相关逻辑,那么任何运行节点的人都可以看到,所以看起来很难。

普通的web服务器可以使用cookie和域名检查等来保护api,但是智能合约不能访问合约外的数据,而且合约内的数据是可见的,所以密码保护比较困难。

似乎唯一可能的解决方案是使用加密数字签名,并使用代理服务器。 代理服务器控制来自应用程序的请求,并为智能合约创建签名请求,该请求只允许来自代理服务器的请求。

【讨论】:

以上是关于是否可以仅从应用程序提供对智能合约的访问并阻止直接访问?的主要内容,如果未能解决你的问题,请参考以下文章

智能合约实战 solidity 语法学习 08 [ 访问函数getter 合约创建 合约对象 合约继承IS ]

基于 sCrypt 智能合约的预言机作弊惩罚

从 sCrypt 智能合约中访问区块链数据

第一行代码:以太坊-使用Solidity语言开发和测试智能合约

以太坊智能合约分析工具/服务

智能合约重构社会契约 预言机基础说明