@@ -239,9 +239,10 @@ pub fn read_scriptint(v: &[u8]) -> Result<i64, Error> {
239
239
/// else as true", except that the overflow rules don't apply.
240
240
#[ inline]
241
241
pub fn read_scriptbool ( v : & [ u8 ] ) -> bool {
242
- !( v. is_empty ( ) ||
243
- ( ( v[ v. len ( ) - 1 ] == 0 || v[ v. len ( ) - 1 ] == 0x80 ) &&
244
- v. iter ( ) . rev ( ) . skip ( 1 ) . all ( |& w| w == 0 ) ) )
242
+ match v. split_last ( ) {
243
+ Some ( ( last, rest) ) => !( ( last & !0x80 == 0x00 ) && rest. iter ( ) . all ( |& b| b == 0 ) ) ,
244
+ None => false ,
245
+ }
245
246
}
246
247
247
248
/// Read a script-encoded unsigned integer
@@ -417,32 +418,37 @@ impl Script {
417
418
/// Checks whether a script pubkey is a p2sh output
418
419
#[ inline]
419
420
pub fn is_p2sh ( & self ) -> bool {
420
- self . 0 . len ( ) == 23 &&
421
- self . 0 [ 0 ] == opcodes:: all:: OP_HASH160 . into_u8 ( ) &&
422
- self . 0 [ 1 ] == opcodes:: all:: OP_PUSHBYTES_20 . into_u8 ( ) &&
423
- self . 0 [ 22 ] == opcodes:: all:: OP_EQUAL . into_u8 ( )
421
+ self . 0 . len ( ) == 23
422
+ && self . 0 [ 0 ] == opcodes:: all:: OP_HASH160 . into_u8 ( )
423
+ && self . 0 [ 1 ] == opcodes:: all:: OP_PUSHBYTES_20 . into_u8 ( )
424
+ && self . 0 [ 22 ] == opcodes:: all:: OP_EQUAL . into_u8 ( )
424
425
}
425
426
426
427
/// Checks whether a script pubkey is a p2pkh output
427
428
#[ inline]
428
429
pub fn is_p2pkh ( & self ) -> bool {
429
- self . 0 . len ( ) == 25 &&
430
- self . 0 [ 0 ] == opcodes:: all:: OP_DUP . into_u8 ( ) &&
431
- self . 0 [ 1 ] == opcodes:: all:: OP_HASH160 . into_u8 ( ) &&
432
- self . 0 [ 2 ] == opcodes:: all:: OP_PUSHBYTES_20 . into_u8 ( ) &&
433
- self . 0 [ 23 ] == opcodes:: all:: OP_EQUALVERIFY . into_u8 ( ) &&
434
- self . 0 [ 24 ] == opcodes:: all:: OP_CHECKSIG . into_u8 ( )
430
+ self . 0 . len ( ) == 25
431
+ && self . 0 [ 0 ] == opcodes:: all:: OP_DUP . into_u8 ( )
432
+ && self . 0 [ 1 ] == opcodes:: all:: OP_HASH160 . into_u8 ( )
433
+ && self . 0 [ 2 ] == opcodes:: all:: OP_PUSHBYTES_20 . into_u8 ( )
434
+ && self . 0 [ 23 ] == opcodes:: all:: OP_EQUALVERIFY . into_u8 ( )
435
+ && self . 0 [ 24 ] == opcodes:: all:: OP_CHECKSIG . into_u8 ( )
435
436
}
436
437
437
438
/// Checks whether a script pubkey is a p2pk output
438
439
#[ inline]
439
440
pub fn is_p2pk ( & self ) -> bool {
440
- ( self . 0 . len ( ) == 67 &&
441
- self . 0 [ 0 ] == opcodes:: all:: OP_PUSHBYTES_65 . into_u8 ( ) &&
442
- self . 0 [ 66 ] == opcodes:: all:: OP_CHECKSIG . into_u8 ( ) )
443
- || ( self . 0 . len ( ) == 35 &&
444
- self . 0 [ 0 ] == opcodes:: all:: OP_PUSHBYTES_33 . into_u8 ( ) &&
445
- self . 0 [ 34 ] == opcodes:: all:: OP_CHECKSIG . into_u8 ( ) )
441
+ match self . len ( ) {
442
+ 67 => {
443
+ self . 0 [ 0 ] == opcodes:: all:: OP_PUSHBYTES_65 . into_u8 ( )
444
+ && self . 0 [ 66 ] == opcodes:: all:: OP_CHECKSIG . into_u8 ( )
445
+ }
446
+ 35 => {
447
+ self . 0 [ 0 ] == opcodes:: all:: OP_PUSHBYTES_33 . into_u8 ( )
448
+ && self . 0 [ 34 ] == opcodes:: all:: OP_CHECKSIG . into_u8 ( )
449
+ }
450
+ _ => false
451
+ }
446
452
}
447
453
448
454
/// Checks whether a script pubkey is a Segregated Witness (segwit) program.
@@ -468,37 +474,48 @@ impl Script {
468
474
/// Checks whether a script pubkey is a p2wsh output
469
475
#[ inline]
470
476
pub fn is_v0_p2wsh ( & self ) -> bool {
471
- self . 0 . len ( ) == 34 &&
472
- self . witness_version ( ) == Some ( WitnessVersion :: V0 ) &&
473
- self . 0 [ 1 ] == opcodes:: all:: OP_PUSHBYTES_32 . into_u8 ( )
477
+ self . 0 . len ( ) == 34
478
+ && self . witness_version ( ) == Some ( WitnessVersion :: V0 )
479
+ && self . 0 [ 1 ] == opcodes:: all:: OP_PUSHBYTES_32 . into_u8 ( )
474
480
}
475
481
476
482
/// Checks whether a script pubkey is a p2wpkh output
477
483
#[ inline]
478
484
pub fn is_v0_p2wpkh ( & self ) -> bool {
479
- self . 0 . len ( ) == 22 &&
480
- self . witness_version ( ) == Some ( WitnessVersion :: V0 ) &&
481
- self . 0 [ 1 ] == opcodes:: all:: OP_PUSHBYTES_20 . into_u8 ( )
485
+ self . 0 . len ( ) == 22
486
+ && self . witness_version ( ) == Some ( WitnessVersion :: V0 )
487
+ && self . 0 [ 1 ] == opcodes:: all:: OP_PUSHBYTES_20 . into_u8 ( )
482
488
}
483
489
484
490
/// Checks whether a script pubkey is a P2TR output
485
491
#[ inline]
486
492
pub fn is_v1_p2tr ( & self ) -> bool {
487
- self . 0 . len ( ) == 34 &&
488
- self . witness_version ( ) == Some ( WitnessVersion :: V1 ) &&
489
- self . 0 [ 1 ] == opcodes:: all:: OP_PUSHBYTES_32 . into_u8 ( )
493
+ self . 0 . len ( ) == 34
494
+ && self . witness_version ( ) == Some ( WitnessVersion :: V1 )
495
+ && self . 0 [ 1 ] == opcodes:: all:: OP_PUSHBYTES_32 . into_u8 ( )
490
496
}
491
497
492
498
/// Check if this is an OP_RETURN output
493
499
pub fn is_op_return ( & self ) -> bool {
494
- !self . 0 . is_empty ( ) && ( opcodes:: All :: from ( self . 0 [ 0 ] ) == opcodes:: all:: OP_RETURN )
500
+ match self . 0 . first ( ) {
501
+ Some ( b) => * b == opcodes:: all:: OP_RETURN . into_u8 ( ) ,
502
+ None => false
503
+ }
495
504
}
496
505
497
506
/// Whether a script can be proven to have no satisfying input
498
507
pub fn is_provably_unspendable ( & self ) -> bool {
499
- !self . 0 . is_empty ( ) &&
500
- ( opcodes:: All :: from ( self . 0 [ 0 ] ) . classify ( opcodes:: ClassifyContext :: Legacy ) == opcodes:: Class :: ReturnOp ||
501
- opcodes:: All :: from ( self . 0 [ 0 ] ) . classify ( opcodes:: ClassifyContext :: Legacy ) == opcodes:: Class :: IllegalOp )
508
+ use blockdata:: opcodes:: Class :: { ReturnOp , IllegalOp } ;
509
+
510
+ match self . 0 . first ( ) {
511
+ Some ( b) => {
512
+ let first = opcodes:: All :: from ( * b) ;
513
+ let class = first. classify ( opcodes:: ClassifyContext :: Legacy ) ;
514
+
515
+ class == ReturnOp || class == IllegalOp
516
+ } ,
517
+ None => false ,
518
+ }
502
519
}
503
520
504
521
/// Gets the minimum value an output with this script should have in order to be
@@ -1448,5 +1465,23 @@ mod test {
1448
1465
assert ! ( instructions. next( ) . is_none( ) ) ;
1449
1466
assert ! ( instructions. next( ) . is_none( ) ) ;
1450
1467
}
1468
+
1469
+ #[ test]
1470
+ fn read_scriptbool_zero_is_false ( ) {
1471
+ let v: Vec < u8 > = vec ! [ 0x00 , 0x00 , 0x00 , 0x00 ] ;
1472
+ assert ! ( !read_scriptbool( & v) ) ;
1473
+
1474
+ let v: Vec < u8 > = vec ! [ 0x00 , 0x00 , 0x00 , 0x80 ] ; // With sign bit set.
1475
+ assert ! ( !read_scriptbool( & v) ) ;
1476
+ }
1477
+
1478
+ #[ test]
1479
+ fn read_scriptbool_non_zero_is_true ( ) {
1480
+ let v: Vec < u8 > = vec ! [ 0x01 , 0x00 , 0x00 , 0x00 ] ;
1481
+ assert ! ( read_scriptbool( & v) ) ;
1482
+
1483
+ let v: Vec < u8 > = vec ! [ 0x01 , 0x00 , 0x00 , 0x80 ] ; // With sign bit set.
1484
+ assert ! ( read_scriptbool( & v) ) ;
1485
+ }
1451
1486
}
1452
1487
0 commit comments