Así que estoy tratando de hacer mis propias firmas de testigos como se describe en bip143. Tengo un código que verifica correctamente la firma de ejemplo, así que pensé que tenía la firma y la verificación básicas. Tengo un código que puede verificar las firmas en bip143 correctamente y, al usar el mismo código, verifico este resultado correctamente, por lo que no estoy seguro de cómo determinar qué está fallando. el error que me sale es
error code: -26
error message:
non-mandatory-script-verify-flag (Non-canonical DER signature)
Sospecho que no estoy invirtiendo el orden de bytes en algo, pero realmente no estoy seguro de cómo diagnosticar esto.
----transacción sin firmar------- 020000000102303e285bb228344346acb5292397a761103efcd0182c4cf95b4d01b2bdda400000000000ffffffff02400d03000000000016001453f0b90d7be69d4f5f1356908a9e12fef93561df74e0022a010000001600140f54e16bd59da94840741b69ab9b9db99467a85800000000 -------finalizar transacción sin firmar------ dhash(prevouts)=02303e285bb228344346acb5292397a761103efcd0182c4cf95b4d01b2bdda4000000000 dhash(secuencias)=ffffffff dhash(salidas)=400d0300000000000001453f0b90d7be69d4f5f1356908a9e12fef93561df74e0022a0100000000140f54e16bd59da94840741b69ab9b9db99467a858 inversión: 02000000 hashPrevouts: 9ebc8589966e2dd13cd64af1835262c2d8e931b4388a8ebe76620814b4f407bd secuencia hash: 3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044 punto de salida: 02303e285bb228344346acb5292397a761103efcd0182c4cf95b4d01b2bdda4000000000 código de secuencia de comandos: 1976a914992fda25fdf8447092aa223a34bedd3572173d8688ac cantidad: 00f2052a01000000 nSecuencia: ffffffff hashSalidas a54e6a8744fa773a5f1c64d7f60d53efd69f8d76e85e7817970a87990874e4c1 nLockTime 00000000 nHashType 01000000 pre hash image: 020000009ebc8589966e2dd13cd64af1835262c2d8e931b4388a8ebe76620814b4f407bd3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e7066504402303e285bb228344346acb5292397a761103efcd0182c4cf95b4d01b2bdda40000000001976a914992fda25fdf8447092aa223a34bedd3572173d8688ac00f2052a01000000ffffffffa54e6a8744fa773a5f1c64d7f60d53efd69f8d76e85e7817970a87990874e4c10000000001000000 imagen punteada: 4f8fce636bb4a44aa6a241e9597bbe54fce3bfe3426a49a94c5b006d42eac007 rawsig: 2cbb748d06a1b87c933a3118d8c2a5a0ab02111bae777a9e52ba8571eee2d549e80a6e4cef24a172e64d11aa7b83c8005fe6fc078307b9e663ef9eb14fce05a3 der sig: 304402202cbb748d06a1b87c933a3118d8c2a5a0ab02111bae777a9e52ba8571eee2d5490220e80a6e4cef24a172e64d11aa7b83c8005fe6fc078307b9e463fce05e6a3 clave de publicación de script: 992fda25fdf8447092aa223a34bedd3572173d86 clave de pub: 0392ff36d0ae9f3a74c0483fd309ff9144972b1dce6d6dfe4d9de474c721b36521 ----transacción firmada------- 0200000000010102303e285bb228344346acb5292397a761103efcd0182c4cf95b4d01b2bdda400000000000ffffffff02400d03000000000016001453f0b90d7be69d4f5f1356908a9e12fef93561df74e0022a010000001600140f54e16bd59da94840741b69ab9b9db99467a8580247304402202cbb748d06a1b87c933a3118d8c2a5a0ab02111bae777a9e52ba8571eee2d5490220e80a6e4cef24a172e64d11aa7b83c8005fe6fc078307b9e663ef9eb14fce05a301210392ff36d0ae9f3a74c0483fd309ff9144972b1dce6d6dfe4d9de474c721b3652100000000 -------finalizar transacción firmada------
Esto se está ejecutando en mi registro. Puedo proporcionar cualquier información adicional que la gente pueda pensar que sería útil. He pasado muchas horas comparando todo lo posible con todos los ejemplos antes de publicar aquí. Sé que dice non connical der sig, pero en mi investigación, otras personas dicen que el error ocurre cuando muchas cosas diferentes salen mal. Además, cuando comparo la firma con las firmadas del núcleo, coinciden exactamente en formato con "30440220", luego 32 bytes, luego 0220 y luego los otros 32 bytes. Lo único que es diferente son los datos de firma reales. Además, recibo el mismo error cuando uso una salida DER cónica nativa. Cualquier ayuda es muy apreciada como siempre
-----ACTUALIZACIÓN-----
entonces, el problema con el script anterior es que principalmente no está codificado en DER correctamente, lo que significa que si s o r most MSB> 0x80 lo trata como negativo porque es un entero con signo. En este ejemplo, el MSB de S es 0xE8, que es mayor que 0x80. bitcoin tiene una política que en realidad debe ser menor que el valor "n" de la curva ecdsa. Primero debajo está el código que corrige el problema, y puedo verificar la firma (pero el error aún existe en el núcleo de bitcoin). Código para invertir S en python:
n=115792089237316195423570985008687907852837564279074904382605163141518161494337
s = bytearray(s_bytes)
sint = 0
cnt = 31
for bb in s:
sint += bb << cnt*8
cnt -= 1
if sint >= n/2:
print("Negated")
sint = n-sint
s = bytearray(sint.to_bytes(32, byteorder='big'))
no está mal. Y en cuanto a r, el núcleo de bitcoin simplemente vuelve a firmar hasta que es inferior a 0x80. es legal que sea mayor si el codificador der rellena correctamente el MSB). Así lo hizo de la misma manera. a continuación hay una nueva transacción que tiene el problema corregido, aunque sigo teniendo el mismo error :-/.
----transacción sin firmar------- 020000000102303e285bb228344346acb5292397a761103efcd0182c4cf95b4d01b2bdda400000000000ffffffff02400d03000000000016001453f0b90d7be69d4f5f1356908a9e12fef93561df74e0022a010000001600140f54e16bd59da94840741b69ab9b9db99467a85800000000 -------finalizar transacción sin firmar------ dhash(prevouts)=02303e285bb228344346acb5292397a761103efcd0182c4cf95b4d01b2bdda4000000000 dhash(secuencias)=ffffffff dhash(salidas)=400d0300000000000001453f0b90d7be69d4f5f1356908a9e12fef93561df74e0022a0100000000140f54e16bd59da94840741b69ab9b9db99467a858 inversión: 02000000 hashPrevouts: 9ebc8589966e2dd13cd64af1835262c2d8e931b4388a8ebe76620814b4f407bd secuencia hash: 3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044 punto de salida: 02303e285bb228344346acb5292397a761103efcd0182c4cf95b4d01b2bdda4000000000 código de secuencia de comandos: 1976a914992fda25fdf8447092aa223a34bedd3572173d8688ac cantidad: 00f2052a01000000 nSecuencia: ffffffff hashSalidas a54e6a8744fa773a5f1c64d7f60d53efd69f8d76e85e7817970a87990874e4c1 nLockTime 00000000 nHashType 01000000 pre hash image: 020000009ebc8589966e2dd13cd64af1835262c2d8e931b4388a8ebe76620814b4f407bd3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e7066504402303e285bb228344346acb5292397a761103efcd0182c4cf95b4d01b2bdda40000000001976a914992fda25fdf8447092aa223a34bedd3572173d8688ac00f2052a01000000ffffffffa54e6a8744fa773a5f1c64d7f60d53efd69f8d76e85e7817970a87990874e4c10000000001000000 imagen hash: 4f8fce636bb4a44aa6a241e9597bbe54fce3bfe3426a49a94c5b006d42eac007 rawsig: 38d610fa975440d09b501864185e656546015ee98dd8b5b58eb41be547b6a686be784798307a123bdfefce7463b6e7203b69d18950ea95ae684dddb5a9bcaeaf s antes: be784798307a123bdfefce7463b6e7203b69d18950ea95ae684dddb5a9bcaeaf negado s después de: 4187b867cf85edc42010318b9c4918de7f450b5d5e5e0a8d578480d726799292 der sig: 3044022038d610fa975440d09b501864185e656546015ee98dd8b5b58eb41be547b6a68602204187b867cf85edc42010318b9c4918de7f450b5d5e5e0a789d29284 clave de publicación de script: 992fda25fdf8447092aa223a34bedd3572173d86 clave de pub: 0392ff36d0ae9f3a74c0483fd309ff9144972b1dce6d6dfe4d9de474c721b36521 ----transacción firmada------- 0200000000010102303e285bb228344346acb5292397a761103efcd0182c4cf95b4d01b2bdda400000000000ffffffff02400d03000000000016001453f0b90d7be69d4f5f1356908a9e12fef93561df74e0022a010000001600140f54e16bd59da94840741b69ab9b9db99467a85802473044022038d610fa975440d09b501864185e656546015ee98dd8b5b58eb41be547b6a68602204187b867cf85edc42010318b9c4918de7f450b5d5e5e0a8d578480d72679929201210392ff36d0ae9f3a74c0483fd309ff9144972b1dce6d6dfe4d9de474c721b3652100000000 -------finalizar transacción firmada------
Nuevamente se agradece la ayuda
ok lo descubrí! después de una semana :-D. Quiero publicar esto porque pasé la última semana aprendiendo el núcleo de bitcoin para generar los valores intermitentes durante el sighash para comparar. Cualquier otra persona que necesite entender realmente cómo funciona el núcleo, espero que esto sea realmente útil. Primero, mi problema específico: mi secuencia de comandos de salida era completamente incorrecta, creo que confundí la secuencia de comandos de bloqueo y de desbloqueo, lo que aún no debería invalidar la firma, pero también notará que en el ejemplo la salida es como:
202cb20600000000 1976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac
bueno, el primer 0x19 no es parte de la clave pública del script (la forma en que lo muestra la transacción sin procesar). Así que en la descripción donde dice
Si el tipo de sighash no es SINGLE ni NONE, hashOutputs es el doble SHA256 de la serialización de toda la cantidad de salida (8 bytes little endian) con scriptPubKey (serializado como scripts dentro de CTxOuts);
hash con el prefijo de longitud 0x19. Incluí la longitud en la transacción general, por lo que todavía se decodificó bien, pero no en la forma en que lo hice. Sencillo malentendido.
A continuación se muestra cómo construí y modifiqué el núcleo (0.21.1) para generar los valores para resolver esto
std::string hexhalftostr (valor de carácter sin signo) { si (valor <= 9) devuelve std::to_string(val); si no (val == 10) devolver "A"; si no (val == 11) devolver "B"; si no (val == 12) devuelve "C"; si no (val == 13) devuelve "D"; si no (val == 14) devuelve "E"; si no (val == 15) devuelve "F"; si no regresa ""; } anular logbytes (caracter sin firmar *datos, int len) { std::ofstream miarchivo; miarchivo.open ("/home/ubuntu/btc/bitcoinsource/bitcoin-0.21.1/special.log", std::ios_base::app); estándar::cadena ss = ""; para (int i = 0;i < len;i++) { char lsb, msb; lsb = 0x0f & datos[i]; msb = 0x0f & (datos[i] << 4); ss += hexhalftostr(msb) + hexhalftostr(lsb); } miarchivo << ss; miarchivo.close(); } anular logbigint (datos uint256) { logbytes(datos.datos(), 32); } inicio de sesión nulo (datos int sin firmar) { arrayOfByte de caracteres sin firmar [4]; para (int i = 0; i < 4; i++) arrayOfByte[i] = (datos << (i * 8)); logbytes(matrizDeBytes, 4); } void loglong (datos largos sin firmar) { char sin firmar arrayOfByte[8]; para (int i = 0; i < 8; i++) arrayOfByte[i] = (datos << (i * 8)); logbytes(matrizDeBytes, 8); } texto de registro vacío (std::string ss) { std::ofstream miarchivo; miarchivo.open ("/home/ubuntu/btc/bitcoinsource/bitcoin-0.21.1/special.log", std::ios_base::app); miarchivo << ss; miarchivo.close(); }
logtext("\nnVersión: "); logint(txTo.nVersion); logtext("\nhashPrevouts: "); logbigint(hashPrevouts); logtext("\nhashSquence: "); logbigint(hashSequence); logtext("\npunto de salida: "); logbigint(txTo.vin[nIn].prevout.hash); logint(txTo.vin[nIn].prevout.n); // no se como tomar los bytes ////logtext("\nscriptCode: "); ////logbigint(códigoscript); logtext("\ncantidad: "); loglong(cantidad); logtext("\nnSecuencia: "); logint(txTo.vin[nIn].nSequence); logtext("\nhashOutputs: "); logbigint(salidas hash); logtext("\nnTiempo de bloqueo: "); logint(txTo.nLockTime); logtext("\ntipohash: "); inicio de sesión (nHashType);
Y el retorno de la función tuvo que ser reemplazado porque el hash sha256 consume los datos, por lo que
return ss.GetHash();
se convierte
uint256 sighash = ss.GetHash();
logtext("\nhashed image: ");
logbigint(sighash);
logtext("\n");
//return ss.GetHash();
return sighash;
pieter wuille
nadie392
nadie392
pieter wuille
pieter wuille
nadie392
pieter wuille
nadie392
pieter wuille
nadie392
pieter wuille
nadie392