Ethereum Whisper 노드 구축 및 테스트
Geth를 이용하여 Ethereum 사설망을 구축하고, whisper 메시지를 전송해보는 테스트를 진행해보겠습니다. Ethereum 사설망 구축에 대해서는 온더의thomashin 님이 작성하신 Geth를이용한 private Ethereum chain 구축 을 참고하시면 좋습니다.
# 글 작성 기준, ethereum whisper v5 RPC API 문서 https://github.com/ethereum/go-ethereum/wiki/Whisper-v5-RPC-API 에 나와 있는 API 들이 변경되어 있음.
1. Intro : Whisper 란 …
- Ethereum P2P protocol 상에서 유저간 암호화 메시지 송수신 프로토콜.
— Ethereum blockchain과 동일 한 네트워크를 사용하며, whisper node간 모든 whisper 메시지를 공유한다.
— 공유 되는 메시지는 암호키를 가지고 있는 수신자만 확인이 가능하다.
— 1대1 또는1대N 메시지 전송 가능.
2. Whisper 메시지 구조
- 송신자는 목적지의 주소로서 PublicKey 또는 SymKeyID 를 가지고 있어햐 하며, Topic, payload 메시지를 삽입하여 전송 한다.
- 수신자는 자신의 노드에 filter를 설정해 둠으로써, PublicKey 해당 되는 , 또는 SymKeyID 매칭되는 메시지를 수신하여 callback function을 호출 한다.
3. Whisper 활성화
go-ethtereum, Geth 실행시 ` — shh` 플래그로 whisper 기능을 활성화 시켜주어야 한다.
whisper 기능이 정상적으로 활성화 되었다면, geth node 실행시 “started whisper v.5.0” 이 출력된다.
4. Whisper Key 생성 및 송수신 명령어
송신측, 수신측에 사용되어지는 PublicKey or SymKeyID는 아래와 같이 geth console 명령어를 통해 생성 할 수 있다.
Whisper 메시지 송신 명령어
송신자는 목적지의 주소로서 PublicKey 또는 SymKeyID를 알고 있어야 한다.
ssh.post({ PublicKey or SymKey, ttl, topic, payload, powTime, powTarget})
: 도착지 주소의 PublicKey 또는 SymKey Required
- ttl : 메시지의 Time to Live, seconds
- Topic은 메시지 제목의 주제에 해당, 수신자 필터링 되는 조건에 맞춰짐.
- Payload : 실제 메시지의 전문 내용, hex encoding
- powTime, powTarget 노드에서 설정 수치 이상 적용
Whisper 메시지 수신측 설정 명령어
수신자는 자신의 노드에 filter
를 설정해 둠으로써 publicKey 또는 SymKeyId에 해당하는 메시지가 수신되었을때 입력된 콜백함수를 실행한다.
ssh.newMessageFilter: function(options, callback, filterCreationErrorCallback)
- options 에 { privateKeyID, SymKeyID, Topic } 등 입력
- callback, filterCreationErrorCallback 함수 설정[filterId가 부여된 객체 생성]
5. Whisper 프라이빗 노드 구성
Whisper Node1 은 송신자, Whisper Node2는 수신자측 노드로 각각 설정.
( Geth를 이용한 Ethereum Node 구축에 대해서는 “ Geth를이용한 private Ethereum chain 구축”을 참고)
Node1과 Node2는 서로 연결이 되어 있지 않은 상태이므로, 메뉴얼로 두 노드를 서로 peer로 설정해 주어야 한다.
Whisper Node1 노드 설정
송신자로 사용될 Whisper Node1의 geth console 에 아래 명령어를 입력한다.
nodeinfo의 enode 주소를 저장해 놓는다. 해당 enode 주소는 Node2에서 peer 설정에 사용할것이다.
$geth — network 4382 — shh$geth attach /[data dir]/geth.ipc> admin.nodeInfo
#[capture peer node1 address] ad nodeInfo result
Whisper Node2 노드 설정
수신자로 사용될 Node2의 geth console에 아래 명령어를 입력한다.
Node1의 enode 주소를 peer로 입력한다. 마지막 admin.peers로 Node1이 Node2의 peer로 설정되어 있는지 확인한다.
$geth — network 4382 — shh$geth attach ~/[datadir/geth.ipc> admin.addPeer(“enode://[node1 enode addr]@[whisper Node1 ip]:30303”)
6. Whisper Message 송수신테스트
Whisper Node1과 Whisper Node2가 서로 Peer로 설정된 이후, 수신자측으로사용될 노드인 Node2에 message filter를 설정해주어야한다.
Generating Keys
whisper 메시지 송신자가 사용할 pubkey
를 Node2에서 생성한다. 아래 명령어를 Node2의 geth console에입력하여 publicKey
를생성한다.
> keypair = shh.newKeyPair()
> pubkey = shh.getPublicKey(keypair)
Generating Filter & callback functions
수신자로 사용될 Node2에서 메시지 수신시 적용할 filter
를 생성한다. 이때 pubkey
를 위의 과정(Generating Keys)을 통해 먼저 생성해 놓아야 한다.
cb
와 cbe
함수는 메시지수신시 filter
의조건에 맞는 메시지가 수신될때 작동하는 콜백 함수와 콜백 에러 처리함수이다.
> cb = function(err,messages){console.log(JSON.stringify(err||messages))}
> cbe = function(error){console.log(error)}
> filter = shh.newMessageFilter({privateKeyId: keypair}, cb, cbe)
filter
가 정상적으로 생성되었으면 아래와 같은 결과가 출력된다.
filter
에 options
내용이 노드의 필터로 적용되는 조건이며, 여기에 topic
과 같은 조건이 추가되면 publicKey
and topic
으로 두 조건이 모두 해당되는 메시지만 콜백함수가 작동한다. (위 예시에 privateKeyId
가 실제로 publicKey
에해당한다)
Send Whisper Message From Node1
송신자로 설정한 Node1에서 shh.post
명령어를 통해 해당 publicKey
주소로 메시지를 전송한다. ( Node2에서 생성한 pubicKey
주소로 “0x ~” 로 시작한다.)
> shh.post({pubkey:”[ pubkey generated at node 2 ]”, ttl: 30, powTime: 1, powTarget: 0.201, payload : web3.fromAscii("message from sender")})
powTarget
은 송신자로 선택한 Node1의최소요구치에 이상 설정해주어야한다. (powTarget
의 default 값은 0.2 )ttl
은 해당 메시지의 지속시간(초)으로 수치가 높을수록 높은 비용 (hash Power)가 요구된다.
Receive Message at Whisper Node 2
Node1에서 ssh.post
를 통해 메시지를 전송하면, 거의 동시에 Node2 콘솔에 아래와 같이 메시지가 출력된다.
payload
로수신한 hex코드를 변환해 보면 송신자의 메시지를 확인해 볼 수 있다.