Будет ли protobuf генерировать побитовую идеальную копию, если он запускается на одном и том же входе на разных языках / архитектурах? - PullRequest
0 голосов
/ 07 января 2019

Если я использую один и тот же файл .proto на нескольких компьютерах (arm, x86, amd64 и т. Д.) С реализациями, написанными на разных языках (c ++, python, java и т. Д.), То одно и то же сообщение приведет к точному одна и та же последовательность байтов при сериализации через эти разные конфигурации?

Я хотел бы использовать эти байты для хеширования, чтобы гарантировать, что одно и то же сообщение при создании на другой платформе получит точно такой же хеш.

1 Ответ

0 голосов
/ 07 января 2019

"Часто, но не всегда"

Причины, по которым вы можете получить расхождение, включают:

  • это только «должен», а не «должен», чтобы поля были записаны в числовом последовательном порядке - цитирование, выделено :

    когда сообщение сериализуется, его известные поля должны записываться последовательно по номеру поля

    и не требует , что поля, таким образом, упорядочены (необходимо, чтобы десериализаторы могли обрабатывать поля не по порядку); это может применяться особенно при обсуждении неожиданных / расширенных полей; если две сериализации выбирают разные порядки полей, байты будут разными

  • protobuf может быть создан путем объединения двух частичных сообщений, что по необходимости приведет к появлению неупорядоченных полей, но при повторной сериализации объекта, десериализованного из объединенного сообщения, он может стать нормализованным (последовательным)
  • кодирование "varint" допускает некоторую небольшую тонкую неоднозначность ... число 1 обычно кодируется как 0x01, но оно может также кодироваться как 0x8100 или 0x818000 или 0x81808080808000 - спецификация не применяется на самом деле требует (AFAIK) использовать самую короткую версию; Я не знаю ни о какой реализации, которая фактически выводит этот вид субнормальной формы, хотя:)
  • некоторые опции предназначены для прямой и обратной совместимости; в частности, опция [packed=true] для примитивных значений repeated может быть безопасно переключена в любое время, и библиотеки должны справиться с этим; если вы первоначально сериализовали его одним способом, а теперь вы сериализовали его с другой опцией: результат может быть другим; побочным эффектом этого является то, что определенная библиотека может просто выбрать для использования альтернативного представления, особенно если она знает, что она будет меньше; если две библиотеки принимают разные решения - разные байты

В большинстве случаев да: это будет надежно и повторяемо. Но это не фактическая гарантия.

Байты должны быть совместимыми , хотя - они будут по-прежнему иметь такую ​​же семантику - только не те же байты. Неважно, какой язык, фреймворк, библиотека, среда выполнения или процессор вы используете. Если это так: это ошибка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...