Reproduzierbare Gitian Builds .. aber nicht der gleiche Hash wie bitcoincore.org

Mit Bitcoincore.org und Bitcoin.org können Sie einen Tarball für Bitcoin v0.20.1 herunterladen

Wenn sie es tun

bitcoind: 4ec74161b2a90293926ae8e20a2efbe952bd23b53aeebf051e6a6285ace18271
bitcoin-0.20.1-x86_64-linux-gnu.tar.gz: 376194f06596ecfa40331167c39bc70c355f960280bd2a645fdbf18f66527397

Sie sagen auch:

Das Reproduzieren einer Binärdatei für sich selbst bietet Ihnen das höchste derzeit verfügbare Maß an Sicherheit

Es scheint also, als ob die aktuelle Methode dazu das Manöver "Gitian Build" ist.

Wenn ich es mache

bitcoind: c5fb850ed9e6afa0af5653e743084912c9bd71fb233acfe2d72738fc319f2181
bitcoin-0.20.1-x86_64-linux-gnu.tar.gz: 277599356bd2df760832c6636797fe5ea5a5c28d929d53635b685f5ac1e4689b

Ging mit Ubuntu 20.04 und Debian 10 durch den Gitian-Prozess . Beide produziert das gleiche falsch? Tarball, 2 verschiedene Setups/ 2 Betriebssysteme, gleicher Tarball.

Meine beiden Assert-Dateien werden hier für Debian und Ubuntu hochgeladen. https://github.com/miketwenty1/images/tree/master/bad_asserts


Als Plebs kann ich 1 von 2 Dingen denken ..

Irgendetwas stimmt mit einigen meiner Pakete/Versionen/env/OS/setup nicht oder alle Prüfer lügen und Bitcoin wurde kompromittiert. Helfen Sie mir, die Möglichkeiten einzugrenzen.

Ich würde diese Übung gerne richtig durchgehen und die gleichen Binärdateien reproduzieren, bin mir aber nicht sicher, wie ich am besten vorgehen soll. Was sind die nächsten Schritte, um den Build für v0.20.1 zu verifizieren? Ich kann den auf bitcoincore beworbenen Tarball nicht reproduzieren. org und bitcoin. org. Ich kann jedoch einen reproduzierbaren Build erstellen, der mich viele Dinge in Frage stellen lässt.

Würde mich freuen, wenn jemand seinen Prozess von Grund auf neu durchgehen und sehen könnte, ob er die gleichen Tarballs produzieren kann, die diese Leute in diesem Repo sehen. https://github.com/bitcoin-core/gitian.sigs/blob/master/0.20.1-linux /*/ bitcoin-core-linux-0.20-build.assert's. Und teilen Sie mir ihren kompletten Prozess mit. Nachdem ich mich selbst reproduziert habe, würde ich gerne eine aktuelle Komplettlösung für die Methode erstellen und die Dokumente aktualisieren, die (Links unten) für fast alle Methoden veraltet und kaputt sind.

HINWEIS: Wenn dies tatsächlich der Defacto-Weg ist, um derzeit reproduzierbare Builds zu erstellen, wäre es schön, eine präzise und aktuelle Dokumentation zu haben. Ich verstehe, dass an Ginx gearbeitet wird, aber es wäre schön, in der Zwischenzeit ein aktuelles Dokument für Leute zu haben, die Builds überprüfen möchten. Ich wäre auch sehr zufrieden, wenn jemand auf etwas hinweist, das ich vermisse.

Referenzlinks:
https://gitian.org/
https://github.com/bitcoin-core/docs/blob/master/gitian-building.md
https://github.com/bitcoin-core/docs/tree/ master/gitian-building
https://github.com/devrandom/gitian-builder/blob/master/README.md
https://github.com/bitcoin/bitcoin/blob/master/contrib/gitian-build.py

Referenz-Github-Problem
https://github.com/devrandom/gitian-builder/issues/235

Antworten (2)

Ich habe 0.20.1 neu erstellt und erhalte die gleichen Ergebnisse wie Sie. Dies würde darauf hindeuten, dass eine Build-Abhängigkeit aktualisiert wurde, um etwas andere Ergebnisse als die Version zu liefern, die zum Zeitpunkt der Veröffentlichung verwendet wurde. Die Build-Abhängigkeitsversionen sind im Gegensatz zu den tatsächlichen Softwareabhängigkeiten fixiert. IIRC Dies ist üblich für Gitian-Builds und der Versuch, noch ältere Versionen neu zu erstellen, führt zu ähnlichen Diskrepanzen.

Es wird laufend daran gearbeitet, zu einem anderen reproduzierbaren Build-System namens guix überzugehen. Dieses Build-System fixiert die genauen Abhängigkeitsversionen zusammen mit der Option, die gesamte Toolchain von Grund auf neu zu erstellen. Dies sollte vollständig reproduzierbare Builds ermöglichen, die zu jedem Zeitpunkt repliziert werden können.


Hier ist eine ausführlichere Erklärung dieser speziellen Diskrepanz, kopiert aus meiner Antwort in dieser GitHub-Ausgabe .

Wenn Sie sich die Gitian-Build-Ergebnisse ansehen, sehen Sie eine Datei mit dem Namen bitcoin-0.20.1-x86_64-linux-gnu-debug.tar.gz. Wenn Sie diese Datei entpacken, gibt es *.dbgDateien, zB bitcoind.dbgund bitcoin-qt.dbg. Diese *.dbgDateien enthalten die Debug-Daten für ihre jeweiligen Binärdateien, dh sie bitcoind.dbgenthalten Debug-Daten für bitcoind.

Um sicherzustellen, dass Sie die richtige dbgDatei mit der richtigen Binärdatei verwenden, bettet gcc eine Prüfsumme der dbgDatei in die Binärdatei selbst ein. Das bedeutet, dass bitcoindenthält eine Prüfsumme von bitcoind.dbg. Dies soll verhindern, dass versucht wird, bitcoindmit einer anderen dbgDatei zu debuggen. Wenn Sie beispielsweise versuchten, gdb mitzuteilen, dass die bitcoin-qt.dbgDatei die Debugging-Symbole für enthält bitcoind, würde es feststellen, dass dies nicht der Fall ist, und nicht versuchen, Debugging-Symbole von zu laden bitcoin-qt.dbg.

Die Debugging-Symbole werden zunächst in die Binärdatei kompiliert bitcoind, aber später während des Gitian-Builds werden diese entfernt und in die bitcoind.dbgDatei eingefügt. Da sie jedoch anfänglich kompiliert werden bitcoind, wirken sich die Debugging-Symbole auf die Build-ID aus, die gcc in die Binärdatei einbettet. Die Build-ID ist ein Hash der kompilierten Binärdatei, einschließlich der Debugging-Daten.

Das Endergebnis ist also, dass die veröffentlichte Binärdatei zwei Verpflichtungen zu den Debug-Symbolen enthält, sie selbst jedoch nicht enthält.

Sie können hier mehr über diese separaten Debug-Dateien lesen: https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html

Der springende Punkt bei diesem Problem ist, dass sich die Debug-Symbole aus neueren Gitian-Builds von den Debug-Symbolen unterscheiden, die für die ursprüngliche Version generiert wurden. Das bedeutet, dass sowohl die Build-ID als auch die Prüfsumme des Debug-Symbols, die wir darin finden, bitcoindunterschiedlich sind. Dies führt dann dazu, dass die bitcoindHashes unterschiedlich sind (sowie alle anderen Binärdateien). Und das führt natürlich dazu, dass die Tarfile-Hashes unterschiedlich sind.


Hier ist der Unterschied der Binärdateien, die das Diffoskop generiert:

--- bitcoind
+++ /mnt/archive/bitcoin/bitcoin-binaries/0.20.1/bitcoin-0.20.1/bin/bitcoind
├── readelf --wide --notes {}
│ @@ -1,15 +1,15 @@
│  Displaying notes found in: .note.ABI-tag
│    Owner                Data size     Description
│    GNU                  0x00000010    NT_GNU_ABI_TAG (ABI version tag)        OS: Linux, ABI: 3.2.0
│  Displaying notes found in: .note.gnu.build-id
│    Owner                Data size     Description
│ -  GNU                  0x00000014    NT_GNU_BUILD_ID (unique build ID bitstring)     Build ID: 6b464617f7f91fd270ac86f43ef4a58eeeedff19
│ +  GNU                  0x00000014    NT_GNU_BUILD_ID (unique build ID bitstring)     Build ID: 3a439a31a5157ff7052ed310050df5643a02ea3f
│  Displaying notes found in: .note.stapsdt
│    Owner                Data size     Description
│    stapsdt              0x00000036    NT_STAPSDT (SystemTap probe descriptors)        Provider: libstdcxx
│      Name: throw
│      Location: 0x00000000006e550d, Base: 0x000000000086d140, Semaphore: 0x0000000000000000
│      Arguments: 8@%rdi 8@%rsi
├── readelf --wide --decompress --hex-dump=.gnu_debuglink {}
│ @@ -1,5 +1,5 @@
│  Hex dump of section '.gnu_debuglink':
│    0x00000000 62697463 6f696e64 2e646267 00000000 bitcoind.dbg....
│ -  0x00000010 b25ceebb                            .\..
│ +  0x00000010 114d519d                            .MQ.

Wie Sie sehen, gibt es hier nur zwei Unterschiede, einen in der Build-ID und einen im .gnu_debuglinkAbschnitt. Aus der Dokumentation, die ich zuvor verlinkt habe, können wir ersehen, dass in diesem .gnu_debuglinkAbschnitt die erste Zeile der Debug-Dateiname ist, gefolgt von genügend 0 Bytes, um bis zu einer 4-Byte-Grenze aufzufüllen. Die zweite Zeile ist die 4-Byte-CRC-Prüfsumme. Und es ist diese CRC-Prüfsumme, die sich unterscheidet.

Warum unterscheiden sich die Debug-Symbole hier? Auch hier kann uns das Diffoskop ein wenig helfen.

--- bitcoind.dbg
+++ /mnt/archive/bitcoin/bitcoin-binaries/0.20.1/bitcoin-0.20.1/bin/bitcoind.dbg
├── readelf --wide --notes {}
│ @@ -1,15 +1,15 @@
│  Displaying notes found in: .note.ABI-tag
│    Owner                Data size     Description
│    GNU                  0x00000010    NT_GNU_ABI_TAG (ABI version tag)        OS: Linux, ABI: 3.2.0
│  Displaying notes found in: .note.gnu.build-id
│    Owner                Data size     Description
│ -  GNU                  0x00000014    NT_GNU_BUILD_ID (unique build ID bitstring)     Build ID: 6b464617f7f91fd270ac86f43ef4a58eeeedff19
│ +  GNU                  0x00000014    NT_GNU_BUILD_ID (unique build ID bitstring)     Build ID: 3a439a31a5157ff7052ed310050df5643a02ea3f
│  Displaying notes found in: .note.stapsdt
│    Owner                Data size     Description
│    stapsdt              0x00000036    NT_STAPSDT (SystemTap probe descriptors)        Provider: libstdcxx
│      Name: throw
│      Location: 0x00000000006e550d, Base: 0x000000000086d140, Semaphore: 0x0000000000000000
│      Arguments: 8@%rdi 8@%rsi
├── readelf --wide --debug-dump=info {}
│┄ error from `readelf --wide --debug-dump=info {}`:
│┄ readelf: Error: /build/binutils/src/binutils-gdb/binutils/dwarf.c:1989: read LEB value is too large to store in destination variable
│┄ readelf: Error: /build/binutils/src/binutils-gdb/binutils/dwarf.c:1989: read LEB value is too large to store in destination variable
│┄ readelf: Error: /build/binutils/src/binutils-gdb/binutils/dwarf.c:1989: read LEB value is too large to store in destination variable
│┄ readelf: Error: /build/binutils/src/binutils-gdb/binutils/dwarf.c:1989: read LEB value is too large to store in destination variable
│┄ readelf: Error: /build/binutils/src/binutils-gdb/binutils/dwarf.c:1989: read LEB value is too large to store in destination variable
│ @@ -85052,36 +85052,36 @@
│      <29607>   DW_AT_decl_line   : 124
│      <29608>   DW_AT_decl_column : 16
│      <29609>   DW_AT_type        : <0x28761>
│      <2960d>   DW_AT_data_member_location: 12
│   <2><2960e>: Abbrev Number: 30 (DW_TAG_member)
│      <2960f>   DW_AT_name        : (indirect string, offset: 0x13aaf): __kind
│      <29613>   DW_AT_decl_file   : 108
│ -    <29614>   DW_AT_decl_line   : 148
│ +    <29614>   DW_AT_decl_line   : 128
│      <29615>   DW_AT_decl_column : 7
│      <29616>   DW_AT_type        : <0x287a6>
│      <2961a>   DW_AT_data_member_location: 16
│   <2><2961b>: Abbrev Number: 30 (DW_TAG_member)
│      <2961c>   DW_AT_name        : (indirect string, offset: 0x7a535): __spins
│      <29620>   DW_AT_decl_file   : 108
│ -    <29621>   DW_AT_decl_line   : 154
│ +    <29621>   DW_AT_decl_line   : 134
│      <29622>   DW_AT_decl_column : 3
│      <29623>   DW_AT_type        : <0x2879a>
│      <29627>   DW_AT_data_member_location: 20
...

Es gibt viel mehr Ausgabe, die ich nicht aufgenommen habe, weil es so ziemlich alles gleich ist.

Das ist jetzt nicht sehr hilfreich, aber wir können sehen, dass sich die Zeilennummer für eine Reihe von Funktionen um 20 Zeilen unterscheidet.

Um weitere Informationen zu erhalten, habe ich dwarfdump verwendet. Dies ist, was es für den neuen Build für die beiden Funktionen sagt, die ich in diffoscope zeige (die Funktionen sind __kind und __spins).

0x0002960e:     DW_TAG_member
                  DW_AT_name    ("__kind")
                  DW_AT_decl_file       ("/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h")
                  DW_AT_decl_line       (148)
                  DW_AT_decl_column     (0x07)
                  DW_AT_type    (0x000287a6 "int")
                  DW_AT_data_member_location    (0x10)

0x0002961b:     DW_TAG_member
                  DW_AT_name    ("__spins")
                  DW_AT_decl_file       ("/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h")
                  DW_AT_decl_line       (154)
                  DW_AT_decl_column     (0x03)
                  DW_AT_type    (0x0002879a "short int")
                  DW_AT_data_member_location    (0x14)

Wie Sie anhand des angegebenen Dateinamens sehen können, stammen diese Funktionen aus Bibliotheken, die auf dem System installiert sind. Dies scheinen Header für die gcc-Implementierung der c++ stdlib zu sein.


Was also passiert ist, ist, dass libstdc++ in Ubuntu aktualisiert wurde. Welche Aktualisierungen auch immer passiert sind, es wurde Code in einigen Header-Dateien verschoben, die Bitcoin Core in die Verwendung der c++ stdlib einbezieht. Das Kompilieren mit diesen aktualisierten Headern führt wiederum zu anderen Debug-Symbolen, da Funktionsdeklarationen in diese Header-Dateien verschoben wurden. Dies führt dann dazu, dass gcc eine andere Build-ID und eine andere CRC-Prüfsumme für die Debug-Symbole berechnet. Dies führt schließlich dazu, dass die endgültigen Binärdateien leicht unterschiedlich sind, was dazu führt, dass die Hashes nicht übereinstimmen.

Ich bin neugierig auf die Wahl von guix gegenüber Nix - haben Sie einen Link zu einer Diskussion im IRC, Github usw. darüber, warum guix gewählt wurde?
@RaghavSood Von github.com/bitcoin/bitcoin/pull/15277 : „Guix ist ein transaktionaler Paketmanager, ähnlich wie Nix, aber im Gegensatz zu Nix konzentriert es sich mehr auf Bootstrap-Fähigkeit und Reproduzierbarkeit, die für sicherheitssensible Projekte wie Bitcoin attraktiv sind ." Ich glaube nicht, dass es viele Diskussionen über guix vs. nix gegeben hat, nur dass guix das ist, wofür sich jemand die Mühe gemacht hat, also haben wir es bekommen.
Danke für die ausführlichen Infos. Wenn es interessant ist, habe ich hier eine cmp-Ausgabe, die beide Bitcoin-Dateien vergleicht. github.com/devrandom/gitian-builder/issues/235 Luke-jr ließ mich wissen, dass die fraglichen Dateien wie folgt aussahen: .note.gnu.build-id .gnu_debuglink @AndrewChow Sie denken, dass dies ein Designfehler ist oder funktioniert wie beabsichtigt?
Es ist ein Designfehler des Gitian-Systems, aber das Gitian-System funktioniert auch wie beabsichtigt.

Solange das zugrunde liegende Betriebssystem-Image anfällig für Änderungen ist, erhalten Sie kein reproduzierbares Build-System, das die Reproduzierbarkeit über einen langen Zeitraum garantiert. Wenn das Betriebssystem Compiler-Toolchains, libc-Versionen und andere Tools, die während eines Gitian-Builds verwendet werden, aktualisieren kann, werden zukünftige Änderungen an der Ausgabe erwartet. Da dies der Fall ist, da gitian ubuntu-basiert ist, und Patches noch zu älteren ubuntu-Versionen ausgeliefert werden, ist damit nach einiger Zeit zu rechnen.