// 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 CheckCommitmentBroadcast() { using (OffchainMonitorContext context = new OffchainMonitorContext()) { var commitmentsToSearchFor = (from c in context.Commitments where c.Punished == false select c).ToArray(); if (commitmentsToSearchFor.Count() > 0) { for (int i = 0; i < commitmentsToSearchFor.Count(); i++) { var c = commitmentsToSearchFor[i]; bool found = false; try { await rpcBitcoinClient.GetTransactionHex(c.CommitmentTxId); found = true; } catch (RPCException exp) { if (!exp.Message.Contains("No such mempool or blockchain transaction.")) { throw exp; } else { continue; } } catch (Exception exp) { throw exp; } if (found) { try { await rpcBitcoinClient.BroadcastTransaction(new Transaction(c.Punishment), new Guid()); c.Punished = true; } catch (Exception exp) { throw exp; } } } } await context.SaveChangesAsync(); } }
public async Task <IActionResult> AddCommitmentPunishmentPair([FromQuery] string commitment, [FromQuery] string punishment, [FromQuery] bool overwrite = false) { if (string.IsNullOrEmpty(commitment) || string.IsNullOrEmpty(punishment)) { return(BadRequest("Passed parameters should not be null or empty")); } else { try { Transaction cTx = new Transaction(commitment); Transaction pTx = new Transaction(punishment); using (OffchainMonitorContext context = new OffchainMonitorContext()) { var matchedCommitment = (from c in context.Commitments where c.CommitmentTxId == cTx.GetHash().ToString() select c).FirstOrDefault(); if (matchedCommitment != null) { if (overwrite == false) { return(BadRequest("To overwrite an existing punishment for existing commitment id, the overwrite flag should bet set to true")); } else { matchedCommitment.Commitment = commitment; matchedCommitment.Punishment = punishment; } } else { var newlyAddedCommitment = new CommitmentEntity { Commitment = commitment, CommitmentTxId = cTx.GetHash().ToString(), Punishment = punishment }; await context.Commitments.AddAsync(newlyAddedCommitment); } await context.SaveChangesAsync(); } } catch (Exception exp) { throw exp; } return(Ok()); } }
public async Task Set <T>(string key, T value) { using (OffchainMonitorContext context = new OffchainMonitorContext()) { var settingRecords = from record in context.Settings where record.Key == key select record; if (settingRecords.Count() > 0) { context.Settings.RemoveRange(settingRecords); } context.Settings.Add(new SettingsEntity { Key = key.ToString(), Value = value.ToString() }); await context.SaveChangesAsync(); } }
public async Task <IActionResult> SetSettingsValue([FromQuery] string key, [FromQuery] string value) { key = key.Trim(); if (string.IsNullOrEmpty(key)) { return(BadRequest("Key should not be null or empty.")); } if (string.IsNullOrEmpty(value)) { return(BadRequest("Value should not be null or empty.")); } if (key.ToLower() == "multisig") { BitcoinAddress address = null; try { address = BitcoinAddress.Create(value); } catch (Exception exp) { throw new Exception("Some problem in parsing the provided address.", exp); } } using (OffchainMonitorContext context = new OffchainMonitorContext()) { var settingRecords = from record in context.Settings where record.Key == key.ToLower() select record; if (settingRecords.Count() > 0) { context.Settings.RemoveRange(settingRecords); } context.Settings.Add(new SettingsEntity { Key = key, Value = value }); await context.SaveChangesAsync(); } return(Ok()); }
/* * private readonly INoSQLTableStorage<LogEntity> _tableStorageError; * private readonly INoSQLTableStorage<LogEntity> _tableStorageWarning; * private readonly INoSQLTableStorage<LogEntity> _tableStorageInfo; * * public LogToTable(INoSQLTableStorage<LogEntity> tableStorageError, INoSQLTableStorage<LogEntity> tableStorageWarning, INoSQLTableStorage<LogEntity> tableStorageInfo) * { * _tableStorageError = tableStorageError; * _tableStorageInfo = tableStorageInfo; * _tableStorageWarning = tableStorageWarning; * } */ private async Task Insert(string level, string component, string process, string context, string type, string stack, string msg, DateTime?dateTime) { var dt = dateTime ?? DateTime.UtcNow; var newEntity = new LogEntity { Level = level, Component = component, Context = context, DateTime = dt, Msg = msg, Process = process, Stack = stack, Type = type }; using (OffchainMonitorContext dbContext = new OffchainMonitorContext()) { dbContext.Add(newEntity); } }
public async Task <IActionResult> ListMonitoredCommitments([FromQuery] int from, [FromQuery] int to) { if (from < 0) { return(BadRequest("From should not be negative.")); } if (to != -1 && to <= from) { return(BadRequest("To should be bigger than from")); } try { using (OffchainMonitorContext context = new OffchainMonitorContext()) { var records = (from record in context.Commitments select new { CommtmentTxId = record.CommitmentTxId, Commitment = record.Commitment, Punishment = record.Punishment, Punished = record.Punished }).Skip(from); if (to != -1) { records = records.Take(to - from); } if (records.Count() > 0) { return(Json(records.ToList())); } else { return(BadRequest("No records to return.")); } } } catch (Exception exp) { throw exp; } }
public async Task <IActionResult> GetSettingsValue([FromQuery] string key) { key = key.Trim(); if (string.IsNullOrEmpty(key)) { return(BadRequest("Key should not be null or empty.")); } using (OffchainMonitorContext context = new OffchainMonitorContext()) { var settingRecord = (from record in context.Settings where record.Key == key select record) .FirstOrDefault(); if (settingRecord == null) { return(BadRequest("Could not find a record for settings")); } else { return(Ok(settingRecord.Value)); } } }
// ToDo: Use the DbContext from the caller public async Task <T> Get <T>(string key) { using (OffchainMonitorContext context = new OffchainMonitorContext()) { var settingRecords = await(from record in context.Settings where record.Key == key select record) .FirstOrDefaultAsync(); if (settingRecords == null) { throw new Exception("The specified settings was not found."); } else { if (typeof(T) == typeof(string)) { return((T)(object)settingRecords.Value); } else { return(default(T)); } } } }
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; } } }