/// <inheritdoc/> public void StoreStateReference <T>( string @namespace, IImmutableSet <Address> addresses, Block <T> block) where T : IAction, new() { int hashSize = HashDigest <SHA256> .Size; byte[] hashBytes = block.Hash.ToByteArray(); byte[] indexBytes = BitConverter.GetBytes(block.Index); foreach (Address address in addresses) { string addrHex = address.ToHex(); var fileId = $"{StateRefIdPrefix}{@namespace}/{addrHex}"; if (!_db.FileStorage.Exists(fileId)) { _db.FileStorage.Upload( fileId, addrHex, new MemoryStream()); } LiteFileInfo file = _db.FileStorage.FindById(fileId); using (var temp = new MemoryStream()) { file.CopyTo(temp); temp.Seek(0, SeekOrigin.Begin); byte[] prev = temp.ToArray(); using (LiteFileStream stream = file.OpenWrite()) { stream.Write(prev, 0, prev.Length); stream.Write(hashBytes, 0, hashSize); stream.Write(indexBytes, 0, sizeof(long)); } } } }
/// <inheritdoc/> public void ForkStateReferences <T>( string srcNamespace, string destNamespace, Block <T> branchPoint, IImmutableSet <Address> addressesToStrip) where T : IAction, new() { long branchPointIndex = branchPoint.Index; List <LiteFileInfo> files = _db.FileStorage .Find($"{StateRefIdPrefix}{srcNamespace}") .ToList(); if (!files.Any() && addressesToStrip.Any()) { throw new NamespaceNotFoundException( srcNamespace, "The source namespace to be forked does not exist."); } foreach (LiteFileInfo srcFile in files) { string destId = $"{StateRefIdPrefix}{destNamespace}/{srcFile.Filename}"; _db.FileStorage.Upload( destId, srcFile.Filename, new MemoryStream()); LiteFileInfo destFile = _db.FileStorage.FindById(destId); using (LiteFileStream srcStream = srcFile.OpenRead()) using (LiteFileStream destStream = destFile.OpenWrite()) { while (srcStream.Position < srcStream.Length) { var hashBytes = new byte[HashDigest <SHA256> .Size]; var indexBytes = new byte[sizeof(long)]; srcStream.Read(hashBytes, 0, hashBytes.Length); srcStream.Read(indexBytes, 0, indexBytes.Length); long currentIndex = BitConverter.ToInt64(indexBytes, 0); if (currentIndex <= branchPointIndex) { destStream.Write(hashBytes, 0, hashBytes.Length); destStream.Write(indexBytes, 0, indexBytes.Length); } else { break; } } } if (destFile.Length == 0) { _db.FileStorage.Delete(destId); } } }