Skip to content

Commit

Permalink
Merge pull request #23 from drmathias/feature/ticket-secret
Browse files Browse the repository at this point in the history
Ticket transaction logging and ticket secrets
  • Loading branch information
drmathias authored Jan 20, 2020
2 parents 668dbde + b05ec5a commit 50adb5d
Show file tree
Hide file tree
Showing 48 changed files with 1,570 additions and 935 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ Ticketbooth can be integrated with payment gateways, ticket sales platforms and

### Ticketbooth.Contract

[![Build Status](https://dev.azure.com/developmomentum/Ticketbooth/_apis/build/status/Contract?branchName=master)](https://dev.azure.com/developmomentum/Ticketbooth/_build/latest?definitionId=8&branchName=master)
[![Build Status](https://dev.azure.com/developmomentum/Ticketbooth/_apis/build/status/Contract?branchName=master)](https://dev.azure.com/developmomentum/Ticketbooth/_build/latest?definitionId=8&branchName=master)
[![Nuget](https://img.shields.io/nuget/v/Ticketbooth)](https://www.nuget.org/packages/Ticketbooth/)

This project contains the smart contract(s) that Ticketbooth is based on.

Expand Down
130 changes: 29 additions & 101 deletions src/Ticketbooth.Contract/TicketContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,33 +190,25 @@ public bool CheckAvailability(byte[] seatIdentifierBytes)
/// Reserves a ticket for the callers address
/// </summary>
/// <param name="seatIdentifierBytes">The serialized seat identifier</param>
/// <param name="secret">The encrypted secret holding ticket ownership</param>
/// <returns>Whether the seat was successfully reserved</returns>
public bool Reserve(byte[] seatIdentifierBytes)
public void Reserve(byte[] seatIdentifierBytes, byte[] secret)
{
return Reserve(seatIdentifierBytes, string.Empty);
Reserve(seatIdentifierBytes, secret, null);
}

/// <summary>
/// Reserves a ticket for the callers address and with an identifier for the customer
/// </summary>
/// <param name="seatIdentifierBytes">The serialized seat identifier</param>
/// <param name="customerIdentifier">A verifiable identifier for the customer</param>
/// <param name="secret">The encrypted secret holding ticket ownership</param>
/// <param name="customerIdentifier">An encrypted verifiable identifier for the customer</param>
/// <returns>Whether the seat was successfully reserved</returns>
public bool Reserve(byte[] seatIdentifierBytes, string customerIdentifier)
public void Reserve(byte[] seatIdentifierBytes, byte[] secret, byte[] customerIdentifier)
{
// no identity
if (RequireIdentityVerification && string.IsNullOrWhiteSpace(customerIdentifier))
{
Refund(Message.Value);
Assert(false, "Customer identifier is required");
}

// sale closed
if (!SaleOpen)
{
Refund(Message.Value);
Assert(false, "Sale not open");
}
Assert(secret != null, "Invalid secret");
Assert(!RequireIdentityVerification || customerIdentifier != null, "Invalid customer identifier");
Assert(SaleOpen, "Sale not open");

var seat = Serializer.ToStruct<Seat>(seatIdentifierBytes);
var copyOfTickets = Tickets;
Expand All @@ -232,57 +224,21 @@ public bool Reserve(byte[] seatIdentifierBytes, string customerIdentifier)
}
}

// seat not found
if (IsDefaultSeat(ticket.Seat))
{
Refund(Message.Value);
Assert(false, "Seat not found");
}

// already reserved
if (!IsAvailable(ticket))
{
Refund(Message.Value);
return false;
}

// not enough funds
if (Message.Value < ticket.Price)
{
Refund(Message.Value);
return false;
}
Assert(!IsDefaultSeat(ticket.Seat), "Seat not found");
Assert(IsAvailable(ticket), "Ticket not available");
Assert(Message.Value >= ticket.Price, "Not enough funds");

if (Message.Value > ticket.Price)
{
Refund(Message.Value - ticket.Price);
Transfer(Message.Sender, Message.Value - ticket.Price);
}

copyOfTickets[ticketIndex].Address = Message.Sender;
copyOfTickets[ticketIndex].Secret = secret;
copyOfTickets[ticketIndex].CustomerIdentifier = customerIdentifier;
Tickets = copyOfTickets;
return true;
}

/// <summary>
/// Used to verify whether an address owns a ticket
/// </summary>
/// <param name="seatIdentifierBytes">The serialized seat identifier</param>
/// <param name="address">The address to verify</param>
/// <returns>The result of the reservation query</returns>
public ReservationQueryResult CheckReservation(byte[] seatIdentifierBytes, Address address)
{
Assert(address != Address.Zero, "Invalid address");

var ticket = SelectTicket(seatIdentifierBytes);

Assert(!IsDefaultSeat(ticket.Seat), "Seat not found");

return new ReservationQueryResult
{
OwnsTicket = address == ticket.Address,
CustomerIdentifier = ticket.CustomerIdentifier
};
Log(copyOfTickets[ticketIndex]);
}

/// <summary>
Expand Down Expand Up @@ -346,28 +302,15 @@ public void ReleaseTicket(byte[] seatIdentifierBytes)

if (ticket.Price > ReleaseFee)
{
TryTransfer(Message.Sender, ticket.Price - ReleaseFee);
Transfer(Message.Sender, ticket.Price - ReleaseFee);
}

copyOfTickets[ticketIndex].Address = Address.Zero;
copyOfTickets[ticketIndex].Secret = null;
copyOfTickets[ticketIndex].CustomerIdentifier = null;
Tickets = copyOfTickets;
}

private bool Refund(ulong amount)
{
Assert(amount <= Message.Value, "Invalid refund value");
return TryTransfer(Message.Sender, amount);
}

private bool TryTransfer(Address recipient, ulong amount)
{
if (amount > 0)
{
var transferResult = Transfer(recipient, amount);
return transferResult.Success;
}

return false;
Log(copyOfTickets[ticketIndex]);
}

private Ticket SelectTicket(byte[] seatIdentifierBytes)
Expand Down Expand Up @@ -403,9 +346,10 @@ private Ticket[] ResetTickets(Ticket[] tickets)
{
for (int i = 0; i < tickets.Length; i++)
{
tickets[i].Address = Address.Zero;
tickets[i].Price = 0;
tickets[i].CustomerIdentifier = string.Empty;
tickets[i].Address = Address.Zero;
tickets[i].Secret = null;
tickets[i].CustomerIdentifier = null;
}

return tickets;
Expand Down Expand Up @@ -448,9 +392,14 @@ public struct Ticket
public Address Address;

/// <summary>
/// Used by the venue to check identity
/// The encrypted ticket secret
/// </summary>
public byte[] Secret;

/// <summary>
/// Encrypted identifier used by the venue to check identity
/// </summary>
public string CustomerIdentifier;
public byte[] CustomerIdentifier;
}

/// <summary>
Expand All @@ -462,11 +411,6 @@ public struct Venue
/// Name of the venue
/// </summary>
public string Name;

/// <summary>
/// Whether the venue requires identity verification on the door
/// </summary>
public bool VerifiesIdentity;
}

/// <summary>
Expand Down Expand Up @@ -527,20 +471,4 @@ public struct IdentityVerificationPolicy
/// </summary>
public bool RequireIdentityVerification;
}

/// <summary>
/// The ticket reservation query result
/// </summary>
public struct ReservationQueryResult
{
/// <summary>
/// Whether the ticket is owned by the Address
/// </summary>
public bool OwnsTicket;

/// <summary>
/// A verifiable identifier for the ticket holder
/// </summary>
public string CustomerIdentifier;
}
}
10 changes: 6 additions & 4 deletions src/Ticketbooth.Contract/Ticketbooth.Contract.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<LangVersion>6.0</LangVersion>
<Company>Develop Momentum</Company>
<Authors>Adam Shirt</Authors>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Version>1.0.0-rc1</Version>
<Company>Develop Momentum</Company>
<Authors>Adam Shirt</Authors>
<PackageId>Ticketbooth</PackageId>
<Description>Components of the Ticketbooth smart contract</Description>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryUrl>https://github.com/drmathias/Ticketbooth</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Description>Structures used in the Ticketbooth contract</Description>
<Product>Ticketbooth</Product>
<PackageTags>blockchain stratis ticketing smart-contracts ticketbooth</PackageTags>
<Version>1.0.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Stratis.SmartContracts" Version="1.2.1" />
Expand Down
31 changes: 31 additions & 0 deletions src/Ticketbooth.Scanner/Converters/ByteArrayToHexConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Newtonsoft.Json;
using System;

namespace Ticketbooth.Scanner.Converters
{
public class ByteArrayToHexConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(byte[]);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var hexString = (string)reader.Value;
int characterCount = hexString.Length;
byte[] result = new byte[characterCount / 2];
for (int i = 0; i < characterCount; i += 2)
{
result[i / 2] = Convert.ToByte(hexString.Substring(i, 2), 16);
}

return result;
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(BitConverter.ToString((byte[])value).Replace("-", string.Empty));
}
}
}
7 changes: 7 additions & 0 deletions src/Ticketbooth.Scanner/Data/Dtos/BlockDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Ticketbooth.Scanner.Data.Dtos
{
public class BlockDto
{
public ulong Height { get; set; }
}
}
14 changes: 11 additions & 3 deletions src/Ticketbooth.Scanner/Data/Dtos/DigitalTicket.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
using Stratis.SmartContracts;
using static TicketContract;

namespace Ticketbooth.Scanner.Data.Dtos
{
public class DigitalTicket
{
public TicketContract.Seat Seat { get; set; }
public Seat Seat { get; set; }

public Address Address { get; set; }
public string Secret { get; set; }

public byte[] SecretKey { get; set; }

public byte[] SecretIV { get; set; }

public byte[] NameKey { get; set; }

public byte[] NameIV { get; set; }
}
}
7 changes: 7 additions & 0 deletions src/Ticketbooth.Scanner/Data/Dtos/LogDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Ticketbooth.Scanner.Data.Dtos
{
public class LogDto<T>
{
public T Log { get; set; }
}
}
7 changes: 5 additions & 2 deletions src/Ticketbooth.Scanner/Data/Dtos/Receipt.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
namespace Ticketbooth.Scanner.Data.Dtos
{
public class Receipt<T>
public class Receipt<TValue, TLog>
{
public string BlockHash { get; set; }

public T ReturnValue { get; set; }
public TValue ReturnValue { get; set; }

public LogDto<TLog>[] Logs { get; set; }
}
}
2 changes: 1 addition & 1 deletion src/Ticketbooth.Scanner/Data/ITicketRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ public interface ITicketRepository

void Add(TicketScanModel ticketScan);

TicketScanModel Find(string key);
TicketScanModel Find(string identifier);
}
}
6 changes: 3 additions & 3 deletions src/Ticketbooth.Scanner/Data/Models/TicketScanModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ public TicketScanModel()
{
}

public TicketScanModel(string transactionHash, SeatModel seat)
public TicketScanModel(string identifier, SeatModel seat)
{
TransactionHash = transactionHash;
Identifier = identifier;
Seat = seat;
Status = TicketScanStatus.Started;
Time = DateTime.Now;
}

public string TransactionHash { get; set; }
public string Identifier { get; }

public SeatModel Seat { get; set; }

Expand Down
4 changes: 2 additions & 2 deletions src/Ticketbooth.Scanner/Data/TicketRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ public void Add(TicketScanModel ticketScan)
_ticketScans.Enqueue(ticketScan);
}

public TicketScanModel Find(string key)
public TicketScanModel Find(string identifier)
{
return _ticketScans.FirstOrDefault(ticketScan => ticketScan.TransactionHash.Equals(key));
return _ticketScans.FirstOrDefault(ticketScan => ticketScan.Identifier.Equals(identifier));
}
}
}
6 changes: 3 additions & 3 deletions src/Ticketbooth.Scanner/Eventing/Events/TicketScanAdded.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
{
public class TicketScanAdded
{
public TicketScanAdded(string transactionHash)
public TicketScanAdded(string identifier)
{
TransactionHash = transactionHash;
Identifier = identifier;
}

public string TransactionHash { get; }
public string Identifier { get; }
}
}
6 changes: 3 additions & 3 deletions src/Ticketbooth.Scanner/Eventing/Events/TicketScanUpdated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
{
public class TicketScanUpdated
{
public TicketScanUpdated(string transactionHash)
public TicketScanUpdated(string identifier)
{
TransactionHash = transactionHash;
Identifier = identifier;
}

public string TransactionHash { get; }
public string Identifier { get; }
}
}
Loading

0 comments on commit 50adb5d

Please sign in to comment.