package org.ripple.power.txns.btc;
import java.io.EOFException;
import java.nio.ByteBuffer;
/**
* <p>The 'alert' message is sent out by the development team to notify all peers in the network
* about a problem. The alert is displayed in the user interface and written to the
* log. It is also sent each time a node connects to another node until the relay time
* is exceeded or the alert is canceled.</p>
*
* <p>The 'alert' message contains two variable-length byte arrays. The first array is the
* payload and the second array is the signature. The alert is packaged this way so that
* a peer at any level can relay the alert even if it doesn't understand the alert format.</p>
*
* <p>Alert Message</p>
* <pre>
* Size Field Description
* ==== ===== ===========
* VarInt PayloadLength Length of the payload
* Variable Payload Alert payload
* VarInt SigLength Length of the signature
* Variable Signature Alert signature
* </pre>
*/
public class AlertMessage {
/** Public key used to verify an alert */
private static final byte[] alertPubKey = {
(byte)0x04, (byte)0xfc, (byte)0x97, (byte)0x02, (byte)0x84, (byte)0x78, (byte)0x40, (byte)0xaa,
(byte)0xf1, (byte)0x95, (byte)0xde, (byte)0x84, (byte)0x42, (byte)0xeb, (byte)0xec, (byte)0xed,
(byte)0xf5, (byte)0xb0, (byte)0x95, (byte)0xcd, (byte)0xbb, (byte)0x9b, (byte)0xc7, (byte)0x16,
(byte)0xbd, (byte)0xa9, (byte)0x11, (byte)0x09, (byte)0x71, (byte)0xb2, (byte)0x8a, (byte)0x49,
(byte)0xe0, (byte)0xea, (byte)0xd8, (byte)0x56, (byte)0x4f, (byte)0xf0, (byte)0xdb, (byte)0x22,
(byte)0x20, (byte)0x9e, (byte)0x03, (byte)0x74, (byte)0x78, (byte)0x2c, (byte)0x09, (byte)0x3b,
(byte)0xb8, (byte)0x99, (byte)0x69, (byte)0x2d, (byte)0x52, (byte)0x4e, (byte)0x9d, (byte)0x6a,
(byte)0x69, (byte)0x56, (byte)0xe7, (byte)0xc5, (byte)0xec, (byte)0xbc, (byte)0xd6, (byte)0x82,
(byte)0x84};
/**
* Create an 'alert' message
*
* @param peer Destination peer or null for a broadcast message
* @param alert Alert
* @return 'alert' message
*/
public static Message buildAlertMessage(Peer peer, Alert alert) {
//
// Build the message data
//
SerializedBuffer msgData = new SerializedBuffer();
msgData.putVarInt(alert.getPayload().length)
.putBytes(alert.getPayload())
.putVarInt(alert.getSignature().length)
.putBytes(alert.getSignature());
//
// Build the message
//
ByteBuffer buffer = MessageHeader.buildMessage("alert", msgData);
Message msg = new Message(buffer, peer, MessageHeader.MessageCommand.ALERT);
return msg;
}
/**
* Process an 'alert' message
*
* @param msg Message
* @param inBuffer Message buffer
* @param msgListener Message listener
* @throws EOFException End-of-data while processing stream
* @throws VerificationException Message verification failed
*/
public static void processAlertMessage(Message msg, SerializedBuffer inBuffer, MessageListener msgListener)
throws EOFException, VerificationException {
//
// Process the message data
//
byte[] payload = inBuffer.getBytes();
byte[] signature = inBuffer.getBytes();
//
// Verify the signature
//
ECKey ecKey = new ECKey(alertPubKey);
try {
if (!ecKey.verifySignature(payload, signature))
throw new VerificationException("Alert signature is not valid");
} catch (ECException exc) {
throw new VerificationException("Alert signature verification failed", exc);
}
//
// Notify the application message listener
//
msgListener.processAlert(msg, new Alert(payload, signature));
}
}