3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-01-31 07:12:17 +00:00

Switch to using DNS for testnet discovery, as LFnet has gone away.

Put DNS seeds into NetworkParams.
Deprecate IrcDiscovery and remove the unit tests for it.
Update examples and tools to use DNS for everything.
Resolves issue 299.
This commit is contained in:
Mike Hearn 2013-03-29 17:38:17 +00:00
parent 41ce887652
commit 3d6691c82a
9 changed files with 41 additions and 113 deletions

View File

@ -17,6 +17,7 @@
package com.google.bitcoin.core; package com.google.bitcoin.core;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import com.google.common.collect.Lists;
import org.spongycastle.util.encoders.Hex; import org.spongycastle.util.encoders.Hex;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
@ -31,8 +32,8 @@ import static com.google.common.base.Preconditions.checkState;
/** /**
* <p>NetworkParameters contains the data needed for working with an instantiation of a Bitcoin chain.</p> * <p>NetworkParameters contains the data needed for working with an instantiation of a Bitcoin chain.</p>
* *
* Currently there are only two, the production chain and the test chain. But in future as Bitcoin * <p></p>Currently there are only two, the production chain and the test chain. There is also a "unit test chain" which
* evolves there may be more. You can create your own as long as they don't conflict. * is internal to bitcoinj and can't be used on a real network. In future there may be others. </p>
*/ */
public class NetworkParameters implements Serializable { public class NetworkParameters implements Serializable {
private static final long serialVersionUID = 3L; private static final long serialVersionUID = 3L;
@ -126,6 +127,11 @@ public class NetworkParameters implements Serializable {
*/ */
public final int[] acceptableAddressCodes; public final int[] acceptableAddressCodes;
/**
* DNS names that when resolved, give active peers on the network. Used to bootstrap the P2P connectivity.
*/
private final String[] dnsSeeds;
/** /**
* Block checkpoints are a safety mechanism that hard-codes the hashes of blocks at particular heights. Re-orgs * Block checkpoints are a safety mechanism that hard-codes the hashes of blocks at particular heights. Re-orgs
@ -167,6 +173,13 @@ public class NetworkParameters implements Serializable {
checkpoints.put(91842, new Sha256Hash("00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")); checkpoints.put(91842, new Sha256Hash("00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec"));
checkpoints.put(91880, new Sha256Hash("00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721")); checkpoints.put(91880, new Sha256Hash("00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721"));
checkpoints.put(200000, new Sha256Hash("000000000000034a7dedef4a161fa058a2d67a173a90155f3a2fe6fc132e0ebf")); checkpoints.put(200000, new Sha256Hash("000000000000034a7dedef4a161fa058a2d67a173a90155f3a2fe6fc132e0ebf"));
dnsSeeds = new String[] {
"seed.bitcoin.sipa.be", // Pieter Wuille
"dnsseed.bluematt.me", // Matt Corallo
"dnsseed.bitcoin.dashjr.org", // Luke Dashjr
"bitseed.xf2.org", // Jeff Garzik
};
} else if (type == 3) { } else if (type == 3) {
// Testnet3 // Testnet3
id = ID_TESTNET; id = ID_TESTNET;
@ -188,6 +201,11 @@ public class NetworkParameters implements Serializable {
String genesisHash = genesisBlock.getHashAsString(); String genesisHash = genesisBlock.getHashAsString();
checkState(genesisHash.equals("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"), checkState(genesisHash.equals("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"),
genesisHash); genesisHash);
dnsSeeds = new String[] {
"testnet-seed.bitcoin.petertodd.org",
"testnet-seed.bluematt.me"
};
} else if (type == 2) { } else if (type == 2) {
id = ID_TESTNET; id = ID_TESTNET;
packetMagic = 0xfabfb5daL; packetMagic = 0xfabfb5daL;
@ -207,6 +225,7 @@ public class NetworkParameters implements Serializable {
String genesisHash = genesisBlock.getHashAsString(); String genesisHash = genesisBlock.getHashAsString();
checkState(genesisHash.equals("00000007199508e34a9ff81e6ec0c477a4cccff2a4767a8eee39c11db367b008"), checkState(genesisHash.equals("00000007199508e34a9ff81e6ec0c477a4cccff2a4767a8eee39c11db367b008"),
genesisHash); genesisHash);
dnsSeeds = null;
} else if (type == -1) { } else if (type == -1) {
id = ID_UNITTESTNET; id = ID_UNITTESTNET;
packetMagic = 0x0b110907; packetMagic = 0x0b110907;
@ -223,6 +242,7 @@ public class NetworkParameters implements Serializable {
spendableCoinbaseDepth = 5; spendableCoinbaseDepth = 5;
acceptableAddressCodes = new int[] { 111 }; acceptableAddressCodes = new int[] { 111 };
subsidyDecreaseBlockCount = 100; subsidyDecreaseBlockCount = 100;
dnsSeeds = null;
} else { } else {
throw new RuntimeException(); throw new RuntimeException();
} }
@ -361,4 +381,9 @@ public class NetworkParameters implements Serializable {
public int getSubsidyDecreaseBlockCount() { public int getSubsidyDecreaseBlockCount() {
return subsidyDecreaseBlockCount; return subsidyDecreaseBlockCount;
} }
/** Returns DNS names that when resolved, give IP addresses of active peers. */
public String[] getDnsSeeds() {
return dnsSeeds;
}
} }

View File

@ -510,7 +510,7 @@ public class PeerGroup extends AbstractIdleService {
Set<PeerAddress> addressSet = Sets.newHashSet(); Set<PeerAddress> addressSet = Sets.newHashSet();
for (PeerDiscovery peerDiscovery : peerDiscoverers) { for (PeerDiscovery peerDiscovery : peerDiscoverers) {
InetSocketAddress[] addresses; InetSocketAddress[] addresses;
addresses = peerDiscovery.getPeers(10, TimeUnit.SECONDS); addresses = peerDiscovery.getPeers(5, TimeUnit.SECONDS);
for (InetSocketAddress address : addresses) addressSet.add(new PeerAddress(address)); for (InetSocketAddress address : addresses) addressSet.add(new PeerAddress(address));
if (addressSet.size() > 0) break; if (addressSet.size() > 0) break;
} }

View File

@ -42,8 +42,7 @@ import java.util.concurrent.*;
* *
* <p>DNS seeds do not attempt to enumerate every peer on the network. {@link DnsDiscovery#getPeers(long, java.util.concurrent.TimeUnit)} * <p>DNS seeds do not attempt to enumerate every peer on the network. {@link DnsDiscovery#getPeers(long, java.util.concurrent.TimeUnit)}
* will return up to 30 random peers from the set of those returned within the timeout period. If you want more peers * will return up to 30 random peers from the set of those returned within the timeout period. If you want more peers
* to connect to, you need to discover them via other means (like addr broadcasts). * to connect to, you need to discover them via other means (like addr broadcasts).</p>
* </p>
*/ */
public class DnsDiscovery implements PeerDiscovery { public class DnsDiscovery implements PeerDiscovery {
private static final Logger log = LoggerFactory.getLogger(DnsDiscovery.class); private static final Logger log = LoggerFactory.getLogger(DnsDiscovery.class);
@ -51,20 +50,13 @@ public class DnsDiscovery implements PeerDiscovery {
private String[] hostNames; private String[] hostNames;
private NetworkParameters netParams; private NetworkParameters netParams;
public static final String[] defaultHosts = new String[]{
"seed.bitcoin.sipa.be", // Pieter Wuille
"dnsseed.bluematt.me", // Matt Corallo
"dnsseed.bitcoin.dashjr.org", // Luke Dashjr
"bitseed.xf2.org", // Jeff Garzik
};
/** /**
* Supports finding peers through DNS A records. Community run DNS entry points will be used. * Supports finding peers through DNS A records. Community run DNS entry points will be used.
* *
* @param netParams Network parameters to be used for port information. * @param netParams Network parameters to be used for port information.
*/ */
public DnsDiscovery(NetworkParameters netParams) { public DnsDiscovery(NetworkParameters netParams) {
this(getDefaultHostNames(), netParams); this(netParams.getDnsSeeds(), netParams);
} }
/** /**
@ -122,14 +114,7 @@ public class DnsDiscovery implements PeerDiscovery {
ArrayList<InetSocketAddress> shuffledAddrs = new ArrayList<InetSocketAddress>(addrs); ArrayList<InetSocketAddress> shuffledAddrs = new ArrayList<InetSocketAddress>(addrs);
Collections.shuffle(shuffledAddrs); Collections.shuffle(shuffledAddrs);
pool.shutdown(); pool.shutdown();
return shuffledAddrs.toArray(new InetSocketAddress[]{}); return shuffledAddrs.toArray(new InetSocketAddress[shuffledAddrs.size()]);
}
/**
* Returns the well known discovery host names on the production network.
*/
public static String[] getDefaultHostNames() {
return defaultHosts;
} }
/** We don't have a way to abort a DNS lookup, so this does nothing */ /** We don't have a way to abort a DNS lookup, so this does nothing */

View File

@ -30,7 +30,10 @@ import java.util.concurrent.TimeUnit;
/** /**
* IrcDiscovery provides a way to find network peers by joining a pre-agreed rendevouz point on the LFnet IRC network. * IrcDiscovery provides a way to find network peers by joining a pre-agreed rendevouz point on the LFnet IRC network.
* <b>This class is deprecated because LFnet has ceased to operate and DNS seeds now exist for both prod and test
* networks.</b> It may conceivably still be useful for running small ad-hoc networks by yourself.
*/ */
@Deprecated
public class IrcDiscovery implements PeerDiscovery { public class IrcDiscovery implements PeerDiscovery {
private static final Logger log = LoggerFactory.getLogger(IrcDiscovery.class); private static final Logger log = LoggerFactory.getLogger(IrcDiscovery.class);

View File

@ -1,50 +0,0 @@
/**
* Copyright John Sample
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.bitcoin.discovery;
import org.junit.Test;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import static org.junit.Assert.assertEquals;
public class IrcDiscoveryTest {
// TODO: Inject a mock IRC server and more thoroughly exercise this class.
@Test
public void testParseUserList() throws UnknownHostException {
// Test some random addresses grabbed from the channel.
String[] userList = new String[]{ "x201500200","u4stwEBjT6FYyVV", "u5BKEqDApa8SbA7"};
ArrayList<InetSocketAddress> addresses = IrcDiscovery.parseUserList(userList);
// Make sure the "x" address is excluded.
assertEquals("Too many addresses.", 2, addresses.size());
String[] ips = new String[]{"69.4.98.82:8333","74.92.222.129:8333"};
InetSocketAddress[] decoded = addresses.toArray(new InetSocketAddress[]{});
for (int i = 0; i < decoded.length; i++) {
String formattedIP = decoded[i].getAddress().getHostAddress() + ":" + ((Integer)decoded[i].getPort())
.toString();
assertEquals("IPs decoded improperly", ips[i], formattedIP);
}
}
}

View File

@ -19,7 +19,6 @@ package com.google.bitcoin.examples;
import com.google.bitcoin.core.*; import com.google.bitcoin.core.*;
import com.google.bitcoin.crypto.KeyCrypterException; import com.google.bitcoin.crypto.KeyCrypterException;
import com.google.bitcoin.discovery.DnsDiscovery; import com.google.bitcoin.discovery.DnsDiscovery;
import com.google.bitcoin.discovery.IrcDiscovery;
import com.google.bitcoin.store.BlockStore; import com.google.bitcoin.store.BlockStore;
import com.google.bitcoin.store.SPVBlockStore; import com.google.bitcoin.store.SPVBlockStore;
import com.google.bitcoin.utils.BriefLogFormatter; import com.google.bitcoin.utils.BriefLogFormatter;
@ -101,11 +100,7 @@ public class PingService {
chain = new BlockChain(params, wallet, blockStore); chain = new BlockChain(params, wallet, blockStore);
peerGroup = new PeerGroup(params, chain); peerGroup = new PeerGroup(params, chain);
peerGroup.setUserAgent("PingService", "1.0"); peerGroup.setUserAgent("PingService", "1.0");
if (testNet) { peerGroup.addPeerDiscovery(new DnsDiscovery(params));
peerGroup.addPeerDiscovery(new IrcDiscovery("#bitcoinTEST3"));
} else {
peerGroup.addPeerDiscovery(new DnsDiscovery(params));
}
peerGroup.addWallet(wallet); peerGroup.addWallet(wallet);
// We want to know when the balance changes. // We want to know when the balance changes.

View File

@ -20,7 +20,6 @@ import com.google.bitcoin.core.NetworkParameters;
import com.google.bitcoin.core.TCPNetworkConnection; import com.google.bitcoin.core.TCPNetworkConnection;
import com.google.bitcoin.core.VersionMessage; import com.google.bitcoin.core.VersionMessage;
import com.google.bitcoin.discovery.DnsDiscovery; import com.google.bitcoin.discovery.DnsDiscovery;
import com.google.bitcoin.discovery.IrcDiscovery;
import com.google.bitcoin.discovery.PeerDiscoveryException; import com.google.bitcoin.discovery.PeerDiscoveryException;
import com.google.bitcoin.utils.BriefLogFormatter; import com.google.bitcoin.utils.BriefLogFormatter;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
@ -35,10 +34,10 @@ import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
* Prints a list of IP addresses connected to the rendezvous point on the LFnet IRC channel. * Prints a list of IP addresses obtained from DNS.
*/ */
public class PrintPeers { public class PrintPeers {
private static InetSocketAddress[] dnsPeers, ircPeers; private static InetSocketAddress[] dnsPeers;
private static void printElapsed(long start) { private static void printElapsed(long start) {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
@ -48,28 +47,10 @@ public class PrintPeers {
private static void printPeers(InetSocketAddress[] addresses) { private static void printPeers(InetSocketAddress[] addresses) {
for (InetSocketAddress address : addresses) { for (InetSocketAddress address : addresses) {
String hostAddress = address.getAddress().getHostAddress(); String hostAddress = address.getAddress().getHostAddress();
System.out.println(String.format("%s:%d", hostAddress.toString(), address.getPort())); System.out.println(String.format("%s:%d", hostAddress, address.getPort()));
} }
} }
private static void printIRC() throws PeerDiscoveryException {
long start = System.currentTimeMillis();
IrcDiscovery d = new IrcDiscovery("#bitcoinTEST3") {
@Override
protected void onIRCReceive(String message) {
System.out.println("<- " + message);
}
@Override
protected void onIRCSend(String message) {
System.out.println("-> " + message);
}
};
ircPeers = d.getPeers(10, TimeUnit.SECONDS);
printPeers(ircPeers);
printElapsed(start);
}
private static void printDNS() throws PeerDiscoveryException { private static void printDNS() throws PeerDiscoveryException {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
DnsDiscovery dns = new DnsDiscovery(NetworkParameters.prodNet()); DnsDiscovery dns = new DnsDiscovery(NetworkParameters.prodNet());
@ -80,15 +61,12 @@ public class PrintPeers {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
BriefLogFormatter.init(); BriefLogFormatter.init();
System.out.println("=== IRC ===");
printIRC();
System.out.println("=== DNS ==="); System.out.println("=== DNS ===");
printDNS(); printDNS();
System.out.println("=== Version/chain heights ==="); System.out.println("=== Version/chain heights ===");
ArrayList<InetAddress> addrs = new ArrayList<InetAddress>(); ArrayList<InetAddress> addrs = new ArrayList<InetAddress>();
for (InetSocketAddress peer : dnsPeers) addrs.add(peer.getAddress()); for (InetSocketAddress peer : dnsPeers) addrs.add(peer.getAddress());
for (InetSocketAddress peer : ircPeers) addrs.add(peer.getAddress());
System.out.println("Scanning " + addrs.size() + " peers:"); System.out.println("Scanning " + addrs.size() + " peers:");
final NetworkParameters params = NetworkParameters.prodNet(); final NetworkParameters params = NetworkParameters.prodNet();

View File

@ -18,8 +18,6 @@ package com.google.bitcoin.examples.toywallet;
import com.google.bitcoin.core.*; import com.google.bitcoin.core.*;
import com.google.bitcoin.discovery.DnsDiscovery; import com.google.bitcoin.discovery.DnsDiscovery;
import com.google.bitcoin.discovery.IrcDiscovery;
import com.google.bitcoin.store.BoundedOverheadBlockStore;
import com.google.bitcoin.store.H2FullPrunedBlockStore; import com.google.bitcoin.store.H2FullPrunedBlockStore;
import com.google.bitcoin.store.SPVBlockStore; import com.google.bitcoin.store.SPVBlockStore;
import com.google.bitcoin.utils.BriefLogFormatter; import com.google.bitcoin.utils.BriefLogFormatter;
@ -174,11 +172,7 @@ public class ToyWallet {
peerGroup = new PeerGroup(params, chain); peerGroup = new PeerGroup(params, chain);
peerGroup.setUserAgent("ToyWallet", "1.0"); peerGroup.setUserAgent("ToyWallet", "1.0");
if (testnet) { peerGroup.addPeerDiscovery(new DnsDiscovery(params));
peerGroup.addPeerDiscovery(new IrcDiscovery("#bitcoinTEST3"));
} else {
peerGroup.addPeerDiscovery(new DnsDiscovery(params));
}
peerGroup.addWallet(wallet); peerGroup.addWallet(wallet);
// Watch for peers coming and going so we can update the UI. // Watch for peers coming and going so we can update the UI.

View File

@ -19,7 +19,6 @@ package com.google.bitcoin.tools;
import com.google.bitcoin.core.*; import com.google.bitcoin.core.*;
import com.google.bitcoin.crypto.KeyCrypterException; import com.google.bitcoin.crypto.KeyCrypterException;
import com.google.bitcoin.discovery.DnsDiscovery; import com.google.bitcoin.discovery.DnsDiscovery;
import com.google.bitcoin.discovery.IrcDiscovery;
import com.google.bitcoin.discovery.PeerDiscovery; import com.google.bitcoin.discovery.PeerDiscovery;
import com.google.bitcoin.store.*; import com.google.bitcoin.store.*;
import com.google.bitcoin.utils.BriefLogFormatter; import com.google.bitcoin.utils.BriefLogFormatter;
@ -272,17 +271,16 @@ public class WalletTool {
logger = LogManager.getLogManager().getLogger(""); logger = LogManager.getLogManager().getLogger("");
logger.setLevel(Level.SEVERE); logger.setLevel(Level.SEVERE);
} }
discovery = new DnsDiscovery(params);
switch (netFlag.value(options)) { switch (netFlag.value(options)) {
case PROD: case PROD:
params = NetworkParameters.prodNet(); params = NetworkParameters.prodNet();
chainFileName = new File("prodnet.chain"); chainFileName = new File("prodnet.chain");
discovery = new DnsDiscovery(params);
break; break;
case TEST: case TEST:
params = NetworkParameters.testNet(); params = NetworkParameters.testNet();
chainFileName = new File("testnet.chain"); chainFileName = new File("testnet.chain");
discovery = new IrcDiscovery("#bitcoinTEST3");
break; break;
default: default:
throw new RuntimeException("Unreachable."); throw new RuntimeException("Unreachable.");