Skip to content

Commit 7276e9a

Browse files
committed
BIP 127: Simple proofs-of-reserves
1 parent b485340 commit 7276e9a

File tree

3 files changed

+244
-0
lines changed

3 files changed

+244
-0
lines changed

README.mediawiki

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,13 @@ Those proposing changes should consider that ultimately consent may rest with th
609609
| Kristov Atlas
610610
| Informational
611611
| Draft
612+
|-
613+
| [[bip-0127.mediawiki|127]]
614+
| Applications
615+
| Simple Proof-of-Reserves Transactions
616+
| Steven Roose
617+
| Standard
618+
| Draft
612619
|- style="background-color: #ffffcf"
613620
| [[bip-0130.mediawiki|130]]
614621
| Peer Services

bip-0127.mediawiki

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
2+
<pre>
3+
BIP: 127
4+
Layer: Applications
5+
Title: Simple Proof-of-Reserves Transactions
6+
Author: Steven Roose <[email protected]>
7+
Comments-Summary: No comments yet.
8+
Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0127
9+
Status: Draft
10+
Type: Standards Track
11+
Created: 2019-01-28
12+
License: CC0-1.0
13+
</pre>
14+
15+
16+
==Abstract==
17+
18+
This BIP describes a simple way to construct proof-of-reserves transactions.
19+
This proposal formalizes a standard format for constructing such proofs, easing
20+
their construction with existing wallet infrastructure and enabling general
21+
proof-verification software. It relies on existing standards such as regular
22+
Bitcoin transaction serialization/validation and the BIP 174 PSBT format.
23+
The proposal also includes the description of a PSBT extension for a better
24+
user experience.
25+
26+
==Copyright==
27+
28+
This BIP is licensed under the Creative Commons CC0 1.0 Universal license.
29+
30+
==Motivation==
31+
32+
From the very early days in the history of Bitcoin, there have been companies
33+
managing bitcoins for their users. These users give up control over their coins
34+
in return for a certain service. Inevitably, there have been many cases of
35+
companies losing their users' bitcoins without timely disclosing such events to
36+
the public. Proofs of Reserves are a way for companies managing large amounts
37+
of bitcoins to prove ownership over a given amount of funds. The regular proof
38+
of control helps to ensure that no significant loss has occurred.
39+
40+
While the term proof-of-reserves is not new by any means, the procedure is not
41+
very common among high-value custodian companies. One of the reasons for this
42+
is that every company that wants to perform a proof-of-reserves has to construct
43+
its own way to do so. Accordingly, their users have to understand the
44+
construction of the proof in order to be able to verify it. This raises the bar
45+
of entry both for custodians and for users.
46+
47+
48+
===What this BIP is not doing===
49+
50+
The proof-of-reserve construction described in this document has some known
51+
shortcomings, mostly with regards to its privacy properties. While there exists
52+
research about improved proof-of-reserves mechanisms that have much better
53+
privacy properties<ref>Dagher, Gaby G., Benedikt Bünz, Joseph Bonneau, Jeremy
54+
Clark, and Dan Boneh. "Provisions: Privacy-preserving proofs of solvency for
55+
Bitcoin exchanges." (2015).</ref>, this BIP intentionally only formalizes
56+
the de-facto existing method.
57+
58+
59+
==Specification==
60+
61+
Our specification consists of two parts:
62+
# the format for the actual proofs
63+
# a file format used to package a set of proofs and relevant metadata
64+
65+
The final construction should have the following properties:
66+
* flexible proof construction to support complex wallet infrastructures
67+
* easy integration with existing wallet solutions (both hardware and software wallets)
68+
* support for verification via a standard procedure, regardless of publisher of the proof
69+
* proof prevents reuse of proofs by other parties by committing to a message
70+
* allow validating that the issuer had the funds under his control at a certain block, regardless of what happened after that block
71+
72+
===Proof Format===
73+
74+
To allow for maximal compatibility with existing systems, proofs are formatted as regular Bitcoin
75+
transactions. However, one small adaptation to the transaction is made that has two functions:
76+
# make the transaction unspendable to avoid putting funds at risk
77+
# link the proof to the issuer of the proof to prevent copying proofs from other custodians
78+
79+
The resulting construction is a Bitcoin transaction with the following
80+
characteristics:
81+
82+
* The first input (the "commitment input")
83+
** MUST have the txid part of the previous outpoint set to the SHA-256 hash of the commitment message prefixed with "Proof-of-Reserves: "<ref>If the message is "Some Message", the txid part should be <tt>SHA-256("Proof-of-Reserves: Some Message")</tt> with the string encoded as UTF-8.</ref> and index 0.
84+
* The remaining inputs
85+
** MUST have signatures that commit to the commitment input (e.g. using <tt>SIGHASH_ALL</tt>).
86+
* The transaction MUST have a single output that is the exact sum of all the inputs, assuming the commitment input to have 0 value; this means the transaction has no miner fee.
87+
88+
The existence of the first input (which is just a commitment hash) ensures
89+
that this transaction is invalid and can never be confirmed.
90+
91+
92+
===Proof File Format===
93+
94+
In theory, the first part of the specification would be sufficient as a minimum
95+
viable standard. However, there are a number of motivations to extend the
96+
standard with an extra layer of metadata:
97+
98+
# constructing and combining multiple proofs
99+
#:Having thousands of UTXOs spread across different offline and online wallets could make it difficult to construct a single proof transaction with all UTXOs. Allowing multiple proof transactions with the same commitment message and block number gives extra flexibility to custodians with complex wallet infrastructure without making the combined proof less secure.
100+
# metadata for verification
101+
#:Not all systems that will be used for verification have access to a full index of all transactions. However, proofs should be easily verifiable even after some of the UTXOs used in the proof are no longer unspent. Metadata present in the proof allows for relatively efficient verification of proofs even if no transaction index is available.
102+
# potential future improvements
103+
#:The extensible metadata format allows for amending the standard in the future. One potential improvement would be having UTXO set commitments. These would allow the proofs-of-reserves to come with accompanying proofs-of-inclusion of all used UTXOs in the UTXO set at the block of proof construction (making validation even more efficient).
104+
105+
The proposed proof-file format provides a standard way of combining multiple
106+
proofs and associated metadata. The specification of the format is in the
107+
Protocol Buffers<ref>https://github.com/protocolbuffers/protobuf/</ref> format.
108+
109+
<pre>
110+
syntax = "proto3";
111+
import "google/protobuf/any.proto";
112+
113+
message OutputMeta {
114+
// Identify the outpoint.
115+
bytes txid = 1;
116+
uint32 vout = 2;
117+
118+
// The block hash of the block where this output was created.
119+
bytes block_hash = 3;
120+
}
121+
122+
message FinalProof {
123+
// The proof transaction. Should be able to be parsed like a regular
124+
// Bitcoin transaction.
125+
bytes proof_tx = 1;
126+
127+
// The metadata of the ouputs used in the proof transaction.
128+
repeated OutputMeta output_metadata = 2;
129+
}
130+
131+
message ProofOfReserves {
132+
// A version number for this format to enable extending it with
133+
// additional fields.
134+
uint32 version = 1;
135+
136+
// The network magic for the network in which the proofs are valid.
137+
// 0xD9B4BEF9 for mainnet, 0x0709110B for testnet
138+
//TODO consider BIP44 coin type ids instead:
139+
// https://github.com/satoshilabs/slips/blob/master/slip-0044.md
140+
uint32 network_magic = 2;
141+
142+
// The commitment message for this proof-of-reserves.
143+
// This message is global for all the proofs.
144+
string message = 3;
145+
146+
// The block at which this proof is supposed to be validated.
147+
// Verification should take into account unspentness of outputs at this
148+
// block height.
149+
bytes block_hash = 4;
150+
151+
// The set of final proof transactions with their output metadata.
152+
repeated FinalProof final_proofs = 5;
153+
154+
// Reserved field that can potentially be used by proof-construction tools.
155+
// It can be ignored for verification.
156+
repeated google.protobuf.Any pending_proofs = 6;
157+
}
158+
</pre>
159+
160+
The last field, <tt>pending_proofs</tt>, leaves open some space in the same
161+
file that can be used by proof-construction tools. This allows them to
162+
construct different proofs incrementally without having to switch between file
163+
formats.
164+
165+
166+
===PSBT (BIP 174) extension===
167+
168+
The "commitment input" detailed in the proof format section does not spend an
169+
existing UTXO and thus shouldn't be signed (empty <tt>scriptSig</tt> and
170+
witness). This can cause some problems when signing this type of transactions.
171+
For example, hardware wallets often require the signer to provide information
172+
about all inputs of transactions they are signing, such as the previous output
173+
or previous transaction; this data obviously doesn't exist for the commitment
174+
inputs.
175+
176+
For most existing devices, it's possible to circumvent these requirements by
177+
providing dummy data or by instructing the device to ignore this specific
178+
input. However, there is still a UX problem. Because the hardware wallet
179+
device doesn't recognize the transaction as a proof-of-reserves transaction it
180+
will think it is signing a regular transaction that is spending all the money
181+
in the UTXOs. Most devices will ask for confirmation with a message along the
182+
lines of "Are you sure you want to send XXX BTC to address [...]?". This is
183+
not the best user experience.
184+
185+
An addition to the BIP 174 PSBT format could help signing devices to recognize proof-of-reserve transactions.
186+
The following field is added to the BIP 174 <tt>INPUT</tt> map:
187+
188+
* Type: Proof-of-reserves commitment <tt>PSBT_IN_POR_COMMITMENT = 0x09</tt>
189+
** Key: None. The key must only contain the 1 byte type.
190+
*** <tt>{0x09}</tt>
191+
** Value: The UTF-8 encoded commitment message string for the proof-of-reserves.
192+
*** <tt>{porCommitment}</tt>
193+
194+
Wallets processing an input that has this field set
195+
* MUST make sure the txid of the previous outpoint is set to the SHA-256 hash of the prefixed commitment message string, as detailed above;
196+
* MUST assume the input value to be 0 (without requiring the previous output or transaction to be provided);
197+
* SHOULD display the commitment message to ask the user for confirmation before signing any inputs;
198+
* SHOULD only provide signatures with a signature hash that commits to this input;
199+
* SHOULD accept an empty <tt>scriptSig</tt> for this input (as if the <tt>scriptPubKey</tt> was <tt>OP_TRUE</tt>).
200+
201+
202+
==Compatibility==
203+
204+
The proof transaction specification is based on the Bitcoin transaction
205+
serialization protocol and will thus always be compatible with serializers
206+
that can interpret Bitcoin transactions. The protobuf file format is custom
207+
to this BIP and has a version byte to enable updates while attempting to remain
208+
backwards compatible.
209+
210+
211+
==Implementations==
212+
213+
A proof-of-concept implementation of the PSBT extension in the
214+
[https://github.com/rust-bitcoin/rust-bitcoin rust-bitcoin] project can be
215+
found in the <tt>psbt-por</tt> branch here:
216+
https://github.com/stevenroose/rust-bitcoin/tree/psbt-por
217+
218+
A work-in-progress implementation of a tool that produces and verifies proofs
219+
in the described format can be found here:
220+
https://github.com/stevenroose/reserves
221+
222+
223+
== Footnotes ==
224+
225+
<references />
226+

bip-0174.mediawiki

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,12 @@ The currently defined per-input types are defined as follows:
174174
** Value: The Finalized scriptWitness contains a fully constructed scriptWitness with signatures and any other scripts necessary for the input to pass validation.
175175
*** <tt>{scriptWitness}</tt>
176176
177+
* Type: Proof-of-reserves commitment <tt>PSBT_IN_POR_COMMITMENT = 0x09</tt>
178+
** Key: None. The key must only contain the 1 byte type.
179+
*** <tt>{0x09}</tt>
180+
** Value: The UTF-8 encoded commitment message string for the proof-of-reserves. See [[bip-0127.mediawiki|BIP 127]] for more information.
181+
*** <tt>{porCommitment}</tt>
182+
177183
The currently defined per-output <ref>'''Why do we need per-output data?''' Per-output data allows signers
178184
to verify that the outputs are going to the intended recipient. The output data can also be use by signers to
179185
determine which outputs are change outputs and verify that the change is returning to the correct place.</ref> types are defined as follows:
@@ -698,6 +704,11 @@ Any data types, their associated scope and BIP number must be defined here
698704
| PSBT_IN_FINAL_SCRIPTWITNESS
699705
| BIP 174
700706
|-
707+
| Input
708+
| 9
709+
| PSBT_IN_POR_COMMITMENT
710+
| [[bip-0127.mediawiki|BIP 127]]
711+
|-
701712
| Output
702713
| 0
703714
| PSBT_OUT_REDEEM_SCRIPT

0 commit comments

Comments
 (0)