I implement a little guessing game; two players pick secret value’s and then take turns guessing the other’s secret. My implementation is here. I used an operator/
referee who has knowledge of both secrets to advance play.
- Is there a way to avoid having a
referee? I don’t think so (within the standard library provided features of the language), but I’m not sure.
- How idiomatic DAML is the code? Are there better patterns that I can use?
- There’s a scenario that demonstrates play, but unfortunately, the current implementation does not allow Alice to play against herself! That source of the error comes from a key uniqueness constraint, as the
referee has to read the current state of play, archive it and create a new one within the same
choice. I can work around this by passing a flipping
Bool in the key logic but that’s ugly. Is there a better way?
Any other feedback would be great!
Regarding 1.) I haven’t tested any of this, but I think you can get rid of the
referee role if you create one template containing the secret that only player A observes, one template announcing the new challenge to the other player containing a contract id of the secret contract. Then player B can create a template with its guess that both player A and B can see and that does contain a reference via a contract id to the secret, with a choice for player A to decide whether B guessed right or wrong. On a side note, this is an interesting example of how DAML divulges contract ids.
This would allow for asynchronous challenges/guesses, but you could order the players moves similar to what you did by having a template to create a new game with an identifier and only if you created the template you can create a new secret/challenge, or if you guessed for a challenge for a game.
To prevent A from cheating one would add
assert's into the choice’s body?
Following up on @drsk’s suggestion I did implement an “operator”-less version of the game! It feels good to refine and find this boundary of DAML. To continue to probe, would it still be possible if the objective of the game was to guess something deterministic about both secrets, for example the GCD of the two secret numbers?
This guessing example, was an attempt at a reduction that lost that element. Specifically, I’m working on a Fog-of-war chess variation and in order to advance play I need to know both sides of the board. This is revealed to the
referee. The problem described in question 3, is real, and aside from the flipping
bool, I haven’t figured out a way to avoid the key conflict. In the operator-less version of the guessing game, there’s still a unique key constraint akin to 3. One can get around it via an extra intermediate contract, but that’s also inelegant; and also superfluous to logic of the game. I wonder if there is a different mechanism in the language that one can leverage when one wants to test that contracts that one signs with oneself have the same behavior as when you sign them with someone else. Is the resolution to just create a second
Party to represent your “other” self?
The code checking whether a guess is correct or not would be in DAML itself, so there’s no way someone could cheat. Also both parties will see the evaluation of that code. So you would add a
Winner template, that can only be created via a choice when the code determined that someone guessed right.
Running computations on secret input data without revealing it to the party carrying out the computation is generally a really hard problem (and also really interesting, check out zero knowledge proofs, and mpc). So in that case, I think the referee solution is best.
Excellent thread but moving to #general as this is discussing an entire project rather than a specific question so it fits better over there.
Another option for (1) which isn’t native DAML but more tied to implementation is using bots which run in TEEs, so you’re running with a “trusted” referee bot where the trust anchor is the trusted execution environment. You can see this as a hardware alternative to using ZKPs.
@soren is working on enabling a similar use case
You may be interested in googling the word “mental poker”; per Wikipedia:
Mental poker is the common name for a set of cryptographic problems that concerns playing a fair game over distance without the need for a trusted third party.
The referee could be a trigger host running on a machine that has no other connectivity than the ledger, but both players still need to trust whoever runs that machine.
Thanks for all the pointers. I do want to constrain myself to what’s possible within current DAML, so we’ll use an
operator when we have to act on two private states.
Is there any feedback on the other points? In point 3, I want to be able to write within an
Update that I will archive and create a template with the same key.