private async Task <LedgerAnchor> ComputeNewAnchor(LedgerAnchor lastAnchor) { IReadOnlyList <ByteString> newTransactions; byte[] currentHash; if (lastAnchor != null) { newTransactions = await storageEngine.GetTransactions(lastAnchor.Position); currentHash = lastAnchor.FullStoreHash.ToByteArray(); } else { newTransactions = await storageEngine.GetTransactions(null); currentHash = new byte[32]; } if (newTransactions.Count == 0) { return(null); } byte[] position = currentHash; byte[] buffer = new byte[64]; using (SHA256 sha = SHA256.Create()) { foreach (ByteString rawTransaction in newTransactions) { currentHash.CopyTo(buffer, 0); position = MessageSerializer.ComputeHash(rawTransaction.ToByteArray()); position.CopyTo(buffer, 32); currentHash = sha.ComputeHash(sha.ComputeHash(buffer)); } } LedgerAnchor result = new LedgerAnchor( new ByteString(position), new ByteString(currentHash), newTransactions.Count + (lastAnchor != null ? lastAnchor.TransactionCount : 0)); return(result); }
/// <summary> /// Determines whether a new anchor should be calculated and recorded, /// and does it if it is the case. /// </summary> /// <returns>The task object representing the asynchronous operation.</returns> public async Task <LedgerAnchor> RecordAnchor() { if (await anchorRecorder.CanRecordAnchor()) { LedgerAnchor anchor = await anchorState.GetLastAnchor(); LedgerAnchor latestAnchor = await ComputeNewAnchor(anchor); if (latestAnchor != null) { // Record the anchor await anchorRecorder.RecordAnchor(latestAnchor); // Commit the anchor if it has been recorded successfully await anchorState.CommitAnchor(latestAnchor); return(latestAnchor); } } return(null); }