@@ -937,6 +937,52 @@ pub fn processSlots(self: *const BeaconStateView, slot_arg: js.Number, options:
937937 return .{ .cached_state = post_state };
938938}
939939
940+ /// Load another state by reusing this state's validators / inactivity_scores subtrees
941+ /// where the byte ranges are unchanged. Mirrors TS `loadState` for ~500ms-per-reload speedup.
942+ pub fn loadOtherState (
943+ self : * const BeaconStateView ,
944+ state_bytes : js.Uint8Array ,
945+ seed_validators_bytes : ? js.Uint8Array ,
946+ _ : ? js.Value ,
947+ ) ! BeaconStateView {
948+ const cached_state = try self .requireState ();
949+ const state_bytes_slice = try state_bytes .toSlice ();
950+ const seed_validators_bytes_slice : ? []const u8 =
951+ if (seed_validators_bytes ) | b | try b .toSlice () else null ;
952+
953+ var result = try st .loadState (
954+ allocator ,
955+ & pool .state .pool ,
956+ cached_state .config ,
957+ cached_state .state ,
958+ state_bytes_slice ,
959+ seed_validators_bytes_slice ,
960+ );
961+
962+ result .modified_validators .deinit (allocator );
963+ errdefer {
964+ result .state .deinit ();
965+ allocator .destroy (result .state );
966+ }
967+
968+ const new_cached_state = try allocator .create (CachedBeaconState );
969+ errdefer allocator .destroy (new_cached_state );
970+
971+ try new_cached_state .init (
972+ allocator ,
973+ result .state ,
974+ .{
975+ .config = cached_state .config ,
976+ .index_to_pubkey = cached_state .epoch_cache .index_to_pubkey ,
977+ .pubkey_to_index = cached_state .epoch_cache .pubkey_to_index ,
978+ },
979+ // as of Feb 2026, it's not necessary to sync pubkey cache as it's shared across states in Lodestar
980+ .{ .skip_sync_pubkeys = true },
981+ );
982+
983+ return .{ .cached_state = new_cached_state };
984+ }
985+
940986fn requireState (self : * const BeaconStateView ) ! * CachedBeaconState {
941987 return self .cached_state orelse error .InvalidState ;
942988}
0 commit comments