From 7d8acc20a074d2730be1a06f1bd460b933875e21 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Fri, 31 Jul 2020 05:00:39 +0000 Subject: [PATCH] Add a flag to make lighthouse portable across machines (#1423) ## Issue Addressed Closes #1395 ## Proposed Changes * Add a feature to `lighthouse` and `lcli` called `portable` which enables the `portable` feature on our fork of BLST. This feature turns off the `-march=native` C compiler flag that produces binaries highly targeted to the host CPU's instruction set. * Tweak the `Makefile` so that when the `PORTABLE` environment variable is set to `true`, it compiles with this feature. * Temporarily enable `PORTABLE=true` in the Docker build so that the image on Docker Hub is portable. Eventually I think we should enable `PORTABLE=true` _only on Docker Hub_, so that users building locally can take advantage of the tasty compiler magic. This seems to be possible by setting a Docker Hub environment variable: https://docs.docker.com/docker-hub/builds/#environment-variables-for-builds ## Additional Info Tested by compiling on a very new CPU (Intel Core i7-8550U) and copying the binary to a very old CPU (Intel Core i3 530). Before the portability fix, this produced the SIGILL crash described in #1395, and after the fix, it worked smoothly. I'm in the process of testing the Docker build and running some benches to confirm that the performance penalty isn't too severe. --- Cargo.lock | 3 ++- Dockerfile | 6 ++++-- Makefile | 8 ++++++++ book/src/docker.md | 4 ++++ crypto/bls/Cargo.toml | 3 ++- hooks/build | 4 ++++ lcli/Cargo.toml | 4 +++- lighthouse/Cargo.toml | 6 +++++- 8 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 hooks/build diff --git a/Cargo.lock b/Cargo.lock index 954201d8b..16d1f8af2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -563,7 +563,6 @@ dependencies = [ [[package]] name = "blst" version = "0.1.1" -source = "git+https://github.com/sigp/blst.git?rev=968c846a2dc46e836e407bbdbac1a38a597ebc46#968c846a2dc46e836e407bbdbac1a38a597ebc46" dependencies = [ "cc", "glob", @@ -2577,6 +2576,7 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" name = "lcli" version = "0.2.0" dependencies = [ + "bls", "clap", "clap_utils", "deposit_contract", @@ -2980,6 +2980,7 @@ dependencies = [ "account_manager", "account_utils", "beacon_node", + "bls", "boot_node", "clap", "clap_utils", diff --git a/Dockerfile b/Dockerfile index cd002b2ed..9f6158b73 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,10 @@ -FROM rust:1.44.1 AS builder +FROM rust:1.45.1 AS builder RUN apt-get update && apt-get install -y cmake COPY . lighthouse +ARG PORTABLE +ENV PORTABLE $PORTABLE RUN cd lighthouse && make -RUN cd lighthouse && cargo install --path lcli --locked +RUN cd lighthouse && make install-lcli FROM debian:buster-slim RUN apt-get update && apt-get install -y --no-install-recommends \ diff --git a/Makefile b/Makefile index a3c3af18e..618f6c30e 100644 --- a/Makefile +++ b/Makefile @@ -7,11 +7,19 @@ STATE_TRANSITION_VECTORS = "testing/state_transition_vectors" # # Binaries will most likely be found in `./target/release` install: +ifeq ($(PORTABLE), true) + cargo install --path lighthouse --force --locked --features portable +else cargo install --path lighthouse --force --locked +endif # Builds the lcli binary in release (optimized). install-lcli: +ifeq ($(PORTABLE), true) + cargo install --path lcli --force --locked --features portable +else cargo install --path lcli --force --locked +endif # Runs the full workspace tests in **release**, without downloading any additional # test vectors. diff --git a/book/src/docker.md b/book/src/docker.md index a12100fcd..8a09e2bb4 100644 --- a/book/src/docker.md +++ b/book/src/docker.md @@ -29,6 +29,10 @@ $ docker run sigp/lighthouse lighthouse --help > Note: when you're running the Docker Hub image you're relying upon a > pre-built binary instead of building from source. +> Note: due to the Docker Hub image being compiled to work on arbitrary machines, it isn't as highly +> optimized as an image built from source. We're working to improve this, but for now if you want +> the absolute best performance, please build the image yourself. + ### Building the Docker Image To build the image from source, navigate to diff --git a/crypto/bls/Cargo.toml b/crypto/bls/Cargo.toml index 1ebce3727..057be4c3f 100644 --- a/crypto/bls/Cargo.toml +++ b/crypto/bls/Cargo.toml @@ -17,10 +17,11 @@ eth2_hashing = "0.1.0" ethereum-types = "0.9.1" arbitrary = { version = "0.4.4", features = ["derive"], optional = true } zeroize = { version = "1.0.0", features = ["zeroize_derive"] } -blst = { git = "https://github.com/sigp/blst.git", rev = "968c846a2dc46e836e407bbdbac1a38a597ebc46" } +blst = { git = "https://github.com/sigp/blst.git", rev = "dad1ad0cd22861e5773bee177bee4e1684792605" } [features] default = ["supranational"] fake_crypto = [] milagro = [] supranational = [] +supranational-portable = ["supranational", "blst/portable"] diff --git a/hooks/build b/hooks/build new file mode 100644 index 000000000..26907a79d --- /dev/null +++ b/hooks/build @@ -0,0 +1,4 @@ +#!/bin/bash + +# Build hook to run on Docker Hub to ensure that the image is built with `PORTABLE=true`. +docker build --build-arg PORTABLE=true -f $DOCKERFILE_PATH -t $IMAGE_NAME . diff --git a/lcli/Cargo.toml b/lcli/Cargo.toml index 8e64c279c..d6335f4d2 100644 --- a/lcli/Cargo.toml +++ b/lcli/Cargo.toml @@ -5,9 +5,11 @@ version = "0.2.0" authors = ["Paul Hauner "] edition = "2018" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +portable = ["bls/supranational-portable"] [dependencies] +bls = { path = "../crypto/bls" } clap = "2.33.0" hex = "0.4.2" log = "0.4.8" diff --git a/lighthouse/Cargo.toml b/lighthouse/Cargo.toml index 59eac118f..f34410aa0 100644 --- a/lighthouse/Cargo.toml +++ b/lighthouse/Cargo.toml @@ -5,7 +5,10 @@ authors = ["Sigma Prime "] edition = "2018" [features] -write_ssz_files = ["beacon_node/write_ssz_files"] # Writes debugging .ssz files to /tmp during block processing. +# Writes debugging .ssz files to /tmp during block processing. +write_ssz_files = ["beacon_node/write_ssz_files"] +# Compiles the BLS crypto code so that the binary is portable across machines. +portable = ["bls/supranational-portable"] [dependencies] beacon_node = { "path" = "../beacon_node" } @@ -13,6 +16,7 @@ tokio = "0.2.21" slog = { version = "2.5.2", features = ["max_level_trace"] } sloggers = "1.0.0" types = { "path" = "../consensus/types" } +bls = { path = "../crypto/bls" } clap = "2.33.0" env_logger = "0.7.1" logging = { path = "../common/logging" }