1.前言
其几章笔者分析了hotstuff的核心逻辑,但是在实际协议运行中,需要从客户端接受信息,这一章笔者将围绕client源码进行分析。
2.源码分析
MsgReqCmd请求命令消息
MsgReqCmd结构体表示一个请求命令消息,由客户端发送给节点(副本)。结构体包含一个静态常量opcode,表示操作码。包含一个DataStream对象serialized用于序列化命令。包含一个命令对象cmd。构造函数将命令序列化到DataStream中。另一个构造函数接受一个DataStream对象。
struct MsgReqCmd {
static const opcode_t opcode = 0x4;
DataStream serialized;
command_t cmd;//entity.h
MsgReqCmd(const Command &cmd) { serialized << cmd; }
MsgReqCmd(DataStream &&s): serialized(std::move(s)) {}
};
MsgRespCmd响应命令消息
MsgRespCmd结构体表示一个响应命令消息,通常由节点发送给客户端。结构体包含一个静态常量opcode,表示操作码。包含一个DataStream对象serialized用于序列化响应。如果定义了HOTSTUFF_CMD_RESPSIZE,则包含一个payload数组。包含一个Finality对象fin。构造函数将Finality对象序列化到DataStream中,如果定义了payload,也进行序列化。另一个构造函数接受一个DataStream对象,并从中反序列化出Finality对象
struct MsgRespCmd {
static const opcode_t opcode = 0x5;
DataStream serialized;
#if HOTSTUFF_CMD_RESPSIZE > 0
uint8_t payload[HOTSTUFF_CMD_RESPSIZE];
#endif
Finality fin;
MsgRespCmd(const Finality &fin) {
serialized << fin;
#if HOTSTUFF_CMD_RESPSIZE > 0
serialized.put_data(payload, payload + sizeof(payload));
#endif
}
MsgRespCmd(DataStream &&s) {
s >> fin;
}
};
CommandDummy示例命令
// CommandDummy 类继承自 Command 类,表示一个示例命令。
// 包含命令ID、命令编号和命令哈希值。
// 如果定义了 HOTSTUFF_CMD_REQSIZE,则包含一个 payload 数组。
// 默认构造函数、析构函数、带参数的构造函数、序列化、反序列化和哈希计算功能。
class CommandDummy: public Command {
uint32_t cid; // 命令ID,表示命令的唯一标识符
uint32_t n; // 命令编号,表示命令的顺序
uint256_t hash; // 命令的256位哈希值,用于标识命令的唯一性
#if HOTSTUFF_CMD_REQSIZE > 0
uint8_t payload[HOTSTUFF_CMD_REQSIZE]; // 可选的载荷数组,大小由 HOTSTUFF_CMD_REQSIZE 决定
#endif
public:
// 默认构造函数
CommandDummy() {}
// 析构函数
~CommandDummy() override {}
// 带参数的构造函数,初始化命令ID和编号,并计算命令的哈希值
CommandDummy(uint32_t cid, uint32_t n):
cid(cid), n(n), hash(salticidae::get_hash(*this)) {}
// 将命令序列化到 DataStream 中
void serialize(DataStream &s) const override {
s << cid << n; // 序列化命令ID和编号
#if HOTSTUFF_CMD_REQSIZE > 0
s.put_data(payload, payload + sizeof(payload)); // 如果定义了 payload,序列化 payload 数据
#endif
}
// 从 DataStream 中反序列化命令
void unserialize(DataStream &s) override {
s >> cid >> n; // 反序列化命令ID和编号
#if HOTSTUFF_CMD_REQSIZE > 0
auto base = s.get_data_inplace(HOTSTUFF_CMD_REQSIZE); // 获取 payload 数据
memmove(payload, base, sizeof(payload)); // 将数据拷贝到 payload 数组
#endif
hash = salticidae::get_hash(*this); // 重新计算命令的哈希值
}
// 返回命令的哈希值
const uint256_t &get_hash() const override {
return hash;
}
// 验证命令,始终返回 true,表示命令验证通过
bool verify() const override {
return true;
}
};