JuliaGizmos / Escher.jl

Composable Web UIs in Julia
https://juliagizmos.github.io/Escher.jl
Other
335 stars 63 forks source link

Random number generation in Escher #109

Open getzdan opened 8 years ago

getzdan commented 8 years ago

Signals between the browser and Julia in Escher use nonce values which are randomly generated (i.e. 239286640159958284960877608660596719563) using string(rand(UInt128)). The rand function uses the global scope Julia RNG state which means if a different part of the system plays with srand(...) it could generate repeating nonce-s which would mess things up.

This is not a theoretical issue, as it was discovered in a real program which failed mysteriously. A small example could be:

using Escher

function main(window)
 push!(window.assets, "widgets")

 srand(1)
 button1signal = Input(Escher.LeftButton())
 button2signal = Input(Escher.LeftButton())
 button1count = foldl((c,x)->c+1,0,button1signal)
 button2count = foldl((c,x)->c+1,0,button2signal)
 button3signal = Input(Escher.LeftButton())

 vbox(
  title(2, "randbug") |> Escher.pad(1em),
  vskip(2em),
  lift(c->button("Button 1") >>> button1signal, button1count),
  lift(c->button("Button 2") >>> button2signal, button2count),
  lift(x->(x>0 ? (srand(1); for i=1:6 rand(UInt128); end; button("Button 1 does not work")>>>button3signal) : button("Button 1 works")>>>button3signal),button2count),
  lift(x->(button3signal = Input(Escher.LeftButton()); string(x)),button2count),
  lift((b1,b2)->"Button1: $(b1) Button2: $(b2)", button1count, button2count)
 )
end

In the example, button 1 fails to operate after a couple of clicks on button 2 because a nonce generated for the third button interferes with it.

Not sure what is the right way to approach this. An internal RNG state for Escher seems needed. But to initialize it, I can see 3 alternatives, which could co-exist and be specified using parameters:

  1. Initialize internal RNG with a combination of external RNG and time.
  2. Initialize internal RNG with specified seed.
  3. Initialize internal RNG with external RNG once and let it run internally.

Additionally, it might be possible to allow playing with RNG state using sanctioned methods instead of Julia allowed internal tinkering.

shashi commented 8 years ago

good catch!

I believe maintaining an RNG state is similar to maintaining any kind of state. I think a global counter would be better here than random numbers to give ids to the signals.

getzdan commented 8 years ago

yeah, a counter would do the trick (non-repeating nonces). the only considerations I could come up with about it are:

but these are mainly non-issues.