Commit a12d5f8d authored by Jeremy Bokobza's avatar Jeremy Bokobza Committed by GitHub

Merge pull request #94 from bokobza/master

Creating TumbleBit sessions
parents be0beb4f bb1db893
......@@ -17,5 +17,10 @@
/// Deletes the state of the current tumbling session..
/// </summary>
void Delete();
/// <summary>
/// Updates this the state of the current tumbling session.
/// </summary>
void Update();
}
}
......@@ -21,7 +21,7 @@ namespace Breeze.TumbleBit.Client
/// <returns></returns>
Task<ClassicTumblerParameters> GetClassicTumblerParametersAsync();
Task<UnsignedVoucherInformation> AskUnsignedVoucher();
Task<UnsignedVoucherInformation> AskUnsignedVoucherAsync();
Task<PuzzleSolution> SignVoucherAsync(SignVoucherRequest signVoucherRequest);
......
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using NBitcoin;
......@@ -22,11 +23,13 @@ namespace Breeze.TumbleBit.Client
private readonly Network network;
private TumblingState tumblingState;
private IDisposable blockReceiver;
int lastCycleStarted;
private ClassicTumblerParameters TumblerParameters { get; set; }
public TumbleBitManager(ILoggerFactory loggerFactory, IWalletManager walletManager, ConcurrentChain chain, Network network, Signals signals)
{
this.lastCycleStarted = 0;
this.walletManager = walletManager;
this.chain = chain;
this.signals = signals;
......@@ -52,7 +55,7 @@ namespace Breeze.TumbleBit.Client
{
this.tumblingState = new TumblingState();
}
// update and save the state
this.tumblingState.TumblerParameters = this.TumblerParameters;
this.tumblingState.Save();
......@@ -115,12 +118,27 @@ namespace Breeze.TumbleBit.Client
this.logger.LogDebug($"Receive block with height {height}");
// update the block height in the tumbling state
if (this.tumblingState.LastBlockReceivedHeight == 0)
{
this.tumblingState.StartHeight = height;
}
this.tumblingState.LastBlockReceivedHeight = height;
this.tumblingState.Save();
// get the next cycle to be started
var cycle = this.TumblerParameters.CycleGenerator.GetRegistratingCycle(height);
// check if we need to start a new session starting from the registration cycle
if (this.lastCycleStarted != cycle.Start)
{
this.lastCycleStarted = cycle.Start;
this.logger.LogDebug($"new registration cycle at {cycle.Start}");
if (this.tumblingState.Sessions.SingleOrDefault(s => s.StartCycle == cycle.Start) == null)
{
this.tumblingState.CreateNewSession(cycle.Start);
this.logger.LogDebug($"new session created at {cycle.Start}");
}
}
// update the state of the tumbling session in this new block
this.tumblingState.Update();
}
}
}
......@@ -42,7 +42,7 @@ namespace Breeze.TumbleBit.Client
}
/// <inheritdoc />
public async Task<UnsignedVoucherInformation> AskUnsignedVoucher()
public async Task<UnsignedVoucherInformation> AskUnsignedVoucherAsync()
{
UnsignedVoucherInformation result = await this.serverAddress.AppendPathSegment("api/v1/tumblers/0/vouchers/").GetJsonAsync<UnsignedVoucherInformation>();
return result;
......
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using NTumbleBit.ClassicTumbler;
using NTumbleBit.PuzzlePromise;
using NTumbleBit.PuzzleSolver;
namespace Breeze.TumbleBit.Client
{
public class TumblingState : IStateMachine
{
private const string StateFileName = "tumblebit_state.json";
[JsonProperty("tumblerParameters")]
public ClassicTumblerParameters TumblerParameters { get; set; }
[JsonProperty("tumblerUri")]
public Uri TumblerUri { get; set; }
[JsonProperty("startHeight")]
public int StartHeight { get; set; }
[JsonProperty("lastBlockReceivedHeight")]
public int LastBlockReceivedHeight { get; set; }
[JsonProperty("destinationWalletName")]
public string DestinationWalletName { get; set; }
public IList<Session> Sessions { get; set; }
public TumblingState()
{
this.Sessions = new List<Session>();
}
/// <inheritdoc />
public void Save()
{
......@@ -44,6 +53,55 @@ namespace Breeze.TumbleBit.Client
File.Delete(stateFilePath);
}
/// <inheritdoc />
public void Update()
{
// get a list of cycles we expect to have at this height
var cycles = this.TumblerParameters.CycleGenerator.GetCycles(this.LastBlockReceivedHeight);
var states = cycles.SelectMany(c => this.Sessions.Where(s => s.StartCycle == c.Start)).ToList();
foreach (var state in states)
{
try
{
// create a new session to be updated
var session = new Session();
if (state.NegotiationClientState != null)
{
session.StartCycle = state.NegotiationClientState.CycleStart;
session.ClientChannelNegotiation = new ClientChannelNegotiation(this.TumblerParameters, state.NegotiationClientState);
}
if (state.PromiseClientState != null)
session.PromiseClientSession = new PromiseClientSession(this.TumblerParameters.CreatePromiseParamaters(), state.PromiseClientState);
if (state.SolverClientState != null)
session.SolverClientSession = new SolverClientSession(this.TumblerParameters.CreateSolverParamaters(), state.SolverClientState);
// update the session
session.Update();
// replace the updated session in the list of existing sessions
int index = this.Sessions.IndexOf(state);
if (index != -1)
{
this.Sessions[index] = session;
}
this.Save();
}
catch (Exception)
{
throw;
}
}
}
public void CreateNewSession(int start)
{
this.Sessions.Add(new Session { StartCycle = start });
this.Save();
}
/// <summary>
/// Loads the saved state of the tumbling execution to the file system.
/// </summary>
......@@ -55,7 +113,7 @@ namespace Breeze.TumbleBit.Client
{
return null;
}
// load the file from the local system
return JsonConvert.DeserializeObject<TumblingState>(File.ReadAllText(stateFilePath));
}
......@@ -81,4 +139,28 @@ namespace Breeze.TumbleBit.Client
return Path.Combine(defaultFolderPath, StateFileName);
}
}
public class Session
{
public int StartCycle { get; set; }
public ClientChannelNegotiation.State NegotiationClientState { get; set; }
public PromiseClientSession.State PromiseClientState { get; set; }
public SolverClientSession.State SolverClientState { get; set; }
public ClientChannelNegotiation ClientChannelNegotiation { get; set; }
public SolverClientSession SolverClientSession { 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