复杂数据结构编码
在上一小节,我们实现了可以验证签名信息的智能合约,并且为了方便学习测试,发布到了测试网上。
这一小节,我们来研究如何使用TypeScript SDK来构建签名。
准备工作
- 使用mint.ts示例代码mint一个
Profile
SBT Object. - 使用get.ts示例代码查询到
Profile
SBT Object的handle, points, last_time
等属性信息。
构建签名
在sign.ts示例代码中,提供了对合约add_points
函数的构建签名函数signMessage
.
export const signMessage = async(id: string, add_points: number, last_time: number): Promise<Uint8Array> => {
const profile_data = bcs.struct('Profile', {
id: bcs.Address,
add_points: bcs.u64(),
last_time: bcs.u64(),
});
const profile_bytedata = profile_data.serialize({ id: id, add_points: add_points, last_time: last_time }).toBytes(); // Bytes
const hash = keccak256(profile_bytedata); // Hex
const hash_bytes = fromHex(hash); // Bytes
const signature_bytes = await keypair.sign(hash_bytes); // Bytes
return signature_bytes;
}
包含以下环节
BCS 序列化
BCS是把数据结构变为二进制编码的序列化格式标准。
先按照智能合约里的Profile
格式去定义序列化数据结构
const profile_data = bcs.struct('Profile', {
id: bcs.Address,
add_points: bcs.u64(),
last_time: bcs.u64(),
});
把函数输入的数据做序列化处理
const profile_bytedata = profile_data.serialize({ id: id, add_points: add_points, last_time: last_time }).toBytes();
哈希计算
把bcs序列化的结果profile_bytedata
放去使用keccak256
算法计算哈希值。得到的结果是十六进制,再转为二进制。
const hash = keccak256(profile_bytedata);
const hash_bytes = fromHex(hash);
产生签名
最后,对二进制数据做签名。
const signature_bytes = await keypair.sign(hash_bytes);
构建交易
add_points.ts展示了调用签名函数然后构建交易的示例代码。
const sign_bytedata = await signMessage(profile_id, add_points, profile_last_time);
const tx = new Transaction();
tx.moveCall({
package: PACKAGE,
module: "profile",
function: "add_points",
arguments: [
tx.object(profile_id),
tx.pure(bcs.u64().serialize(add_points).toBytes()),
tx.pure(bcs.vector(bcs.u8()).serialize(sign_bytedata).toBytes()),
tx.object("0x6"),
],
});
tx.setSender(address);
作业
为上一小节作业的edit_handle
函数实现构建签名和交易信息的TypeScript代码。