Skip to content
This repository has been archived by the owner on Aug 24, 2023. It is now read-only.

Commit

Permalink
FFI support for ain integration
Browse files Browse the repository at this point in the history
* Parse args and run in a separate thread

* Native helper struct for static FFI invocation

* Wait until node starts when run as daemon

* Flags for success, daemon and displaying help

* Graceful shutdown on interrupt signal
  • Loading branch information
wafflespeanut committed Nov 30, 2022
1 parent b592186 commit 0060779
Show file tree
Hide file tree
Showing 10 changed files with 332 additions and 20 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ target/

# These are backup files generated by rustfmt
**/*.rs.bk
# Rust package files
pkg/
# ain depends integration artifacts
.stamp_*
master-*

### Substrate
.local
Expand Down
76 changes: 73 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
CARGO ?= cargo
TARGET ?=

build-native-pkg:
CRATE_CC_NO_DEFAULTS=1 $(CARGO) build --package meta-node --release $(if $(TARGET),--target $(TARGET),)
mkdir -p pkg/metachain/include pkg/metachain/lib
cp target/$(if $(TARGET),$(TARGET)/,)release/libmeta_node.a pkg/metachain/lib/libmetachain.a
cp target/libmc.hpp pkg/metachain/include/
cp target/libmc.cpp pkg/metachain/
13 changes: 12 additions & 1 deletion meta/meta-node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,22 @@ version = "0.1.0"
edition = "2021"
build = "build.rs"

[lib]
crate-type = ["staticlib"]

[[bin]]
name = "meta-node"
path = "src/main.rs"

[dependencies]
async-trait = "0.1"
clap = { version = "3.1", features = ["derive"] }
cxx = "1.0"
futures = "0.3.21"
lazy_static = "1.4.0"
log = "0.4.17"
serde_json = "1.0"
tokio = { version = "1.22", features = ["sync"] }
# Parity
codec = { version = "3.1.5", features = ["derive"], package = "parity-scale-codec" }
jsonrpsee = { version = "0.14.0", features = ["server"] }
Expand Down Expand Up @@ -58,4 +68,5 @@ meta-runtime = { package = "meta-runtime", path = "../meta-runtime" }

[build-dependencies]
substrate-build-script-utils = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.27" }

cxx-gen = "0.7"
proc-macro2 = "1.0"
32 changes: 32 additions & 0 deletions meta/meta-node/build.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,39 @@
use proc_macro2::TokenStream;
use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed};

use std::env;
use std::fs::File;
use std::io::{Read, Write};
use std::path::PathBuf;

fn main() {
generate_cargo_keys();

rerun_if_git_head_changed();

let mut root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
let parent = root.clone();
root.pop();
root.pop();
let lib_path = &parent.join("src").join("lib.rs");
println!("cargo:rerun-if-changed={}", lib_path.display());
let target_dir = &root.join("target");

let mut content = String::new();
File::open(lib_path)
.unwrap()
.read_to_string(&mut content)
.unwrap();
let tt: TokenStream = content.parse().unwrap();
let codegen = cxx_gen::generate_header_and_cc(tt, &cxx_gen::Opt::default()).unwrap();

let cpp_stuff = String::from_utf8(codegen.implementation).unwrap();
File::create(target_dir.join("libmc.hpp"))
.unwrap()
.write_all(&codegen.header)
.unwrap();
File::create(target_dir.join("libmc.cpp"))
.unwrap()
.write_all(cpp_stuff.as_bytes())
.unwrap();
}
45 changes: 37 additions & 8 deletions meta/meta-node/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ use crate::{
cli::{Cli, Subcommand},
service::{self, db_config_dir},
};
use clap::Parser;
use fc_db::frontier_database_dir;
use sc_cli::{ChainSpec, RuntimeVersion, SubstrateCli};
use sc_service::{DatabaseSource, PartialComponents};
use tokio::sync::mpsc;

use std::thread;

impl SubstrateCli for Cli {
fn impl_name() -> String {
Expand Down Expand Up @@ -51,10 +53,8 @@ impl SubstrateCli for Cli {
}
}

/// Parse and run command line arguments
pub fn run() -> sc_cli::Result<()> {
let cli = Cli::parse();

/// Parse and run command line arguments in a separate thread and return handle
pub fn run(cli: Cli) -> sc_cli::Result<()> {
match &cli.subcommand {
Some(Subcommand::Key(cmd)) => cmd.run(&cli),
Some(Subcommand::BuildSpec(cmd)) => {
Expand Down Expand Up @@ -154,10 +154,39 @@ pub fn run() -> sc_cli::Result<()> {
})
}
None => {
// Metachain should block until the network starts before handing over
// control to the native chain. One way to accomplish this is by moving
// everything over to a separate thread, wait for the result of node start,
// and let native chain take control after.
let (tx, mut rx) = mpsc::channel(1);
let runner = cli.create_runner(&cli.run.base)?;
runner.run_node_until_exit(|config| async move {
service::new_full(config, &cli).map_err(sc_cli::Error::Service)
})
let (signal_tx, mut signal_rx) = mpsc::channel(1);
crate::native::setup_interrupt_handler(signal_tx);
let handle = thread::spawn(move || {
runner.async_run(|config| {
match service::new_full(config, &cli) {
Ok((starter, manager)) => {
starter.start_network();
let _ = tx.blocking_send(None); // network has started, return control to native chain
Ok((async move {
signal_rx.recv().await; // wait for signal from native chain
Ok(())
}, manager))
},
Err(e) => {
let _ = tx.blocking_send(Some(e.to_string())); // failed to start network
Err(sc_cli::Error::Service(e))
},
}
})
});

// Wait for startup failure, if any
if let Some(Some(msg)) = rx.blocking_recv() {
return Err(msg.into());
}

crate::native::store_handle(handle)
}
}
}
Loading

0 comments on commit 0060779

Please sign in to comment.