Revision 6e25cc48 trunk/Pithos.Network/Signature.cs
b/trunk/Pithos.Network/Signature.cs | ||
---|---|---|
159 | 159 |
return finalHash; |
160 | 160 |
} |
161 | 161 |
}*/ |
162 |
|
|
163 |
public static byte[] CalculateTopHash(IEnumerable<byte[]> hashMap, string algorithm)
|
|
162 |
|
|
163 |
public static byte[] CalculateTopHash(IList<byte[]> hashMap, string algorithm)
|
|
164 | 164 |
{ |
165 | 165 |
if (hashMap == null) |
166 | 166 |
throw new ArgumentNullException("hashMap"); |
167 | 167 |
if (String.IsNullOrWhiteSpace(algorithm)) |
168 | 168 |
throw new ArgumentNullException("algorithm"); |
169 |
Contract.EndContractBlock(); |
|
169 |
Contract.EndContractBlock();
|
|
170 | 170 |
|
171 |
var hashCount = hashMap.Count(); |
|
171 |
var hashCount = hashMap.Count; |
|
172 |
//The tophash of an empty hashmap is an empty array |
|
172 | 173 |
if (hashCount == 0) |
173 |
return null; |
|
174 |
return new byte[0]; |
|
175 |
//The tophash of a one-item hashmap is the hash itself |
|
174 | 176 |
if (hashCount == 1) |
175 |
return hashMap.First();
|
|
177 |
return hashMap[0];
|
|
176 | 178 |
|
177 |
var newHashes=new List<byte[]>();
|
|
179 |
//Calculate the required number of leaf nodes
|
|
178 | 180 |
var leafs =(int)Math.Pow(2, Math.Ceiling(Math.Log(hashCount,2))); |
179 |
for (int i = 0; i < leafs;i+=2 ) |
|
180 |
{ |
|
181 |
using (var hasher = HashAlgorithm.Create(algorithm)) |
|
181 |
//The size of all nodes is the same and equal to the size of the input hashes |
|
182 |
var hashSize = hashMap[0].Length; |
|
183 |
|
|
184 |
//If the hashmap containes fewer nodes than the required leaf count, we need to fill |
|
185 |
//the rest with empty blocks |
|
186 |
byte[] empty=null; |
|
187 |
if (hashCount < leafs) |
|
188 |
empty = new byte[hashSize]; |
|
189 |
|
|
190 |
//New hashes will be stored in a dictionary keyed by their step to preserve order |
|
191 |
var newHashes=new ConcurrentDictionary<int, byte[]>(); |
|
192 |
|
|
193 |
Parallel.For(0, leafs/2, |
|
194 |
(step, state) => |
|
182 | 195 |
{ |
183 |
var block1 = i >hashCount - 1 ? new byte[hashMap.First().Length] : hashMap.ElementAt(i); |
|
184 |
var block2 = i>hashCount-2 ? new byte[block1.Length] : hashMap.ElementAt(i+1); |
|
185 |
|
|
196 |
using (var hasher = HashAlgorithm.Create(algorithm)) |
|
197 |
{ |
|
198 |
var i = step*2; |
|
199 |
var block1 = i <= hashCount - 1 ? hashMap[i] : empty; |
|
200 |
var block2 = i <= hashCount - 2 ? hashMap[i + 1] : empty; |
|
201 |
|
|
202 |
hasher.TransformBlock(block1, 0, block1.Length, null, 0); |
|
203 |
hasher.TransformFinalBlock(block2, 0, block2.Length); |
|
204 |
|
|
205 |
var finalHash = hasher.Hash; |
|
206 |
//Store the final value in its proper place |
|
207 |
newHashes[step] = finalHash; |
|
208 |
} |
|
209 |
}); |
|
210 |
/* |
|
211 |
Parallel.For(0, leafs/2, |
|
212 |
() => HashAlgorithm.Create(algorithm), |
|
213 |
(step, state, hasher) => |
|
214 |
{ |
|
215 |
|
|
216 |
var i = step*2; |
|
217 |
var block1 = i <= hashCount - 1 ? hashMap[i]: empty; |
|
218 |
var block2 = i <= hashCount - 2 ? hashMap[i + 1] : empty; |
|
219 |
|
|
186 | 220 |
hasher.TransformBlock(block1, 0, block1.Length, null, 0); |
187 |
hasher.TransformFinalBlock(block2, 0, block2.Length); |
|
221 |
hasher.TransformFinalBlock(block2, 0, block2.Length); |
|
222 |
|
|
188 | 223 |
var finalHash = hasher.Hash; |
189 |
newHashes.Add(finalHash); |
|
190 |
} |
|
191 |
} |
|
192 |
return CalculateTopHash(newHashes, algorithm); |
|
224 |
//Store the final value in its proper place |
|
225 |
newHashes[step] = finalHash; |
|
226 |
|
|
227 |
return hasher; |
|
228 |
}, |
|
229 |
hasher => hasher.Dispose()); |
|
230 |
*/ |
|
231 |
//Extract the hashes to a list ordered by their step |
|
232 |
var hashes = newHashes.OrderBy(pair => pair.Key).Select(pair => pair.Value).ToList(); |
|
233 |
return CalculateTopHash(hashes, algorithm); |
|
193 | 234 |
} |
194 | 235 |
|
195 | 236 |
|
196 | 237 |
|
197 |
public static string CalculateTopHash(string hashString, string algorithm) |
|
238 |
/* public static string CalculateTopHash(string hashString, string algorithm)
|
|
198 | 239 |
{ |
199 | 240 |
if (String.IsNullOrWhiteSpace(algorithm)) |
200 | 241 |
throw new ArgumentNullException("algorithm"); |
... | ... | |
208 | 249 |
var hash=hasher.ComputeHash(bytes); |
209 | 250 |
return hash.ToHashString(); |
210 | 251 |
} |
211 |
} |
|
252 |
}*/
|
|
212 | 253 |
|
213 | 254 |
private static Task<ConcurrentDictionary<int, byte[]>> CalculateBlockHashesAsync(FileStream stream, int blockSize, string algorithm, ConcurrentDictionary<int, byte[]> hashes, int index = 0) |
214 | 255 |
{ |
Also available in: Unified diff