BIP47 (2) - Construyendo la transacción de notificación

Clásico contestador de la década de los 90
En el anterior post hemos dejado a Bob con su código de pago armado y habiendo identificado todas sus partes:
A sabiendas de que a alguien le podría interesar conocerlo para poder enviarle bitcoin, Bob lo ha colgado en su perfil de Nostr y Twitter.
PM8TJS2JxQ5ztXUpBBRnpTbcUXbUHy2T1abfrb3KkAAtMEGNbey4oumH7Hc578WgQJhPjBxteQ5GHHToTYHE3A1w6p7tU6KSoFmWBVbFGjKPisZDbP97
Alice — buena amiga de Bob — lo ve y recuerda que le debe unos satoshis. Entonces, decide aprovechar la ocasión para pagarle sin tener que molestarlo pidiéndole una dirección. Sin interacción.
Y esto desencadena algo mágico de la criptografía:
    Cuando Alice pague a Bob utilizando su código de pago, no lo hará a ninguna dirección que éste conozca.
    Lo hará a una dirección de Bob :
      de la que tiene el control
      pero que todavía no ha nacido
      y de la que el receptor no tiene conocimiento de su existencia, ni la tendrá (a menos que Alice se lo comunique).
¿Pero no hemos dicho que Alice no va a molestarle?, ¿cómo se lo va a comunicar?
Alice no le molestará pero sí que le dejará un mensaje en su "contestador de voz", con pistas de estas nuevas direcciones que ella le creará. Así, él las podrá localizar y gastar cuando desee.
En el BIP47, ese contestador de voz es una salida OP_Return de una transacción de notificación que Alice debe hacerle a Bob.

Transacción de notificación

Antes de empezar con esta operación, Alice ha creado un código de pago propio:
PM8TJTLJbPRGxSbc8EJi42Wrr6QbNSaSSVJ5Y3E4pbCYiTHUskHg13935Ubb7q8tx9GVbh2UuRnBc3WSyJHhUrw8KhprKnn9eDznYGieTzFcwQRya4GA
¿Por qué?
Le va a hacer falta para calcular las direcciones de Bob a las que enviará fondos.
Lo interesante del tema es que a Bob también le va a hacer falta conocer el código de pago de Alice, porque sin él le va a ser imposible tener conocimiento de que ha recibido pagos y de cómo gastarlos.
Así que la primera misión de Alice es hacerle saber su código de pago (sin molestarlo).
¿Cómo?
Se lo va a enviar a Bob en un el campo OP_Return de una transacción que le va a hacer y que llamaremos de notificación
Pero ¿A qué dirección?, ¿no hemos dicho que no va a molestarle pidiéndole nada?
Y no le molestará. Se lo enviará a una dirección que ella derivará con la información que Bob ha incluido en su código de pago.

Encontrando la dirección de notificación de Bob

En su código de pago público, Bob ha dejado la siguiente data:
public key de Bob:
029d125e1cb89e5a1a108192643ee25370c2e75c192b10aac18de8d5a09b5f48d5
chain code de Bob:
1db1243aaa57c7fbea3072249c1bd4dab9482b4fee4d25e1c69707e8144dc137
Esta información pertenece a la ruta de derivación m/47'/0'/0' de la semilla de Bob, y es suficiente data como para que Alice pueda calcular una pubkey hija enm/47'/0'/0'/0 , desde la que codificará una dirección que utilizará para notificar a Bob.
Forma en la que se calcula pubkey hija https://learnmeabitcoin.com/technical/extended-keys
El BIP47 establece que la dirección en índice 0 m/47'/0'/0'/0 sea la que se utiliza para recibir todas las notificaciones de que se quieran hacer a Código de Pago. Y por lo tanto si después de Alice, Carol también quisiera hacer una transacción de notificación a Bob, ambas reutilizarían la misma dirección.
Alice hace ese cálculo y encuentra que la pubkey en m/47'/0'/0'/0 de Bob (B) es:
B = 024ce8e3b04ea205ff49f529950616c3db615b1e37753858cc60c1ce64d17e2ad8
Que pasada a dirección simple es:
1ChvUUvht2hUQufHBXF8NgLhW8SwE2ecGV
Fantástico. Ya tiene el destino donde enviar su tx de notificación. Pero, si como hemos dicho, toda esta información se puede calcular de forma pública por cualquiera ¿querrá Alice enviar tu código de pago en claro en un OP_Return para que todo el mundo sepa que está interactuando con Bob y a qué direcciones le está enviando?
No, no querrá y por eso enviará el código de pago cifrado con un secreto que Bob todavía no conoce pero que puede conocer.
Y ahora me dirás "Te pillé. Aquí es donde sí que Alice ha de molestar a Bob para decirle el secreto."
Nope. Alice utilizará un secreto que nadie conoce pero que Bob sí que puede conocer si ve la transacción de notificación.
Entonces todo el mundo podrá saberlo también, ¿no?
No. Solo Bob podrá calcularlo porque solo él conoce sus claves privadas y serán capitales para que pueda reconstruir el secreto.

Cifrando el código de pago de Alice con ECDH

Alice tiene la dirección de destino.
Ahora le falta saber qué moneda va a enviar.
Alice escoge una moneda de 30.000 sats que tenía sin gastar de la transacción:
9c6000d597c5008f7bfc2618aed5e4a6ae57677aab95078aae708e1cab11f486
De hecho es la moneda 1 (la segunda salida de esa TX. La primera sería la 0), con lo que su outpoint (la localización de la moneda en la cadena de bloques) es
9c6000d597c5008f7bfc2618aed5e4a6ae57677aab95078aae708e1cab11f486||01 (siendo || = concatenación)
Esta información, Alice la va a dejar a un lado pero antes la va a poner en formato correcto de endianidad (algo que ahora no viene al caso pero que hace que a veces se utilicen girados):
outpoint = 86f411ab1c8e70ae8a0795ab7a6757aea6e4d5ae1826fc7b8f00c597d500609c01000000
Vale. Seguimos.
Cada moneda de bitcoin (o UTXO) tiene varias características que la hacen ser ella y no otra:
    el outpoint
    el tamaño en satoshis
    una dirección donde se ha depositado
    una clave pública de esa dirección
    y una clave privada asociada a esta última que permite firmarla (gastarla)
Cuando gastamos una moneda en una transacción exponemos al mundo la clave pública de la dirección que la guardaba.
Esto es importante para el caso que nos ocupa, porque Bob va a utilizar la clave pública de la dirección 1Mm4yYUw6KVMYLHMbWVpPGukfsXr5T7G9 que custodia ese UTXO de 30.000 sats (y que conocerá cuando Alice lo gaste) para conseguir el secreto con el que cifrará ella su Código de Pago.
La clave pública (K) de la dirección del UTXO a gastar es:
K= 0272d83d8a1fa323feab1c085157a0791b46eba34afb8bfbfaeb3a3fcc3f2c9ad8
Alice, como poseedora de ese UTXO conoce todos los datos. Incluso la clave privada (k).
Alice tiene la k de la moneda que va a gastar y ahora lo que necesita es recuperar la clave pública de la dirección de notificación de Bob que ya había calculado:
B = 024ce8e3b04ea205ff49f529950616c3db615b1e37753858cc60c1ce64d17e2ad8
Toda clave pública nace de una clave privada y la operación es la siguiente:
B = b*G
K = k*G
Siendo G el número generador de la curva elíptica de bitcoin secp256k1.
Las curvas elípticas quedan fuera del ámbito de desarrollo de este artículo pero quédate con esa fórmula y también con que k = K/G NO te da como resultado la clave privada. Aquí chocarías con el problema del logaritmo discreto y por eso es fácil calcular la clave pública desde una clave privada y no al revés.
Pues bien con k y B, calcula el secreto S:
S = k*B
Lo que le da un punto en la curva elíptica de bitcoin con coordenadas (x,y).
Y con esto valores, ahora sí que tenemos todo lo que necesitamos para cifrar el código de pago de Alice en una salida OP_Return.
El BIP47 especifica que el cifrado se haga así:
    primero se realiza un HMAC SHA512 con los valores (x, outpoint)
    el resultado de esto es una cadena de 64 bytes que llama s
    luego serializa el código de pago de Alice a binario (cero y unos) y teniendo bien claros qué bits pertenecen a la clave pública, y cuáles al chaincode hace la siguiente operación:
      con los primeros 256 bits de s, hace una operación XOR a la clave pública
      con los segundos 256 bits de s, hace una operación XOR a el chaincode
    Con esta cadena binaria del código de pago alterado de Alice, lo añade al OP_Return en formato hexadecimal:
    010002063e4eb95e62791b06c50e1a3a942e1ecaaa9afbbeb324d16ae6821e091611fa96c0cf048f607fe51a0327f5e2528979311c78cb2de0d682c61e1180fc3d543b00000000000000000000000000
Y así incluye su código de pago en la transacción de notificación vía OP_Return. Firma la tx y la envía.
Si te fijas, si comparamos a este código de pago en hexadecimal con la estructura que el BIP47 establece y que Bob había seguido, le faltan cosas:
Le falta el prefijo 47 y le falta el checksum:
    Sin saberlo a ciencia cierta entiendo que el prefijo no lo ponen para ahorrar 1 byte que Bob la wallet puede añadir sin que se lo digan. Siempre tiene el mismo valor.
    El checksum falta porque también puede calcularlo Bob cuando descifre la clave pública y el chain code. Y así también no se dejan pistas en la cadena de bloques sobre cuál es la solución al acertijo.
Y así, con la transacción confirmada en la Mempool, Bob acaba de recibir un mensaje secreto, que quizá el no vea, pero que su wallet ya ha empezado a descifrar para localizar fondos que le puedan estar llegando desde Alice.

Referencias

Curva elíptica de bitcoin: https://en.bitcoin.it/wiki/Secp256k1