private static void NextAddresses(BlockFiller blockFiller, Block zeroBlock, Block inputBlock, Block addressBlock) { inputBlock.V[6]++; blockFiller.FillBlock(zeroBlock, inputBlock, addressBlock); blockFiller.FillBlock(zeroBlock, addressBlock, addressBlock); }
private void FillSegment(BlockFiller blockFiller, Position position) { var dataIndependentAddressing = IsDataIndependentAddressing(position); var startingIndex = GetStartingIndex(position); var currentOffset = position.Lane * _laneLength + position.Slice * _segmentLength + startingIndex; var prevOffset = GetPrevOffset(currentOffset); var addressBlock = Block.DefaultBlock(); var inputBlock = Block.DefaultBlock(); var zeroBlock = Block.DefaultBlock(); if (dataIndependentAddressing) { blockFiller.AddressBlock.Clear(); blockFiller.ZeroBlock.Clear(); blockFiller.InputBlock.Clear(); InitAddressBlocks(blockFiller, position, zeroBlock, inputBlock, addressBlock); } position.Index = startingIndex; while (position.Index < _segmentLength) { prevOffset = RotatePrevOffset(currentOffset, prevOffset); var pseudoRandom = GetPseudoRandom(blockFiller, position, addressBlock, inputBlock, zeroBlock, prevOffset, dataIndependentAddressing); var refLane = GetRefLane(position, pseudoRandom); var refColumn = GetRefColumn(position, pseudoRandom, refLane == position.Lane); // 2 Creating a new block var prevBlock = _memory[prevOffset]; var refBlock = _memory[_laneLength * refLane + refColumn]; var currentBlock = _memory[currentOffset]; if (IsWithXor(position)) { blockFiller.FillBlockWithXor(prevBlock, refBlock, currentBlock); } else { blockFiller.FillBlock(prevBlock, refBlock, currentBlock); } position.Index++; currentOffset++; prevOffset++; } }
private ulong GetPseudoRandom(BlockFiller blockFiller, Position position, Block addressBlock, Block inputBlock, Block zeroBlock, int prevOffset, bool dataIndependentAddressing) { if (!dataIndependentAddressing) { return(_memory[prevOffset].V[0]); } if (position.Index % ARGON2_ADDRESSES_IN_BLOCK == 0) { NextAddresses(blockFiller, zeroBlock, inputBlock, addressBlock); } return(addressBlock.V[position.Index % ARGON2_ADDRESSES_IN_BLOCK]); }
private void InitAddressBlocks(BlockFiller blockFiller, Position position, Block zeroBlock, Block inputBlock, Block addressBlock) { inputBlock.V[0] = IntToUInt64(position.Pass); inputBlock.V[1] = IntToUInt64(position.Lane); inputBlock.V[2] = IntToUInt64(position.Slice); inputBlock.V[3] = IntToUInt64(_memory.Length); inputBlock.V[4] = IntToUInt64(_parameters.Iterations); inputBlock.V[5] = IntToUInt64((int)_parameters.Type); // Don't forget to generate the first block of addresses: */ if (position.Pass == 0 && position.Slice == 0) { NextAddresses(blockFiller, zeroBlock, inputBlock, addressBlock); } }
private void DoFillMemoryBlocks() { /* // single threaded version * var filler = BlockFiller.DefaultBlockFiller(); * var position = Position.DefaultPosition(); * * var iterations = _parameters.Iterations; * var lanes = _parameters.Lanes; * * for (var idx = 0; idx < iterations; idx++) * { * for (var jdx = 0; jdx < ARGON2_SYNC_POINTS; jdx++) * { * for (var kdx = 0; kdx < lanes; kdx++) * { * position.Update(idx, kdx, jdx, 0); * FillMemoryBlocks(filler, position); * } * } * } */ // multi threaded version var iterations = _parameters.Iterations; var lanes = _parameters.Lanes; var tasks = new Task[lanes]; for (var idx = 0; idx < iterations; idx++) { for (var jdx = 0; jdx < ARGON2_SYNC_POINTS; jdx++) { for (var kdx = 0; kdx < lanes; kdx++) { var filler = BlockFiller.DefaultBlockFiller(); var position = Position.CreatePosition(idx, kdx, jdx, 0); tasks[kdx] = CreateFillMemoryBlocksTask(filler, position); tasks[kdx].Start(); } Task.WaitAll(tasks); } } }
private Task CreateFillMemoryBlocksTask(BlockFiller blockFiller, Position position) => new Task(() => FillMemoryBlocks(blockFiller, position));
private void FillMemoryBlocks(BlockFiller blockFiller, Position position) => FillSegment(blockFiller, position);