@@ -30,32 +30,80 @@ 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) => (
37- impl Default for $name {
38- fn default ( ) -> Self {
39- $name:: Null
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) )
4050 }
41- }
4251
43- impl fmt :: Display for $name {
44- fn fmt ( & self , f : & mut fmt :: Formatter ) -> fmt :: Result {
52+ /// Check if the object is null.
53+ pub fn is_null ( & self ) -> bool {
4554 match * self {
46- $name:: Null => f. write_str( "null" ) ,
47- $name:: Explicit ( n) => write!( f, "{}" , n) ,
48- $name:: Confidential ( prefix, bytes) => {
49- write!( f, "{:02x}" , prefix) ?;
50- for b in bytes. iter( ) {
51- write!( f, "{:02x}" , b) ?;
52- }
53- Ok ( ( ) )
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)
5495 }
96+ _ => None ,
5597 }
5698 }
5799 }
58100
101+ impl Default for $name {
102+ fn default ( ) -> Self {
103+ $name:: Null
104+ }
105+ }
106+
59107 impl Encodable for $name {
60108 fn consensus_encode<S : io:: Write >( & self , mut s: S ) -> Result <usize , encode:: Error > {
61109 match * self {
@@ -82,10 +130,11 @@ macro_rules! impl_confidential_commitment {
82130 let explicit = $explicit_fn( Decodable :: consensus_decode( & mut d) ?) ;
83131 Ok ( $name:: Explicit ( explicit) )
84132 }
85- x => {
133+ p if p == $prefixA || p == $prefixB => {
86134 let commitment = <[ u8 ; 32 ] >:: consensus_decode( & mut d) ?;
87- Ok ( $name:: Confidential ( x , commitment) )
135+ Ok ( $name:: Confidential ( p , commitment) )
88136 }
137+ p => return Err ( encode:: Error :: InvalidConfidentialPrefix ( p) ) ,
89138 }
90139 }
91140 }
@@ -143,12 +192,15 @@ macro_rules! impl_confidential_commitment {
143192 None => Err ( A :: Error :: custom( "missing commitment" ) ) ,
144193 }
145194 }
146- x => {
195+ p if p == $prefixA || p == $prefixB => {
147196 match access. next_element( ) ? {
148- Some ( y) => Ok ( $name:: Confidential ( x , y) ) ,
197+ Some ( y) => Ok ( $name:: Confidential ( p , y) ) ,
149198 None => Err ( A :: Error :: custom( "missing commitment" ) ) ,
150199 }
151200 }
201+ p => return Err ( A :: Error :: custom( format!(
202+ "invalid commitment, invalid prefix: 0x{:02x}" , p
203+ ) ) ) ,
152204 }
153205 }
154206 }
@@ -172,7 +224,7 @@ pub enum Value {
172224 /// Value is committed
173225 Confidential ( u8 , [ u8 ; 32 ] ) ,
174226}
175- impl_confidential_commitment ! ( Value , 0x08 , 0x09 , u64 :: swap_bytes) ;
227+ impl_confidential_commitment ! ( Value , u64 , 0x08 , 0x09 , u64 :: swap_bytes) ;
176228
177229impl Value {
178230 /// Serialized length, in bytes
@@ -183,21 +235,20 @@ impl Value {
183235 Value :: Confidential ( ..) => 33 ,
184236 }
185237 }
238+ }
186239
187- /// Check if the value is explicit.
188- pub fn is_explicit ( & self ) -> bool {
189- match * self {
190- Value :: Explicit ( _) => true ,
191- _ => false ,
192- }
193- }
194-
195- /// Returns the explicit value.
196- /// Returns [None] if [is_explicit] returns false.
197- pub fn explicit ( & self ) -> Option < u64 > {
240+ impl fmt:: Display for Value {
241+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
198242 match * self {
199- Value :: Explicit ( v) => Some ( v) ,
200- _ => None ,
243+ Value :: Null => f. write_str ( "null" ) ,
244+ Value :: Explicit ( n) => write ! ( f, "{}" , n) ,
245+ Value :: Confidential ( prefix, bytes) => {
246+ write ! ( f, "{:02x}" , prefix) ?;
247+ for b in bytes. iter ( ) {
248+ write ! ( f, "{:02x}" , b) ?;
249+ }
250+ Ok ( ( ) )
251+ }
201252 }
202253 }
203254}
@@ -212,7 +263,7 @@ pub enum Asset {
212263 /// Asset is committed
213264 Confidential ( u8 , [ u8 ; 32 ] ) ,
214265}
215- impl_confidential_commitment ! ( Asset , 0x0a , 0x0b ) ;
266+ impl_confidential_commitment ! ( Asset , AssetId , 0x0a , 0x0b ) ;
216267
217268impl Asset {
218269 /// Serialized length, in bytes
@@ -223,26 +274,24 @@ impl Asset {
223274 Asset :: Confidential ( ..) => 33 ,
224275 }
225276 }
277+ }
226278
227- /// Check if the asset is explicit.
228- pub fn is_explicit ( & self ) -> bool {
229- match * self {
230- Asset :: Explicit ( _) => true ,
231- _ => false ,
232- }
233- }
234-
235- /// Returns the explicit asset.
236- /// Returns [None] if [is_explicit] returns false.
237- pub fn explicit ( & self ) -> Option < AssetId > {
279+ impl fmt:: Display for Asset {
280+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
238281 match * self {
239- Asset :: Explicit ( v) => Some ( v) ,
240- _ => None ,
282+ Asset :: Null => f. write_str ( "null" ) ,
283+ Asset :: Explicit ( n) => write ! ( f, "{}" , n) ,
284+ Asset :: Confidential ( prefix, bytes) => {
285+ write ! ( f, "{:02x}" , prefix) ?;
286+ for b in bytes. iter ( ) {
287+ write ! ( f, "{:02x}" , b) ?;
288+ }
289+ Ok ( ( ) )
290+ }
241291 }
242292 }
243293}
244294
245-
246295/// A CT commitment to an output nonce (i.e. a public key)
247296#[ derive( Copy , Clone , Debug , Eq , Hash , PartialEq , PartialOrd , Ord ) ]
248297pub enum Nonce {
@@ -251,11 +300,11 @@ pub enum Nonce {
251300 /// There should be no such thing as an "explicit nonce", but Elements will deserialize
252301 /// such a thing (and insists that its size be 32 bytes). So we stick a 32-byte type here
253302 /// that implements all the traits we need.
254- Explicit ( sha256d :: Hash ) ,
303+ Explicit ( [ u8 ; 32 ] ) ,
255304 /// Nonce is committed
256305 Confidential ( u8 , [ u8 ; 32 ] ) ,
257306}
258- impl_confidential_commitment ! ( Nonce , 0x02 , 0x03 ) ;
307+ impl_confidential_commitment ! ( Nonce , [ u8 ; 32 ] , 0x02 , 0x03 ) ;
259308
260309impl Nonce {
261310 /// Serialized length, in bytes
@@ -266,28 +315,32 @@ impl Nonce {
266315 Nonce :: Confidential ( ..) => 33 ,
267316 }
268317 }
318+ }
269319
270- /// Check if the nonce is explicit.
271- pub fn is_explicit ( & self ) -> bool {
272- match * self {
273- Nonce :: Explicit ( _) => true ,
274- _ => false ,
275- }
276- }
277-
278- /// Returns the explicit nonce.
279- /// Returns [None] if [is_explicit] returns false.
280- pub fn explicit ( & self ) -> Option < sha256d:: Hash > {
320+ impl fmt:: Display for Nonce {
321+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
281322 match * self {
282- Nonce :: Explicit ( v) => Some ( v) ,
283- _ => None ,
323+ Nonce :: Null => f. write_str ( "null" ) ,
324+ Nonce :: Explicit ( n) => {
325+ for b in n. iter ( ) {
326+ write ! ( f, "{:02x}" , b) ?;
327+ }
328+ Ok ( ( ) )
329+ } ,
330+ Nonce :: Confidential ( prefix, bytes) => {
331+ write ! ( f, "{:02x}" , prefix) ?;
332+ for b in bytes. iter ( ) {
333+ write ! ( f, "{:02x}" , b) ?;
334+ }
335+ Ok ( ( ) )
336+ }
284337 }
285338 }
286339}
287340
288341#[ cfg( test) ]
289342mod tests {
290- use bitcoin:: hashes:: { Hash , sha256} ;
343+ use bitcoin:: hashes:: sha256;
291344 use super :: * ;
292345
293346 #[ test]
@@ -305,7 +358,7 @@ mod tests {
305358
306359 let nonces = [
307360 Nonce :: Null ,
308- Nonce :: Explicit ( sha256d :: Hash :: from_inner ( [ 0 ; 32 ] ) ) ,
361+ Nonce :: Explicit ( [ 0 ; 32 ] ) ,
309362 Nonce :: Confidential ( 0x02 , [ 1 ; 32 ] ) ,
310363 ] ;
311364 for v in & nonces[ ..] {
@@ -325,5 +378,26 @@ mod tests {
325378 assert_eq ! ( x. len( ) , v. encoded_length( ) ) ;
326379 }
327380 }
381+
382+ #[ test]
383+ fn commitments ( ) {
384+ let x = Value :: Confidential ( 0x08 , [ 1 ; 32 ] ) ;
385+ let mut commitment = x. commitment ( ) . unwrap ( ) ;
386+ assert_eq ! ( x, Value :: from_commitment( & commitment[ ..] ) . unwrap( ) ) ;
387+ commitment[ 0 ] = 42 ;
388+ assert ! ( Value :: from_commitment( & commitment[ ..] ) . is_err( ) ) ;
389+
390+ let x = Asset :: Confidential ( 0x0a , [ 1 ; 32 ] ) ;
391+ let mut commitment = x. commitment ( ) . unwrap ( ) ;
392+ assert_eq ! ( x, Asset :: from_commitment( & commitment[ ..] ) . unwrap( ) ) ;
393+ commitment[ 0 ] = 42 ;
394+ assert ! ( Asset :: from_commitment( & commitment[ ..] ) . is_err( ) ) ;
395+
396+ let x = Nonce :: Confidential ( 0x02 , [ 1 ; 32 ] ) ;
397+ let mut commitment = x. commitment ( ) . unwrap ( ) ;
398+ assert_eq ! ( x, Nonce :: from_commitment( & commitment[ ..] ) . unwrap( ) ) ;
399+ commitment[ 0 ] = 42 ;
400+ assert ! ( Nonce :: from_commitment( & commitment[ ..] ) . is_err( ) ) ;
401+ }
328402}
329403
0 commit comments