public static async Task <Tuple <bool, string> > TryWriteMerkleNodeAsync(this ICampfireNetObjectStore store, string ns, MerkleNode node) { using (var ms = new MemoryStream()) { using (var writer = new BinaryWriter(ms, Encoding.UTF8, true)) { writer.WriteMerkleNode(node); } var objectData = ms.GetBuffer(); var length = (int)ms.Position; var hash = CampfireNetHash.ComputeSha256Base64(objectData, 0, length); var isNewlyWritten = await store.TryWriteUniqueAsync(ns, hash, objectData).ConfigureAwait(false); // var copy = await ReadMerkleNodeAsync(store, ns, hash).ConfigureAwait(false); // if (copy.TypeTag != node.TypeTag || copy.LeftHash != node.LeftHash || copy.RightHash != node.RightHash || copy.Descendents != node.Descendents) { // throw new InvalidStateException(); // } return(Tuple.Create(isNewlyWritten, hash)); } }
private async Task <string> InsertHelperAsyncUnderTreeLock(string replaceeHash, MerkleNode replaceeNode, string inserteeHash) { var rightHash = replaceeNode.RightHash; var rightNode = await objectStore.ReadMerkleNodeAsync(NetworkDataNamespace, rightHash).ConfigureAwait(false); var rightwardDescendents = rightNode == null ? 0 : (1 + rightNode.Descendents); var isReplaceePerfect = replaceeNode.Descendents == rightwardDescendents * 2; if (isReplaceePerfect) { var internalNode = new MerkleNode { TypeTag = MerkleNodeTypeTag.Node, LeftHash = replaceeHash, RightHash = inserteeHash, Descendents = 2 + replaceeNode.Descendents }; var internalNodeHash = (await objectStore.TryWriteMerkleNodeAsync(NetworkDataNamespace, internalNode).ConfigureAwait(false)).Item2; await objectStore.TryWriteUniqueAsync(TreeContainmentNamespace, internalNodeHash, new byte[0]).ConfigureAwait(false); return(internalNodeHash); } var rightReplacementHash = await InsertHelperAsyncUnderTreeLock(rightHash, rightNode, inserteeHash).ConfigureAwait(false); replaceeNode.Descendents += 2; // leaf and inner node replaceeNode.RightHash = rightReplacementHash; var newReplaceeNodeHash = (await objectStore.TryWriteMerkleNodeAsync(NetworkDataNamespace, replaceeNode).ConfigureAwait(false)).Item2; await objectStore.TryWriteUniqueAsync(TreeContainmentNamespace, newReplaceeNodeHash, new byte[0]).ConfigureAwait(false); return(newReplaceeNodeHash); }