public async Task assembleBlock_should_not_create_block_with_unknown_parent()
        {
            using MergeTestBlockchain chain = await CreateBlockChain();

            IEngineRpcModule     rpc                     = CreateConsensusModule(chain);
            Keccak               notExistingHash         = TestItem.KeccakH;
            AssembleBlockRequest assembleBlockRequest    = new() { ParentHash = notExistingHash };
            ResultWrapper <BlockRequestResult?> response = await rpc.engine_assembleBlock(assembleBlockRequest);

            response.Data.Should().BeNull();
        }
        public async Task assembleBlock_should_create_block_on_top_of_genesis()
        {
            using MergeTestBlockchain chain = await CreateBlockChain();

            IEngineRpcModule     rpc                     = CreateConsensusModule(chain);
            Keccak               startingHead            = chain.BlockTree.HeadHash;
            UInt256              timestamp               = Timestamper.UnixTime.Seconds;
            AssembleBlockRequest assembleBlockRequest    = new() { ParentHash = startingHead, Timestamp = timestamp };
            ResultWrapper <BlockRequestResult?> response = await rpc.engine_assembleBlock(assembleBlockRequest);

            BlockRequestResult expected = CreateParentBlockRequestOnHead(chain.BlockTree);

            expected.GasLimit   = 4000000L;
            expected.BlockHash  = new Keccak("0xfe37027d377e75ffb161f11733d8880083378fe6236270c7a2ee1fc7efe71cfd");
            expected.LogsBloom  = Bloom.Empty;
            expected.Miner      = chain.MinerAddress;
            expected.Number     = 1;
            expected.ParentHash = startingHead;
            expected.SetTransactions(Array.Empty <Transaction>());
            expected.Timestamp = timestamp;

            response.Data.Should().BeEquivalentTo(expected);
        }
        public async Task newBlock_accepts_previously_assembled_block_multiple_times([Values(1, 3)] int times)
        {
            using MergeTestBlockchain chain = await CreateBlockChain();

            IEngineRpcModule     rpc          = CreateConsensusModule(chain);
            Keccak               startingHead = chain.BlockTree.HeadHash;
            BlockHeader          startingBestSuggestedHeader        = chain.BlockTree.BestSuggestedHeader !;
            AssembleBlockRequest assembleBlockRequest               = new() { ParentHash = startingHead };
            ResultWrapper <BlockRequestResult?> assembleBlockResult = await rpc.engine_assembleBlock(assembleBlockRequest);

            assembleBlockResult.Data !.ParentHash.Should().Be(startingHead);

            for (int i = 0; i < times; i++)
            {
                ResultWrapper <NewBlockResult> newBlockResult = await rpc.engine_newBlock(assembleBlockResult.Data !);

                newBlockResult.Data.Valid.Should().BeTrue();
            }

            Keccak bestSuggestedHeaderHash = chain.BlockTree.BestSuggestedHeader !.Hash !;

            bestSuggestedHeaderHash.Should().Be(assembleBlockResult.Data !.BlockHash);
            bestSuggestedHeaderHash.Should().NotBe(startingBestSuggestedHeader !.Hash !);
        }