Skip to content

Commit 3453cf2

Browse files
committed
Merge #15277: contrib: Enable building in Guix containers
751549b contrib: guix: Additional clarifications re: substitutes (Carl Dong) cd3e947 contrib: guix: Various improvements. (Carl Dong) 8dff3e4 contrib: guix: Clarify SOURCE_DATE_EPOCH. (Carl Dong) 3e80ec3 contrib: Add deterministic Guix builds. (Carl Dong) Pull request description: ~~**This post is kept updated as this project progresses. Use this [latest update link](bitcoin/bitcoin#15277 (comment)) to see what's new.**~~ Please read the `README.md`. ----- ### Guix Introduction This PR enables building bitcoin in Guix containers. [Guix](https://www.gnu.org/software/guix/manual/en/html_node/Features.html) is a transactional package manager much like Nix, but unlike Nix, it has more of a focus on [bootstrappability](https://www.gnu.org/software/guix/manual/en/html_node/Bootstrapping.html) and [reproducibility](https://www.gnu.org/software/guix/blog/tags/reproducible-builds/) which are attractive for security-sensitive projects like bitcoin. ### Guix Build Walkthrough Please read the `README.md`. [Old instructions no. 4](bitcoin/bitcoin#15277 (comment)) [Old instructions no. 3](bitcoin/bitcoin#15277 (comment)) [Old instructions no. 2](bitcoin/bitcoin#15277 (comment)) <details> <summary>Old instructions no. 1</summary> In this PR, we define a Guix [manifest](https://www.gnu.org/software/guix/manual/en/html_node/Invoking-guix-package.html#profile_002dmanifest) in `contrib/guix/manifest.scm`, which declares what packages we want in our environment. We can then invoke ``` guix environment --manifest=contrib/guix/manifest.scm --container --pure --no-grafts --no-substitutes ``` To have Guix: 1. Build an environment containing the packages we defined in our `contrib/guix/manifest.scm` manifest from the Guix bootstrap binaries (see [bootstrappability](https://www.gnu.org/software/guix/manual/en/html_node/Bootstrapping.html) for more details). 2. Start a container with that environment that has no network access, and no access to the host's filesystem except to the `pwd` that it was started in. 3. Drop you into a shell in that container. > Note: if you don't want to wait hours for Guix to build the entire world from scratch, you can eliminate the `--no-substitutes` option to have Guix download from available binary sources. Note that this convenience doesn't necessarily compromise your security, as you can check that a package was built correctly after the fact using `guix build --check <packagename>` Therefore, we can perform a build of bitcoin much like in Gitian by invoking the following: ``` make -C depends -j"$(nproc)" download && \ cat contrib/guix/build.sh | guix environment --manifest=contrib/guix/manifest.scm --container --pure --no-grafts --no-substitutes ``` We don't include `make -C depends -j"$(nproc)" download` inside `contrib/guix/build.sh` because `contrib/guix/build.sh` is run inside the container, which has no network access (which is a good thing). </details> ### Rationale I believe that this represents a substantial improvement for the "supply chain security" of bitcoin because: 1. We no longer have to rely on Ubuntu for our build environment for our releases ([oh the horror](https://github.com/bitcoin/bitcoin/blob/72bd4ab867e3be0d8410403d9641c08288d343e3/contrib/gitian-descriptors/gitian-linux.yml#L10)), because Guix builds everything about the container, we can perform this on almost any Linux distro/system. 2. It is now much easier to determine what trusted binaries are in our supply chain, and even make a nice visualization! (see [bootstrappability](https://www.gnu.org/software/guix/manual/en/html_node/Bootstrapping.html)). 3. There is active effort among Guix folks to minimize the number of trusted binaries even further. OriansJ's [stage0](https://github.com/oriansj/stage0), and janneke's [Mes](https://www.gnu.org/software/mes/) all aim to achieve [reduced binary boostrap](http://joyofsource.com/reduced-binary-seed-bootstrap.html) for Guix. In fact, I believe if OriansJ gets his way, we will end up some day with only a single trusted binary: hex0 (a ~500 byte self-hosting hex assembler). ### Steps to Completion - [x] Successfully build bitcoin inside the Guix environment - [x] Make `check-symbols` pass - [x] Do the above but without nasty hacks - [x] Solve some of the more innocuous hacks - [ ] Make it cross-compile (HELP WANTED HERE) - [x] Linux - [x] x86_64-linux-gnu - [x] i686-linux-gnu - [x] aarch64-linux-gnu - [x] arm-linux-gnueabihf - [x] riscv64-linux-gnu - [ ] OS X - [ ] x86_64-apple-darwin14 - [ ] Windows - [ ] x86_64-w64-mingw32 - [ ] Maybe make importer for depends syntax - [ ] Document build process for future releases - [ ] Extra: Pin the revision of Guix that we build with with Guix [inferiors](https://www.gnu.org/software/guix/manual/en/html_node/Inferiors.html) ### Help Wanted [Old content no. 3](bitcoin/bitcoin#15277 (comment)) [Old content no. 2](bitcoin/bitcoin#15277 (comment)) <details> <summary>Old content no. 1</summary> As of now, the command described above to perform a build of bitcoin a lot like Gitian works, but fails at the `check-symbols` stage. This is because a few dynamic libraries are linked in that shouldn't be. Here's what `ldd src/bitcoind` looks like when built in a Guix container: ``` linux-vdso.so.1 (0x00007ffcc2d90000) libdl.so.2 => /gnu/store/h90vnqw0nwd0hhm1l5dgxsdrigddfmq4-glibc-2.28/lib/libdl.so.2 (0x00007fb7eda09000) librt.so.1 => /gnu/store/h90vnqw0nwd0hhm1l5dgxsdrigddfmq4-glibc-2.28/lib/librt.so.1 (0x00007fb7ed9ff000) libstdc++.so.6 => /gnu/store/4sqps8dczv3g7rwbdibfz6rf5jlk7w90-gcc-5.5.0-lib/lib/libstdc++.so.6 (0x00007fb7ed87c000) libpthread.so.0 => /gnu/store/h90vnqw0nwd0hhm1l5dgxsdrigddfmq4-glibc-2.28/lib/libpthread.so.0 (0x00007fb7ed85b000) libm.so.6 => /gnu/store/h90vnqw0nwd0hhm1l5dgxsdrigddfmq4-glibc-2.28/lib/libm.so.6 (0x00007fb7ed6da000) libgcc_s.so.1 => /gnu/store/4sqps8dczv3g7rwbdibfz6rf5jlk7w90-gcc-5.5.0-lib/lib/libgcc_s.so.1 (0x00007fb7ed6bf000) libc.so.6 => /gnu/store/h90vnqw0nwd0hhm1l5dgxsdrigddfmq4-glibc-2.28/lib/libc.so.6 (0x00007fb7ed506000) /gnu/store/h90vnqw0nwd0hhm1l5dgxsdrigddfmq4-glibc-2.28/lib/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fb7ee3a0000) ``` And here's what it looks in one of our releases: ``` linux-vdso.so.1 (0x00007ffff52cd000) libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f87726b4000) librt.so.1 => /usr/lib/librt.so.1 (0x00007f87726aa000) libm.so.6 => /usr/lib/libm.so.6 (0x00007f8772525000) libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f877250b000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f8772347000) /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f8773392000) ``` ~~I suspect it is because my script does not apply the gitian-input patches [described in the release process](https://github.com/bitcoin/bitcoin/blob/master/doc/release-process.md#fetch-and-create-inputs-first-time-or-when-dependency-versions-change) but there is no description as to how these patches are applied.~~ It might also be something else entirely. Edit: It is something else. It appears that the gitian inputs are only used by [`gitian-win-signer.yml`](https://github.com/bitcoin/bitcoin/blob/d6e700e40f861ddd6743f4d13f0d6f6bc19093c2/contrib/gitian-descriptors/gitian-win-signer.yml#L14) </details> ### How to Help 1. Install Guix on your distro either [from source](https://www.gnu.org/software/guix/manual/en/html_node/Requirements.html) or perform a [binary installation](https://www.gnu.org/software/guix/manual/en/html_node/Binary-Installation.html#Binary-Installation) 2. Try out my branch and the command described above! ACKs for top commit: MarcoFalke: Thanks for the replies. ACK 751549b laanwj: ACK 751549b Tree-SHA512: 50e6ab58c6bda9a67125b6271daf7eff0ca57d0efa8941ed3cd951e5bf78b31552fc5e537b1e1bcf2d3cc918c63adf19d685aa117a0f851024dc67e697890a8d
2 parents 735d6b5 + 751549b commit 3453cf2

File tree

5 files changed

+634
-1
lines changed

5 files changed

+634
-1
lines changed

contrib/guix/README.md

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
# Bootstrappable Bitcoin Core Builds
2+
3+
This directory contains the files necessary to perform bootstrappable Bitcoin
4+
Core builds.
5+
6+
[Bootstrappability][b17e] furthers our binary security guarantees by allowing us
7+
to _audit and reproduce_ our toolchain instead of blindly _trusting_ binary
8+
downloads.
9+
10+
We achieve bootstrappability by using Guix as a functional package manager.
11+
12+
## Requirements
13+
14+
Conservatively, a x86_64 machine with:
15+
16+
- 2 or more logical cores
17+
- 4GB of free disk space on the partition that /gnu/store will reside in
18+
- 24GB of free disk space on the partition that the Bitcoin Core git repository
19+
resides in
20+
21+
> Note: these requirements are slightly less onerous than those of Gitian builds
22+
23+
## Setup
24+
25+
### Installing Guix
26+
27+
If you're just testing this out, you can use the
28+
[Dockerfile][fanquake/guix-docker] for convenience. It automatically speeds up
29+
your builds by [using substitutes](#speeding-up-builds-with-substitute-servers).
30+
If you don't want this behaviour, refer to the [next
31+
section](#choosing-your-security-model).
32+
33+
Otherwise, follow the [Guix installation guide][guix/bin-install].
34+
35+
> Note: For those who like to keep their filesystems clean, Guix is designed to
36+
> be very standalone and _will not_ conflict with your system's package
37+
> manager/existing setup. It _only_ touches `/var/guix`, `/gnu`, and
38+
> `~/.config/guix`.
39+
40+
### Choosing your security model
41+
42+
Guix allows us to achieve better binary security by using our CPU time to build
43+
everything from scratch. However, it doesn't sacrifice user choice in pursuit of
44+
this: users can decide whether or not to bootstrap and to use substitutes.
45+
46+
After installation, you may want to consider [adding substitute
47+
servers](#speeding-up-builds-with-substitute-servers) to speed up your build if
48+
that fits your security model (say, if you're just testing that this works).
49+
This is skippable if you're using the [Dockerfile][fanquake/guix-docker].
50+
51+
If you prefer not to use any substitutes, make sure to set
52+
`ADDITIONAL_GUIX_ENVIRONMENT_FLAGS` like the following snippet. The first build
53+
will take a while, but the resulting packages will be cached for future builds.
54+
55+
```sh
56+
export ADDITIONAL_GUIX_ENVIRONMENT_FLAGS='--no-substitutes'
57+
```
58+
59+
Likewise, to perform a bootstrapped build (takes even longer):
60+
61+
```sh
62+
export ADDITIONAL_GUIX_ENVIRONMENT_FLAGS='--bootstrap --no-substitutes'
63+
```
64+
65+
### Using the right Guix
66+
67+
Once Guix is installed, deploy our patched version into your current Guix
68+
profile. The changes there are slowly being upstreamed.
69+
70+
```sh
71+
guix pull --url=https://github.com/dongcarl/guix.git \
72+
--commit=82c77e52b8b46e0a3aad2cb12307c2e30547deec \
73+
--max-jobs=4 # change accordingly
74+
```
75+
76+
Make sure that you are using your current profile. (You are prompted to do this
77+
at the end of the `guix pull`)
78+
79+
```bash
80+
export PATH="${HOME}/.config/guix/current/bin${PATH:+:}$PATH"
81+
```
82+
83+
> Note: There is ongoing work to eliminate this entire section using Guix
84+
> [inferiors][guix/inferiors] and [channels][guix/channels].
85+
86+
## Usage
87+
88+
### As a Development Environment
89+
90+
For a Bitcoin Core depends development environment, simply invoke
91+
92+
```sh
93+
guix environment --manifest=contrib/guix/manifest.scm
94+
```
95+
96+
And you'll land back in your shell with all the build dependencies required for
97+
a `depends` build injected into your environment.
98+
99+
### As a Tool for Deterministic Builds
100+
101+
From the top of a clean Bitcoin Core repository:
102+
103+
```sh
104+
./contrib/guix/guix-build.sh
105+
```
106+
107+
After the build finishes successfully (check the status code please), compare
108+
hashes:
109+
110+
```sh
111+
find output/ -type f -print0 | sort -z | xargs -r0 sha256sum
112+
```
113+
114+
#### Recognized environment variables
115+
116+
* _**HOSTS**_
117+
118+
Override the space-separated list of platform triples for which to perform a
119+
bootstrappable build. _(defaults to "i686-linux-gnu x86\_64-linux-gnu
120+
arm-linux-gnueabihf aarch64-linux-gnu riscv64-linux-gnu")_
121+
122+
> Windows and OS X platform triplet support are WIP.
123+
124+
* _**SOURCES_PATH**_
125+
126+
Set the depends tree download cache for sources. This is passed through to the
127+
depends tree. Setting this to the same directory across multiple builds of the
128+
depends tree can eliminate unnecessary redownloading of package sources.
129+
130+
* _**MAX_JOBS**_
131+
132+
Override the maximum number of jobs to run simultaneously, you might want to
133+
do so on a memory-limited machine. This may be passed to `make` as in `make
134+
--jobs="$MAX_JOBS"` or `xargs` as in `xargs -P"$MAX_JOBS"`. _(defaults to the
135+
value of `nproc` outside the container)_
136+
137+
* _**SOURCE_DATE_EPOCH**_
138+
139+
Override the reference UNIX timestamp used for bit-for-bit reproducibility,
140+
the variable name conforms to [standard][r12e/source-date-epoch]. _(defaults
141+
to the output of `$(git log --format=%at -1)`)_
142+
143+
* _**V**_
144+
145+
If non-empty, will pass `V=1` to all `make` invocations, making `make` output
146+
verbose.
147+
148+
* _**ADDITIONAL_GUIX_ENVIRONMENT_FLAGS**_
149+
150+
Additional flags to be passed to `guix environment`. For a fully-bootstrapped
151+
build, set this to `--bootstrap --no-substitutes` (refer to the [security
152+
model section](#choosing-your-security-model) for more details). Note that a
153+
fully-bootstrapped build will take quite a long time on the first run.
154+
155+
## Tips and Tricks
156+
157+
### Speeding up builds with substitute servers
158+
159+
_This whole section is automatically done in the convenience
160+
[Dockerfiles][fanquake/guix-docker]_
161+
162+
For those who are used to life in the fast _(and trustful)_ lane, you can use
163+
[substitute servers][guix/substitutes] to enable binary downloads of packages.
164+
165+
> For those who only want to use substitutes from the official Guix build farm
166+
> and have authorized the build farm's signing key during Guix's installation,
167+
> you don't need to do anything.
168+
169+
#### Authorize the signing keys
170+
171+
For the official Guix build farm at https://ci.guix.gnu.org, run as root:
172+
173+
```
174+
guix archive --authorize < ~root/.config/guix/current/share/guix/ci.guix.gnu.org.pub
175+
```
176+
177+
For dongcarl's substitute server at https://guix.carldong.io, run as root:
178+
179+
```sh
180+
wget -qO- 'https://guix.carldong.io/signing-key.pub' | guix archive --authorize
181+
```
182+
183+
#### Use the substitute servers
184+
185+
The official Guix build farm at https://ci.guix.gnu.org is automatically used
186+
unless the `--no-substitutes` flag is supplied.
187+
188+
This can be overridden for all `guix` invocations by passing the
189+
`--substitute-urls` option to your invocation of `guix-daemon`. This can also be
190+
overridden on a call-by-call basis by passing the same `--substitute-urls`
191+
option to client tools such at `guix environment`.
192+
193+
To use dongcarl's substitute server for Bitcoin Core builds after having
194+
[authorized his signing key](#authorize-the-signing-keys):
195+
196+
```
197+
export ADDITIONAL_GUIX_ENVIRONMENT_FLAGS='--substitute-urls="https://guix.carldong.io https://ci.guix.gnu.org"'
198+
```
199+
200+
## FAQ
201+
202+
### How can I trust the binary installation?
203+
204+
As mentioned at the bottom of [this manual page][guix/bin-install]:
205+
206+
> The binary installation tarballs can be (re)produced and verified simply by
207+
> running the following command in the Guix source tree:
208+
>
209+
> make guix-binary.x86_64-linux.tar.xz
210+
211+
### When will Guix be packaged in debian?
212+
213+
Vagrant Cascadian has been making good progress on this
214+
[here][debian/guix-package]. We have all the pieces needed to put up an APT
215+
repository and will likely put one up soon.
216+
217+
[b17e]: http://bootstrappable.org/
218+
[r12e/source-date-epoch]: https://reproducible-builds.org/docs/source-date-epoch/
219+
220+
[guix/install.sh]: https://git.savannah.gnu.org/cgit/guix.git/plain/etc/guix-install.sh
221+
[guix/bin-install]: https://www.gnu.org/software/guix/manual/en/html_node/Binary-Installation.html
222+
[guix/env-setup]: https://www.gnu.org/software/guix/manual/en/html_node/Build-Environment-Setup.html
223+
[guix/substitutes]: https://www.gnu.org/software/guix/manual/en/html_node/Substitutes.html
224+
[guix/substitute-server-auth]: https://www.gnu.org/software/guix/manual/en/html_node/Substitute-Server-Authorization.html
225+
[guix/inferiors]: https://www.gnu.org/software/guix/manual/en/html_node/Inferiors.html
226+
[guix/channels]: https://www.gnu.org/software/guix/manual/en/html_node/Channels.html
227+
228+
[debian/guix-package]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=850644
229+
[fanquake/guix-docker]: https://github.com/fanquake/core-review/tree/master/guix

contrib/guix/guix-build.sh

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/usr/bin/env bash
2+
export LC_ALL=C
3+
set -e -o pipefail
4+
5+
# Determine the maximum number of jobs to run simultaneously (overridable by
6+
# environment)
7+
MAX_JOBS="${MAX_JOBS:-$(nproc)}"
8+
9+
# Download the depends sources now as we won't have internet access in the build
10+
# container
11+
make -C "${PWD}/depends" -j"$MAX_JOBS" download ${V:+V=1} ${SOURCES_PATH:+SOURCES_PATH="$SOURCES_PATH"}
12+
13+
# Determine the reference time used for determinism (overridable by environment)
14+
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-$(git log --format=%at -1)}"
15+
16+
# Deterministically build Bitcoin Core for HOSTs (overriable by environment)
17+
for host in ${HOSTS=i686-linux-gnu x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu riscv64-linux-gnu}; do
18+
19+
# Display proper warning when the user interrupts the build
20+
trap 'echo "** INT received while building ${host}, you may want to clean up the relevant output and distsrc-* directories before rebuilding"' INT
21+
22+
# Run the build script 'contrib/guix/libexec/build.sh' in the build
23+
# container specified by 'contrib/guix/manifest.scm'
24+
# shellcheck disable=SC2086
25+
guix environment --manifest="${PWD}/contrib/guix/manifest.scm" \
26+
--container \
27+
--pure \
28+
--no-cwd \
29+
--share="$PWD"=/bitcoin \
30+
${SOURCES_PATH:+--share="$SOURCES_PATH"} \
31+
${ADDITIONAL_GUIX_ENVIRONMENT_FLAGS} \
32+
-- env HOST="$host" \
33+
MAX_JOBS="$MAX_JOBS" \
34+
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:?unable to determine value}" \
35+
${V:+V=1} \
36+
${SOURCES_PATH:+SOURCES_PATH="$SOURCES_PATH"} \
37+
bash -c "cd /bitcoin && bash contrib/guix/libexec/build.sh"
38+
39+
done

0 commit comments

Comments
 (0)