Підтвердження резервів

Наша орієнтація на прозорість

Підзвітність, регулярні перевірки

У Kraken ми не просто даємо вам змогу торгувати сучасними цифровими активами, але й працюємо для забезпечення прозорості блокчейнів із відкритим кодом, на яких вони функціонують.

Завдяки нашим регулярним оглядам Підтвердження резервів клієнти можуть легко підтверджувати свої відповідні баланси з реальними активами всього в кілька простих кліків у своєму обліковому записі.

Підтвердження резервів, передова процедура криптографічної бухгалтерії, що регулярно проводиться довіреними аудиторами, дає вам змогу переконатися, що Kraken дотримується суворих стандартів фінансової відповідальності та перевищує стандарти прозорості, які пропонують традиційні фінансові компанії.

Що таке Підтвердження резервів?

Перевірка підтверджених резервів (PoR) – це процедура, що виконується незалежним стороннім аудитором. Вона має підтвердити, що зберігач володіє активами, які йому довірили клієнти. Цей аудитор робить анонімний знімок усіх наявних балансів і накопичує їх у дереві Меркла — конфіденційно захищеній структурі даних, яка містить усі баланси клієнтів.

Merkle Root Hash

Після цього аудитор отримує корінь дерева Меркла: криптографічний відбиток, який служить унікальним ідентифікатором комбінації цих балансів на момент створення знімку.

Після цього аудитор збирає цифрові підписи від Kraken, які доводять право власності на ончейн-адреси з публічно підтверджуваними балансами. У кінці аудитор порівнює дані та підтверджує, що ці баланси є не меншими за клієнтські баланси, відображені в дереві Меркла, і що активи клієнта утримуються Kraken за принципом стовідсоткового резерву.

Будь-який клієнт може незалежно підтвердити включення свого балансу в процедуру підтвердження резервів, порівнюючи обрані частини даних із коренем дерева Меркла. Будь-які зміни решти даних, наскільки незначними вони б не були, впливають на корінь, – що робить маніпуляції очевидними.

Що включає підтвердження резервів?

Залишки спотові

Огляд міститиме всі ваші баланси в активах, які підтримуються перевіркою та які ви тримаєте на момент створення знімка. На момент останньої перевірки в аудит були включені такі активи: Bitcoin (BTC), Ether (ETH), Cardano (ADA), Polkadot (DOT), USD Coin (USDC), Tether (USDT) і Ripple (XRP).

Залишки стейкінгові

Якщо на момент створення знімка ваші баланси були розподілені в ончейн-стейкінг, ви побачите для них окремий запис, ім’я якого міститиме суфікс .S (наприклад, DOT.S).

Торгівля з маржею

Якщо у вас були маржинальні позиції на той момент, ви побачите загальний баланс, скоригований на позитивні значення позицій.

Приклад 1

Якщо ви купили 1 BTC/ETH за 30 000 дол. США з маржею і ваша позиція відкрита, ваш баланс підтвердження резервів відображатиме позитивне коригування +1 BTC до вашого балансу BTC. Негативного коригування балансу в доларах США не буде. Баланс ваших активів BTC, що зберігаються в Kraken, включатиме ваш баланс BTC на той момент, скоригований на позитивну поправку +1 BTC для вашої маржинальної позиції. Ваш баланс активів у доларах США залишиться незмінним.

Приклад 2

Якщо ви продали 1 BTC/ETH за 15 ETH із маржею і ваша позиція відкрита, ваш баланс підтвердження резервів відображатиме позитивне коригування +15 ETH до вашого балансу ETH. Негативного коригування балансу BTC не буде. Баланс ваших активів ETH, що зберігаються в Kraken, включатиме ваш баланс ETH на той момент, скоригований на позитивну поправку +15 ETH для ваших маржинальних позицій. Баланс ваших BTC-активів, що зберігаються в Kraken, залишиться незмінним.

Примітка. Описана вище методологія для ф’ючерсів вступила в силу з моменту перевірки підтвердження резервів у травні 2023 року.

Залишки ф'ючерсні

Якщо на момент перевірки у вашому ф’ючерсному гаманці були баланси, для залишків заставного забезпечення ф’ючерсів буде створено окремий запис підтвердження резервів. Ваші баланси коригуються на суму нереалізованих прибутків і збитків за ф’ючерсними угодами з єдиним забезпеченням. Вони включатимуть ті ж самі активи, що і для споту й маржі, і будуть частиною того ж самого дерева Меркла (із власним ідентифікатором листа Меркла). 

Приклад 1

Якщо у вашому ф’ючерсному гаманці був 1 BTC і ви відкрили позицію в BTC Perp Single Collateral, яка має нереалізований прибуток і збиток –0,1 BTC, то ваш баланс BTC, що зберігається в Kraken, складе 0,9 BTC (ваш 1 BTC, скоригований на –0,1 BTC за нереалізований P&L).

Приклад 2

Якщо у вашому ф’ючерсному гаманці був 1 BTC і ви відкрили позицію в BTC Perp Multi-Collateral, який має нереалізований прибуток і збиток –100,0 дол. США, то ваш баланс BTC, що зберігається в Kraken, складе 1 BTC (ваш 1 BTC не коригується на нереалізований P&L, оскільки він відстежується в доларах США, а долари США не є активом, що розглядається в цьому огляді).

Примітка. Описана вище методологія для ф’ючерсів вступила в силу з моменту перевірки підтвердження резервів у травні 2023 року. 

Перевірка того, що ваш акаунт було включено до перевірки підтвердження резервів

Проста верифікація

Для криптографічного підтвердження включення вашого балансу рахунку Kraken до останньої перевірки підтвердження резервів виконайте наведені нижче дії.

Примітка. Це підтвердження відображатиметься лише на балансах вашого рахунку в активах, що підтримувалися на момент перевірки. Воно не відображатиметься на пізніших торгах або транзакціях, а також на балансах в активах, що не охоплювались перевіркою.

1. Увійдіть у свій акаунт Kraken і перейдіть на сторінку підтвердження резервів в інтерфейсі Kraken Pro (pro.kraken.com) (значок акаунту > Підтвердження резервів). 

Kraken Proof of Reserves review list

2. Виберіть вкладку Підтвердження резервів. Тут ви побачите наші останні підтверджені коефіцієнти резервів, а також інформацію для вашого акаунту. У вашому акаунті відображатимуться останні звіти про підтвердження резервів, в яких було перевірено баланс вашого акаунту, включно з датою звіту, постачальником та обсягом оцінки. 

Kraken Proof of Reserves review list

3. Виберіть дату і натисніть Перевірити себе. Тут ви знайдете підтвердження балансу на момент перевірки, а також інструкцію щодо того, як перевірити свої дані.

Kraken audit details

Перевірити у стороннього аудитора

  • Використовуйте свій ідентифікатор листа Меркла – скопіюйте перші 16 символів і введіть їх у сторонні аудиторські інструменти, щоб отримати відомості про свої баланси й переглянути ваш ідентифікатор у шляху в дереві Меркла. Інструмент стороннього аудитора відкриється в окремому вікні. 

Примітка. Ця функція стала доступною починаючи з 2023 року. Інструменти для перегляду результатів попередніх перевірок ви зможете знайти на сторінці нашого партнера.

Kraken audit details

Перевірити у Kraken

  • Підтвердьте свій ідентифікатор запису – виконайте кроки, щоб відтворити свій ідентифікатор запису, який унікальним чином ідентифікує дані вашого акаунту, та ідентифікатор перевірки (унікальний для кожної дати звіту).
  • Підтвердьте свій ідентифікатор листа Меркла – виконайте кроки, щоб відтворити свій ідентифікатор листа Меркла, який унікальним чином ідентифікує ваш акаунт разом із балансами на ньому на момент створення аудиторського знімка. 
  • Підтвердьте свій ідентифікатор листа Меркла в дереві Меркла – підтвердьте, що ваш ідентифікатор належить до дерева Меркла, і перевірте шлях до кореня дерева, який перевіряється нашим стороннім аудитором і доступний всім клієнтам.

Примітка. Ця функція стала доступною починаючи з 2023 року. Інструменти для перегляду результатів попередніх перевірок ви зможете знайти на сторінці нашого партнера.

Kraken audit details
Kraken audit details
Kraken audit details

Розширена верифікація

Технічно підковані клієнти можуть самостійно відтворити хеш свого конкретного вузла дерева Меркла й подивитися свої баланси в дереві програмно, а не через візуальні інструменти Kraken або сторонніх аудиторів. 

Ви можете реалізувати такі кроки перевірки у програмному коді:

  1. Ви можете перевірити генерацію ідентифікатора листа дерева Меркла для свого акаунту, виконавши описані нижче кроки.  

  2. Потім ви можете перевірити шлях дерева Меркла для ідентифікатора листа й реконструювати шлях від вашої позиції до кореневого вузла. Ми забезпечуємо повну прозорість і також включаємо ідентифікатори ваших сусідніх листів. 

Нижче описано необхідні кроки для реконструкції ідентифікатора запису і листа Меркла з вашого коду акаунту, Kraken  IIBAN , ідентифікатора перевірки та балансів. Зверніть увагу, що результати є чутливими до певного форматування рядків балансів і порядку перегляду активів, як показано на сторінці підтвердження резервів.

  • Ідентифікатор запису = SHA256(concatenate(код акаунту, Kraken IIBAN, ідентифікатор перевірки))
  • Баланси = ""
  • Для кожного активу:
    • Баланси = concatenate(актив, ":", баланси_активу[asset])
  • Хеш Меркла = concatenate(ідентифікатор запису, “,”, баланси)
  • Лист Меркла = substring(SHA256(хеш Меркла), 0, 16)

Коли ваш лист Меркла буде ідентифікований, ви зможете скористатися перевіркою SHA256 зі значеннями HEX для відтворення шляху дерева Меркла.

Конкретні приклади наведено у фрагментах коду нижче. Отриманий лист Меркла буде також видно в інформації про перевірку, щоб ви могли переконатися, що правильно його реконструювали.

python

Python

import hashlib

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

balances = "ADA:15129.4,ADA.S:0.0,BTC:0.2600852178,DOT:50.0,DOT.S:20.5,DOT.P:0.0,DOT28.S:30.1,ETH:5.27518778,ETH2.S:10.123,USDC:50000.0,USDT:0.0,XRP:0.000002"

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 = "PR30NOV23";
const BALANCES: &str = "ADA:15129.4,ADA.S:0.0,BTC:0.2600852178,DOT:50.0,DOT.S:20.5,DOT.P:0.0,DOT28.S:30.1,ETH:5.27518778,ETH2.S:10.123,USDC:50000.0,USDT:0.0,XRP:0.000002";

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 := "PR30NOV23"

	secret := accountCode + iiban + reviewId

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

	balances := "ADA:15129.4,ADA.S:0.0,BTC:0.2600852178,DOT:50.0,DOT.S:20.5,DOT.P:0.0,DOT28.S:30.1,ETH:5.27518778,ETH2.S:10.123,USDC:50000.0,USDT:0.0,XRP:0.000002"

	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="PR30NOV23"
RECORD_ID=$(echo -n "${ACCOUNT_CODE}${IIBAN}${REVIEW_ID}" | sha256sum | head -c 64)
BALANCES="ADA:15129.4,ADA.S:0.0,BTC:0.2600852178,DOT:50.0,DOT.S:20.5,DOT.P:0.0,DOT28.S:30.1,ETH:5.27518778,ETH2.S:10.123,USDC:50000.0,USDT:0.0,XRP:0.000002"
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

Недоліки та майбутні покращення

Задля забезпечення прозорості ми хотіли б навести деякі виявлені нами недоліки процесу Підтвердження резервів.

  • Підтвердження резервів доводить контроль коштів ончейн на момент проведення перевірки, але не може довести ексклюзивне володіння закритими ключами, які теоретично могли б бути продубльовані хакерами.
  • Процедура не може встановити приховані обтяження або довести, що кошти не було позичено з метою проходження перевірки. Однак рух коштів видно в блокчейні, оскільки ми забезпечуємо прозорість адрес, за якими розташовані наші активи. Таким же чином, з моменту останньої перевірки ключі могли бути загублені або кошти могли бути вкрадені.
  • Щоб мінімізувати ризик дублювання частини об’єкта аудиту або таємної змови сторін, аудитор має бути компетентним і незалежним.
  • Ми намагаємось усунути деякі з цих недоліків шляхом співпраці з авторитетними й незалежними сторонніми компаніями для проведення підтвердження резервів, а також регулярно проводимо ці перевірки. Ми також гарантуємо прозорість цих даних безпосередньо на нашій клієнтській платформі.