Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Address::address_type returns Result instead of Option
- Loading branch information
1 parent
ad60698
commit 8d72ee3
Showing
2 changed files
with
53 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -79,31 +79,46 @@ pub enum Error { | |
InvalidSegwitV0ProgramLength(usize), | ||
/// An uncompressed pubkey was used where it is not allowed. | ||
UncompressedPubkey, | ||
/// Witness version which is not (yet) supported by this library. | ||
/// | ||
/// It may be in the future that the consensus rules will support more | ||
/// witness versions and corresponding addresses, but this library is not | ||
/// (yet) updated for them. Also, a user can always send money to the output | ||
/// with a future witness version, and construct a corresponding address – | ||
/// but such address will not be parsed by this library. | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
apoelstra
Member
|
||
UnsupportedWitnessVersion { | ||
/// Witness version that was found during address decoding | ||
version: WitnessVersion, | ||
/// Length of the witness program | ||
length: usize | ||
}, | ||
/// Address size more than 520 bytes is not allowed. | ||
ExcessiveScriptSize | ||
} | ||
|
||
impl fmt::Display for Error { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
match *self { | ||
Error::Base58(_) => write!(f, "base58 address encoding error"), | ||
Error::Bech32(_) => write!(f, "bech32 address encoding error"), | ||
Error::EmptyBech32Payload => write!(f, "the bech32 payload was empty"), | ||
Error::Base58(_) => f.write_str("base58 address encoding error"), | ||
Error::Bech32(_) => f.write_str( "bech32 address encoding error"), | ||
Error::EmptyBech32Payload => f.write_str( "the bech32 payload was empty"), | ||
Error::InvalidBech32Variant { expected, found } => write!(f, "invalid bech32 checksum variant found {:?} when {:?} was expected", found, expected), | ||
Error::InvalidWitnessVersion(v) => write!(f, "invalid witness script version: {}", v), | ||
Error::UnparsableWitnessVersion(_) => write!(f, "incorrect format of a witness version byte"), | ||
Error::UnparsableWitnessVersion(_) => f.write_str( "incorrect format of a witness version byte"), | ||
Error::MalformedWitnessVersion => f.write_str("bitcoin script opcode does not match any known witness version, the script is malformed"), | ||
Error::InvalidWitnessProgramLength(l) => write!(f, | ||
"the witness program must be between 2 and 40 bytes in length: length={}", l, | ||
Error::InvalidWitnessProgramLength(len) => write!(f, | ||
"the witness program must be between 2 and 40 bytes in length: length={}", len, | ||
), | ||
Error::InvalidSegwitV0ProgramLength(l) => write!(f, | ||
"a v0 witness program must be either of length 20 or 32 bytes: length={}", l, | ||
Error::InvalidSegwitV0ProgramLength(len) => write!(f, | ||
"a v0 witness program must be either of length 20 or 32 bytes: length={}", len, | ||
), | ||
Error::UncompressedPubkey => write!(f, | ||
Error::UncompressedPubkey => f.write_str( | ||
"an uncompressed pubkey was used where it is not allowed", | ||
), | ||
Error::ExcessiveScriptSize => write!(f, | ||
"Script size exceed 520 bytes") | ||
Error::UnsupportedWitnessVersion { version, length } => write!( | ||
f, "witness version {:?} is not supported yet for witness program length {}", version, length | ||
), | ||
Error::ExcessiveScriptSize => write!(f, "Script size exceed 520 bytes") | ||
} | ||
} | ||
} | ||
|
@@ -531,23 +546,21 @@ impl Address { | |
|
||
/// Get the address type of the address. | ||
/// None if unknown, non-standard or related to the future witness version. | ||
pub fn address_type(&self) -> Option<AddressType> { | ||
pub fn address_type(&self) -> Result<AddressType, Error> { | ||
match self.payload { | ||
Payload::PubkeyHash(_) => Some(AddressType::P2pkh), | ||
Payload::ScriptHash(_) => Some(AddressType::P2sh), | ||
Payload::PubkeyHash(_) => Ok(AddressType::P2pkh), | ||
Payload::ScriptHash(_) => Ok(AddressType::P2sh), | ||
Payload::WitnessProgram { | ||
version, | ||
program: ref prog, | ||
} => { | ||
// BIP-141 p2wpkh or p2wsh addresses. | ||
match version { | ||
WitnessVersion::V0 => match prog.len() { | ||
20 => Some(AddressType::P2wpkh), | ||
32 => Some(AddressType::P2wsh), | ||
_ => None, | ||
}, | ||
WitnessVersion::V1 if prog.len() == 32 => Some(AddressType::P2tr), | ||
_ => None, | ||
match (version, prog.len()) { | ||
(WitnessVersion::V0, 20) => Ok(AddressType::P2wpkh), | ||
(WitnessVersion::V0, 32) => Ok(AddressType::P2wsh), | ||
(WitnessVersion::V0, len) => Err(Error::InvalidWitnessProgramLength(len)), | ||
(WitnessVersion::V1, 32) => Ok(AddressType::P2tr), | ||
(version, length) => Err(Error::UnsupportedWitnessVersion { version, length }), | ||
} | ||
} | ||
} | ||
|
@@ -559,7 +572,7 @@ impl Address { | |
/// SegWit addresses with unassigned witness versions or non-standard | ||
/// program sizes are considered non-standard. | ||
pub fn is_standard(&self) -> bool { | ||
self.address_type().is_some() | ||
self.address_type().is_ok() | ||
} | ||
|
||
/// Get an [Address] from an output script (scriptPubkey). | ||
|
@@ -612,7 +625,7 @@ impl Address { | |
/// ``` | ||
pub fn is_valid_for_network(&self, network: Network) -> bool { | ||
let is_legacy = match self.address_type() { | ||
Some(AddressType::P2pkh) | Some(AddressType::P2sh) => true, | ||
Ok(AddressType::P2pkh) | Ok(AddressType::P2sh) => true, | ||
_ => false | ||
}; | ||
|
||
|
@@ -830,7 +843,7 @@ mod tests { | |
hex_script!("76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac") | ||
); | ||
assert_eq!(&addr.to_string(), "132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM"); | ||
assert_eq!(addr.address_type(), Some(AddressType::P2pkh)); | ||
assert_eq!(addr.address_type(), Ok(AddressType::P2pkh)); | ||
roundtrips(&addr); | ||
} | ||
|
||
|
@@ -843,7 +856,7 @@ mod tests { | |
let key = hex_key!(&"03df154ebfcf29d29cc10d5c2565018bce2d9edbab267c31d2caf44a63056cf99f"); | ||
let addr = Address::p2pkh(&key, Testnet); | ||
assert_eq!(&addr.to_string(), "mqkhEMH6NCeYjFybv7pvFC22MFeaNT9AQC"); | ||
assert_eq!(addr.address_type(), Some(AddressType::P2pkh)); | ||
assert_eq!(addr.address_type(), Ok(AddressType::P2pkh)); | ||
roundtrips(&addr); | ||
} | ||
|
||
|
@@ -859,7 +872,7 @@ mod tests { | |
hex_script!("a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087") | ||
); | ||
assert_eq!(&addr.to_string(), "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k"); | ||
assert_eq!(addr.address_type(), Some(AddressType::P2sh)); | ||
assert_eq!(addr.address_type(), Ok(AddressType::P2sh)); | ||
roundtrips(&addr); | ||
} | ||
|
||
|
@@ -868,7 +881,7 @@ mod tests { | |
let script = hex_script!("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae"); | ||
let addr = Address::p2sh(&script, Testnet).unwrap(); | ||
assert_eq!(&addr.to_string(), "2N3zXjbwdTcPsJiy8sUK9FhWJhqQCxA8Jjr"); | ||
assert_eq!(addr.address_type(), Some(AddressType::P2sh)); | ||
assert_eq!(addr.address_type(), Ok(AddressType::P2sh)); | ||
roundtrips(&addr); | ||
} | ||
|
||
|
@@ -884,7 +897,7 @@ mod tests { | |
let mut key = hex_key!("033bc8c83c52df5712229a2f72206d90192366c36428cb0c12b6af98324d97bfbc"); | ||
let addr = Address::p2wpkh(&key, Bitcoin).unwrap(); | ||
assert_eq!(&addr.to_string(), "bc1qvzvkjn4q3nszqxrv3nraga2r822xjty3ykvkuw"); | ||
assert_eq!(addr.address_type(), Some(AddressType::P2wpkh)); | ||
assert_eq!(addr.address_type(), Ok(AddressType::P2wpkh)); | ||
roundtrips(&addr); | ||
|
||
// Test uncompressed pubkey | ||
|
@@ -901,7 +914,7 @@ mod tests { | |
&addr.to_string(), | ||
"bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej" | ||
); | ||
assert_eq!(addr.address_type(), Some(AddressType::P2wsh)); | ||
assert_eq!(addr.address_type(), Ok(AddressType::P2wsh)); | ||
roundtrips(&addr); | ||
} | ||
|
||
|
@@ -911,7 +924,7 @@ mod tests { | |
let mut key = hex_key!("026c468be64d22761c30cd2f12cbc7de255d592d7904b1bab07236897cc4c2e766"); | ||
let addr = Address::p2shwpkh(&key, Bitcoin).unwrap(); | ||
assert_eq!(&addr.to_string(), "3QBRmWNqqBGme9er7fMkGqtZtp4gjMFxhE"); | ||
assert_eq!(addr.address_type(), Some(AddressType::P2sh)); | ||
assert_eq!(addr.address_type(), Ok(AddressType::P2sh)); | ||
roundtrips(&addr); | ||
|
||
// Test uncompressed pubkey | ||
|
@@ -925,7 +938,7 @@ mod tests { | |
let script = hex_script!("522103e5529d8eaa3d559903adb2e881eb06c86ac2574ffa503c45f4e942e2a693b33e2102e5f10fcdcdbab211e0af6a481f5532536ec61a5fdbf7183770cf8680fe729d8152ae"); | ||
let addr = Address::p2shwsh(&script, Bitcoin); | ||
assert_eq!(&addr.to_string(), "36EqgNnsWW94SreZgBWc1ANC6wpFZwirHr"); | ||
assert_eq!(addr.address_type(), Some(AddressType::P2sh)); | ||
assert_eq!(addr.address_type(), Ok(AddressType::P2sh)); | ||
roundtrips(&addr); | ||
} | ||
|
||
|
@@ -959,8 +972,8 @@ mod tests { | |
("bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqzk5jj0", "512079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798") | ||
]; | ||
for vector in &valid_vectors { | ||
let addr: Address = vector.0.parse().unwrap(); | ||
assert_eq!(&addr.script_pubkey().as_bytes().to_hex(), vector.1); | ||
let addr: Address = vector.0.parse().expect(&format!("error in test vector {}", vector.0)); | ||
assert_eq!(&addr.script_pubkey().as_bytes().to_hex(), vector.1, "failure for test vector {}", vector.0); | ||
roundtrips(&addr); | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
I believe it still is parsed it's just some methods will return this error. Am I missing something?