跳到主要内容

复杂数据结构编码

在上一小节,我们实现了可以验证签名信息的智能合约,并且为了方便学习测试,发布到了测试网上

这一小节,我们来研究如何使用TypeScript SDK来构建签名。

准备工作

  1. 使用mint.ts示例代码mint一个Profile SBT Object.
  2. 使用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代码。