// ToDo: The finding of transaction in DB will probably has a better algorithm // The following one by one version is the preliminary design private async Task <Transaction> FindThePunishment(BalanceOperation op, MultisigOutputEntity output) { using (OffchainMonitorContext context = new OffchainMonitorContext()) { var commitments = from c in context.Commitments where c.CommitmentOutput.TransactionId == output.TransactionId && c.CommitmentOutput.OutputNumber == output.OutputNumber select c; if (commitments != null && commitments.Count() > 0) { foreach (var c in commitments) { if (TransactionsMatch(c, op)) { return(new Transaction(c.Punishment)); } } } else { // No commitment cosuming the specified output return(null); } // No commitment found matching the specified transaction, spending multisig output return(null); } }
public async Task CheckCommitmentBroadcastOld() { string multisig = null; Network network = Network.TestNet; try { multisig = await settingsRepository.Get <string>("multisig"); network = await Helper.GetNetwork(settingsRepository); } catch (Exception exp) { return; } var outputs = await qBitNinjaApiCaller.GetAddressBalance(multisig, true, true); MultisigOutputEntity desiredOutput = null; using (OffchainMonitorContext context = new OffchainMonitorContext()) { desiredOutput = (from o in context.MultisigOutputs orderby o.LastSeen ascending select o).FirstOrDefault(); } if (desiredOutput == null) { // There is no commitment return; } else { foreach (var op in outputs.Operations) { var found = op.ReceivedCoins.Where(o => o.Outpoint.Hash.ToString() == desiredOutput.TransactionId && o.Outpoint.N == desiredOutput.OutputNumber).Any(); if (found) { // The output is still unspent which means no commitments is spent return; } } } // The output has not been found, which means it has been spent by a commitment outputs = await qBitNinjaApiCaller.GetAddressBalance(multisig, true, false); foreach (var op in outputs.Operations) { bool found = op.SpentCoins. Where(sc => sc.Outpoint.Hash.ToString() == desiredOutput.TransactionId && sc.Outpoint.N == desiredOutput.OutputNumber).Any(); if (found) { var respectivePunishment = await FindThePunishment(op, desiredOutput); if (respectivePunishment != null) { await rpcBitcoinClient.BroadcastTransaction(respectivePunishment, new Guid()); } else { // The punishment has not been found } } } }
public async Task <IActionResult> AddCommitmentPunishmentPairOldDesign([FromQuery] string commitment, [FromQuery] string punishment) { if (string.IsNullOrEmpty(commitment) || string.IsNullOrEmpty(punishment)) { return(BadRequest("Passed parameters should not be null or empty")); } else { Transaction cTx = new Transaction(commitment); Transaction pTx = new Transaction(punishment); try { using (OffchainMonitorContext context = new OffchainMonitorContext()) { var newlyAddedCommitment = new CommitmentEntity { Commitment = commitment, Punishment = punishment }; bool found = false; var multisig = await settingsRepository.Get <string>("multisig"); var netwok = await Helper.GetNetwork(settingsRepository); for (int i = 0; i < cTx.Inputs.Count; i++) { var prevHash = cTx.Inputs[i].PrevOut.Hash.ToString(); var prevTx = await bitcoinTransactionService.GetTransaction(prevHash); var prevOut = cTx.Inputs[i].PrevOut; if (prevTx.Outputs[prevOut.N].ScriptPubKey.GetDestinationAddress(netwok).ToString() == multisig) { found = true; var existingMultisigOutput = (from o in context.MultisigOutputs where o.TransactionId == prevOut.Hash.ToString() && o.OutputNumber == prevOut.N select o).FirstOrDefault(); if (existingMultisigOutput == null) { var newMultisigOutput = new MultisigOutputEntity(); newMultisigOutput.TransactionId = prevOut.Hash.ToString(); newMultisigOutput.OutputNumber = (int)prevOut.N; newMultisigOutput.LastSeen = DateTime.UtcNow; await context.MultisigOutputs.AddAsync(newMultisigOutput); existingMultisigOutput = newMultisigOutput; } existingMultisigOutput.LastSeen = DateTime.UtcNow; existingMultisigOutput.Commitments.Add(newlyAddedCommitment); newlyAddedCommitment.CommitmentOutput = existingMultisigOutput; await context.Commitments.AddAsync(newlyAddedCommitment); } } if (!found) { return(BadRequest(string.Format("The provide transaction does not pay to multisig:{0}", multisig))); } await context.SaveChangesAsync(); } return(Ok()); } catch (Exception exp) { throw exp; } } }