1818use std:: io:: Cursor ;
1919use std:: { error, fmt, io, mem} ;
2020
21- use bitcoin:: consensus :: encode as btcenc ;
21+ use bitcoin:: ScriptBuf ;
2222use secp256k1_zkp:: { self , RangeProof , SurjectionProof , Tweak } ;
2323
2424use crate :: hashes:: { sha256, Hash } ;
@@ -38,7 +38,7 @@ pub enum Error {
3838 /// And I/O error
3939 Io ( io:: Error ) ,
4040 /// A Bitcoin encoding error.
41- Bitcoin ( btcenc :: Error ) ,
41+ Bitcoin ( bitcoin :: consensus :: encode :: Error ) ,
4242 /// Tried to allocate an oversized vector
4343 OversizedVectorAllocation {
4444 /// The capacity requested
@@ -62,6 +62,8 @@ pub enum Error {
6262 HexError ( crate :: hex:: Error ) ,
6363 /// Got a time-based locktime when expecting a height-based one, or vice-versa
6464 BadLockTime ( crate :: LockTime ) ,
65+ /// VarInt was encoded in a non-minimal way.
66+ NonMinimalVarInt ,
6567}
6668
6769impl fmt:: Display for Error {
@@ -87,23 +89,22 @@ impl fmt::Display for Error {
8789 Error :: PsetError ( ref e) => write ! ( f, "Pset Error: {}" , e) ,
8890 Error :: HexError ( ref e) => write ! ( f, "Hex error {}" , e) ,
8991 Error :: BadLockTime ( ref lt) => write ! ( f, "Invalid locktime {}" , lt) ,
92+ Error :: NonMinimalVarInt => write ! ( f, "non-minimal varint" ) ,
9093 }
9194 }
9295}
9396
9497impl error:: Error for Error {
9598 fn cause ( & self ) -> Option < & dyn error:: Error > {
9699 match * self {
97- Error :: Bitcoin ( ref e) => Some ( e) ,
98100 Error :: Secp256k1zkp ( ref e) => Some ( e) ,
99101 _ => None ,
100102 }
101103 }
102104}
103-
104105#[ doc( hidden) ]
105- impl From < btcenc :: Error > for Error {
106- fn from ( e : btcenc :: Error ) -> Error {
106+ impl From < bitcoin :: consensus :: encode :: Error > for Error {
107+ fn from ( e : bitcoin :: consensus :: encode :: Error ) -> Error {
107108 Error :: Bitcoin ( e)
108109 }
109110}
@@ -210,42 +211,11 @@ pub(crate) fn consensus_encode_with_size<S: io::Write>(
210211 data : & [ u8 ] ,
211212 mut s : S ,
212213) -> Result < usize , Error > {
213- let vi_len = bitcoin :: VarInt ( data. len ( ) as u64 ) . consensus_encode ( & mut s) ?;
214+ let vi_len = VarInt ( data. len ( ) as u64 ) . consensus_encode ( & mut s) ?;
214215 s. emit_slice ( data) ?;
215216 Ok ( vi_len + data. len ( ) )
216217}
217218
218- /// Implement Elements encodable traits for Bitcoin encodable types.
219- macro_rules! impl_upstream {
220- ( $type: ty) => {
221- impl Encodable for $type {
222- fn consensus_encode<W : io:: Write >( & self , mut e: W ) -> Result <usize , Error > {
223- Ok ( btcenc:: Encodable :: consensus_encode( self , & mut e) ?)
224- }
225- }
226-
227- impl Decodable for $type {
228- fn consensus_decode<D : io:: Read >( mut d: D ) -> Result <Self , Error > {
229- Ok ( btcenc:: Decodable :: consensus_decode( & mut d) ?)
230- }
231- }
232- } ;
233- }
234- impl_upstream ! ( u8 ) ;
235- impl_upstream ! ( u32 ) ;
236- impl_upstream ! ( u64 ) ;
237- impl_upstream ! ( [ u8 ; 4 ] ) ;
238- impl_upstream ! ( [ u8 ; 32 ] ) ;
239- impl_upstream ! ( Box <[ u8 ] >) ;
240- impl_upstream ! ( [ u8 ; 33 ] ) ;
241- impl_upstream ! ( Vec <u8 >) ;
242- impl_upstream ! ( Vec <Vec <u8 >>) ;
243- impl_upstream ! ( btcenc:: VarInt ) ;
244- impl_upstream ! ( bitcoin:: Transaction ) ;
245- impl_upstream ! ( bitcoin:: BlockHash ) ;
246- impl_upstream ! ( bitcoin:: ScriptBuf ) ;
247- impl_upstream ! ( crate :: hashes:: sha256d:: Hash ) ;
248-
249219// Specific locktime types (which appear in PSET/PSBT2 but not in rust-bitcoin PSBT)
250220impl Encodable for crate :: locktime:: Height {
251221 fn consensus_encode < S : io:: Write > ( & self , s : S ) -> Result < usize , Error > {
@@ -275,14 +245,133 @@ impl Decodable for crate::locktime::Time {
275245 }
276246}
277247
248+ // TODO reuse bitcoin's `WriteExt::emit_varint`, `ReadExt::read_varint` when available
249+
250+ /// A variable sized integer.
251+ pub struct VarInt ( pub u64 ) ;
252+ impl Encodable for VarInt {
253+ fn consensus_encode < W : io:: Write > ( & self , mut e : W ) -> Result < usize , Error > {
254+ match self . 0 {
255+ i @ 0 ..=0xFC => {
256+ e. emit_u8 ( i as u8 ) ?;
257+ Ok ( 1 )
258+ }
259+ i @ 0xFD ..=0xFFFF => {
260+ e. emit_u8 ( 0xFD ) ?;
261+ e. emit_u16 ( i as u16 ) ?;
262+ Ok ( 3 )
263+ }
264+ i @ 0x10000 ..=0xFFFFFFFF => {
265+ e. emit_u8 ( 0xFE ) ?;
266+ e. emit_u32 ( i as u32 ) ?;
267+ Ok ( 5 )
268+ }
269+ i => {
270+ e. emit_u8 ( 0xFF ) ?;
271+ e. emit_u64 ( i) ?;
272+ Ok ( 9 )
273+ }
274+ }
275+ }
276+ }
277+ impl Decodable for VarInt {
278+ fn consensus_decode < D : io:: Read > ( mut d : D ) -> Result < Self , Error > {
279+ match d. read_u8 ( ) ? {
280+ 0xFF => {
281+ let x = d. read_u64 ( ) ?;
282+ if x < 0x100000000 {
283+ Err ( Error :: NonMinimalVarInt )
284+ } else {
285+ Ok ( VarInt ( x) )
286+ }
287+ }
288+ 0xFE => {
289+ let x = d. read_u32 ( ) ?;
290+ if x < 0x10000 {
291+ Err ( Error :: NonMinimalVarInt )
292+ } else {
293+ Ok ( VarInt ( x as u64 ) )
294+ }
295+ }
296+ 0xFD => {
297+ let x = d. read_u16 ( ) ?;
298+ if x < 0xFD {
299+ Err ( Error :: NonMinimalVarInt )
300+ } else {
301+ Ok ( VarInt ( x as u64 ) )
302+ }
303+ }
304+ n => Ok ( VarInt ( n as u64 ) ) ,
305+ }
306+ }
307+ }
308+ impl VarInt {
309+ /// returns the byte size used if this var int is serialized
310+ pub fn size ( & self ) -> usize {
311+ match self . 0 {
312+ 0 ..=0xFC => 1 ,
313+ 0xFD ..=0xFFFF => 3 ,
314+ 0x10000 ..=0xFFFFFFFF => 5 ,
315+ _ => 9 ,
316+ }
317+ }
318+ }
319+
320+ // Primitive types
321+ macro_rules! impl_int {
322+ ( $ty: ident, $meth_dec: ident, $meth_enc: ident) => {
323+ impl Encodable for $ty {
324+ fn consensus_encode<W : io:: Write >( & self , mut w: W ) -> Result <usize , Error > {
325+ w. $meth_enc( * self ) ?;
326+ Ok ( mem:: size_of:: <$ty>( ) )
327+ }
328+ }
329+ impl Decodable for $ty {
330+ fn consensus_decode<R : io:: Read >( mut r: R ) -> Result <Self , Error > {
331+ Ok ( ReadExt :: $meth_dec( & mut r) ?)
332+ }
333+ }
334+ } ;
335+ }
336+
337+ impl_int ! ( u8 , read_u8, emit_u8) ;
338+ impl_int ! ( u16 , read_u16, emit_u16) ;
339+ impl_int ! ( u32 , read_u32, emit_u32) ;
340+ impl_int ! ( u64 , read_u64, emit_u64) ;
341+
342+ impl Encodable for bitcoin:: ScriptBuf {
343+ fn consensus_encode < W : io:: Write > ( & self , w : W ) -> Result < usize , Error > {
344+ consensus_encode_with_size ( self . as_script ( ) . as_bytes ( ) , w)
345+ }
346+ }
347+ impl Decodable for bitcoin:: ScriptBuf {
348+ fn consensus_decode < D : io:: Read > ( d : D ) -> Result < Self , Error > {
349+ let bytes = Vec :: < u8 > :: consensus_decode ( d) ?;
350+ Ok ( ScriptBuf :: from_bytes ( bytes) )
351+ }
352+ }
353+
354+ impl Encodable for bitcoin:: hashes:: sha256d:: Hash {
355+ fn consensus_encode < W : io:: Write > ( & self , mut w : W ) -> Result < usize , Error > {
356+ self . as_byte_array ( ) . consensus_encode ( & mut w)
357+ }
358+ }
359+ impl Decodable for bitcoin:: hashes:: sha256d:: Hash {
360+ fn consensus_decode < D : io:: Read > ( d : D ) -> Result < Self , Error > {
361+ Ok ( Self :: from_byte_array (
362+ <<Self as Hash >:: Bytes >:: consensus_decode ( d) ?,
363+ ) )
364+ }
365+ }
366+
278367// Vectors
279368macro_rules! impl_vec {
280369 ( $type: ty) => {
281370 impl Encodable for Vec <$type> {
282371 #[ inline]
283372 fn consensus_encode<S : io:: Write >( & self , mut s: S ) -> Result <usize , Error > {
284373 let mut len = 0 ;
285- len += btcenc :: VarInt ( self . len( ) as u64 ) . consensus_encode( & mut s) ?;
374+ len += VarInt ( self . len( ) as u64 ) . consensus_encode( & mut s) ?;
286375 for c in self . iter( ) {
287376 len += c. consensus_encode( & mut s) ?;
288377 }
@@ -293,7 +382,7 @@ macro_rules! impl_vec {
293382 impl Decodable for Vec <$type> {
294383 #[ inline]
295384 fn consensus_decode<D : io:: Read >( mut d: D ) -> Result <Self , Error > {
296- let len = btcenc :: VarInt :: consensus_decode( & mut d) ?. 0 ;
385+ let len = VarInt :: consensus_decode( & mut d) ?. 0 ;
297386 let byte_size = ( len as usize )
298387 . checked_mul( mem:: size_of:: <$type>( ) )
299388 . ok_or( self :: Error :: ParseFailed ( "Invalid length" ) ) ?;
@@ -316,6 +405,60 @@ impl_vec!(TxIn);
316405impl_vec ! ( TxOut ) ;
317406impl_vec ! ( Transaction ) ;
318407impl_vec ! ( TapLeafHash ) ;
408+ impl_vec ! ( Vec <u8 >) ; // Vec<Vec<u8>>
409+
410+ macro_rules! impl_array {
411+ ( $size: literal ) => {
412+ impl Encodable for [ u8 ; $size] {
413+ #[ inline]
414+ fn consensus_encode<W : WriteExt >(
415+ & self ,
416+ mut w: W ,
417+ ) -> core:: result:: Result <usize , Error > {
418+ w. emit_slice( & self [ ..] ) ?;
419+ Ok ( $size)
420+ }
421+ }
422+
423+ impl Decodable for [ u8 ; $size] {
424+ #[ inline]
425+ fn consensus_decode<R : ReadExt >( mut r: R ) -> core:: result:: Result <Self , Error > {
426+ let mut ret = [ 0 ; $size] ;
427+ r. read_slice( & mut ret) ?;
428+ Ok ( ret)
429+ }
430+ }
431+ } ;
432+ }
433+ impl_array ! ( 4 ) ;
434+ impl_array ! ( 32 ) ;
435+ impl_array ! ( 33 ) ;
436+
437+ impl Encodable for Box < [ u8 ] > {
438+ fn consensus_encode < W : io:: Write > ( & self , mut w : W ) -> Result < usize , Error > {
439+ consensus_encode_with_size ( & self [ ..] , & mut w)
440+ }
441+ }
442+ impl Decodable for Box < [ u8 ] > {
443+ fn consensus_decode < D : io:: Read > ( d : D ) -> Result < Self , Error > {
444+ let v = Vec :: < u8 > :: consensus_decode ( d) ?;
445+ Ok ( v. into ( ) )
446+ }
447+ }
448+
449+ impl Encodable for Vec < u8 > {
450+ fn consensus_encode < W : io:: Write > ( & self , mut w : W ) -> Result < usize , Error > {
451+ consensus_encode_with_size ( & self [ ..] , & mut w)
452+ }
453+ }
454+ impl Decodable for Vec < u8 > {
455+ fn consensus_decode < D : io:: Read > ( mut d : D ) -> Result < Self , Error > {
456+ let s = VarInt :: consensus_decode ( & mut d) ?. 0 as usize ;
457+ let mut v = vec ! [ 0 ; s] ;
458+ d. read_slice ( & mut v) ?;
459+ Ok ( v)
460+ }
461+ }
319462
320463macro_rules! impl_box_option {
321464 ( $type: ty) => {
0 commit comments