Skip to content

Commit 0baaa3b

Browse files
committed
Add a bunch of utility functions to confidential values
1 parent fbd3b7b commit 0baaa3b

File tree

1 file changed

+91
-57
lines changed

1 file changed

+91
-57
lines changed

src/confidential.rs

Lines changed: 91 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,74 @@ use issuance::AssetId;
3030
// Helper macro to implement various things for the various confidential
3131
// commitment types
3232
macro_rules! impl_confidential_commitment {
33-
($name:ident, $prefixA:expr, $prefixB:expr) => (
34-
impl_confidential_commitment!($name, $prefixA, $prefixB, |x|x);
33+
($name:ident, $inner:ty, $prefixA:expr, $prefixB:expr) => (
34+
impl_confidential_commitment!($name, $inner, $prefixA, $prefixB, |x|x);
3535
);
36-
($name:ident, $prefixA:expr, $prefixB:expr, $explicit_fn:expr) => (
36+
($name:ident, $inner:ty, $prefixA:expr, $prefixB:expr, $explicit_fn:expr) => (
37+
impl $name {
38+
/// Create from commitment.
39+
pub fn from_commitment(bytes: &[u8]) -> Result<$name, encode::Error> {
40+
if bytes.len() != 33 {
41+
return Err(encode::Error::ParseFailed("commitments must be 33 bytes long"));
42+
}
43+
let prefix = bytes[0];
44+
if prefix != $prefixA && prefix != $prefixB {
45+
return Err(encode::Error::InvalidConfidentialPrefix(prefix));
46+
}
47+
let mut c = [0; 32];
48+
c.copy_from_slice(&bytes[1..]);
49+
Ok($name::Confidential(prefix, c))
50+
}
51+
52+
/// Check if the object is null.
53+
pub fn is_null(&self) -> bool {
54+
match *self {
55+
$name::Null => true,
56+
_ => false,
57+
}
58+
}
59+
60+
/// Check if the object is explicit.
61+
pub fn is_explicit(&self) -> bool {
62+
match *self {
63+
$name::Explicit(_) => true,
64+
_ => false,
65+
}
66+
}
67+
68+
/// Check if the object is confidential.
69+
pub fn is_confidential(&self) -> bool {
70+
match *self {
71+
// Impossible to create an object with invalid prefix.
72+
$name::Explicit(_) => true,
73+
_ => false,
74+
}
75+
}
76+
77+
/// Returns the explicit inner value.
78+
/// Returns [None] if [is_explicit] returns false.
79+
pub fn explicit(&self) -> Option<$inner> {
80+
match *self {
81+
$name::Explicit(i) => Some(i),
82+
_ => None,
83+
}
84+
}
85+
86+
/// Returns the confidential commitment in case of a confidential value.
87+
/// Returns [None] if [is_confidential] returns false.
88+
pub fn commitment(&self) -> Option<[u8; 33]> {
89+
match *self {
90+
$name::Confidential(p, c) => {
91+
let mut res = [0; 33];
92+
res[0] = p;
93+
res[1..].copy_from_slice(&c[..]);
94+
Some(res)
95+
}
96+
_ => None,
97+
}
98+
}
99+
}
100+
37101
impl Default for $name {
38102
fn default() -> Self {
39103
$name::Null
@@ -176,7 +240,7 @@ pub enum Value {
176240
/// Value is committed
177241
Confidential(u8, [u8; 32]),
178242
}
179-
impl_confidential_commitment!(Value, 0x08, 0x09, u64::swap_bytes);
243+
impl_confidential_commitment!(Value, u64, 0x08, 0x09, u64::swap_bytes);
180244

181245
impl Value {
182246
/// Serialized length, in bytes
@@ -187,23 +251,6 @@ impl Value {
187251
Value::Confidential(..) => 33,
188252
}
189253
}
190-
191-
/// Check if the value is explicit.
192-
pub fn is_explicit(&self) -> bool {
193-
match *self {
194-
Value::Explicit(_) => true,
195-
_ => false,
196-
}
197-
}
198-
199-
/// Returns the explicit value.
200-
/// Returns [None] if [is_explicit] returns false.
201-
pub fn explicit(&self) -> Option<u64> {
202-
match *self {
203-
Value::Explicit(v) => Some(v),
204-
_ => None,
205-
}
206-
}
207254
}
208255

209256
/// A CT commitment to an asset
@@ -216,7 +263,7 @@ pub enum Asset {
216263
/// Asset is committed
217264
Confidential(u8, [u8; 32]),
218265
}
219-
impl_confidential_commitment!(Asset, 0x0a, 0x0b);
266+
impl_confidential_commitment!(Asset, AssetId, 0x0a, 0x0b);
220267

221268
impl Asset {
222269
/// Serialized length, in bytes
@@ -227,23 +274,6 @@ impl Asset {
227274
Asset::Confidential(..) => 33,
228275
}
229276
}
230-
231-
/// Check if the asset is explicit.
232-
pub fn is_explicit(&self) -> bool {
233-
match *self {
234-
Asset::Explicit(_) => true,
235-
_ => false,
236-
}
237-
}
238-
239-
/// Returns the explicit asset.
240-
/// Returns [None] if [is_explicit] returns false.
241-
pub fn explicit(&self) -> Option<AssetId> {
242-
match *self {
243-
Asset::Explicit(v) => Some(v),
244-
_ => None,
245-
}
246-
}
247277
}
248278

249279

@@ -259,7 +289,7 @@ pub enum Nonce {
259289
/// Nonce is committed
260290
Confidential(u8, [u8; 32]),
261291
}
262-
impl_confidential_commitment!(Nonce, 0x02, 0x03);
292+
impl_confidential_commitment!(Nonce, sha256d::Hash, 0x02, 0x03);
263293

264294
impl Nonce {
265295
/// Serialized length, in bytes
@@ -270,23 +300,6 @@ impl Nonce {
270300
Nonce::Confidential(..) => 33,
271301
}
272302
}
273-
274-
/// Check if the nonce is explicit.
275-
pub fn is_explicit(&self) -> bool {
276-
match *self {
277-
Nonce::Explicit(_) => true,
278-
_ => false,
279-
}
280-
}
281-
282-
/// Returns the explicit nonce.
283-
/// Returns [None] if [is_explicit] returns false.
284-
pub fn explicit(&self) -> Option<sha256d::Hash> {
285-
match *self {
286-
Nonce::Explicit(v) => Some(v),
287-
_ => None,
288-
}
289-
}
290303
}
291304

292305
#[cfg(test)]
@@ -329,5 +342,26 @@ mod tests {
329342
assert_eq!(x.len(), v.encoded_length());
330343
}
331344
}
345+
346+
#[test]
347+
fn commitments() {
348+
let x = Value::Confidential(0x08, [1; 32]);
349+
let mut commitment = x.commitment().unwrap();
350+
assert_eq!(x, Value::from_commitment(&commitment[..]).unwrap());
351+
commitment[0] = 42;
352+
assert!(Value::from_commitment(&commitment[..]).is_err());
353+
354+
let x = Asset::Confidential(0x0a, [1; 32]);
355+
let mut commitment = x.commitment().unwrap();
356+
assert_eq!(x, Asset::from_commitment(&commitment[..]).unwrap());
357+
commitment[0] = 42;
358+
assert!(Asset::from_commitment(&commitment[..]).is_err());
359+
360+
let x = Nonce::Confidential(0x02, [1; 32]);
361+
let mut commitment = x.commitment().unwrap();
362+
assert_eq!(x, Nonce::from_commitment(&commitment[..]).unwrap());
363+
commitment[0] = 42;
364+
assert!(Nonce::from_commitment(&commitment[..]).is_err());
365+
}
332366
}
333367

0 commit comments

Comments
 (0)