cambio: OP_RETURN solo detecta presencia y tamaño, no muestra contenido
This commit is contained in:
@@ -12,6 +12,19 @@ y el versionado sigue [Versionado Semántico](https://semver.org/lang/es/):
|
||||
|
||||
---
|
||||
|
||||
## [1.2.1] — 2026-06-02
|
||||
|
||||
### Cambiado
|
||||
|
||||
- La herramienta de OP_RETURN pasa de decodificar y mostrar el contenido a
|
||||
solo detectar su presencia y tamaño. Para auditar privacidad, lo relevante
|
||||
es que una transacción contenga datos arbitrarios (revela uso de un
|
||||
protocolo o servicio), no qué dicen esos datos. Además, la herramienta no
|
||||
debe funcionar como visor de contenido arbitrario de la cadena. Ahora indica
|
||||
cuántos outputs OP_RETURN hay y su tamaño en bytes, sin mostrar el contenido.
|
||||
|
||||
---
|
||||
|
||||
## [1.2.0] — 2026-06-01
|
||||
|
||||
### Añadido
|
||||
|
||||
+29
-17
@@ -2586,7 +2586,7 @@
|
||||
const tools = [
|
||||
{id:"converter", label:"Conversor", icon:"⇄"},
|
||||
{id:"validator", label:"Validar dirección", icon:"✓"},
|
||||
{id:"op_return", label:"OP_RETURN", icon:"📄"},
|
||||
{id:"op_return", label:"OP_RETURN", icon:"🔍"},
|
||||
{id:"psbt", label:"PSBT", icon:"🔍"},
|
||||
{id:"rawtx", label:"Tx Raw", icon:"⬡"},
|
||||
{id:"verifysig", label:"Verificar firma", icon:"🔐"},
|
||||
@@ -2737,7 +2737,11 @@
|
||||
);
|
||||
}
|
||||
|
||||
// ── Decodificador OP_RETURN ────────────────────────────────────────────
|
||||
// ── Detector OP_RETURN ─────────────────────────────────────────────────
|
||||
// Indica SI hay datos arbitrarios y su tamaño, pero NO decodifica ni
|
||||
// muestra el contenido. Para auditar privacidad lo relevante es QUE HAYA
|
||||
// un OP_RETURN (revela uso de protocolo/servicio), no qué dice. Además,
|
||||
// evita ser un visor de contenido arbitrario de la cadena.
|
||||
function ToolOpReturn({base}) {
|
||||
const {get} = useApi(base);
|
||||
const [txid, setTxid] = useState("");
|
||||
@@ -2754,37 +2758,45 @@
|
||||
if (!tx) throw new Error("Transacción no encontrada");
|
||||
const opReturns = tx.vout.filter(o=>o.scriptpubkey_type==="op_return"||o.scriptpubkey?.startsWith("6a"));
|
||||
if (opReturns.length===0) { setErr("Esta transacción no contiene outputs OP_RETURN"); setLoading(false); return; }
|
||||
const decoded = opReturns.map(o=>{
|
||||
// Solo medimos el tamaño en bytes. NO decodificamos el contenido.
|
||||
const detected = opReturns.map(o=>{
|
||||
const hex = o.scriptpubkey?.slice(4)||"";
|
||||
let text = "";
|
||||
try { text = decodeURIComponent(escape(hex.match(/.{1,2}/g).map(b=>String.fromCharCode(parseInt(b,16))).join(""))); } catch {}
|
||||
return { hex, text, value:o.value };
|
||||
const bytes = Math.floor(hex.length/2);
|
||||
return { bytes };
|
||||
});
|
||||
setResult({ txid:tx.txid, outputs:decoded });
|
||||
setResult({ txid:tx.txid, count:opReturns.length, outputs:detected });
|
||||
} catch(e) { setErr(e.message); }
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<div style={{fontSize:"0.62rem",color:C.blue,fontFamily:"monospace",textTransform:"uppercase",letterSpacing:"0.1em",marginBottom:8}}>Decodificador OP_RETURN</div>
|
||||
<div style={{fontSize:"0.65rem",color:C.t2,marginBottom:12}}>Los outputs OP_RETURN almacenan mensajes arbitrarios en la blockchain. Introduce un txid para leerlos.</div>
|
||||
<div style={{fontSize:"0.62rem",color:C.blue,fontFamily:"monospace",textTransform:"uppercase",letterSpacing:"0.1em",marginBottom:8}}>Detector OP_RETURN</div>
|
||||
<div style={{fontSize:"0.65rem",color:C.t2,marginBottom:12}}>Indica si una transacción contiene datos arbitrarios (OP_RETURN) y su tamaño. No muestra el contenido: para auditar privacidad lo relevante es que existan, no qué dicen.</div>
|
||||
<div style={{display:"flex",gap:8,marginBottom:12}}>
|
||||
<input value={txid} onChange={e=>setTxid(e.target.value)} onKeyDown={e=>e.key==="Enter"&&decode()}
|
||||
placeholder="txid de una transacción"
|
||||
style={{flex:1,background:C.bg,border:`1px solid ${C.borderBright}`,borderRadius:6,padding:"9px 12px",color:C.t1,fontFamily:"monospace",fontSize:"0.75rem",outline:"none"}}
|
||||
onFocus={e=>e.target.style.borderColor=C.blue} onBlur={e=>e.target.style.borderColor=C.borderBright}
|
||||
/>
|
||||
<button onClick={decode} style={{padding:"9px 16px",background:C.blueMuted,border:`1px solid ${C.blue}40`,borderRadius:6,color:C.blue,fontFamily:"monospace",fontSize:"0.72rem",cursor:"pointer",fontWeight:700}}>{loading?"···":"LEER"}</button>
|
||||
<button onClick={decode} style={{padding:"9px 16px",background:C.blueMuted,border:`1px solid ${C.blue}40`,borderRadius:6,color:C.blue,fontFamily:"monospace",fontSize:"0.72rem",cursor:"pointer",fontWeight:700}}>{loading?"···":"DETECTAR"}</button>
|
||||
</div>
|
||||
{err&&<div style={{padding:"8px 12px",background:C.redMuted,border:`1px solid ${C.red}30`,borderRadius:6,color:C.red,fontFamily:"monospace",fontSize:"0.72rem"}}>{err}</div>}
|
||||
{result&&result.outputs.map((o,i)=>(
|
||||
<div key={i} style={{padding:"12px 14px",background:C.bg,borderRadius:6,border:`1px solid ${C.border}`,marginTop:8}}>
|
||||
<div style={{fontSize:"0.62rem",color:C.t2,fontFamily:"monospace",marginBottom:6}}>OP_RETURN #{i+1}</div>
|
||||
{o.text&&<div style={{fontSize:"0.8rem",color:C.green,fontFamily:"monospace",marginBottom:6,wordBreak:"break-all"}}>"{o.text}"</div>}
|
||||
<div style={{fontSize:"0.65rem",color:C.t2,fontFamily:"monospace",wordBreak:"break-all"}}>HEX: {o.hex||"(vacío)"}</div>
|
||||
{result&&(
|
||||
<div style={{padding:"12px 14px",background:C.bg,borderRadius:6,border:`1px solid ${C.border}`,marginTop:8}}>
|
||||
<div style={{fontSize:"0.8rem",color:C.amber,fontFamily:"monospace",marginBottom:8}}>
|
||||
Contiene {result.count} output{result.count>1?"s":""} OP_RETURN con datos arbitrarios.
|
||||
</div>
|
||||
{result.outputs.map((o,i)=>(
|
||||
<div key={i} style={{fontSize:"0.65rem",color:C.t2,fontFamily:"monospace",marginTop:4}}>
|
||||
OP_RETURN #{i+1}: {o.bytes} bytes de datos
|
||||
</div>
|
||||
))}
|
||||
<div style={{fontSize:"0.6rem",color:C.t3,marginTop:10,lineHeight:1.5}}>
|
||||
Se indica la presencia y el tamaño, no el contenido. Un OP_RETURN puede revelar qué protocolo o servicio se usó — ese es el dato relevante para tu privacidad.
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
)}
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@@ -3087,7 +3099,7 @@
|
||||
<P>Herramientas criptográficas que funcionan completamente en el navegador. Ningún dato se envía a servidores externos.</P>
|
||||
<Li><strong style={{color:C.t1}}>Conversor sat/BTC/EUR/USD</strong> — conversión en tiempo real usando el precio de tu propio nodo. Sin APIs de terceros.</Li>
|
||||
<Li><strong style={{color:C.t1}}>Validador de dirección</strong> — verifica el formato y tipo de cualquier dirección Bitcoin: Legacy, P2SH, Native SegWit o Taproot.</Li>
|
||||
<Li><strong style={{color:C.t1}}>Decodificador OP_RETURN</strong> — lee los mensajes almacenados en outputs OP_RETURN de cualquier transacción.</Li>
|
||||
<Li><strong style={{color:C.t1}}>Detector OP_RETURN</strong> — indica si una transacción contiene datos arbitrarios y su tamaño, sin mostrar el contenido.</Li>
|
||||
<Li><strong style={{color:C.t1}}>Validador PSBT</strong> — verifica que una PSBT tiene formato correcto antes de firmarla. Para verificación criptográfica completa usa Sparrow o Bitcoin Core.</Li>
|
||||
<Li><strong style={{color:C.t1}}>Decodificador tx raw</strong> — valida el formato hexadecimal de una transacción sin firmar.</Li>
|
||||
<Li><strong style={{color:C.t1}}>Verificador de firma</strong> — valida el formato de una firma de mensaje Bitcoin. Para verificación criptográfica completa usa Bitcoin Core (<Code>verifymessage</Code>).</Li>
|
||||
|
||||
Reference in New Issue
Block a user