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 } ;
@@ -27,9 +27,6 @@ use crate::transaction::{Transaction, TxIn, TxOut};
2727
2828pub use bitcoin:: { self , consensus:: encode:: MAX_VEC_SIZE } ;
2929
30- // Use the ReadExt/WriteExt traits as is from upstream
31- pub use bitcoin:: consensus:: encode:: { ReadExt , WriteExt } ;
32-
3330use crate :: taproot:: TapLeafHash ;
3431
3532/// Encoding error
@@ -38,7 +35,7 @@ pub enum Error {
3835 /// And I/O error
3936 Io ( io:: Error ) ,
4037 /// A Bitcoin encoding error.
41- Bitcoin ( btcenc :: Error ) ,
38+ Bitcoin ( bitcoin :: consensus :: encode :: Error ) ,
4239 /// Tried to allocate an oversized vector
4340 OversizedVectorAllocation {
4441 /// The capacity requested
@@ -62,6 +59,8 @@ pub enum Error {
6259 HexError ( crate :: hex:: Error ) ,
6360 /// Got a time-based locktime when expecting a height-based one, or vice-versa
6461 BadLockTime ( crate :: LockTime ) ,
62+ /// VarInt was encoded in a non-minimal way.
63+ NonMinimalVarInt ,
6564}
6665
6766impl fmt:: Display for Error {
@@ -87,23 +86,22 @@ impl fmt::Display for Error {
8786 Error :: PsetError ( ref e) => write ! ( f, "Pset Error: {}" , e) ,
8887 Error :: HexError ( ref e) => write ! ( f, "Hex error {}" , e) ,
8988 Error :: BadLockTime ( ref lt) => write ! ( f, "Invalid locktime {}" , lt) ,
89+ Error :: NonMinimalVarInt => write ! ( f, "non-minimal varint" ) ,
9090 }
9191 }
9292}
9393
9494impl error:: Error for Error {
9595 fn cause ( & self ) -> Option < & dyn error:: Error > {
9696 match * self {
97- Error :: Bitcoin ( ref e) => Some ( e) ,
9897 Error :: Secp256k1zkp ( ref e) => Some ( e) ,
9998 _ => None ,
10099 }
101100 }
102101}
103-
104102#[ doc( hidden) ]
105- impl From < btcenc :: Error > for Error {
106- fn from ( e : btcenc :: Error ) -> Error {
103+ impl From < bitcoin :: consensus :: encode :: Error > for Error {
104+ fn from ( e : bitcoin :: consensus :: encode :: Error ) -> Error {
107105 Error :: Bitcoin ( e)
108106 }
109107}
@@ -206,46 +204,15 @@ impl Decodable for sha256::Midstate {
206204 }
207205}
208206
209- pub ( crate ) fn consensus_encode_with_size < S : io :: Write > (
207+ pub ( crate ) fn consensus_encode_with_size < S : crate :: WriteExt > (
210208 data : & [ u8 ] ,
211209 mut s : S ,
212210) -> Result < usize , Error > {
213- let vi_len = bitcoin :: VarInt ( data. len ( ) as u64 ) . consensus_encode ( & mut s) ?;
211+ let vi_len = VarInt ( data. len ( ) as u64 ) . consensus_encode ( & mut s) ?;
214212 s. emit_slice ( data) ?;
215213 Ok ( vi_len + data. len ( ) )
216214}
217215
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-
249216// Specific locktime types (which appear in PSET/PSBT2 but not in rust-bitcoin PSBT)
250217impl Encodable for crate :: locktime:: Height {
251218 fn consensus_encode < S : io:: Write > ( & self , s : S ) -> Result < usize , Error > {
@@ -275,14 +242,85 @@ impl Decodable for crate::locktime::Time {
275242 }
276243}
277244
245+ /// A variable sized integer.
246+ pub struct VarInt ( pub u64 ) ;
247+ impl Encodable for VarInt {
248+ fn consensus_encode < W : crate :: WriteExt > ( & self , mut e : W ) -> Result < usize , Error > {
249+ Ok ( e. emit_varint ( self . 0 ) ?)
250+ }
251+ }
252+ impl Decodable for VarInt {
253+ fn consensus_decode < D : crate :: ReadExt > ( mut d : D ) -> Result < Self , Error > {
254+ Ok ( VarInt ( d. read_varint ( ) ?) )
255+ }
256+ }
257+ impl VarInt {
258+ /// returns the byte size used if this var int is serialized
259+ pub fn size ( & self ) -> usize {
260+ match self . 0 {
261+ 0 ..=0xFC => 1 ,
262+ 0xFD ..=0xFFFF => 3 ,
263+ 0x10000 ..=0xFFFFFFFF => 5 ,
264+ _ => 9 ,
265+ }
266+ }
267+ }
268+
269+ // Primitive types
270+ macro_rules! impl_int {
271+ ( $ty: ident, $meth_dec: ident, $meth_enc: ident) => {
272+ impl Encodable for $ty {
273+ fn consensus_encode<W : crate :: WriteExt >( & self , mut w: W ) -> Result <usize , Error > {
274+ w. $meth_enc( * self ) ?;
275+ Ok ( mem:: size_of:: <$ty>( ) )
276+ }
277+ }
278+ impl Decodable for $ty {
279+ fn consensus_decode<R : crate :: ReadExt >( mut r: R ) -> Result <Self , Error > {
280+ crate :: ReadExt :: $meth_dec( & mut r)
281+ }
282+ }
283+ } ;
284+ }
285+
286+ impl_int ! ( u8 , read_u8, emit_u8) ;
287+ impl_int ! ( u16 , read_u16, emit_u16) ;
288+ impl_int ! ( u32 , read_u32, emit_u32) ;
289+ impl_int ! ( u64 , read_u64, emit_u64) ;
290+
291+ impl Encodable for bitcoin:: ScriptBuf {
292+ fn consensus_encode < W : io:: Write > ( & self , w : W ) -> Result < usize , Error > {
293+ consensus_encode_with_size ( self . as_script ( ) . as_bytes ( ) , w)
294+ }
295+ }
296+ impl Decodable for bitcoin:: ScriptBuf {
297+ fn consensus_decode < D : io:: Read > ( d : D ) -> Result < Self , Error > {
298+ let bytes = Vec :: < u8 > :: consensus_decode ( d) ?;
299+ Ok ( ScriptBuf :: from_bytes ( bytes) )
300+ }
301+ }
302+
303+ impl Encodable for bitcoin:: hashes:: sha256d:: Hash {
304+ fn consensus_encode < W : io:: Write > ( & self , mut w : W ) -> Result < usize , Error > {
305+ self . as_byte_array ( ) . consensus_encode ( & mut w)
306+ }
307+ }
308+ impl Decodable for bitcoin:: hashes:: sha256d:: Hash {
309+ fn consensus_decode < D : io:: Read > ( d : D ) -> Result < Self , Error > {
310+ Ok ( Self :: from_byte_array (
311+ <<Self as Hash >:: Bytes >:: consensus_decode ( d) ?,
312+ ) )
313+ }
314+ }
315+
278316// Vectors
279317macro_rules! impl_vec {
280318 ( $type: ty) => {
281319 impl Encodable for Vec <$type> {
282320 #[ inline]
283321 fn consensus_encode<S : io:: Write >( & self , mut s: S ) -> Result <usize , Error > {
284322 let mut len = 0 ;
285- len += btcenc :: VarInt ( self . len( ) as u64 ) . consensus_encode( & mut s) ?;
323+ len += VarInt ( self . len( ) as u64 ) . consensus_encode( & mut s) ?;
286324 for c in self . iter( ) {
287325 len += c. consensus_encode( & mut s) ?;
288326 }
@@ -293,7 +331,7 @@ macro_rules! impl_vec {
293331 impl Decodable for Vec <$type> {
294332 #[ inline]
295333 fn consensus_decode<D : io:: Read >( mut d: D ) -> Result <Self , Error > {
296- let len = btcenc :: VarInt :: consensus_decode( & mut d) ?. 0 ;
334+ let len = VarInt :: consensus_decode( & mut d) ?. 0 ;
297335 let byte_size = ( len as usize )
298336 . checked_mul( mem:: size_of:: <$type>( ) )
299337 . ok_or( self :: Error :: ParseFailed ( "Invalid length" ) ) ?;
@@ -316,6 +354,60 @@ impl_vec!(TxIn);
316354impl_vec ! ( TxOut ) ;
317355impl_vec ! ( Transaction ) ;
318356impl_vec ! ( TapLeafHash ) ;
357+ impl_vec ! ( Vec <u8 >) ; // Vec<Vec<u8>>
358+
359+ macro_rules! impl_array {
360+ ( $size: literal ) => {
361+ impl Encodable for [ u8 ; $size] {
362+ #[ inline]
363+ fn consensus_encode<W : crate :: WriteExt >(
364+ & self ,
365+ mut w: W ,
366+ ) -> core:: result:: Result <usize , Error > {
367+ w. emit_slice( & self [ ..] ) ?;
368+ Ok ( $size)
369+ }
370+ }
371+
372+ impl Decodable for [ u8 ; $size] {
373+ #[ inline]
374+ fn consensus_decode<R : crate :: ReadExt >( mut r: R ) -> core:: result:: Result <Self , Error > {
375+ let mut ret = [ 0 ; $size] ;
376+ r. read_slice( & mut ret) ?;
377+ Ok ( ret)
378+ }
379+ }
380+ } ;
381+ }
382+ impl_array ! ( 4 ) ;
383+ impl_array ! ( 32 ) ;
384+ impl_array ! ( 33 ) ;
385+
386+ impl Encodable for Box < [ u8 ] > {
387+ fn consensus_encode < W : io:: Write > ( & self , mut w : W ) -> Result < usize , Error > {
388+ consensus_encode_with_size ( & self [ ..] , & mut w)
389+ }
390+ }
391+ impl Decodable for Box < [ u8 ] > {
392+ fn consensus_decode < D : io:: Read > ( d : D ) -> Result < Self , Error > {
393+ let v = Vec :: < u8 > :: consensus_decode ( d) ?;
394+ Ok ( v. into ( ) )
395+ }
396+ }
397+
398+ impl Encodable for Vec < u8 > {
399+ fn consensus_encode < W : io:: Write > ( & self , mut w : W ) -> Result < usize , Error > {
400+ consensus_encode_with_size ( & self [ ..] , & mut w)
401+ }
402+ }
403+ impl Decodable for Vec < u8 > {
404+ fn consensus_decode < D : crate :: ReadExt > ( mut d : D ) -> Result < Self , Error > {
405+ let s = VarInt :: consensus_decode ( & mut d) ?. 0 as usize ;
406+ let mut v = vec ! [ 0 ; s] ;
407+ d. read_slice ( & mut v) ?;
408+ Ok ( v)
409+ }
410+ }
319411
320412macro_rules! impl_box_option {
321413 ( $type: ty) => {
0 commit comments