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; }
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(); }
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); } }
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); } }
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); }