Hashing de scripts multisig (p2sh): diferencia entre legado y segwit

Hace algún tiempo noté que, dadas las mismas entradas, addmultisigaddressy createmultisiglos métodos del núcleo de Bitcoin generaban diferentes p2sh (direcciones).

Pregunté y un usuario de la lista de desarrolladores de bitcoin me dijo que esto se debía a que:

"addmultisigaddress usa el tipo de dirección predeterminado de la billetera, que es p2sh-segwit y createmultisig usa un tipo de dirección predeterminado de legado"

Un ejemplo de este comportamiento es:

bitcoin-cli addmultisigaddress 1 '["045897fee25bd7c5692510b2f50fcae9aa20fbc4d49d59814f4c7fdb5c4bc6eb1c0ce382458f9588e922e0d509ed8d34856787380075b00418b02e0bf7c652ef9d","02ac46c6d74d15e60f4f1035ff07ef740aca1d68d55ba0b8d336a73d7a35858831","0224a4dc5620714a9ecf67a09583d1e4c04f5bedb8ecea99028da05bb15a2a7e07"]'
{
  "address": "36ULucjWUTrDvaJzCyhFoVbDoNS6Zum2Du",
  "redeemScript": "5141045897fee25bd7c5692510b2f50fcae9aa20fbc4d49d59814f4c7fdb5c4bc6eb1c0ce382458f9588e922e0d509ed8d34856787380075b00418b02e0bf7c652ef9d2102ac46c6d74d15e60f4f1035ff07ef740aca1d68d55ba0b8d336a73d7a35858831210224a4dc5620714a9ecf67a09583d1e4c04f5bedb8ecea99028da05bb15a2a7e0753ae"
}

bitcoin-cli createmultisig 1 '["045897fee25bd7c5692510b2f50fcae9aa20fbc4d49d59814f4c7fdb5c4bc6eb1c0ce382458f9588e922e0d509ed8d34856787380075b00418b02e0bf7c652ef9d","02ac46c6d74d15e60f4f1035ff07ef740aca1d68d55ba0b8d336a73d7a35858831","0224a4dc5620714a9ecf67a09583d1e4c04f5bedb8ecea99028da05bb15a2a7e07"]'
{
  "address": "3GiimyxF1R5VixfBFAbQZbuy9EesD2r6n1",
  "redeemScript": "5141045897fee25bd7c5692510b2f50fcae9aa20fbc4d49d59814f4c7fdb5c4bc6eb1c0ce382458f9588e922e0d509ed8d34856787380075b00418b02e0bf7c652ef9d2102ac46c6d74d15e60f4f1035ff07ef740aca1d68d55ba0b8d336a73d7a35858831210224a4dc5620714a9ecf67a09583d1e4c04f5bedb8ecea99028da05bb15a2a7e0753ae"
}

El caso es que, luego, noté que con ciertas claves públicas los dos métodos generan el mismo hash:

bitcoin-cli addmultisigaddress 1 '["03fc5e16d0ece343a94735ca467d5812922fcc30e3ce43ceaf3cff7d7617631146","02ea92a0cd1738cef7502e42fe119a322845f8f1a2dd9b7216635e17dd2fffd101","04633794a75bfbd9fb2bc6bd54836831c0916dc27f9ac528045cc9352bb2cc97a003b3a6ae397101d801f3d95e6a153368b939aaf7b27bd3a5bb8a30ed92aac204"]'
{
  "address": "32AVnYUUSvm4bGgEXoQ2zuFAJBPH4P31Gi",
  "redeemScript": "512103fc5e16d0ece343a94735ca467d5812922fcc30e3ce43ceaf3cff7d76176311462102ea92a0cd1738cef7502e42fe119a322845f8f1a2dd9b7216635e17dd2fffd1014104633794a75bfbd9fb2bc6bd54836831c0916dc27f9ac528045cc9352bb2cc97a003b3a6ae397101d801f3d95e6a153368b939aaf7b27bd3a5bb8a30ed92aac20453ae"
}

bitcoin-cli createmultisig 1 '["03fc5e16d0ece343a94735ca467d5812922fcc30e3ce43ceaf3cff7d7617631146","02ea92a0cd1738cef7502e42fe119a322845f8f1a2dd9b7216635e17dd2fffd101","04633794a75bfbd9fb2bc6bd54836831c0916dc27f9ac528045cc9352bb2cc97a003b3a6ae397101d801f3d95e6a153368b939aaf7b27bd3a5bb8a30ed92aac204"]'
{
  "address": "32AVnYUUSvm4bGgEXoQ2zuFAJBPH4P31Gi",
  "redeemScript": "512103fc5e16d0ece343a94735ca467d5812922fcc30e3ce43ceaf3cff7d76176311462102ea92a0cd1738cef7502e42fe119a322845f8f1a2dd9b7216635e17dd2fffd1014104633794a75bfbd9fb2bc6bd54836831c0916dc27f9ac528045cc9352bb2cc97a003b3a6ae397101d801f3d95e6a153368b939aaf7b27bd3a5bb8a30ed92aac20453ae"
}

No entiendo cómo esto puede ser posible si las entradas y los scripts de canje son los mismos.

¿Cuál es la diferencia entre los dos casos y, en general, entre una transacción multisig heredada y una segwit?

Al leer los datos de transacciones sin procesar de la cadena de bloques, ¿cómo es posible saber si un script debe codificarse usando legado o segwit?

No estoy seguro de por qué sucede eso. Si hay al menos una clave pública sin comprimir, ambos métodos deberían proporcionar direcciones p2sh heredadas. Sin embargo, noté que en el primer caso, si empuja la clave pública sin comprimir de la posición 1 a la posición 2 o 3 mientras pasa la llamada RPC, obtenemos las mismas direcciones p2sh por ambos métodos.
Este es un buen punto @UgamKamat, gracias. No pensé que si una de las claves públicas no está comprimida, el p2sh debe ser heredado porque segwit no admite claves sin comprimir. Sin embargo, no es suficiente como regla general porque creo que también en el caso de que todas las claves públicas estén comprimidas, el p2sh aún puede ser heredado.
eso es correcto, pero lo que me deja perplejo es por qué las dos llamadas RPC dan direcciones diferentes en su primer caso. Puede verificar, si cambia la clave pública sin comprimir en el primer caso en la última posición y ejecuta ambas llamadas RPC, darán las mismas direcciones P2SH. Lo que me cuesta entender es por qué son diferentes si la clave pública sin comprimir es la primera
En ambos ejemplos, ¿la clave pública sin comprimir forma parte de su billetera? Creo que hay un error aquí.

Respuestas (1)

Creo que el comportamiento que estás viendo es en realidad un error.

De manera predeterminada, addmultisigaddressusa p2sh-segwit, que es el tipo de dirección predeterminado para la billetera. De forma predeterminada, createmultisigutiliza el legado. Estos son dos tipos de direcciones diferentes y, normalmente, obtienes dos direcciones diferentes.

Sin embargo, segwit no permite claves públicas sin comprimir. Entonces, cuando se crea el script de redimir, si se detecta una clave pública sin comprimir, ambos RPC devolverán direcciones heredadas. Es por eso que ve la misma dirección en el segundo ejemplo.

Pero creo que hay un error. Su primer ejemplo también debería dar las mismas direcciones heredadas, pero no es así. Creo que esto se debe a que la clave pública sin comprimir no es parte de la billetera, por lo que no detecta correctamente que es una clave pública sin comprimir. Por lo tanto, addmultisigaddresssigue su valor predeterminado para brindarle la dirección p2sh-segwit y createmultisigsigue su valor predeterminado para brindarle la dirección heredada.

Al leer los datos de transacciones sin procesar de la cadena de bloques, ¿cómo es posible saber si un script debe codificarse usando legado o segwit?

Para p2sh-segwit, el script de redimir no es en realidad el script de redimir que obtiene de los RPC. Más bien es el script para una salida P2WSH. El "redeemScript" es en realidad el script de testigo para el script P2WSH que es el script de redención real. El tipo de secuencia de comandos (ya sea en scriptPubKey o en redimirScript) determina si esa salida es segwit o no.

Estoy de acuerdo en que hay un error, pero incluso si esas claves públicas no se agregan a la billetera y cambia la clave pública sin comprimir de la primera posición a la última, ambas generan una dirección heredada. Esto funciona solo si la clave pública sin comprimir está en la última posición. Esa es la razón por la que en el segundo caso de la pregunta, ambas direcciones son iguales (la clave pública sin comprimir está en la última posición en ese ejemplo).