Proof of Reserves
(プルーフ・オブ・リザーブ)
透明性へのコミットメント
クラーケンでは、最先端のデジタル資産を取引できるようにするだけでなく、それらが動作するオープンソースのブロックチェーンの透明性を最大限に活用するように取り組んでいます。
当社の定期的なProof of Reservesにより、お客様はご自身が保有する残高が実際の資産に裏付けられていることを、アカウントで数回クリックするだけで簡単に確認することができます。
お客様におかれましては、信頼できる監査人(会計事務所)によって半年ごとに実施されるこのProof of Reservesによって、クラーケンが透明性と説明責任の観点で自ら課した厳格な基準を満たしていること、そして、これらは伝統的な金融機関を凌駕するものであることをご確認いただけますと幸いです。
Proof of Reserves(プルーフ・オブ・リザーブ)とは
Proof of Reserves(PoR)は、第三者によって行われる独立した残高確認で、カストディアンが顧客のために資産を保有していることを確認することを目的としています。
この監査人(会計事務所)は、クラーケンが保有するすべての残高の匿名化されたスナップショットを取得し、それらを Merkleツリー (すべての顧客残高をカプセル化したプライバシーに配慮したデータ構造)に集約します。
これは、スナップショットが作成された時点の残高の組み合わせを一意に識別する暗号化フィンガープリント(指紋)です。
監査人(会計事務所)は次に、クラーケンによって生成されたデジタル署名を収集します。これは、公に検証可能な残高を持つオンチェーンアドレスの所有権を証明するものです。最後に、監査人(会計事務所)は、これらの残高がMerkleツリーで表される顧客の残高を超えるか一致すること、つまり、顧客資産がフルリザーブベースで保有されていることを比較・検証します。
どの顧客も、選択したデータの一部を Merkle ルートと比較することで、自分の残高が Proof of Reserves に含まれることを独自に検証することができます。関連する他のデータに加えられた変更は、どんなに小さくても当該ルートに影響するため、改ざんがあればすぐに明らかになります。
確認の手順
以下の手順に従って、最新のProof of Reservesにお客様のアカウントの残高が含まれていることを暗号的に検証してください。
注意: この検証は、残高確認時にサポートされている資産におけるお客様のアカウントの残高のみを反映します。それ以降の取引やトランザクションは反映されません。また、当該残高確認の対象になっていない資産で保有されている残高も反映されません。
1. クラーケンアカウントにログインし、アカウント設定に移動します。(設定 > アカウント).
2. [Audits] タブを選択します。お客様のアカウントには、お客様のアカウント残高が確認された最近の残高確認、関連するID、基準日、残高確認を行った会計事務所名、および実施された確認の種類が表示されます。上記のIDは、特定の残高確認に関連する識別文字列です。クラーケンは定期的に残高証明の確認を行うことを予定しており、それぞれが一意に識別可能であることが重要になります。
3. 確認したい基準日を選択します。ここでは、タイプ、お客様の記録ID(お客様のアカウントと特定の残高確認に固有のもの)、対象となった資産、および残高確認時のお客様の資産残高を確認できます。
記録ID(Record ID)を用いることで、第三者監査人(会計事務所)を通じて、自分の口座残高が含まれていることを独自に確認することができます。
記録の照合について
シンプル:
お客様のアカウントの記録を確認する最も早い方法は、お客様の記録ID(Record ID)で第三者監査人(会計事務所)のポータルを使用することです。
1. 自分のアカウントと指定された残高確認に対応する記録ID(Record ID) をコピーします(記録ID を見つけるには、前のセクションを参照してください)。
2. Proof of Reserves を担当する第三者監査人(会計事務所)のウェブサイトにアクセスします。
3. 第三者監査人(会計事務所)のポータルで、お客様の記録ID(Record ID) を入力します。監査人(会計事務所)のウェブサイトは、このIDを使用して、監査時にお客様のアカウントに保持されている暗号通貨の記録をオンチェーンで検索します。
4. 残高を確認する。
アドバンスド(上級):
技術上対応可能なお客様は、記録IDだけでなく、特定のMerkle Treeのリーフノードのハッシュを独自に再構築し、このハッシュを使用して第三者監査人(会計事務所)の提供するツールで残高を調べることができます。
これにより、自分の記録ID(および残高確認時の自分のアカウントの関連残高)が、監査人(会計事務所)によって公開されたルートハッシュをもたらした Merkle Tree 構造に含まれていたことを検証することができます。
1. kraken.comの[Audits]の詳細には、「アカウントコード」も含まれています。これは、お客様のアカウントとこの特定の監査に固有のコードで、監査間で識別コードが再利用されるのを避けるためのものです。
2. Merkle Hashも表示されます。これは、直接使用するか、またはお客様のアカウントと特定の残高確認の詳細を使用して再構築することができます(以下参照)。監査ツールで検索するために使用するMerkle Leafは、このMerkle HashのSHA256の最初の16文字です。
3. アカウントコード、Kraken IIBAN、ID、および残高から記録IDとMerkle Leafを再構築するために必要な手順を、擬似コードで以下に説明します。結果は、Audits ページに表示される残高の特定の文字列フォーマットに依存することに注意してください。
- Record ID = SHA256(concatenate(Account Code, Kraken IIBAN, Audit ID))
- Balances = concatenate(“BTC:”, balBTC)
- Balances = concatenate(Balances, “,BTC.M:”, balBTCM)
- Balances = concatenate(Balances, “,ETH:”, balETH)
- Balances = concatenate(Balances, “,ETH2.S:”, balETH2S)
- Merkle Hash = concatenate(Record ID, “,”, Balances)
- Merkle Leaf = substring(SHA256(Merkle Hash), 0, 16)
具体的な例は、以下のコードスニペットでも紹介されています。また、残高確認結果のMerkle Leafは、残高確認の詳細で見ることができ、正しく再構築されていることを確認することができます。
Python
import hashlib
account_code = "8dc20f34da8cea8dd0f46b001694f5123ecd30d786c5eb92ad1a013703a4f8d1"
iiban = "AB12C34DEFG5KSQI"
audit_id = "PR30JUN22"
record_id = hashlib.sha256((account_code + iiban + audit_id).encode('utf-8')).hexdigest()
balances = "ADA:15129.4,ADA.S:0.0,BTC:0.2600852178,BTC.M:1.25,DOT:50.0,DOT.S:20.5,DOT.P:0.0,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]))
Rust
use sha2::{Digest, Sha256};
const ACCOUNT_CODE: &str = "8dc20f34da8cea8dd0f46b001694f5123ecd30d786c5eb92ad1a013703a4f8d1";
const IIBAN: &str = "AB12C34DEFG5KSQI";
const AUDIT_ID: &str = "PR30JUN22";
const BALANCES: &str = "ADA:15129.4,ADA.S:0.0,BTC:0.2600852178,BTC.M:1.25,DOT:50.0,DOT.S:20.5,DOT.P:0.0,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(AUDIT_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]);
}
Go
package main
import (
"crypto/sha256"
"fmt"
)
func main() {
accountCode := "8dc20f34da8cea8dd0f46b001694f5123ecd30d786c5eb92ad1a013703a4f8d1"
iiban := "AB12C34DEFG5KSQI"
auditId := "PR30JUN22"
secret := accountCode + iiban + auditId
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,BTC.M:1.25,DOT:50.0,DOT.S:20.5,DOT.P:0.0,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])
}
Bash
#!/bin/bash
ACCOUNT_CODE="8dc20f34da8cea8dd0f46b001694f5123ecd30d786c5eb92ad1a013703a4f8d1"
IIBAN="AB12C34DEFG5KSQI"
AUDIT_ID="PR30JUN22"
RECORD_ID=$(echo -n "${ACCOUNT_CODE}${IIBAN}${AUDIT_ID}" | sha256sum | head -c 64)
BALANCES="ADA:15129.4,ADA.S:0.0,BTC:0.2600852178,BTC.M:1.25,DOT:50.0,DOT.S:20.5,DOT.P:0.0,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)"
今後の改善点
透明性を高めるために、私たちが確認したProof of Reservesプロセスの改善点をいくつか紹介したいと思います。
- Proof of Reservesは、残高確認時点におけるオンチェーンの資金の管理を証明するものですが、攻撃者によって理論上複製される可能性がある秘密鍵の独占的な所有を証明することはできません。
- この手続きでは、隠れた担保を特定したり、残高確認に合格する目的で資金が借り出されていないことを証明することはできません。同様に、最新の残高確認以降に鍵が紛失したり、資金が盗まれたりしている可能性もあります。
- 監査人(会計事務所)は、被監査者側の二重性、あるいは当事者間の共謀のリスクを最小化するために、資格を有し、独立した存在でなければなりません。
私たちは、信頼できる独立した第三者機関と契約し、これらの残高確認を定期的かつ頻繁に実施することで、これらの欠点を軽減するよう努めています。
*注: 残高確認(監査)を定義する、正式に認められた手続きルールはありません。当社は、米国公認会計士協会の定める基準により、独立した会計事務所に監査業務を委託し、「合意された手続きに関する独立会計士による報告書」を発行しています。この報告書には、会計事務所が実施した具体的な手続きとその結果が記載されています。
なお上記に加えて、Krakenの日本法人であるPayward Asia株式会社においては、独立した監査法人による、資金決済法に基づく財務諸表に関する監査及び利用者財産の分別管理に関する監査を受けております。