21
21
// limitations under the License.
22
22
23
23
use std:: cmp:: Ordering ;
24
- use std:: ops:: Deref ;
25
24
26
- use bp:: dbc;
27
- use bp:: dbc:: anchor:: MergeError ;
25
+ use bp:: dbc:: opret:: OpretProof ;
26
+ use bp:: dbc:: tapret:: TapretProof ;
27
+ use bp:: dbc:: Anchor ;
28
+ use bp:: Txid ;
28
29
use commit_verify:: mpc;
29
30
use strict_encoding:: StrictDumb ;
30
31
31
- use crate :: { TransitionBundle , WitnessId , WitnessOrd , LIB_NAME_RGB } ;
32
+ use crate :: { BundleId , ContractId , TransitionBundle , WitnessId , WitnessOrd , LIB_NAME_RGB } ;
32
33
33
34
#[ derive( Clone , Eq , PartialEq , Debug ) ]
34
35
#[ derive( StrictType , StrictDumb , StrictEncode , StrictDecode ) ]
@@ -39,10 +40,15 @@ use crate::{TransitionBundle, WitnessId, WitnessOrd, LIB_NAME_RGB};
39
40
serde( crate = "serde_crate" , rename_all = "camelCase" )
40
41
) ]
41
42
pub struct AnchoredBundle {
42
- pub anchor : Anchor ,
43
+ pub anchor : XAnchor ,
43
44
pub bundle : TransitionBundle ,
44
45
}
45
46
47
+ impl AnchoredBundle {
48
+ #[ inline]
49
+ pub fn bundle_id ( & self ) -> BundleId { self . bundle . bundle_id ( ) }
50
+ }
51
+
46
52
#[ derive( Clone , Eq , PartialEq , Debug ) ]
47
53
#[ derive( StrictType , StrictDumb , StrictEncode , StrictDecode ) ]
48
54
#[ strict_type( lib = LIB_NAME_RGB , tags = custom, dumb = Self :: Bitcoin ( strict_dumb!( ) ) ) ]
@@ -51,65 +57,212 @@ pub struct AnchoredBundle {
51
57
derive( Serialize , Deserialize ) ,
52
58
serde( crate = "serde_crate" , rename_all = "camelCase" )
53
59
) ]
54
- pub enum Anchor < P : mpc:: Proof + StrictDumb = mpc:: MerkleProof > {
60
+ pub enum XAnchor < P : mpc:: Proof + StrictDumb = mpc:: MerkleProof > {
55
61
#[ strict_type( tag = 0x00 ) ]
56
- Bitcoin ( dbc :: Anchor < P > ) ,
62
+ Bitcoin ( AnchorSet < P > ) ,
57
63
58
64
#[ strict_type( tag = 0x01 ) ]
59
- Liquid ( dbc :: Anchor < P > ) ,
65
+ Liquid ( AnchorSet < P > ) ,
60
66
}
61
67
62
- impl < P : mpc:: Proof + StrictDumb > Deref for Anchor < P > {
63
- type Target = dbc:: Anchor < P > ;
64
-
68
+ impl < P : mpc:: Proof + StrictDumb > XAnchor < P > {
65
69
#[ inline]
66
- fn deref ( & self ) -> & Self :: Target {
70
+ pub fn layer1 ( & self ) -> Layer1 {
67
71
match self {
68
- Anchor :: Bitcoin ( anchor) | Anchor :: Liquid ( anchor) => anchor,
72
+ XAnchor :: Bitcoin ( _) => Layer1 :: Bitcoin ,
73
+ XAnchor :: Liquid ( _) => Layer1 :: Liquid ,
69
74
}
70
75
}
71
- }
72
76
73
- impl < P : mpc:: Proof + StrictDumb > Anchor < P > {
74
77
#[ inline]
75
- pub fn layer1 ( & self ) -> Layer1 {
78
+ pub fn witness_id ( & self ) -> WitnessId {
76
79
match self {
77
- Anchor :: Bitcoin ( _ ) => Layer1 :: Bitcoin ,
78
- Anchor :: Liquid ( _ ) => Layer1 :: Liquid ,
80
+ XAnchor :: Bitcoin ( anchor ) => WitnessId :: Bitcoin ( anchor . txid_unchecked ( ) ) ,
81
+ XAnchor :: Liquid ( anchor ) => WitnessId :: Liquid ( anchor . txid_unchecked ( ) ) ,
79
82
}
80
83
}
81
84
82
- #[ inline]
83
- pub fn witness_id ( & self ) -> WitnessId {
85
+ fn map < Q : mpc:: Proof + StrictDumb , E > (
86
+ self ,
87
+ f : impl FnOnce ( AnchorSet < P > ) -> Result < AnchorSet < Q > , E > ,
88
+ ) -> Result < XAnchor < Q > , E > {
84
89
match self {
85
- Anchor :: Bitcoin ( anchor) => WitnessId :: Bitcoin ( anchor. txid ) ,
86
- Anchor :: Liquid ( anchor) => WitnessId :: Liquid ( anchor. txid ) ,
90
+ XAnchor :: Bitcoin ( anchor) => f ( anchor) . map ( XAnchor :: Bitcoin ) ,
91
+ XAnchor :: Liquid ( anchor) => f ( anchor) . map ( XAnchor :: Liquid ) ,
87
92
}
88
93
}
94
+ }
89
95
90
- pub fn map < Q : mpc:: Proof + StrictDumb , E > (
91
- self ,
92
- f : impl FnOnce ( dbc:: Anchor < P > ) -> Result < dbc:: Anchor < Q > , E > ,
93
- ) -> Result < Anchor < Q > , E > {
96
+ impl XAnchor < mpc:: MerkleBlock > {
97
+ pub fn known_bundle_ids ( & self ) -> impl Iterator < Item = ( BundleId , ContractId ) > + ' _ {
94
98
match self {
95
- Anchor :: Bitcoin ( anchor) => f ( anchor) . map ( Anchor :: Bitcoin ) ,
96
- Anchor :: Liquid ( anchor) => f ( anchor) . map ( Anchor :: Liquid ) ,
99
+ XAnchor :: Bitcoin ( anchor) | XAnchor :: Liquid ( anchor) => anchor. known_bundle_ids ( ) ,
97
100
}
98
101
}
102
+
103
+ pub fn to_merkle_proof (
104
+ & self ,
105
+ contract_id : ContractId ,
106
+ ) -> Result < XAnchor < mpc:: MerkleProof > , mpc:: LeafNotKnown > {
107
+ self . clone ( ) . into_merkle_proof ( contract_id)
108
+ }
109
+
110
+ pub fn into_merkle_proof (
111
+ self ,
112
+ contract_id : ContractId ,
113
+ ) -> Result < XAnchor < mpc:: MerkleProof > , mpc:: LeafNotKnown > {
114
+ self . map ( |a| a. into_merkle_proof ( contract_id) )
115
+ }
116
+ }
117
+
118
+ impl XAnchor < mpc:: MerkleProof > {
119
+ pub fn to_merkle_block (
120
+ & self ,
121
+ contract_id : ContractId ,
122
+ bundle_id : BundleId ,
123
+ ) -> Result < XAnchor < mpc:: MerkleBlock > , mpc:: InvalidProof > {
124
+ self . clone ( ) . into_merkle_block ( contract_id, bundle_id)
125
+ }
126
+
127
+ pub fn into_merkle_block (
128
+ self ,
129
+ contract_id : ContractId ,
130
+ bundle_id : BundleId ,
131
+ ) -> Result < XAnchor < mpc:: MerkleBlock > , mpc:: InvalidProof > {
132
+ self . map ( |a| a. into_merkle_block ( contract_id, bundle_id) )
133
+ }
99
134
}
100
135
101
- impl Anchor < mpc:: MerkleBlock > {
102
- pub fn merge_reveal ( self , other : Self ) -> Result < Self , MergeError > {
103
- match ( self , other) {
104
- ( Anchor :: Bitcoin ( anchor) , Anchor :: Bitcoin ( other) ) => {
105
- anchor. merge_reveal ( other) . map ( Anchor :: Bitcoin )
106
- }
107
- ( Anchor :: Liquid ( anchor) , Anchor :: Liquid ( other) ) => {
108
- anchor. merge_reveal ( other) . map ( Anchor :: Liquid )
109
- }
110
- _ => Err ( MergeError :: ProofMismatch ) ,
136
+ #[ derive( Clone , Eq , PartialEq , Debug ) ]
137
+ #[ derive( StrictType , StrictDumb , StrictEncode , StrictDecode ) ]
138
+ #[ strict_type( lib = LIB_NAME_RGB , tags = custom, dumb = Self :: Tapret ( strict_dumb!( ) ) ) ]
139
+ #[ cfg_attr(
140
+ feature = "serde" ,
141
+ derive( Serialize , Deserialize ) ,
142
+ serde( crate = "serde_crate" , rename_all = "camelCase" )
143
+ ) ]
144
+ pub enum AnchorSet < P : mpc:: Proof + StrictDumb = mpc:: MerkleProof > {
145
+ #[ strict_type( tag = 0x01 ) ]
146
+ Tapret ( Anchor < P , TapretProof > ) ,
147
+ #[ strict_type( tag = 0x02 ) ]
148
+ Opret ( Anchor < P , OpretProof > ) ,
149
+ #[ strict_type( tag = 0x03 ) ]
150
+ Dual {
151
+ tapret : Anchor < P , TapretProof > ,
152
+ opret : Anchor < P , OpretProof > ,
153
+ } ,
154
+ }
155
+
156
+ impl < P : mpc:: Proof + StrictDumb > AnchorSet < P > {
157
+ pub fn txid ( & self ) -> Option < Txid > {
158
+ match self {
159
+ AnchorSet :: Tapret ( a) => Some ( a. txid ) ,
160
+ AnchorSet :: Opret ( a) => Some ( a. txid ) ,
161
+ AnchorSet :: Dual { tapret, opret } if tapret. txid == opret. txid => Some ( tapret. txid ) ,
162
+ _ => None ,
163
+ }
164
+ }
165
+
166
+ pub ( crate ) fn txid_unchecked ( & self ) -> Txid {
167
+ match self {
168
+ AnchorSet :: Tapret ( a) => a. txid ,
169
+ AnchorSet :: Opret ( a) => a. txid ,
170
+ AnchorSet :: Dual { tapret, .. } => tapret. txid ,
171
+ }
172
+ }
173
+
174
+ pub fn from_split (
175
+ tapret : Option < Anchor < P , TapretProof > > ,
176
+ opret : Option < Anchor < P , OpretProof > > ,
177
+ ) -> Option < Self > {
178
+ Some ( match ( tapret, opret) {
179
+ ( Some ( tapret) , Some ( opret) ) => Self :: Dual { tapret, opret } ,
180
+ ( Some ( tapret) , None ) => Self :: Tapret ( tapret) ,
181
+ ( None , Some ( opret) ) => Self :: Opret ( opret) ,
182
+ ( None , None ) => return None ,
183
+ } )
184
+ }
185
+
186
+ #[ allow( clippy:: type_complexity) ]
187
+ pub fn as_split ( & self ) -> ( Option < & Anchor < P , TapretProof > > , Option < & Anchor < P , OpretProof > > ) {
188
+ match self {
189
+ AnchorSet :: Tapret ( tapret) => ( Some ( tapret) , None ) ,
190
+ AnchorSet :: Opret ( opret) => ( None , Some ( opret) ) ,
191
+ AnchorSet :: Dual { tapret, opret } => ( Some ( tapret) , Some ( opret) ) ,
192
+ }
193
+ }
194
+
195
+ #[ allow( clippy:: type_complexity) ]
196
+ pub fn into_split ( self ) -> ( Option < Anchor < P , TapretProof > > , Option < Anchor < P , OpretProof > > ) {
197
+ match self {
198
+ AnchorSet :: Tapret ( tapret) => ( Some ( tapret) , None ) ,
199
+ AnchorSet :: Opret ( opret) => ( None , Some ( opret) ) ,
200
+ AnchorSet :: Dual { tapret, opret } => ( Some ( tapret) , Some ( opret) ) ,
111
201
}
112
202
}
203
+
204
+ pub fn mpc_proofs ( & self ) -> impl Iterator < Item = & P > {
205
+ let ( t, o) = self . as_split ( ) ;
206
+ t. map ( |a| & a. mpc_proof )
207
+ . into_iter ( )
208
+ . chain ( o. map ( |a| & a. mpc_proof ) )
209
+ }
210
+ }
211
+
212
+ impl AnchorSet < mpc:: MerkleProof > {
213
+ pub fn to_merkle_block (
214
+ & self ,
215
+ contract_id : ContractId ,
216
+ bundle_id : BundleId ,
217
+ ) -> Result < AnchorSet < mpc:: MerkleBlock > , mpc:: InvalidProof > {
218
+ self . clone ( ) . into_merkle_block ( contract_id, bundle_id)
219
+ }
220
+
221
+ pub fn into_merkle_block (
222
+ self ,
223
+ contract_id : ContractId ,
224
+ bundle_id : BundleId ,
225
+ ) -> Result < AnchorSet < mpc:: MerkleBlock > , mpc:: InvalidProof > {
226
+ let ( tapret, opret) = self . into_split ( ) ;
227
+ let tapret = tapret
228
+ . map ( |t| t. into_merkle_block ( contract_id, bundle_id) )
229
+ . transpose ( ) ?;
230
+ let opret = opret
231
+ . map ( |o| o. into_merkle_block ( contract_id, bundle_id) )
232
+ . transpose ( ) ?;
233
+ Ok ( AnchorSet :: from_split ( tapret, opret) . expect ( "one must be non-None" ) )
234
+ }
235
+ }
236
+
237
+ impl AnchorSet < mpc:: MerkleBlock > {
238
+ pub fn known_bundle_ids ( & self ) -> impl Iterator < Item = ( BundleId , ContractId ) > + ' _ {
239
+ self . mpc_proofs ( ) . flat_map ( |p| {
240
+ p. to_known_message_map ( )
241
+ . into_iter ( )
242
+ . map ( |( p, m) | ( m. into ( ) , p. into ( ) ) )
243
+ } )
244
+ }
245
+
246
+ pub fn to_merkle_proof (
247
+ & self ,
248
+ contract_id : ContractId ,
249
+ ) -> Result < AnchorSet < mpc:: MerkleProof > , mpc:: LeafNotKnown > {
250
+ self . clone ( ) . into_merkle_proof ( contract_id)
251
+ }
252
+
253
+ pub fn into_merkle_proof (
254
+ self ,
255
+ contract_id : ContractId ,
256
+ ) -> Result < AnchorSet < mpc:: MerkleProof > , mpc:: LeafNotKnown > {
257
+ let ( tapret, opret) = self . into_split ( ) ;
258
+ let tapret = tapret
259
+ . map ( |t| t. into_merkle_proof ( contract_id) )
260
+ . transpose ( ) ?;
261
+ let opret = opret
262
+ . map ( |o| o. into_merkle_proof ( contract_id) )
263
+ . transpose ( ) ?;
264
+ Ok ( AnchorSet :: from_split ( tapret, opret) . expect ( "one must be non-None" ) )
265
+ }
113
266
}
114
267
115
268
/// Txid and height information ordered according to the RGB consensus rules.
0 commit comments