Skip to content

Commit 773dce7

Browse files
Adam GibsonAdam Gibson
Adam Gibson
authored and
Adam Gibson
committed
Add GUI for verifying audit proofs
This is built using eframe/egui and intended to be cross platform. The functionality is limited to only: * user inputs proof file and keyset file * user inputs signature message * user clicks verify and receives a valid/invalid message in response, with the proved sats range. This does *not* yet include server functionality, so a different instance of the autct binary must already be running as server, serving the given keyset file and context.
1 parent b24a90f commit 773dce7

File tree

9 files changed

+368
-64
lines changed

9 files changed

+368
-64
lines changed

.github/workflows/binaries.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
with:
3434
# (required) Comma-separated list of binary names (non-extension portion of filename) to build and upload.
3535
# Note that glob pattern is not supported yet.
36-
bin: autct
36+
bin: autct, auditverifier
3737
# (optional) On which platform to distribute the `.tar.gz` file.
3838
# [default value: unix]
3939
# [possible values: all, unix, windows, none]

Cargo.toml

+7-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ rayon = {version = "1.5.3", optional = true}
3131
hex = {version ="0.4.3", features = ["serde"] }
3232
tokio = { version = "1", features = ["rt-multi-thread", "macros", "net"] }
3333
toy-rpc = { version = "0.8.1", default-features = false, features = ["serde_json", "tokio_runtime", "ws_tokio", "server", "client"] }
34+
eframe = "0.28.1"
35+
rfd = "0.12"
3436
serde = { version = "1.0", features = ["derive"] }
3537
serde_json = "1.0"
3638
serde_derive = "1.0"
@@ -56,7 +58,11 @@ rpassword = "7.3"
5658

5759
[[bin]]
5860
name = "autct"
59-
path = "src/autct.rs"
61+
path = "src/bin/autctbin.rs"
62+
63+
[[bin]]
64+
name = "auditverifier"
65+
path = "src/bin/gui.rs"
6066

6167
[features]
6268
default = ["asm"]

auditor-docs/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ Run the server exactly as for `aut-ct` functions detailed on the main page:
3131
target/release/autct -M serve -k mycontext:something.pks -n signet
3232
```
3333

34+
(note: the context string "mycontext" is ignored for the auditing function; it can be anything, like "abcdef:..", but it must be there).
35+
3436
But use the `auditprove` method from the client:
3537

3638
```

src/auditor.rs

-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ use crate::utils::{get_generators, get_curve_tree_proof_from_curve_tree,
5757
pub const J_GENERATOR_LABEL: &[u8] = b"auditor-J";
5858
pub const H_GENERATOR_LABEL: &[u8] = b"auditor-H";
5959

60-
6160
pub fn get_audit_generators() -> (Affine<SecpConfig>, Affine<SecpConfig>){
6261
let G = SecpConfig::GENERATOR;
6362
let J = get_generators::<SecpBase, SecpConfig>(J_GENERATOR_LABEL);

src/autct.rs src/autctactions.rs

+39-49
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,15 @@
33
extern crate rand;
44
extern crate alloc;
55
extern crate ark_secp256k1;
6-
use autct::key_processing::create_fake_privkeys_values_files;
7-
use autct::rpcclient;
8-
use autct::rpcserver;
9-
use autct::config::{AutctConfig, get_params_from_config_string};
10-
use autct::utils::write_file_string;
6+
use crate::key_processing::create_fake_privkeys_values_files;
7+
use crate::rpcclient;
8+
//use crate::rpcserver;
9+
use crate::config::{AutctConfig, get_params_from_config_string};
10+
use crate::utils::write_file_string;
1111
use std::io::Write;
1212
use std::error::Error;
1313
use base64::prelude::*;
14-
use autct::encryption::{encrypt, decrypt};
15-
16-
#[tokio::main]
17-
async fn main() -> Result<(), Box<dyn Error>>{
18-
let autctcfg = AutctConfig::build()?;
19-
match autctcfg.clone().mode.unwrap().as_str() {
20-
"prove" => {return request_prove(autctcfg).await
21-
},
22-
"verify" => {return request_verify(autctcfg).await},
23-
"serve" => {return rpcserver::do_serve(autctcfg).await
24-
},
25-
"newkeys" => {return request_create_keys(autctcfg).await},
26-
"auditprove" => {return request_audit(autctcfg).await},
27-
"auditverify" => {return request_audit_verify(autctcfg).await},
28-
// this extra tool is really just for testing:
29-
"encryptkey" => {return request_encrypt_key(autctcfg).await},
30-
// extra tool for exporting the key:
31-
"decryptkey" => {return request_decrypted_key(autctcfg).await},
32-
// extra (undocumented) tool for creating test files:
33-
"audittestgen" => {return create_test_data(autctcfg).await},
34-
_ => {return Err("Invalid mode, must be 'prove', 'auditprove', 'serve', 'newkeys', 'encryptkey', 'decryptkey' or 'verify'".into())},
35-
36-
}
37-
}
14+
use crate::encryption::{encrypt, decrypt};
3815

3916
/// An undocumented tool for creating test files.
4017
/// Note that this misuses config vars as follows:
@@ -46,7 +23,7 @@ async fn main() -> Result<(), Box<dyn Error>>{
4623
/// the proof, along with the value for each index, using colon
4724
/// separated pairs. For example:
4825
/// ./autct -M audittestgen -W 100 -l 2:5000,14:90000 -k mytestdata
49-
async fn create_test_data(autctcfg: AutctConfig) -> Result<(), Box<dyn Error>> {
26+
pub async fn create_test_data(autctcfg: AutctConfig) -> Result<(), Box<dyn Error>> {
5027
let filenameprefix = autctcfg.keysets.clone().unwrap();
5128
let numprivs = autctcfg.depth.clone().unwrap() as u64;
5229
let values_indices_str = autctcfg.rpc_host.clone().unwrap();
@@ -62,10 +39,10 @@ async fn create_test_data(autctcfg: AutctConfig) -> Result<(), Box<dyn Error>> {
6239
/// This is a tool for manual testing; users will always
6340
/// have privkeys stored in encrypted files. Hence
6441
/// there is no attempt to handle errors properly.
65-
async fn request_encrypt_key(autctcfg: AutctConfig) -> Result<(), Box<dyn Error>> {
42+
pub async fn request_encrypt_key(autctcfg: AutctConfig) -> Result<(), Box<dyn Error>> {
6643
let password = rpassword::prompt_password("Enter a password to encrypt the private key: ").unwrap();
6744
let privkey_file_str = autctcfg.privkey_file_str.clone().unwrap();
68-
let plaintext_priv_wif = autct::utils::read_file_string(&privkey_file_str)?;
45+
let plaintext_priv_wif = crate::utils::read_file_string(&privkey_file_str)?;
6946
let mut buf: Vec<u8> = Vec::new();
7047
write!(&mut buf, "{}", plaintext_priv_wif)?;
7148
let encrypted_data = encrypt(&buf, &password.as_bytes())?;
@@ -75,7 +52,7 @@ async fn request_encrypt_key(autctcfg: AutctConfig) -> Result<(), Box<dyn Error>
7552
}
7653

7754
// This tool is helpful to allow importing the key to a Bitcoin wallet
78-
async fn request_decrypted_key(autctcfg: AutctConfig) -> Result<(), Box<dyn Error>> {
55+
pub async fn request_decrypted_key(autctcfg: AutctConfig) -> Result<(), Box<dyn Error>> {
7956
let password = rpassword::prompt_password("Enter password to decrypt private key: ")?;
8057
let privkey_file_str = autctcfg.privkey_file_str.clone().unwrap();
8158
let encrypted_priv_wif = std::fs::read(&privkey_file_str)?;
@@ -85,7 +62,7 @@ async fn request_decrypted_key(autctcfg: AutctConfig) -> Result<(), Box<dyn Erro
8562
Ok(())
8663
}
8764

88-
async fn request_create_keys(autctcfg: AutctConfig) ->Result<(), Box<dyn Error>> {
65+
pub async fn request_create_keys(autctcfg: AutctConfig) ->Result<(), Box<dyn Error>> {
8966
// This requires interaction from user: give a password on the command line:
9067
let password = rpassword::prompt_password("Enter a password to encrypt the new private key: ").unwrap();
9168
let res = rpcclient::createkeys(autctcfg, password).await;
@@ -109,7 +86,7 @@ async fn request_create_keys(autctcfg: AutctConfig) ->Result<(), Box<dyn Error>>
10986
Ok(())
11087
}
11188

112-
async fn request_verify(autctcfg: AutctConfig) -> Result<(), Box<dyn Error>> {
89+
pub async fn request_verify(autctcfg: AutctConfig) -> Result<(), Box<dyn Error>> {
11390
let res = rpcclient::verify(autctcfg).await;
11491
match res {
11592
Ok(rest) => {
@@ -132,27 +109,40 @@ async fn request_verify(autctcfg: AutctConfig) -> Result<(), Box<dyn Error>> {
132109
Ok(())
133110
}
134111

135-
async fn request_audit_verify(autctcfg: AutctConfig) -> Result<(), Box<dyn Error>>{
112+
fn print_and_return(s: &str) -> Result<String, Box<dyn Error>>{
113+
println!("{}", s);
114+
Ok(s.to_string())
115+
}
116+
117+
pub async fn request_audit_verify(autctcfg: AutctConfig) -> Result<String, Box<dyn Error>>{
136118
let res = rpcclient::auditverify(autctcfg.clone()).await;
137119
match res {
138120
Ok(rest) => {
139-
let satmin = autctcfg.audit_range_min.unwrap();
140-
let satmax = satmin + 2u64.pow(autctcfg.audit_range_exponent.unwrap() as u32);
121+
// Note that we are guaranteed non-nonsense values
122+
// for these fields because this is a non-Err response:
123+
let satmin = rest.audit_range_min;
124+
let satmax = satmin + 2u64.pow(rest.audit_range_exponent as u32);
141125
match rest.accepted {
142-
1 => println!("Audit is valid! The utxos' total value is between {} and {} satoshis.",
143-
satmin, satmax),
144-
-1 => println!("Invalid encoding of proof, should be base64."),
145-
-2 => println!("Invalid proof serialization"),
146-
-3 => println!("Proof of assets in range is rejected, proof invalid."),
147-
_ => println!("Unrecognized error code from server?"),
126+
1 => {let s = format!("Audit is valid! The utxos' total value is between {} and {} satoshis.",
127+
satmin, satmax);
128+
println!("{}", s);
129+
return Ok(s)},
130+
-1 => {let s = "Invalid encoding of proof, should be base64.";
131+
return print_and_return(s);},
132+
-2 => {let s = "Invalid proof serialization";
133+
return print_and_return(s);},
134+
-3 => {let s = "Proof of assets in range is rejected, proof invalid.";
135+
return print_and_return(s);},
136+
_ => {let s = "Unrecognized error code from server?";
137+
return print_and_return(s);},
148138
}
149139
},
150-
Err(_) => return Err("Verificatoin request processing failed.".into()),
140+
Err(e) => return Err(
141+
format!("{}", e).into()),
151142
};
152-
Ok(())
153-
154143
}
155-
async fn request_audit(autctcfg: AutctConfig) -> Result<(), Box<dyn Error>>{
144+
145+
pub async fn request_audit(autctcfg: AutctConfig) -> Result<(), Box<dyn Error>>{
156146
let res = rpcclient::auditprove(
157147
autctcfg.clone()).await;
158148
let required_proof_destination = autctcfg.clone()
@@ -185,7 +175,7 @@ async fn request_audit(autctcfg: AutctConfig) -> Result<(), Box<dyn Error>>{
185175
Ok(())
186176
}
187177

188-
async fn request_prove(autctcfg: AutctConfig) -> Result<(), Box<dyn Error>>{
178+
pub async fn request_prove(autctcfg: AutctConfig) -> Result<(), Box<dyn Error>>{
189179
// This requires interaction from user: give a password on the command line:
190180
let password = rpassword::prompt_password("Enter a password to decrypt the private key: ").unwrap();
191181
let required_proof_destination = autctcfg.clone().proof_file_str.unwrap();

src/bin/autctbin.rs

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#![allow(non_snake_case)]
2+
3+
extern crate rand;
4+
extern crate alloc;
5+
extern crate ark_secp256k1;
6+
use autct::rpcserver;
7+
use std::error::Error;
8+
use autct::autctactions::*;
9+
use autct::config::AutctConfig;
10+
11+
#[tokio::main]
12+
async fn main() -> Result<(), Box<dyn Error>>{
13+
let autctcfg = AutctConfig::build()?;
14+
match autctcfg.clone().mode.unwrap().as_str() {
15+
"prove" => {return request_prove(autctcfg).await
16+
},
17+
"verify" => {return request_verify(autctcfg).await},
18+
"serve" => {return rpcserver::do_serve(autctcfg).await
19+
},
20+
"newkeys" => {return request_create_keys(autctcfg).await},
21+
"auditprove" => {return request_audit(autctcfg).await},
22+
"auditverify" => {let _ = request_audit_verify(autctcfg).await;
23+
return Ok(())},
24+
// this extra tool is really just for testing:
25+
"encryptkey" => {return request_encrypt_key(autctcfg).await},
26+
// extra tool for exporting the key:
27+
"decryptkey" => {return request_decrypted_key(autctcfg).await},
28+
// extra (undocumented) tool for creating test files:
29+
"audittestgen" => {return create_test_data(autctcfg).await},
30+
_ => {return Err("Invalid mode, must be 'prove', 'auditprove', 'serve', 'newkeys', 'encryptkey', 'decryptkey' or 'verify'".into())},
31+
32+
}
33+
}

0 commit comments

Comments
 (0)