public static List <string> PartnersUpdateRequest <T>(T requestUpdate)
        {
            /* Build the message */
            var content = PreparePartnerSyncRequest(PartnerMsgToType <T>(requestUpdate), JSONSerializer <T> .Serialize(requestUpdate));

            var ErrNodes = new List <string>();

            /* Ask each of the participants to send its database version */
            foreach (var partner in Partners)
            {
                try
                {
                    var request = Request(partner);

                    JSONSerializer <PartnerSyncMessage> .Serialize(content, request.GetRequestStream()).Close();

                    /* Get the response */
                    var signedResponse = JSONSerializer <PartnerSyncMessage> .Deserialize(request.GetResponse().GetResponseStream());

                    if (!CryptoEngine.GetInstance().verifyCertificate(signedResponse.key, signedResponse.certId, signedResponse.cert).VerifyData(signedResponse.data, signedResponse.signature))
                    {
                        /* Invalid response. Ignore. */
                        continue;
                    }

                    var response = JSONSerializer <BooleanResponse> .Deserialize(JSONSerializer <PartnerSyncMessageData> .Deserialize(signedResponse.data).Data);

                    if (!response.Success)
                    {
                        Console.WriteLine("Error in request...");

                        ErrNodes.Add(partner);
                    }
                }
                catch (Exception e)
                {
                    /* Add to err nodes */
                    ErrNodes.Add(partner);
                }
            }

            return(ErrNodes);
        }
        public static PartnerSyncMessage PrepareSignedMessage(byte[] data)
        {
            PartnerSyncMessage msg = new PartnerSyncMessage();

            /* Provide certificate data */
            msg.certId = CryptoEngine.GetInstance().Certificate.Cert.Id;
            msg.cert   = new byte[CryptoEngine.GetInstance().Certificate.Cert.Signature.ToByteArray().Length];
            CryptoEngine.GetInstance().Certificate.Cert.Signature.ToByteArray().CopyTo(msg.cert, 0);
            msg.key = CryptoEngine.GetInstance().Certificate.Keys.PublicKey.PublicKey.ToByteArray();

            /* Copy data itself */
            msg.data = data;

            var dsa = CryptoEngine.GetInstance().ECLoad(CryptoEngine.GetInstance().Certificate.Keys.PublicKey.PublicKey.ToByteArray(), CryptoEngine.GetInstance().Certificate.Keys.PrivateKey.ToByteArray());

            /* Sign the data */
            msg.signature = dsa.SignData(data, HashAlgorithmName.SHA256);

            return(msg);
        }
        public static void PartnerJoinRequest(PartnerSyncRequestJoin requestJoin)
        {
            /* Build the message */
            var content = PreparePartnerSyncRequest(PartnerSyncMessageType.PARTNER_JOIN, JSONSerializer <PartnerSyncRequestJoin> .Serialize(requestJoin));

            byte[] dbDump = null;

            var newPartners = new List <string>();

            /* Ask each of the participants to send its database version */
            foreach (var partner in Partners)
            {
                var request = Request(partner);

                try
                {
                    JSONSerializer <PartnerSyncMessage> .Serialize(content, request.GetRequestStream()).Close();
                }
                catch (WebException)
                {
                    /* Node might be down */
                    continue;
                }

                PartnerSyncMessage signedResponse;

                try
                {
                    /* Get the response */
                    signedResponse = JSONSerializer <PartnerSyncMessage> .Deserialize(request.GetResponse().GetResponseStream());
                }
                catch (SerializationException)
                {
                    continue;
                }

                if (!CryptoEngine.GetInstance().verifyCertificate(signedResponse.key, signedResponse.certId, signedResponse.cert).VerifyData(signedResponse.data, signedResponse.signature))
                {
                    /* Invalid response. Ignore. */
                    continue;
                }

                var response = JSONSerializer <PartnerSyncResponseDBDump> .Deserialize(JSONSerializer <PartnerSyncMessageData> .Deserialize(signedResponse.data).Data);

                foreach (var newPartner in response.Partners)
                {
                    if ((!Partners.Exists(s => s == newPartner)) && (newPartners.Exists(s => s == newPartner)) && (newPartner != Config <string> .GetInstance()["PUBLIC_ADDRESS"]) && (newPartner.StartsWith("http://") || newPartner.StartsWith("https://")))
                    {
                        newPartners.Add(newPartner);
                    }
                }

                /* Choose largest dump too sync with (TODO: Not sure it's the best idea) - Currently best-effort. */
                if ((dbDump == null) || (dbDump.Length < response.DBDump.Length))
                {
                    dbDump = response.DBDump;
                }
            }

            if (dbDump != null)
            {
                /* Write DB To file */
                var dbFile = File.Open(Config <string> .GetInstance()["DB_Filename"], FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);

                using (var writer = new BinaryWriter(dbFile))
                {
                    writer.Write(dbDump);
                }
            }

            /* Add additional partners */
            foreach (var newPartner in newPartners)
            {
                Partners.Add(newPartner);
            }
        }