C#

비트코인 Peer 노드 검색

비트코인 Peer 노드 검색

비트코인 클라이언트는 Peer 노드를 찾기위해 다양한 방법을 사용할 수 있는데, 여기서는 그 중 많이 쓰는 방법들을 설명한다.

  • 먼저 클라이언트는 이전에 연결했던 Peer를 캐시에서 가져와 사용할 수 있다.
  • 다음으로 DNS Seed를 사용할 수 있다. 클라이언트가 처음으로 구동되었을 때는, 이전에 사용한 Peer가 없을 것이다. 이런 경우에 일반적으로 DNS Seeding이라고 불리우는 방법을 사용한다. 즉, 비트코인 클라이언트는 DNS Seed 라고 불리우는 하나 이상의 DNS 호스트명을 쿼리하여 Peer들의 IP 정보를 얻을 수 있다. 이러한 DNS 쿼리는 현재 사용중인 Full 노드들의 IP 주소들을 리턴하게 된다. 비트코인 클라이언트는 널리 알려진 DNS Seed 들을 하드코드하여 사용하곤 하는데, 이러한 DNS Seed들은 비트코인 커뮤너티에 의해 관리된다. DNS Seed에는 네트크워 스캔을 통해 자동으로 갱신되는 Dynamic DNS Seed와 수작업으로 IP를 갱신하는 Static DNS Seed가 있다.
  • 만약 위의 방법들이 실패하면, 클라이언트는 마지막으로 하드코드된 IP 주소들을 사용하게 되는데, 하드코드된 IP 주소는 IPv6 포맷으로 chainparamsseeds.h 파일에 저장되어 있다.

여러 비트코인 클라이언트는 서로 다른 Peer 노드 검색 메카니즘을 사용한다. 예를 들어, Bitcoin Core 는 처음 11초 동안 캐쉬 (DB)로부터 전에 사용한 Peer 들을 연결하려고 시도한다. 만약 그것이 실패하면, 다음으로 60초 동안 DNS Seed 방법을 사용한다. 그리고 이마저도 실패하면, 하드코드된 IP 주소들을 사용한다. 다른 BitcoinJ 라는 클라이언트에서는 캐쉬를 사용하지 않고 바로 DNS Seed를 쿼리하여 사용하며, 이것이 실패하면 하드코드된 IP 주소들을 사용한다.

DNS Seed로부터 IP 주소들을 얻는 방법

C#에서 DNS Seed로부터 IP 주소들을 가져오기 위해서는 System.Net 네임스페이스에 있는 Dns.GetHostAddresses(dnsSeed) 메서드를 사용하면 된다. 이 메서드는 해당 DNS Seed와 연관된 모든 IP 주소들을 리턴한다.

Mainnet과 Testnet3는 서로 다른 DNS Seed를 사용한다. Mainnet DNS Seed는 chainparams.cpp 안에 있는 CMainParams 클래스에 정의되어 있으며, Testnet DNS Seed는 동일한 파일의 CTestNetParams 클래스에 정의되어 있다.
요약하면, 각 네트워크별 현재 DNS Seed 리스트는 다음과 같다.

네트워크 종류 DNS Seed
Mainnet bitseed.xf2.org
dnsseed.bluematt.me
dnsseed.bitcoin.dashjr.org
seed.bitcoinstats.com
seed.bitcoin.sipa.be
bitseed.xf2.org
seed.bitcoin.jonasschnelli.ch
Testnet3 testnet-seed.bitcoin.jonasschnelli.ch
seed.tbtc.petertodd.org
testnet-seed.bluematt.me
testnet-seed.bitcoin.schildbach.de
Regnet Regtest은 DNS Seed를 가지고 있지 않다.

아래 코드는 모든 DNS Seed들에 대해 IP 주소를 가져오는 예제이다. 비록 실제 이렇게 모든 IP 주소를 반드시 한꺼번에 가져올 필요는 없겠지만.

public List<string> FindPeersFromDnsSeeding()
{
	/*
	// Mainnet DNS Seeds
	List<string> dnsSeeds = new List<string>
	{
		"bitseed.xf2.org",
		"dnsseed.bluematt.me",                
		"dnsseed.bitcoin.dashjr.org",
		"seed.bitcoinstats.com",
		"seed.bitcoin.sipa.be",
		"bitseed.xf2.org",
		"seed.bitcoin.jonasschnelli.ch"
	};
	*/

	// Test DNS Seeds
	List<string> dnsSeeds = new List<string>
	{
		"seed.tbtc.petertodd.org",
		"testnet-seed.bitcoin.jonasschnelli.ch",		
		"testnet-seed.bluematt.me",
		"testnet-seed.bitcoin.schildbach.de"
	};

	HashSet<string> ipSet = new HashSet<string>();
	foreach (var seed in dnsSeeds)
	{
		try
		{
			// Get IP addresses from a DNS seed
			IPAddress[] ips = Dns.GetHostAddresses(seed);
			
			foreach (var ip in ips)
			{
				ipSet.Add(ip.ToString());
			}
		}
		catch (Exception ex)
		{
			Debug.WriteLine("{0}: {1}", seed, ex.ToString());
		}
	}

	return ipSet.ToList();
}

하나의 DNS Seed는 복수개의 IP 주소를 리턴한다. 예를 들어, Dns.GetHostAddresses("testnet-seed.bluematt.me") 는 다음과 같은 IP 주소들을 리턴한다. (주: 이 IP 주소들을 임의로 변경될 수 있음).

  198.251.83.19
  192.99.46.190
  50.0.37.37
  45.56.122.234
  104.236.132.224

본 웹사이트는 광고를 포함하고 있습니다. 광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.

Previous Next Print