1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use clap::{arg, Parser};
use std::{fmt::Display, str::FromStr};

#[derive(Debug, Clone)]
pub struct HexString(pub Vec<u8>);

impl FromStr for HexString {
    type Err = hex::FromHexError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let stripped = s.strip_prefix("0x").unwrap_or(s);
        Ok(HexString(hex::decode(stripped)?))
    }
}

impl Display for HexString {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "0x{}", hex::encode(&self.0))
    }
}

#[derive(Parser)]
pub struct EncodeFileArgs {
    #[arg(long, short = 'i', value_name = "FILE", help = "input file")]
    pub input: String,

    #[arg(
        long,
        short = 'o',
        value_name = "FILE",
        help = "output file (encoded as field elements)"
    )]
    pub output: String,

    #[arg(long = "srs-filepath", value_name = "SRS_FILEPATH")]
    pub srs_cache: Option<String>,

    #[arg(
        long = "assert-commitment",
        value_name = "COMMITMENT",
        help = "hash of commitments (hex encoded)"
    )]
    pub assert_commitment: Option<HexString>,
}

#[derive(Parser)]
pub struct DecodeFileArgs {
    #[arg(
        long,
        short = 'i',
        value_name = "FILE",
        help = "input file (encoded as field elements)"
    )]
    pub input: String,

    #[arg(long, short = 'o', value_name = "FILE", help = "output file")]
    pub output: String,

    #[arg(long = "srs-filepath", value_name = "SRS_FILEPATH")]
    pub srs_cache: Option<String>,
}

#[derive(Parser)]
pub struct ComputeCommitmentArgs {
    #[arg(long, short = 'i', value_name = "FILE", help = "input file")]
    pub input: String,

    #[arg(long, short = 'o', value_name = "FILE", help = "output file")]
    pub output: String,

    #[arg(long = "srs-filepath", value_name = "SRS_FILEPATH")]
    pub srs_cache: Option<String>,
}

#[derive(Parser)]
pub struct StorageProofArgs {
    #[arg(
        long,
        short = 'i',
        value_name = "FILE",
        help = "input file (encoded as field elements)"
    )]
    pub input: String,

    #[arg(long = "srs-filepath", value_name = "SRS_FILEPATH")]
    pub srs_cache: Option<String>,

    #[arg(
        long = "challenge",
        value_name = "CHALLENGE",
        help = "challenge (hex encoded"
    )]
    pub challenge: HexString,
}

#[derive(Parser)]
pub struct VerifyStorageProofArgs {
    #[arg(long = "srs-filepath", value_name = "SRS_FILEPATH")]
    pub srs_cache: Option<String>,

    #[arg(
        long,
        short = 'c',
        value_name = "COMMITMENT",
        help = "commitment (hex encoded)"
    )]
    pub commitment: HexString,

    #[arg(
        long = "challenge",
        value_name = "CHALLENGE",
        help = "challenge (hex encoded"
    )]
    pub challenge: HexString,

    #[arg(long, short = 'p', value_name = "PROOF", help = "proof (hex encoded)")]
    pub proof: HexString,
}

#[derive(Parser)]
#[command(
    name = "saffron",
    version = "0.1",
    about = "saffron - a mutable state layer"
)]
pub enum Commands {
    #[command(name = "encode")]
    Encode(EncodeFileArgs),
    #[command(name = "decode")]
    Decode(DecodeFileArgs),
    #[command(name = "compute-commitment")]
    ComputeCommitment(ComputeCommitmentArgs),
    #[command(name = "storage-proof")]
    StorageProof(StorageProofArgs),
    #[command(name = "verify-storage-proof")]
    VerifyStorageProof(VerifyStorageProofArgs),
}