package org.ripple.power.txns.btc; import java.io.EOFException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; import org.ripple.power.Helper; /** * <p>The 'getblocks' message is sent by a peer when it does not have the latest block chain * and needs a list of the blocks required to get to the latest block.</p> * * <p>GetBlocks Message</p> * <pre> * Size Field Description * ==== ===== =========== * 4 bytes Version Negotiated protocol version * VarInt Count Number of locator hash entries * Variable Entries Locator hash entries * 32 bytes Stop Hash of the last desired block or zero to get as many as possible * </pre> */ public class GetBlocksMessage { /** * Build a 'getblocks' message * * @param peer Destination peer * @param blockList Block hash list * @param stopBlock Stop block hash (Sha256Hash.ZERO_HASH to get all blocks) * @return 'getblocks' message */ public static Message buildGetBlocksMessage(Peer peer, List<Sha256Hash> blockList, Sha256Hash stopBlock) { // // Build the message payload // // The protocol version will be set to the lesser of our version and the peer version // SerializedBuffer msgBuffer = new SerializedBuffer(blockList.size()*32+40); msgBuffer.putInt(Math.min(peer.getVersion(), NetParams.PROTOCOL_VERSION)) .putVarInt(blockList.size()); for(Sha256Hash hash:blockList){ msgBuffer.putBytes(Helper.reverseBytes(hash.getBytes())); } msgBuffer.putBytes(Helper.reverseBytes(stopBlock.getBytes())); // // Build the message // ByteBuffer buffer = MessageHeader.buildMessage("getblocks", msgBuffer); return new Message(buffer, peer, MessageHeader.MessageCommand.GETBLOCKS); } /** * Process the 'getblocks' message and return an 'inv' message * * @param msg Message * @param inBuffer Input buffer * @param msgListener Message listener * @throws EOFException End-of-data processing stream * @throws VerificationException Message verification failed */ public static void processGetBlocksMessage(Message msg, SerializedBuffer inBuffer, MessageListener msgListener) throws EOFException, VerificationException { // // Process the message // int version = inBuffer.getInt(); if (version < NetParams.MIN_PROTOCOL_VERSION) throw new VerificationException(String.format("Protocol version %d is not supported", version)); int count = inBuffer.getVarInt(); if (count < 0 || count > 500) throw new VerificationException("More than 500 locator entries in 'getblocks' message"); List<Sha256Hash> blockList = new ArrayList<>(count); for (int i=0; i<count; i++) blockList.add(new Sha256Hash(Helper.reverseBytes(inBuffer.getBytes(32)))); Sha256Hash stopBlock = new Sha256Hash(Helper.reverseBytes(inBuffer.getBytes(32))); // // Notify the message listener // msgListener.processGetBlocks(msg, version, blockList, stopBlock); } }