-
Notifications
You must be signed in to change notification settings - Fork 30
/
psbts.txt
221 lines (161 loc) · 9.19 KB
/
psbts.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
PSBTs - Partially-Signed Bitcoin Transactions
Last update: 2019-07-16
Summary from the following sources
- Andrew Chow talk: https://youtu.be/H6xZSRDXUiU
- Greg Sanders talk: https://youtu.be/iJR9Lg1jyJg
- bitcoin-cli help (master v0.18.99.0 / May 2019)
- IRC discussions
-----
BIP 174 describes the PSBT protocol format
https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki
Roles: Creator
Updater
Signer -> does sanity checking
Combiner
Finaliser
Extractor -> broadcast
Uses: Multisigs
Coinjoins
Hardware wallets
Offline wallets (ColdCard)
Initially landed in Bitcoin Core 0.17 release.
-----
PSBTs are stored in base64 key-value maps. Each key-value map field tells the
signer critical information about the transaction.
*Global* types are to be used once for possibly many reasons.
- Unsigned transaction: the raw unsigned txn itself.
It should not carry any witness data in this form.
*Per-Input* types correspond to the transaction's inputs; are 0-indexed.
- Non-Witness UTXO (non-SegWit)
Value: Serialised prevtx
- Witness UTXO (SegWit)
Value: Serialised prevtx output
- Partial Signature
Key: public key - Value: signature
- Sighash Type
Value: sighash advisory type, default is sighash all, e.g. hash entire txn and
sign, other options include single
- Redeem Script (for P2SH)
Value: redeemScript - serialised script which is then recursively evaluated
- Witness Script
Value: witnessScript
- BIP 32 Derivation Paths (in a multisig can be any number of them)
Key: public key - Value: master fingerprint, index array
- Finalised scriptSig
Value: valid and final scriptSig
- Finalised scriptWitness
Value: valid and final scriptWitness
*Per-Output* types are a subset of Per-Input Types. Example: change outputs.
- Redeem Script
- Witness Script
- BIP 32 Derivation Paths
-----
RPC calls
- analyzepsbt "psbt"
- combinepsbt ["psbt",...]
- converttopsbt "hexstring" ( permitsigdata iswitness )
- createpsbt - like createrawtransaction
[{"txid":"hex","vout":n,"sequence":n},...] [{"address":amount},
{"data":"hex"},...] ( locktime replaceable )
- decodepsbt "psbt" - useful for introspection
- finalizepsbt "psbt" ( extract )
- joinpsbts ["psbt",...]
- utxoupdatepsbt "psbt"
- walletcreatefundedpsbt - equivalent to fundrawtransaction
[{"txid":"hex","vout":n,"sequence":n},...]
[{"address":amount},{"data":"hex"},...]
( locktime options bip32derivs )
- walletprocesspsbt "psbt" ( sign "sighashtype" bip32derivs )
-----
PSBT Subscriptors
Idea proposed 10 May 2019 on bitcoin-core-dev IRC channel, log URL here:
http://www.erisian.com.au/bitcoin-core-dev/log-2019-05-10.html#l-439
<meshcollider> #topic signing scripts where different satisfactions may have different costs (sipa)
<sipa> gmaxwell: yes, the easiest approach is always assuming the worst case
<sipa> this is in the context of things like miniscript or the taproot proposal i recently published
<gmaxwell> sipa: that isn't quite what I meant, like if you're going to spend via branch X, you have to know that in advance if you want to use lower weight for fee purposes.
<gmaxwell> so I think PSBT may need an extension for that.
<sipa> right, but plugging that into fee estimation and coin selection seems nontrivial
<gmaxwell> I think its trivial once you assume you have a way of knowing the "weight bound" for each input you're going to use... which itself is only triial if you always assume the worst case branch.
<sipa> gmaxwell: hmm, i guess if we can come up with something sufficiently generic to put in PSBT (something that restricts certain options or so?), it can probably go in the same form into descriptor records
<gmaxwell> right.
<gmaxwell> my thought is that a descriptor should be subsettable.
<gmaxwell> Like if a script is A or B, there should exist a descriptor that maps to the same spk but only lets you spend via A
<sipa> that's an interesting idea, putting it in the descriptor itself
<gmaxwell> in the context of taproot, that descriptor might not even reveal the content of B.
<gmaxwell> Descriptor-slice.
<sipa> let's call it a subscriptor
<sipa> :p
<gmaxwell> oohhhh
<meshcollider> lol
<gmaxwell> Right, so basically you make the cost analysis use the worst case, but use of a subscriptor can lower the worst case.
<achow101> so if used with taproot, you would have the hash of the other branch indicating that that other branch won't be used
<gmaxwell> right. something like that. I think you should be also able to include the data but indicate it won't be used.
<sipa> i guess there could be an unavailable(...) syntax element in descriptors, which for output calculation is identical to ..., but assumes the key/path/... subexpression isn't available for signing
<gmaxwell> (for a lot of applications you'll want to know what it is)
<sipa> (or something more syntax sugarry)
<sipa> i like this
<achow101> but does such a subscriptor need to be included in a psbt?
<sipa> i think a subscriptor could just result in certain information not being put in a PSBT
<instagibbs> was going to ask "when miniscript in Core"
<instagibbs> motivating use-cases are probably required, but above conversation answers that one way
<gmaxwell> instagibbs: well, maybe it makes sense to do miniscript with taproot and not bother without.
<instagibbs> yep
<gmaxwell> certantly, things like taproot need miniscript in the sense that their ability will be wasted if we don't make it easier to make complex scripts.
-----
2019-07-16 Combining Taproot with PSBT via descriptors - notes from IRC
http://www.erisian.com.au/bitcoin-core-dev/log-2019-07-15.html#l-548
elichai: We would need
1. new descriptors
2. classes and support for Witness V2 Bech32 addresses
3. classes for Taproot in the wallet
4. serialization/deserialization of Taproot and witness v2 addresses
sipa / achow:
To combine Taproot into PSBT, would need to touch signing/PSBT logic
and descriptors. If we have Taproot support in descriptors and PSBT,
we'll automatically have it in the wallet, just like right now the
user never provides keys, UTXOs, etc.
In the RPC, we have PSBT support for the full stack of operations
outside of the wallet, so Taproot can be implemented and tested
without ever touching the wallet code at all (assuming descriptor
wallets, since we don't have the equivalent of walletprocesspsbt
using descriptors yet, maybe we need that first), then all we need is
to add Taproot to PSBT/descriptors, and the full stack of operations
would be supported outside of the wallet.
Musig is harder though, as it requires state on the signer device.
The tree structure for multiple scripts would be in the descriptor.
The 32-byte x-coordinate idea (which we may update Taproot with) may
affect how that PSBT record is structured too, but it's not like we
need new parsing code; Bech32 parsing is already generic.
If you want to learn Bitcoin Core better (which i very much encourage
you to!) I think it's better to focus on one piece at a time, and
actually integrate it.
For example, an RPC that takes a descriptor and a bunch of private
keys, and signs with them, would be pretty generally useful.
For the extensions to PSBT... I think it's generally too early.
Once Taproot is finalized, I think the way to actually add it to PSBT
via descriptors will be pretty straightforward.
What will be needed in terms of data structures is:
1. a "taproot derivation" record in signing providers
2. descriptors that can fill that record
3. a way for that record to be serialized in PSBT
4. and signing logic to use it
For descriptors we likely want a fragment tap(KEY,[[X,Y],[Z,[T,U]]])
kind of construction, where you give the root key and the leaves in
some tree-encoding way where the X/Y/Z/T/U are subexpressions that
represent scripts.
They could be pk(), or multi(), ... or once we
have miniscript probably a whole bunch more things (I hope to publish
more about that soon) and that would then get converted into a
"taproot key record" for the key path and for each leaf in
signingprovider/psbt.
src/script/descriptor.cpp L149-170 is an interface for all the "key"
expressions inside BIP32, with a number of implementations (pubkeys,
descriptors, origin info).
L335-497 is a generic implementation of a "script" node in a
descriptor, followed by implementations that add node-specific logic
(pk, pkh, sh, wpkh, wsh, multi, combi, addr, raw), and after that is
parsing (string to descriptor) code, and inference (script to
descriptor) code.
If your end goal is integrating things into Bitcoin Core, I suspect
getting familiar with the code is the best way to spend time.