javaandroidsocketsbitcoinbitcoinj

Bitcoin Protocol GetAddr returns Alert Message


I am implementing the bitcoin protocol in Android/Java. When I send a getaddr message, the peer responds with an alert message

The flow of messages are:

  1. Send a version message.
  2. Receive a version message.
  3. Send a verack message.
  4. Receive a verack message.

When I try to send a getaddr message, my peer responds with an alert message.

Here is a small code snippet of the logic in the app:

 private void connect(Peer peer) {

    InetSocketAddress address = new InetSocketAddress(peer.ip, 8333);
    Socket socket = new Socket();
    try {
        socket.connect(address, 10000);

        OutputStream out = socket.getOutputStream();
        InputStream in = socket.getInputStream();

        // Step 1 - send version
        VersionMessage versionMessage = new VersionMessage();
        writeMessage(versionMessage, out);

        // Step 2 - read peer version
        VersionMessage peerVersionMessage = (VersionMessage) readMessage(in);

        // Step 3 - write verack
        VerAckMessage verAckMessage = new VerAckMessage();
        writeMessage(verAckMessage, out);

        // Step 4 - read verack
        VerAckMessage peerVerAckMessage = (VerAckMessage) readMessage(in);

        //Step 6 - read addr message (this does not happen, an alert is returned...)
        readMessage(in);

        writeMessage(getAddrMessage, out);

        out.close();
        in.close();
        socket.close();

    } catch (IOException e) {
        Log.i(App.TAG, "Socket failed to conenct");
    }
}

And is a snippet of some logs

connect to: 47.93.25.228:8333

writeMessage: version
readMessage: Version{version=70015, services=13,
timestamp=1518015001, addrRecv='null',
addrFrom='null', nonce=-2830171230962795176, 
userAgent='/Satoshi:0.15.1/', startHeight=508112, relay=true}

writeMessage: verack
readMessage: VerAckMessage{count=0, addrList=null}

writeMessage: getaddr
readMessage: alert {, version=1, relayUntil=0, expiration=2147483647,
id=2147483647, cancel=2147483646, setCancel=[2147483647], minVer=0, maxVer=2147483647, setSubVer=[], priority=2147483647, comment='', statusBar='URGENT: Alert key compromised, upgrade required', reserved=''}

If I send the same getaddr message 4 times in a row - eventually the peer responds with an addr message (with 1 addr - his own address)


Solution

  • The protocol version was: 70012, bumping it to 70015 - stoped the peer from sending the alert.

    You can find more information about this in the reference client here: https://github.com/bitcoin/bitcoin/blob/master/src/net_processing.cpp#L1707-L1711

     // If the peer is old enough to have the old alert system, send it the final alert.
        if (pfrom->nVersion <= 70012) {
            CDataStream finalAlert(ParseHex("60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"), SER_NETWORK, PROTOCOL_VERSION);
            connman->PushMessage(pfrom, CNetMsgMaker(nSendVersion).Make("alert", finalAlert));
        }