nearprotocol - 处理来自 nearlib 的账户和交易签名
问题描述
我有一份合同叫做exchange
. 用户Bob
想要通过放置 的方式花钱near tokens
购买头寸。
有一个名为 的字段,在这种情况下,合约必须证明某个地址归某个地址所有,这一点很重要。markets
Order
Order
owner
order
Bob
当前处理发送到exchange
的事务的流程类似于:
const init = async () => {
this.near = await window.nearlib.connect(Object.assign({ deps: { keyStore: new window.nearlib.keyStores.BrowserLocalStorageKeyStore() } }, window.nearConfig));
this.walletAccount = new window.nearlib.WalletAccount(this.near);
this.accountId = this.walletAccount.getAccountId();
this.exchange = await this.near.loadContract(window.nearConfig.contractName, {
viewMethods: [],
changeMethods: ["place_new_order"],
sender: this.accountId,
});
}
await init();
// Bob logs into to near
this.walletAccount.requestSignIn(
window.nearConfig.contractName,
window.nearConfig.contractName,
);
// Login process
[...]
// Bob wants to place a new order
this.exchange.place_new_order(price, amount);
exchange
合约导入一个struct
被调用的Order
.
Order
看起来像:
use std::string::String;
use borsh::{BorshDeserialize, BorshSerialize};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, BorshDeserialize, BorshSerialize, Clone)]
pub struct Order {
pub owner: String,
pub amount: u64,
pub price: u64,
}
impl Order {
pub fn new(owner: String, amount: u64, price: u64) -> Self {
Order {
owner,
amount,
price
}
}
}
Exchange
在这种情况下,是实现 mod 的合约order
。Exchange
有place_new_order
一种方法,我希望能够确保这Bob
是发送交易的人:
use near_bindgen::{near_bindgen, env};
[...]
mod Order;
[...]
pub fn place_new_order(&mut self, amount: u64, price: u64) {
// Stuff happens here
let order = Order::new(env::current_account_id(), amount, price);
// Stuff happens here
}
现在的问题是,以防万一,使用这个 nearlib 代码env::current_account_id()
将始终返回exchange
为current_account_id
. 这是有道理的,因为所有登录所做的只是创建一个access_key
允许exchange
以 的名义做几件事,Bob
但它仍在Exchange
签署交易。
这里的问题是:我如何确保该交易所知道那Bob
是初始化交易的人?
一种可行的方法是有意义的:
Bob
用他的私钥签署每笔交易,我在这里的问题是:如何?
这将导致类似 Metamask 的 UX 问题,在每个 tx 上签名都是错误的 UX。
我建议如下:
Bob
使用一种deposit
方法来存入一定数量的near-tokens
onexchange
并且exchange
只要它可以证明它通过由 签名的“登录访问令牌”来证明它正在这样做Bob
,那么这里的问题再次是:这可能吗?如果是这样怎么办?
解决方案
简短的回答
您应该使用env::predecessor_account_id()
来获取在交换中调用方法的用户或合约的帐户 ID。
细节
在您的情况下,即使通过指向exchange
它的访问密钥点仍然由bob. The
signer_idand the
前辈during the execution are both going to be
_id bob`签名。
执行期间有 3 种不同类型的帐户:
env::current_account_id()
返回当前正在执行的合约的当前账户 ID。env::signer_account_id()
返回签署原始交易的用户的帐户 ID。大多数时候你不应该依赖签名者帐户 ID,因为当前调用可以从另一个合约完成。env::predecessor_account_id()
返回调用当前合约的直接前任的帐户 ID。您应该使用它来验证呼叫您的用户的身份。
推荐阅读
- html - 在全屏容器中居中 img 响应
- ruby-on-rails - 带有 Webpacker 的 Rails 6 中的 Blazy,如何以可用格式导入 Blazy?
- reactjs - 将 React Native 项目连接到 Firebase
- sql - SQLite 中 TOKEN_GENERATOR ORACLE SQL 语句的等价物
- networking - omnetpp 中的转发节点
- c# - 嵌套循环 C# Visual Studio
- ruby-on-rails - 避免 SQL 注入:范围内的原始 SQL
- c++ - 在arduino中将小阵列分解成更大的阵列以用于盲文应用
- spring-boot - ZonedDateTime 到 MySql——错误的偏移量?
- ios - SwiftUI 如何创建具有个性化结果的问卷?