123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2022 Nomadic Labs <contact@nomadic-labs.com> *)(* *)(* Permission is hereby granted, free of charge, to any person obtaining a *)(* copy of this software and associated documentation files (the "Software"),*)(* to deal in the Software without restriction, including without limitation *)(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)(* and/or sell copies of the Software, and to permit persons to whom the *)(* Software is furnished to do so, subject to the following conditions: *)(* *)(* The above copyright notice and this permission notice shall be included *)(* in all copies or substantial portions of the Software. *)(* *)(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)(* DEALINGS IN THE SOFTWARE. *)(* *)(*****************************************************************************)moduleParameters=structtypepersistent_state={protocol:Protocol.t;runner:Runner.toption;node:Node.t;mutablepending_ready:unitoptionLwt.ulist;}typesession_state={mutableready:bool}letbase_default_name="vdf"letdefault_colors=Log.Color.[|BG.magenta++FG.black;BG.magenta++FG.gray;BG.magenta++FG.bright_white;|]endopenParametersincludeDaemon.Make(Parameters)letnode_rpc_portaccuser=Node.rpc_portaccuser.persistent_state.nodelettrigger_readyvdf_bakervalue=letpending=vdf_baker.persistent_state.pending_readyinvdf_baker.persistent_state.pending_ready<-[];List.iter(funpending->Lwt.wakeup_laterpendingvalue)pendingletset_readyvdf_baker=(matchvdf_baker.statuswith|Not_running->()|Runningstatus->status.session_state.ready<-true);trigger_readyvdf_baker(Some())lethandle_raw_stdoutvdf_bakerline=ifline=~rex"^VDF daemon v.+ for .+ started.$"thenset_readyvdf_bakerletcreate~protocol?name?color?event_pipe?runnernode=letname=matchnamewithNone->fresh_name()|Somename->nameinletvdf_baker=create~path:(Protocol.bakerprotocol)?name:(Somename)?color?event_pipe?runner{protocol;runner;node;pending_ready=[]}inon_stdoutvdf_baker(handle_raw_stdoutvdf_baker);vdf_bakerletrun(vdf_baker:t)=(matchvdf_baker.statuswith|Not_running->()|Running_->Test.fail"VDF daemon %s is already running"vdf_baker.name);letrunner=vdf_baker.persistent_state.runnerinletnode_runner=Node.runnervdf_baker.persistent_state.nodeinletnode_rpc_port=node_rpc_portvdf_bakerinletaddress="http://"^Runner.address?from:runnernode_runner^":"inletarguments=["-E";address^string_of_intnode_rpc_port;"run";"vdf"]inleton_terminate_=(* Cancel all [Ready] event listeners. *)trigger_readyvdf_bakerNone;unitinrunvdf_baker{ready=false}arguments~on_terminate?runnerletcheck_event?wherevdf_bakernamepromise=let*result=promiseinmatchresultwith|None->raise(Terminated_before_event{daemon=vdf_baker.name;event=name;where})|Somex->returnxletwait_for_readyvdf_baker=matchvdf_baker.statuswith|Running{session_state={ready=true;_};_}->unit|Not_running|Running{session_state={ready=false;_};_}->letpromise,resolver=Lwt.task()invdf_baker.persistent_state.pending_ready<-resolver::vdf_baker.persistent_state.pending_ready;check_eventvdf_baker"VDF daemon started."promiseletinit~protocol?name?color?event_pipe?runnernode=let*()=Node.wait_for_readynodeinletvdf_baker=create~protocol?name?color?event_pipe?runnernodeinlet*()=runvdf_bakerinlet*()=wait_for_readyvdf_bakerinreturnvdf_bakerletrestartvdf_baker=let*()=terminatevdf_bakerinlet*()=runvdf_bakerinwait_for_readyvdf_bakermoduleHelpers=structletis_in_nonce_revelation_stage~nonce_revelation_threshold~(level:RPC.level)=letcycle_position=Int32.of_intlevel.cycle_positioninInt32.comparecycle_positionnonce_revelation_threshold<0end