public static void ClaimPreloadGas(NeoSystem system, Neo.Wallets.Wallet wallet, Random random)
        {
            void SubmitTransaction(Func <Snapshot, WalletAccount, Transaction?> factory)
            {
                using var snapshot = Blockchain.Singleton.GetSnapshot();
                var validators = snapshot.GetValidators();

                if (validators.Length != 1)
                {
                    throw new InvalidOperationException("Preload only supported for single-node blockchains");
                }

                var account = wallet.GetAccounts().Single(a => a.Contract.Script.IsMultiSigContract());

                var tx = factory(snapshot, account);

                if (tx == null)
                {
                    throw new Exception("Attempted to submit null preload transaction");
                }
                var context = new ContractParametersContext(tx);

                wallet.Sign(context);
                if (!context.Completed)
                {
                    throw new InvalidOperationException("could not complete signing of preload transaction");
                }

                var block  = CreatePreloadBlock(wallet, random, tx);
                var result = system.Blockchain.Ask <RelayResultReason>(block).Result;

                if (result != RelayResultReason.Succeed)
                {
                    throw new Exception($"Preload {tx.Type} transaction failed {result}");
                }
            }

            SubmitTransaction((snapshot, account) => NodeUtility.MakeTransferTransaction(snapshot,
                                                                                         ImmutableHashSet.Create(account.ScriptHash), account.ScriptHash, Blockchain.GoverningToken.Hash, null));

            // There needs to be least one block after the transfer transaction before submitting a GAS claim
            var block  = CreatePreloadBlock(wallet, random);
            var result = system.Blockchain.Ask <RelayResultReason>(block).Result;

            if (result != RelayResultReason.Succeed)
            {
                throw new Exception($"Preload transfer suffix block failed {result}");
            }

            SubmitTransaction((snapshot, account) => NodeUtility.MakeClaimTransaction(snapshot, account.ScriptHash,
                                                                                      Blockchain.GoverningToken.Hash));
        }
        // Since ConensusContext's constructor is internal, it can't be used from neo-express.
        // CreatePreloadBlock replicates the following logic for creating an empty block with ConensusContext

        // var ctx = new Neo.Consensus.ConsensusContext(wallet, store);
        // ctx.Reset(0);
        // ctx.MakePrepareRequest();
        // ctx.MakeCommit();
        // ctx.Save();
        // Block block = ctx.CreateBlock();

        static Block CreatePreloadBlock(Neo.Wallets.Wallet wallet, Random random, Transaction?transaction = null)
        {
            using var snapshot = Blockchain.Singleton.GetSnapshot();
            var validators = snapshot.GetValidators();

            if (validators.Length != 1)
            {
                throw new InvalidOperationException("Preload only supported for single-node blockchains");
            }

            var amountNetFee = Block.CalculateNetFee(Enumerable.Empty <Transaction>());

            if (amountNetFee != Fixed8.Zero)
            {
                throw new InvalidOperationException("amountNetFee must be zero");
            }

            var keyPair   = wallet.GetAccount(validators[0]).GetKey();
            var prevHash  = snapshot.CurrentBlockHash;
            var prevBlock = snapshot.GetBlock(prevHash);
            var nonce     = NextNonce(random);

            var minerTx = new MinerTransaction
            {
                Nonce      = (uint)(nonce % (uint.MaxValue + 1ul)),
                Attributes = Array.Empty <TransactionAttribute>(),
                Inputs     = Array.Empty <CoinReference>(),
                Outputs    = Array.Empty <TransactionOutput>(),
                Witnesses  = Array.Empty <Witness>()
            };

            var blockTransactions = transaction == null ? new Transaction[] { minerTx } : new Transaction[] { minerTx, transaction };
            var txHashes          = blockTransactions.Select(tx => tx.Hash).ToArray();
            var merkleRoot        = MerkleTree.ComputeRoot(txHashes);
            var nextConsensus     = Blockchain.GetConsensusAddress(snapshot.GetValidators(blockTransactions).ToArray());
            var consensusData     = nonce;

            var block = new Block()
            {
                Version       = 0,
                PrevHash      = prevHash,
                MerkleRoot    = merkleRoot,
                Timestamp     = prevBlock.Timestamp + 1,
                Index         = prevBlock.Index + 1,
                ConsensusData = nonce,
                NextConsensus = nextConsensus,
                Transactions  = Array.Empty <Transaction>(),
            };

            var commit = new Neo.Consensus.Commit()
            {
                ViewNumber = 0,
                Signature  = block.Sign(keyPair)
            };
            var payload = new ConsensusPayload
            {
                Version        = 0,
                PrevHash       = prevHash,
                BlockIndex     = block.Index,
                ValidatorIndex = (ushort)0,
                Data           = Neo.IO.Helper.ToArray(commit)
            };

            {
                var sc = new ContractParametersContext(payload);
                wallet.Sign(sc);
                payload.Witness = sc.GetWitnesses()[0];
            }

            {
                var      m                   = validators.Length - ((validators.Length - 1) / 3);
                Contract contract            = Contract.CreateMultiSigContract(m, validators);
                ContractParametersContext sc = new ContractParametersContext(block);
                for (int i = 0, j = 0; i < validators.Length && j < m; i++)
                {
                    sc.AddSignature(contract, validators[0], payload.GetDeserializedMessage <Neo.Consensus.Commit>().Signature);
                    j++;
                }
                block.Witness      = sc.GetWitnesses()[0];
                block.Transactions = blockTransactions;
            }
            return(block);
        }