Skip to content

Commit 5fd6593

Browse files
committed
Merge BlockstreamResearch#180: feature(simc): flag for json output
55e7fd8 feature(simc): flag for json output (Byron Hambly) Pull request description: re: BlockstreamResearch#179 Adds a `--json` flag to simc to output the resulting program/witness as JSON ACKs for top commit: apoelstra: ACK 55e7fd8; successfully ran local tests; though we should really rewrite and refactor this main function sometime.. Tree-SHA512: dd0a617697addb5a488a9639e1ce0a3363d9da7a5f1905105e5e1a58d8047f4349ecde32f28187a288faf03f19df364e5c6b091b1f6efd0a1aec13a207bed481
2 parents ffccd85 + 55e7fd8 commit 5fd6593

2 files changed

Lines changed: 79 additions & 57 deletions

File tree

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,13 @@ The SimplicityHL compiler takes two arguments:
6363
The compiler produces a base64-encoded Simplicity program. Witness data will be included if a witness file is provided.
6464

6565
```bash
66-
./target/debug/simc examples/test.simf examples/test.wit
66+
./target/debug/simc examples/p2pkh.simf examples/p2pkh.wit
67+
```
68+
69+
Produce JSON output with the `--json` flag.
70+
71+
```bash
72+
./target/debug/simc examples/p2pkh.simf examples/p2pkh.wit --json
6773
```
6874

6975
### VSCode extension

src/main.rs

Lines changed: 72 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,28 @@ use base64::engine::general_purpose::STANDARD;
33
use clap::{Arg, ArgAction, Command};
44

55
use simplicityhl::{Arguments, CompiledProgram};
6-
use std::env;
6+
use std::{env, fmt};
77

8-
// Directly returning Result<(), String> prints the error using Debug
9-
// Add indirection via run() to print errors using Display
10-
fn main() {
11-
if let Err(error) = run() {
12-
eprintln!("{error}");
13-
std::process::exit(1);
8+
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
9+
/// The compilation output.
10+
struct Output {
11+
/// Simplicity program result, base64 encoded.
12+
program: String,
13+
/// Simplicity witness result, base64 encoded, if the .wit file was provided.
14+
witness: Option<String>,
15+
}
16+
17+
impl fmt::Display for Output {
18+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19+
writeln!(f, "Program:\n{}", self.program)?;
20+
if let Some(witness) = &self.witness {
21+
writeln!(f, "Witness:\n{}", witness)?;
22+
}
23+
Ok(())
1424
}
1525
}
1626

17-
fn run() -> Result<(), String> {
27+
fn main() -> Result<(), Box<dyn std::error::Error>> {
1828
let command = {
1929
Command::new(env!("CARGO_BIN_NAME"))
2030
.about(
@@ -31,76 +41,82 @@ fn run() -> Result<(), String> {
3141
.action(ArgAction::Set)
3242
.help("SimplicityHL program file to build"),
3343
)
34-
};
35-
36-
let command = {
37-
command.arg(
38-
Arg::new("wit_file")
39-
.value_name("WITNESS_FILE")
40-
.action(ArgAction::Set)
41-
.help("File containing the witness data"),
42-
)
43-
};
44-
45-
let matches = {
46-
command
44+
.arg(
45+
Arg::new("wit_file")
46+
.value_name("WITNESS_FILE")
47+
.action(ArgAction::Set)
48+
.help("File containing the witness data"),
49+
)
4750
.arg(
4851
Arg::new("debug")
4952
.long("debug")
5053
.action(ArgAction::SetTrue)
5154
.help("Include debug symbols in the output"),
5255
)
53-
.get_matches()
56+
.arg(
57+
Arg::new("json")
58+
.long("json")
59+
.action(ArgAction::SetTrue)
60+
.help("Output in JSON"),
61+
)
5462
};
5563

64+
let matches = command.get_matches();
65+
5666
let prog_file = matches.get_one::<String>("prog_file").unwrap();
5767
let prog_path = std::path::Path::new(prog_file);
5868
let prog_text = std::fs::read_to_string(prog_path).map_err(|e| e.to_string())?;
5969
let include_debug_symbols = matches.get_flag("debug");
70+
let output_json = matches.get_flag("json");
6071

6172
let compiled = CompiledProgram::new(prog_text, Arguments::default(), include_debug_symbols)?;
6273

6374
#[cfg(feature = "serde")]
64-
let witness_opt = {
65-
matches
66-
.get_one::<String>("wit_file")
67-
.map(|wit_file| -> Result<simplicityhl::WitnessValues, String> {
68-
let wit_path = std::path::Path::new(wit_file);
69-
let wit_text = std::fs::read_to_string(wit_path).map_err(|e| e.to_string())?;
70-
let witness =
71-
serde_json::from_str::<simplicityhl::WitnessValues>(&wit_text).unwrap();
72-
Ok(witness)
73-
})
74-
.transpose()?
75-
};
75+
let witness_opt = matches
76+
.get_one::<String>("wit_file")
77+
.map(|wit_file| -> Result<simplicityhl::WitnessValues, String> {
78+
let wit_path = std::path::Path::new(wit_file);
79+
let wit_text = std::fs::read_to_string(wit_path).map_err(|e| e.to_string())?;
80+
let witness = serde_json::from_str::<simplicityhl::WitnessValues>(&wit_text).unwrap();
81+
Ok(witness)
82+
})
83+
.transpose()?;
7684
#[cfg(not(feature = "serde"))]
77-
let witness_opt: Option<simplicityhl::WitnessValues> = {
78-
if matches.contains_id("wit_file") {
79-
return Err(
80-
"Program was compiled without the 'serde' feature and cannot process .wit files."
81-
.into(),
82-
);
83-
}
85+
let witness_opt = if matches.contains_id("wit_file") {
86+
return Err(
87+
"Program was compiled without the 'serde' feature and cannot process .wit files."
88+
.into(),
89+
);
90+
} else {
8491
None
8592
};
8693

87-
if let Some(witness) = witness_opt {
88-
let satisfied = compiled.satisfy(witness)?;
89-
let (program_bytes, witness_bytes) = satisfied.redeem().to_vec_with_witness();
90-
println!(
91-
"Program:\n{}",
92-
Base64Display::new(&program_bytes, &STANDARD)
93-
);
94-
println!(
95-
"Witness:\n{}",
96-
Base64Display::new(&witness_bytes, &STANDARD)
94+
let (program_bytes, witness_bytes) = match witness_opt {
95+
Some(witness) => {
96+
let satisfied = compiled.satisfy(witness)?;
97+
let (program_bytes, witness_bytes) = satisfied.redeem().to_vec_with_witness();
98+
(program_bytes, Some(witness_bytes))
99+
}
100+
None => {
101+
let program_bytes = compiled.commit().to_vec_without_witness();
102+
(program_bytes, None)
103+
}
104+
};
105+
106+
let output = Output {
107+
program: Base64Display::new(&program_bytes, &STANDARD).to_string(),
108+
witness: witness_bytes.map(|bytes| Base64Display::new(&bytes, &STANDARD).to_string()),
109+
};
110+
111+
if output_json {
112+
#[cfg(not(feature = "serde"))]
113+
return Err(
114+
"Program was compiled without the 'serde' feature and cannot output JSON.".into(),
97115
);
116+
#[cfg(feature = "serde")]
117+
println!("{}", serde_json::to_string(&output)?);
98118
} else {
99-
let program_bytes = compiled.commit().to_vec_without_witness();
100-
println!(
101-
"Program:\n{}",
102-
Base64Display::new(&program_bytes, &STANDARD)
103-
);
119+
println!("{}", output);
104120
}
105121

106122
Ok(())

0 commit comments

Comments
 (0)