0127 - Draft - Standards - Jan. 28, 2019 (7 years, 5 months ago)
28
2019
BIP: 127
Layer: Applications
Title: Simple Proof-of-Reserves Transactions
Author: Steven Roose <[email protected]>
Comments-Summary: No comments yet.
Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP 127
Status: Draft
Type: Standards Track
Created: 2019-01-28
License: CC0-1.0
This BIP describes a simple way to construct proof-of-reserves transactions. This proposal formalizes a standard format for constructing such proofs, easing their construction with existing wallet infrastructure and enabling general proof-verification software. It relies on existing standards such as regular Bitcoin transaction serialization/validation and the BIP 174 PSBT format. The proposal also includes the description of a PSBT extension for a better user experience.
This BIP is licensed under the Creative Commons CC0 1.0 Universal license.
From the very early days in the history of Bitcoin, there have been companies managing bitcoins for their users. These users give up control over their coins in return for a certain service. Inevitably, there have been many cases of companies losing their users' bitcoins without timely disclosing such events to the public. Proofs of Reserves are a way for companies managing large amounts of bitcoins to prove ownership over a given amount of funds. The regular proof of control helps to ensure that no significant loss has occurred.
While the term proof-of-reserves is not new by any means, the procedure is not very common among high-value custodian companies. One of the reasons for this is that every company that wants to perform a proof-of-reserves has to construct its own way to do so. Accordingly, their users have to understand the construction of the proof in order to be able to verify it. This raises the bar of entry both for custodians and for users.
The proof-of-reserve construction described in this document has some known shortcomings, mostly with regards to its privacy properties. While there exists research about improved proof-of-reserves mechanisms that have much better privacy properties 1 , this BIP intentionally only formalizes the de-facto existing method.
Our specification consists of two parts:
The final construction should have the following properties:
To allow for maximal compatibility with existing systems, proofs are formatted as regular Bitcoin transactions. However, one small adaptation to the transaction is made that has two functions:
The resulting construction is a Bitcoin transaction with the following characteristics:
SIGHASH_ALL
).
The existence of the first input (which is just a commitment hash) ensures that this transaction is invalid and can never be confirmed.
In theory, the first part of the specification would be sufficient as a minimum viable standard. However, there are a number of motivations to extend the standard with an extra layer of metadata:
The proposed proof-file format provides a standard way of combining multiple proofs and associated metadata. The specification of the format is in the Protocol Buffers 3 format.
syntax = "proto3";
import "google/protobuf/any.proto";
message OutputMeta {
// Identify the outpoint.
bytes txid = 1;
uint32 vout = 2;
// The block hash of the block where this output was created.
bytes block_hash = 3;
}
message FinalProof {
// The proof transaction. Should be able to be parsed like a regular
// Bitcoin transaction.
bytes proof_tx = 1;
// The metadata of the outputs used in the proof transaction.
repeated OutputMeta output_metadata = 2;
}
message ProofOfReserves {
// A version number for this format to enable extending it with
// additional fields.
uint32 version = 1;
// The network magic for the network in which the proofs are valid.
// 0xD9B4BEF9 for mainnet, 0x0709110B for testnet
//TODO consider BIP 44 coin type ids instead:
// https://github.com/satoshilabs/slips/blob/master/slip-0044.md
uint32 network_magic = 2;
// The commitment message for this proof-of-reserves.
// This message is global for all the proofs.
string message = 3;
// The block at which this proof is supposed to be validated.
// Verification should take into account unspentness of outputs at this
// block height.
bytes block_hash = 4;
// The set of final proof transactions with their output metadata.
repeated FinalProof final_proofs = 5;
// Reserved field that can potentially be used by proof-construction tools.
// It can be ignored for verification.
repeated google.protobuf.Any pending_proofs = 6;
}
The last field,
pending_proofs
, leaves open some space
in the same file that can be used by proof-construction tools. This
allows them to construct different proofs incrementally without having
to switch between file formats.
The "commitment input" detailed in the proof format section does not
spend an existing UTXO and thus shouldn't be signed (empty
scriptSig
and witness). This can cause some problems when
signing this type of transactions. For example, hardware wallets often
require the signer to provide information about all inputs of
transactions they are signing, such as the previous output or previous
transaction; this data obviously doesn't exist for the commitment
inputs.
For most existing devices, it's possible to circumvent these requirements by providing dummy data or by instructing the device to ignore this specific input. However, there is still a UX problem. Because the hardware wallet device doesn't recognize the transaction as a proof-of-reserves transaction it will think it is signing a regular transaction that is spending all the money in the UTXOs. Most devices will ask for confirmation with a message along the lines of "Are you sure you want to send XXX BTC to address [...]?". This is not the best user experience.
An addition to the BIP 174 PSBT format could help signing devices to
recognize proof-of-reserve transactions. The following field is added to
the BIP 174
INPUT
map:
PSBT_IN_POR_COMMITMENT = 0x09
{0x09}
{porCommitment}
Wallets processing an input that has this field set
scriptSig
for this input (as if
the
scriptPubKey
was
OP_TRUE
).
The proof transaction specification is based on the Bitcoin transaction serialization protocol and will thus always be compatible with serializers that can interpret Bitcoin transactions. The protobuf file format is custom to this BIP and has a version byte to enable updates while attempting to remain backwards compatible.
A proof-of-concept implementation of the PSBT extension in the
rust-bitcoin
project can be found in the
psbt-por
branch here:
https://github.com/stevenroose/rust-bitcoin/tree/psbt-por
A work-in-progress implementation of a tool that produces and verifies proofs in the described format can be found here: https://github.com/stevenroose/reserves
An implementation of the custom proof PSBTs is part of the BDK , and can be found here: https://crates.io/crates/bdk-reserves
SHA-256("Proof-of-Reserves: Some Message")
with the string
encoded as UTF-8.
↩︎