在我的项目中,我们有一个API,许多客户可能会向此API发送交易。交易应该签署。客户端可以使用任何语言(C ++,C#,python,go,等等)编写,具有任何CPU架构和字节序。
现在的问题是将我们的Transaction模型序列化为字节,以便能够签名然后发送它。
我们的团队为此选择了protobuf v3.3.0(proto syntax = proto3)。
我们想要使用信封图案,它看起来像:
message SignedTransaction {
message Transaction {/* any data that should be signed */}
Transaction transaction = 1;
Signature signature = 2;
}
要签名,我们只是序列化内部对象事务:
Transaction tx = <...>;
std::string bytes = tx.SerializeAsString();
// and then sign bytes
现在protobuf的问题在于它似乎对于不同的语言不是确定性的。今天我们用简单的整数和字符串编写了简单的proto文件,填充了相同的数据,为不同的语言序列化并观察结果。
我们尝试过Javascript,C ++,Java,Swift,结果证明除C ++之外的所有内容都会生成相同的输出字符串:
JavaScript,Java,Swift制作:08B90A10BA0A1A106C6F6C206B656B20636865627572656B
C ++制作:8FFFFFFB9A10FFFFFFBAA1A106C6F6C206B656B20636865627572656B
C ++ parseFromString(str)
能够从其他语言反序列化字符串,但反之亦然。
问题是:
详细说明:
// test.proto:
syntax = "proto3";
package api;
message Msg {
uint32 a = 1;
int32 b = 2;
string c = 3;
bytes d = 4;
}
// test.cpp:
api::Msg msg;
msg.set_a(1337);
msg.set_b(1338);
msg.set_c("lol kek cheburek");
std::string str = msg.SerializeAsString();
// str = 8FFFFFFB9A10FFFFFFBAA1A106C6F6C206B656B20636865627572656B
答案 0 :(得分:1)
我认为protobuf与序列化一词混淆。 protobuf所做的是一种特殊的编码。
除此之外我怀疑不设置b
会导致问题。这意味着b的值未初始化。 java对象是用零自动初始化的,c ++对象没有自动初始化,这意味着内容可能只是随机值。可能发生在b
答案 1 :(得分:1)
原来我打印hexstring的代码中有bug。 details
简短回答: Protobuf是一种稳定的序列化方法,可用于描述的用例。
答案 2 :(得分:0)
Protobuf不稳定,因为可以用不同的方式序列化内存中的同一对象。主要是因为当一个对象具有多个字段时,可以按任何顺序对字段进行序列化。
在此处查看文档:{{3}}。