@@ -22,6 +22,10 @@ use sui_types::{
2222
2323use crate :: { config:: Limits , error:: RpcError , task:: watermark:: Watermarks } ;
2424
25+ /// A map of objects from an executed transaction, keyed by (ObjectID, SequenceNumber).
26+ /// None values indicate tombstones for deleted/wrapped objects.
27+ type ExecutionObjectMap = Arc < BTreeMap < ( ObjectID , SequenceNumber ) , Option < NativeObject > > > ;
28+
2529/// A way to share information between fields in a request, similar to [Context].
2630///
2731/// Unlike [Context], [Scope] is not referenced by every field resolver. Instead, fields must
@@ -52,7 +56,7 @@ pub(crate) struct Scope {
5256 /// Maps (ObjectID, SequenceNumber) to optional object data.
5357 /// None indicates the object was deleted or wrapped at that version.
5458 /// This enables any Object GraphQL type to access fresh data without database queries.
55- execution_objects : Arc < BTreeMap < ( ObjectID , SequenceNumber ) , Option < NativeObject > > > ,
59+ execution_objects : ExecutionObjectMap ,
5660
5761 /// Access to packages for type resolution.
5862 package_store : Arc < dyn PackageStore > ,
@@ -163,16 +167,16 @@ impl Scope {
163167 pub ( crate ) fn with_executed_transaction (
164168 & self ,
165169 executed_transaction : & grpc:: ExecutedTransaction ,
166- ) -> Self {
167- let execution_objects = extract_objects_from_executed_transaction ( executed_transaction) ;
170+ ) -> Result < Self , RpcError > {
171+ let execution_objects = extract_objects_from_executed_transaction ( executed_transaction) ? ;
168172
169- Self {
173+ Ok ( Self {
170174 checkpoint_viewed_at : None ,
171175 root_version : self . root_version ,
172176 execution_objects,
173177 package_store : self . package_store . clone ( ) ,
174178 resolver_limits : self . resolver_limits . clone ( ) ,
175- }
179+ } )
176180 }
177181
178182 /// A package resolver with access to the packages known at this scope.
@@ -187,38 +191,49 @@ impl Scope {
187191/// where None indicates the object was deleted or wrapped at that version.
188192fn extract_objects_from_executed_transaction (
189193 executed_transaction : & grpc:: ExecutedTransaction ,
190- ) -> Arc < BTreeMap < ( ObjectID , SequenceNumber ) , Option < NativeObject > > > {
194+ ) -> Result < ExecutionObjectMap , RpcError > {
195+ use anyhow:: Context ;
196+
191197 let mut map = BTreeMap :: new ( ) ;
192198
193199 // Extract all objects from the ObjectSet.
194200 if let Some ( object_set) = & executed_transaction. objects {
195201 for obj in & object_set. objects {
196202 if let Some ( bcs) = & obj. bcs {
197- let native_obj: NativeObject =
198- bcs. deserialize ( ) . expect ( "Object BCS should be valid" ) ;
203+ let native_obj: NativeObject = bcs
204+ . deserialize ( )
205+ . context ( "Failed to deserialize object BCS" ) ?;
199206 map. insert ( ( native_obj. id ( ) , native_obj. version ( ) ) , Some ( native_obj) ) ;
200207 }
201208 }
202209 }
203210
204211 // Add tombstones for objects that no longer exist from effects
205212 if let Some ( effects) = & executed_transaction. effects {
213+ // Get lamport version directly from gRPC effects
214+ let lamport_version = SequenceNumber :: from_u64 (
215+ effects
216+ . lamport_version
217+ . context ( "Effects should have lamport_version" ) ?,
218+ ) ;
219+
206220 for changed_obj in & effects. changed_objects {
207221 if changed_obj. output_state ( ) == OutputObjectState :: DoesNotExist {
208222 let object_id = changed_obj
209223 . object_id
210224 . as_ref ( )
211- . and_then ( |id_str| id_str . parse :: < ObjectID > ( ) . ok ( ) )
212- . expect ( "Changed object should have valid object_id") ;
225+ . and_then ( |id| id . parse ( ) . ok ( ) )
226+ . context ( "ChangedObject should have valid object_id") ? ;
213227
214- // Use MAX as sentinel version for tombstones (e.g. deleted objects don't have output_version)
215- // This ensures execution_output_object_latest returns None for such objects
216- map. insert ( ( object_id, SequenceNumber :: MAX ) , None ) ;
228+ // Deleted/wrapped objects don't have an output_version, so we use the transaction's
229+ // lamport version as the tombstone version. This ensures execution_output_object_latest
230+ // returns None for these objects.
231+ map. insert ( ( object_id, lamport_version) , None ) ;
217232 }
218233 }
219234 }
220235
221- Arc :: new ( map)
236+ Ok ( Arc :: new ( map) )
222237}
223238
224239impl Debug for Scope {
0 commit comments