오랜만에 개발 이야기를 씁니다.
이더리움 풀을 운영하는 경우, geth 노드로부터 전달받을 수 있는 마이닝 작업을 getWork JSONRPC 호출을 통해 가져오고, 이렇게 가져온 마이닝 작업(getWork)를 풀에 연결된 마이너에게 뿌려 주는 방식을 사용하고 있습니다.
대표적인 예로 open-ethereum-pool의 경우, 풀에 연결된 노드에 getWork JSONRPC 요청을 120ms 간격으로 받아서
새로운 마이닝 작업이 발견되면 이를 마이너에게 뿌려주는 방식이죠.
https://github.com/sammy007/open-ethereum-pool/blob/master/config.example.json#L12 (오픈-이더리움-풀 소스코드의 기본 값이 120ms)
이를 도식화 해보면 새로운 마이닝 작업은 3단계를 통해 들어오게 되는 것입니다.
(풀) -- JSON RPC CALL --> (노드) -- JSON RPC 응답 --> (풀) --> JSON RPC notify --> (마이너)
그러나 이 방식 보다는 다음과 같은 방식을 쓴다면 이는 2단계가 되어 마이닝 작업이 좀 더 빠르게 전송이 될 것입니다.
(노드) -- 새작업 정보 알림 --> (풀) -- JSON RPC notify --> (마이너)
응답 속도가 대략 10ms라고 했을때에, 기존 3단계의 경우 120 ms + 10ms * 3 = 150ms 즉, 최소 지연이 30ms ~ 최대 지연 150ms
notify 방식은 지연이 없으므로 2단계 응답속도인 10ms * 2 = 20ms 정도의 응답 속도를 가지게 됩니다.
이러한 푸쉬 방식을 2018년까지 geth 노드에서 제대로 지원하지 않고 있다가 2018년 8월부터 --miner.notify 옵션을 통해 지원하고 있습니다.
푸쉬 notify 소스코드 위치 https://github.com/ethereum/go-ethereum/blob/master/consensus/ethash/sealer.go#L359-L366
커밋 2018년 8월 8일 https://github.com/ethereum/go-ethereum/commit/f0998415ba9a73f0add32f9b5aed2aec98b9a7f3
Geth v1.8.14 버전부터 지원 시작. (2018년 8월22일)
다만 geth의 --miner.notify 옵션을 open-ethereum-pool에서 지원하지 않고 있기때문에 이를 지원하려면 open-ethereum-pool 소스코드를 수정해야 합니다. (제가 기존 소스코드를 참조해서 고친 다음 소스코드를 참조하실 수 있습니다.)
이를 풀에 실제로 적용하여 보니 다음과 같은 장점이 있었습니다.
- push notify 하는 방식이 좀 더 빠르다.
- 아주 가끔은 push notify하는 방식이 job을 세개 연속적으로 보내는 경우, 기존 방식은 두개만 보내는 경우가 있다. 즉, 기존 방식은 120ms 간격으로 getwork를 통해 끌어오면서 시간 지연등의 이유로 마이닝 job을 놓치는 경우가 있다.
- 여러 노드를 통해서 push notify하는 것이 가능하기때문에, 여러 노드중에 가장 빠르게 push notify 하는 작업이 풀을 통해 보내지게 된다.
실제로 다른 풀과 비교를 해보니 아주 미세한 차이로 pool 작업이 먼저 도착하는 것을 확인할 수 있었습니다.
open-ethereum-pool을 운영하시는 분들은 이를 참고하시기 바랍니다~
※추가: 급조한 PR입니다만 open-ethereum-pool 깃허브 PR로도 넣어보았습니다. https://github.com/sammy007/open-ethereum-pool/pull/457