본문 바로가기
IT/이더리움 Ethereum

이더리움 geth 멀티 노드 만들기 . private test network

by SidePower 2022. 9. 21.

 

geth 클라이언트를 여러대 만들어서

테스트넷에서도 실제로 메인넷처럼 노드들이 각자 채굴하고 

서로 송금하는 트랜젝션을 발생시켜 보려고요.

 

동일한 이더리움 네트워크로 연결하기 위해서는

genesis.json과 networkid를 같은 걸로 지정하면 됩니다.

 

노드마다 다른 컴퓨터로 한다면

나머지는 다른 설정들도 동일하게 지정해도 되겠죠.

그치만 여건이 안되어 리눅스 서버 한대에 3개의 geth 클라이언트를 구성합니다.

 

 다르게 해야 될 설정값

 데이터 디렉터리

 --port

   이더리움 클라이언트 listen 포트

 --http.port

   HTTP-RPC server listen 포트 . http rpc 사용시

 --ws.port

   WS-RPC server listen 포트 . ws(WebSocket) rpc 사용시

 

 

 테스트넷 구성

 TestNet_1
nohup geth --networkid 55 --allow-insecure-unlock --datadir /home/tmach/gethmain/testnet_1 --port 30303 --http --http.addr "0.0.0.0" --http.port 3331 --http.corsdomain "*" --http.api "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" --verbosity 6 2>>/home/tmach/gethmain/testnet_1/gethErr.log &


 TestNet_2
nohup geth --networkid 55 --allow-insecure-unlock --datadir /home/tmach/gethmain/testnet_2 --port 30304 --http --http.addr "0.0.0.0" --http.port 3332 --http.corsdomain "*" --http.api "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" --verbosity 6 2>>/home/tmach/gethmain/testnet_2/gethErr.log &


 TestNet_3
nohup geth --networkid 55 --allow-insecure-unlock --datadir /home/tmach/gethmain/testnet_3 --port 30305 --http --http.addr "0.0.0.0" --http.port 3333 --http.corsdomain "*" --http.api "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" --verbosity 6 2>>/home/tmach/gethmain/testnet_3/gethErr.log &

 

 

 노드 식별자 확인

admin 명령어로 노드에 대한 전반적인 정보를 확인할 수 있습니다.

노드 식별자 enode 값을 이용해서 멀티노드로 연결합니다.


 TestNet_1

admin
{
  datadir: "/home/tmach/gethmain/testnet_1",
  nodeInfo: {
    enode: "enode://b31dc6ed85ffa0e86314d444f55be4ab52f7beec5c3b32f27149d4ede7ac4b87d43afd7184580f099576e911ba07440798febdf91d88d0428af78ac8ebf10efd@127.0.0.1:30303",
    enr: "enr:-KO4QGOfIOY3b3JFKvOGNchAgQwWfOZ4YEXXyhrc3-EWTZL-XvyQ6fZ26CrEBq3sUlJhwGIDPOYParaiAZH6O3zSNrGGAX28nYINg2V0aMfGhEpCZCKAgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQOzHcbthf-g6GMU1ET1W-SrUve-7Fw7MvJxSdTt56xLh4RzbmFwwIN0Y3CCdl-DdWRwgnZf",
    id: "8b052ac19cd70371ab317948e8cc835b10128a6e2ede0638d3fc72253ba057e2",
    ip: "127.0.0.1",
    listenAddr: "[::]:30303",
    name: "Geth/v1.10.14-unstable-85064ed0-20211202/linux-amd64/go1.17.3",
    ports: {
      discovery: 30303,
      listener: 30303
    },
    protocols: {
      eth: {
        config: {...},
        difficulty: 16384,
        genesis: "0x04d8be6fcee0e7706d1693b818d85b2f55352a917b2fc7a6806b33caa0e469b5",
        head: "0x04d8be6fcee0e7706d1693b818d85b2f55352a917b2fc7a6806b33caa0e469b5",
        network: 55
      },
      snap: {}
    }
  },
  peers: [],
  addPeer: function(),
  addTrustedPeer: function(),
  clearHistory: function github.com/ethereum/go-ethereum/console.(*Console).clearHistory-fm(),
  exportChain: function(),
  getDatadir: function(callback),
  getNodeInfo: function(callback),
  getPeers: function(callback),
  importChain: function(),
  removePeer: function(),
  removeTrustedPeer: function(),
  sleep: function github.com/ethereum/go-ethereum/internal/jsre.MakeCallback.func1(),
  sleepBlocks: function github.com/ethereum/go-ethereum/internal/jsre.MakeCallback.func1(),
  startHTTP: function(),
  startRPC: function(),
  startWS: function(),
  stopHTTP: function(),
  stopRPC: function(),
  stopWS: function()
}



 TestNet_2

admin
{
  datadir: "/home/tmach/gethmain/testnet_2",
  nodeInfo: {
    enode: "enode://f7f5fc3ba4bbb697073a52d262aeae2cc043490f134b20809a66e6f83f5a87f9503cf61c342c69413820ebce61fc90974705a0ccde9a718ee5d3d80264934b8b@127.0.0.1:30304",
    enr: "enr:-KO4QFyLrQO4MwNUF7HZWgITyV7Gv1YAEq9fKYZ7K51z6ra7WutYBhXhJMzXGtw-qJt3zSf_TEdN4BjFmiUAt4k2fS6GAX28pd50g2V0aMfGhEpCZCKAgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQP39fw7pLu2lwc6UtJirq4swENJDxNLIICaZub4P1qH-YRzbmFwwIN0Y3CCdmCDdWRwgnZg",
    id: "2b8a5a98e8fe93a257f6dfaa1d3f08cf4a66154a483e119e2293121febb5a76d",
    ip: "127.0.0.1",
    listenAddr: "[::]:30304",
    name: "Geth/v1.10.14-unstable-85064ed0-20211202/linux-amd64/go1.17.3",
    ports: {
      discovery: 30304,
      listener: 30304
    },
    protocols: {
      eth: {
        config: {...},
        difficulty: 16384,
        genesis: "0x04d8be6fcee0e7706d1693b818d85b2f55352a917b2fc7a6806b33caa0e469b5",
        head: "0x04d8be6fcee0e7706d1693b818d85b2f55352a917b2fc7a6806b33caa0e469b5",
        network: 55
      },
      snap: {}
    }
  },
  peers: [],
  addPeer: function(),
  addTrustedPeer: function(),
  clearHistory: function github.com/ethereum/go-ethereum/console.(*Console).clearHistory-fm(),
  exportChain: function(),
  getDatadir: function(callback),
  getNodeInfo: function(callback),
  getPeers: function(callback),
  importChain: function(),
  removePeer: function(),
  removeTrustedPeer: function(),
  sleep: function github.com/ethereum/go-ethereum/internal/jsre.MakeCallback.func1(),
  sleepBlocks: function github.com/ethereum/go-ethereum/internal/jsre.MakeCallback.func1(),
  startHTTP: function(),
  startRPC: function(),
  startWS: function(),
  stopHTTP: function(),
  stopRPC: function(),
  stopWS: function()
}


 TestNet_3

admin
{
  datadir: "/home/tmach/gethmain/testnet_3",
  nodeInfo: {
    enode: "enode://46e3008ef0bb73adc1a53a56e1cedadc40f2ecec75a4b789933acc448585793fd2d6b7faf8f43b517b424534313c5a7e26d882f4b4094c4286cda6da6b970aaa@127.0.0.1:30305",
    enr: "enr:-KO4QAkLZQxRwMQchmWO6Zq-6ojjsx8kR9cDQXFD1JYpqBjYGa1lQ154N_FXsDS-1Hi4rqXQ9qnkOvN2MwIh0Onf0v-GAX28_CJLg2V0aMfGhEpCZCKAgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQJG4wCO8LtzrcGlOlbhztrcQPLs7HWkt4mTOsxEhYV5P4RzbmFwwIN0Y3CCdmGDdWRwgnZh",
    id: "1ecd97b855a192f6b74a92bea2288dfcc838614c8b82c802c2d9d658c7fafc0a",
    ip: "127.0.0.1",
    listenAddr: "[::]:30305",
    name: "Geth/v1.10.14-unstable-85064ed0-20211202/linux-amd64/go1.17.3",
    ports: {
      discovery: 30305,
      listener: 30305
    },
    protocols: {
      eth: {
        config: {...},
        difficulty: 16384,
        genesis: "0x04d8be6fcee0e7706d1693b818d85b2f55352a917b2fc7a6806b33caa0e469b5",
        head: "0x04d8be6fcee0e7706d1693b818d85b2f55352a917b2fc7a6806b33caa0e469b5",
        network: 55
      },
      snap: {}
    }
  },
  peers: [],
  addPeer: function(),
  addTrustedPeer: function(),
  clearHistory: function github.com/ethereum/go-ethereum/console.(*Console).clearHistory-fm(),
  exportChain: function(),
  getDatadir: function(callback),
  getNodeInfo: function(callback),
  getPeers: function(callback),
  importChain: function(),
  removePeer: function(),
  removeTrustedPeer: function(),
  sleep: function github.com/ethereum/go-ethereum/internal/jsre.MakeCallback.func1(),
  sleepBlocks: function github.com/ethereum/go-ethereum/internal/jsre.MakeCallback.func1(),
  startHTTP: function(),
  startRPC: function(),
  startWS: function(),
  stopHTTP: function(),
  stopRPC: function(),
  stopWS: function()
}


 admin.nodeInfo.enode 명령어로 간단하게 알수도 있습니다.
> admin.nodeInfo.enode
"enode://b31dc6ed85ffa0e86314d444f55be4ab52f7beec5c3b32f27149d4ede7ac4b87d43afd7184580f099576e911ba07440798febdf91d88d0428af78ac8ebf10efd@127.0.0.1:30303"

 

 노드 연결 하기

admin.addPeer 명령어로 연결할수 있어요.

 

TestNet_1노드를 이더리움 메인노드로 정하고

다른 노드들이 메인노드에 연결하게 구성할거에요.

① TestNet_2 노드에서 TestNet_1 노드로 연결 요청하기

② TestNet_3 노드에서 TestNet_1 노드로 연결 요청하기


 TestNet_2에서 실행
> admin.addPeer("enode://b31dc6ed85ffa0e86314d444f55be4ab52f7beec5c3b32f27149d4ede7ac4b87d43afd7184580f099576e911ba07440798febdf91d88d0428af78ac8ebf10efd@127.0.0.1:30303")
true
>
 TestNet_1의 enode를 addPeer에 입력.



 TestNet_3에서 실행
> admin.addPeer("enode://b31dc6ed85ffa0e86314d444f55be4ab52f7beec5c3b32f27149d4ede7ac4b87d43afd7184580f099576e911ba07440798febdf91d88d0428af78ac8ebf10efd@127.0.0.1:30303")
true
>
 TestNet_1의 enode를 addPeer에 입력.

 

 노드 연결되었는지 확인

admin.peers 명령어로 연결된 노드들을 확인할수 있습니다.


 TestNet_2에서 실행

> admin.peers

[{
    caps: ["eth/66", "snap/1"],
    enode: "enode://b31dc6ed85ffa0e86314d444f55be4ab52f7beec5c3b32f27149d4ede7ac4b87d43afd7184580f099576e911ba07440798febdf91d88d0428af78ac8ebf10efd@127.0.0.1:30303",
    id: "8b052ac19cd70371ab317948e8cc835b10128a6e2ede0638d3fc72253ba057e2",
    name: "Geth/v1.10.14-unstable-85064ed0-20211202/linux-amd64/go1.17.3",
    network: {
      inbound: false,
      localAddress: "127.0.0.1:53884",
      remoteAddress: "127.0.0.1:30303",
      static: true,
      trusted: false
    },
    protocols: {
      eth: {
        difficulty: 16384,
        head: "0x04d8be6fcee0e7706d1693b818d85b2f55352a917b2fc7a6806b33caa0e469b5",
        version: 66
      },
      snap: {
        version: 1
      }
    }
}]
>
 peer의 enode값이 TestNet_1의 enode값으로 지정되며
     remoteAddress값이 TestNet_1의 IP:Port로 지정됨을 확인됩니다.



 TestNet_3에서 실행
> admin.peers
[{
    caps: ["eth/66", "snap/1"],
    enode: "enode://b31dc6ed85ffa0e86314d444f55be4ab52f7beec5c3b32f27149d4ede7ac4b87d43afd7184580f099576e911ba07440798febdf91d88d0428af78ac8ebf10efd@127.0.0.1:30303",
    id: "8b052ac19cd70371ab317948e8cc835b10128a6e2ede0638d3fc72253ba057e2",
    name: "Geth/v1.10.14-unstable-85064ed0-20211202/linux-amd64/go1.17.3",
    network: {
      inbound: false,
      localAddress: "127.0.0.1:53996",
      remoteAddress: "127.0.0.1:30303",
      static: true,
      trusted: false
    },
    protocols: {
      eth: {
        difficulty: 16384,
        head: "0x04d8be6fcee0e7706d1693b818d85b2f55352a917b2fc7a6806b33caa0e469b5",
        version: 66
      },
      snap: {
        version: 1
      }
    }
}]
 peer의 enode값이 TestNet_1의 enode값으로 지정되며
     remoteAddress값이 TestNet_1의 IP:Port로 지정됨을 확인됩니다.




 TestNet_1에서 실행
> admin.peers
[{
    caps: ["eth/66", "snap/1"],
    enode: "enode://46e3008ef0bb73adc1a53a56e1cedadc40f2ecec75a4b789933acc448585793fd2d6b7faf8f43b517b424534313c5a7e26d882f4b4094c4286cda6da6b970aaa@127.0.0.1:53996",
    id: "1ecd97b855a192f6b74a92bea2288dfcc838614c8b82c802c2d9d658c7fafc0a",
    name: "Geth/v1.10.14-unstable-85064ed0-20211202/linux-amd64/go1.17.3",
    network: {
      inbound: true,
      localAddress: "127.0.0.1:30303",
      remoteAddress: "127.0.0.1:53996",
      static: false,
      trusted: false
    },
    protocols: {
      eth: {
        difficulty: 16384,
        head: "0x04d8be6fcee0e7706d1693b818d85b2f55352a917b2fc7a6806b33caa0e469b5",
        version: 66
      },
      snap: {
        version: 1
      }
    }
}, {
    caps: ["eth/66", "snap/1"],
    enode: "enode://f7f5fc3ba4bbb697073a52d262aeae2cc043490f134b20809a66e6f83f5a87f9503cf61c342c69413820ebce61fc90974705a0ccde9a718ee5d3d80264934b8b@127.0.0.1:53884",
    id: "2b8a5a98e8fe93a257f6dfaa1d3f08cf4a66154a483e119e2293121febb5a76d",
    name: "Geth/v1.10.14-unstable-85064ed0-20211202/linux-amd64/go1.17.3",
    network: {
      inbound: true,
      localAddress: "127.0.0.1:30303",
      remoteAddress: "127.0.0.1:53884",
      static: false,
      trusted: false
    },
    protocols: {
      eth: {
        difficulty: 16384,
        head: "0x04d8be6fcee0e7706d1693b818d85b2f55352a917b2fc7a6806b33caa0e469b5",
        version: 66
      },
      snap: {
        version: 1
      }
    }
}]
>
▶ peer 정보가 2개 표시되네요.
     enode값이 TestNet_2와 TestNet_3로 각각 지정된거 보이네요.

이렇게 각 노드마다 연결된 peer 를 확인할수 있어요.

 

 network 상태 체크

net 명령어 사용으로 peerCount로 연결 개수를 확인할수 있습니다.


 TestNet_1에서 실행
> net
{
  listening: true,
  peerCount: 2,
  version: "55",
  getListening: function(callback),
  getPeerCount: function(callback),
  getVersion: function(callback)
}
>

 TestNet_2에서 실행
> net
{
  listening: true,
  peerCount: 1,
  version: "55",
  getListening: function(callback),
  getPeerCount: function(callback),
  getVersion: function(callback)
}

 TestNet_3에서 실행
> net
{
  listening: true,
  peerCount: 1,
  version: "55",
  getListening: function(callback),
  getPeerCount: function(callback),
  getVersion: function(callback)
}


 net.listening과 net.peerCount 명령어로도
통신 가능한 상태인지 연결된 노드가 몇개인지 알수 있어요.
> net.listening
true
> net.peerCount
2

다음에 3개의 노드로 송금 트랜젝션을 발생시키고

채굴해서 노드 간에 잘 통신이 되는지 확인해 볼게요.

 

 

감사합니다.

반응형

댓글