Prueba de reservas

Nuestro compromiso con la transparencia

Responsabilidad: revisiones periódicas

En Kraken, no solo te ofrecemos la posibilidad de operar con activos digitales de vanguardia, sino que también tratamos de aprovechar la transparencia de las blockchains de código abierto en las que figuran estos activos.

Nuestras revisiones periódicas de prueba de reservas te facilitan verificar que los balances revisados que posees están respaldados por activos reales, todo ello con solo unos pocos clics en tu cuenta.

La prueba de reservas, un avanzado procedimiento de contabilidad criptográfica llevado a cabo periódicamente por contables fiables, le permite verificar que Kraken cumple con las rigurosas normativas de responsabilidad y ofrece una transparencia superior a la que ofrecen las empresas financieras tradicionales.

¿Qué es una prueba de reservas?

Una revisión de prueba de reservas (PoR, por sus siglas en inglés) es un procedimiento que realiza un contable externo independiente. Sirve para confirmar que un custodio efectivamente mantiene los activos que afirma poseer en nombre de sus clientes. Este contable analiza un resumen anonimizado de todos los balances y los agrega a un árbol de Merkle, una estructura de datos confidencial que recoge todos los balances de los clientes.

Merkle Root Hash

A partir de ahí, el contable obtiene una raíz de Merkle: una huella criptográfica que identifica de forma única la combinación de estos balances en el momento en que se generó el resumen.

A continuación, el contable recopila las firmas digitales de Kraken, que certifican la propiedad de las direcciones de on-chain con balances de verificación pública. Por último, el contable compara y verifica si estos balances superan o coinciden con los balances de los clientes representados en el árbol de Merkle y, por tanto, si Kraken controla los activos de los clientes.

Los clientes también pueden verificar de forma independiente si su balance se ha incluido en el procedimiento de prueba de reservas comparando determinados datos con la raíz de Merkle. Cualquier cambio realizado en el resto de los datos, por pequeño que sea, afectará a la raíz, lo que evidenciará que se han manipulado.

¿Qué aspectos abarca la prueba de reservas?

Balances spot

La revisión contendrá todos los balances de los activos incluidos que poseyeras en el momento en el que se creó el resumen. Los siguientes activos están incluidos a partir de la revisión más reciente: Bitcoin (BTC), Ether (ETH), Solana (SOL), USD Coin (USDC), Tether (USDT) y Ripple (XRP).

Balance de participaciones (Staking)

Si contabas con balances asignados a on-chain staking cuando se realizó el resumen, el valor de tu balance en staking se añadirá a tu balance de spot en un único balance.

Opera con márgenes

Si tenías posiciones de margen en ese momento, tu balance se verá ajustado en función de los valores positivos de las posiciones.

Ejemplo 1

Si compras 1 BTC/USD a 30.000 USD con margen y tu posición está abierta, tu balance de prueba de reservas incluirá un ajuste positivo de 1 BTC en tu balance de BTC. No habrá ningún ajuste negativo en tu balance de USD. Tu balance de activos de BTC que custodia Kraken incluirá tu balance de BTC en ese momento, con el ajuste positivo de 1 BTC en tu posición de margen. Tu balance de activos de USD permanecerá sin cambios.

Ejemplo 2

Si vendes 1 BTC/ETH a 15 ETH con margen y tu posición está abierta, tu balance de prueba de reservas incluirá un ajuste positivo de 15 ETH en tu balance de ETH. No habrá ningún ajuste negativo en tu balance de BTC. Tu balance de activos de ETH que custodia Kraken incluirá tu balance de ETH en ese momento, con el ajuste positivo de 15 ETH en tus posiciones de margen. Tu balance de activos de BTC que custodia Kraken permanecerá sin cambios.

Nota: La metodología de futuros descrita anteriormente entra en vigor a partir de las revisiones de prueba de reservas de mayo de 2023.

Balances futuros

Si tenías balances en tu monedero de futuros en el momento en el que se llevó a cabo la revisión, habrá un registro de prueba de reservas aparte para tus balances colaterales de futuros. Tus balances se ajustan según las pérdidas y ganancias no realizadas para operaciones de futuros de colateral único. Esto incluirá los mismos activos que aparezcan en la revisión para spot y margen, y formará parte del mismo árbol de Merkle (con su propio ID de la hoja de Merkle). 

Ejemplo 1

Si tienes 1 BTC en tu monedero de futuros y abres una posición en el colateral único de BTC Perp, que cuenta con unas ganancias y pérdidas sin realizar de -0,1 BTC, tu balance de BTC que custodia Kraken será de 0,9 BTC (tu 1 BTC, con ajuste de -0,1 BTC para las PyG sin realizar).

Ejemplo 2

Si tienes 1 BTC en tu monedero de futuros y abres una posición en el multicolateral de BTC Perp, que cuenta con unas ganancias y pérdidas sin realizar de -100,0 USD, tu balance de BTC que custodia Kraken será de 1 BTC (tu 1 BTC no se ve afectado por las PyG sin realizar, ya que estas figuran en USD y este activo no se incluye en la revisión).

Nota: La metodología de futuros descrita anteriormente entra en vigor a partir de las revisiones de prueba de reservas de mayo de 2023. 

Comprobar que tu cuenta se haya incluido en la revisión de prueba de reservas

Verificación sencilla

Sigue los pasos que se detallan a continuación para verificar de forma criptográfica la inclusión del balance de tu cuenta de Kraken en la revisión de prueba de reservas más reciente.

Nota: Esta verificación reflejará únicamente los balances de tu cuenta en los activos incluidos en la revisión en el momento en el que se lleve a cabo. No reflejará las operaciones ni las transacciones posteriores, ni tampoco los balances de los activos que no se incluyen en la revisión.

1. Inicia sesión en tu cuenta de Kraken y ve a la página Prueba de reservas en la interfaz de Kraken Pro (pro.kraken.com) (Icono de cuenta > Prueba de reservas). 

Kraken Proof of Reserves review list

2. Selecciona la pestaña Prueba de reservas. Esta incluirá nuestros ratios de reserva verificados más recientes, así como la información específica de tu cuenta. En tu cuenta se mostrarán los informes de prueba de reservas recientes en los que se verificó el balance de la cuenta, lo que incluye la fecha del informe, el proveedor y el alcance de la evaluación. 

Kraken Proof of Reserves review list

3. Selecciona la fecha y haz clic en Verificarme. Aquí encontrarás la confirmación de los balances en posesión en el momento de la revisión, así como una guía sobre cómo verificar los detalles.

Kraken audit details

Verifíquelo con el contable externo

  • Utiliza tu hoja de Merkle: copia los primeros 16 caracteres e introdúcelos en las herramientas del contable externo para consultar tus balances y revisar tu ID en la ruta del árbol de Merkle. La herramienta del contable externo se abrirá en una ventana aparte. 

Nota: Esta funcionalidad se ha puesto a disposición de los usuarios a partir de las revisiones del 2023. Para revisiones anteriores, consulta la página web de nuestro socio para acceder a las herramientas de verificación.

Kraken audit details

Verificar con Kraken

  • Verifica tu ID de registro: sigue los pasos para recrear tu ID de registro, que sirve para identificar los detalles de tu cuenta, y el ID de revisión (único para cada fecha de informe).
  • Verifica tu ID de hoja de Merkle: sigue los pasos para recrear tu ID de hoja de Merkle, que sirve para identificar tu cuenta junto con los balances retenidos en el momento en el que se creó el resumen. 
  • Confirma tu ID de hoja de Merkle en el árbol de Merkle: confirma que tu ID pertenece al árbol de Merkle y valida la ruta a la raíz del árbol de Merkle, que verifica nuestro contable externo y que comparten todos los clientes.

Nota: Esta funcionalidad se ha puesto a disposición de los usuarios a partir de las revisiones del 2023. Para revisiones anteriores, consulta la página web de nuestro socio para acceder a las herramientas de verificación.

Kraken audit details
Kraken audit details
Kraken audit details

Verificación avanzada

Es posible que los clientes expertos en tecnología quieran reconstruir su hash del nodo de la hoja del árbol de Merkle y consultar sus balances en el árbol de Merkle mediante programación, en lugar de hacerlo mediante las herramientas visuales de Kraken o de terceros. 

Puedes realizar las siguientes verificaciones en código:

  1. Puedes verificar la generación del ID de la hoja del árbol de Merkle para tu cuenta siguiendo los pasos descritos a continuación.  

  2. A continuación, puedes verificar la ruta del árbol de Merkle para el ID de hoja y reconstruir la ruta desde tu posición en el nodo raíz. Ofrecemos transparencia completa e incluimos los ID de las hojas colindantes. 

Los pasos necesarios (incluidos en pseudocódigo) para reconstruir el ID de registro y la hoja de Merkle de tu código de cuenta, el IIBAN de Kraken, el ID de revisión y los balances se describen a continuación. Ten en cuenta que los resultados dependen del formato de cadenas de balances, así como del orden de los activos revisados, tal y como se muestra en la página Prueba de reservas.

  • Record ID = SHA256(concatenate(Account Code, Kraken IIBAN, Review ID))
  • Balances = ""
  • ForEachAsset:
    • Balances = concatenate(Asset, ":", AssetBalances[asset])
  • Merkle Hash = concatenate(Record ID, “,”, Balances)
  • Merkle Leaf = substring(SHA256(Merkle Hash), 0, 16)

Una vez que se identifique tu hoja de Merkle, puedes usar una verificación SHA256 con valores HEX para reconstruir la ruta del árbol de Merkle.

Asimismo, algunos ejemplos específicos se incluyen en los fragmentos de código a continuación. La hoja de Merkle resultante aparece también en los detalles de la revisión, lo que ayuda a confirmar que la reconstrucción se ha realizado correctamente.

python

Python

import hashlib

# Merkle Leaf ID calculation
account_code = "8dc20f34da8cea8dd0f46b001694f5123ecd30d786c5eb92ad1a013703a4f8d1"
iiban = "AB12C34DEFG5KSQI"
review_id = "PR30SEP24"
record_id = hashlib.sha256((account_code + iiban + review_id).encode('utf-8')).hexdigest()

balances = "BTC:0.00093799,ETH:0.0422125592,SOL:0.0,USDC:0.0,USDT:6.72754,XRP:0.0"

print("Record ID: {}".format(record_id))
print("Merkle Hash: {}".format((record_id + "," + balances)))
hash_result = hashlib.sha256((record_id + "," + balances).encode('utf-8')).hexdigest()
print("SHA Result: {}".format(hash_result))
print("Merkle Leaf: {}".format(hash_result[0:16]))

#Merkle Tree Path function 
def mix(x, y):
    a = bytes.fromhex(x)
    b = bytes.fromhex(y)

    d = hashlib.sha256()
    d.update(a)
    d.update(b)
    return d.hexdigest()
rust

Rust

use sha2::{Digest, Sha256};

//Merkle Leaf ID calculation
const ACCOUNT_CODE: &str = "8dc20f34da8cea8dd0f46b001694f5123ecd30d786c5eb92ad1a013703a4f8d1";
const IIBAN: &str = "AB12C34DEFG5KSQI";
const REVIEW_ID: &str = "PR30SEP24";
const BALANCES: &str = "BTC:0.00093799,ETH:0.0422125592,SOL:0.0,USDC:0.0,USDT:6.72754,XRP:0.0";

fn main() {
    let mut record_hasher: Sha256 = Default::default();

    record_hasher.update(ACCOUNT_CODE);
    record_hasher.update(IIBAN);
    record_hasher.update(REVIEW_ID);

    let record_id = format!("{:x}", record_hasher.finalize());
    let merkle_hash = format!("{},{}", record_id, BALANCES);

    let mut merkle_hasher: Sha256 = Default::default();
    merkle_hasher.update(&merkle_hash);
    let merkle_result = format!("{:x}", merkle_hasher.finalize());

    println!("Record ID: {}", record_id);
    println!("Merkle Hash: {}", merkle_hash);
    println!("SHA Result: {}", merkle_result);
    println!("Merkle Leaf: {}", &merkle_result[..16]);
}

//Merkle Tree Path function
fn mix(x: &str, y: &str) -> Result<String, hex::FromHexError> {
    let mut leaves_hasher: Sha256 = Default::default();
    let a = hex::decode(x)?;
    let b = hex::decode(y)?;
    leaves_hasher.update(&a);
    leaves_hasher.update(&b);
    Ok(hex::encode(leaves_hasher.finalize()))
}

fn main() {
    println!("{}", mix("f42372aeb1be7296", "dfcced6ec3235f5e").unwrap());
    assert_eq!(
        mix("f42372aeb1be7296", "dfcced6ec3235f5e").unwrap(),
        "ad86a5ee2f21347403ce07e365530604690454fa76787e76be9d2f6efdceeabf"
    );
}
go

Go

package main

import (
	"crypto/sha256"
	"fmt"
)

//Merkle Leaf ID Calculation
func main() {

	accountCode := "8dc20f34da8cea8dd0f46b001694f5123ecd30d786c5eb92ad1a013703a4f8d1"
	iiban := "AB12C34DEFG5KSQI"
	reviewId := "PR30SEP24"

	secret := accountCode + iiban + reviewId

	data := []byte(secret)
	hash := sha256.Sum256(data)
	recordId := string(hash[:])
	fmt.Printf("Record ID: %x\n", recordId)

	balances := "BTC:0.00093799,ETH:0.0422125592,SOL:0.0,USDC:0.0,USDT:6.72754,XRP:0.0"

	merkleHash := fmt.Sprintf("%x%s%s", recordId, ",", balances)
	fmt.Printf("Merkle Hash: %s\n", merkleHash)

	hashResult := sha256.Sum256([]byte(merkleHash))
	hashResultStr := string(hashResult[:])
	fmt.Printf("SHA Result: %x\n", hashResultStr)
	fmt.Printf("Merkle Leaf: %x\n", hashResultStr[0:8])

}

//Merkle Tree path hashing
func mix(x, y string) (string, error) {
        // Convert the hex strings to bytes
        a, err := hex.DecodeString(x)
        if err != nil {
                return "", err
        }

        b, err := hex.DecodeString(y)
        if err != nil {
                return "", err
        }

        h := sha256.New()

        h.Write(a)
        h.Write(b)

        // Get the final hash value as a byte slice
        hashed := h.Sum(nil)

        // Convert the hash to a hex string and return it
        return hex.EncodeToString(hashed), nil
}

func main() {
        result, _ := mix("f42372aeb1be7296", "dfcced6ec3235f5e")
        fmt.Println(result)
}
bash

Bash

#!/bin/bash

#Merkle Leaf ID calculation
ACCOUNT_CODE="8dc20f34da8cea8dd0f46b001694f5123ecd30d786c5eb92ad1a013703a4f8d1"
IIBAN="AB12C34DEFG5KSQI"
REVIEW_ID="PR30SEP24"
RECORD_ID=$(echo -n "${ACCOUNT_CODE}${IIBAN}${REVIEW_ID}" | sha256sum | head -c 64)
BALANCES="BTC:0.00093799,ETH:0.0422125592,SOL:0.0,USDC:0.0,USDT:6.72754,XRP:0.0"
MERKLE_HASH="${RECORD_ID},${BALANCES}"
HASH_RESULT=$(echo -n ${MERKLE_HASH} | sha256sum | head -c 64)

echo "Record ID: ${RECORD_ID}"
echo "Merkle Hash: ${MERKLE_HASH}"
echo "SHA Result: ${HASH_RESULT}"
echo "Merkle Leaf: $(echo -n ${HASH_RESULT} | head -c 16)"

#Merkle Tree Path function
hex_string1="f42372aeb1be7296"
hex_string2="dfcced6ec3235f5e"

# convert hex strings to binary, concatenate them and then hash
hash_result=$(echo -n "$(echo -n $hex_string1 | xxd -r -p)$(echo -n $hex_string2 | xxd -r -p)" | sha256sum | awk '{ print $1 }')

echo $hash_result

Deficiencias y futuras mejoras

Para reafirmar nuestro compromiso con la transparencia, nos gustaría compartir algunas deficiencias del proceso de prueba de reservas que hemos identificado.

  • Una prueba de reservas implica demostrar el control sobre los fondos on-chain en el momento de la revisión, pero no puede demostrar la posesión exclusiva de claves privadas que, en un caso hipotético, podría haber duplicado un atacante.
  • Con este procedimiento no es posible identificar cargas ocultas ni demostrar que los fondos no se hayan tomado prestados con el fin de pasar la revisión. Sin embargo, el movimiento de los fondos es visible en la blockchain, dado que ofrecemos transparencia con respecto a las direcciones en las que se ubican nuestros activos. Por otro lado, es posible que las claves se hayan perdido o que se haya producido un robo de los fondos desde la última revisión.
  • El contable debe presentar un alto nivel de cualificación e independencia para minimizar el riesgo de duplicidad por parte del examinado o de colusión entre las partes implicadas.
  • Tratamos de mitigar algunas de estas deficiencias al colaborar con una empresa externa independiente para nuestra prueba de reservas, así como al realizar estas revisiones con regularidad. También ofrecemos transparencia con respecto a estos datos directamente en nuestra plataforma de clientes.