Meditation on ephemeral resources

A discussion about ephemeral resources arose yesterday, and my thoughts on that seemed too much for a slack discussion, so posting it here. They are not very well organised for a post tho.

The questions I am addressing:

  • what ephemeral resources are
  • the role of ephemeral resources
  • what can and cannot be simplified for them when it is known that the resource is ephemeral (e.g., transparent execution)

I feel like this part is not described at all in the specs (which I will address), but the only difference between ephemeral and non-ephemeral resources is that when consuming ephemeral resources, we don’t need to check the merkle path. It implies some of the things can be simplified for such resources in the transparent case, but none of these simplifications can be publicly (when I say public I mean the shared public environment that is RM-instantiation-agnostic) visible (e.g., we can’t avoid computing nullifiers for such resources).

If we don’t check the merkle path, it means we can consume a resource that has not been created, which is how we want it to be for ephemeral resources. That means, on the one hand, that by not adding an ephemeral resource nullifier to the nullifier set in the transparent case we don’t lose much (double spend for a resource that never was created isn’t such a big deal, I feel like), but on the other hand it sounds somewhat troubling even in the transparent case that we can consume the same ephemeral resource again and again, which is strictly speaking against the rules.

Note that there is a difference between not computing a nullifier and not storing a nullifier - computing a nullifier is a part of the RM interface and cannot be avoided, storing a nullifier is outside of scope of the RM. So, roughly speaking, if storage receives a nullifier to store and can determine that it nullifies an ephemeral resource and decides to throw it away, it could be fine, if we don’t expect to verify the “proper” consumption of a resource. We only need “proper” verification in case we want to tie this resource to some new resource (e.g., to prevent double spend), which afaik will never be the case for ephemeral resources - they are in a sense not contributing to the history but exist to enforce some constraints on transaction validity at the execution time. That makes me wonder, can we exploit this transparent-ephemeral-resource-double-spend mechanics as a transparent-only application optimisation (e.g., consuming the same resource when enforcing the same constraints)? I can’t see how it breaks anything. Am I missing something?

For the privacy-preserving RM, I’m not sure we can simplify anything (beyond the merkle check) with recursion because the difference between the amount of resources in a transaction and the amount of resources added to the nullifier set reveals the number of ephemeral resources. At the same time, we can’t completely remove ephemeral data (commitments, nullifiers) from the public (not encrypted) part of the transaction because that is what allows us to enforce constraints

2 Likes

Thanks for the writeup. A few notes from my end:

I think that strictly speaking (for correct RM behavior):

  1. We need to add ephemeral resource nullifiers to a nullifier set that is local to the transaction in question (they cannot be consumed multiple times in the same transaction - that would be incorrect behavior).
  2. We don’t need to add ephemeral resource nullifiers to the regular nullifier set (which persists beyond the lifetime of a single transaction), because it doesn’t matter if an identical ephemeral resource is created and consumed in some later transaction (since it could always have been created in a way which didn’t result in a conflicting nullifier).

If we in fact add ephemeral resource nullifiers to the regular nullifier set, this meets the security requirements (but it is not strictly necessary).

This is true (there is a slight privacy leak), but it is very minor one, and dummy ephemeral resources could always be added to any transaction, meaning that an adversary learns very little, in expectation. If this is a big performance optimization it might be worth at least making possible at some point.

1 Like

Yes, I think, this is covered by some constraint check for a valid transaction, at least by the fact that we have sets and we iterate over them (so can’t have the same nullifier twice)

Dummy resources are also ephemeral, so we basically reveal the number of non-ephemeral resources by doing this. It is hard for me to argue how little this “very little” is, so I only point to the fact that there is privacy leak without making any conclusions

2 Likes