Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Free list is not the same before/after serialization #104

Open
Uriopass opened this issue Jul 26, 2023 · 10 comments
Open

Free list is not the same before/after serialization #104

Uriopass opened this issue Jul 26, 2023 · 10 comments
Labels

Comments

@Uriopass
Copy link
Contributor

I'm not sure if this is intended (it probably is). But the freelist is not necessarily the same after a serialization cycle.

This means that doing operations_1 -> ser -> deser -> operations_2 does not result in the same keys as
operations_1 -> operations_2

This is a bit troublesome as I wish my program was deterministic even through serialization cycles as it is necessary for lockstep networking.

If this is intended, I can fork and serialize the freelist, or maybe this crate can provide another serde implementation using serde(with = "..")).
If this is not intended, I can try to make an example to reproduce.

@orlp
Copy link
Owner

orlp commented Jul 26, 2023

It's neither intended nor unintended, I hadn't considered your usecase yet. I might consider serializing the freelist structure as well for slotmap 2.0, but I'll have to have a good think about what that means for serialization size, backwards compatibility and the performance checks needed to verify a freelist is correct after deserialization.

I assume the problem comes up with iteration order? Could you give some more context.

@Uriopass
Copy link
Contributor Author

The problem comes up with iteration order and key values yes.

For more context, I am implementing a replay system for my game. Therefore I want to make sure that applying actions successively will always end up with the same state even if it was serialized in the middle.

Take a random player:
plays game -> saves -> loads the next day -> continue playing

The actions the player can take have slotmap ids associated with them, for example "Built road between this IntersectionID and this IntersectionID"

Now imagine the player wants to watch his replay, he starts from an empty world and replays his action. But since he doesn't save/load during those actions, the state is not the same anymore and the keys in the replay are wrong!
That's the issue I'm trying to fix.

@Uriopass
Copy link
Contributor Author

but I'll have to have a good think about what that means for serialization size, backwards compatibility and the performance checks needed to verify a freelist is correct after deserialization.

Note that you can have multiple serializers for the same object. You can provide a separate module to be used with serde(with)

@orlp
Copy link
Owner

orlp commented Jul 26, 2023

I'm leaning towards serializing freelist state in slotmap 2.0, but that will be some time away. I'm not particularly tempted to duplicate all of the serialization code (and tests) to provide an alternate serializer.

I'm afraid that for now your best option is forking until I get around to this.

@Uriopass
Copy link
Contributor Author

Thank you for your quick responses.

@Uriopass
Copy link
Contributor Author

Uriopass commented Aug 3, 2023

For your information, I have published the fork on crates.io. You can see the changes I made in this commit if you're interested.

@orlp
Copy link
Owner

orlp commented Aug 3, 2023

For your information, I have published the fork on crates.io. You can see the changes I made in this commit if you're interested.

I'm afraid this is not sound. Someone could send you a serialized freelist that accesses out-of-bounds memory. You have to check that the freelist is all in-bounds, unique and actually linked.

@Uriopass
Copy link
Contributor Author

Uriopass commented Aug 3, 2023

You're right, I didn't think about this kind of protection. I'll fix it and yank the old ones.

@Uriopass
Copy link
Contributor Author

Uriopass commented Aug 6, 2023

I implemented deserialization validation if you want to take a look: Uriopass@90ffc61

I might have missed an invariant. The HopSlotMap was definitely the hardest to understand. Thankfully quickcheck was a lifesaver.

@orlp orlp added the accepted label Oct 31, 2023
@Fuuzetsu
Copy link

Fuuzetsu commented Nov 7, 2023

I'd just like to add our 2 cents: we have a very similar problem.

We have some deterministic software that goes forward in time and takes regular snapshots, serialising its state as it goes along. Sometimes we want to go back to a snapshot to have a another look at something. Once we do this, going forward again from the snapshot causes a divergence in state: we get different keys when resuming from snapshot and when just going forward.

I'll have a look at the fork mentioned here but we're looking forward to this working out of the box.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants