public State GetInternalState() { var state = Serializer.Clone(InternalState); if (_PuzzleElements != null) { var commitments = new ServerCommitment[_PuzzleElements.Length]; var puzzles = new PuzzleValue[_PuzzleElements.Length]; var fakeSolutions = new PuzzleSolution[Parameters.FakePuzzleCount]; var blinds = new BlindFactor[Parameters.RealPuzzleCount]; int fakeI = 0, realI = 0; for (int i = 0; i < _PuzzleElements.Length; i++) { commitments[i] = _PuzzleElements[i].Commitment; puzzles[i] = _PuzzleElements[i].Puzzle.PuzzleValue; var fake = _PuzzleElements[i] as FakePuzzle; if (fake != null) { fakeSolutions[fakeI++] = fake.Solution; } var real = _PuzzleElements[i] as RealPuzzle; if (real != null) { blinds[realI++] = real.BlindFactor; } } state.FakeSolutions = fakeSolutions; state.BlindFactors = blinds; state.Commitments = commitments; state.Puzzles = puzzles; } return(state); }
public SolvedPuzzle(PuzzleValue puzzle, SolutionKey key, PuzzleSolution solution) { Puzzle = puzzle; SolutionKey = key; Solution = solution; EncryptedSolution = GetEncryptedSolution(); }
public void AcceptPuzzle(PuzzleValue puzzleValue) { if (puzzleValue == null) { throw new ArgumentNullException(nameof(puzzleValue)); } AssertState(SolverClientStates.WaitingPuzzle); InternalState.Puzzle = puzzleValue; InternalState.Status = SolverClientStates.WaitingGeneratePuzzles; }
public PuzzleValue[] CheckCommitmentProof(ServerCommitmentsProof proof) { // steps 8, 10, 12 if (proof == null) { throw new ArgumentNullException(nameof(proof)); } var FakeSolutionsCount = proof.FakeSolutions.Select(a => a.Length).Sum(); // sums the number of FakeSolutions. if (FakeSolutionsCount != Parameters.GetTotalFakeTransactionsCount()) { throw new ArgumentException($"Expecting {Parameters.GetTotalFakeTransactionsCount()} solutions"); } var QuotientsCount = proof.Quotients.Select(a => a.Length).Sum(); // sums the number of Quotients. if (QuotientsCount != (Parameters.GetTotalRealTransactionsCount() - _Parameters.PaymentsCount)) // this is Q * (mu - 1) { throw new ArgumentException($"Expecting {(Parameters.GetTotalRealTransactionsCount() - _Parameters.PaymentsCount)} quotients"); } AssertState(PromiseClientStates.WaitingCommitmentsProof); var previousSolutions = new byte[Parameters.FakeTransactionCountPerLevel][]; previousSolutions = previousSolutions.Select(a => new byte[0]).ToArray(); // Initialize to empty for (int i = 0; i < _Hashes.Length; i++) { var fakeHashes = _Hashes[i].OfType <FakeHash>().ToArray(); for (int j = 0; j < fakeHashes.Length; j++) { // TODO: prove that the solutions are lined up in same order as the hashes. var fakeHash = fakeHashes[j]; var solution = proof.FakeSolutions[i][j]; if (solution._Value.CompareTo(Parameters.ServerKey._Key.Modulus) >= 0) { throw new PuzzleException("Solution bigger than modulus"); } if (!new Puzzle(Parameters.ServerKey, fakeHash.Commitment.Puzzle).Verify(solution)) { throw new PuzzleException("Invalid puzzle solution"); } previousSolutions[j] = Utils.Combine(solution.ToBytes(), previousSolutions[j]); var paddedSolution = new PuzzleSolution(Utils.Combine(NBitcoin.Utils.ToBytes((uint)i, true), NBitcoin.Utils.ToBytes((uint)fakeHash.Index, true), previousSolutions[j])); if (!IsValidSignature(paddedSolution, fakeHash, out ECDSASignature sig)) { throw new PuzzleException("Invalid ECDSA signature"); } } } // Step 10 for (int i = 0; i < _Hashes.Length; i++) { var realHashes = _Hashes[i].OfType <RealHash>().ToArray(); for (int j = 1; j < realHashes.Length; j++) { var q = proof.Quotients[i][j - 1]._Value; var p1 = realHashes[j - 1].Commitment.Puzzle._Value; var p2 = realHashes[j].Commitment.Puzzle._Value; var p22 = p1.Multiply(Parameters.ServerKey.Encrypt(q)).Mod(Parameters.ServerKey._Key.Modulus); if (!p2.Equals(p22)) { throw new PuzzleException("Invalid quotient"); } } } _Hashes = _Hashes.Select(a => a.OfType <RealHash>().ToArray()).ToArray(); // we do not need the fake one anymore InternalState.FakeColumns = null; InternalState.Quotients = proof.Quotients; // Step 12 // Maybe move this step outside such that we can blind and send puzzles one by one. BlindFactor[] blindFactors = new BlindFactor[_Hashes.Length]; PuzzleValue[] blindedPuzzles = new PuzzleValue[_Hashes.Length]; for (int i = 0; i < _Hashes.Length; i++) { var puzzleToSolve = _Hashes[i].OfType <RealHash>().First().Commitment.Puzzle; blindedPuzzles[i] = new Puzzle(Parameters.ServerKey, puzzleToSolve).Blind(ref blindFactors[i]).PuzzleValue; } InternalState.BlindFactors = blindFactors; InternalState.Status = PromiseClientStates.Completed; return(blindedPuzzles); }
public SolvedPuzzle(PuzzleValue puzzle, SolutionKey key, PuzzleSolution solution) { Puzzle = puzzle; SolutionKey = key; Solution = solution; }
public ServerCommitment(PuzzleValue puzzleValue, byte[] promise) { Puzzle = puzzleValue; Promise = promise; }