Commit 0e05b59e authored by Jeremy Bokobza's avatar Jeremy Bokobza

better handling of the state machine object

parent b200b823
...@@ -8,10 +8,10 @@ ...@@ -8,10 +8,10 @@
void Save(); void Save();
/// <summary> /// <summary>
/// Loads the state of the current tumbling session. /// Loads the saved state of the tumbling execution to the file system.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
IStateMachine Load(); void LoadStateFromMemory();
/// <summary> /// <summary>
/// Deletes the state of the current tumbling session.. /// Deletes the state of the current tumbling session..
......
...@@ -34,8 +34,7 @@ namespace Breeze.TumbleBit.Client ...@@ -34,8 +34,7 @@ namespace Breeze.TumbleBit.Client
this.network = network; this.network = network;
this.logger = loggerFactory.CreateLogger(this.GetType().FullName); this.logger = loggerFactory.CreateLogger(this.GetType().FullName);
// load the persisted tumbling state this.tumblingState = new TumblingState(loggerFactory);
this.tumblingState = TumblingState.LoadState();
} }
/// <inheritdoc /> /// <inheritdoc />
...@@ -48,13 +47,12 @@ namespace Breeze.TumbleBit.Client ...@@ -48,13 +47,12 @@ namespace Breeze.TumbleBit.Client
{ {
throw new Exception($"The tumbler is on network {this.TumblerParameters.Network} while the wallet is on network {this.network}."); throw new Exception($"The tumbler is on network {this.TumblerParameters.Network} while the wallet is on network {this.network}.");
} }
if (this.tumblingState == null) // load the current tumbling state fromt he file system
{ this.tumblingState.LoadStateFromMemory();
this.tumblingState = new TumblingState();
}
// update and save the state // update and save the state
this.tumblingState.TumblerUri = serverAddress;
this.tumblingState.TumblerParameters = this.TumblerParameters; this.tumblingState.TumblerParameters = this.TumblerParameters;
this.tumblingState.Save(); this.tumblingState.Save();
......
...@@ -15,31 +15,38 @@ namespace Breeze.TumbleBit.Client ...@@ -15,31 +15,38 @@ namespace Breeze.TumbleBit.Client
{ {
public class TumblingState : IStateMachine public class TumblingState : IStateMachine
{ {
private readonly ILogger logger;
private const string StateFileName = "tumblebit_state.json"; private const string StateFileName = "tumblebit_state.json";
[JsonProperty("tumblerParameters")] [JsonProperty("tumblerParameters")]
public ClassicTumblerParameters TumblerParameters { get; set; } public ClassicTumblerParameters TumblerParameters { get; set; }
[JsonProperty("tumblerUri")] [JsonProperty("tumblerUri")]
public Uri TumblerUri { get; set; } public Uri TumblerUri { get; set; }
[JsonProperty("lastBlockReceivedHeight")] [JsonProperty("lastBlockReceivedHeight", DefaultValueHandling = DefaultValueHandling.Ignore)]
public int LastBlockReceivedHeight { get; set; } public int LastBlockReceivedHeight { get; set; }
[JsonProperty("originWalletName")] [JsonProperty("originWalletName", NullValueHandling = NullValueHandling.Ignore)]
public string OriginWalletName { get; set; } public string OriginWalletName { get; set; }
[JsonProperty("destinationWalletName")] [JsonProperty("destinationWalletName", NullValueHandling = NullValueHandling.Ignore)]
public string DestinationWalletName { get; set; } public string DestinationWalletName { get; set; }
[JsonProperty("sessions")] [JsonProperty("sessions", NullValueHandling = NullValueHandling.Ignore)]
public IList<Session> Sessions { get; set; } public IList<Session> Sessions { get; set; }
[JsonConstructor]
public TumblingState() public TumblingState()
{ {
this.Sessions = new List<Session>();
} }
public TumblingState(ILoggerFactory loggerFactory)
{
this.logger = loggerFactory.CreateLogger(this.GetType().FullName);
}
/// <inheritdoc /> /// <inheritdoc />
public void Save() public void Save()
{ {
...@@ -47,9 +54,23 @@ namespace Breeze.TumbleBit.Client ...@@ -47,9 +54,23 @@ namespace Breeze.TumbleBit.Client
} }
/// <inheritdoc /> /// <inheritdoc />
public IStateMachine Load() public void LoadStateFromMemory()
{ {
return LoadState(); var stateFilePath = GetStateFilePath();
if (!File.Exists(stateFilePath))
{
return;
}
// load the file from the local system
var savedState = JsonConvert.DeserializeObject<TumblingState>(File.ReadAllText(stateFilePath));
this.Sessions = savedState.Sessions ?? new List<Session>();
this.OriginWalletName = savedState.OriginWalletName;
this.DestinationWalletName = savedState.DestinationWalletName;
this.LastBlockReceivedHeight = savedState.LastBlockReceivedHeight;
this.TumblerParameters = savedState.TumblerParameters;
this.TumblerUri = savedState.TumblerUri;
} }
/// <inheritdoc /> /// <inheritdoc />
...@@ -64,78 +85,68 @@ namespace Breeze.TumbleBit.Client ...@@ -64,78 +85,68 @@ namespace Breeze.TumbleBit.Client
{ {
// get the next cycle to be started // get the next cycle to be started
var cycle = this.TumblerParameters.CycleGenerator.GetRegistratingCycle(this.LastBlockReceivedHeight); var cycle = this.TumblerParameters.CycleGenerator.GetRegistratingCycle(this.LastBlockReceivedHeight);
var lastCycleStarted = this.Sessions.Max(s => s.StartCycle);
// check if we need to start a new session starting from the registration cycle // create a new session if allowed
// TODO remove the limitation to have only 1 session if (this.Sessions.Count == 0)
if (lastCycleStarted != cycle.Start && this.Sessions.Count == 0) {
{ this.CreateNewSession(cycle.Start);
if (this.Sessions.SingleOrDefault(s => s.StartCycle == cycle.Start) == null)
{
this.CreateNewSession(cycle.Start);
}
} }
else
{
// TODO remove the limitation to have only 1 session
//var lastCycleStarted = this.Sessions.Max(s => s.StartCycle);
//// check if we need to start a new session starting from the registration cycle
//if (lastCycleStarted != cycle.Start)
//{
// if (this.Sessions.SingleOrDefault(s => s.StartCycle == cycle.Start) == null)
// {
// this.CreateNewSession(cycle.Start);
// }
//}
}
// get a list of cycles we expect to have at this height // get a list of cycles we expect to have at this height
var cycles = this.TumblerParameters.CycleGenerator.GetCycles(this.LastBlockReceivedHeight); var cycles = this.TumblerParameters.CycleGenerator.GetCycles(this.LastBlockReceivedHeight);
var existingSessions = cycles.SelectMany(c => this.Sessions.Where(s => s.StartCycle == c.Start)).ToList(); var existingSessions = cycles.SelectMany(c => this.Sessions.Where(s => s.StartCycle == c.Start)).ToList();
foreach (var existingSession in existingSessions) foreach (var existingSession in existingSessions)
{ {
try // create a new session to be updated
var session = new Session();
if (existingSession.NegotiationClientState != null)
{ {
// create a new session to be updated session.StartCycle = existingSession.NegotiationClientState.CycleStart;
var session = new Session(); session.ClientChannelNegotiation = new ClientChannelNegotiation(this.TumblerParameters, existingSession.NegotiationClientState);
if (existingSession.NegotiationClientState != null)
{
session.StartCycle = existingSession.NegotiationClientState.CycleStart;
session.ClientChannelNegotiation = new ClientChannelNegotiation(this.TumblerParameters, existingSession.NegotiationClientState);
}
if (existingSession.PromiseClientState != null)
session.PromiseClientSession = new PromiseClientSession(this.TumblerParameters.CreatePromiseParamaters(), existingSession.PromiseClientState);
if (existingSession.SolverClientState != null)
session.SolverClientSession = new SolverClientSession(this.TumblerParameters.CreateSolverParamaters(), existingSession.SolverClientState);
// update the session
session.Update();
// replace the updated session in the list of existing sessions
int index = this.Sessions.IndexOf(existingSession);
if (index != -1)
{
this.Sessions[index] = session;
}
this.Save();
} }
catch (Exception) if (existingSession.PromiseClientState != null)
session.PromiseClientSession = new PromiseClientSession(this.TumblerParameters.CreatePromiseParamaters(), existingSession.PromiseClientState);
if (existingSession.SolverClientState != null)
session.SolverClientSession = new SolverClientSession(this.TumblerParameters.CreateSolverParamaters(), existingSession.SolverClientState);
// update the session
this.MoveToNextPhase(session);
// replace the updated session in the list of existing sessions
int index = this.Sessions.IndexOf(existingSession);
if (index != -1)
{ {
throw; this.Sessions[index] = session;
} }
this.Save();
} }
} }
public void MoveToNextPhase(Session session)
{
this.logger.LogInformation($"Entering next phase for cycle {session.StartCycle}.");
}
public void CreateNewSession(int start) public void CreateNewSession(int start)
{ {
this.Sessions.Add(new Session { StartCycle = start }); this.Sessions.Add(new Session { StartCycle = start });
this.Save(); this.Save();
} }
/// <summary>
/// Loads the saved state of the tumbling execution to the file system.
/// </summary>
/// <returns></returns>
public static TumblingState LoadState()
{
var stateFilePath = GetStateFilePath();
if (!File.Exists(stateFilePath))
{
return null;
}
// load the file from the local system
return JsonConvert.DeserializeObject<TumblingState>(File.ReadAllText(stateFilePath));
}
/// <summary> /// <summary>
/// Gets the file path of the file containing the state of the tumbling execution. /// Gets the file path of the file containing the state of the tumbling execution.
...@@ -179,10 +190,5 @@ namespace Breeze.TumbleBit.Client ...@@ -179,10 +190,5 @@ namespace Breeze.TumbleBit.Client
[JsonIgnore] [JsonIgnore]
public PromiseClientSession PromiseClientSession { get; set; } public PromiseClientSession PromiseClientSession { get; set; }
public void Update()
{
}
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment