public void TestProofOfWork() { // This params accepts any difficulty target. var @params = NetworkParameters.UnitTests(); var block = new Block(@params, _blockBytes); block.Nonce = 12346; try { block.Verify(); Assert.Fail(); } catch (VerificationException) { // Expected. } // Blocks contain their own difficulty target. The BlockChain verification mechanism is what stops real blocks // from containing artificially weak difficulties. block.TargetDifficulty = Block.EasiestDifficultyTarget; // Now it should pass. block.Verify(); // Break the nonce again at the lower difficulty level so we can try solving for it. block.Nonce = 1; try { block.Verify(); Assert.Fail(); } catch (VerificationException) { // Expected to fail as the nonce is no longer correct. } // Should find an acceptable nonce. block.Solve(); block.Verify(); Assert.AreEqual(block.Nonce, 2U); }
/// <summary> /// Returns a solved block that builds on top of this one. This exists for unit tests. /// </summary> internal Block CreateNextBlock(Address toAddress, uint time) { var block = new Block(NetworkParameters) {TargetDifficulty = _targetDifficulty}; block.AddCoinbaseTransaction(EmptyBytes); // Add a transaction paying 50 coins to the "to" address. var transaction = new Transaction(NetworkParameters); transaction.AddOutput(new TransactionOutput(NetworkParameters, transaction, Utils.ToNanoCoins(50, 0), toAddress)); // The input does not really need to be a valid signature, as long as it has the right general form. var input = new TransactionInput(NetworkParameters, transaction, Script.CreateInputScript(EmptyBytes, EmptyBytes)); // Importantly the outpoint hash cannot be zero as that's how we detect a coinbase transaction in isolation // but it must be unique to avoid 'different' transactions looking the same. var counter = new byte[32]; counter[0] = (byte) _transactionCounter++; input.Outpoint.Hash = new Sha256Hash(counter); transaction.AddInput(input); block.AddTransaction(transaction); block.PreviousBlockHash = Hash; block.TimeSeconds = time; block.Solve(); block.VerifyHeader(); return block; }