@@ -81,7 +81,9 @@ pub enum Error {
81
81
/// An uncompressed pubkey was used where it is not allowed.
82
82
UncompressedPubkey ,
83
83
/// Address size more than 520 bytes is not allowed.
84
- ExcessiveScriptSize
84
+ ExcessiveScriptSize ,
85
+ /// Script is not a p2pkh, p2sh or witness program.
86
+ UnrecognizedScript ,
85
87
}
86
88
87
89
impl fmt:: Display for Error {
@@ -98,6 +100,7 @@ impl fmt::Display for Error {
98
100
Error :: InvalidSegwitV0ProgramLength ( l) => write ! ( f, "a v0 witness program must be either of length 20 or 32 bytes: length={}" , l) ,
99
101
Error :: UncompressedPubkey => write ! ( f, "an uncompressed pubkey was used where it is not allowed" ) ,
100
102
Error :: ExcessiveScriptSize => write ! ( f, "Script size exceed 520 bytes" ) ,
103
+ Error :: UnrecognizedScript => write ! ( f, "script is not a p2pkh, p2sh or witness program" )
101
104
}
102
105
}
103
106
}
@@ -119,7 +122,8 @@ impl std::error::Error for Error {
119
122
| InvalidWitnessProgramLength ( _)
120
123
| InvalidSegwitV0ProgramLength ( _)
121
124
| UncompressedPubkey
122
- | ExcessiveScriptSize => None ,
125
+ | ExcessiveScriptSize
126
+ | UnrecognizedScript => None ,
123
127
}
124
128
}
125
129
}
@@ -386,8 +390,8 @@ pub enum Payload {
386
390
387
391
impl Payload {
388
392
/// Constructs a [Payload] from an output script (`scriptPubkey`).
389
- pub fn from_script ( script : & script:: Script ) -> Option < Payload > {
390
- Some ( if script. is_p2pkh ( ) {
393
+ pub fn from_script ( script : & script:: Script ) -> Result < Payload , Error > {
394
+ Ok ( if script. is_p2pkh ( ) {
391
395
let mut hash_inner = [ 0u8 ; 20 ] ;
392
396
hash_inner. copy_from_slice ( & script. as_bytes ( ) [ 3 ..23 ] ) ;
393
397
Payload :: PubkeyHash ( PubkeyHash :: from_inner ( hash_inner) )
@@ -396,12 +400,16 @@ impl Payload {
396
400
hash_inner. copy_from_slice ( & script. as_bytes ( ) [ 2 ..22 ] ) ;
397
401
Payload :: ScriptHash ( ScriptHash :: from_inner ( hash_inner) )
398
402
} else if script. is_witness_program ( ) {
403
+ if script. witness_version ( ) == Some ( WitnessVersion :: V0 ) && !( script. is_v0_p2wpkh ( ) || script. is_v0_p2wsh ( ) ) {
404
+ return Err ( Error :: InvalidSegwitV0ProgramLength ( script. len ( ) ) ) ;
405
+ }
406
+
399
407
Payload :: WitnessProgram {
400
- version : WitnessVersion :: from_opcode ( opcodes:: All :: from ( script[ 0 ] ) ) . ok ( ) ?,
408
+ version : WitnessVersion :: from_opcode ( opcodes:: All :: from ( script[ 0 ] ) ) ?,
401
409
program : script[ 2 ..] . to_vec ( ) ,
402
410
}
403
411
} else {
404
- return None ;
412
+ return Err ( Error :: UnrecognizedScript ) ;
405
413
} )
406
414
}
407
415
@@ -692,14 +700,8 @@ impl Address {
692
700
}
693
701
694
702
/// Constructs an [`Address`] from an output script (`scriptPubkey`).
695
- pub fn from_script ( script : & script:: Script , network : Network ) -> Option < Address > {
696
- if script. is_witness_program ( )
697
- && script. witness_version ( ) == Some ( WitnessVersion :: V0 )
698
- && !( script. is_v0_p2wpkh ( ) || script. is_v0_p2wsh ( ) ) {
699
- return None
700
- }
701
-
702
- Some ( Address {
703
+ pub fn from_script ( script : & script:: Script , network : Network ) -> Result < Address , Error > {
704
+ Ok ( Address {
703
705
payload : Payload :: from_script ( script) ?,
704
706
network,
705
707
} )
@@ -959,7 +961,7 @@ mod tests {
959
961
) ;
960
962
assert_eq ! (
961
963
Address :: from_script( & addr. script_pubkey( ) , addr. network) . as_ref( ) ,
962
- Some ( addr) ,
964
+ Ok ( addr) ,
963
965
"script round-trip failed for {}" ,
964
966
addr,
965
967
) ;
@@ -1428,8 +1430,9 @@ mod tests {
1428
1430
fn test_fail_address_from_script ( ) {
1429
1431
let bad_p2wpkh = hex_script ! ( "0014dbc5b0a8f9d4353b4b54c3db48846bb15abfec" ) ;
1430
1432
let bad_p2wsh = hex_script ! ( "00202d4fa2eb233d008cc83206fa2f4f2e60199000f5b857a835e3172323385623" ) ;
1433
+ let expected = Err ( Error :: UnrecognizedScript ) ;
1431
1434
1432
- assert_eq ! ( Address :: from_script( & bad_p2wpkh, Network :: Bitcoin ) , None ) ;
1433
- assert_eq ! ( Address :: from_script( & bad_p2wsh, Network :: Bitcoin ) , None ) ;
1435
+ assert_eq ! ( Address :: from_script( & bad_p2wpkh, Network :: Bitcoin ) , expected ) ;
1436
+ assert_eq ! ( Address :: from_script( & bad_p2wsh, Network :: Bitcoin ) , expected ) ;
1434
1437
}
1435
1438
}
0 commit comments