NEAR智能合约实例变量:全局共享还是客户端独有?
NEAR智能合约实例与普通Rust实例的差异解答
问题背景
用户提供的NEAR智能合约代码如下:
#[near_bindgen] pub struct A { pub var1: AccountId, pub var2: Balance, pub my_map: TreeMap<String, (u128, u128, u128)>, } #[near_bindgen] impl A { #[init] pub fn init() -> Self { let _my_map: TreeMap<String, (u128, u128, u128)> = TreeMap::new(b"t"); Self { //...other fields my_map: _my_map } } //!!! // will this work properly for each client at all? // pub fn my_method1(&mut self) { // !! instance variable !! if !self.my_map.contains_key("some_key") { self.my_map.insert(&"aaa", &(1, 2, 3)); } else { // already exists, error! } } }
针对你的疑问,逐一解答如下:
1. 普通Rust环境中每个用户拥有独立A实例的理解是否正确?
正确。在普通Rust程序中,struct A的实例由代码主动创建,每个用户(或代码中的每个创建逻辑)都会生成独立的内存实例,各自的var1、var2、my_map数据完全隔离,互不影响。
2. NEAR网络中所有客户端是否共用同一个A实例?
是的。NEAR智能合约的运行模型和普通Rust程序完全不同:
- 合约部署到NEAR网络后,整个合约对应唯一的链上存储实例——所有调用该合约的客户端(无论哪个账户发起调用),操作的都是同一个
A结构体实例。 - 这个实例的所有字段数据都存储在NEAR链上的合约账户存储区,是全局共享的。
3. A.my_map对所有客户端数据完全相同?
完全正确。my_map作为合约结构体的字段,存储在链上的合约账户中,所有客户端调用合约方法时,读取或修改的都是同一个TreeMap实例。比如某客户端调用my_method1插入数据后,其他客户端读取my_map时都会看到该新增数据。
4. A.var1和A.var2的情况?
和my_map完全一致:它们是合约全局实例的字段,所有客户端看到的都是同一组值。若某个调用修改了var1,之后所有调用都会读取到修改后的结果。
5. my_method1能否为每个客户端正常工作?
不能。my_method1的逻辑是检查my_map中是否存在"some_key",不存在则插入"aaa"。但因为所有客户端共用同一个my_map:
- 第一个调用该方法的客户端会成功插入
"aaa"; - 后续所有客户端调用
my_method1时,都会触发else分支的错误逻辑——因为"some_key"已存在(由第一个调用留下的全局状态)。 - 该方法逻辑针对全局状态,而非单个客户端。若要实现每个客户端独立的逻辑,需要把调用者的
AccountId作为my_map键的一部分,以此区分不同客户端的数据。
内容的提问来源于stack exchange,提问作者Koklushkin
相关产品推荐
相关产品推荐

