public static void SetupBitwiseAndProtocol(Quorum quorum) { int n = quorum.Size; var polyDeg = (int)Math.Ceiling(n / 3.0) - 1; var sharesA = BigShamirSharing.Share(new BigZp(prime, 0), n, polyDeg); var sharesB = BigShamirSharing.Share(new BigZp(prime, 1), n, polyDeg); var sharesC = BigShamirSharing.Share(new BigZp(prime, 0), n, polyDeg); var sharesD = BigShamirSharing.Share(new BigZp(prime, 0), n, polyDeg); var sharesE = BigShamirSharing.Share(new BigZp(prime, 1), n, polyDeg); var sharesF = BigShamirSharing.Share(new BigZp(prime, 1), n, polyDeg); for (int i = 0; i < n; i++) { Quorum q = quorum.Clone() as Quorum; TestParty <List <Share <BigZp> > > party = new TestParty <List <Share <BigZp> > >(); party.UnderTest = new BitwiseOperationProtocol(party, q, MakeList(sharesA[i], sharesB[i], sharesC[i]), MakeList(sharesD[i], sharesE[i], sharesF[i]), new SharedBitAnd.ProtocolFactory(party, q)); NetSimulator.RegisterParty(party); } }
private void SetupResultBroadcast() { // we need to broadcast each result to every other quorum List <Protocol> resultProtocols = new List <Protocol>(); for (int i = 0; i < PartyIds.Count; i++) { Quorum evalQuorum = GateQuorumMapping[SortNetwork.LastGateForWire[i].Gate]; if (Result[i] == null) { // setup a receive for this result resultProtocols.Add(new MajorityFilteringProtocol <BigZp>(Me, PartyIds, evalQuorum.Members, ProtocolIdGenerator.ResultBroadcastIdentifier(i))); } else { // setup a broadcast for this result ISet <int> others = new SortedSet <int>(PartyIds); foreach (var qid in evalQuorum.Members) { others.Remove(qid); } resultProtocols.Add(new MajorityFilteringProtocol <BigZp>(Me, PartyIds, others, Result[i], ProtocolIdGenerator.ResultBroadcastIdentifier(i))); } } ExecuteSubProtocols(resultProtocols); }
public void AppendToQueryParameters(Dictionary <string, string> queryParameters) { if (Phased) { queryParameters.Add(Parameters.Phased, Phased.ToString()); queryParameters.Add(Parameters.PhasingFinishHeight, FinishHeight.ToString()); queryParameters.Add(Parameters.PhasingVotingModel, ((int)VotingModel).ToString()); queryParameters.Add(Parameters.PhasingQuorum, Quorum.ToString()); if (MinBalance > 0) { queryParameters.Add(Parameters.PhasingMinBalance, MinBalance.ToString()); } if (HoldingId > 0) { queryParameters.Add(Parameters.PhasingHolding, HoldingId.ToString()); } if (MinBalanceModel != MinBalanceModel.None) { queryParameters.Add(Parameters.PhasingMinBalanceModel, ((int)MinBalanceModel).ToString()); } WhiteListed.ForEach(w => queryParameters.Add(Parameters.PhasingWhitelisted, w.AccountRs)); LinkedFullHash.ForEach(h => queryParameters.Add(Parameters.PhasingLinkedFullHash, h.ToHexString())); if (HashedSecret != null) { queryParameters.Add(Parameters.PhasingHashedSecret, HashedSecret.ToHexString()); } if (HashedSecretAlgorithm.HasValue) { queryParameters.Add(Parameters.PhasingHashedSecretAlgorithm, ((int)HashedSecretAlgorithm.Value).ToString()); } } }
public static void ReconstructDictionary(Quorum q, OutputGateAddress[] ordering, int qSize) { List <BigZp> result = new List <BigZp>(); foreach (OutputGateAddress outAddr in ordering) { if (outAddr == null) { continue; } BigZp[] shares = new BigZp[qSize]; int j = 0; foreach (var id in q.Members) { Protocol <IDictionary <OutputGateAddress, Share <BigZp> > > p = (NetSimulator.GetParty(id) as TestParty <IDictionary <OutputGateAddress, Share <BigZp> > >).UnderTest; if (p.Result.ContainsKey(outAddr)) { shares[j++] = p.Result[outAddr].Value; } } result.Add(BigShamirSharing.Recombine(new List <BigZp>(shares), (int)Math.Ceiling(qSize / 3.0) - 1, prime)); } Console.WriteLine("Result: " + string.Join(" ", result)); }
/* * prime = prime20; * Main(32); * NetSimulator.Reset(); * * prime = prime30; * Main(32); * NetSimulator.Reset(); * * prime = prime40; * Main(32); * NetSimulator.Reset(); * * prime = prime50; * Main(32); * NetSimulator.Reset(); */ public static void Main(int n) // number of parties { Debug.Assert(NumTheoryUtils.MillerRabin(prime, 5) == false); // must be a prime // Create an MPC network, add parties, and init them with random inputs NetSimulator.Init(seed); //seed StaticRandom.Init(seed + 1); //seed + 1 Quorum q = new Quorum(0, 0, n); SetupMps(n); //SetupMultiQuorumCircuitEvaluation(q); Console.WriteLine(n + " parties initialized. Running simulation...\n"); // run the simulator var elapsedTime = Timex.Run(() => NetSimulator.Run()); // CheckMps(n); //ReconstructDictionary(q, network.LastGateForWire, 4); Console.WriteLine("Simulation finished. Checking results...\n"); Console.WriteLine("# parties = " + n); Console.WriteLine("# msgs sent = " + NetSimulator.SentMessageCount.ToString("0.##E+00")); Console.WriteLine("# bits sent = " + (NetSimulator.SentByteCount * 8).ToString("0.##E+00")); Console.WriteLine("Rounds = " + NetSimulator.RoundCount + "\n"); Console.WriteLine("Key size = " + NumTheoryUtils.GetBitLength2(prime) + " bits"); Console.WriteLine("Seed = " + seed + "\n"); Console.WriteLine("Elapsed time = " + elapsedTime.ToString("hh':'mm':'ss'.'fff") + "\n"); }
public ReconstructionProtocol(Party me, Quorum quorum, Share <BigZp> share) : base(me, quorum) { Share = share; Prime = share.Value.Prime; ReconstRecv = new Dictionary <int, BigZp>(); }
public ShareMultiplicationProtocol(Party me, Quorum quorum, Share <BigZp> share1, Share <BigZp> share2) : base(me, quorum) { Debug.Assert(share1.Value.Prime == share2.Value.Prime); Prime = share1.Value.Prime; Share1 = share1; Share2 = share2; }
public void NegTwoThroughNegFive_AreValidQuorums() { for (int i = -2; i >= -5; --i) { var q = new Quorum(i); Assert.AreEqual(i, (int)q); } }
public CompareAndSwapProtocol(Party me, Quorum quorum, Share <BigZp> shareA, Share <BigZp> shareB) : base(me, quorum) { Debug.Assert(shareA.Value.Prime == shareB.Value.Prime); ShareA = shareA; ShareB = shareB; Prime = shareA.Value.Prime; }
public BitwiseOperationProtocol(Party me, Quorum quorum, IList <Share <BigZp> > bitSharesA, IList <Share <BigZp> > bitSharesB, IBitProtocolFactory bitProtocolFactory) : base(me, quorum) { Debug.Assert(bitSharesA.Count == bitSharesB.Count); BitSharesA = bitSharesA; BitSharesB = bitSharesB; ProtocolFactory = bitProtocolFactory; }
public BitwiseLessThanProtocol(Party me, Quorum quorum, List <Share <BigZp> > aBitShares, List <Share <BigZp> > bBitShares) : base(me, quorum) { Debug.Assert(aBitShares.Count == bBitShares.Count); BitSharesA = aBitShares; BitSharesB = bBitShares; baclone = new List <Share <BigZp> >(BitSharesA); }
public ConditionalSwapProtocol(Party me, Quorum quorum, Share <BigZp> shareA, Share <BigZp> shareB, Share <BigZp> swapBit) : base(me, quorum) { Debug.Assert(shareA.Value.Prime == shareB.Value.Prime); ShareA = shareA; ShareB = shareB; SwapBit = swapBit; Prime = ShareA.Value.Prime; }
public ShareLessThanProtocol(Party me, Quorum Quorum, Share <BigZp> shareA, Share <BigZp> shareB) : base(me, Quorum) { Debug.Assert(shareA.Value.Prime == shareB.Value.Prime); ShareA = shareA; ShareB = shareB; Prime = ShareA.Value.Prime; }
public TBuilder WithW(Quorum w) { if (w == null) { throw new ArgumentNullException("w", "w may not be null"); } this.w = w; return((TBuilder)this); }
public TBuilder WithPW(Quorum pw) { if (pw == null) { throw new ArgumentNullException("pw", "pw may not be null"); } this.pw = pw; return((TBuilder)this); }
public TBuilder WithDW(Quorum dw) { if (dw == null) { throw new ArgumentNullException("dw", "dw may not be null"); } this.dw = dw; return((TBuilder)this); }
public TBuilder WithR(Quorum r) { if (r == null) { throw new ArgumentNullException("r", "r may not be null"); } this.r = r; return((TBuilder)this); }
public TaggedCompareAndSwapProtocol(Party me, Quorum quorum, Tuple <Share <BigZp>, Share <BigZp> > taggedShareA, Tuple <Share <BigZp>, Share <BigZp> > taggedShareB) : base(me, quorum) { Debug.Assert(taggedShareA.Item1.Value.Prime == taggedShareB.Item1.Value.Prime); CompShareA = taggedShareA.Item1; CompShareB = taggedShareB.Item1; TagShareA = taggedShareA.Item2; TagShareB = taggedShareB.Item2; Prime = CompShareA.Value.Prime; }
public QuorumTaggedShareRenewalProtocol(Party me, Quorum quorumFrom, Quorum quorumTo, Tuple <Share <BigZp>, Share <BigZp> > shares, BigInteger prime, ulong protocolId) : base(me, new Quorum[] { quorumFrom, quorumTo }, protocolId) { if (shares != null) { Debug.Assert(shares.Item1.Value.Prime == shares.Item2.Value.Prime); } Shares = shares; Prime = prime; }
public TBuilder WithPR(Quorum pr) { if (pr == null) { throw new ArgumentNullException("pr", "pr may not be null"); } this.pr = pr; return((TBuilder)this); }
/* * public static void SetupSimpleCircuitEvaluation(Quorum quorum) * { * int n = quorum.Size; * var polyDeg = (int)Math.Ceiling(n / 3.0) - 1; * * Debug.Assert((n & (n - 1)) == 0); // is power of 2 * * network = new LPSortingNetwork(n); * * IList<BigZp>[] shares = new IList<BigZp>[n]; * * for (int i = 0; i < n; i++) * shares[i] = BigShamirSharing.Share(new BigZp(prime, 500 - 2*i), n, polyDeg); * * foreach (var id in quorum.Members) * { * Dictionary<InputGateAddress, Share<BigZp>> inShares = new Dictionary<InputGateAddress, Share<BigZp>>(); * * int i = 0; * foreach (var inAddr in network.Circuit.InputAddrs) * { * inShares[inAddr] = new Share<BigZp>(shares[i][id]); * i++; * } * * TestParty<IDictionary<OutputGateAddress, Share<BigZp>>> party = new TestParty<IDictionary<OutputGateAddress, Share<BigZp>>>(); * party.UnderTest = new SecureGroupCircuitEvaluation(party, quorum.Clone() as Quorum, network.Circuit, inShares); * NetSimulator.RegisterParty(party); * } * } */ public static void SetupMultiQuorumCircuitEvaluation(Quorum bigQuorum) { int n = bigQuorum.Size; int qSize = n / 2; var polyDeg = (int)Math.Ceiling(qSize / 3.0) - 1; var quorums = new List <Quorum>(); quorums.Add(new Quorum(0, 0, qSize)); quorums.Add(new Quorum(1, qSize, 2 * qSize)); Debug.Assert((n & (n - 1)) == 0); // is power of 2 network = new LPSortingNetwork(n); //network = SortingNetworkFactory.CreateButterflyTournamentRound(n); network.CollapsePermutationGates(); IList <BigZp>[] shares = new IList <BigZp> [n]; for (int i = 0; i < n; i++) { shares[i] = BigShamirSharing.Share(new BigZp(prime, 500 - 2 * i), qSize, polyDeg); } Dictionary <Gate, Quorum> gqmapping = new Dictionary <Gate, Quorum>(); for (int i = 0; i < network.Circuit.TopologicalOrder.Count; i++) { gqmapping[network.Circuit.TopologicalOrder[i]] = quorums[i]; } foreach (var id in bigQuorum.Members) { Dictionary <InputGateAddress, Share <BigZp> > inShares = new Dictionary <InputGateAddress, Share <BigZp> >(); int i = 0; foreach (var inAddr in network.Circuit.InputAddrs) { inShares[inAddr] = new Share <BigZp>(shares[i][id % 4]); i++; } TestParty <IDictionary <OutputGateAddress, Share <BigZp> > > party = new TestParty <IDictionary <OutputGateAddress, Share <BigZp> > >(); Quorum[] quorumsClone = quorums.Select(a => a.Clone() as Quorum).ToArray(); party.UnderTest = new SecureMultiQuorumCircuitEvaluation <Share <BigZp> >(party, quorumsClone[id / qSize], quorumsClone, ProtocolIdGenerator.GenericIdentifier(0), network.Circuit, inShares, new BigZpShareGateEvaluationFactory(prime), gqmapping, prime); NetSimulator.RegisterParty(party); } }
public static void SetupRandomBitGenProtocol(Quorum quorum) { int n = quorum.Size; for (int i = 0; i < n; i++) { TestParty <Share <BigZp> > party = new TestParty <Share <BigZp> >(); party.UnderTest = new RandomBitGenProtocol(party, quorum.Clone() as Quorum, prime); NetSimulator.RegisterParty(party); } }
public QuorumShareRenewalProtocol(Party me, Quorum quorumFrom, Quorum quorumTo, Share <BigZp> share, BigInteger prime, ulong protocolId) : base(me, new Quorum[] { quorumFrom, quorumTo }, protocolId) { Debug.Assert(share == null || !share.IsPublic); // makes no sense to do share renewal on a public value Prime = prime; if (share != null) { Shares = new BigZp[] { share.Value } } ; }
public ShareRenewalRound(Party me, Quorum quorumFrom, Quorum quorumTo, BigZp[] startShares, BigInteger prime, int startSharesPerParty, int finalSharesPerParty, ulong protocolId) : base(me, new Quorum[] { quorumFrom, quorumTo }, protocolId) { FinalSharesPerParty = finalSharesPerParty; StartSharesPerParty = startSharesPerParty; StartShares = startShares; Prime = prime; ReceivedReshareCount = 0; foreach (var from in Quorums[0].Members) { sharesRecv[from] = new List <ShareWitnessMsg <BigZp> > [startSharesPerParty]; for (int i = 0; i < startSharesPerParty; i++) { numCommitsRecv[from] = 0; sharesRecv[from][i] = new List <ShareWitnessMsg <BigZp> >(); } } StartShareCount = Quorums[FROM].Size * StartSharesPerParty; FinalShareCount = Quorums[TO].Size * FinalSharesPerParty; NewPolyDeg = (int)Math.Ceiling(FinalShareCount / 3.0) - 1; VandermondeInv = StaticCache.GetVandermondeInvColumn(Prime, StartShareCount); if (Quorums[TO].HasMember(Me.Id)) { var quorumIter = Quorums[TO].Members.GetEnumerator(); int i = 0; while (quorumIter.MoveNext()) { if (Me.Id == quorumIter.Current) { MyQuorumIndex = i; break; } i++; } } if (Quorums[TO] is ByzantineQuorum) { var byzTo = Quorums[TO] as ByzantineQuorum; if (FinalShareCount == Quorums[TO].Size) { PolyCommit = byzTo.PolyCommit; } else { PolyCommit = new PolyCommit(); PolyCommit.Setup(NewPolyDeg + 1, byzTo.Seed); } } }
public static void SetupBitwiseRandomGeneration(Quorum quorum) { int n = quorum.Size; for (int i = 0; i < n; i++) { TestParty <List <Share <BigZp> > > party = new TestParty <List <Share <BigZp> > >(); party.UnderTest = new RandomBitwiseGenProtocol(party, quorum, prime, 15); NetSimulator.RegisterParty(party); } }
public UpdateCommandBuilder(UpdateCommandBuilder <TBuilder, TCommand, TOptions, TResponse> source) : base(source) { this.w = source.w; this.pw = source.pw; this.dw = source.dw; this.returnBody = source.returnBody; this.includeContext = source.includeContext; this.context = source.context; }
private static SortedSet <int> QuorumPlusParty(Quorum q, int p) { if (q.HasMember(p)) { return(q.Members); } var newSet = new SortedSet <int>(q.Members); newSet.Add(p); return(newSet); }
public MultiQuorumGateEvaluation(Party me, ComputationGate evalGate, IDictionary <Gate, Quorum> gateQuorumMapping, Circuit circuit, IGateEvaluationProtocolFactory <T> protocolFactory, IDictionary <InputGateAddress, T> circuitInputs, BigInteger prime, ulong protocolId) : base(me, GetParticipatingQuorumList(evalGate, gateQuorumMapping, circuit), protocolId) { EvalGate = evalGate; GateQuorumMapping = gateQuorumMapping; Circuit = circuit; Prime = prime; EvalQuorum = gateQuorumMapping[EvalGate]; CircuitInputs = circuitInputs; ProtocolFactory = protocolFactory; Result = new Dictionary <OutputGateAddress, T>(); }
public RandomBitwiseGenProtocol(Party me, Quorum quorum, BigInteger prime, BigInteger max) : base(me, quorum) { Max = max; Prime = prime; BitsNeeded = NumTheoryUtils.GetBitLength2(Max); if (Max.IsPowerOfTwo) { BitsNeeded--; } Result = new List <Share <BigZp> >(); }
public RandGenProtocol(Party me, Quorum quorum, BigZp myRandom, BigInteger prime) : base(me, quorum) { MyRandom = myRandom; Prime = prime; PolyDegree = (int)Math.Ceiling(Quorum.Size / 3.0) - 1; if (Quorum is ByzantineQuorum) { PolyCommit = (Quorum as ByzantineQuorum).PolyCommit; } CombinedShare = new BigZp(Prime); }
public void WellKnownUnsignedIntValues_AreValidQuorums() { uint quorum_uint = uint.MaxValue - 1; var quorum = new Quorum(quorum_uint); Assert.AreEqual(Quorum.WellKnown.One, quorum); quorum_uint = uint.MaxValue - 2; quorum = new Quorum(quorum_uint); Assert.AreEqual(Quorum.WellKnown.Quorum, quorum); quorum_uint = uint.MaxValue - 3; quorum = new Quorum(quorum_uint); Assert.AreEqual(Quorum.WellKnown.All, quorum); quorum_uint = uint.MaxValue - 4; quorum = new Quorum(quorum_uint); Assert.AreEqual(Quorum.WellKnown.Default, quorum); }
public void Should_Build_DtUpdateReq_Correctly() { var updateSetCommandBuilder = new UpdateSet.Builder(DefaultAdds, DefaultRemoves); var q1 = new Quorum(1); var q2 = new Quorum(2); var q3 = new Quorum(3); updateSetCommandBuilder .WithBucketType(BucketType) .WithBucket(Bucket) .WithKey(Key) .WithW(q3) .WithPW(q1) .WithDW(q2) .WithReturnBody(true) .WithIncludeContext(false) .WithContext(Context) .WithTimeout(TimeSpan.FromSeconds(20)); UpdateSet updateSetCommand = updateSetCommandBuilder.Build(); DtUpdateReq protobuf = (DtUpdateReq)updateSetCommand.ConstructRequest(false); Assert.AreEqual(Encoding.UTF8.GetBytes(BucketType), protobuf.type); Assert.AreEqual(Encoding.UTF8.GetBytes(Bucket), protobuf.bucket); Assert.AreEqual(Encoding.UTF8.GetBytes(Key), protobuf.key); Assert.AreEqual((uint)q3, protobuf.w); Assert.AreEqual((uint)q1, protobuf.pw); Assert.AreEqual((uint)q2, protobuf.dw); Assert.IsTrue(protobuf.return_body); Assert.IsFalse(protobuf.include_context); Assert.AreEqual(20000, protobuf.timeout); SetOp setOpMsg = protobuf.op.set_op; Assert.AreEqual(DefaultAdds, setOpMsg.adds); Assert.AreEqual(DefaultRemoves, setOpMsg.removes); }
public void Should_Build_DtUpdateReq_Correctly() { var mapOp = new UpdateMap.MapOperation() .IncrementCounter("counter_1", 50) .RemoveCounter("counter_2") .AddToSet("set_1", "set_value_1") .RemoveFromSet("set_2", "set_value_2") .RemoveSet("set_3") .SetRegister("register_1", "register_value_1") .RemoveRegister("register_2") .SetFlag("flag_1", true) .RemoveFlag("flag_2") .RemoveMap("map_3"); mapOp.Map("map_2").IncrementCounter("counter_1", 50) .RemoveCounter("counter_2") .AddToSet("set_1", "set_value_1") .RemoveFromSet("set_2", "set_value_2") .RemoveSet("set_3") .SetRegister("register_1", "register_value_1") .RemoveRegister("register_2") .SetFlag("flag_1", true) .RemoveFlag("flag_2") .RemoveMap("map_3"); var updateMapCommandBuilder = new UpdateMap.Builder(mapOp); var q1 = new Quorum(1); var q2 = new Quorum(2); var q3 = new Quorum(3); updateMapCommandBuilder .WithBucketType(BucketType) .WithBucket(Bucket) .WithKey(Key) .WithContext(Context) .WithW(q3) .WithPW(q1) .WithDW(q2) .WithReturnBody(true) .WithIncludeContext(false) .WithTimeout(TimeSpan.FromSeconds(20)); UpdateMap updateMapCommand = updateMapCommandBuilder.Build(); DtUpdateReq protobuf = (DtUpdateReq)updateMapCommand.ConstructRequest(false); Assert.AreEqual(Encoding.UTF8.GetBytes(BucketType), protobuf.type); Assert.AreEqual(Encoding.UTF8.GetBytes(Bucket), protobuf.bucket); Assert.AreEqual(Encoding.UTF8.GetBytes(Key), protobuf.key); Assert.AreEqual((uint)q3, protobuf.w); Assert.AreEqual((uint)q1, protobuf.pw); Assert.AreEqual((uint)q2, protobuf.dw); Assert.IsTrue(protobuf.return_body); Assert.IsFalse(protobuf.include_context); Assert.AreEqual(20000, protobuf.timeout); Assert.AreEqual(Context, protobuf.context); MapOp mapOpMsg = protobuf.op.map_op; VerifyRemoves(mapOpMsg.removes); MapUpdate innerMapUpdate = VerifyUpdates(mapOpMsg.updates, true); VerifyRemoves(innerMapUpdate.map_op.removes); VerifyUpdates(innerMapUpdate.map_op.updates, false); }
public void Zero_IsValidQuorum() { var q = new Quorum(0); Assert.IsNotNull(q); }
public void WhenUsingValidQuorumString_ResultsInValidQuorumValue() { var validQuorumData = new Dictionary<string, int[]> { { "one", new[] { 1, Quorum.WellKnown.One } }, { "One", new[] { 1, Quorum.WellKnown.One } }, { "ONE", new[] { 1, Quorum.WellKnown.One } }, { "onE", new[] { 1, Quorum.WellKnown.One } }, { "quorum", new[] { 2, Quorum.WellKnown.Quorum } }, { "Quorum", new[] { 2, Quorum.WellKnown.Quorum } }, { "QUORUM", new[] { 2, Quorum.WellKnown.Quorum } }, { "quOrUm", new[] { 2, Quorum.WellKnown.Quorum } }, { "all", new[] { 3, Quorum.WellKnown.All } }, { "All", new[] { 3, Quorum.WellKnown.All } }, { "ALL", new[] { 3, Quorum.WellKnown.All } }, { "alL", new[] { 3, Quorum.WellKnown.All } }, { "default", new[] { 4, Quorum.WellKnown.Default } }, { "Default", new[] { 4, Quorum.WellKnown.Default } }, { "DEFAULT", new[] { 4, Quorum.WellKnown.Default } }, { "deFaulT", new[] { 4, Quorum.WellKnown.Default } } }; foreach (var vqd in validQuorumData) { string quorum_str = vqd.Key; int quorum_int_base = vqd.Value[0]; int quorum_as_int = vqd.Value[1]; uint quorum_uint = uint.MaxValue - (uint)quorum_int_base; var quorum = new Quorum(quorum_str); Assert.AreEqual(quorum_as_int, (int)quorum); Assert.AreEqual(quorum_uint, (uint)quorum); Assert.AreEqual(quorum_str.ToLowerInvariant(), (string)quorum); Assert.AreEqual(quorum_str.ToLowerInvariant(), quorum.ToString()); var quorum_from_int = new Quorum(quorum_as_int); Assert.AreEqual(quorum_from_int, quorum); Assert.True(quorum_from_int.Equals(quorum)); } }