public void AddRange(ChecksummedByteCollection aCollection) { if (_bytes.Count == 0) { // Is empty so just copy checksum from argument _computedIndex = aCollection._computedIndex; _checksum = aCollection.Checksum; _murMur3 = (Murmur3_x86_32Digest)aCollection._murMur3.Copy(); } _bytes.AddRange(aCollection._bytes); }
public ChecksummedByteCollection Clone() { ChecksummedByteCollection result = new ChecksummedByteCollection { _bytes = new List <byte[]>() }; result._bytes.AddRange(_bytes); result._computedIndex = _computedIndex; result._checksum = Checksum; result._murMur3 = (Murmur3_x86_32Digest)_murMur3.Copy(); return(result); }
private byte[] Compress(ChecksummedByteCollection aInputs) { byte[] result = new byte[100]; uint seed = aInputs.Checksum; Mersenne32 gen = new Mersenne32(seed); int inputCount = aInputs.Count; for (int i = 0; i < 100; i++) { byte[] source = aInputs.Get((int)(gen.NextUInt32() % inputCount)); result[i] = source[gen.NextUInt32() % source.Length]; } return(result); }
private ChecksummedByteCollection Hash(byte[] aBlockHeader, int aRound) { if ((aRound < 1) || (aRound > N)) { throw new ArgumentOutOfRangeException(string.Format("Round '{0}' must be between 0 and N inclusive", nameof(aRound))); } // NOTE: instance is destroyed by caller! ChecksummedByteCollection roundOutputs = new ChecksummedByteCollection(); Mersenne32 gen = new Mersenne32(0); byte[] roundInput; uint seed; if (aRound == 1) { seed = Checksum(aBlockHeader); gen.Initialize(seed); roundInput = aBlockHeader; } else { ChecksummedByteCollection parentOutputs; if ((aRound == N) && (aBlockHeader.Length >= 4) && (NextNonce == GetNonce(aBlockHeader)) && Arrays.AreEqual(aBlockHeader, _cachedHeader)) { // Parent (round N - 1) has already been calculated so re-use values. This saves 50% of calculations! parentOutputs = _cachedOutput; } else { // Need to calculate parent output parentOutputs = Hash(aBlockHeader, aRound - 1); } seed = parentOutputs.Checksum; gen.Initialize(seed); roundOutputs.AddRange(parentOutputs); // Determine the neighbouring nonce uint neighbourNonce = gen.NextUInt32(); byte[] neighbourNonceHeader = ChangeNonce(aBlockHeader, neighbourNonce); ChecksummedByteCollection neighbourOutputs = Hash(neighbourNonceHeader, aRound - 1); // Cache neighbour nonce n-1 calculation if on final round (neighbour will be next nonce) if (aRound == N) { _cachedNonce = neighbourNonce; _cachedHeader = neighbourNonceHeader; _cachedOutput = neighbourOutputs.Clone(); } roundOutputs.AddRange(neighbourOutputs); roundInput = Compress(roundOutputs); } Func <byte[], byte[]> hashFunc = _hashAlg[gen.NextUInt32() % 18]; byte[] output = hashFunc(roundInput); output = Expand(output, N - aRound); roundOutputs.Add(output); return(roundOutputs); }
private byte[] Hash(byte[] aBlockHeader) { ChecksummedByteCollection allOutputs = Hash(aBlockHeader, N); return(_hashAlg[0](Compress(allOutputs))); }