Skip to content

Instantly share code, notes, and snippets.

@scottyeager
Created December 23, 2022 23:46
Show Gist options
  • Save scottyeager/8f52448b9be42078ad3783c6c1541168 to your computer and use it in GitHub Desktop.
Save scottyeager/8f52448b9be42078ad3783c6c1541168 to your computer and use it in GitHub Desktop.
Python script to fetch the peers of all peers of an Yggdrasil node
# It's a script that prints some stats about the Yggdrasil peers that your local machine is connected to, based partiall on the crawler script from https://github.com/Arceliar/yggdrasil-map. Tells how many peers each of your peers is connected to, how many unique peers there are total, and how many interconnections there are between the peers you've queried.
import json, socket, sys, time
socktype = socket.AF_UNIX
sockaddr = "/var/run/yggdrasil.sock"
def getNodeInfoRequest(key):
return '{{"keepalive":true, "request":"getNodeInfo", "arguments": {{"key":"{}"}}}}'.format(key)
def getSelfRequest(key):
return '{{"keepalive":true, "request":"debug_remoteGetSelf", "arguments": {{"key":"{}"}}}}'.format(key)
def getPeersRequest(key):
return '{{"keepalive":true, "request":"debug_remoteGetPeers", "arguments": {{"key":"{}"}}}}'.format(key)
def getSessionsRequest(key):
return '{{"keepalive":true, "request":"debug_remoteGetSessions", "arguments": {{"key":"{}"}}}}'.format(key)
def getDHTRequest(key):
return '{{"keepalive":true, "request":"debug_remoteGetDHT", "arguments": {{"key":"{}"}}}}'.format(key)
def doRequest(req):
ygg = socket.socket(socktype, socket.SOCK_STREAM)
ygg.connect(sockaddr)
ygg.send(req.encode())
data = json.loads(ygg.recv(1048576))
return data
def getSelf():
return doRequest('{"keepalive":true, "request":"getSelf"}')
def getMyKey():
return getSelf()['response']['key']
def getPeers(key):
return list(doRequest(getPeersRequest(key))['response'].values())[0]['keys']
def getPeerLists(keys):
peers = []
for key in keys:
peers.append(getPeers(key))
return peers
def uniqueSet(lists):
unique = set()
for l in lists:
for item in l:
unique.add(item)
return unique
def comparePeers(peers, lists):
return [len(set(peers) & set(l)) for l in lists]
mykey = getMyKey()
mypeers = sorted(getPeers(mykey))
peerlists = getPeerLists(mypeers)
peerlengths = [len(l) for l in peerlists]
unique = len(uniqueSet(peerlists))
common = comparePeers(mypeers, peerlists)
duplex = sum([1 if mykey in l else 0 for l in peerlists])
peerkeystrunc = [key[0:4] for key in mypeers]
print('Local peer list length: {}'.format(len(mypeers)))
print('Truncated peer keys {}'.format(peerkeystrunc))
print('Remote peer list lengths: {}'.format(peerlengths))
print('Total unique peers: {}'.format(unique))
print('Common peers from local and each remote: {}'.format(common))
print('Remotes that report local as peer: {}'.format(duplex))
@leksmut
Copy link

leksmut commented Oct 22, 2024

Minor changes to make it works on debian at 2024, yggdrasil 0.5.8

# It's a script that prints some stats about the Yggdrasil peers that your local machine is connected to, based partiall on the crawler script from https://github.com/Arceliar/yggdrasil-map. Tells how many peers each of your peers is connected to, how many unique peers there are total, and how many interconnections there are between the peers you've queried.

import json, socket, sys, time

socktype = socket.AF_UNIX
sockaddr = "/var/run/yggdrasil/yggdrasil.sock"

def getNodeInfoRequest(key):
    return '{{"keepalive":true, "request":"getNodeInfo", "arguments": {{"key":"{}"}}}}'.format(key)

def getSelfRequest(key):
    return '{{"keepalive":true, "request":"GetSelf", "arguments": {{"key":"{}"}}}}'.format(key)

def getPeersRequest(key):
    return '{{"keepalive":true, "request":"GetPeers", "arguments": {{"key":"{}"}}}}'.format(key)

def getSessionsRequest(key):
    return '{{"keepalive":true, "request":"GetSessions", "arguments": {{"key":"{}"}}}}'.format(key)

def getDHTRequest(key):
    return '{{"keepalive":true, "request":"GetDHT", "arguments": {{"key":"{}"}}}}'.format(key)

def doRequest(req):
    ygg = socket.socket(socktype, socket.SOCK_STREAM)
    ygg.connect(sockaddr)
    ygg.send(req.encode())
    data = json.loads(ygg.recv(1048576))
    return data

def getSelf():
    return doRequest('{"keepalive":true, "request":"getSelf"}')

def getMyKey():
    return getSelf()['response']['key']

def getPeers(key):
    tmp = list(doRequest(getPeersRequest(key))['response'].values())[0]
    return list({di['key']:None for di in tmp}.keys())
    
def getPeerLists(keys):
    peers = []
    for key in keys:
        peers.append(getPeers(key))
    return peers

def uniqueSet(lists):
    unique = set()
    for l in lists:
        for item in l:
            unique.add(item)
    return unique

def comparePeers(peers, lists):
    return [len(set(peers) & set(l)) for l in lists]

mykey = getMyKey()

mypeers = sorted(getPeers(mykey))
peerlists = getPeerLists(mypeers)
peerlengths = [len(l) for l in peerlists]
unique = len(uniqueSet(peerlists))
common = comparePeers(mypeers, peerlists)
duplex = sum([1 if mykey in l else 0 for l in peerlists])
peerkeystrunc = [key[0:4] for key in mypeers]

print('Local peer list length: {}'.format(len(mypeers)))
print('Truncated peer keys {}'.format(peerkeystrunc))
print('Remote peer list lengths: {}'.format(peerlengths))
print('Total unique peers: {}'.format(unique))
print('Common peers from local and each remote: {}'.format(common))
print('Remotes that report local as peer: {}'.format(duplex))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment