private bool IsBeyondBlockSecurityDelay(MonitorChainSession monitorChainSession)
        {
            this.logger.LogInformation("() Session started at block {0}, block security delay {1}, current block height {2}, waiting for {3} more blocks",
                                       monitorChainSession.BlockNumber, BlockSecurityDelay, this.concurrentChain.Tip.Height,
                                       monitorChainSession.BlockNumber + BlockSecurityDelay - this.concurrentChain.Tip.Height);

            return(this.concurrentChain.Tip.Height >= (monitorChainSession.BlockNumber + BlockSecurityDelay));
        }
        // Creates the Monitor session.
        // A session is added when the CrossChainTransactionMonitor identifies a transaction that needs to be completed cross chain.
        public void RegisterMonitorSession(MonitorChainSession monitorSession)
        {
            this.logger.LogTrace("({0}:'{1}')", nameof(monitorSession.BlockNumber), monitorSession.BlockNumber);

            this.monitorSessions.TryAdd(monitorSession.BlockNumber, monitorSession);

            //monitorChainSession.CrossChainTransactions.Add(crossChainTransactionInfo);

            //this.monitorSessions.TryAdd(monitorChainSession.SessionId, monitorChainSession);
            //this.logger.LogInformation("MonitorChainSession added: {0}", monitorChainSession);

            //// Call to the counter chain and tell it to also create a session.
            //this.CreateSessionOnCounterChain(this.federationGatewaySettings.CounterChainApiPort, monitorChainSession);
            //    //crossChainTransactionInfo.TransactionHash,
            //    //crossChainTransactionInfo.Amount,
            //    //crossChainTransactionInfo.DestinationAddress,
            //    //crossChainTransactionInfo.BlockNumber);
        }
        // Calls into the counter chain and registers the session there.
        public void CreateSessionOnCounterChain(int apiPortForSidechain, MonitorChainSession monitorChainSession)
        {
            this.logger.LogTrace("({0}:'{1}',{2}:'{3}',{4}:'{5}')", nameof(apiPortForSidechain), apiPortForSidechain, nameof(monitorChainSession.BlockNumber), monitorChainSession.BlockNumber, "Transactions Count", monitorChainSession.CrossChainTransactions.Count);

            var createCounterChainSessionRequest = new CreateCounterChainSessionRequest
            {
                BlockHeight = monitorChainSession.BlockNumber,
                CounterChainTransactionInfos = monitorChainSession.CrossChainTransactions.Select(t => new CounterChainTransactionInfoRequest
                {
                    TransactionHash    = t.TransactionHash,
                    DestinationAddress = t.DestinationAddress,
                    Amount             = t.Amount.ToString()
                }).ToList()
            };

            using (var client = new HttpClient())
            {
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                var uri     = new Uri($"http://localhost:{apiPortForSidechain}/api/FederationGateway/create-session-oncounterchain");
                var request = new JsonContent(createCounterChainSessionRequest);

                try
                {
                    var    httpResponseMessage = client.PostAsync(uri, request).ConfigureAwait(false).GetAwaiter().GetResult();
                    string json = httpResponseMessage.Content.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult();
                }
                catch (Exception e)
                {
                    this.logger.LogError(e, "Error occurred when calling /api/FederationGateway/create-session-oncounterchain: {0}", e.Message);
                }
            }

            this.logger.LogTrace("(-)");
        }
        // Calls into the counter chain and sets off the process to build the multi-sig transaction.
        private async Task <uint256> ProcessSessionOnCounterChain(int apiPortForSidechain, MonitorChainSession monitorChainSession)
        {
            this.logger.LogTrace("({0}:'{1}',{2}:'{3}',{4}:'{5}')", nameof(apiPortForSidechain), apiPortForSidechain, nameof(monitorChainSession.BlockNumber), monitorChainSession.BlockNumber, "Transactions Count", monitorChainSession.CrossChainTransactions.Count);

            var createCounterChainSessionRequest = new CreateCounterChainSessionRequest
            {
                BlockHeight = monitorChainSession.BlockNumber,
                CounterChainTransactionInfos = monitorChainSession.CrossChainTransactions.Select(t => new CounterChainTransactionInfoRequest
                {
                    TransactionHash    = t.TransactionHash,
                    DestinationAddress = t.DestinationAddress,
                    Amount             = t.Amount.ToString()
                }).ToList()
            };

            using (var client = new HttpClient())
            {
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                var uri     = new Uri($"http://localhost:{apiPortForSidechain}/api/FederationGateway/process-session-oncounterchain");
                var request = new JsonContent(createCounterChainSessionRequest);

                try
                {
                    var httpResponseMessage = await client.PostAsync(uri, request);

                    this.logger.LogInformation("Response: {0}", await httpResponseMessage.Content.ReadAsStringAsync());

                    if (httpResponseMessage.StatusCode == System.Net.HttpStatusCode.NotFound)
                    {
                        return(uint256.One);
                    }

                    if (httpResponseMessage.StatusCode != System.Net.HttpStatusCode.OK)
                    {
                        this.logger.LogError("Error occurred when calling /api/FederationGateway/process-session-oncounterchain: {0}-{1}", httpResponseMessage.StatusCode, httpResponseMessage.ToString());
                        return(uint256.Zero);
                    }

                    string json = await httpResponseMessage.Content.ReadAsStringAsync();

                    return(JsonConvert.DeserializeObject <uint256>(json, new UInt256JsonConverter()));
                }
                catch (Exception e)
                {
                    this.logger.LogError(e, "Error occurred when calling /api/FederationGateway/process-session-oncounterchain: {0}", e.Message);
                    return(uint256.Zero);
                }
            }
        }
        // A session is added when the CrossChainTransactionMonitor identifies a transaction that needs to be completed cross chain.
        public void RegisterMonitorSession(MonitorChainSession monitorSession)
        {
            this.logger.LogTrace("({0}:'{1}')", nameof(monitorSession.BlockNumber), monitorSession.BlockNumber);

            this.monitorSessions.TryAdd(monitorSession.BlockNumber, monitorSession);
        }