Hair has been pulled, nails have been bitten, and tears have been shed – but the next CypherPoker update is now live!
You can find the latest, albeit still somewhat fragile, version at the GitHub repository.
With the following new features CypherPoker takes a big step toward full v2.0 functionality:
The desktop version of CypherPoker is now able to launch child windows in which to play games. Up until this update the only way to play multiple games on the same machine was to launch the same application more than once and because of the limitations of the AIR runtime this was only possible with the web version.
I usually avoid going into such depth but perhaps my adventures may be of help to other developers so for the rest of this section I’m going to nerd out. If the technical details don’t interest you then I suggest you skip to the Ethereum part.
As it turns out, multi-instance execution was surprisingly tricky to implement because loading up a second instance of the game in a new window of the same application caused communication with workers to stop, even when running within its own segregated application domain . In effect, this meant that the new window had no access to a multi-threaded cryptosystem.
To understand why this is a bad thing, it’s important to note that ActionScript content runs on a single thread by default which means that without workers/multi-threading, anytime something needs to be encrypted or decrypted the entire window effectively freezes because it’s busy working on the crypto task(s).
With this limitation, not only is the game not able to handle multiple concurrent operations (they have to happen one after the other), but at an average of 50 to 100 milliseconds per operation, 52 cards will take between 2.5 to 5 seconds in total to encrypt during which the entire window is frozen. It can’t even display an animation to indicate that something is happening in the background.
There are ways to split up such operations into discrete chunks that can run on timers but it makes them significantly slower and with the only advantage that we can provide some sort of indication to the player that something is happening in the background. Would you want to wait 50 to 60 seconds for just one player to encrypt the deck?
Yeah. Not great.
Unfortunately, CypherPoker is already pushing the limits of the runtime so it wasn’t surprising that I found no mention of the particular problem I was experiencing. I still don’t really know why workers are limited in this way. Is it a bug in the runtime? Is it by design?
On top of this I discovered that the new (child) game window wasn’t able to make direct use of the launching (parent) window’s workers because of the segregated application domain thing. Even though the code running in both windows is identical, the runtime considers them incompatible and lets me know by halting execution and throwing up an error dialog whenever a direct interaction between the two is attempted.
Thankfully my exposure to ActionScript suggested using LocalConnection communications which, as the name suggests, provides a type of seamless, local, loop-back “bridge” between pieces of code. This connection can be used between portions of an individual application or between entirely distinct runtimes such as the web and desktop versions.
The result is that every child window now shares the cryptosystem of the parent window. This has the added benefit of enforcing the limits on concurrency, or the maximum number of workers/threads that the game can launch at any given time.
With this out of the way I encountered another problem: a noticeable stall whenever a crypto operation was taking place. This had the effect of freezing the game window for about half a second whenever an encryption or decryption was happening. It was not dissimilar to the single-threaded problem I described above, and with 52 cards waiting to be encrypted at the start you can probably imagine what this did to the game.
Yeah. Not great.
After much wailing and gnashing of teeth I was able to isolate the problem to what initially seemed like the JSON parser which is used to prepare data for transit to/from the workers. The data itself is tiny and the parser is native to the runtime so I was very surprised to see that it was taking up to half a second for processing.
With some further digging, however, I discovered that it was actually the retrieval and storage of the encryption/decryption keys in the SRAKey class that was the problem. More specifically, it was the use of the Encrypted Local Store system within each key instance that was causing the hiccups.
Earlier in the CypherPoker project I’d decided to use ELS to store encryption and decryption keys so that they’re not sitting around in main memory where there’s a chance that some spyware may be able to access them. At the time that I’d implemented this functionality everything was running smoothly.
Unfortunately and for reasons unbeknownst to me, the AIR runtime now requires a relatively large amount of time to access ELS and so the only viable solution for the time being is to disable it. ELS is still available as an option but until the half-second access time is addressed I wouldn’t recommend enabling it.
This doesn’t mean that the encryption/decryption keys are openly accessible to hackers – they would still need to install malware on your machine and be able to access the application’s protected memory – but ELS would provide a little bit more security, which is never a bad thing (unless, as in this case, it is).
Ethereum Client Integration
A rudimentary integration is already a part of the v1.29b branch so some of this functionality already existed but with this update CypherPoker got a whole lot chummier with Ethereum.
The first new feature allows CypherPoker to automatically download, install, and execute the Ethereum client as a background process. This is currently only available in the Windows standalone version but has been designed to support any version of CypherPoker that has the capability to execute native processes.
When it starts up, CypherPoker now checks to see if the Ethereum client (Geth) has been installed. If it has it’s launched with configurable host and port settings, customizable data directory to prevent collisions with any non-CypherPoker installations, a customizable network ID to enable dev/test/full network access, an optional custom genesis block to start a private blockchain, and with the full RPC interface enabled (also optional).
If the Ethereum client hasn’t been installed it’s downloaded from the official GitHub repository or any other URL that may be specified by the user or provided through configuration data. Once downloaded the client is unzipped and installed to CypherPoker’s application storage directory from which it’s launched.
Although it’s possible to launch multiple instances of the Ethereum client this is usually unnecessary and can be detrimental to performance. Instead, a communication channel (LocalConnection), is established by the parent CypherPoker instance in order to share information about the running Ethereum client with any other instances of CypherPoker.
Currently this console may be accessed by right-clicking on the game area and selecting “ETHEREUM >> Toggle console“.
…which will return an array of registered account addresses. To get the list of registered accounts in ActionsScript the command would be:
…which will return an array of registered account addresses.
In both cases the invocations are synchronous and pretty much anything that can be accomplished via the web3.js interface can be done identically in ActionScript.
Now that CypherPoker is capable of launching multiple instances of itself and the Ethereum client the next step will be to update and optimize the existing smart contracts for more robust game control and validation, and to support the updated multi-round cryptosystem which is already partially complete.
Depending on how this goes it may be worth exploring sidechaining and incorporating some of the research I’ve been doing on non-interactive zero-knowledge proofs that apply to the CypherPoker cryptosystem.
It’s worth noting that unlike in the infamous DAO hack, CypherPoker is not hardcoded to use or reference any single contract or set of contracts in perpetuity. That’s not to say that the whole suite of contracts are published with each new game or hand, but CypherPoker accesses them dynamically so that they can be.
Unless there are reasons to preserve game histories, contracts are automatically removed from the blockchain when completed along with any problematic code. In this way the effects of contract coding errors are be greatly limited, fixes/updates are be available holistically with each new hand or game, and players needn’t depend on any single source for updated contract code (they can use their own if they want).
With the completion of the smart contracts I’ll be looking at integrating cryptocurrencies other than Ether. At present, the path of least resistance appears to be through services such as ShapeShift which provide APIs for integration. This will allow CypherPoker to use almost any cryptocurrency immediately, albeit with transaction costs. BTCRelay also sounds like a great candidate for integrating Bitcoin into CypherPoker so this is something I’ll be exploring.
Finally, the CypherPoker user interface desperately needs a facelift so this, along with fixes and optimizations, will be the final steps on the road to version 2.0
Early to mid-October is still looking viable so long as I don’t have to wrestle with too many more unexpected surprises. Either way, be sure to check back here as I’m sure I’ll have more updates to share soon!