1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00

Merge pull request #242 from Zokrates/short-field-display

Display field elements in a more compact way
This commit is contained in:
JacobEberhardt 2019-02-01 13:11:21 +01:00 committed by GitHub
commit 732c1b70f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 60 additions and 2 deletions

View file

@ -16,5 +16,6 @@
- [CLI](reference/cli.md)
- [Backends](reference/backends.md)
- [Verification](reference/verification.md)
- [ZIR](reference/ir.md)
- [Tutorial: Proof of preimage](./sha256example.md)
- [Tutorial: Proof of preimage](./sha256example.md)

View file

@ -6,3 +6,4 @@ The reference covers the details of various areas of ZoKrates.
- [CLI](cli.md)
- [Backends](backends.md)
- [Verification](verification.md)
- [ZIR](ir.md)

View file

@ -0,0 +1,19 @@
# ZIR
ZIR is the intermediate representation ZoKrates uses to represent programs. It is close to R1CS but still encapsulates witness generation.
**Note that ZIR is still in development and can change without notice.**
When generating R1CS constraints, very large numbers are often used, which can make reading ZIR hard for humans.
To mitigate this, ZIR applies an isomorphism when displaying field elements: they are shown as members of the interval `[- (p - 1)/2, (p - 1)/2]`. In other words, the following mapping is used:
- elements in `[0, (p - 1)/2]` map to themselves
- elements in `[(p + 1)/2, p - 1]` map to themselves minus `p`
Therefore, instead of writing `p - 1` as:
```
21888242871839275222246405745257275088548364400416034343698204186575808495616
```
... in ZIR, we simply write:
```
-1
```

View file

@ -57,7 +57,7 @@ impl<T: Field> fmt::Display for LinComb<T> {
"{}",
self.0
.iter()
.map(|(k, v)| format!("{} * {}", v, k))
.map(|(k, v)| format!("{} * {}", v.to_compact_dec_string(), k))
.collect::<Vec<_>>()
.join(" + ")
)

View file

@ -71,6 +71,9 @@ pub trait Field:
fn get_required_bits() -> usize;
/// Tries to parse a string into this representation
fn try_from_str<'a>(s: &'a str) -> Result<Self, ()>;
/// Returns a decimal string representing a the member of the equivalence class of this `Field` in Z/pZ
/// which lies in [-(p-1)/2, (p-1)/2]
fn to_compact_dec_string(&self) -> String;
}
#[derive(PartialEq, PartialOrd, Clone, Eq, Ord, Hash, Serialize, Deserialize)]
@ -129,6 +132,17 @@ impl Field for FieldPrime {
value: &x - x.div_floor(&*P) * &*P,
})
}
fn to_compact_dec_string(&self) -> String {
// values up to (p-1)/2 included are represented as positive, values between (p+1)/2 and p-1 as represented as negative by subtracting p
if self.value <= FieldPrime::max_value().value / 2 {
format!("{}", self.value.to_str_radix(10))
} else {
format!(
"({})",
(&self.value - (FieldPrime::max_value().value + BigInt::one())).to_str_radix(10)
)
}
}
}
impl Default for FieldPrime {
@ -612,6 +626,29 @@ mod tests {
let bv = fp.to_dec_string();
assert_eq!(fp, FieldPrime::from_dec_string(bv));
}
#[test]
fn compact_representation() {
let one = FieldPrime::from(1);
assert_eq!("1", &one.to_compact_dec_string());
let minus_one = FieldPrime::from(0) - one;
assert_eq!("(-1)", &minus_one.to_compact_dec_string());
// (p-1)/2 -> positive notation
let p_minus_one_over_two =
(FieldPrime::from(0) - FieldPrime::from(1)) / FieldPrime::from(2);
assert_eq!(
"10944121435919637611123202872628637544274182200208017171849102093287904247808",
&p_minus_one_over_two.to_compact_dec_string()
);
// (p-1)/2 + 1 -> negative notation (p-1)/2 + 1 - p == (-p+1)/2
let p_minus_one_over_two_plus_one = ((FieldPrime::from(0) - FieldPrime::from(1))
/ FieldPrime::from(2))
+ FieldPrime::from(1);
assert_eq!(
"(-10944121435919637611123202872628637544274182200208017171849102093287904247808)",
&p_minus_one_over_two_plus_one.to_compact_dec_string()
);
}
}
#[test]