public ProofDTO(Proof proof) { ApplicationName = proof.ApplicationName; LogName = proof.LogName; SnapshotValue = proof.SnapshotValue; ProofBlobName = proof.ProofBlobName; CoinbaseTransactionID = proof.CoinbaseTransactionID; TimeBlock = proof.TimeBlock; BitcoinTransactionHash = proof.BitcoinTransactionHash; BitcoinBlockNumber = proof.BitcoinBlockNumber; }
private void ProcessQueueMessages(List<CloudQueueMessage> msgs) { Trace.TraceInformation("WorkerB (RoleInstance {0}: ProcessQueueMessages start", GetRoleInstance()); HashTree hashTree = new HashTree(new SHA256Aggregator()); List<Tuple<CloudQueueMessage, Snapshot>> goodMsgs = new List<Tuple<CloudQueueMessage, Snapshot>>(); foreach (CloudQueueMessage msg in msgs) { // Log and delete if this is a "poison" queue message (repeatedly processed // and always causes an error that prevents processing from completing). // Production applications should move the "poison" message to a "dead message" // queue for analysis rather than deleting the message. if (msg.DequeueCount > 5) { Trace.TraceError( "Deleting poison message: message {0} Role Instance {1}.", msg.ToString(), GetRoleInstance() ); snapshotsQueue.DeleteMessage(msg); continue; } // Parse summarized snapshot retrieved from queue. string[] snapshotParts = msg.AsString.Split(new char[] { ',' }); string partitionKey = snapshotParts[0]; string rowKey = snapshotParts[1]; string restartFlag = snapshotParts[2]; var retrieveOperation = TableOperation.Retrieve<Snapshot>(partitionKey, rowKey); var retrievedResult = snapshotsTable.Execute(retrieveOperation); var snapshot = retrievedResult.Result as Snapshot; if (snapshot == null) { Trace.TraceError("WorkerB: Snapshot does not exist for RK {0}", rowKey); continue; } // If this is a restart, verify that the shapshot has not already been logged if (restartFlag == "1") { /*if (snapshot.Status == "Complete") { }*/ } // Add snapshot value into history tree hashTree.Append(snapshot.SnapshotValue); goodMsgs.Add(new Tuple<CloudQueueMessage, Snapshot>(msg, snapshot)); } // Snapshot commitment into bitcoin Transaction transaction = SnapshotCommitmentIntoBitcoin( hashTree.RootCommitmentString ); if (transaction == null) { Trace.TraceError("Snapshot into Bitcoin failed, unable to continue."); return; } for (int i = 0; i < goodMsgs.Count; ++i) { Snapshot snapshot = goodMsgs[i].Item2; string proofText = hashTree.GenerateMembershipProof(i).ToString(); // Save proof string proofName = snapshot.RowKey + ".proof"; SaveBlob(proofName, proofText); var proof = new Proof { ApplicationName = snapshot.ApplicationName, // Sets partition key RowKey = snapshot.RowKey, LogName = snapshot.LogName, SnapshotValue = snapshot.SnapshotValue, ProofBlobName = proofName, CoinbaseTransactionID = transaction.ID }; // Save in archive var upsertOperation = TableOperation.InsertOrReplace(proof); proofsArchiveTable.Execute(upsertOperation); // TODO: Decide if need to mark as complete var deleteOperation = TableOperation.Delete(snapshot); snapshotsTable.Execute(deleteOperation); // Delete the associated queue message snapshotsQueue.DeleteMessage(goodMsgs[i].Item1); } Trace.TraceInformation("WorkerB (RoleInstance {0}: ProcessQueueMessages complete", GetRoleInstance() ); }
public ActionResult Audit(Proof proof) { ViewData["BlobURL"] = blobContainer.Uri.AbsoluteUri; ViewBag.ApplicationName = proof.ApplicationName; ViewBag.LogName = proof.LogName; ViewBag.LatestBlockNumber = BlockchainAPI.GetLatestBlock().BlockHeight; if (ModelState.IsValid) { DateTime dt; DateTime.TryParse(proof.TimeBlock, out dt); // Validate Query if (string.IsNullOrWhiteSpace(proof.ApplicationName)) { return View("Proofs", model:new List<Proof>()); } else if (string.IsNullOrWhiteSpace(proof.LogName)) { return View("Proofs", model:new List<Proof>()); } else if (dt.Ticks <= 0) { dt = DateTime.Now; } Subscription subscriber = FindSubscription(proof.ApplicationName, proof.LogName); if (subscriber == null) { return View("Proofs", model: new List<Proof>()); } else if (subscriber.Verified != true) { return View("Proofs", model: new List<Proof>()); } TableRequestOptions reqOptions = new TableRequestOptions() { MaximumExecutionTime = TimeSpan.FromSeconds(10), RetryPolicy = new LinearRetry(TimeSpan.FromSeconds(3), 3) }; List<Proof> proofs; try { Snapshot snapshot = new Snapshot() { ApplicationName = proof.ApplicationName, LogName = proof.LogName, TimeBlock = dt }; var tableQuery = new TableQuery<Proof>().Where( TableQuery.CombineFilters( TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, proof.ApplicationName), TableOperators.And, TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.LessThanOrEqual, snapshot.RowKey) ), TableOperators.And, TableQuery.GenerateFilterCondition("LogName", QueryComparisons.Equal, proof.LogName) ) ); proofs = proofsArchiveTable.ExecuteQuery(tableQuery, reqOptions).ToList(); if (proofs.Count == 0) { return View("Proofs", model: new List<Proof>()); } Proof proofToAudit = null; long maxTicks = 0; foreach (Proof singleProof in proofs) { long ticks = DateTime.Parse(singleProof.TimeBlock).Ticks; if (ticks > maxTicks) { maxTicks = ticks; proofToAudit = singleProof; } } // // TODO: Make API Call, Update Database! // if (proofToAudit.BitcoinBlockNumber == null || proofToAudit.BitcoinTransactionHash == null) { if (PopulateBitcoinInformation(proofToAudit)) { var replaceOperation = TableOperation.Replace(proofToAudit); proofsArchiveTable.Execute(replaceOperation); } } return View("Proofs", model: new List<Proof>() { proofToAudit }); } catch (StorageException se) { ViewBag.errorMessage = "Timeout error, try again."; Trace.TraceError(se.Message); return View("Error: " + se.Message); } } return View("Proofs", model: new List<Proof>()); }
private bool PopulateBitcoinInformation(Proof proof) { APIKey apiKey = new APIKey(RoleEnvironment.GetConfigurationSettingValue( "CoinbaseAccountKey1" )); Transaction coinbaseTransaction = API.GetTransaction(proof.CoinbaseTransactionID, apiKey); if (coinbaseTransaction.Hash != null) { proof.BitcoinTransactionHash = coinbaseTransaction.Hash; BitcoinTransaction bitcoinTransaction = BlockchainAPI.GetTransaction(coinbaseTransaction.Hash); if (bitcoinTransaction.BlockHeight > 0) { proof.BitcoinBlockNumber = bitcoinTransaction.BlockHeight; return true; } } return false; }