Пример #1
0
        internal IEnumerable <Transaction> GetSignedTransactions(PuzzleSolution solution)
        {
            if (solution == null)
            {
                throw new ArgumentNullException(nameof(solution));
            }
            AssertState(PromiseClientStates.Completed);
            solution = solution.Unblind(Parameters.ServerKey, InternalState.BlindFactor);
            BigInteger cumul  = solution._Value;
            var        hashes = _Hashes.OfType <RealHash>().ToArray();

            for (int i = 0; i < Parameters.RealTransactionCount; i++)
            {
                var hash     = hashes[i];
                var quotient = i == 0 ? BigInteger.One : InternalState.Quotients[i - 1]._Value;
                cumul    = cumul.Multiply(quotient).Mod(Parameters.ServerKey._Key.Modulus);
                solution = new PuzzleSolution(cumul);
                ECDSASignature signature;
                PubKey         signer;
                if (!IsValidSignature(solution, hash, out signer, out signature))
                {
                    continue;
                }

                var transaction = hash.GetTransaction();
                TransactionBuilder txBuilder = new TransactionBuilder();
                txBuilder.Extensions.Add(new EscrowBuilderExtension());
                txBuilder.AddCoins(InternalState.EscrowedCoin);
                txBuilder.AddKeys(InternalState.EscrowKey);
                txBuilder.AddKnownSignature(signer, signature);
                txBuilder.SignTransactionInPlace(transaction);
                yield return(transaction);
            }
        }
        internal IEnumerable <Transaction> GetSignedTransactions(PuzzleSolution solution)
        {
            if (solution == null)
            {
                throw new ArgumentNullException(nameof(solution));
            }
            AssertState(PromiseClientStates.Completed);
            solution = solution.Unblind(Parameters.ServerKey, InternalState.BlindFactor);
            BigInteger cumul  = solution._Value;
            var        hashes = _Hashes.OfType <RealHash>().ToArray();

            for (int i = 0; i < Parameters.RealTransactionCount; i++)
            {
                var hash     = hashes[i];
                var quotient = i == 0 ? BigInteger.One : InternalState.Quotients[i - 1]._Value;
                cumul    = cumul.Multiply(quotient).Mod(Parameters.ServerKey._Key.Modulus);
                solution = new PuzzleSolution(cumul);
                if (!IsValidSignature(solution, hash, out ECDSASignature tumblerSig))
                {
                    continue;
                }
                var transaction = hash.GetTransaction();
                var bobSig      = transaction.SignInput(InternalState.EscrowKey, InternalState.EscrowedCoin);
                transaction.Inputs[0].WitScript = new WitScript(
                    Op.GetPushOp(new TransactionSignature(tumblerSig, SigHash.All).ToBytes()),
                    Op.GetPushOp(bobSig.ToBytes()),
                    Op.GetPushOp(InternalState.EscrowedCoin.Redeem.ToBytes())
                    );
                //transaction is already witnessified
                if (transaction.Inputs.AsIndexedInputs().First().VerifyScript(InternalState.EscrowedCoin))
                {
                    yield return(transaction);
                }
            }
        }
Пример #3
0
        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);
        }
Пример #4
0
        public PartialViewResult GetBoardSolution(string board, string wordLengths)
        {
            ModelState.Clear();

            var solutionModel = new PuzzleSolutionModel();

            string[] splitLengths = wordLengths.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

            int dummy;

            if (splitLengths.Any(sl => !Int32.TryParse(sl, out dummy)))
            {
                solutionModel.ErrorMessage = "Word lengths must be comma separated numbers.";
                return(PartialView("_BoardSolutionView", solutionModel));
            }

            int[]  lengths = splitLengths.Select(w => Convert.ToInt32(w)).ToArray();
            string message = PuzzlePlant.IsValidPuzzle(board, lengths);

            if (!string.IsNullOrWhiteSpace(message))
            {
                solutionModel.ErrorMessage = message;
                return(PartialView("_BoardSolutionView", solutionModel));
            }

            IBoardSolver   boardSolver = Plant.Plant.BoardSolver;
            Puzzle         puzzle      = PuzzlePlant.BuildPuzzle(board, lengths);
            PuzzleSolution solution    = boardSolver.SolvePuzzle(puzzle);

            solutionModel.Words = solution.Solutions.Select(words => words.Select(w => w.Letters).ToList()).ToList();
            return(PartialView("_BoardSolutionView", solutionModel));
        }
Пример #5
0
 public SolvedPuzzle(PuzzleValue puzzle, SolutionKey key, PuzzleSolution solution)
 {
     Puzzle            = puzzle;
     SolutionKey       = key;
     Solution          = solution;
     EncryptedSolution = GetEncryptedSolution();
 }
Пример #6
0
        public SolverServerSession ConfirmClientEscrow(Transaction transaction, out PuzzleSolution solvedVoucher)
        {
            AssertState(AliceServerChannelNegotiationStates.WaitingClientEscrow);
            solvedVoucher = null;
            var escrow = CreateEscrowScript();
            var coin   = transaction.Outputs.AsCoins().FirstOrDefault(txout => txout.ScriptPubKey == escrow.Hash.ScriptPubKey);

            if (coin == null)
            {
                throw new PuzzleException("No output containing the escrowed coin");
            }
            if (coin.Amount != Parameters.Denomination + Parameters.Fee)
            {
                throw new PuzzleException("Incorrect amount");
            }
            var voucher      = InternalState.UnsignedVoucher;
            var escrowedCoin = coin.ToScriptCoin(escrow);

            var session = new SolverServerSession(TumblerKey, Parameters.CreateSolverParamaters());

            session.ConfigureEscrowedCoin(escrowedCoin, InternalState.EscrowKey);
            InternalState.UnsignedVoucher = null;
            InternalState.OtherEscrowKey  = null;
            InternalState.RedeemKey       = null;
            InternalState.EscrowKey       = null;
            solvedVoucher        = voucher.WithRsaKey(VoucherKey.PubKey).Solve(VoucherKey);
            InternalState.Status = AliceServerChannelNegotiationStates.Completed;
            return(session);
        }
Пример #7
0
        public ServerCommitment[] SignHashes(SignaturesRequest sigRequest)
        {
            if (sigRequest == null)
            {
                throw new ArgumentNullException(nameof(sigRequest));
            }
            if (sigRequest.Hashes.Length != Parameters.GetTotalTransactionsCount())
            {
                throw new ArgumentException("Incorrect number of hashes, expected " + sigRequest.Hashes.Length);
            }
            AssertState(PromiseServerStates.WaitingHashes);
            List <ServerCommitment>   promises            = new List <ServerCommitment>();
            List <EncryptedSignature> encryptedSignatures = new List <EncryptedSignature>();

            foreach (var hash in sigRequest.Hashes)
            {
                var            ecdsa    = InternalState.EscrowKey.Sign(hash);
                var            ecdsaDER = ecdsa.ToDER();
                var            key      = new XORKey(Parameters.ServerKey);
                var            promise  = key.XOR(ecdsaDER);
                PuzzleSolution solution = new PuzzleSolution(key.ToBytes());
                var            puzzle   = Parameters.ServerKey.GeneratePuzzle(ref solution);
                promises.Add(new ServerCommitment(puzzle.PuzzleValue, promise));
                encryptedSignatures.Add(new EncryptedSignature(ecdsa, hash, solution));
            }
            InternalState.Status = PromiseServerStates.WaitingRevelation;
            InternalState.EncryptedSignatures = encryptedSignatures.ToArray();
            InternalState.FakeIndexesHash     = sigRequest.FakeIndexesHash;
            return(promises.ToArray());
        }
Пример #8
0
        public PuzzleValue[] GeneratePuzzles()
        {
            AssertState(SolverClientStates.WaitingGeneratePuzzles);
            List <PuzzleSetElement> puzzles = new List <PuzzleSetElement>();

            for (int i = 0; i < Parameters.RealPuzzleCount; i++)
            {
                BlindFactor blind  = null;
                Puzzle      puzzle = new Puzzle(ServerKey, InternalState.Puzzle).Blind(ref blind);
                puzzles.Add(new RealPuzzle(puzzle, blind));
            }

            for (int i = 0; i < Parameters.FakePuzzleCount; i++)
            {
                PuzzleSolution solution = null;
                Puzzle         puzzle   = ServerKey.GeneratePuzzle(ref solution);
                puzzles.Add(new FakePuzzle(puzzle, solution));
            }

            _PuzzleElements = puzzles.ToArray();
            NBitcoin.Utils.Shuffle(_PuzzleElements, RandomUtils.GetInt32());
            InternalState.FakeIndexes = new int[Parameters.FakePuzzleCount];
            int fakeI = 0;

            for (int i = 0; i < _PuzzleElements.Length; i++)
            {
                _PuzzleElements[i].Index = i;
                if (_PuzzleElements[i] is FakePuzzle)
                {
                    InternalState.FakeIndexes[fakeI++] = i;
                }
            }
            InternalState.Status = SolverClientStates.WaitingCommitments;
            return(_PuzzleElements.Select(p => p.Puzzle.PuzzleValue).ToArray());
        }
Пример #9
0
        public BlindFactor[] GetBlindFactors(SolutionKey[] keys)
        {
            if (keys == null)
            {
                throw new ArgumentNullException(nameof(keys));
            }
            if (keys.Length != Parameters.FakePuzzleCount)
            {
                throw new ArgumentException("Expecting " + Parameters.FakePuzzleCount + " keys");
            }
            AssertState(SolverClientStates.WaitingFakeCommitmentsProof);

            int y = 0;

            foreach (var puzzle in _PuzzleElements.OfType <FakePuzzle>())
            {
                var key  = keys[y++].ToBytes(true);
                var hash = new uint160(Hashes.RIPEMD160(key, key.Length));
                if (hash != puzzle.Commitment.KeyHash)
                {
                    throw new PuzzleException("Commitment hash invalid");
                }
                var solution = new PuzzleSolution(Utils.ChachaDecrypt(puzzle.Commitment.EncryptedSolution, key));
                if (solution != puzzle.Solution)
                {
                    throw new PuzzleException("Commitment encrypted solution invalid");
                }
            }

            InternalState.Status = SolverClientStates.WaitingOffer;
            return(_PuzzleElements.OfType <RealPuzzle>()
                   .Select(p => p.BlindFactor)
                   .ToArray());
        }
Пример #10
0
        private PuzzleSolution OptimizeSolution(PuzzleSolution solution)
        {
            sm_log.Info("Optimizing solution");
            new CostOptimizer(solution).Optimize();

            return(solution);
        }
Пример #11
0
    // The function that collects all the cubes in the scene and saves them for later as a
    // JSON file.
    public void SavePuzzle(string filePath)
    {
        // Create an array of all the cubes with the BuildCube tag.
        cubesToSave = GameObject.FindGameObjectsWithTag("BuildCube");

        // Get the minimum and maximum values for each dimension of the puzzle.
        int[] minMaxValues = GetMinMaxValues(cubesToSave);

        PuzzleSolution newPuzzleSolution = new PuzzleSolution(minMaxValues, true);

        // Add each puzzleUnit attached to the cubes in cubesToSave to the PuzzleSolution.
        foreach (GameObject cube in cubesToSave)
        {
            newPuzzleSolution.AddUnit(cube.GetComponent <CubeScript>().GetPuzzleUnit());
        }

        // goal make a PuzzleSolution from cubesToSave.

        // Create a string that is made from the PuzzleSolution object
        string jsonString = JsonUtility.ToJson(newPuzzleSolution, true);

        // Write the json string to the file.
        File.WriteAllText(filePath, jsonString);

        // Call the function that shows the puzzle save confirmation text on UIManager.
        uiManager.StartSavedTextTimer();

        // Refreshes the assets in the Editor so you can immediately see the new file made.
        //AssetDatabase.Refresh();

        // If the solution was saved successfully, we are no longer using the save UI
        // so the puzzle can be interacted with again.
        usingSaveUI = false;
    }
Пример #12
0
        public ServerCommitment[][] SignHashes(SignaturesRequest sigRequest)
        {
            // Almost done, just need to confirm a typo and a function.
            // Step 5

            if (sigRequest == null)
            {
                throw new ArgumentNullException(nameof(sigRequest));
            }

            var hashesCount = sigRequest.Hashes.Select(a => a.Length).Sum();

            if (hashesCount != Parameters.GetTotalTransactionsCount())
            {
                throw new ArgumentException($"Incorrect number of hashes, expected {Parameters.GetTotalTransactionsCount()}");
            }

            AssertState(PromiseServerStates.WaitingHashes);
            // 2D array of pairs of puzzles and promises (z_i, c_i).
            var promises = new ServerCommitment[Parameters.PaymentsCount][];
            // 2D array of encrypted signatures with their solutions.
            var encryptedSignatures = new EncryptedSignature[Parameters.PaymentsCount][];
            // 1-D array is used to store the epsilons for each column to be used when Hashing.
            var previousSolutions = new byte[Parameters.GetTotalTransactionsCountPerLevel()][];

            previousSolutions = previousSolutions.Select(a => new byte[0]).ToArray(); // Initialize to empty array of bytes
            for (int i = 0; i < Parameters.PaymentsCount; i++)
            {
                promises[i]            = new ServerCommitment[sigRequest.Hashes[i].Length]; // Initialization
                encryptedSignatures[i] = new EncryptedSignature[promises[i].Length];        // Initialization
                for (int j = 0; j < promises[i].Length; j++)
                {
                    var hash = sigRequest.Hashes[i][j];
                    // Sign the hash value
                    var ecdsa = InternalState.EscrowKey.Sign(hash);
                    // Convert Signature to Bytes.
                    var ecdsaDER = ecdsa.ToDER();
                    // This can be replaced by "Utils.GenerateEncryptableInteger(Key)" if padding when XORing is not important.
                    var key = (new XORKey(Parameters.ServerKey)).ToBytes(); // This just generates a random epsilon.
                    // Append the new epsilon to the list of epsilons we have for that column to create "epsilon_{i-1,j}|| . . . , epsilon_{0,j}".
                    previousSolutions[j] = Utils.Combine(key, previousSolutions[j]);
                    // Create the padded solution with the following format "i||j||epsilon_{i,j}||epsilon_{i-1,j}|| . . . , epsilon_{0,j}"
                    var paddedSolutions = new PuzzleSolution(Utils.Combine(NBitcoin.Utils.ToBytes((uint)i, true), NBitcoin.Utils.ToBytes((uint)j, true), previousSolutions[j]));
                    // Hash and XOR the padded solution with the signature we have.
                    var            promise  = XORKey.XOR(paddedSolutions._Value.ToByteArrayUnsigned(), ecdsaDER); // This function needs to be approved "XOR".
                    PuzzleSolution solution = new PuzzleSolution(key);                                            // Epsilon
                    // Encrypt the epsilon value using RSA
                    var puzzle = Parameters.ServerKey.GeneratePuzzle(ref solution);
                    promises[i][j]            = new ServerCommitment(puzzle.PuzzleValue, promise);
                    encryptedSignatures[i][j] = new EncryptedSignature(ecdsa, hash, solution);
                }
            }

            InternalState.Status = PromiseServerStates.WaitingRevelation;
            InternalState.EncryptedSignatures = encryptedSignatures;
            InternalState.FakeIndexesHash     = sigRequest.FakeIndexesHash;
            return(promises);
        }
Пример #13
0
        public Transaction GetSignedTransaction(PuzzleSolution solution)
        {
            var tx = GetSignedTransactions(solution).FirstOrDefault();

            if (tx == null)
            {
                throw new PuzzleException("Wrong solution for the puzzle");
            }
            return(tx);
        }
Пример #14
0
        public void SolveBoard_16_Test()
        {
            Puzzle puzzle = GeneratePuzzle("aynedhecrtcaibkl", 8, 8); // cupboard roof oval

            IWordDictionary dictionary = GetDictionary();
            IBoardCop       boardCop   = new BoardCop.BoardCop();
            IBoardSolver    solver     = new BoardSolver.BoardSolver(boardCop, dictionary);
            PuzzleSolution  solutions  = solver.SolvePuzzle(puzzle);

            Assert.IsNotNull(solutions);
        }
Пример #15
0
        public Transaction GetSignedTransaction(PuzzleSolution solution, int paymentNumber)
        {
            // Fix the Exception message to include the number of the puzzle.
            var tx = GetSignedTransactions(solution, paymentNumber).FirstOrDefault();

            if (tx == null)
            {
                throw new PuzzleException($"Wrong solution for the puzzle {paymentNumber}");
            }
            return(tx);
        }
Пример #16
0
        public void SolveBoard_4_Test()
        {
            Puzzle puzzle = GeneratePuzzle("cart", 4);

            IWordDictionary dictionary = GetDictionary();
            IBoardCop       boardCop   = new BoardCop.BoardCop();
            IBoardSolver    solver     = new BoardSolver.BoardSolver(boardCop, dictionary);

            PuzzleSolution ps = solver.SolvePuzzle(puzzle);

            Assert.IsNotNull(ps);
        }
Пример #17
0
        public void SolveBoard_9_Test_WrongFirstChoice()
        {
            Puzzle puzzle = GeneratePuzzle("efdidlrie", 4, 5); // ride field

            IWordDictionary dictionary = GetDictionary();
            IBoardCop       boardCop   = new BoardCop.BoardCop();
            IBoardSolver    solver     = new BoardSolver.BoardSolver(boardCop, dictionary);

            PuzzleSolution solutions = solver.SolvePuzzle(puzzle);

            Assert.IsNotNull(solutions);
        }
Пример #18
0
        public void SolveBoard_9_Test()
        {
            Puzzle puzzle = GeneratePuzzle("flfooirde", 4, 5); // roof field

            IWordDictionary dictionary = GetDictionary();
            IBoardCop       boardCop   = new BoardCop.BoardCop();
            IBoardSolver    solver     = new BoardSolver.BoardSolver(boardCop, dictionary);

            PuzzleSolution solutions = solver.SolvePuzzle(puzzle);

            Assert.IsNotNull(solutions);
        }
Пример #19
0
        public void CheckVoucherSolution(PuzzleSolution blindedVoucherSignature)
        {
            AssertState(TumblerClientSessionStates.WaitingSolvedVoucher);
            var solution = blindedVoucherSignature.Unblind(Parameters.VoucherKey.PublicKey, InternalState.BlindedVoucherFactor);

            if (!InternalState.UnsignedVoucher.Puzzle.WithRsaKey(Parameters.VoucherKey.PublicKey).Verify(solution))
            {
                throw new PuzzleException("Incorrect puzzle solution");
            }
            InternalState.BlindedVoucherFactor = null;
            InternalState.SignedVoucher        = new XORKey(solution).XOR(InternalState.UnsignedVoucher.EncryptedSignature);
            InternalState.UnsignedVoucher.EncryptedSignature = new byte[0];
            InternalState.ClientEscrowKey = null;
            InternalState.Status          = TumblerClientSessionStates.WaitingGenerateTumblerTransactionKey;
        }
Пример #20
0
        public UnsignedVoucherInformation GenerateUnsignedVoucher()
        {
            PuzzleSolution solution = null;
            var            puzzle   = Parameters.VoucherKey.GeneratePuzzle(ref solution);
            uint160        nonce;
            var            cycle     = GetCycle().Start;
            var            signature = VoucherKey.Sign(NBitcoin.Utils.ToBytes((uint)cycle, true), out nonce);

            return(new UnsignedVoucherInformation
            {
                CycleStart = cycle,
                Nonce = nonce,
                Puzzle = puzzle.PuzzleValue,
                EncryptedSignature = new XORKey(solution).XOR(signature)
            });
        }
Пример #21
0
        public static void Main()
        {
            string?searchType = null;

            while (true)
            {
                Console.Write("Depth-first or Breadth-first search? (d/b): ");
                searchType = Console.ReadLine();
                if ((searchType == "d") || (searchType == "b"))
                {
                    break;
                }
                Console.WriteLine("Invalid Selection");
                Console.WriteLine();
            }

            try
            {
                var findStarted = DateTime.UtcNow;

                var initialState = new PuzzleState(
                    AirTimeMinutesRemaining:    21,
                    AstronautLocations:         ImmutableDictionary.CreateRange(new[]
                {
                    new KeyValuePair <Astronaut, StationSection>(Astronaut.Neil, StationSection.SectionA),
                    new KeyValuePair <Astronaut, StationSection>(Astronaut.Michael, StationSection.SectionA),
                    new KeyValuePair <Astronaut, StationSection>(Astronaut.Valentina, StationSection.SectionA),
                    new KeyValuePair <Astronaut, StationSection>(Astronaut.Yuri, StationSection.SectionA),
                    new KeyValuePair <Astronaut, StationSection>(Astronaut.Edwin, StationSection.SectionA)
                }),
                    SuitsLocation:              StationSection.SectionA);

                var(solution, solutionsChecked) = (searchType == "d")
                    ? PuzzleSolution.FindDepth(initialState)
                    : PuzzleSolution.FindBreadth(initialState);

                var findDuration = DateTime.UtcNow - findStarted;

                Console.WriteLine("Solution found");
                Console.WriteLine("Steps:");
                foreach (var mutation in solution.Mutations)
                {
                    Console.WriteLine($"\t{string.Join(" and ", mutation.AstronautsMoved)} spend{((mutation.AstronautsMoved.Length == 1) ? "s" : "")} {mutation.TravelTimeMinutes} minute{((mutation.TravelTimeMinutes == 1) ? "" : "s")} moving to {mutation.TargetStationSection}");
                }
                var finalState = solution.States[^ 1];
Пример #22
0
        public void CanSolvePuzzle()
        {
            RsaKey         key       = TestKeys.Default;
            PuzzleSolution solution  = null;
            var            puzzle    = key.PubKey.GeneratePuzzle(ref solution);
            PuzzleSolution solution2 = puzzle.Solve(key);

            Assert.True(puzzle.Verify(solution));
            Assert.True(solution == solution2);


            puzzle = key.PubKey.GeneratePuzzle(ref solution);
            BlindFactor    blind           = null;
            Puzzle         blindedPuzzle   = puzzle.Blind(ref blind);
            PuzzleSolution blindedSolution = key.SolvePuzzle(blindedPuzzle);
            var            unblinded       = blindedSolution.Unblind(key.PubKey, blind);

            Assert.True(unblinded == solution);
        }
Пример #23
0
        public void CanBlind()
        {
            RsaKey key = TestKeys.Default;

            PuzzleSolution solution = null;
            BlindFactor    blind    = null;

            Puzzle puzzle        = key.PubKey.GeneratePuzzle(ref solution);
            Puzzle blindedPuzzle = puzzle.Blind(ref blind);

            Assert.True(puzzle != blindedPuzzle);
            Assert.True(puzzle == blindedPuzzle.Unblind(blind));


            PuzzleSolution blindedSolution = blindedPuzzle.Solve(key);

            Assert.False(puzzle.Verify(blindedSolution));
            Assert.True(puzzle.Verify(blindedSolution.Unblind(key.PubKey, blind)));
        }
Пример #24
0
        internal IEnumerable <Transaction> GetSignedTransactions(PuzzleSolution solution, int paymentNumber)
        {
            /*
             * parameter "paymentNumber" indicates which j payment this is.
             * TODO: In order to solve the puzzle using the "solution", we need the previous solution
             * to get the signatures.
             *
             */
            if (solution == null)
            {
                throw new ArgumentNullException(nameof(solution));
            }
            AssertState(PromiseClientStates.Completed);
            solution = solution.Unblind(Parameters.ServerKey, InternalState.BlindFactors[paymentNumber]);
            BigInteger cumul  = solution._Value;
            var        hashes = _Hashes[paymentNumber].OfType <RealHash>().ToArray();

            for (int i = 0; i < Parameters.RealTransactionCountPerLevel; i++)
            {
                var hash     = hashes[i];
                var quotient = i == 0 ? BigInteger.One : InternalState.Quotients[paymentNumber][i - 1]._Value;
                cumul = cumul.Multiply(quotient).Mod(Parameters.ServerKey._Key.Modulus); // Epsilon_i
                // Need to fix how the solution is recovered given how we need the previous solutions to get the current one.
                solution = new PuzzleSolution(cumul);
                if (!IsValidSignature(solution, hash, out ECDSASignature tumblerSig))
                {
                    continue;
                }
                var transaction = hash.GetTransaction();
                var bobSig      = transaction.SignInput(InternalState.EscrowKey, InternalState.EscrowedCoin);
                transaction.Inputs[0].ScriptSig = new Script(
                    Op.GetPushOp(new TransactionSignature(tumblerSig, SigHash.All).ToBytes()),
                    Op.GetPushOp(bobSig.ToBytes()),
                    Op.GetPushOp(InternalState.EscrowedCoin.Redeem.ToBytes())
                    );
                if (transaction.Inputs.AsIndexedInputs().First().VerifyScript(InternalState.EscrowedCoin))
                {
                    yield return(transaction);
                }
            }
        }
Пример #25
0
        public void CheckSolutions(SolutionKey[] keys)
        {
            if (keys == null)
            {
                throw new ArgumentNullException(nameof(keys));
            }
            if (keys.Length != Parameters.RealPuzzleCount)
            {
                throw new ArgumentException("Expecting " + Parameters.RealPuzzleCount + " keys");
            }
            AssertState(SolverClientStates.WaitingPuzzleSolutions);
            PuzzleSolution solution     = null;
            RealPuzzle     solvedPuzzle = null;
            int            y            = 0;

            foreach (var puzzle in _PuzzleElements.OfType <RealPuzzle>())
            {
                var key        = keys[y++].ToBytes(true);
                var commitment = puzzle.Commitment;

                var hash = new uint160(Hashes.RIPEMD160(key, key.Length));
                if (hash == commitment.KeyHash)
                {
                    var decryptedSolution = new PuzzleSolution(Utils.ChachaDecrypt(commitment.EncryptedSolution, key));
                    if (puzzle.Puzzle.Verify(decryptedSolution))
                    {
                        solution     = decryptedSolution;
                        solvedPuzzle = puzzle;
                        break;
                    }
                }
            }

            if (solution == null)
            {
                throw new PuzzleException("Impossible to find solution to the puzzle");
            }

            InternalState.PuzzleSolution = solution.Unblind(ServerKey, solvedPuzzle.BlindFactor);
            InternalState.Status         = SolverClientStates.Completed;
        }
Пример #26
0
        private bool IsValidSignature(PuzzleSolution solution, HashBase hash, out ECDSASignature signature)
        {
            signature = null;
            var escrow = EscrowScriptPubKeyParameters.GetFromCoin(InternalState.EscrowedCoin);

            try
            {
                var key = new XORKey(solution);
                signature = new ECDSASignature(key.XOR(hash.Commitment.Promise));
                var ok = escrow.Initiator.Verify(hash.GetHash(), signature);
                if (!ok)
                {
                    signature = null;
                }
                return(ok);
            }
            catch
            {
            }
            return(false);
        }
Пример #27
0
        private void CheckAllowedGlyphs(PuzzleSolution solution)
        {
            var usedGlyphs    = solution.GetObjects <Glyph>().Select(glyph => glyph.Type).Distinct();
            var missingGlyphs = usedGlyphs.Except(Puzzle.AllowedGlyphs);

            // We only check the basic glyphs as the others are checked when generating the pipeline.

            if (missingGlyphs.Contains(GlyphType.Bonding))
            {
                throw new SolverException("This puzzle doesn't allow the glyph of bonding.");
            }

            if (missingGlyphs.Contains(GlyphType.Unbonding))
            {
                throw new SolverException("This puzzle doesn't allow the glyph of unbonding.");
            }

            if (missingGlyphs.Contains(GlyphType.TriplexBonding))
            {
                throw new SolverException("One or more products contain triplex bonds but the puzzle doesn't allow the glyph of triplex bonding.");
            }
        }
Пример #28
0
        public UnsignedVoucherInformation AskUnsignedVoucher(
            [ModelBinder(BinderType = typeof(TumblerParametersModelBinder))]
            ClassicTumblerParameters tumblerId)
        {
            if (tumblerId == null)
            {
                throw new ArgumentNullException(nameof(tumblerId));
            }
            var            height          = Services.BlockExplorerService.GetCurrentHeight();
            var            cycleParameters = Parameters.CycleGenerator.GetRegisteringCycle(height);
            PuzzleSolution solution        = null;
            var            puzzle          = Parameters.VoucherKey.PublicKey.GeneratePuzzle(ref solution);
            var            cycle           = cycleParameters.Start;
            var            signature       = Runtime.VoucherKey.Sign(NBitcoin.Utils.ToBytes((uint)cycle, true), out uint160 nonce);

            return(new UnsignedVoucherInformation
            {
                CycleStart = cycle,
                Nonce = nonce,
                Puzzle = puzzle.PuzzleValue,
                EncryptedSignature = new XORKey(solution).XOR(signature)
            });
        }
Пример #29
0
 private bool IsValidSignature(PuzzleSolution solution, HashBase hash, out PubKey signer, out ECDSASignature signature)
 {
     signer    = null;
     signature = null;
     try
     {
         var key = new XORKey(solution);
         signature = new ECDSASignature(key.XOR(hash.Commitment.Promise));
         foreach (var sig in GetExpectedSigners())
         {
             if (sig.Verify(hash.GetHash(), signature))
             {
                 signer = sig;
                 return(true);
             }
         }
         return(false);
     }
     catch
     {
     }
     return(false);
 }
Пример #30
0
	public void GeneratePuzzle()
	{
		// Select moon phase for this round
		MoonPhase = Random.Range (0, 5);
		PuzzleSolutions = new Dictionary<int, PuzzleSolution> ();
		// Generate Puzzle
		// Repeat for each phase of the moon
		for (int i=0; i<5; i++) {
			List<GameObject> tmpRuneList = new List<GameObject>(Runes);
			List<GameObject> tmpRitualObjectsList = new List<GameObject>(RitualObjects);
			PuzzleSolution aSolution = new PuzzleSolution() 
				{ 	BlackPair = new Dictionary<GameObject, GameObject>(),  
					GreenPair = new Dictionary<GameObject, GameObject>(),  
					RedPair = new Dictionary<GameObject, GameObject>() 
				};
			
			//aSolution.BlackPair.Add(tmpRitualObjectsList[tmpRitualObjectIndex], tmpRuneList[tmpRuneIndex]);
			CreatePair(aSolution.BlackPair, tmpRitualObjectsList, tmpRuneList);
			CreatePair(aSolution.RedPair, tmpRitualObjectsList, tmpRuneList);
			CreatePair(aSolution.GreenPair, tmpRitualObjectsList, tmpRuneList);
			PuzzleSolutions.Add (i, aSolution);
		}
		// Generate the five hint pages, one for each phase of the moon

		// Decide which puzzle to use based on the moon phase
		ActualSolution = PuzzleSolutions [MoonPhase];
		// Put a costume on the red, green and black the ritual objects

		// Hook up the coloured candles to their ritual objects
		//KeyCollection kc = 
		GameObject RedRitualObject = null; 
		var keys = ActualSolution.RedPair.Keys;
		foreach (GameObject go in keys) {
			RedRitualObject = go;
			break;
		}
		GameObject RedGlyph = null;
		ActualSolution.RedPair.TryGetValue (RedRitualObject, out RedGlyph);
		ParticleSystem[] redParticles = RedGlyph.GetComponentsInChildren<ParticleSystem> ();
		foreach (ParticleSystem p in redParticles) {
			p.Play();
		}
		Imposter RedImposter = RedRitualObject.GetComponent<Imposter> ();
		RedCandle.RevealedObject = RedImposter;

		GameObject GreenRitualObject = null; 
		keys = ActualSolution.GreenPair.Keys;
		foreach (GameObject go in keys) {
			GreenRitualObject = go;
			break;
		}
		GameObject GreenGlyph = null;
		ActualSolution.GreenPair.TryGetValue (GreenRitualObject, out GreenGlyph);
		ParticleSystem[] greenParticles = GreenGlyph.GetComponentsInChildren<ParticleSystem> ();
		foreach (ParticleSystem p in greenParticles) {
			p.startColor = Color.green;
			p.Play();
		}
		Imposter GreenImposter = GreenRitualObject.GetComponent<Imposter> ();
		GreenCandle.RevealedObject = GreenImposter;

		GameObject BlackRitualObject = null; 
		keys = ActualSolution.BlackPair.Keys;
		foreach (GameObject go in keys) {
			BlackRitualObject = go;
			break;
		}
		GameObject BlackGlyph = null;
		ActualSolution.BlackPair.TryGetValue (BlackRitualObject, out BlackGlyph);
		ParticleSystem[] blackParticles = BlackGlyph.GetComponentsInChildren<ParticleSystem> ();
		foreach (ParticleSystem p in blackParticles) {
			p.startColor = Color.black;
			p.Play();
		}
		Imposter BlackImposter = BlackRitualObject.GetComponent<Imposter> ();
		BlackCandle.RevealedObject = BlackImposter;
	}
 public void SaveSignedVoucher(int start, uint160 channelId, PuzzleSolution solution)
 {
     Repository.UpdateOrInsert(GetCyclePartition(start), "V-" + channelId, solution, (o, n) => o);
 }