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

Is it possible to provide access to the smart contract only from the application and block direct access?

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

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

如果contract中包含secret token相关的逻辑,那么任何运行node的人都可以看到,所以这似乎很难。

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

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

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

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


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

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

要做到这一点,你可以发出一个事件并监听它,然后发送一个 tx 来更新 appHash,但这会花费你的 gas,并且可能会让你面临定时攻击,具体取决于你的其余部分实现就像。

您还可以将功能设置为锁定状态,然后通过重置 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;
}