Beispiel #1
0
 public void Remove(MerkleTreeSection merkleTreeSection)
 {
     lock (_lockObject)
     {
         _map.Remove(merkleTreeSection);
     }
 }
Beispiel #2
0
 public void Add(MerkleTreeSection merkleTreeSection)
 {
     lock (_lockObject)
     {
         _map[merkleTreeSection] = new MerkleTreeSectionManager(merkleTreeSection);
     }
 }
Beispiel #3
0
 public int GetCount(MerkleTreeSection merkleTreeSection, bool state)
 {
     lock (_lockObject)
     {
         if (_map.TryGetValue(merkleTreeSection, out var merkleTreeSectionManager))
         {
             return(merkleTreeSectionManager.GetCount(state));
         }
         else
         {
             if (state)
             {
                 return(0);
             }
             else
             {
                 return(merkleTreeSection.Hashes.Count);
             }
         }
     }
 }
Beispiel #4
0
 public IEnumerable <OmniHash> GetOmniHashes(MerkleTreeSection merkleTreeSection, bool state)
 {
     lock (_lockObject)
     {
         if (_map.TryGetValue(merkleTreeSection, out var merkleTreeSectionManager))
         {
             return(merkleTreeSectionManager.GetHashes(state));
         }
         else
         {
             if (state)
             {
                 return(Enumerable.Empty <OmniHash>());
             }
             else
             {
                 return(merkleTreeSection.Hashes);
             }
         }
     }
 }
Beispiel #5
0
            public MerkleTreeSectionManager(MerkleTreeSection merkleTreeSection)
            {
                _bloomFilter = new BloomFilter <OmniHash>(256, 0.001, (n) => n.GetHashCode());

                _dic = new Dictionary <OmniHash, State>();

                foreach (var key in merkleTreeSection.Hashes)
                {
                    _bloomFilter.Add(key);

                    State info;

                    if (!_dic.TryGetValue(key, out info))
                    {
                        info           = new State();
                        info.IsEnabled = false;
                        info.Count     = 0;

                        _dic.Add(key, info);
                    }

                    info.Count++;
                }
            }
Beispiel #6
0
        public async ValueTask <OmniHash[]> ParityDecode(MerkleTreeSection merkleTreeSection, CancellationToken token = default)
        {
            return(await Task.Run(async() =>
            {
                if (merkleTreeSection.CorrectionAlgorithmType == CorrectionAlgorithmType.ReedSolomon8)
                {
                    // 実ブロック数
                    int informationCount = merkleTreeSection.Hashes.Count - 128;

                    // デコード可能かチェックする
                    if (merkleTreeSection.Hashes.Count(n => this.Contains(n)) < informationCount)
                    {
                        throw new ParityDecodeFailed();
                    }

                    // デコードする必要がない場合
                    if (merkleTreeSection.Hashes.Take(informationCount).All(n => this.Contains(n)))
                    {
                        return merkleTreeSection.Hashes.Take(informationCount).ToArray();
                    }

                    // 最大ブロック長
                    uint blockLength = merkleTreeSection.Hashes.Max(n => this.GetLength(n));

                    var memoryOwners = new List <IMemoryOwner <byte> >();

                    try
                    {
                        var targetBuffers = new Memory <byte> [128];
                        var indexes = new int[128];

                        // Load
                        {
                            int count = 0;
                            int index = 0;
                            int position = 0;

                            for (; index < informationCount && count < informationCount; index++, position++)
                            {
                                token.ThrowIfCancellationRequested();

                                if (!this.TryGetBlock(merkleTreeSection.Hashes[position], out var blockMemoryOwner))
                                {
                                    continue;
                                }

                                // 実ブロックの長さが足りない場合、0byteでpaddingを行う
                                if (blockMemoryOwner.Memory.Length < blockLength)
                                {
                                    var tempMemoryOwner = _bufferPool.Rent((int)blockLength);

                                    BytesOperations.Copy(blockMemoryOwner.Memory.Span, tempMemoryOwner.Memory.Span, blockMemoryOwner.Memory.Length);
                                    BytesOperations.Zero(tempMemoryOwner.Memory.Span.Slice(blockMemoryOwner.Memory.Length));

                                    blockMemoryOwner.Dispose();
                                    blockMemoryOwner = tempMemoryOwner;
                                }

                                memoryOwners.Add(blockMemoryOwner);

                                indexes[count] = index;
                                targetBuffers[count] = blockMemoryOwner.Memory;

                                count++;
                            }

                            // 実ブロック数が128に満たない場合、0byte配列でPaddingを行う。
                            for (; index < 128 && count < informationCount; index++)
                            {
                                token.ThrowIfCancellationRequested();

                                var tempMemoryOwner = _bufferPool.Rent((int)blockLength);

                                BytesOperations.Zero(tempMemoryOwner.Memory.Span);

                                memoryOwners.Add(tempMemoryOwner);

                                indexes[count] = index;
                                targetBuffers[count] = tempMemoryOwner.Memory;

                                count++;
                            }

                            for (; index < 256 && count < informationCount; index++, position++)
                            {
                                token.ThrowIfCancellationRequested();

                                if (!this.TryGetBlock(merkleTreeSection.Hashes[position], out var blockMemoryOwner))
                                {
                                    continue;
                                }

                                memoryOwners.Add(blockMemoryOwner);

                                indexes[count] = index;
                                targetBuffers[count] = blockMemoryOwner.Memory;

                                count++;
                            }

                            if (count < informationCount)
                            {
                                throw new BlockNotFoundException();
                            }
                        }

                        var reedSolomon = new ReedSolomon8(informationCount, _threadCount, _bufferPool);
                        await reedSolomon.Decode(targetBuffers, indexes, (int)blockLength, informationCount * 2, token);

                        // Set
                        {
                            ulong length = merkleTreeSection.Length;

                            for (int i = 0; i < informationCount; length -= blockLength, i++)
                            {
                                bool result = _blockStorage.TrySet(merkleTreeSection.Hashes[i], memoryOwners[i].Memory.Span.Slice(0, (int)Math.Min(length, blockLength)));

                                if (!result)
                                {
                                    throw new ParityDecodeFailed("Failed to save Block.");
                                }
                            }
                        }
                    }
                    finally
                    {
                        foreach (var memoryOwner in memoryOwners)
                        {
                            memoryOwner.Dispose();
                        }
                    }

                    return merkleTreeSection.Hashes.Take(informationCount).ToArray();
                }
                else
                {
                    throw new NotSupportedException();
                }
            }));
        }