explain_inscription_listing_security
Analyze Bitcoin inscription listings for snipe resistance by examining PSBT sighash types and mempool vulnerabilities, providing remediation steps for developers and marketplace operators.
Instructions
Explain in plain language whether an ordinals inscription listing is snipe-resistant.
Analyzes the PSBT and returns a human-readable explanation of:
Whether the listing can be front-run in the mempool
What sighash type each input uses and why it matters
Specific remediation steps if the listing is vulnerable
Use this when you need a clear explanation for a developer or marketplace operator rather than raw analysis data.
Args: psbt_hex: Hex-encoded PSBT string (BIP 174 v0)
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| psbt_hex | Yes |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- src/bitcoin_mcp/server.py:1758-1816 (handler)Handler function for the explain_inscription_listing_security tool. It calls the internal _psbt_analyze function to assess security risks in an ordinals inscription listing PSBT and returns a human-readable explanation.
def explain_inscription_listing_security(psbt_hex: str) -> str: """Explain in plain language whether an ordinals inscription listing is snipe-resistant. Analyzes the PSBT and returns a human-readable explanation of: - Whether the listing can be front-run in the mempool - What sighash type each input uses and why it matters - Specific remediation steps if the listing is vulnerable Use this when you need a clear explanation for a developer or marketplace operator rather than raw analysis data. Args: psbt_hex: Hex-encoded PSBT string (BIP 174 v0) """ result = _psbt_analyze(psbt_hex) if "error" in result: return result["error"] risk = result["overall_risk"] inputs = result["inputs"] n = result["input_count"] if risk == "vulnerable": vuln_inputs = [str(inp["index"]) for inp in inputs if inp["vulnerability"] == "vulnerable"] explanation = ( f"VULNERABLE — This listing can be stolen from the mempool.\n\n" f"Input(s) {', '.join(vuln_inputs)} of {n} use SIGHASH_SINGLE|ANYONECANPAY " f"without a 2-of-2 multisig locking step. An attacker watching the mempool can " f"construct a competing transaction that spends the inscription UTXO to themselves " f"without invalidating your signature.\n\n" f"Fix: Lock the inscription into a 2-of-2 P2WSH multisig (seller + marketplace " f"pubkeys) BEFORE broadcasting the sale. The marketplace must co-sign the sale " f"transaction with SIGHASH_ALL so no output can be modified." ) elif risk == "protected": explanation = ( f"PROTECTED — This listing is snipe-resistant.\n\n" f"The inscription is locked in a 2-of-2 multisig output requiring both the " f"seller and marketplace to co-sign. The marketplace signature uses SIGHASH_ALL, " f"which commits to the entire transaction structure. Any attacker attempting to " f"redirect the inscription or substitute themselves as the buyer would invalidate " f"the marketplace's signature, making the attack impossible without the marketplace " f"private key." ) elif risk == "not_inscription_listing": explanation = ( f"NOT AN INSCRIPTION LISTING — No inputs use SIGHASH_SINGLE|ANYONECANPAY.\n\n" f"This PSBT does not appear to be an ordinals inscription sale transaction. " f"All {n} input(s) use standard sighash types." ) else: explanation = ( f"UNKNOWN — Could not determine vulnerability.\n\n" f"Sighash type information is missing from the PSBT inputs. " f"Ensure the PSBT includes PSBT_IN_SIGHASH_TYPE fields or partial signatures." ) return explanation