@@ -30,10 +30,74 @@ use issuance::AssetId;
3030// Helper macro to implement various things for the various confidential
3131// commitment types
3232macro_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
181245impl 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
221268impl 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
264294impl 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