diff --git a/Cargo.lock b/Cargo.lock index 44ab86cb84..016d22ce0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -508,6 +508,12 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" +[[package]] +name = "beef" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "474a626a67200bd107d44179bb3d4fc61891172d11696609264589be6a0e6a43" + [[package]] name = "bit-set" version = "0.5.2" @@ -626,18 +632,19 @@ checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" [[package]] name = "candid" -version = "0.5.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3928acd8e9b66774a2eb21ad675e827f6723058163347f18b1d967e02637d86" +checksum = "15f6e879d53af7853a2d8ec7fd7d786bbf363a1535296542b957e67592f229dc" dependencies = [ - "base32", "byteorder", "candid_derive", - "crc32fast", + "codespan-reporting", "hex", + "ic-types", "lalrpop", "lalrpop-util", "leb128", + "logos", "num-bigint", "num-traits", "num_enum", @@ -648,9 +655,9 @@ dependencies = [ [[package]] name = "candid_derive" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a51d65ed24b5b03624aefc86967af49039882d63161a67aef0dd4306f7251330" +checksum = "ab31ccaf3ab1184bab4a139afb0d23c3aa54144d4a92ef0d0de7653cad4f679f" dependencies = [ "proc-macro2 1.0.19", "quote 1.0.7", @@ -725,6 +732,16 @@ dependencies = [ "bitflags", ] +[[package]] +name = "codespan-reporting" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e0762455306b1ed42bc651ef6a2197aabda5e1d4a43c34d5eab5c1a3634e81d" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "colored" version = "1.9.3" @@ -1675,7 +1692,7 @@ dependencies = [ [[package]] name = "ic-agent" version = "0.1.0" -source = "git+ssh://git@github.com/dfinity-lab/agent-rust.git?branch=next#e61e646c7a810c13c1b3d898d1d2ed7366b67a0a" +source = "git+ssh://git@github.com/dfinity-lab/agent-rust.git?branch=next#35a0f9851cf8cceea34acf405ba50c84ab5fbc5e" dependencies = [ "async-trait", "base32", @@ -1702,8 +1719,8 @@ dependencies = [ [[package]] name = "ic-types" -version = "0.1.0" -source = "git+ssh://git@github.com/dfinity-lab/agent-rust.git?branch=next#e61e646c7a810c13c1b3d898d1d2ed7366b67a0a" +version = "0.1.1" +source = "git+ssh://git@github.com/dfinity-lab/agent-rust.git?branch=next#35a0f9851cf8cceea34acf405ba50c84ab5fbc5e" dependencies = [ "base32", "crc32fast", @@ -1964,6 +1981,30 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "logos" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91c49573597a5d6c094f9031617bb1fed15c0db68c81e6546d313414ce107e4" +dependencies = [ + "logos-derive", +] + +[[package]] +name = "logos-derive" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "797b1f8a0571b331c1b47e7db245af3dc634838da7a92b3bef4e30376ae1c347" +dependencies = [ + "beef", + "fnv", + "proc-macro2 1.0.19", + "quote 1.0.7", + "regex-syntax", + "syn 1.0.38", + "utf8-ranges", +] + [[package]] name = "lru-cache" version = "0.1.2" @@ -3896,6 +3937,12 @@ dependencies = [ "percent-encoding 2.1.0", ] +[[package]] +name = "utf8-ranges" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" + [[package]] name = "v_escape" version = "0.7.4" diff --git a/Cargo.toml b/Cargo.toml index 23380a657d..eaa1d3163d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,3 +2,6 @@ members = [ "src/dfx", ] + +[patch.crates-io] +ic-types = { git = "ssh://git@github.com/dfinity-lab/agent-rust.git", branch = "next", version = "0.1.1" } diff --git a/assets.nix b/assets.nix index a519a789ec..6a419d45d3 100644 --- a/assets.nix +++ b/assets.nix @@ -8,7 +8,6 @@ pkgs.runCommandNoCCLocal "assets" {} '' cp ${pkgs.dfinity.ic-replica}/bin/replica $out cp ${pkgs.dfinity.ic-starter}/bin/ic-starter $out cp -R ${pkgs.motoko.base-src} $out/base - cp ${pkgs.motoko.didc}/bin/didc $out cp ${pkgs.motoko.mo-doc}/bin/mo-doc $out cp ${pkgs.motoko.mo-ide}/bin/mo-ide $out cp ${pkgs.motoko.moc}/bin/moc $out diff --git a/distributed-canisters.nix b/distributed-canisters.nix index 91d41d19a0..9d334c36c2 100644 --- a/distributed-canisters.nix +++ b/distributed-canisters.nix @@ -6,7 +6,7 @@ let in pkgs.runCommandNoCCLocal "distributed-canisters" { - inherit (pkgs.motoko) didc rts; + inherit (pkgs.motoko) rts; moc = pkgs.motoko.moc; base = pkgs.motoko.base-src; } '' diff --git a/e2e/bats/assetscanister.bash b/e2e/bats/assetscanister.bash index 99d0775538..9dba0de47e 100644 --- a/e2e/bats/assetscanister.bash +++ b/e2e/bats/assetscanister.bash @@ -21,11 +21,11 @@ teardown() { dfx build dfx canister install e2e_project_assets - assert_command dfx canister call --query e2e_project_assets retrieve '("binary/noise.txt")' - assert_eq '(vec { 184; 1; 32; 128; 10; 119; 49; 50; 32; 0; 120; 121; 10; 75; 76; 11; 10; 106; 107; })' + assert_command dfx canister call --query e2e_project_assets retrieve '("binary/noise.txt")' --output idl + assert_eq '(vec { 184; 1; 32; 128; 10; 119; 49; 50; 32; 0; 120; 121; 10; 75; 76; 11; 10; 106; 107 })' - assert_command dfx canister call --query e2e_project_assets retrieve '("text-with-newlines.txt")' - assert_eq '(vec { 99; 104; 101; 114; 114; 105; 101; 115; 10; 105; 116; 39; 115; 32; 99; 104; 101; 114; 114; 121; 32; 115; 101; 97; 115; 111; 110; 10; 67; 72; 69; 82; 82; 73; 69; 83; })' + assert_command dfx canister call --query e2e_project_assets retrieve '("text-with-newlines.txt")' --output idl + assert_eq '(vec { 99; 104; 101; 114; 114; 105; 101; 115; 10; 105; 116; 39; 115; 32; 99; 104; 101; 114; 114; 121; 32; 115; 101; 97; 115; 111; 110; 10; 67; 72; 69; 82; 82; 73; 69; 83 })' assert_command dfx canister call --update e2e_project_assets store '("AA", vec { 100; 107; 62; 9; })' assert_eq '()' @@ -33,13 +33,13 @@ teardown() { assert_eq '()' assert_command dfx canister call --query e2e_project_assets retrieve '("B")' - assert_eq '(vec { 88; 87; 86; })' + assert_eq '(vec { 88; 87; 86 })' assert_command dfx canister call --query e2e_project_assets retrieve '("AA")' - assert_eq '(vec { 100; 107; 62; 9; })' + assert_eq '(vec { 100; 107; 62; 9 })' assert_command dfx canister call --query e2e_project_assets retrieve '("B")' - assert_eq '(vec { 88; 87; 86; })' + assert_eq '(vec { 88; 87; 86 })' assert_command_fail dfx canister call --query e2e_project_assets retrieve '("C")' diff --git a/e2e/bats/basic-project.bash b/e2e/bats/basic-project.bash index b84fe66b27..e9294ff561 100644 --- a/e2e/bats/basic-project.bash +++ b/e2e/bats/basic-project.bash @@ -90,8 +90,8 @@ teardown() { dfx build dfx canister install --all - assert_command dfx canister call hello inc '(42,false,"testzZ",vec{1;2;3},opt record{head=42; tail=opt record{head=+43; tail=null}}, variant { cons=record{ 42; variant { cons=record{43; variant { nil }} } } })' - assert_eq "(43, true, \"uftu{[\", vec { 2; 3; 4; }, opt record { head = 43; tail = opt record { head = 44; tail = null; }; }, variant { cons = record { 0 = 43; 1 = variant { cons = record { 0 = 44; 1 = variant { nil = null }; } }; } })" + assert_command dfx canister call hello inc '(42,false,"testzZ",vec{1;2;3},opt record{head=42; tail=opt record{head=+43; tail=null}}, variant { cons=record{ 42; variant { cons=record{43; variant { nil }} } } })' --output idl + assert_eq "(43, true, \"uftu{[\", vec { 2; 3; 4 }, opt record { head = 43; tail = opt record { head = 44; tail = null } }, variant { cons = record { 43; variant { cons = record { 44; variant { nil } } } } })" } @test "build + install + call -- matrix_multiply_mo" { @@ -102,5 +102,5 @@ teardown() { dfx canister install --all assert_command dfx canister call hello multiply '(vec{vec{1;2};vec{3;4};vec{5;6}},vec{vec{1;2;3};vec{4;5;6}})' - assert_eq "(vec { vec { 9; 12; 15; }; vec { 19; 26; 33; }; vec { 29; 40; 51; }; })" + assert_eq "(vec { vec { 9; 12; 15 }; vec { 19; 26; 33 }; vec { 29; 40; 51 } })" } diff --git a/e2e/bats/build_granular.bash b/e2e/bats/build_granular.bash index a56e6d4dda..c95f5cf641 100644 --- a/e2e/bats/build_granular.bash +++ b/e2e/bats/build_granular.bash @@ -65,11 +65,11 @@ teardown() { dfx build e2e_project_assets dfx canister install e2e_project_assets - assert_command dfx canister call --query e2e_project_assets retrieve '("binary/noise.txt")' - assert_eq '(vec { 184; 1; 32; 128; 10; 119; 49; 50; 32; 0; 120; 121; 10; 75; 76; 11; 10; 106; 107; })' + assert_command dfx canister call --query e2e_project_assets retrieve '("binary/noise.txt")' --output idl + assert_eq '(vec { 184; 1; 32; 128; 10; 119; 49; 50; 32; 0; 120; 121; 10; 75; 76; 11; 10; 106; 107 })' - assert_command dfx canister call --query e2e_project_assets retrieve '("text-with-newlines.txt")' - assert_eq '(vec { 99; 104; 101; 114; 114; 105; 101; 115; 10; 105; 116; 39; 115; 32; 99; 104; 101; 114; 114; 121; 32; 115; 101; 97; 115; 111; 110; 10; 67; 72; 69; 82; 82; 73; 69; 83; })' + assert_command dfx canister call --query e2e_project_assets retrieve '("text-with-newlines.txt")' --output idl + assert_eq '(vec { 99; 104; 101; 114; 114; 105; 101; 115; 10; 105; 116; 39; 115; 32; 99; 104; 101; 114; 114; 121; 32; 115; 101; 97; 115; 111; 110; 10; 67; 72; 69; 82; 82; 73; 69; 83 })' } diff --git a/e2e/bats/identity.bash b/e2e/bats/identity.bash index 87495e1ac9..7bbe614717 100644 --- a/e2e/bats/identity.bash +++ b/e2e/bats/identity.bash @@ -70,16 +70,16 @@ teardown() { assert_eq '(false)' # these all fail (other identities are not initializer; cannot store assets): - assert_command_fail dfx --identity bob canister call e2e_project_assets store '("B", vec { 88; 87; 86; })' - assert_command_fail dfx --identity default canister call e2e_project_assets store '("B", vec { 88; 87; 86; })' - assert_command_fail dfx canister call e2e_project_assets store '("B", vec { 88; 87; 86; })' + assert_command_fail dfx --identity bob canister call e2e_project_assets store '("B", vec { 88; 87; 86 })' + assert_command_fail dfx --identity default canister call e2e_project_assets store '("B", vec { 88; 87; 86 })' + assert_command_fail dfx canister call e2e_project_assets store '("B", vec { 88; 87; 86 })' assert_command_fail dfx canister call e2e_project_assets retrieve '("B")' # but alice, the initializer, can store assets: - assert_command dfx --identity alice canister call e2e_project_assets store '("B", vec { 88; 87; 86; })' + assert_command dfx --identity alice canister call e2e_project_assets store '("B", vec { 88; 87; 86 })' assert_eq '()' assert_command dfx canister call e2e_project_assets retrieve '("B")' - assert_eq '(vec { 88; 87; 86; })' + assert_eq '(vec { 88; 87; 86 })' } @test "after renaming an identity, the renamed identity is still initializer" { @@ -102,8 +102,8 @@ teardown() { assert_command dfx --identity bob canister call e2e_project amInitializer assert_eq '(true)' - assert_command dfx --identity bob canister call e2e_project_assets store '("B", vec { 40; 67; })' + assert_command dfx --identity bob canister call e2e_project_assets store '("B", vec { 40; 67 })' assert_eq '()' assert_command dfx canister call e2e_project_assets retrieve '("B")' - assert_eq '(vec { 40; 67; })' + assert_eq '(vec { 40; 67 })' } diff --git a/src/dfx/Cargo.toml b/src/dfx/Cargo.toml index 215bd673d5..c9b13f0fa1 100644 --- a/src/dfx/Cargo.toml +++ b/src/dfx/Cargo.toml @@ -21,7 +21,7 @@ actix-server = "0.6.1" actix-web = { version = "1.0.8", features = [ "default", "openssl", "ssl" ] } atty = "0.2.13" base64 = "0.11.0" -candid = "0.5.2" +candid = "0.6.0" chrono = "0.4.9" clap = "2.33.0" console = "0.7.7" @@ -69,14 +69,13 @@ wasmparser = "0.45.0" version = "0.1.0" git = "ssh://git@github.com/dfinity-lab/agent-rust.git" branch = "next" -rev = "e61e646c7a810c13c1b3d898d1d2ed7366b67a0a" +rev = "35a0f9851cf8cceea34acf405ba50c84ab5fbc5e" [dependencies.ic-types] -version = "0.1.0" +version = "0.1.1" git = "ssh://git@github.com/dfinity-lab/agent-rust.git" branch = "next" -rev = "e61e646c7a810c13c1b3d898d1d2ed7366b67a0a" - +rev = "35a0f9851cf8cceea34acf405ba50c84ab5fbc5e" [dev-dependencies] env_logger = "0.6" diff --git a/src/dfx/src/commands/canister/call.rs b/src/dfx/src/commands/canister/call.rs index 3f461f34c1..be26401aba 100644 --- a/src/dfx/src/commands/canister/call.rs +++ b/src/dfx/src/commands/canister/call.rs @@ -60,7 +60,7 @@ pub fn construct() -> App<'static, 'static> { .long("output") .takes_value(true) .conflicts_with("async") - .possible_values(&["idl", "raw"]), + .possible_values(&["idl", "raw", "pp"]), ) .arg( Arg::with_name("argument") diff --git a/src/dfx/src/lib/models/canister.rs b/src/dfx/src/lib/models/canister.rs index 622f27df79..0fbcfade8e 100644 --- a/src/dfx/src/lib/models/canister.rs +++ b/src/dfx/src/lib/models/canister.rs @@ -1,4 +1,3 @@ -use crate::config::cache::Cache; use crate::config::dfinity::Config; use crate::lib::builders::{ BuildConfig, BuildOutput, BuilderPool, CanisterBuilder, IdlBuildOutput, WasmBuildOutput, @@ -7,7 +6,7 @@ use crate::lib::canister_info::CanisterInfo; use crate::lib::environment::Environment; use crate::lib::error::{BuildErrorKind, DfxError, DfxResult}; use crate::lib::models::canister_id_store::CanisterIdStore; -use crate::util::assets; +use crate::util::{assets, check_candid_file}; use ic_types::principal::Principal as CanisterId; use petgraph::graph::{DiGraph, NodeIndex}; use rand::{thread_rng, Rng, RngCore}; @@ -89,7 +88,6 @@ impl Canister { pub struct CanisterPool { canisters: Vec>, logger: Logger, - cache: Arc, } struct PoolConstructHelper<'a> { @@ -195,7 +193,6 @@ impl CanisterPool { Ok(CanisterPool { canisters: canisters_map, logger, - cache: env.get_cache().clone(), }) } @@ -331,7 +328,7 @@ impl CanisterPool { .map(|_| {}) .map_err(DfxError::from)?; - build_canister_js(self.cache.clone(), &canister.canister_id(), &canister.info)?; + build_canister_js(&canister.canister_id(), &canister.info)?; canister.postbuild(self, build_config) } @@ -440,35 +437,15 @@ fn decode_path_to_str(path: &Path) -> DfxResult<&str> { } /// Create a canister JavaScript DID and Actor Factory. -fn build_canister_js( - cache: Arc, - canister_id: &CanisterId, - canister_info: &CanisterInfo, -) -> DfxResult { +fn build_canister_js(canister_id: &CanisterId, canister_info: &CanisterInfo) -> DfxResult { let output_did_js_path = canister_info.get_build_idl_path().with_extension("did.js"); let output_canister_js_path = canister_info.get_build_idl_path().with_extension("js"); - let mut cmd = cache.get_binary_command("didc")?; - let cmd = cmd - .arg("--js") - .arg(&canister_info.get_build_idl_path()) - .arg("-o") - .arg(&output_did_js_path); - - let output = cmd.output()?; - if !output.status.success() { - return Err(DfxError::BuildError(BuildErrorKind::CompilerError( - format!("{:?}", cmd), - String::from_utf8_lossy(&output.stdout).to_string(), - String::from_utf8_lossy(&output.stderr).to_string(), - ))); - } else if !output.stderr.is_empty() { - // Cannot use eprintln, because it would interfere with the progress bar. - println!("{}", String::from_utf8_lossy(&output.stderr)); - } + let (env, ty) = check_candid_file(&canister_info.get_build_idl_path())?; + let content = candid::bindings::javascript::compile(&env, &ty); + std::fs::write(output_did_js_path, content)?; let mut language_bindings = assets::language_bindings()?; - for f in language_bindings.entries()? { let mut file = f?; let mut file_contents = String::new(); diff --git a/src/dfx/src/util/mod.rs b/src/dfx/src/util/mod.rs index 6a10cc39b2..09260e13ed 100644 --- a/src/dfx/src/util/mod.rs +++ b/src/dfx/src/util/mod.rs @@ -12,13 +12,13 @@ pub fn print_idl_blob( output_type: Option<&str>, method_type: &Option<(TypeEnv, Function)>, ) -> DfxResult<()> { - let output_type = output_type.unwrap_or("idl"); + let output_type = output_type.unwrap_or("pp"); match output_type { "raw" => { let hex_string = hex::encode(blob); println!("{}", hex_string); } - "idl" => { + "idl" | "pp" => { let result = match method_type { None => candid::IDLArgs::from_bytes(blob), Some((env, func)) => candid::IDLArgs::from_bytes_with_types(blob, &env, &func.rets), @@ -27,7 +27,14 @@ pub fn print_idl_blob( let hex_string = hex::encode(blob); eprintln!("Error deserializing blob 0x{}", hex_string); } - println!("{}", result?); + if output_type == "idl" { + println!( + "{}", + candid::parser::value::pretty::pp_args(&result?).pretty(usize::MAX) + ); + } else { + println!("{}", result?); + } } v => return Err(DfxError::Unknown(format!("Invalid output type: {}", v))), } @@ -49,7 +56,7 @@ pub fn get_candid_type( pub fn check_candid_file(idl_path: &std::path::Path) -> DfxResult<(TypeEnv, Option)> { let idl_file = std::fs::read_to_string(idl_path)?; - let ast = idl_file.parse::()?; + let ast = candid::pretty_parse::(&idl_path.to_string_lossy(), &idl_file)?; let mut env = TypeEnv::new(); let actor = check_prog(&mut env, &ast)?; Ok((env, actor)) @@ -70,39 +77,37 @@ pub fn blob_from_arguments( } "idl" => { let arguments = arguments.unwrap_or("()"); - let args: DfxResult = - arguments.parse::().map_err(|e: candid::Error| { - DfxError::InvalidArgument(format!("Invalid Candid values: {}", e)) - }); let typed_args = match method_type { None => { eprintln!("cannot find method type, dfx will send message with inferred type"); - args?.to_bytes() + candid::pretty_parse::("Candid argument", &arguments) + .map_err(|e| { + DfxError::InvalidArgument(format!("Invalid Candid values: {}", e)) + })? + .to_bytes() } Some((env, func)) => { let first_char = arguments.chars().next(); let is_candid_format = first_char.map_or(false, |c| c == '('); // If parsing fails and method expects a single value, try parsing as IDLValue. // If it still fails, and method expects a text type, send arguments as text. - let args = args.or_else(|e| { + let args = arguments.parse::().or_else(|_| { if func.args.len() == 1 && !is_candid_format { let is_quote = first_char.map_or(false, |c| c == '"'); if candid::types::Type::Text == func.args[0] && !is_quote { Ok(IDLValue::Text(arguments.to_string())) } else { - arguments.parse::().map_err(|e| { - DfxError::InvalidArgument(format!( - "Invalid Candid values: {}", - e - )) - }) + candid::pretty_parse::("Candid argument", &arguments) } .map(|v| IDLArgs::new(&[v])) } else { - Err(e) + candid::pretty_parse::("Candid argument", &arguments) } }); - args?.to_bytes_with_types(&env, &func.args) + args.map_err(|e| { + DfxError::InvalidArgument(format!("Invalid Candid values: {}", e)) + })? + .to_bytes_with_types(&env, &func.args) } } .map_err(|e| {