public PromiseClientSession ReceiveTumblerEscrowedCoin(ScriptCoin escrowedCoin) { AssertState(TumblerClientSessionStates.WaitingTumblerEscrow); var escrow = EscrowScriptPubKeyParameters.GetFromCoin(escrowedCoin); var expectedEscrow = new EscrowScriptPubKeyParameters() { Initiator = escrow?.Initiator, Receiver = InternalState.TumblerEscrowKey.PubKey, LockTime = GetCycle().GetTumblerLockTime() }; if (escrow == null || escrow != expectedEscrow) { throw new PuzzleException("invalid-escrow"); } if (escrowedCoin.Amount != Parameters.Denomination) { throw new PuzzleException("invalid-amount"); } InternalState.Status = TumblerClientSessionStates.PromisePhase; var session = new PromiseClientSession(Parameters.CreatePromiseParamaters()); session.SetChannelId(InternalState.ChannelId); session.ConfigureEscrowedCoin(escrowedCoin, InternalState.TumblerEscrowKey); InternalState.TumblerEscrowKey = null; return(session); }
public PromiseClientSession ReceiveTumblerEscrowedCoin(ScriptCoin escrowedCoin) { AssertState(TumblerClientSessionStates.WaitingTumblerEscrow); var escrow = EscrowScriptPubKeyParameters.GetFromCoin(escrowedCoin); if (escrow == null) { throw new PuzzleException("invalid-escrow"); } if (!escrowedCoin.IsP2SH || escrowedCoin.RedeemType != RedeemType.WitnessV0) { throw new PuzzleException("invalid-escrow"); } var expectedEscrow = GetTumblerEscrowParameters(escrow.Initiator); if (escrow != expectedEscrow) { throw new PuzzleException("invalid-escrow"); } if (escrowedCoin.Amount != Parameters.Denomination) { throw new PuzzleException("invalid-amount"); } InternalState.Status = TumblerClientSessionStates.PromisePhase; var session = new PromiseClientSession(Parameters.CreatePromiseParamaters()); session.SetChannelId(InternalState.ChannelId); session.ConfigureEscrowedCoin(escrowedCoin, InternalState.TumblerEscrowKey); InternalState.TumblerEscrowKey = null; return(session); }
public PromiseClientSession ReceiveTumblerEscrowedCoin(ScriptCoin escrowedCoin) { AssertState(TumblerClientSessionStates.WaitingTumblerEscrow); var escrow = EscrowScriptBuilder.ExtractEscrowScriptPubKeyParameters(escrowedCoin.Redeem); if (escrow == null || !escrow.EscrowKeys.Contains(InternalState.TumblerEscrowKey.PubKey)) { throw new PuzzleException("invalid-escrow"); } if (escrowedCoin.Amount != Parameters.Denomination) { throw new PuzzleException("invalid-amount"); } InternalState.Status = TumblerClientSessionStates.PromisePhase; var session = new PromiseClientSession(Parameters.CreatePromiseParamaters()); session.ConfigureEscrowedCoin(escrowedCoin, InternalState.TumblerEscrowKey); InternalState.TumblerEscrowKey = null; return(session); }
public void TestPuzzlePromise() { RsaKey key = TestKeys.Default; Key serverEscrow = new Key(); Key clientEscrow = new Key(); var parameters = new PromiseParameters(key.PubKey) { FakeTransactionCount = 5, RealTransactionCount = 5 }; var client = new PromiseClientSession(parameters); var server = new PromiseServerSession(parameters); var coin = CreateEscrowCoin(serverEscrow.PubKey, clientEscrow.PubKey); client.ConfigureEscrowedCoin(coin, clientEscrow); SignaturesRequest request = client.CreateSignatureRequest(clientEscrow.PubKey.Hash, FeeRate); RoundTrip(ref client, parameters); RoundTrip(ref request); server.ConfigureEscrowedCoin(coin, serverEscrow, new Key().ScriptPubKey); PuzzlePromise.ServerCommitment[] commitments = server.SignHashes(request); RoundTrip(ref server, parameters); RoundTrip(ref commitments); PuzzlePromise.ClientRevelation revelation = client.Reveal(commitments); RoundTrip(ref client, parameters); RoundTrip(ref revelation); ServerCommitmentsProof proof = server.CheckRevelation(revelation); RoundTrip(ref server, parameters); RoundTrip(ref proof); var puzzleToSolve = client.CheckCommitmentProof(proof); RoundTrip(ref client, parameters); Assert.NotNull(puzzleToSolve); var solution = key.SolvePuzzle(puzzleToSolve); var transactions = client.GetSignedTransactions(solution).ToArray(); RoundTrip(ref client, parameters); Assert.True(transactions.Length == parameters.RealTransactionCount); var escrow = server.GetInternalState().EscrowedCoin; // In case things do not go well and timeout is hit... var redeemTransaction = server.CreateRedeemTransaction(FeeRate); var resigned = redeemTransaction.ReSign(escrow); TransactionBuilder bb = new TransactionBuilder(); bb.AddCoins(server.GetInternalState().EscrowedCoin); Assert.True(bb.Verify(resigned)); //Check can ve reclaimed if malleated bb = new TransactionBuilder(); escrow.Outpoint = new OutPoint(escrow.Outpoint.Hash, 10); bb.AddCoins(escrow); resigned = redeemTransaction.ReSign(escrow); Assert.False(bb.Verify(redeemTransaction.Transaction)); Assert.True(bb.Verify(resigned)); }
public void TestPuzzlePromise() { RsaKey key = TestKeys.Default; Key serverEscrow = new Key(); Key clientEscrow = new Key(); var parameters = new PromiseParameters(key.PubKey) { FakeTransactionCountPerLevel = 5, RealTransactionCountPerLevel = 5, PaymentsCount = 5 //Not sure if this is the way to go. }; var client = new PromiseClientSession(parameters); var server = new PromiseServerSession(parameters); var coin = CreateEscrowCoin(serverEscrow.PubKey, clientEscrow.PubKey); client.ConfigureEscrowedCoin(coin, clientEscrow); SignaturesRequest request = client.CreateSignatureRequest(clientEscrow.PubKey.Hash, FeeRate); RoundTrip(ref client, parameters); RoundTrip(ref request); server.ConfigureEscrowedCoin(uint160.Zero, coin, serverEscrow, new Key().ScriptPubKey); PuzzlePromise.ServerCommitment[][] commitments = server.SignHashes(request); RoundTrip(ref server, parameters); RoundTrip(ref commitments); PuzzlePromise.ClientRevelation revelation = client.Reveal(commitments); RoundTrip(ref client, parameters); RoundTrip(ref revelation); ServerCommitmentsProof proof = server.CheckRevelation(revelation, clientEscrow.PubKey.Hash, FeeRate); RoundTrip(ref server, parameters); RoundTrip(ref proof); var puzzlesToSolve = client.CheckCommitmentProof(proof); RoundTrip(ref client, parameters); foreach (var puzzle in puzzlesToSolve) { Assert.NotNull(puzzle); } for (int i = 0; i < puzzlesToSolve.Length; i++) { // Doesn't work for now! Need to figure how Bob will be spending the puzzles. var solution = key.SolvePuzzle(puzzlesToSolve[i]); // I'm not sure if GetSignedTransactions should handle all payments or only one payment at a time. var transactions = client.GetSignedTransactions(solution, i).ToArray(); RoundTrip(ref client, parameters); Assert.True(transactions.Length == parameters.RealTransactionCountPerLevel); } var escrow = server.GetInternalState().EscrowedCoin; // In case things do not go well and timeout is hit... var redeemTransaction = server.CreateRedeemTransaction(FeeRate); var resigned = redeemTransaction.ReSign(escrow); TransactionBuilder bb = new TransactionBuilder(); bb.AddCoins(server.GetInternalState().EscrowedCoin); Assert.True(bb.Verify(resigned)); //Check can ve reclaimed if malleated bb = new TransactionBuilder(); escrow.Outpoint = new OutPoint(escrow.Outpoint.Hash, 10); bb.AddCoins(escrow); resigned = redeemTransaction.ReSign(escrow); Assert.False(bb.Verify(redeemTransaction.Transaction)); Assert.True(bb.Verify(resigned)); }