private async Task ConnectToPeers(IEnumerable <KeyValuePair <string, ServiceFlags> > hosts) // PASS THE SERVICE_FLAGS.
        {
            if (hosts == null)
            {
                throw new ArgumentNullException(nameof(hosts));
            }

            var tasks = new List <Task>();

            foreach (var kvp in hosts)
            {
                var ip   = IPAddress.Parse(kvp.Key);
                var myIp = PeersStore.Instance().GetMyIpAddress();
                if (myIp.Ipv6.SequenceEqual(ip.MapToIPv6().GetAddressBytes())) // NOT SAME ADDRESS.
                {
                    continue;
                }

                if (ContainsPeer(ip.MapToIPv6().GetAddressBytes())) // CONNECTION DOESNT EXIST.
                {
                    continue;
                }

                tasks.Add(ConnectToPeer(kvp.Key, kvp.Value));
            }

            var   result = Task.WhenAll(tasks.ToArray());
            await result;
        }
Пример #2
0
        public byte[] Serialize()
        {
            var result = new List <byte>();

            result.AddRange(MessageHeader.GetStartString());
            var         commandName       = GetCommandName();
            List <byte> commandNameBuffer = System.Text.Encoding.ASCII.GetBytes(commandName).ToList();

            for (var i = commandNameBuffer.Count(); i < 12; i++)
            {
                commandNameBuffer.Add(0x00);
            }

            result.AddRange(commandNameBuffer);
            result.AddRange(PeersStore.Instance().GetMyIpAddress().Ipv6);
            var content = GetSerializedContent();
            var size    = BitConverter.GetBytes(content.Length);

            result.AddRange(size);
            byte[] checksum = null;
            if (content == null)
            {
                checksum = new byte[] { 0x5d, 0xf6, 0xe0, 0xe2 };
            }
            else
            {
                SHA256 mySHA256 = SHA256.Create();
                var    hashed   = mySHA256.ComputeHash(mySHA256.ComputeHash(content));
                checksum = hashed.Take(4).ToArray();
            }

            result.AddRange(checksum);
            result.AddRange(content);
            return(result.ToArray());
        }
        public async Task Listen(Networks network, bool keepConnectionsAlive = true)
        {
            _network = network;
            var instance         = PeersStore.Instance();
            var currentIpAddress = instance.GetMyIpAddress();

            _isSeedNode = IsSeedNode(currentIpAddress, _network);
            await DiscoverNodes();
        }
Пример #4
0
        public void Connect(string host, ServiceFlags serviceFlag)
        {
            if (string.IsNullOrWhiteSpace(host))
            {
                throw new ArgumentNullException(nameof(host));
            }

            var       iid   = Interop.Constants.InterfaceId;
            var       port  = PortsHelper.GetPort(_network);
            IPAddress ipAdr = null;

            if (!IPAddress.TryParse(host, out ipAdr))
            {
                // TODO : Throw an exception.
            }

            var adrBytes = ipAdr.MapToIPv6().GetAddressBytes();

            _serviceFlag      = serviceFlag;
            _currentIpAddress = new IpAddress(serviceFlag, adrBytes, ushort.Parse(port));
            // _client = new RpcClientApi(iid, RpcProtseq.ncacn_ip_tcp, host, port);
            _client = new RpcClientApi(iid, RpcProtseq.ncalrpc, null, host);
            // Connection to peers : https://bitcoin.org/en/developer-guide#connecting-to-peers
            var instance         = PeersStore.Instance();
            var transmittingNode = instance.GetMyIpAddress();
            var nonce            = NonceHelper.GetNonceUInt64();
            var versionMessage   = new VersionMessage(transmittingNode, _currentIpAddress, nonce, string.Empty, 0, false, _network);

            try
            {
                _peerConnection = new PeerConnection(adrBytes);
                var result = _messageCoordinator.Launch(this, versionMessage);
                if (result != null && result is VerackMessage)
                {
                    _peerConnection.Connect();
                    if (ConnectEvent != null)
                    {
                        ConnectEvent(this, new IpAddressEventArgs(_currentIpAddress));
                    }

                    _timer = new Timer(TimerElapsed, _autoEvent, CHECK_INTERVAL, CHECK_INTERVAL); // CHECK PEERS AVAILABILITY EVERY 60 SECONDS.
                }
            }
            catch (Interop.RpcException)
            {
                throw new PeerConnectorException(ErrorCodes.PeerRpcError);
            }
        }
Пример #5
0
        public void Start(IEnumerable <byte> ipAddress = null)
        {
            if (ipAddress == null)
            {
                ipAddress = _ipAdrHelper.GetIpv4Address();
            }

            _ipAddress = new IpAddress(DateTime.UtcNow, _serviceFlag, ipAddress.ToArray(), ushort.Parse(PortsHelper.GetPort(_network)));
            PeersStore.Instance().SetMyIpAddress(_ipAddress);
            var iid      = Interop.Constants.InterfaceId;
            var instance = PeersStore.Instance();
            var port     = PortsHelper.GetPort(_network);
            // _server = new RpcServerApi(iid, 1234, -1, true);
            // _server.AddProtocol(RpcProtseq.ncacn_ip_tcp, port, 5);
            var name = (new IPAddress(_ipAddress.Ipv6)).MapToIPv4().ToString(); // USE QUEUE.

            _server = new RpcServerApi(iid, 1234, -1, true);
            _server.AddProtocol(RpcProtseq.ncalrpc, name, 5);
            _server.StartListening();
            _server.OnExecute += delegate(IRpcClientInfo client, byte[] arg)
            {
                var message       = _messageParser.Parse(arg);
                var connectedPeer = _p2pNetworkConnector.GetPeer(message.MessageHeader.Ipv6);
                if (NewMessageEvent != null)
                {
                    NewMessageEvent(this, new StringEventArgs(message.GetCommandName()));
                }

                var response = _messageCoordinator.Receive(message, connectedPeer, _p2pNetworkConnector);
                if (response == null)
                {
                    return(new byte[0]);
                }

                return(response.Serialize());
            };

            if (StartNodeEvent != null)
            {
                StartNodeEvent(this, EventArgs.Empty);
            }
        }
        private async Task DiscoverNodesViaSeeds()
        {
            var dic = GetSeedNodes(_network).Select(s => new KeyValuePair <string, ServiceFlags>(s, ServiceFlags.NODE_NETWORK));

            await ConnectToPeers(dic);

            var instance         = PeersStore.Instance();
            var currentIpAddress = instance.GetMyIpAddress();
            var addrMessage      = new AddrMessage(new CompactSize {
                Size = 1
            }, _network);

            addrMessage.IpAddresses.Add(currentIpAddress);
            Broadcast(addrMessage);
            var getAddrMessage = new GetAddressMessage(_network);
            var getAddrLst     = Broadcast(getAddrMessage);

            if (getAddrLst != null && getAddrLst.Any())
            {
                foreach (var getAddr in getAddrLst)
                {
                    var getAdrMsg = getAddr as AddrMessage;
                    if (getAdrMsg == null)
                    {
                        continue;
                    }

                    _peersRepository.AddPeers(getAdrMsg.IpAddresses);
                }
            }

            var peers = _peersRepository.GetAll();

            if (peers.Any())
            {
                await DiscoverNodesViaStore(peers);
            }
        }
Пример #7
0
        public Message Receive(Message message, PeerConnector peer, P2PNetworkConnector p2pNetworkConnector)
        {
            var blockChain    = _blockChainStore.GetBlockChain();
            var smartContract = _smartContractStore.GetSmartContracts();

            if (message.GetCommandName() == Constants.MessageNames.Version) // RETURNS VERSION.
            {
                var msg              = message as VersionMessage;
                var instance         = PeersStore.Instance();
                var transmittingNode = instance.GetMyIpAddress();
                var receivingNode    = msg.TransmittingNode;
                return(new VersionMessage(transmittingNode, receivingNode, msg.Nonce, msg.UserAgent, msg.StartHeight, msg.Relay, msg.MessageHeader.Network));
            }

            if (message.GetCommandName() == Constants.MessageNames.Ping) // RETURNS PONG.
            {
                var msg  = message as PingMessage;
                var pong = new PongMessage(msg.Nonce, msg.MessageHeader.Network);
                return(pong);
            }

            if (message.GetCommandName() == Constants.MessageNames.Verack) // RETURNS VERACK MESSAGE.
            {
                var msg = message as VerackMessage;
                return(new VerackMessage(msg.MessageHeader.Network));
            }

            if (message.GetCommandName() == Constants.MessageNames.Addr) // RETURNS THE ADDRS.
            {
                var msg = message as AddrMessage;
                if (msg.IpAddresses != null)
                {
                    foreach (var ipAddress in msg.IpAddresses)
                    {
                        PeerEventStore.Instance().NewPeer(ipAddress);
                    }
                }

                return(null);
            }

            if (message.GetCommandName() == Constants.MessageNames.GetAddr) // RETURNS THE ADDRS.
            {
                var msg      = message as GetAddressMessage;
                var ipAdrLst = _peersStorage.GetAll();
                var response = new AddrMessage(new CompactSize {
                    Size = (ulong)ipAdrLst.Count()
                }, msg.MessageHeader.Network);
                foreach (var ipAdr in ipAdrLst)
                {
                    response.IpAddresses.Add(ipAdr);
                }

                return(response);
            }

            if (message.GetCommandName() == Constants.MessageNames.MemPool) // RETURNS THE INVENTORY.
            {
                var msg         = message as MemPoolMessage;
                var memoryPool  = MemoryPool.Instance();
                var txIds       = memoryPool.GetTransactions().Select(t => t.Transaction.GetTxId());
                var inventories = new List <Inventory>();
                foreach (var txId in txIds)
                {
                    inventories.Add(new Inventory(InventoryTypes.MSG_TX, txId));
                }

                return(new InventoryMessage(inventories, msg.MessageHeader.Network));
            }

            if (message.GetCommandName() == Constants.MessageNames.GetData) // RETURNS ALL THE DATA TO THE PEER.
            {
                var msg      = message as GetDataMessage;
                var messages = Execute(msg);
                if (messages != null)
                {
                    foreach (var m in messages)
                    {
                        peer.Execute(m.Serialize());
                    }
                }

                return(null);
            }

            if (message.GetCommandName() == Constants.MessageNames.Transaction) // ADD TRANSACTION INTO MEMORY POOL & BROADCAST IT.
            {
                var msg = message as TransactionMessage;
                AddTransaction(msg.Transaction);
                MemoryPool.Instance().Remove(msg.Transaction);
                p2pNetworkConnector.Broadcast(msg.Transaction, msg.MessageHeader.Ipv6);
                return(null);
            }

            if (message.GetCommandName() == Constants.MessageNames.Block) // ADD THE BLOCK.
            {
                var msg = message as BlockMessage;
                _blockValidator.Check(msg.Block);
                if (msg.Block.Transactions != null)
                {
                    MemoryPool.Instance().Remove(msg.Block.Transactions.Select(tx => tx.GetTxId()));
                }

                smartContract.AddBlock(msg.Block);
                smartContract.Commit();
                blockChain.AddBlock(msg.Block);
            }

            if (message.GetCommandName() == Constants.MessageNames.NotFound) //  SOME INVENTORIES ARE NOT FOUND.
            {
                return(null);
            }

            if (message.GetCommandName() == Constants.MessageNames.GetBlocks) // RETURN THE BLOCKS : https://bitcoin.org/en/developer-reference#getblocks
            {
                var msg             = message as GetBlocksMessage;
                int lastBlockHeight = -1;
                foreach (var blockHash in msg.BlockHashes)
                {
                    lastBlockHeight = blockChain.GetBlockHeight(blockHash);
                    if (lastBlockHeight != -1)
                    {
                        goto Found;
                    }
                }

Found:
                var currentBlockHeight = blockChain.GetCurrentBlockHeight();
                if (currentBlockHeight == lastBlockHeight)
                {
                    return(new InventoryMessage(new List <Inventory>(), msg.MessageHeader.Network));
                }

                var nbBlocks = currentBlockHeight - lastBlockHeight;
                if (lastBlockHeight == -1)
                {
                    nbBlocks = currentBlockHeight - 1;
                }

                if (nbBlocks > Constants.DEFAULT_MAX_GET_INVENTORIES)
                {
                    nbBlocks = Constants.DEFAULT_MAX_GET_INVENTORIES;
                }

                var blocks      = blockChain.GetLastBlocks(nbBlocks);
                var inventories = new List <Inventory>();
                foreach (var block in blocks)
                {
                    inventories.Add(new Inventory(InventoryTypes.MSG_BLOCK, block.GetHashHeader()));
                }

                return(new InventoryMessage(inventories, msg.MessageHeader.Network));
            }

            return(null);
        }