1818use std:: io:: Cursor ;
1919use std:: { error, fmt, io, mem} ;
2020
21- use bitcoin:: consensus:: encode as btcenc;
2221use secp256k1_zkp:: { self , RangeProof , SurjectionProof , Tweak } ;
2322
2423use crate :: hashes:: { sha256, Hash } ;
@@ -38,7 +37,7 @@ pub enum Error {
3837 /// And I/O error
3938 Io ( io:: Error ) ,
4039 /// A Bitcoin encoding error.
41- Bitcoin ( btcenc :: Error ) ,
40+ Bitcoin ( bitcoin :: consensus :: encode :: Error ) ,
4241 /// Tried to allocate an oversized vector
4342 OversizedVectorAllocation {
4443 /// The capacity requested
@@ -62,6 +61,8 @@ pub enum Error {
6261 HexError ( crate :: hex:: Error ) ,
6362 /// Got a time-based locktime when expecting a height-based one, or vice-versa
6463 BadLockTime ( crate :: LockTime ) ,
64+ /// VarInt was encoded in a non-minimal way.
65+ NonMinimalVarInt ,
6566}
6667
6768impl fmt:: Display for Error {
@@ -87,23 +88,22 @@ impl fmt::Display for Error {
8788 Error :: PsetError ( ref e) => write ! ( f, "Pset Error: {}" , e) ,
8889 Error :: HexError ( ref e) => write ! ( f, "Hex error {}" , e) ,
8990 Error :: BadLockTime ( ref lt) => write ! ( f, "Invalid locktime {}" , lt) ,
91+ Error :: NonMinimalVarInt => write ! ( f, "non-minimal varint" ) ,
9092 }
9193 }
9294}
9395
9496impl error:: Error for Error {
9597 fn cause ( & self ) -> Option < & dyn error:: Error > {
9698 match * self {
97- Error :: Bitcoin ( ref e) => Some ( e) ,
9899 Error :: Secp256k1zkp ( ref e) => Some ( e) ,
99100 _ => None ,
100101 }
101102 }
102103}
103-
104104#[ doc( hidden) ]
105- impl From < btcenc :: Error > for Error {
106- fn from ( e : btcenc :: Error ) -> Error {
105+ impl From < bitcoin :: consensus :: encode :: Error > for Error {
106+ fn from ( e : bitcoin :: consensus :: encode :: Error ) -> Error {
107107 Error :: Bitcoin ( e)
108108 }
109109}
@@ -210,42 +210,11 @@ pub(crate) fn consensus_encode_with_size<S: io::Write>(
210210 data : & [ u8 ] ,
211211 mut s : S ,
212212) -> Result < usize , Error > {
213- let vi_len = bitcoin :: VarInt ( data. len ( ) as u64 ) . consensus_encode ( & mut s) ?;
213+ let vi_len = VarInt ( data. len ( ) as u64 ) . consensus_encode ( & mut s) ?;
214214 s. emit_slice ( data) ?;
215215 Ok ( vi_len + data. len ( ) )
216216}
217217
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-
249218// Specific locktime types (which appear in PSET/PSBT2 but not in rust-bitcoin PSBT)
250219impl Encodable for crate :: locktime:: Height {
251220 fn consensus_encode < S : io:: Write > ( & self , s : S ) -> Result < usize , Error > {
@@ -275,14 +244,136 @@ impl Decodable for crate::locktime::Time {
275244 }
276245}
277246
247+ // TODO reuse bitcoin's `WriteExt::emit_varint`, `ReadExt::read_varint` when available
248+
249+ /// A variable sized integer.
250+ pub struct VarInt ( pub u64 ) ;
251+ impl Encodable for VarInt {
252+ fn consensus_encode < W : io:: Write > ( & self , mut e : W ) -> Result < usize , Error > {
253+ match self . 0 {
254+ i @ 0 ..=0xFC => {
255+ e. emit_u8 ( i as u8 ) ?;
256+ Ok ( 1 )
257+ }
258+ i @ 0xFD ..=0xFFFF => {
259+ e. emit_u8 ( 0xFD ) ?;
260+ e. emit_u16 ( i as u16 ) ?;
261+ Ok ( 3 )
262+ }
263+ i @ 0x10000 ..=0xFFFFFFFF => {
264+ e. emit_u8 ( 0xFE ) ?;
265+ e. emit_u32 ( i as u32 ) ?;
266+ Ok ( 5 )
267+ }
268+ i => {
269+ e. emit_u8 ( 0xFF ) ?;
270+ e. emit_u64 ( i) ?;
271+ Ok ( 9 )
272+ }
273+ }
274+ }
275+ }
276+ impl Decodable for VarInt {
277+ fn consensus_decode < D : io:: Read > ( mut d : D ) -> Result < Self , Error > {
278+ match d. read_u8 ( ) ? {
279+ 0xFF => {
280+ let x = d. read_u64 ( ) ?;
281+ if x < 0x100000000 {
282+ Err ( Error :: NonMinimalVarInt )
283+ } else {
284+ Ok ( VarInt ( x) )
285+ }
286+ }
287+ 0xFE => {
288+ let x = d. read_u32 ( ) ?;
289+ if x < 0x10000 {
290+ Err ( Error :: NonMinimalVarInt )
291+ } else {
292+ Ok ( VarInt ( x as u64 ) )
293+ }
294+ }
295+ 0xFD => {
296+ let x = d. read_u16 ( ) ?;
297+ if x < 0xFD {
298+ Err ( Error :: NonMinimalVarInt )
299+ } else {
300+ Ok ( VarInt ( x as u64 ) )
301+ }
302+ }
303+ n => Ok ( VarInt ( n as u64 ) ) ,
304+ }
305+ }
306+ }
307+ impl VarInt {
308+ /// returns the byte size used if this var int is serialized
309+ pub fn size ( & self ) -> usize {
310+ match self . 0 {
311+ 0 ..=0xFC => 1 ,
312+ 0xFD ..=0xFFFF => 3 ,
313+ 0x10000 ..=0xFFFFFFFF => 5 ,
314+ _ => 9 ,
315+ }
316+ }
317+ }
318+
319+ // Primitive types
320+ macro_rules! impl_int {
321+ ( $ty: ident, $meth_dec: ident, $meth_enc: ident) => {
322+ impl Encodable for $ty {
323+ fn consensus_encode<W : io:: Write >( & self , mut w: W ) -> Result <usize , Error > {
324+ w. $meth_enc( * self ) ?;
325+ Ok ( mem:: size_of:: <$ty>( ) )
326+ }
327+ }
328+ impl Decodable for $ty {
329+ fn consensus_decode<R : io:: Read >( mut r: R ) -> Result <Self , Error > {
330+ Ok ( ReadExt :: $meth_dec( & mut r) ?)
331+ }
332+ }
333+ } ;
334+ }
335+
336+ impl_int ! ( u8 , read_u8, emit_u8) ;
337+ impl_int ! ( u16 , read_u16, emit_u16) ;
338+ impl_int ! ( u32 , read_u32, emit_u32) ;
339+ impl_int ! ( u64 , read_u64, emit_u64) ;
340+
341+ impl Encodable for bitcoin:: ScriptBuf {
342+ fn consensus_encode < W : io:: Write > ( & self , mut w : W ) -> Result < usize , Error > {
343+ Ok ( bitcoin:: consensus:: encode:: Encodable :: consensus_encode (
344+ & self , & mut w,
345+ ) ?)
346+ }
347+ }
348+ impl Decodable for bitcoin:: ScriptBuf {
349+ fn consensus_decode < D : io:: Read > ( mut d : D ) -> Result < Self , Error > {
350+ Ok ( bitcoin:: consensus:: encode:: Decodable :: consensus_decode (
351+ & mut d,
352+ ) ?)
353+ }
354+ }
355+
356+ impl Encodable for bitcoin:: hashes:: sha256d:: Hash {
357+ fn consensus_encode < W : io:: Write > ( & self , mut w : W ) -> Result < usize , Error > {
358+ self . as_byte_array ( ) . consensus_encode ( & mut w)
359+ }
360+ }
361+ impl Decodable for bitcoin:: hashes:: sha256d:: Hash {
362+ fn consensus_decode < D : io:: Read > ( d : D ) -> Result < Self , Error > {
363+ Ok ( Self :: from_byte_array (
364+ <<Self as Hash >:: Bytes >:: consensus_decode ( d) ?,
365+ ) )
366+ }
367+ }
368+
278369// Vectors
279370macro_rules! impl_vec {
280371 ( $type: ty) => {
281372 impl Encodable for Vec <$type> {
282373 #[ inline]
283374 fn consensus_encode<S : io:: Write >( & self , mut s: S ) -> Result <usize , Error > {
284375 let mut len = 0 ;
285- len += btcenc :: VarInt ( self . len( ) as u64 ) . consensus_encode( & mut s) ?;
376+ len += VarInt ( self . len( ) as u64 ) . consensus_encode( & mut s) ?;
286377 for c in self . iter( ) {
287378 len += c. consensus_encode( & mut s) ?;
288379 }
@@ -293,7 +384,7 @@ macro_rules! impl_vec {
293384 impl Decodable for Vec <$type> {
294385 #[ inline]
295386 fn consensus_decode<D : io:: Read >( mut d: D ) -> Result <Self , Error > {
296- let len = btcenc :: VarInt :: consensus_decode( & mut d) ?. 0 ;
387+ let len = VarInt :: consensus_decode( & mut d) ?. 0 ;
297388 let byte_size = ( len as usize )
298389 . checked_mul( mem:: size_of:: <$type>( ) )
299390 . ok_or( self :: Error :: ParseFailed ( "Invalid length" ) ) ?;
@@ -316,6 +407,60 @@ impl_vec!(TxIn);
316407impl_vec ! ( TxOut ) ;
317408impl_vec ! ( Transaction ) ;
318409impl_vec ! ( TapLeafHash ) ;
410+ impl_vec ! ( Vec <u8 >) ; // Vec<Vec<u8>>
411+
412+ macro_rules! impl_array {
413+ ( $size: literal ) => {
414+ impl Encodable for [ u8 ; $size] {
415+ #[ inline]
416+ fn consensus_encode<W : WriteExt >(
417+ & self ,
418+ mut w: W ,
419+ ) -> core:: result:: Result <usize , Error > {
420+ w. emit_slice( & self [ ..] ) ?;
421+ Ok ( $size)
422+ }
423+ }
424+
425+ impl Decodable for [ u8 ; $size] {
426+ #[ inline]
427+ fn consensus_decode<R : ReadExt >( mut r: R ) -> core:: result:: Result <Self , Error > {
428+ let mut ret = [ 0 ; $size] ;
429+ r. read_slice( & mut ret) ?;
430+ Ok ( ret)
431+ }
432+ }
433+ } ;
434+ }
435+ impl_array ! ( 4 ) ;
436+ impl_array ! ( 32 ) ;
437+ impl_array ! ( 33 ) ;
438+
439+ impl Encodable for Box < [ u8 ] > {
440+ fn consensus_encode < W : io:: Write > ( & self , mut w : W ) -> Result < usize , Error > {
441+ consensus_encode_with_size ( & self [ ..] , & mut w)
442+ }
443+ }
444+ impl Decodable for Box < [ u8 ] > {
445+ fn consensus_decode < D : io:: Read > ( d : D ) -> Result < Self , Error > {
446+ let v = Vec :: < u8 > :: consensus_decode ( d) ?;
447+ Ok ( v. into ( ) )
448+ }
449+ }
450+
451+ impl Encodable for Vec < u8 > {
452+ fn consensus_encode < W : io:: Write > ( & self , mut w : W ) -> Result < usize , Error > {
453+ consensus_encode_with_size ( & self [ ..] , & mut w)
454+ }
455+ }
456+ impl Decodable for Vec < u8 > {
457+ fn consensus_decode < D : io:: Read > ( mut d : D ) -> Result < Self , Error > {
458+ let s = VarInt :: consensus_decode ( & mut d) ?. 0 as usize ;
459+ let mut v = vec ! [ 0 ; s] ;
460+ d. read_slice ( & mut v) ?;
461+ Ok ( v)
462+ }
463+ }
319464
320465macro_rules! impl_box_option {
321466 ( $type: ty) => {
0 commit comments