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); } } }
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); } }
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; }
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))); }
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); }
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); } } }
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; }