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
use snarkvm_fields::{Field, PrimeField};
use snarkvm_r1cs::{Assignment, ConstraintSystem, LinearCombination, SynthesisError};
use crate::{
bits::boolean::AllocatedBit,
errors::UnsignedIntegerError,
integers::uint::*,
traits::{alloc::AllocGadget, integers::Integer},
};
pub trait Sub<F: Field, Rhs = Self>
where
Self: std::marker::Sized,
{
type ErrorType;
fn sub<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self) -> Result<Self, Self::ErrorType>;
fn sub_unsafe<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self) -> Result<Self, Self::ErrorType>;
}
macro_rules! sub_int_impl {
($($gadget:ident),*) => ($(
impl<F: PrimeField> Sub<F> for $gadget {
type ErrorType = UnsignedIntegerError;
fn sub<CS: ConstraintSystem<F>>(
&self,
mut cs: CS,
other: &Self,
) -> Result<Self, Self::ErrorType> {
Self::addmany(&mut cs.ns(|| "add_not"), &[self.clone(), other.negate()]).map_err(|e| e.into())
}
fn sub_unsafe<CS: ConstraintSystem<F>>(
&self,
mut cs: CS,
other: &Self,
) -> Result<Self, Self::ErrorType> {
match (self.value, other.value) {
(Some(val1), Some(val2)) => {
if val1 < val2 {
if Self::result_is_constant(&self, &other) {
Ok(Self::constant(0 as <$gadget as Integer>::IntegerType))
} else {
let result_value = Some(0u128);
let modular_value = result_value.map(|v| v as <$gadget as Integer>::IntegerType);
let mut result_bits = Vec::with_capacity(<$gadget as Integer>::SIZE);
let mut lc = LinearCombination::zero();
let mut coeff = F::one();
for i in 0..<$gadget as Integer>::SIZE {
let b = AllocatedBit::alloc(cs.ns(|| format!("result bit_gadget {}", i)), || {
result_value.map(|v| (v >> i) & 1 == 1).get()
})?;
lc = lc - (coeff, b.get_variable());
result_bits.push(b.into());
coeff.double_in_place();
}
cs.enforce(|| "unsafe subtraction", |lc| lc, |lc| lc, |_| lc);
Ok(Self {
bits: result_bits,
negated: false,
value: modular_value,
})
}
} else {
self.sub(&mut cs.ns(|| ""), &other)
}
}
(_, _) => {
Err(SynthesisError::AssignmentMissing.into())
}
}
}
}
)*)
}
sub_int_impl!(UInt8, UInt16, UInt32, UInt64, UInt128);