diff --git a/src/rest.rs b/src/rest.rs index 5493a0fc0..cb2680e8f 100644 --- a/src/rest.rs +++ b/src/rest.rs @@ -334,30 +334,7 @@ impl TxOutValue { let script_asm = script.to_asm(); let script_addr = script.to_address_str(config.network_type); - // TODO should the following something to put inside rust-elements lib? - let script_type = if is_fee { - "fee" - } else if script.is_empty() { - "empty" - } else if script.is_op_return() { - "op_return" - } else if script.is_p2pk() { - "p2pk" - } else if script.is_p2pkh() { - "p2pkh" - } else if script.is_p2sh() { - "p2sh" - } else if script.is_p2wpkh() { - "v0_p2wpkh" - } else if script.is_p2wsh() { - "v0_p2wsh" - } else if script.is_p2tr() { - "v1_p2tr" - } else if script.is_op_return() { - "provably_unspendable" - } else { - "unknown" - }; + let script_type = script_type(script, is_fee); #[cfg(feature = "liquid")] let pegout = PegoutValue::from_txout(txout, config.network_type, config.parent_network); @@ -380,6 +357,35 @@ impl TxOutValue { } } +#[allow(deprecated)] +fn script_type(script: &Script, is_fee: bool) -> &'static str { + // OP_RETURN has a dedicated API type and must precede the broader + // provably-unspendable check. + if is_fee { + "fee" + } else if script.is_empty() { + "empty" + } else if script.is_op_return() { + "op_return" + } else if script.is_p2pk() { + "p2pk" + } else if script.is_p2pkh() { + "p2pkh" + } else if script.is_p2sh() { + "p2sh" + } else if script.is_p2wpkh() { + "v0_p2wpkh" + } else if script.is_p2wsh() { + "v0_p2wsh" + } else if script.is_p2tr() { + "v1_p2tr" + } else if script.is_provably_unspendable() { + "provably_unspendable" + } else { + "unknown" + } +} + #[derive(Serialize)] struct UtxoValue { txid: Txid, @@ -1621,8 +1627,12 @@ impl From for HttpError { #[cfg(test)] mod tests { - use crate::rest::{is_block_template_request, HttpError}; - use crate::{errors, errors::ErrorKind}; + use crate::{ + chain::Script, + errors, + errors::ErrorKind, + rest::{is_block_template_request, script_type, HttpError}, + }; use http_body_util::BodyExt; use hyper::{Method, StatusCode}; use serde_json::Value; @@ -1739,6 +1749,25 @@ mod tests { assert!(err.is_err()); } + #[test] + fn test_script_type_unspendable_classification() { + let op_return = Script::from(vec![0x6a]); + assert_eq!(script_type(&op_return, false), "op_return"); + + #[cfg(not(feature = "liquid"))] + let provably_unspendable = Script::from(vec![0x50]); // OP_RESERVED + #[cfg(feature = "liquid")] + let provably_unspendable = Script::from(vec![0x51; 10_001]); + assert_eq!( + script_type(&provably_unspendable, false), + "provably_unspendable" + ); + + // OP_TRUE is spendable but does not match a recognized output type. + let unknown = Script::from(vec![0x51]); + assert_eq!(script_type(&unknown, false), "unknown"); + } + #[test] fn test_getblocktemplate_rpc_error() { let err: errors::Error = errors::ErrorKind::RpcError(