@@ -19,28 +19,42 @@ use spaces_protocol::{
1919 slabel:: SLabel ,
2020 SpaceOut ,
2121} ;
22+ use spaces_ptr:: { PtrOut , Commitment , sptr:: Sptr } ;
23+
24+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
25+ pub enum ProofType {
26+ Spaces ,
27+ Ptrs ,
28+ }
2229
2330pub struct Veritas {
2431 anchors : BTreeSet < hasher:: Hash > ,
32+ proof_type : ProofType ,
2533 ctx : Secp256k1 < VerifyOnly > ,
2634}
2735
2836pub struct Proof {
2937 root : Hash ,
38+ proof_type : ProofType ,
3039 inner : SubTree < Sha256Hasher > ,
3140}
3241
3342pub struct ProofIter < ' a > {
43+ proof_type : ProofType ,
3444 inner : SubtreeIter < ' a > ,
3545}
3646
3747pub enum Value {
3848 Outpoint ( OutPoint ) ,
3949 UTXO ( SpaceOut ) ,
50+ PtrUTXO ( PtrOut ) ,
51+ Commitment ( Commitment ) ,
52+ Space ( SLabel ) ,
53+ Root ( hasher:: Hash ) ,
4054 Unknown ( Vec < u8 > ) ,
4155}
4256
43- pub trait SpaceoutExt {
57+ pub trait UtxoExt {
4458 fn public_key ( & self ) -> Option < XOnlyPublicKey > ;
4559}
4660
@@ -58,9 +72,10 @@ pub enum Error {
5872}
5973
6074impl Veritas {
61- pub fn new ( ) -> Self {
75+ pub fn new ( proof_type : ProofType ) -> Self {
6276 Self {
6377 anchors : BTreeSet :: new ( ) ,
78+ proof_type,
6479 ctx : Secp256k1 :: verification_only ( ) ,
6580 }
6681 }
@@ -76,7 +91,11 @@ impl Veritas {
7691 if !self . anchors . contains ( & root) {
7792 return Err ( Error :: NoMatchingAnchor ) ;
7893 }
79- Ok ( Proof { root, inner } )
94+ Ok ( Proof {
95+ root,
96+ proof_type : self . proof_type . clone ( ) ,
97+ inner
98+ } )
8099 }
81100
82101 pub fn verify_schnorr ( & self , pubkey : & [ u8 ] , digest : & [ u8 ] , sig : & [ u8 ] ) -> bool {
@@ -105,6 +124,7 @@ impl Veritas {
105124impl Proof {
106125 pub fn iter ( & self ) -> ProofIter {
107126 ProofIter {
127+ proof_type : self . proof_type ,
108128 inner : self . inner . iter ( ) ,
109129 }
110130 }
@@ -146,6 +166,69 @@ impl Proof {
146166 }
147167 Ok ( None )
148168 }
169+
170+ /// Retrieves a PTR UTXO leaf within the subtree specified by the outpoint hash
171+ pub fn get_ptrout ( & self , utxo_key : & Hash ) -> Result < Option < PtrOut > , Error > {
172+ let ( _, value) = match self . inner . iter ( ) . find ( |( k, _) | * k == utxo_key) {
173+ None => return Ok ( None ) ,
174+ Some ( kv) => kv,
175+ } ;
176+ let ( ptrout, _) : ( PtrOut , _ ) = bincode:: decode_from_slice ( value, config:: standard ( ) )
177+ . map_err ( |_| Error :: MalformedValue ) ?;
178+ Ok ( Some ( ptrout) )
179+ }
180+
181+ /// Retrieves a PTR UTXO leaf containing the specified sptr
182+ pub fn find_ptr ( & self , sptr : & Sptr ) -> Result < Option < PtrOut > , Error > {
183+ for ( _, v) in self . iter ( ) {
184+ match v {
185+ Value :: PtrUTXO ( ptrout) => {
186+ if ptrout
187+ . sptr
188+ . as_ref ( )
189+ . is_some_and ( |ptr| & ptr. id == sptr)
190+ {
191+ return Ok ( Some ( ptrout) ) ;
192+ }
193+ }
194+ _ => continue ,
195+ }
196+ }
197+ Ok ( None )
198+ }
199+
200+ /// Retrieves a commitment by its key
201+ pub fn get_commitment ( & self , commitment_key : & Hash ) -> Result < Option < Commitment > , Error > {
202+ let ( _, value) = match self . inner . iter ( ) . find ( |( k, _) | * k == commitment_key) {
203+ None => return Ok ( None ) ,
204+ Some ( kv) => kv,
205+ } ;
206+ let ( commitment, _) : ( Commitment , _ ) = bincode:: decode_from_slice ( value, config:: standard ( ) )
207+ . map_err ( |_| Error :: MalformedValue ) ?;
208+ Ok ( Some ( commitment) )
209+ }
210+
211+ /// Retrieves the delegated space for an SPTR
212+ pub fn get_delegation ( & self , sptr_key : & Hash ) -> Result < Option < SLabel > , Error > {
213+ let ( _, value) = match self . inner . iter ( ) . find ( |( k, _) | * k == sptr_key) {
214+ None => return Ok ( None ) ,
215+ Some ( kv) => kv,
216+ } ;
217+ let ( space, _) : ( SLabel , _ ) = bincode:: decode_from_slice ( value, config:: standard ( ) )
218+ . map_err ( |_| Error :: MalformedValue ) ?;
219+ Ok ( Some ( space) )
220+ }
221+
222+ /// Retrieves the latest commitment root for a space
223+ pub fn get_registry_tip ( & self , registry_key : & Hash ) -> Result < Option < hasher:: Hash > , Error > {
224+ let ( _, value) = match self . inner . iter ( ) . find ( |( k, _) | * k == registry_key) {
225+ None => return Ok ( None ) ,
226+ Some ( kv) => kv,
227+ } ;
228+ let ( root, _) : ( hasher:: Hash , _ ) = bincode:: decode_from_slice ( value, config:: standard ( ) )
229+ . map_err ( |_| Error :: MalformedValue ) ?;
230+ Ok ( Some ( root) )
231+ }
149232}
150233
151234impl From < spacedb:: Error > for Error {
@@ -161,7 +244,16 @@ impl From<spacedb::Error> for Error {
161244 }
162245}
163246
164- impl SpaceoutExt for SpaceOut {
247+ impl UtxoExt for SpaceOut {
248+ fn public_key ( & self ) -> Option < XOnlyPublicKey > {
249+ match self . script_pubkey . is_p2tr ( ) {
250+ true => XOnlyPublicKey :: from_slice ( & self . script_pubkey . as_bytes ( ) [ 2 ..] ) . ok ( ) ,
251+ false => None ,
252+ }
253+ }
254+ }
255+
256+ impl UtxoExt for PtrOut {
165257 fn public_key ( & self ) -> Option < XOnlyPublicKey > {
166258 match self . script_pubkey . is_p2tr ( ) {
167259 true => XOnlyPublicKey :: from_slice ( & self . script_pubkey . as_bytes ( ) [ 2 ..] ) . ok ( ) ,
@@ -175,24 +267,64 @@ impl Iterator for ProofIter<'_> {
175267
176268 fn next ( & mut self ) -> Option < Self :: Item > {
177269 self . inner . next ( ) . map ( |( k, v) | {
178- if OutpointKey :: is_valid ( k) {
179- let result = bincode:: decode_from_slice ( v. as_slice ( ) , config:: standard ( ) )
180- . ok ( )
181- . map ( |( raw, _) | Value :: UTXO ( raw) ) ;
270+ match self . proof_type {
271+ ProofType :: Spaces => {
272+ // Spaces proof: OutpointKey → SpaceOut, SpaceKey → OutPoint
273+ if OutpointKey :: is_valid ( k) {
274+ let result = bincode:: decode_from_slice ( v. as_slice ( ) , config:: standard ( ) )
275+ . ok ( )
276+ . map ( |( raw, _) | Value :: UTXO ( raw) ) ;
277+ return ( * k, result. unwrap_or ( Value :: Unknown ( v. clone ( ) ) ) ) ;
278+ }
279+ if SpaceKey :: is_valid ( k) {
280+ let result: Option < OutPoint > =
281+ bincode:: serde:: decode_from_slice ( v. as_slice ( ) , config:: standard ( ) )
282+ . ok ( )
283+ . map ( |( raw, _) | raw) ;
284+ return result
285+ . map ( |r| ( * k, Value :: Outpoint ( r) ) )
286+ . unwrap_or_else ( || ( * k, Value :: Unknown ( v. clone ( ) ) ) ) ;
287+ }
288+ ( * k, Value :: Unknown ( v. clone ( ) ) )
289+ }
290+ ProofType :: Ptrs => {
291+ // PTR proof: Try to decode value as different PTR types
182292
183- return ( * k , result . unwrap_or ( Value :: Unknown ( v . clone ( ) ) ) ) ;
184- }
185- if SpaceKey :: is_valid ( k ) {
186- let result : Option < OutPoint > =
187- bincode :: serde :: decode_from_slice ( v . as_slice ( ) , config :: standard ( ) )
188- . ok ( )
189- . map ( | ( raw , _ ) | raw ) ;
190- return result
191- . map ( |r| ( * k , Value :: Outpoint ( r ) ) )
192- . unwrap_or_else ( || ( * k, Value :: Unknown ( v . clone ( ) ) ) ) ;
193- }
293+ // Try PtrOutpointKey → PtrOut
294+ let ptrout_result : Result < ( PtrOut , _ ) , _ > = bincode :: decode_from_slice ( v . as_slice ( ) , config :: standard ( ) ) ;
295+ if let Ok ( ( ptrout , _ ) ) = ptrout_result {
296+ return ( * k , Value :: PtrUTXO ( ptrout ) ) ;
297+ }
298+
299+ // Try Sptr → OutPoint
300+ let outpoint_result : Result < ( OutPoint , _ ) , _ > = bincode :: serde :: decode_from_slice ( v . as_slice ( ) , config :: standard ( ) ) ;
301+ if let Ok ( ( outpoint , _ ) ) = outpoint_result {
302+ return ( * k, Value :: Outpoint ( outpoint ) ) ;
303+ }
194304
195- ( * k, Value :: Unknown ( v. clone ( ) ) )
305+ // Try CommitmentKey → Commitment
306+ let commitment_result: Result < ( Commitment , _ ) , _ > = bincode:: decode_from_slice ( v. as_slice ( ) , config:: standard ( ) ) ;
307+ if let Ok ( ( commitment, _) ) = commitment_result {
308+ return ( * k, Value :: Commitment ( commitment) ) ;
309+ }
310+
311+ // Try RegistrySptrKey → SLabel
312+ let space_result: Result < ( SLabel , _ ) , _ > = bincode:: decode_from_slice ( v. as_slice ( ) , config:: standard ( ) ) ;
313+ if let Ok ( ( space, _) ) = space_result {
314+ return ( * k, Value :: Space ( space) ) ;
315+ }
316+
317+ // Try RegistryKey → Hash (root)
318+ if v. len ( ) == 32 {
319+ let root_result: Result < ( hasher:: Hash , _ ) , _ > = bincode:: decode_from_slice ( v. as_slice ( ) , config:: standard ( ) ) ;
320+ if let Ok ( ( root, _) ) = root_result {
321+ return ( * k, Value :: Root ( root) ) ;
322+ }
323+ }
324+
325+ ( * k, Value :: Unknown ( v. clone ( ) ) )
326+ }
327+ }
196328 } )
197329 }
198330}
0 commit comments