원문 캡처 · github.com
원문 캡처 · github.com

p2pIM은 작업증명(Proof of Work, PoW)을 스팸 방지에 사용하는 P2P(피어 투 피어) 인스턴트 메시징 시스템이다. 메시지가 클수록 더 강한 작업증명이 필요하며, 작업증명은 시간이 지나면서 약해져 새 메시지가 들어올 여지를 만든다. 저장소에는 두 가지 서버 프로토타입과 메시지 생성 도구가 포함돼 있다.

프로토타입 서버 2 사용법

첫 번째 서버를 실행하고 브라우저에서 http://127.0.1.0:8000을 연다. 메시지를 입력하고 엔터를 누르면 전송된다. 페이지를 새로 고치며 약 10초 기다리면 해당 메시지의 작업증명 값이 증가하는 것을 볼 수 있다. 값이 낮을수록 좋다. --update-pow로 작업증명 갱신 간격을 바꿀 수 있다.

메시지를 3~4개 더 보내면 작업증명 값이 가장 큰 메시지가 사라질 수 있다. --mem으로 메시지에 할당하는 메모리 양을 조절할 수 있다. 메시지를 계속 보내면 논스(nonce)가 aaaaaaaaaa에서 증가해 기존 메시지보다 나은 작업증명을 만들고, 기존 메시지를 대체한다. 또는 이전 메시지의 작업증명이 약해질 때까지 기다리면 더 낮은 작업증명으로 새 메시지를 받아들일 수 있다.

sh
$ ./server2.py --ui-addr 127.0.1.0 --comm-addr 127.0.1.0

두 번째 서버를 실행한 뒤 브라우저에서 http://127.0.2.0:8000을 연다. 두 번째 서버의 피어 목록에 첫 번째 서버의 통신 URL인 http://127.0.1.0:6000을 추가한다. 몇 초 뒤 페이지를 새로 고치면 첫 번째 서버의 메시지가 두 번째 서버로 전송된 것을 확인할 수 있다. --peer-interval로 피어 확인 간격을 바꿀 수 있다.

sh
$ ./server2.py --ui-addr 127.0.2.0 --comm-addr 127.0.2.0

통신 포트에서는 curl로도 서버와 통신할 수 있다.

sh
$ curl http://127.0.2.0:6000/peers
http://127.0.1.0:6000/

$ curl http://127.0.2.0:6000/ids
20790578
9615130
70494565
17993413

$ curl http://127.0.2.0:6000/get/70494565
["0","20261010082449","aaaaaaaaaa","ab530a13e459","message"]

통신 형식은 messages.py의 Message_v0 클래스에 설명돼 있다. generate1.py로 올바른 형식의 메시지를 만들 수 있다.

sh
$ curl http://127.0.2.0:6000/put/$(urlencode \\
 $(./generate1.py "another message"))
Required PoW: 0x00235572

오류가 발생해 응답이 ok가 아니면 더 나은, 즉 더 작은 작업증명 값으로 다시 시도한다.

sh
$ curl http://127.0.2.0:6000/put/$(urlencode \\
 $(./generate1.py "another message" --pow 10000))
ok

프로토타입 서버 1 사용법

generate1.py로 페이로드가 hello world인 메시지를 출력한다.

sh
$ ./generate1.py "hello world"
["0","20251109124254","aaaaaaaaaa","b94d27b9934d","hello world"]

한 터미널에서 server1.py를 실행한다.

sh
./server1.py

다른 터미널에서는 generate1.py와 socat을 사용해 메시지를 보낸다.

sh
$ ./generate1.py test1 | tr -d \\\n | socat - TCP:localhost:8765
ok
$ ./generate1.py test2 | tr -d \\\n | socat - TCP:localhost:8765
ok

제어 메시지 __messages__로 server1.py에 저장된 메시지를 조회한다.

sh
$ ./generate1.py __messages__ | tr -d \\\n | socat - TCP:localhost:8765
["0","20251109105926","aaaaaaaaaa","1b4f0e985197","test1"]
["0","20251109105930","aaaaaaaaaa","60303ae22b99","test2"]

옵션은 ./generate1.py --help에서 확인할 수 있다.

서버 1 간 메시지 전송

두 번째 server1.py를 포트 8764에서 실행한다.

sh
./server1.py --port 8764

첫 번째 서버의 포트 8765에 있는 모든 메시지를 두 번째 서버로 보낸다.

sh
$ for m in $(./generate1.py __messages__ | tr -d \\\n | socat - TCP:localhost:8765); do echo $m | tr -d \\\n | socat - TCP:localhost:8764; done
ok
ok

구현 및 명세

메시지 형식은 messages.py의 Message_v0 클래스에 설명돼 있으며, 옵션은 ./server1.py --help에서 확인할 수 있다.