/// <inheritdoc /> public async Task <PuzzleSolution> SignVoucherAsync(SignVoucherRequest request) { PuzzleSolution result = await this.serverAddress.AppendPathSegment("api/v1/tumblers/0/clientchannels/confirm").PostJsonAsync(request).ReceiveJson <PuzzleSolution>(); return(result); }
public PuzzleSolution SignVoucher(SignVoucherRequest signVoucherRequest) { return(SignVoucherAsync(signVoucherRequest).GetAwaiter().GetResult()); }
public async Task <PuzzleSolution> SignVoucher( [ModelBinder(BinderType = typeof(TumblerParametersModelBinder))] ClassicTumblerParameters tumblerId, [FromBody] SignVoucherRequest request) { if (tumblerId == null) { throw new ArgumentNullException("tumblerId"); } if (request.UnsignedVoucher == null) { throw new ActionResultException(BadRequest("Missing UnsignedVoucher")); } if (request.MerkleProof == null) { throw new ActionResultException(BadRequest("Missing MerkleProof")); } if (request.Transaction == null) { throw new ActionResultException(BadRequest("Missing Transaction")); } if (request.ClientEscrowKey == null) { throw new ActionResultException(BadRequest("Missing ClientEscrowKey")); } if (request.ChannelId == null) { throw new ActionResultException(BadRequest("Missing ChannelId")); } var cycle = GetCycle(request.Cycle); var height = Services.BlockExplorerService.GetCurrentHeight(); if (!cycle.IsInPhase(CyclePhase.ClientChannelEstablishment, height)) { throw new ActionResultException(BadRequest("invalid-phase")); } if (request.MerkleProof.PartialMerkleTree .GetMatchedTransactions() .FirstOrDefault() != request.Transaction.GetHash() || !request.MerkleProof.Header.CheckProofOfWork()) { Logs.Tumbler.LogDebug("Invalid transaction merkle proof"); throw new ActionResultException(BadRequest("invalid-merkleproof")); } var confirmations = Services.BlockExplorerService.GetBlockConfirmations(request.MerkleProof.Header.GetHash()); if ((confirmations < Parameters.CycleGenerator.FirstCycle.SafetyPeriodDuration)) { Logs.Tumbler.LogDebug("Not enough confirmations"); throw new ActionResultException(BadRequest("not-enough-confirmation")); } var transaction = request.Transaction; if (transaction.Outputs.Count > 2) { Logs.Tumbler.LogDebug("Incorrect number of outputs"); throw new ActionResultException(BadRequest("invalid-transaction")); } var key = Repository.GetKey(cycle.Start, request.KeyReference); if (Repository.IsUsed(cycle.Start, request.ChannelId)) { throw new ActionResultException(BadRequest("duplicate-query")); } var expectedEscrow = new EscrowScriptPubKeyParameters(request.ClientEscrowKey, key.PubKey, cycle.GetClientLockTime()); var expectedTxOut = new TxOut(Parameters.Denomination + Parameters.Fee, expectedEscrow.ToScript().WitHash.ScriptPubKey.Hash); var escrowedCoin = transaction .Outputs .AsCoins() .Where(c => c.TxOut.Value == expectedTxOut.Value && c.TxOut.ScriptPubKey == expectedTxOut.ScriptPubKey) .Select(c => c.ToScriptCoin(expectedEscrow.ToScript())) .FirstOrDefault(); if (escrowedCoin == null) { Logs.Tumbler.LogDebug("Could not find escrowed coin"); throw new ActionResultException(BadRequest("invalid-transaction")); } var solverServerSession = new SolverServerSession(Runtime.TumblerKey, Parameters.CreateSolverParamaters()); solverServerSession.SetChannelId(request.ChannelId); solverServerSession.ConfigureEscrowedCoin(escrowedCoin, key); await Services.BlockExplorerService.TrackAsync(escrowedCoin.ScriptPubKey); if (!await Services.BlockExplorerService.TrackPrunedTransactionAsync(request.Transaction, request.MerkleProof)) { throw new ActionResultException(BadRequest("invalid-merkleproof")); } //Without this one, someone could spam the nonce db by replaying this request with different channelId if (!Repository.MarkUsedNonce(cycle.Start, Hashes.Hash160(escrowedCoin.Outpoint.ToBytes()))) { throw new ActionResultException(BadRequest("duplicate-query")); } AssertNotDuplicateQuery(cycle.Start, request.ChannelId); Repository.Save(cycle.Start, solverServerSession); Logs.Tumbler.LogInformation($"Cycle {cycle.Start} Proof of Escrow signed for " + transaction.GetHash()); var correlation = GetCorrelation(solverServerSession); Tracker.AddressCreated(cycle.Start, TransactionType.ClientEscrow, escrowedCoin.ScriptPubKey, correlation); Tracker.TransactionCreated(cycle.Start, TransactionType.ClientEscrow, request.Transaction.GetHash(), correlation); var solution = request.UnsignedVoucher.WithRsaKey(Runtime.VoucherKey.PubKey).Solve(Runtime.VoucherKey); return(solution); }
public Task <PuzzleSolution> SignVoucherAsync(SignVoucherRequest signVoucherRequest) { return(SendAsync <PuzzleSolution>(HttpMethod.Post, signVoucherRequest, $"clientchannels/confirm")); }
public PuzzleSolution SignVoucher( [ModelBinder(BinderType = typeof(TumblerParametersModelBinder))] ClassicTumblerParameters tumblerId, [FromBody] SignVoucherRequest request) { if (tumblerId == null) { throw new ArgumentNullException("tumblerId"); } if (request.UnsignedVoucher == null) { throw new ActionResultException(BadRequest("Missing UnsignedVoucher")); } if (request.MerkleProof == null) { throw new ActionResultException(BadRequest("Missing MerkleProof")); } if (request.Transaction == null) { throw new ActionResultException(BadRequest("Missing Transaction")); } if (request.ClientEscrowKey == null) { throw new ActionResultException(BadRequest("Missing ClientEscrowKey")); } if (request.MerkleProof.PartialMerkleTree .GetMatchedTransactions() .FirstOrDefault() != request.Transaction.GetHash() || !request.MerkleProof.Header.CheckProofOfWork()) { throw new ActionResultException(BadRequest("invalid-merkleproof")); } var confirmations = Services.BlockExplorerService.GetBlockConfirmations(request.MerkleProof.Header.GetHash()); if ((confirmations < Parameters.CycleGenerator.FirstCycle.SafetyPeriodDuration)) { throw new ActionResultException(BadRequest("not-enough-confirmation")); } var transaction = request.Transaction; if (transaction.Outputs.Count > 2) { throw new ActionResultException(BadRequest("invalid-transaction")); } var cycle = GetCycle(request.Cycle); var height = Services.BlockExplorerService.GetCurrentHeight(); if (!cycle.IsInPhase(CyclePhase.ClientChannelEstablishment, height)) { throw new ActionResultException(BadRequest("invalid-phase")); } var key = Repository.GetKey(cycle.Start, request.KeyReference); var expectedEscrow = new EscrowScriptPubKeyParameters(request.ClientEscrowKey, key.PubKey, cycle.GetClientLockTime()); var expectedTxOut = new TxOut(Parameters.Denomination + Parameters.Fee, expectedEscrow.ToScript().Hash); var escrowedCoin = transaction .Outputs .AsCoins() .Where(c => c.TxOut.Value == expectedTxOut.Value && c.TxOut.ScriptPubKey == expectedTxOut.ScriptPubKey) .Select(c => c.ToScriptCoin(expectedEscrow.ToScript())) .FirstOrDefault(); if (escrowedCoin == null) { throw new ActionResultException(BadRequest("invalid-transaction")); } try { var solverServerSession = new SolverServerSession(Runtime.TumblerKey, Parameters.CreateSolverParamaters()); solverServerSession.ConfigureEscrowedCoin(escrowedCoin, key); Services.BlockExplorerService.Track(escrowedCoin.ScriptPubKey); if (!Services.BlockExplorerService.TrackPrunedTransaction(request.Transaction, request.MerkleProof)) { throw new ActionResultException(BadRequest("invalid-merkleproof")); } if (!Repository.MarkUsedNonce(cycle.Start, new uint160(key.PubKey.Hash.ToBytes()))) { throw new ActionResultException(BadRequest("invalid-transaction")); } Repository.Save(cycle.Start, solverServerSession); Logs.Tumbler.LogInformation($"Cycle {cycle.Start} Proof of Escrow signed for " + transaction.GetHash()); var correlation = GetCorrelation(solverServerSession); Tracker.AddressCreated(cycle.Start, TransactionType.ClientEscrow, escrowedCoin.ScriptPubKey, correlation); Tracker.TransactionCreated(cycle.Start, TransactionType.ClientEscrow, request.Transaction.GetHash(), correlation); var solution = request.UnsignedVoucher.WithRsaKey(Runtime.VoucherKey.PubKey).Solve(Runtime.VoucherKey); return(solution); } catch (PuzzleException) { throw new ActionResultException(BadRequest("invalid-transaction")); } }
public void BeginSignVoucher(SignVoucherRequest signVoucherRequest) { BeginSignVoucherAsync(signVoucherRequest).GetAwaiter().GetResult(); }
public Task BeginSignVoucherAsync(SignVoucherRequest signVoucherRequest) { //Will always return null return(SendAsync <PuzzleSolution>(HttpMethod.Post, signVoucherRequest, $"clientchannels/confirm")); }
public IActionResult SignVoucher([FromBody] SignVoucherRequest request) { if (request.MerkleProof.PartialMerkleTree .GetMatchedTransactions() .FirstOrDefault() != request.Transaction.GetHash() || !request.MerkleProof.Header.CheckProofOfWork()) { return(BadRequest("invalid-merkleproof")); } var transaction = request.Transaction; if (transaction.Outputs.Count > 2) { return(BadRequest("invalid-transaction")); } var cycle = Parameters.CycleGenerator.GetCycle(request.ClientEscrowInformation.Cycle); var height = Services.BlockExplorerService.GetCurrentHeight(); if (!cycle.IsInPhase(CyclePhase.ClientChannelEstablishment, height)) { return(BadRequest("incorrect-phase")); } AliceServerChannelNegotiation aliceNegotiation = new AliceServerChannelNegotiation(Parameters, Tumbler.TumblerKey, Tumbler.VoucherKey); var key = Repository.GetKey(cycle.Start, request.KeyReference); if (key.PubKey != request.TumblerEscrowPubKey) { return(BadRequest("incorrect-escrowpubkey")); } aliceNegotiation.ReceiveClientEscrowInformation(request.ClientEscrowInformation, key); try { var expectedTxOut = aliceNegotiation.BuildEscrowTxOut(); PuzzleSolution voucher; var solverServerSession = aliceNegotiation.ConfirmClientEscrow(transaction, out voucher); var confirmations = Services.BlockExplorerService.GetBlockConfirmations(request.MerkleProof.Header.GetHash()); if ((confirmations < Parameters.CycleGenerator.FirstCycle.SafetyPeriodDuration)) { return(BadRequest("not-enough-confirmation")); } Services.BlockExplorerService.Track($"Cycle {cycle.Start} Client Escrow", expectedTxOut.ScriptPubKey); if (!Services.BlockExplorerService.TrackPrunedTransaction(request.Transaction, request.MerkleProof)) { return(BadRequest("invalid-merkleproof")); } if (!Repository.MarkUsedNonce(cycle.Start, new uint160(key.PubKey.Hash.ToBytes()))) { return(BadRequest("invalid-transaction")); } Repository.Save(cycle.Start, solverServerSession); Logs.Server.LogInformation($"Cycle {cycle.Start} Proof of Escrow signed for " + transaction.GetHash()); return(Json(voucher)); } catch (PuzzleException) { return(BadRequest("invalid-transaction")); } }