From 69e36c1443497c615979972e7619229d77d6891c Mon Sep 17 00:00:00 2001 From: librelois <c@elo.tf> Date: Wed, 25 May 2022 15:50:56 +0200 Subject: [PATCH] feat(xtask): add subcommand inject-runtime-code --- Cargo.lock | 3 ++ xtask/Cargo.toml | 3 ++ xtask/src/main.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index ef1ee7c1b..01a4067c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9000,9 +9000,12 @@ dependencies = [ "anyhow", "clap", "frame-metadata", + "hex", + "memmap2 0.5.0", "parity-scale-codec", "run_script", "scale-info", + "serde_json", "version-compare", "version_check", ] diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 43fefae3b..c9f4dc22c 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -17,7 +17,10 @@ anyhow = "1.0.32" clap = { version = "3.0", features = ["derive"] } codec = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive", "full", "bit-vec"] } frame-metadata = "14.0.0" +hex = "0.4" +memmap2 = "0.5.0" run_script = "0.6.3" scale-info = { version = "1.0.0", features = ["bit-vec"] } +serde_json = "1.0" version_check = "0.9.2" version-compare = "0.0.11" diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 0873750f8..ee06e50af 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -16,8 +16,10 @@ mod gen_calls_doc; -use anyhow::Result; +use anyhow::{Context, Result}; use clap::Parser; +use std::io::{BufReader, BufWriter, Read, Write}; +use std::path::{Path, PathBuf}; use std::process::Command; const MIN_RUST_VERSION: &str = "1.58.0"; @@ -37,6 +39,15 @@ enum DuniterXTaskCommand { }, /// Generate calls documentation GenCallsDoc, + /// Inject runtime code in raw specs + InjectRuntimeCode { + #[clap(short, long, parse(from_os_str))] + /// Runtime filepath + runtime: PathBuf, + #[clap(short = 's', long, parse(from_os_str))] + /// Raw spec filepath + raw_spec: PathBuf, + }, /// Execute unit tests and integration tests /// End2tests are skipped Test, @@ -60,10 +71,67 @@ fn main() -> Result<()> { match args.command { DuniterXTaskCommand::Build { production } => build(production), DuniterXTaskCommand::GenCallsDoc => gen_calls_doc::gen_calls_doc(), + DuniterXTaskCommand::InjectRuntimeCode { runtime, raw_spec } => { + inject_runtime_code(&raw_spec, &runtime) + } DuniterXTaskCommand::Test => test(), } } +fn inject_runtime_code(raw_spec: &Path, runtime: &Path) -> Result<()> { + // Read runtime code + // SAFETY: `mmap` is fundamentally unsafe since technically the file can change + // underneath us while it is mapped; in practice it's unlikely to be a problem + let mut file = + std::fs::File::open(runtime).with_context(|| "Failed to open runtime wasm file")?; + let mut runtime_code = + unsafe { memmap2::Mmap::map(&file).with_context(|| "Failed to read runtime wasm file")? }; + + // Read raw spec + let mut file = std::fs::File::open(raw_spec).with_context(|| "Failed to open raw spec file")?; + let reader = BufReader::new(file); + let mut json: serde_json::Value = + serde_json::from_reader(reader).with_context(|| "Failed to read raw spec file")?; + println!("json raw specs loaded!"); + + let mut hex_runtime_code = String::with_capacity(2 + (runtime_code.len() * 2)); + hex_runtime_code.push('0'); + hex_runtime_code.push('x'); + hex_runtime_code.push_str(&hex::encode(runtime_code)); + //hex::encode_to_slice(runtime_code, &mut hex_runtime_code[2..]) + //.with_context(|| "fail to convert runtime code to hex")?; + + const CODE_KEY: &str = "0x3a636f6465"; + + json.as_object_mut() + .with_context(|| "invalid raw spec file")? + .get_mut("genesis") + .with_context(|| "invalid raw spec file: missing field genesis")? + .as_object_mut() + .with_context(|| "invalid raw spec file")? + .get_mut("raw") + .with_context(|| "invalid raw spec file: missing field raw")? + .as_object_mut() + .with_context(|| "invalid raw spec file")? + .get_mut("top") + .with_context(|| "invalid raw spec file: missing field top")? + .as_object_mut() + .with_context(|| "invalid raw spec file")? + .insert( + CODE_KEY.to_owned(), + serde_json::Value::String(unsafe { std::mem::transmute(hex_runtime_code) }), + ); + + // Write modified raw specs + + let mut file = std::fs::File::create(raw_spec)?; + + serde_json::to_writer_pretty(BufWriter::new(file), &json) + .with_context(|| "fail to write raw specs")?; + + Ok(()) +} + fn build(_production: bool) -> Result<()> { exec_should_success(Command::new("cargo").args(&["clean", "-p", "duniter"]))?; exec_should_success(Command::new("cargo").args(&["build", "--locked"]))?; -- GitLab