diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0773143 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +.git/ +.github/ +.vscode +doc/ +target/ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 8365502..a7a996e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -179,6 +179,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "android-tzdata" version = "0.1.1" @@ -2370,6 +2376,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + [[package]] name = "fastrand" version = "1.9.0" @@ -3254,9 +3266,20 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" dependencies = [ + "ahash 0.8.3", + "allocator-api2", "serde", ] +[[package]] +name = "hashlink" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +dependencies = [ + "hashbrown 0.14.0", +] + [[package]] name = "heck" version = "0.3.3" @@ -3296,6 +3319,12 @@ dependencies = [ "serde", ] +[[package]] +name = "hex-literal" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" + [[package]] name = "hkdf" version = "0.12.3" @@ -3957,7 +3986,7 @@ dependencies = [ [[package]] name = "kzg" version = "0.1.0" -source = "git+https://github.com/ZeroDAO/rust-kzg?rev=de872ad#de872ad80eeea976473f6498add519387169a18f" +source = "git+https://github.com/ZeroDAO/rust-kzg.git?rev=de872ad#de872ad80eeea976473f6498add519387169a18f" dependencies = [ "blst", "sha2 0.10.7", @@ -4513,6 +4542,16 @@ dependencies = [ "libsecp256k1-core", ] +[[package]] +name = "libsqlite3-sys" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29f835d03d717946d28b1d1ed632eb6f0e24a299388ee623d0c23118d3e8a7fa" +dependencies = [ + "pkg-config", + "vcpkg", +] + [[package]] name = "libz-sys" version = "1.1.12" @@ -4704,6 +4743,7 @@ version = "0.1.0" dependencies = [ "lazy_static", "log", + "melo-das-db", "melo-das-primitives", "melo-erasure-coding", "parity-scale-codec", @@ -4726,6 +4766,18 @@ dependencies = [ "zstd 0.12.4", ] +[[package]] +name = "melo-das-db" +version = "0.0.1" +dependencies = [ + "rusqlite", + "sc-client-api", + "sc-offchain", + "sp-core", + "sp-io", + "sp-runtime", +] + [[package]] name = "melo-das-network" version = "0.0.1" @@ -4832,6 +4884,7 @@ dependencies = [ "frame-benchmarking-cli", "frame-system", "futures", + "hex-literal", "jsonrpsee", "melo-core-primitives", "melo-das-network", @@ -4980,6 +5033,7 @@ dependencies = [ "serde_json", "simple_logger", "structopt", + "substrate-build-script-utils", "subxt", "subxt-signer", "tokio", @@ -7279,10 +7333,24 @@ dependencies = [ "webrtc-util", ] +[[package]] +name = "rusqlite" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01e213bc3ecb39ac32e81e51ebe31fd888a940515173e3a18a35f8c6e896422a" +dependencies = [ + "bitflags 1.3.2", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "smallvec", +] + [[package]] name = "rust-kzg-blst" version = "0.1.0" -source = "git+https://github.com/ZeroDAO/rust-kzg?rev=de872ad#de872ad80eeea976473f6498add519387169a18f" +source = "git+https://github.com/ZeroDAO/rust-kzg.git?rev=de872ad#de872ad80eeea976473f6498add519387169a18f" dependencies = [ "blst", "hex", diff --git a/Cargo.toml b/Cargo.toml index 2972ec7..ad24169 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ members = [ "crates/frame-system-ext", "crates/melo-erasure-coding", "crates/pallet-melo-store", + "crates/das-db", "crates/meloxt", "runtime", ] diff --git a/Containerfile b/Containerfile index 01a4a54..3eb70ad 100644 --- a/Containerfile +++ b/Containerfile @@ -11,21 +11,21 @@ RUN apt-get update && \ apt-get autoremove -y && \ apt-get clean && \ find /var/lib/apt/lists/ -type f -not -name lock -delete; \ -# add user and link ~/.local/share/polkadot to /data - useradd -m -u 1000 -U -s /bin/sh -d /polkadot polkadot && \ - mkdir -p /data /polkadot/.local/share && \ - chown -R polkadot:polkadot /data && \ - ln -s /data /polkadot/.local/share/node-template +# add user and link ~/.local/share/melodot to /data + useradd -m -u 1000 -U -s /bin/sh -d /melodot melodot && \ + mkdir -p /data /melodot/.local/share && \ + chown -R melodot:melodot /data && \ + ln -s /data /melodot/.local/share/melodot-node -USER polkadot +USER melodot # copy the compiled binary to the container -COPY --chown=polkadot:polkadot --chmod=774 node-template /usr/bin/node-template +COPY --chown=melodot:melodot --chmod=774 melodot-node /usr/bin/melodot-node # check if executable works in this container -RUN /usr/bin/node-template --version +RUN /usr/bin/melodot-node --version # ws_port EXPOSE 9930 9333 9944 30333 30334 -CMD ["/usr/bin/node-template"] +CMD ["/usr/bin/melodot-node"] \ No newline at end of file diff --git a/crates/core-primitives/Cargo.toml b/crates/core-primitives/Cargo.toml index e678d27..165e7b6 100644 --- a/crates/core-primitives/Cargo.toml +++ b/crates/core-primitives/Cargo.toml @@ -12,12 +12,14 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] melo-das-primitives = { version = "0.1.0", path = "../das-primitives", default-features = false} melo-erasure-coding = { version = "0.1.0", path = "../melo-erasure-coding", default-features = false} +melo-das-db = { version = "0.0.1", path = "../das-db", default-features = false} rayon = "1.5.1" codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false, features = ["derive"] } log = { version = "0.4.17", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0.136", optional = true, features = ["alloc", "derive"] } +rand = { version = "0.8", default-features = false, features = ["alloc"] } sp-core = { version = "7.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } sp-std = { version = "5.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } @@ -31,11 +33,10 @@ sc-offchain = {optional = true, default-features = false, git = "https://github. # For testing lazy_static = "1.4" -rand = { version = "0.8.5", optional = true } sp-application-crypto = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } [dev-dependencies] -rand = "0.8.5" +rand = "0.8" serde_json = "1.0.85" zstd = { version = "0.12.3", default-features = false } sp-state-machine = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } @@ -47,9 +48,9 @@ default = ["std", "outside"] std = [ "codec/std", "log/std", - "rand", "scale-info/std", "serde", + "rand/std", "sp-core/std", "sp-runtime/std", "melo-das-primitives/std", @@ -62,11 +63,13 @@ std = [ "sp-application-crypto/std", "sc-client-api", "sc-offchain", + "melo-das-db/std", ] outside = [ "melo-das-primitives/serde", "sc-client-api", "sc-offchain", + # "melo-das-db/outside", ] parallel = [ "melo-das-primitives/parallel", diff --git a/crates/core-primitives/src/confidence.rs b/crates/core-primitives/src/confidence.rs new file mode 100644 index 0000000..017505e --- /dev/null +++ b/crates/core-primitives/src/confidence.rs @@ -0,0 +1,165 @@ +// Copyright 2023 ZeroDAO +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +extern crate alloc; +use alloc::vec::Vec; +use codec::{Decode, Encode}; +use rand::Rng; + +use melo_das_db::traits::DasKv; +use melo_das_primitives::{config::FIELD_ELEMENTS_PER_BLOB, Position}; + +const CHUNK_COUNT: usize = 2 ^ 4; +const SAMPLES_PER_BLOB: usize = FIELD_ELEMENTS_PER_BLOB / CHUNK_COUNT; + +/// Confidence trait defines methods related to the confidence of an application. +pub trait Confidence { + /// Returns the confidence value. + fn value(&self, base_factor: f64) -> f32; + + /// Constructs a unique ID. + fn id(&self) -> Vec; + + /// Fetches `n` random sample positions from the `SAMPLES_PER_BLOB * total_rows` matrix. + fn set_sample(&mut self, n: usize); + + /// Checks if the availability exceeds the provided threshold. + fn exceeds_threshold(&self, base_factor: f64, threshold: f32) -> bool; + + /// Saves the current instance to the database. + fn save(&self, db: &mut impl DasKv); + + /// Retrieves an instance from the database. + fn get(id: &[u8], db: &mut impl DasKv) -> Option + where + Self: Sized; + + /// Removes the current instance from the database. + fn remove(&self, db: &mut impl DasKv); +} + +#[derive(Debug, Clone, Default, Decode, Encode)] +pub struct Sample { + position: Position, + is_availability: bool, +} + +impl Sample { + pub fn set_success(&mut self) { + self.is_availability = true; + } +} + +pub const AVAILABILITY_THRESHOLD: f32 = 0.8; + +#[derive(Debug, Clone, Decode, Encode, Default)] +pub struct ConfidenceBase { + id: Vec, + total_rows: u32, + samples: Vec, +} + +impl Confidence for ConfidenceBase { + fn value(&self, base_factor: f64) -> f32 { + let success_count = self.samples.iter().filter(|&sample| sample.is_availability).count(); + calculate_confidence(success_count as u32, base_factor) as f32 + } + + fn id(&self) -> Vec { + self.id.clone() + } + + fn set_sample(&mut self, n: usize) { + let mut rng = rand::thread_rng(); + let mut positions = Vec::with_capacity(n); + + while positions.len() < n { + let x = rng.gen_range(0..SAMPLES_PER_BLOB) as u32; + let y = rng.gen_range(0..self.total_rows); + + let pos = Position { x, y }; + + if !positions.contains(&pos) { + positions.push(pos); + } + } + + self.samples = positions + .into_iter() + .map(|pos| Sample { position: pos, is_availability: false }) + .collect(); + } + + fn exceeds_threshold(&self, base_factor: f64, threshold: f32) -> bool { + self.value(base_factor) > threshold + } + + fn save(&self, db: &mut impl DasKv) { + db.set(&self.id(), &self.encode()); + } + + fn get(id: &[u8], db: &mut impl DasKv) -> Option + where + Self: Sized, + { + db.get(id).and_then(|encoded_data| Decode::decode(&mut &encoded_data[..]).ok()) + } + + fn remove(&self, db: &mut impl DasKv) { + db.remove(&self.id()); + } +} + +fn calculate_confidence(samples: u32, base_factor: f64) -> f64 { + 100f64 * (1f64 - base_factor.powi(samples as i32)) +} + +pub mod app_confidence { + use super::*; + + pub const BASE_FACTOR: f64 = 0.5; + + pub fn id(block_num: BlockNum, app_id: Vec) -> Vec { + let mut id = app_id.clone(); + id.extend_from_slice(&block_num.encode()); + id + } + + pub fn new_confidence( + block_num: BlockNum, + app_id: Vec, + total_rows: u32, + ) -> ConfidenceBase { + let id = id(block_num.clone(), app_id.clone()); + ConfidenceBase { id, total_rows, samples: Vec::new() } + } +} + +pub mod block_confidence { + use super::*; + + pub const BASE_FACTOR: f64 = 0.25; + + pub fn id(block_hash: Vec) -> Vec { + block_hash + } + + pub fn new_confidence( + block_hash: Vec, + total_rows: u32, + ) -> ConfidenceBase { + let id = id(block_hash); + ConfidenceBase { id, total_rows, samples: Vec::new() } + } +} \ No newline at end of file diff --git a/crates/core-primitives/src/lib.rs b/crates/core-primitives/src/lib.rs index bc15dad..51fc6df 100644 --- a/crates/core-primitives/src/lib.rs +++ b/crates/core-primitives/src/lib.rs @@ -30,7 +30,7 @@ pub mod sidecar; pub use sidecar::*; pub mod localstorage; - +pub mod confidence; pub mod traits; #[cfg(feature = "std")] diff --git a/crates/das-db/Cargo.toml b/crates/das-db/Cargo.toml new file mode 100644 index 0000000..5cd2eb9 --- /dev/null +++ b/crates/das-db/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "melo-das-db" +version = "0.0.1" +description = "" +license = "Apache-2.0" +authors = ["DKLee "] +edition = "2021" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42", default-features = false} +sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42", default-features = false} +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42", default-features = false} + +sc-client-api = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42", optional = true} +sc-offchain = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42", optional = true} + +rusqlite = { version = "0.28.0", optional = true } + +[dev-dependencies] + +[features] +default = ["std"] +std = [ + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "rusqlite", +] +outside = [ + "sc-client-api", + "sc-offchain", +] \ No newline at end of file diff --git a/crates/das-db/src/lib.rs b/crates/das-db/src/lib.rs new file mode 100644 index 0000000..4d69875 --- /dev/null +++ b/crates/das-db/src/lib.rs @@ -0,0 +1,27 @@ +// Copyright 2023 ZeroDAO +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate alloc; +pub use alloc::{ + vec::Vec, + vec, +}; + +pub mod traits; +#[cfg(feature = "std")] +pub mod sqlite; +pub mod offchain; +#[cfg(feature = "outside")] +pub mod offchain_outside; \ No newline at end of file diff --git a/crates/das-db/src/offchain.rs b/crates/das-db/src/offchain.rs new file mode 100644 index 0000000..7950801 --- /dev/null +++ b/crates/das-db/src/offchain.rs @@ -0,0 +1,66 @@ +// Copyright 2023 ZeroDAO +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::traits::DasKv; +use crate::Vec; + +use sp_core::offchain::StorageKind; + +// Implementation for the non-outside environment +pub struct OffchainKv { + prefix: Vec, +} + +impl OffchainKv { + fn get_prefixed_key(&self, key: &[u8]) -> Vec { + let mut prefixed_key = self.prefix.clone(); + prefixed_key.extend_from_slice(key); + prefixed_key + } +} + +impl DasKv for OffchainKv { + fn get(&mut self, key: &[u8]) -> Option> { + let prefixed_key = self.get_prefixed_key(key); + sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, &prefixed_key) + } + + fn set(&mut self, key: &[u8], value: &[u8]) { + let prefixed_key = self.get_prefixed_key(key); + sp_io::offchain::local_storage_set(StorageKind::PERSISTENT, &prefixed_key, value); + } + + fn remove(&mut self, key: &[u8]) { + let prefixed_key = self.get_prefixed_key(key); + sp_io::offchain::local_storage_clear(StorageKind::PERSISTENT, &prefixed_key); + } + + fn contains(&mut self, key: &[u8]) -> bool { + self.get(key).is_some() + } + + fn compare_and_set(&mut self, key: &[u8], old_value: Option<&[u8]>, new_value: &[u8]) -> bool { + let prefixed_key = self.get_prefixed_key(key); + let old_value = old_value.map(|v| v.to_vec()); + sp_io::offchain::local_storage_compare_and_set(StorageKind::PERSISTENT, &prefixed_key, old_value, new_value) + } +} + +impl OffchainKv { + pub fn new(prefix: Option<&[u8]>) -> Self { + let default_prefix = b"default_prefix"; + let prefix = prefix.unwrap_or(default_prefix).to_vec(); + OffchainKv { prefix } + } +} \ No newline at end of file diff --git a/crates/das-db/src/offchain_outside.rs b/crates/das-db/src/offchain_outside.rs new file mode 100644 index 0000000..e32b80f --- /dev/null +++ b/crates/das-db/src/offchain_outside.rs @@ -0,0 +1,69 @@ +// Copyright 2023 ZeroDAO +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::traits::DasKv; + +use sc_client_api::Backend; +use sc_offchain::OffchainDb; +use sp_core::offchain::DbExternalities; +use sp_runtime::traits::Block; + +use sp_core::offchain::StorageKind; +// Implementation for the outside environment +pub struct OffchainKvOutside> { + db: OffchainDb, + prefix: Vec, +} + +impl> OffchainKvOutside { + fn get_prefixed_key(&self, key: &[u8]) -> Vec { + let mut prefixed_key = self.prefix.clone(); + prefixed_key.extend_from_slice(key); + prefixed_key + } +} + +impl> DasKv for OffchainKvOutside { + fn get(&mut self, key: &[u8]) -> Option> { + let prefixed_key = self.get_prefixed_key(key); + self.db.local_storage_get(StorageKind::PERSISTENT, &prefixed_key) + } + + fn set(&mut self, key: &[u8], value: &[u8]) { + let prefixed_key = self.get_prefixed_key(key); + self.db.local_storage_set(StorageKind::PERSISTENT, &prefixed_key, value); + } + + fn remove(&mut self, key: &[u8]) { + let prefixed_key = self.get_prefixed_key(key); + self.db.local_storage_clear(StorageKind::PERSISTENT, &prefixed_key); + } + + fn contains(&mut self, key: &[u8]) -> bool { + self.get(key).is_some() + } + + fn compare_and_set(&mut self, key: &[u8], old_value: Option<&[u8]>, new_value: &[u8]) -> bool { + let prefixed_key = self.get_prefixed_key(key); + self.db.local_storage_compare_and_set(StorageKind::PERSISTENT, &prefixed_key, old_value, new_value) + } +} + +impl> OffchainKvOutside { + pub fn new(db: OffchainDb, prefix: Option<&[u8]>) -> Self { + let default_prefix = b"default_prefix"; + let prefix = prefix.unwrap_or(default_prefix).to_vec(); + OffchainKvOutside { db, prefix } + } +} \ No newline at end of file diff --git a/crates/das-db/src/sqlite.rs b/crates/das-db/src/sqlite.rs new file mode 100644 index 0000000..4da3b61 --- /dev/null +++ b/crates/das-db/src/sqlite.rs @@ -0,0 +1,105 @@ +// Copyright 2023 ZeroDAO +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::traits::DasKv; +use rusqlite::{self, OptionalExtension}; + +use rusqlite::{params, Connection}; +use std::{ + path::PathBuf, + sync::{Arc, Mutex}, +}; + +pub struct SqliteDasDb { + conn: Arc>, +} + +impl SqliteDasDb { + pub fn new(db_path: &str) -> rusqlite::Result { + let conn = Connection::open(db_path)?; + conn.execute( + "CREATE TABLE IF NOT EXISTS kvs (key BLOB PRIMARY KEY, value BLOB NOT NULL)", + [], + )?; + Ok(Self { conn: Arc::new(Mutex::new(conn)) }) + } +} + +impl Default for SqliteDasDb { + fn default() -> Self { + let default_path = PathBuf::from("./default_db.sqlite3"); + Self::new(&default_path.to_str().unwrap()).unwrap() + } +} + +impl DasKv for SqliteDasDb { + fn get(&mut self, key: &[u8]) -> Option> { + let conn = self.conn.lock().unwrap(); + conn.query_row("SELECT value FROM kvs WHERE key = ?", params![key], |row| row.get(0)) + .optional() + .unwrap_or(None) + } + + fn set(&mut self, key: &[u8], value: &[u8]) { + let conn = self.conn.lock().unwrap(); + conn.execute("INSERT OR REPLACE INTO kvs (key, value) VALUES (?,?)", params![key, value]) + .unwrap(); + } + + fn remove(&mut self, key: &[u8]) { + let conn = self.conn.lock().unwrap(); + conn.execute("DELETE FROM kvs WHERE key = ?", params![key]).unwrap(); + } + + fn contains(&mut self, key: &[u8]) -> bool { + let conn = self.conn.lock().unwrap(); + let count: i64 = conn + .query_row("SELECT COUNT(*) FROM kvs WHERE key = ?", params![key], |row| row.get(0)) + .unwrap(); + count > 0 + } + + fn compare_and_set(&mut self, key: &[u8], old_value: Option<&[u8]>, new_value: &[u8]) -> bool { + let conn = self.conn.lock().unwrap(); + match old_value { + Some(old_val) => { + // Check if the current value matches the old value. + let current: Option> = conn.query_row("SELECT value FROM kvs WHERE key = ?", params![key], |row| row.get(0)) + .optional() + .unwrap_or(None); + if current.as_ref() == Some(&old_val.to_vec()) { + // If they match, update to the new value. + conn.execute("INSERT OR REPLACE INTO kvs (key, value) VALUES (?,?)", params![key, new_value]) + .unwrap(); + true + } else { + false + } + }, + None => { + let count: i64 = conn + .query_row("SELECT COUNT(*) FROM kvs WHERE key = ?", params![key], |row| row.get(0)) + .unwrap(); + if count == 0 { + conn.execute("INSERT OR REPLACE INTO kvs (key, value) VALUES (?,?)", params![key, new_value]) + .unwrap(); + true + } else { + false + } + }, + } + } + +} diff --git a/crates/das-db/src/traits.rs b/crates/das-db/src/traits.rs new file mode 100644 index 0000000..dc0b48a --- /dev/null +++ b/crates/das-db/src/traits.rs @@ -0,0 +1,68 @@ +// Copyright 2023 ZeroDAO +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +use crate::Vec; + +/// `DasKv` is a trait representing a key-value store interface. +pub trait DasKv { + /// Retrieves the value associated with the given key. + /// + /// # Arguments + /// + /// * `key` - A byte slice representing the key to look up. + /// + /// # Returns + /// + /// An `Option` containing the value associated with the key if it exists, or `None` if the key is not present. + fn get(&mut self, key: &[u8]) -> Option>; + + /// Sets a value for the given key in the store. + /// + /// # Arguments + /// + /// * `key` - A byte slice representing the key to set. + /// * `value` - A byte slice representing the value to associate with the key. + fn set(&mut self, key: &[u8], value: &[u8]); + + /// Removes the value associated with the given key from the store. + /// + /// # Arguments + /// + /// * `key` - A byte slice representing the key to remove. + fn remove(&mut self, key: &[u8]); + + /// Checks if the store contains the given key. + /// + /// # Arguments + /// + /// * `key` - A byte slice representing the key to check. + /// + /// # Returns + /// + /// `true` if the key is present in the store, `false` otherwise. + fn contains(&mut self, key: &[u8]) -> bool; + + /// Compares the current value of the given key with the specified old value and, if they match, sets the new value. + /// + /// # Arguments + /// + /// * `key` - A byte slice representing the key to compare and set. + /// * `old_value` - An `Option` containing a byte slice representing the expected current value of the key. + /// If `None`, it expects the key to not be present in the store. + /// * `new_value` - A byte slice representing the new value to set if the comparison succeeds. + /// + /// # Returns + /// + /// `true` if the comparison was successful and the value was set, `false` otherwise. + fn compare_and_set(&mut self, key: &[u8], old_value: Option<&[u8]>, new_value: &[u8]) -> bool; +} diff --git a/crates/das-primitives/Cargo.toml b/crates/das-primitives/Cargo.toml index 0303c6c..177d769 100644 --- a/crates/das-primitives/Cargo.toml +++ b/crates/das-primitives/Cargo.toml @@ -11,12 +11,11 @@ include = [ ] [lib] -# Necessary for CLI options to work on benches bench = false [dependencies] -rust-kzg-blst = { git = "https://github.com/ZeroDAO/rust-kzg", rev = "de872ad", default-features = false} -kzg = { git = "https://github.com/ZeroDAO/rust-kzg", rev = "de872ad", default-features = false} +rust-kzg-blst = { git = "https://github.com/ZeroDAO/rust-kzg.git", rev = "de872ad", default-features = false} +kzg = { git = "https://github.com/ZeroDAO/rust-kzg.git", rev = "de872ad", default-features = false} derive_more = "0.99.17" hex = { version = "0.4.3", default-features = false, features = ["alloc"] } diff --git a/crates/das-primitives/src/crypto/mod.rs b/crates/das-primitives/src/crypto/mod.rs index 68fcc1d..c414dc8 100644 --- a/crates/das-primitives/src/crypto/mod.rs +++ b/crates/das-primitives/src/crypto/mod.rs @@ -639,7 +639,7 @@ impl KZG { } } -#[derive(Debug, Default, Clone, PartialEq, Eq, From)] +#[derive(Debug, Default, Clone, PartialEq, Eq, From, Decode, Encode)] pub struct Position { pub x: u32, pub y: u32, diff --git a/crates/melo-erasure-coding/Cargo.toml b/crates/melo-erasure-coding/Cargo.toml index 3cad064..3fcda16 100644 --- a/crates/melo-erasure-coding/Cargo.toml +++ b/crates/melo-erasure-coding/Cargo.toml @@ -10,21 +10,20 @@ edition = "2021" targets = ["x86_64-unknown-linux-gnu"] [lib] -# Necessary for CLI options to work on benches bench = false [dependencies] melo-das-primitives = { default-features = false, version = "0.1.0", path = "../das-primitives"} -rust-kzg-blst = { git = "https://github.com/ZeroDAO/rust-kzg", rev = "de872ad", default-features = false } -kzg = { git = "https://github.com/ZeroDAO/rust-kzg", rev = "de872ad", default-features = false } +rust-kzg-blst = { git = "https://github.com/ZeroDAO/rust-kzg.git", rev = "de872ad", default-features = false } +kzg = { git = "https://github.com/ZeroDAO/rust-kzg.git", rev = "de872ad", default-features = false } derive_more = "0.99.17" [dev-dependencies] criterion = "0.4.0" rand = "0.8.5" -rust-kzg-blst = { git = "https://github.com/ZeroDAO/rust-kzg", rev = "de872ad", default-features = false, features = ["rand"] } +rust-kzg-blst = { git = "https://github.com/ZeroDAO/rust-kzg.git", rev = "de872ad", default-features = false, features = ["rand"] } [features] default = ["std","parallel"] @@ -33,4 +32,4 @@ std = [ "kzg/std", "melo-das-primitives/std", ] -parallel = ["rust-kzg-blst/parallel"] +parallel = ["rust-kzg-blst/parallel"] \ No newline at end of file diff --git a/crates/meloxt/Cargo.toml b/crates/meloxt/Cargo.toml index 8968c63..fb9319b 100644 --- a/crates/meloxt/Cargo.toml +++ b/crates/meloxt/Cargo.toml @@ -7,6 +7,7 @@ authors = ["DKLee "] edition = "2021" repository = "https://github.com/ZeroDAO/melodot" readme = "README.md" +build = "build.rs" # [workspace] @@ -39,4 +40,7 @@ primitive-types = { version = "0.12.1", default-features = false, features = ["c melo-core-primitives = { path = "../core-primitives" } melo-das-primitives = { version = "0.1.0", path = "../das-primitives"} -melo-das-rpc = { version = "0.0.1", path = "../das-rpc"} \ No newline at end of file +melo-das-rpc = { version = "0.0.1", path = "../das-rpc"} + +[build-dependencies] +substrate-build-script-utils = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } \ No newline at end of file diff --git a/crates/meloxt/build.rs b/crates/meloxt/build.rs new file mode 100644 index 0000000..0b10785 --- /dev/null +++ b/crates/meloxt/build.rs @@ -0,0 +1,7 @@ +use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed}; + +fn main() { + generate_cargo_keys(); + + rerun_if_git_head_changed(); +} \ No newline at end of file diff --git a/crates/meloxt/src/lib.rs b/crates/meloxt/src/lib.rs index 0eedb68..0c4047b 100644 --- a/crates/meloxt/src/lib.rs +++ b/crates/meloxt/src/lib.rs @@ -29,7 +29,7 @@ pub mod header; use header::MelodotHeader; mod log; -pub use log::init_logger; +pub use crate::log::init_logger; mod helper; pub use helper::*; @@ -105,4 +105,4 @@ impl Default for ClientBuilder { signer: dev::alice(), } } -} +} \ No newline at end of file diff --git a/node/Cargo.toml b/node/Cargo.toml index a69f660..265c62c 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -22,6 +22,7 @@ futures = { version = "0.3.21", features = ["thread-pool"]} jsonrpsee = { version = "0.16.3", features = ["server"] } array-bytes = "6.1" serde = { version = "1.0.163", features = ["derive"] } +hex-literal = "0.3.1" sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } sc-sync-state-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } diff --git a/node/src/chain_spec.rs b/node/src/chain_spec.rs index 6e9f9e9..3a568f8 100644 --- a/node/src/chain_spec.rs +++ b/node/src/chain_spec.rs @@ -1,6 +1,7 @@ //! Substrate chain configurations. use grandpa_primitives::AuthorityId as GrandpaId; +use hex_literal::hex; use melodot_runtime::{ config::{consensus::MaxNominations, currency::*}, wasm_binary_unwrap, AuthorityDiscoveryConfig, BabeConfig, BalancesConfig, Block, CouncilConfig, @@ -14,15 +15,15 @@ use sc_service::ChainType; use serde::{Deserialize, Serialize}; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_consensus_babe::AuthorityId as BabeId; -use sp_core::{sr25519, Pair, Public}; +use sp_core::{crypto::UncheckedInto, sr25519, Pair, Public}; use sp_runtime::{ traits::{IdentifyAccount, Verify}, Perbill, }; +pub use helper::*; pub use melodot_runtime::GenesisConfig; pub use node_primitives::{AccountId, Balance, Signature}; -pub use helper::*; type AccountPublic = ::Signer; @@ -59,7 +60,8 @@ pub fn testnet_genesis( endowed_accounts: Option>, ) -> GenesisConfig { let default_endowed_accounts = vec![ALICE, BOB, CHARLIE, DAVE, EVE, FERDIE]; - let mut endowed_accounts = endowed_accounts.unwrap_or_else(|| endow_accounts(&default_endowed_accounts)); + let mut endowed_accounts = + endowed_accounts.unwrap_or_else(|| endow_accounts(&default_endowed_accounts)); // endow all authorities and nominators. initial_authorities @@ -161,12 +163,7 @@ pub fn testnet_genesis( } fn development_config_genesis() -> GenesisConfig { - testnet_genesis( - authority_keys_from_seeds(&[ALICE]), - vec![], - sr25519_id(ALICE), - None, - ) + testnet_genesis(authority_keys_from_seeds(&[ALICE]), vec![], sr25519_id(ALICE), None) } /// Development config (single validator Alice) @@ -186,12 +183,7 @@ pub fn development_config() -> ChainSpec { } fn local_testnet_genesis() -> GenesisConfig { - testnet_genesis( - authority_keys_from_seeds(&[ALICE, BOB]), - vec![], - sr25519_id(ALICE), - None, - ) + testnet_genesis(authority_keys_from_seeds(&[ALICE, BOB]), vec![], sr25519_id(ALICE), None) } /// Local testnet config (multivalidator Alice + Bob) @@ -210,6 +202,56 @@ pub fn local_testnet_config() -> ChainSpec { ) } +fn overtrue_testnet_genesis() -> GenesisConfig { + // ./melodot-node key inspect "$secret"//$j//$i//stash; + // ./melodot-node key inspect "$secret"//$j//$i; + // ./melodot-node key inspect --scheme ed25519 "$secret"//$j//$i; + // ./melodot-node key inspect "$secret"//$j//$i; + let initial_authorities: Vec<( + AccountId, + AccountId, + GrandpaId, + BabeId, + ImOnlineId, + AuthorityDiscoveryId, + )> = vec![( + // 5DhXG4yusZ98m7Tfm3doqvasUD2en6omxtLPXsW2hdS4rCcK + hex!["4850a46ca0afedc00ad8239f903fe0348fc7f2dfb6af5100ef85f1d934871b1c"].into(), + // 5DoUdqyEZsgwsQ1YprLKDSGupMN1PVjTcgvP9jqHpTt5Mb2j + hex!["4cdb4797d1d237f7e7ea5207140a290bd16cc5df23a9dcfe7c6841e4a41a0358"].into(), + // 5DueQE9NG2GeRL4VQY5VpbyRweje5J6Wtiyre7vgvX6icMfL + hex!["518f9fedc6b65cee2bfbe750e8fd92b24266e1b624c6359730e63081233ebcd3"].unchecked_into(), + // 5FCRAaNfM8wuYg6jQBHryeCXZSG68eLvHLdAYA6eWxukrbsG + hex!["8a9679d0624a555c9c1088578b0c488b03c5150fe6c021f4968d338a6ebfb24b"].unchecked_into(), + // 5FCRAaNfM8wuYg6jQBHryeCXZSG68eLvHLdAYA6eWxukrbsG + hex!["8a9679d0624a555c9c1088578b0c488b03c5150fe6c021f4968d338a6ebfb24b"].unchecked_into(), + // 5FCRAaNfM8wuYg6jQBHryeCXZSG68eLvHLdAYA6eWxukrbsG + hex!["8a9679d0624a555c9c1088578b0c488b03c5150fe6c021f4968d338a6ebfb24b"].unchecked_into(), + )]; + testnet_genesis( + initial_authorities, + vec![], + // 5F1NhF2fdsvBwFxAhQga9WjB344ECAJ8hDQJ99p1gWqpuzY1 + hex!["822a75157ca69ee2ef0c04d9b7c45e5532edc87a4bc642ab531155df665b7266"].into(), + Some(vec![hex!["822a75157ca69ee2ef0c04d9b7c45e5532edc87a4bc642ab531155df665b7266"].into()]), + ) +} + +pub fn overtrue_testnet_config() -> ChainSpec { + ChainSpec::from_genesis( + "Overtrue Testnet", + "overtrue_testnet", + ChainType::Live, + overtrue_testnet_genesis, + vec![], + None, + None, + None, + None, + Default::default(), + ) +} + mod helper { use super::*; @@ -221,7 +263,7 @@ mod helper { ) -> SessionKeys { SessionKeys { grandpa, babe, im_online, authority_discovery } } - + // Constants for default seeds and values pub const ALICE: &str = "Alice"; pub const BOB: &str = "Bob"; @@ -229,17 +271,17 @@ mod helper { pub const DAVE: &str = "Dave"; pub const EVE: &str = "Eve"; pub const FERDIE: &str = "Ferdie"; - + pub const ENDOWMENT: Balance = 10_000_000 * DOLLARS; pub const STASH: Balance = ENDOWMENT / 1000; - + /// Generates a public key from a seed. pub fn get_from_seed(seed: &str) -> ::Public { TPublic::Pair::from_string(&format!("//{}", seed), None) .expect("static values are valid; qed") .public() } - + /// Generates an account ID from a seed. pub fn account_id_from_seed(seed: &str) -> AccountId where @@ -252,19 +294,20 @@ mod helper { pub fn sr25519_id(key: &str) -> AccountId { account_id_from_seed::(key) } - + /// Endows a list of accounts with the default balance. pub fn endow_accounts(accounts: &[&str]) -> Vec { - accounts.iter() + accounts + .iter() .flat_map(|&x| { vec![ account_id_from_seed::(x), - account_id_from_seed::(&format!("{}//stash", x)) + account_id_from_seed::(&format!("{}//stash", x)), ] }) .collect() } - + /// Helper function to generate stash, controller and session key from seed pub fn authority_keys_from_seed( seed: &str, @@ -278,7 +321,7 @@ mod helper { get_from_seed::(seed), ) } - + pub fn authority_keys_from_seeds( seeds: &[&str], ) -> Vec<(AccountId, AccountId, GrandpaId, BabeId, ImOnlineId, AuthorityDiscoveryId)> { diff --git a/node/src/cli.rs b/node/src/cli.rs index 3f95e8d..e41260c 100644 --- a/node/src/cli.rs +++ b/node/src/cli.rs @@ -7,20 +7,6 @@ pub struct Cli { #[clap(flatten)] pub run: RunCmd, - - /// Disable automatic hardware benchmarks. - /// - /// By default these benchmarks are automatically ran at startup and measure - /// the CPU speed, the memory bandwidth and the disk speed. - /// - /// The results are then printed out in the logs, and also sent as part of - /// telemetry, if telemetry is enabled. - #[arg(long)] - pub no_hardware_benchmarks: bool, - - #[allow(missing_docs)] - #[clap(flatten)] - pub storage_monitor: sc_storage_monitor::StorageMonitorParams, } #[derive(Debug, clap::Subcommand)] diff --git a/node/src/command.rs b/node/src/command.rs index b6928ec..05905b9 100644 --- a/node/src/command.rs +++ b/node/src/command.rs @@ -46,6 +46,7 @@ impl SubstrateCli for Cli { .into(), ) }, + "overtrue" => Box::new(chain_spec::overtrue_testnet_config()), "dev" => Box::new(chain_spec::development_config()), "local" => Box::new(chain_spec::local_testnet_config()), path => { @@ -214,7 +215,7 @@ pub fn run() -> sc_cli::Result<()> { None => { let runner = cli.create_runner(&cli.run)?; runner.run_node_until_exit(|config| async move { - service::new_full(config, cli).map_err(sc_cli::Error::Service) + service::new_full(config).map_err(sc_cli::Error::Service) }) }, } diff --git a/node/src/service.rs b/node/src/service.rs index 8f0e212..91cb90c 100644 --- a/node/src/service.rs +++ b/node/src/service.rs @@ -1,7 +1,6 @@ //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. #![warn(unused_extern_crates)] -use crate::cli::Cli; use futures::channel::mpsc::Receiver; use futures::prelude::*; use grandpa::SharedVoterState; @@ -12,13 +11,9 @@ use melodot_runtime::{self, NodeBlock as Block, RuntimeApi}; use sc_client_api::BlockBackend; use sc_consensus_babe::{self, SlotProportion}; pub use sc_executor::NativeElseWasmExecutor; -use sc_network::{event::Event, NetworkEventStream, NetworkService}; -use sc_network_sync::SyncingService; -use sc_service::{ - error::Error as ServiceError, Configuration, RpcHandlers, TaskManager, WarpSyncParams, -}; +use sc_network::{event::Event, NetworkEventStream}; +use sc_service::{error::Error as ServiceError, Configuration, TaskManager, WarpSyncParams}; use sc_telemetry::{Telemetry, TelemetryWorker}; -use sp_runtime::traits::Block as BlockT; use std::{sync::Arc, time::Duration}; use crate::rpc as melo_rpc; @@ -47,7 +42,6 @@ type FullBackend = sc_service::TFullBackend; pub(crate) type FullClient = sc_service::TFullClient>; type FullSelectChain = sc_consensus::LongestChain; -pub type TransactionPool = sc_transaction_pool::FullPool; type FullGrandpaBlockImport = grandpa::GrandpaBlockImport; @@ -218,30 +212,8 @@ pub fn new_partial( }) } -/// Result of [`new_full_base`]. -pub struct NewFullBase { - /// The task manager of the node. - pub task_manager: TaskManager, - /// The client instance of the node. - pub client: Arc, - /// The networking service of the node. - pub network: Arc::Hash>>, - /// The syncing service of the node. - pub sync: Arc>, - /// The transaction pool of the node. - pub transaction_pool: Arc, - /// The rpc handlers of the node. - pub rpc_handlers: RpcHandlers, -} - /// Builds a new service for a full client. -pub fn new_full_base( - mut config: Configuration, - with_startup_data: impl FnOnce( - &sc_consensus_babe::BabeBlockImport, - &sc_consensus_babe::BabeLink, - ), -) -> Result { +pub fn new_full(mut config: Configuration) -> Result { let sc_service::PartialComponents { client, backend, @@ -260,8 +232,6 @@ pub fn new_full_base( let (block_import, grandpa_link, babe_link) = import_setup; - (with_startup_data)(&block_import, &babe_link); - let auth_disc_publish_non_global_ips = config.network.allow_non_globals_in_dht; config @@ -321,14 +291,20 @@ pub fn new_full_base( } }); - let dht_worker = - new_worker(client.clone(), network.clone(), backend.clone(), dht_receiver, Box::pin(dht_event_stream)).expect("Failed to create DHT worker"); + let dht_worker = new_worker( + client.clone(), + network.clone(), + backend.clone(), + dht_receiver, + Box::pin(dht_event_stream), + ) + .expect("Failed to create DHT worker"); task_manager .spawn_essential_handle() .spawn("dht-worker", None, dht_worker.run(|| {})); - let rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { + let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { network: network.clone(), client: client.clone(), keystore: keystore_container.keystore(), @@ -471,29 +447,5 @@ pub fn new_full_base( } network_starter.start_network(); - Ok(NewFullBase { - task_manager, - client, - network, - sync: sync_service, - transaction_pool, - rpc_handlers, - }) - // Ok(task_manager) -} - -/// Builds a new service for a full client. -pub fn new_full(config: Configuration, cli: Cli) -> Result { - let database_source = config.database.clone(); - let task_manager = - new_full_base(config, |_, _| ()).map(|NewFullBase { task_manager, .. }| task_manager)?; - - sc_storage_monitor::StorageMonitorService::try_spawn( - cli.storage_monitor, - database_source, - &task_manager.spawn_essential_handle(), - ) - .map_err(|e| ServiceError::Application(e.into()))?; - Ok(task_manager) } diff --git a/runtime/build.rs b/runtime/build.rs index c03d618..af6a69c 100644 --- a/runtime/build.rs +++ b/runtime/build.rs @@ -1,10 +1,10 @@ fn main() { #[cfg(feature = "std")] { - substrate_wasm_builder::WasmBuilder::new() - .with_current_project() - .export_heap_base() - .import_memory() - .build(); + // substrate_wasm_builder::WasmBuilder::new() + // .with_current_project() + // .export_heap_base() + // .import_memory() + // .build(); } } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index fb86200..7082450 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "stable-2023-08-24" -components = ["rustfmt", "clippy", "llvm-tools-preview"] +channel = "nightly-2023-10-10" +components = ["rustfmt", "clippy", "llvm-tools"] profile = "minimal" targets = ["wasm32-unknown-unknown"] \ No newline at end of file diff --git a/scripts/docker_run.sh b/scripts/docker_run.sh index 65ec02f..3f9c601 100755 --- a/scripts/docker_run.sh +++ b/scripts/docker_run.sh @@ -6,42 +6,46 @@ echo "*** Melodot ***" cd $(dirname ${BASH_SOURCE[0]})/.. +# Ensure the .local directory exists +if [ ! -d "./.local" ]; then + mkdir ./.local +fi + # Get the arguments passed to the script cmd=$1 crate=$2 -if [ "$cmd" != "new" ]; then - docker-compose down --remove-orphans - docker-compose run --rm --name melodot --service-ports dev $@ -else +if [ "$cmd" == "new" ]; then docker exec -it melodot bash + exit 0 fi +docker compose down --remove-orphans + # Check if the crate parameter is provided if [ -z "$crate" ]; then - docker-compose run --rm --service-ports dev $@ -else - # Define a function to execute different commands - execute_command() { - crate_name="$1" - cd "crates/$crate_name" - case "$cmd" in - "build") - cargo build - ;; - "test") - cargo test - ;; - # You can add more command options here - *) - echo "Unknown command: $cmd" - exit 1 - ;; - esac - } - - # Call the function to execute the command - execute_command "$crate" - - read -p "$cmd completed. Press Enter to exit..." + docker compose run --rm --name melodot --service-ports dev $@ + exit 0 fi + +# Define a function to execute different commands +execute_command() { + crate_name="$1" + cd "crates/$crate_name" + case "$cmd" in + "build") + cargo build + ;; + "test") + cargo test + ;; + # You can add more command options here + *) + echo "Unknown command: $cmd" + exit 1 + ;; + esac +} + +# Call the function to execute the command +execute_command "$crate" \ No newline at end of file diff --git a/scripts/init.sh b/scripts/init.sh index 0e4b80e..f2f68a3 100755 --- a/scripts/init.sh +++ b/scripts/init.sh @@ -4,11 +4,11 @@ set -e echo "*** Initializing WASM build environment" -# if [ -z $CI_PROJECT_NAME ] ; then -# rustup update nightly -# rustup update stable -# fi +if [ -z $CI_PROJECT_NAME ] ; then + rustup update nightly + rustup update stable +fi -rustup default nightly-2023-08-26 +rustup default -rustup target add wasm32-unknown-unknown --toolchain nightly-2023-08-26 +rustup target add wasm32-unknown-unknown --toolchain nightly \ No newline at end of file