verify_profile示例程序在第一单元的profile_clock示例程序的基础上,增加了需要验证签名信息的add_points
函数。
在智能合约模块的开头,引入依赖模块。
use sui::{
clock::Clock,
bcs,
hash,
ed25519
};
const PK: vector<u8> = vector[185, 198, 238, 22, 48,
239, 62, 113, 17, 68, 166, 72, 219, 6, 187, 178,
40, 79, 114, 116, 207, 190, 229, 63, 252, 238, 80,
60, 193, 164, 146, 0];
定义常量PK
来记录公钥二进制数据。
public struct ProfileData has drop {
id: ID,
add_points: u64,
last_time: u64,
}
ProfileData
数据结构中包含了验证的必须信息,除了需要增加的分数add_points
, 还有每个Profile
的Object ID和上次更新的时间last_time
. 增加这些信息是为了让签名变得唯一,不可以被重复使用。
ProfileData
数据结构的ability是drop
, 是为了作用域结束之后可以被自动销毁。
public fun add_points(
profile: &mut Profile,
add_points: u64,
sig: vector<u8>,
clock: &Clock
) {
let profile_data = ProfileData {
id: object::id(profile),
add_points,
last_time: profile.last_time,
};
let byte_data = bcs::to_bytes(&profile_data);
let hash_data = hash::keccak256(&byte_data);
let pk = PK;
let verify = ed25519::ed25519_verify(&sig, &pk, &hash_data);
assert!(verify == true);
profile.points = profile.points + add_points;
profile.last_time = clock.timestamp_ms();
}
在函数中,先构建需要验证的数据ProfileData
.
let profile_data = ProfileData {
id: object::id(profile),
add_points,
last_time: profile.last_time,
};
将ProfileData
数据转为二进制,然后计算哈希值。
let byte_data = bcs::to_bytes(&profile_data);
let hash_data = hash::keccak256(&byte_data);
其实二进制的数据已经可以用于签名验证,但是取哈希值计算之后,会变为定长的数据,提升后续加密算法的计算效率。如果ProfileData
中还包含可变长度的字符串数据,取哈希值计算是很有帮助的,这里仅作为演示使用。
复制公钥数据pk
, 然后验证传入的签名数据sig
和之前计算得到的哈希值hash_data
.
let pk = PK;
let verify = ed25519::ed25519_verify(&sig, &pk, &hash_data);
assert!(verify == true);
最后,再添加积分,然后更新Profile
的last_time
属性。
profile.points = profile.points + add_points;
profile.last_time = clock.timestamp_ms();
在本小节示例代码的基础上进行修改,添加一个edit_handle
函数,在验证签名信息后,可以编辑Profile
的handle
属性。