mirror of
https://github.com/serai-dex/serai.git
synced 2024-12-22 19:49:22 +00:00
Use the deterministically built wasm
Has the Dockerfile output to a volume. Has the node use the wasm from the volume, if it exists.
This commit is contained in:
parent
84cee06ac1
commit
fab7a0a7cb
6 changed files with 117 additions and 18 deletions
|
@ -1,17 +1,20 @@
|
||||||
FROM --platform=linux/amd64 rust:1.77.0-slim-bookworm as builder
|
# rust:1.77.0-slim-bookworm as of March 22nd, 2024 (GMT)
|
||||||
|
FROM --platform=linux/amd64 rust@sha256:e785e4aa81f87bc1ee02fa2026ffbc491e0410bdaf6652cea74884373f452664 as deterministic
|
||||||
|
|
||||||
# Move to a Debian package snapshot
|
# Move to a Debian package snapshot
|
||||||
RUN rm -rf /etc/apt/sources.list.d/debian.sources && \
|
RUN rm -rf /etc/apt/sources.list.d/debian.sources && \
|
||||||
rm -rf /var/lib/apt/lists/* && \
|
rm -rf /var/lib/apt/lists/* && \
|
||||||
echo "deb [arch=amd64] http://snapshot.debian.org/archive/debian/20240201T000000Z bookworm main" > /etc/apt/sources.list && \
|
echo "deb [arch=amd64] http://snapshot.debian.org/archive/debian/20240301T000000Z bookworm main" > /etc/apt/sources.list && \
|
||||||
apt update
|
apt update
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
RUN apt install clang -y
|
RUN apt update && apt upgrade && apt install clang -y
|
||||||
|
|
||||||
# Add the wasm toolchain
|
# Add the wasm toolchain
|
||||||
RUN rustup target add wasm32-unknown-unknown
|
RUN rustup target add wasm32-unknown-unknown
|
||||||
|
|
||||||
|
FROM deterministic
|
||||||
|
|
||||||
# Add files for build
|
# Add files for build
|
||||||
ADD patches /serai/patches
|
ADD patches /serai/patches
|
||||||
ADD common /serai/common
|
ADD common /serai/common
|
||||||
|
@ -30,3 +33,8 @@ ADD Cargo.lock /serai
|
||||||
ADD AGPL-3.0 /serai
|
ADD AGPL-3.0 /serai
|
||||||
|
|
||||||
WORKDIR /serai
|
WORKDIR /serai
|
||||||
|
|
||||||
|
# Build the runtime, copying it to the volume if it exists
|
||||||
|
CMD cargo build --release -p serai-runtime && \
|
||||||
|
mkdir -p /volume && \
|
||||||
|
cp /serai/target/release/wbuild/serai-runtime/serai_runtime.wasm /volume/serai.wasm
|
||||||
|
|
|
@ -325,6 +325,87 @@ fn start(network: Network, services: HashSet<String>) {
|
||||||
_ => panic!("starting unrecognized service"),
|
_ => panic!("starting unrecognized service"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// If we're building the Serai service, first build the runtime
|
||||||
|
let serai_runtime_volume = format!("serai-{}-runtime-volume", network.label());
|
||||||
|
if name == "serai" {
|
||||||
|
// Check if it's built by checking if the volume has the expected runtime file
|
||||||
|
let built = || {
|
||||||
|
if let Ok(path) = Command::new("docker")
|
||||||
|
.arg("volume")
|
||||||
|
.arg("inspect")
|
||||||
|
.arg("-f")
|
||||||
|
.arg("{{ .Mountpoint }}")
|
||||||
|
.arg(&serai_runtime_volume)
|
||||||
|
.output()
|
||||||
|
{
|
||||||
|
if let Ok(path) = String::from_utf8(path.stdout) {
|
||||||
|
if let Ok(iter) = std::fs::read_dir(PathBuf::from(path.trim())) {
|
||||||
|
for item in iter.flatten() {
|
||||||
|
if item.file_name() == "serai.wasm" {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
if !built() {
|
||||||
|
let mut repo_path = env::current_exe().unwrap();
|
||||||
|
repo_path.pop();
|
||||||
|
if repo_path.as_path().ends_with("deps") {
|
||||||
|
repo_path.pop();
|
||||||
|
}
|
||||||
|
assert!(repo_path.as_path().ends_with("debug") || repo_path.as_path().ends_with("release"));
|
||||||
|
repo_path.pop();
|
||||||
|
assert!(repo_path.as_path().ends_with("target"));
|
||||||
|
repo_path.pop();
|
||||||
|
|
||||||
|
// Build the image to build the runtime
|
||||||
|
if !Command::new("docker")
|
||||||
|
.current_dir(&repo_path)
|
||||||
|
.arg("build")
|
||||||
|
.arg("-f")
|
||||||
|
.arg("orchestration/runtime/Dockerfile")
|
||||||
|
.arg(".")
|
||||||
|
.arg("-t")
|
||||||
|
.arg(format!("serai-{}-runtime-img", network.label()))
|
||||||
|
.spawn()
|
||||||
|
.unwrap()
|
||||||
|
.wait()
|
||||||
|
.unwrap()
|
||||||
|
.success()
|
||||||
|
{
|
||||||
|
panic!("failed to build runtime image");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the image, building the runtime
|
||||||
|
println!("Building the Serai runtime");
|
||||||
|
let container_name = format!("serai-{}-runtime", network.label());
|
||||||
|
let _ =
|
||||||
|
Command::new("docker").arg("rm").arg("-f").arg(&container_name).spawn().unwrap().wait();
|
||||||
|
let _ = Command::new("docker")
|
||||||
|
.arg("run")
|
||||||
|
.arg("--name")
|
||||||
|
.arg(container_name)
|
||||||
|
.arg("--volume")
|
||||||
|
.arg(format!("{serai_runtime_volume}:/volume"))
|
||||||
|
.arg(format!("serai-{}-runtime-img", network.label()))
|
||||||
|
.spawn();
|
||||||
|
|
||||||
|
// Wait until its built
|
||||||
|
let mut ticks = 0;
|
||||||
|
while !built() {
|
||||||
|
std::thread::sleep(core::time::Duration::from_secs(60));
|
||||||
|
ticks += 1;
|
||||||
|
if ticks > 6 * 60 {
|
||||||
|
panic!("couldn't build the runtime after 6 hours")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Build it
|
// Build it
|
||||||
println!("Building {service}");
|
println!("Building {service}");
|
||||||
docker::build(&orchestration_path(network), network, name);
|
docker::build(&orchestration_path(network), network, name);
|
||||||
|
@ -367,6 +448,7 @@ fn start(network: Network, services: HashSet<String>) {
|
||||||
assert_eq!(network, Network::Dev, "monero-wallet-rpc is only for dev");
|
assert_eq!(network, Network::Dev, "monero-wallet-rpc is only for dev");
|
||||||
command.arg("-p").arg("18082:18082")
|
command.arg("-p").arg("18082:18082")
|
||||||
}
|
}
|
||||||
|
"serai" => command.arg("--volume").arg(format!("{serai_runtime_volume}:/runtime")),
|
||||||
_ => command,
|
_ => command,
|
||||||
};
|
};
|
||||||
assert!(
|
assert!(
|
||||||
|
|
|
@ -21,7 +21,7 @@ EXPOSE 30333 9615 9933 9944
|
||||||
ADD /orchestration/{}/serai/run.sh /
|
ADD /orchestration/{}/serai/run.sh /
|
||||||
CMD ["/run.sh"]
|
CMD ["/run.sh"]
|
||||||
"#,
|
"#,
|
||||||
network.label()
|
network.label(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let run = os(Os::Debian, "", "serai") + &run_serai;
|
let run = os(Os::Debian, "", "serai") + &run_serai;
|
||||||
|
|
|
@ -15,6 +15,14 @@ fn account_from_name(name: &'static str) -> PublicKey {
|
||||||
insecure_pair_from_name(name).public()
|
insecure_pair_from_name(name).public()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn wasm_binary() -> Vec<u8> {
|
||||||
|
// TODO: Accept a config of runtime path
|
||||||
|
if let Ok(binary) = std::fs::read("/runtime/serai.wasm") {
|
||||||
|
return binary;
|
||||||
|
}
|
||||||
|
WASM_BINARY.ok_or("compiled in wasm not available").unwrap().to_vec()
|
||||||
|
}
|
||||||
|
|
||||||
fn testnet_genesis(
|
fn testnet_genesis(
|
||||||
wasm_binary: &[u8],
|
wasm_binary: &[u8],
|
||||||
validators: &[&'static str],
|
validators: &[&'static str],
|
||||||
|
@ -64,18 +72,18 @@ fn testnet_genesis(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn development_config() -> Result<ChainSpec, &'static str> {
|
pub fn development_config() -> ChainSpec {
|
||||||
let wasm_binary = WASM_BINARY.ok_or("Development wasm not available")?;
|
let wasm_binary = wasm_binary();
|
||||||
|
|
||||||
Ok(ChainSpec::from_genesis(
|
ChainSpec::from_genesis(
|
||||||
// Name
|
// Name
|
||||||
"Development Network",
|
"Development Network",
|
||||||
// ID
|
// ID
|
||||||
"devnet",
|
"devnet",
|
||||||
ChainType::Development,
|
ChainType::Development,
|
||||||
|| {
|
move || {
|
||||||
testnet_genesis(
|
testnet_genesis(
|
||||||
wasm_binary,
|
&wasm_binary,
|
||||||
&["Alice"],
|
&["Alice"],
|
||||||
vec![
|
vec![
|
||||||
account_from_name("Alice"),
|
account_from_name("Alice"),
|
||||||
|
@ -99,21 +107,21 @@ pub fn development_config() -> Result<ChainSpec, &'static str> {
|
||||||
None,
|
None,
|
||||||
// Extensions
|
// Extensions
|
||||||
None,
|
None,
|
||||||
))
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn testnet_config() -> Result<ChainSpec, &'static str> {
|
pub fn testnet_config() -> ChainSpec {
|
||||||
let wasm_binary = WASM_BINARY.ok_or("Testnet wasm not available")?;
|
let wasm_binary = wasm_binary();
|
||||||
|
|
||||||
Ok(ChainSpec::from_genesis(
|
ChainSpec::from_genesis(
|
||||||
// Name
|
// Name
|
||||||
"Local Test Network",
|
"Local Test Network",
|
||||||
// ID
|
// ID
|
||||||
"local",
|
"local",
|
||||||
ChainType::Local,
|
ChainType::Local,
|
||||||
|| {
|
move || {
|
||||||
testnet_genesis(
|
testnet_genesis(
|
||||||
wasm_binary,
|
&wasm_binary,
|
||||||
&["Alice", "Bob", "Charlie", "Dave"],
|
&["Alice", "Bob", "Charlie", "Dave"],
|
||||||
vec![
|
vec![
|
||||||
account_from_name("Alice"),
|
account_from_name("Alice"),
|
||||||
|
@ -137,5 +145,5 @@ pub fn testnet_config() -> Result<ChainSpec, &'static str> {
|
||||||
None,
|
None,
|
||||||
// Extensions
|
// Extensions
|
||||||
None,
|
None,
|
||||||
))
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,8 +39,8 @@ impl SubstrateCli for Cli {
|
||||||
|
|
||||||
fn load_spec(&self, id: &str) -> Result<Box<dyn sc_service::ChainSpec>, String> {
|
fn load_spec(&self, id: &str) -> Result<Box<dyn sc_service::ChainSpec>, String> {
|
||||||
match id {
|
match id {
|
||||||
"dev" | "devnet" => Ok(Box::new(chain_spec::development_config()?)),
|
"dev" | "devnet" => Ok(Box::new(chain_spec::development_config())),
|
||||||
"local" => Ok(Box::new(chain_spec::testnet_config()?)),
|
"local" => Ok(Box::new(chain_spec::testnet_config())),
|
||||||
_ => panic!("Unknown network ID"),
|
_ => panic!("Unknown network ID"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,6 +142,7 @@ pub mod pallet {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 80% threshold
|
// 80% threshold
|
||||||
|
// TODO: Use 34% for halting a set (not 80%)
|
||||||
const REQUIREMENT_NUMERATOR: u64 = 4;
|
const REQUIREMENT_NUMERATOR: u64 = 4;
|
||||||
const REQUIREMENT_DIVISOR: u64 = 5;
|
const REQUIREMENT_DIVISOR: u64 = 5;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue