/** * 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); }
/** * Configure the network parameters * * <p>The configure() method must be called before using any of the BitcoinCore library routines. * * @param testNetwork TRUE for the test network, FALSE for the production network * @param applicationName Application name * @param minProtocolVersion Minimum supported protocol version * @param supportedServices Supported services * @throws ClassNotFoundException org.ScripterRon.BitcoinCore.NetParams class not found * @throws IOException Unable read application properties */ public static void configure( boolean testNetwork, int minProtocolVersion, String applicationName, long supportedServices) throws ClassNotFoundException, IOException { // // Initialize data arreas for the desired network // if (testNetwork) { MAGIC_NUMBER = MAGIC_NUMBER_TESTNET; ADDRESS_VERSION = ADDRESS_VERSION_TESTNET; DUMPED_PRIVATE_KEY_VERSION = DUMPED_PRIVATE_KEY_VERSION_TESTNET; GENESIS_BLOCK_HASH = GENESIS_BLOCK_TESTNET; GENESIS_BLOCK_TIME = GENESIS_TIME_TESTNET; MAX_TARGET_DIFFICULTY = MAX_DIFFICULTY_TESTNET; } else { MAGIC_NUMBER = MAGIC_NUMBER_PRODNET; ADDRESS_VERSION = ADDRESS_VERSION_PRODNET; DUMPED_PRIVATE_KEY_VERSION = DUMPED_PRIVATE_KEY_VERSION_PRODNET; GENESIS_BLOCK_HASH = GENESIS_BLOCK_PRODNET; GENESIS_BLOCK_TIME = GENESIS_TIME_PRODNET; MAX_TARGET_DIFFICULTY = MAX_DIFFICULTY_PRODNET; } PROOF_OF_WORK_LIMIT = Helper.decodeCompactBits(MAX_TARGET_DIFFICULTY); // // Get the library build properties // Class<?> thisClass = Class.forName("org.ScripterRon.BitcoinCore.NetParams"); String applicationID; String applicationVersion; try (InputStream classStream = thisClass.getClassLoader().getResourceAsStream("META-INF/bitcoincore.properties")) { if (classStream == null) throw new IOException("Library build properties not found"); Properties applicationProperties = new Properties(); applicationProperties.load(classStream); applicationID = applicationProperties.getProperty("application.id"); applicationVersion = applicationProperties.getProperty("application.version"); } LIBRARY_NAME = String.format("%s:%s", applicationID, applicationVersion); // // Set the application properties // APPLICATION_NAME = applicationName; MIN_PROTOCOL_VERSION = Math.max(MIN_PROTOCOL_VERSION, minProtocolVersion); SUPPORTED_SERVICES = supportedServices; }
/** Network-specific parameters */ public class NetParams { /** Protocol version */ public static final int PROTOCOL_VERSION = 70002; /** Minimum acceptable protocol version */ public static int MIN_PROTOCOL_VERSION = 60001; /** Peer provides network services */ public static final long NODE_NETWORK = 1; /** Our supported services */ public static long SUPPORTED_SERVICES = 0; /** Library identifier */ public static String LIBRARY_NAME = "BitcoinCore:?.?"; /** Application identifier */ public static String APPLICATION_NAME = "??"; /** Production network magic number */ public static final long MAGIC_NUMBER_PRODNET = 0xd9b4bef9L; /** Test network magic number */ public static final long MAGIC_NUMBER_TESTNET = 0xdab5bffaL; /** Magic number */ public static long MAGIC_NUMBER = MAGIC_NUMBER_PRODNET; /** Production network address version */ public static final int ADDRESS_VERSION_PRODNET = 0; /** Test network address version */ public static final int ADDRESS_VERSION_TESTNET = 111; /** Address version */ public static int ADDRESS_VERSION = ADDRESS_VERSION_PRODNET; /** Production network dumped private key version */ public static final int DUMPED_PRIVATE_KEY_VERSION_PRODNET = 128; /** Test network dumped private key version */ public static final int DUMPED_PRIVATE_KEY_VERSION_TESTNET = 239; /** Dumped private key version */ public static int DUMPED_PRIVATE_KEY_VERSION = DUMPED_PRIVATE_KEY_VERSION_PRODNET; /** Production network maximum target difficulty */ public static final long MAX_DIFFICULTY_PRODNET = 0x1d00ffffL; /** Test network maximum target difficulty */ public static final long MAX_DIFFICULTY_TESTNET = 0x207fffffL; /** Maximum target difficulty (represents least amount of work) */ public static long MAX_TARGET_DIFFICULTY = MAX_DIFFICULTY_PRODNET; /** Proof-of-work limit */ public static BigInteger PROOF_OF_WORK_LIMIT = Helper.decodeCompactBits(MAX_DIFFICULTY_PRODNET); /** Maximum clock drift in seconds */ public static final long ALLOWED_TIME_DRIFT = 2 * 60 * 60; /** Production network genesis block */ public static final String GENESIS_BLOCK_PRODNET = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"; /** Test network genesis block */ public static final String GENESIS_BLOCK_TESTNET = "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206"; /** Genesis block hash */ public static String GENESIS_BLOCK_HASH = GENESIS_BLOCK_PRODNET; /** Production network genesis block time */ public static final long GENESIS_TIME_PRODNET = 0x495fab29L; /** Test network genesis block time */ public static final long GENESIS_TIME_TESTNET = 1296688602L; /** Genesis block time */ public static long GENESIS_BLOCK_TIME = GENESIS_TIME_PRODNET; /** Maximum block size */ public static final int MAX_BLOCK_SIZE = 1 * 1024 * 1024; /** Maximum message size */ public static final int MAX_MESSAGE_SIZE = 2 * 1024 * 1024; /** Maximum amount of money in the Bitcoin system */ public static final BigInteger MAX_MONEY = new BigInteger("2100000000000000", 10); /** * Configure the network parameters * * <p>The configure() method must be called before using any of the BitcoinCore library routines. * * @param testNetwork TRUE for the test network, FALSE for the production network * @param applicationName Application name * @param minProtocolVersion Minimum supported protocol version * @param supportedServices Supported services * @throws ClassNotFoundException org.ScripterRon.BitcoinCore.NetParams class not found * @throws IOException Unable read application properties */ public static void configure( boolean testNetwork, int minProtocolVersion, String applicationName, long supportedServices) throws ClassNotFoundException, IOException { // // Initialize data arreas for the desired network // if (testNetwork) { MAGIC_NUMBER = MAGIC_NUMBER_TESTNET; ADDRESS_VERSION = ADDRESS_VERSION_TESTNET; DUMPED_PRIVATE_KEY_VERSION = DUMPED_PRIVATE_KEY_VERSION_TESTNET; GENESIS_BLOCK_HASH = GENESIS_BLOCK_TESTNET; GENESIS_BLOCK_TIME = GENESIS_TIME_TESTNET; MAX_TARGET_DIFFICULTY = MAX_DIFFICULTY_TESTNET; } else { MAGIC_NUMBER = MAGIC_NUMBER_PRODNET; ADDRESS_VERSION = ADDRESS_VERSION_PRODNET; DUMPED_PRIVATE_KEY_VERSION = DUMPED_PRIVATE_KEY_VERSION_PRODNET; GENESIS_BLOCK_HASH = GENESIS_BLOCK_PRODNET; GENESIS_BLOCK_TIME = GENESIS_TIME_PRODNET; MAX_TARGET_DIFFICULTY = MAX_DIFFICULTY_PRODNET; } PROOF_OF_WORK_LIMIT = Helper.decodeCompactBits(MAX_TARGET_DIFFICULTY); // // Get the library build properties // Class<?> thisClass = Class.forName("org.ScripterRon.BitcoinCore.NetParams"); String applicationID; String applicationVersion; try (InputStream classStream = thisClass.getClassLoader().getResourceAsStream("META-INF/bitcoincore.properties")) { if (classStream == null) throw new IOException("Library build properties not found"); Properties applicationProperties = new Properties(); applicationProperties.load(classStream); applicationID = applicationProperties.getProperty("application.id"); applicationVersion = applicationProperties.getProperty("application.version"); } LIBRARY_NAME = String.format("%s:%s", applicationID, applicationVersion); // // Set the application properties // APPLICATION_NAME = applicationName; MIN_PROTOCOL_VERSION = Math.max(MIN_PROTOCOL_VERSION, minProtocolVersion); SUPPORTED_SERVICES = supportedServices; } }