public void TestVerack()
 {
     var bs = new BitcoinSerializer(NetworkParameters.ProdNet(), false);
     // the actual data from https://en.bitcoin.it/wiki/Protocol_specification#verack
     using (var bais = new MemoryStream(Hex.Decode("f9beb4d976657261636b00000000000000000000")))
     {
         bs.Deserialize(bais);
     }
 }
 public void TestVersion()
 {
     var bs = new BitcoinSerializer(NetworkParameters.ProdNet(), false);
     // the actual data from https://en.bitcoin.it/wiki/Protocol_specification#version
     using (var bais = new MemoryStream(Hex.Decode("f9beb4d976657273696f6e0000000000550000009" +
                                                   "c7c00000100000000000000e615104d00000000010000000000000000000000000000000000ffff0a000001daf6010000" +
                                                   "000000000000000000000000000000ffff0a000002208ddd9d202c3ab457130055810100")))
     {
         var vm = (VersionMessage) bs.Deserialize(bais);
         Assert.AreEqual(31900U, vm.ClientVersion);
         Assert.AreEqual(1292899814UL, vm.Time);
         Assert.AreEqual(98645U, vm.BestHeight);
     }
 }
 public void TestAddr()
 {
     var bs = new BitcoinSerializer(NetworkParameters.ProdNet(), true);
     // the actual data from https://en.bitcoin.it/wiki/Protocol_specification#addr
     using (var bais = new MemoryStream(Hex.Decode("f9beb4d96164647200000000000000001f000000" +
                                                   "ed52399b01e215104d010000000000000000000000000000000000ffff0a000001208d")))
     {
         var a = (AddressMessage) bs.Deserialize(bais);
         Assert.AreEqual(1, a.Addresses.Count);
         var pa = a.Addresses[0];
         Assert.AreEqual(8333, pa.Port);
         Assert.AreEqual("10.0.0.1", pa.Addr.ToString());
     }
 }
Ejemplo n.º 4
0
        /// <summary>
        /// Connect to the given IP address using the port specified as part of the network parameters. Once construction
        /// is complete a functioning network channel is set up and running.
        /// </summary>
        /// <param name="peerAddress">IP address to connect to. IPv6 is not currently supported by BitCoin. If port is not positive the default port from params is used.</param>
        /// <param name="networkParameters">Defines which network to connect to and details of the protocol.</param>
        /// <param name="bestHeight">How many blocks are in our best chain</param>
        /// <param name="connectTimeout">Timeout in milliseconds when initially connecting to peer</param>
        /// <exception cref="IOException">If there is a network related failure.</exception>
        /// <exception cref="ProtocolException">If the version negotiation failed.</exception>
        public NetworkConnection(PeerAddress peerAddress, NetworkParameters networkParameters, uint bestHeight,
            int connectTimeout = 60000)
        {
            _networkParameters = networkParameters;
            _remoteIp = peerAddress.IpAddress;

            var port = (peerAddress.Port > 0) ? peerAddress.Port : networkParameters.Port;

            var address = new IPEndPoint(_remoteIp, port);
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            _socket.Connect(address);
            _socket.SendTimeout = _socket.ReceiveTimeout = connectTimeout;

            _outputStream = new NetworkStream(_socket, FileAccess.Write);
            _inputStream = new NetworkStream(_socket, FileAccess.Read);

            // the version message never uses check-summing. Update check-summing property after version is read.
            _serializer = new BitcoinSerializer(networkParameters);

            // Announce ourselves. This has to come first to connect to clients beyond v0.30.20.2 which wait to hear
            // from us until they send their version message back.
            var versionMessage = new VersionMessage(networkParameters, bestHeight);
            //Log.DebugFormat("Version Message: {0}", versionMessage);
            WriteMessage(versionMessage);
            //Log.Debug("Sent version message. Now we should read the ack from the peer.");

            VersionMessage versionMessageFromPeer;
            while ((versionMessage = ReadMessage() as VersionMessage)==null)
            {

            }
            Log.Info("WE HAVE A VERSION MESSAGE!");
            // When connecting, the remote peer sends us a version message with various bits of
            // useful data in it. We need to know the peer protocol version before we can talk to it.
            _versionMessage = (VersionMessage) versionMessage;
            //Log.Debug("read message of type version.");
            Log.Debug(_versionMessage);
            // Now it's our turn ...
            // Send an ACK message stating we accept the peers protocol version.
            WriteMessage(new VersionAckMessage());
            // And get one back ...
            ReadMessage();
            // Switch to the new protocol version.
            var peerVersion = _versionMessage.ClientVersion;
            Log.InfoFormat("Connected to peer: version={0}, subVer='{1}', services=0x{2:X}, time={3}, blocks={4}",
                peerVersion,
                _versionMessage.SubVersion,
                _versionMessage.LocalServices,
                UnixTime.FromUnixTime(_versionMessage.Time),
                _versionMessage.BestHeight
                );
            // BitcoinSharp is a client mode implementation. That means there's not much point in us talking to other client
            // mode nodes because we can't download the data from them we need to find/verify transactions.
            if (!_versionMessage.HasBlockChain())
            {
                // Shut down the socket
                try
                {
                    Shutdown();
                }
                catch (IOException)
                {
                    // ignore exceptions while aborting
                }
                throw new ProtocolException("Peer does not have a copy of the block chain.");
            }
            // Handshake is done!
        }