Hyperledger Besu의 Private Networks에서 진행하는 실습입니다. 주요 내용은 공식 문서인https://besu.hyperledger.org/private-networks/tutorials 의 내용에서 발췌하였으며, Privacy Enabled Network와 Permissioned Network까지 다루고 있습니다.
This is a training ses...
Hyperledger Besu의 Private Networks에서 진행하는 실습입니다. 주요 내용은 공식 문서인https://besu.hyperledger.org/private-networks/tutorials 의 내용에서 발췌하였으며, Privacy Enabled Network와 Permissioned Network까지 다루고 있습니다.
This is a training session at Hyperledger Besu's Private Networks, with the main content excerpts from the official document besu.hyperledger.org/private-networks/tutorials and even covers the Private Enabled and Permitted Networks.
Hello World (Quorum Developer Quickstart ) Docker 를 활용한 Private Network 구성 - 필요 도구 : Docker Compose, Node.js, Hardhat, MetaMask - 실습 목적 : Private Network 구동 (5 초 마다 블록 자동 생성 ) 하여 이더리움 스마트 컨트랙트 배포 및 토큰 전송 실습 - 실습 환경 : Four Besu IBFT 2.0 validator nodes and a non-validator node are created to simulate a base network.
프로젝트 생성 및 기동 위 웹사이트의 가이드에 따라서 npx quorum-dev- quickstart 로 프로젝트 생성 - 프로젝트 생성 단계에서 ELK Stack 은 N 으로 설정 ( 설정시 docker image pull 및 기동에 상당 시간 소요 ) - 프로젝트 디렉토리 이름은 자유롭게 설정 - 생성된 프로젝트 디렉토리에서 ./ run.sh 로 기동 - 로그는 프로젝트 디렉토리에서 docker-compose logs -f docker- compose.yml 를 통해 확인 가능 - 초기에 노드간 연결이 완성되지 못해 로그에 에러 메시지가 많이 보이나 , 10 분 정도 기다리면 자동 정상화됨 - block explorer, Grafana 등 서비스 모니터링을 위한 주소 확인은 ./ list.sh - 필요 메모리 : 8GB https:// besu.hyperledger.org /private-networks/tutorials/ quickstart
hre_1559_public_tx.js - 스마트 컨트랙트 배포 - increment 함수 호출 , 특정 변수 값 +1 - decrement 함수 호출 , 특정 변수 값 -1 누가 호출하던 상관 없이 전역 count 의 값이 변경되게 예제가 구현되어 있음 async function main(){ const provider = new ethers.JsonRpcProvider (host); const wallet = new ethers.Wallet ( accountPrivateKey , provider); createContract (provider, wallet, contractAbi , contractBytecode ) .then(async function(contract){ console.log (contract); contractAddress = await contract.getAddress (); console.log ("Use the smart contracts 'get' function to read the contract's initialized value .. " ) await getValueAtAddress (provider, contractAbi , contractAddress ); console.log ("Use the smart contracts 'increment' function to update that value .. " ); await incrementValueAtAddress (provider, wallet, contractAbi , contractAddress ); console.log ("Verify the updated value that was set .. " ) await getValueAtAddress (provider, contractAbi , contractAddress ); console.log ("Use the smart contracts 'decrement' function to update that value .. " ); await decrementValueAtAddress (provider, wallet, contractAbi , contractAddress ); console.log ("Verify the updated value that was set .. " ) await getValueAtAddress (provider, contractAbi , contractAddress ); }) .catch( console.error ); } source : https:// besu.hyperledger.org /private-networks
hre_1559_public_tx.js node scripts/public/ hre_1559_public_tx.js BaseContract { target: ' 0xBca0fDc68d9b21b5bfB16D784389807017B2bbbc ', interface: Interface { fragments: [ [ FunctionFragment ], [ FunctionFragment ], [ FunctionFragment ] ], deploy: ConstructorFragment { type: 'constructor', inputs: [], payable: false, gas: null }, fallback: null, receive: false }, runner: Wallet { provider: JsonRpcProvider {}, address: ' 0xC9C913c8c3C1Cd416d80A0abF475db2062F161f6 ' }, filters: {}, fallback: null, [Symbol(_ ethersInternal_contract )]: {} } Use the smart contracts 'get' function to read the contract's initialized value .. Obtained value at deployed contract is: 0 Use the smart contracts 'increment' function to update that value .. Verify the updated value that was set .. Obtained value at deployed contract is: 1 Use the smart contracts 'decrement' function to update that value .. Verify the updated value that was set .. Obtained value at deployed contract is: 0 source : https:// besu.hyperledger.org /private-networks
node scripts/public/ hre_1559_public_tx.js BaseContract { target: ' 0xBca0fDc68d9b21b5bfB16D784389807017B2bbbc ', interface: Interface { fragments: [ [ FunctionFragment ], [ FunctionFragment ], [ FunctionFragment ] ], deploy: ConstructorFragment { type: 'constructor', inputs: [], payable: false, gas: null }, fallback: null, receive: false }, runner: Wallet { provider: JsonRpcProvider {}, address: ' 0xC9C913c8c3C1Cd416d80A0abF475db2062F161f6 ' }, filters: {}, fallback: null, [Symbol(_ ethersInternal_contract )]: {} } Use the smart contracts 'get' function to read the contract's initialized value .. Obtained value at deployed contract is: 0 Use the smart contracts 'increment' function to update that value .. Verify the updated value that was set .. Obtained value at deployed contract is: 1 Use the smart contracts 'decrement' function to update that value .. Verify the updated value that was set .. Obtained value at deployed contract is: 0 hre_1559_public_tx.js source : https:// besu.hyperledger.org /private-networks
hre_public_tx.js - 컨트랙트 배포 ( 배포와 동시에 배포를 요청하는 지갑주소에 47 을 설정 - 위 값을 123 으로 업데이트 async function main(){ const provider = new ethers.JsonRpcProvider (host); const wallet = new ethers.Wallet ( accountPrivateKey , provider); createContract (provider, wallet, contractAbi , contractBytecode , 47 ) .then(async function(contract){ contractAddress = await contract.getAddress (); console.log ("Contract deployed at address: " + contractAddress ); console.log ("Use the smart contracts 'get' function to read the contract's constructor initialized value .. " ) await getValueAtAddress (provider, contractAbi , contractAddress ); console.log ("Use the smart contracts 'set' function to update that value to 123 .. " ); await setValueAtAddress (provider, wallet, contractAbi , contractAddress , 123 ); console.log ("Verify the updated value that was set .. " ) await getValueAtAddress (provider, contractAbi , contractAddress ); // await getAllPastEvents (host, contractAbi , tx.contractAddress ); }) source : https:// besu.hyperledger.org /private-networks
hre_eth_tx.js - A 계정의 잔고 (90000) 에서 B 계정 ( 잔고 0) 으로 16 wei 이체 Account A has balance of: 90000000000000000000000 Account B has balance of: create and sign the txn tx transactionHash : 0x2338ce8a2249de93b59dfa0e6e29eb7e5050c74880cfc20e8b6aaa0ebbc995b1 Account A has balance of: 89999999999999999999984 Account B has balance of: 16 source : https:// besu.hyperledger.org /private-networks
Create a transaction using MetaMask Add a Test Network source : https:// besu.hyperledger.org /private-networks
Create a transaction using MetaMask Add account ( 신규 계정 생성 - 이더를 수신 받기 위한 테스트용 계정 ) 계정 생성 결과 source : https:// besu.hyperledger.org /private-networks
Create a transaction using MetaMask Add account ( 네트워크 상 등록된 계정 Import - 이더 송신용 계정 ) Private Key Copy & Paste 계정 Import 결과 source : https:// besu.hyperledger.org /private-networks
Create a transaction using MetaMask In the Block Explorer, search for the new test account by selecting the 🔍 and pasting the test account address into the search box. The new test account displays with a zero balance. source : https:// besu.hyperledger.org /private-networks
Create a transaction using MetaMask 9 페이지에서 Import 한 계정에서 8 페이지에서 신규 생성한 계정으로 1 이더 전송 source : https:// besu.hyperledger.org /private-networks
Create a transaction using MetaMask 결과 확인 source : https:// besu.hyperledger.org /private-networks
Smart contract and dapp usage # install dependencies npm i # compile the contract npm run compile npm run test # deploy the contract to the quickstart network npm run deploy- quorumtoken import "@ openzeppelin /contracts/token/ ERC20 / ERC20.sol "; contract QuorumToken is ERC20 { constructor( uint256 initialSupply ) ERC20 (" QuorumToken ", "QT") { _mint( msg.sender , initialSupply ); } } Contract deploy at: 0x9a3DBCa554e9f6b9257aAa24010DA8377C57c17e
Smart contract and dapp usage
Create a QBFT network block header validator selection method 를 적용하여 validator 노드를 관리 ( 추가 / 삭제 ) 하는 예제 ( 스마트 컨트랙트를 별도로 배포하여 관리하는 방법도 있음 (contract validator selection method)
Create a private network using QBFT 디렉토리 생성 [ root@master qbft -network]# pwd /root/ qbft -network [ root@master qbft -network]# tree . ├── Node-1 │ └── data ├── Node-2 │ └── data ├── Node-3 │ └── data └── Node-4 └── data 8 directories, 0 files source : https:// besu.hyperledger.org /private-networks
Create a private network using QBFT configuration file 생성 [ root@master qbft -network]# pwd /root/ qbft -network [ root@master qbft -network]# ll total 4 drwxr - xr -x. 3 root root 18 Jun 20 02:46 Node-1 drwxr - xr -x. 3 root root 18 Jun 20 02:46 Node-2 drwxr - xr -x. 3 root root 18 Jun 20 02:47 Node-3 drwxr - xr -x. 3 root root 18 Jun 20 02:47 Node-4 - rw -r--r--. 1 root root 1513 Jun 20 02:54 qbftConfigFile.json { "genesis": { "config": { " chainId ": 1337 , " berlinBlock ": 0, " qbft ": { " blockperiodseconds ": 2, " epochlength ": 30000, " requesttimeoutseconds ": 4 } }, "nonce": " 0x0 ", "timestamp": " 0x58ee40ba ", " gasLimit ": " 0x47b760 ", "difficulty": " 0x1 ", " mixHash ": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", " coinbase ": " 0x0000000000000000000000000000000000000000 ", " alloc ": { " fe3b557e8fb62b89f4916b721be55ceb828dbd73 ": { " privateKey ": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", "balance": " 0xad78ebc5ac6200000 " }, " 627306090abaB3A6e1400e9345bC60c78a8BEf57 ": { " privateKey ": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3", "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", "balance": "90000000000000000000000" }, " f17f52151EbEF6C7334FAD080c5704D77216b732 ": { " privateKey ": "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f", "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", "balance": "90000000000000000000000" } } }, "blockchain": { "nodes": { "generate": true, "count": 4 } } } genesis property ( 참고로 , extraData 섹션은 Besu 에서 자동 생성 ) blockchain property : 생성할 key pair 수 source : https:// besu.hyperledger.org /private-networks
Create a private network using QBFT 노드 키 ( 공개키 / 비밀키 ) 및 genesis.json 생성 # ../ besu /bin/ besu operator generate-blockchain-config --config-file= qbftConfigFile.json --to= networkFiles --private-key-file-name=key 03:15:38.052-04:00 | main | INFO | GenerateBlockchainConfig | Generating 4 nodes keys. 03:15:38.062-04:00 | main | INFO | GenerateBlockchainConfig | Generating keypair for node 0. 03:15:38.377-04:00 | main | INFO | GenerateBlockchainConfig | Generating keypair for node 1. 03:15:38.409-04:00 | main | INFO | GenerateBlockchainConfig | Generating keypair for node 2. 03:15:38.431-04:00 | main | INFO | GenerateBlockchainConfig | Generating keypair for node 3. 03:15:38.461-04:00 | main | INFO | GenerateBlockchainConfig | Generating QBFT extra data. 03:15:38.500-04:00 | main | INFO | GenerateBlockchainConfig | Writing genesis file. [ root@master qbft -network]# tree . ├── networkFiles │ ├── genesis.json │ └── keys │ ├── 0x258ed3d4c40fa5cfecb67597c6dba6248804014c │ │ ├── key │ │ └── key.pub │ ├── 0x4914ca1ac7afb825cc1a416817597144bf878180 │ │ ├── key │ │ └── key.pub │ ├── 0x898c92dc5fff31af05de0e1a465c0ff812120d15 │ │ ├── key │ │ └── key.pub │ └── 0x984769eacf61592cf42695a7147c9116c8ed738a │ ├── key │ └── key.pub ├── Node-1 │ └── data ├── Node-2 │ └── data ├── Node-3 │ └── data ├── Node-4 │ └── data └── qbftConfigFile.json 생성 결과 source : https:// besu.hyperledger.org /private-networks
Create a private network using QBFT 1 번 노드 기동 ( bootnode ) # pwd /root/ qbft -network/Node-1 # ../../ besu /bin/ besu --data-path=data --genesis-file=../ genesis.json -- rpc -http-enabled -- rpc -http- api = ETH,NET,QBFT --host-allowlist="*" -- rpc -http- cors -origins="all" 2024-06-20 03:42:54.457-04:00 | main | INFO | DefaultP2PNetwork | Enode URL enode ://952bfa93e63eecb6adc4c07688df3af41c9d71c4d736b108102758835bb7672ec6abf15f0afc7ae19d9c402a7e48fc92d350fe0bacfe7a0d3fc082540af7cc56@127.0.0.1:30303 2024-06-20 03:42:54.458-04:00 | main | INFO | DefaultP2PNetwork | Node address 0x258ed3d4c40fa5cfecb67597c6dba6248804014c Copy the enode URL to specify Node-1 as the bootnode in the following steps. source : https:// besu.hyperledger.org /private-networks
Create a private network using QBFT 2 번 노드 기동 ( bootnode 와 연결 ) # pwd /root/ qbft -network/Node-2 [ root@master Node-2]# ../../ besu /bin/ besu --data-path=data --genesis-file=../ genesis.json -- bootnodes = enode ://952bfa93e63eecb6adc4c07688df3af41c9d71c4d736b108102758835bb7672ec6abf15f0afc7ae19d9c402a7e48fc92d350fe0bacfe7a0d3fc082540af7cc56@127.0.0.1:30303 -- p2p -port=30304 -- rpc -http-enabled -- rpc -http- api = ETH,NET,QBFT --host-allowlist="*" -- rpc -http- cors -origins="all" -- rpc -http-port=8546 3 번 노드 기동 ( bootnode 와 연결 ) # pwd /root/ qbft -network/Node-3 [ root@master Node-3]# ../../ besu /bin/ besu --data-path=data --genesis-file=../ genesis.json -- bootnodes = enode ://952bfa93e63eecb6adc4c07688df3af41c9d71c4d736b108102758835bb7672ec6abf15f0afc7ae19d9c402a7e48fc92d350fe0bacfe7a0d3fc082540af7cc56@127.0.0.1:30303 -- p2p -port=30305 -- rpc -http-enabled -- rpc -http- api = ETH,NET,QBFT --host-allowlist="*" -- rpc -http- cors -origins="all" -- rpc -http-port=8547 이전 장에서 복사한 bootnode 의 enode url source : https:// besu.hyperledger.org /private-networks
Create a private network using QBFT 4 번 노드 기동 ( bootnode 와 연결 ) # pwd /root/ qbft -network/Node-4 [ root@master Node-4]# ../../ besu /bin/ besu --data-path=data --genesis-file=../ genesis.json -- bootnodes = enode ://952bfa93e63eecb6adc4c07688df3af41c9d71c4d736b108102758835bb7672ec6abf15f0afc7ae19d9c402a7e48fc92d350fe0bacfe7a0d3fc082540af7cc56@127.0.0.1:30303 -- p2p -port=30306 -- rpc -http-enabled -- rpc -http- api = ETH,NET,QBFT --host-allowlist="*" -- rpc -http- cors -origins="all" -- rpc -http-port=8548 이전 장에서 복사한 bootnode 의 enode url source : https:// besu.hyperledger.org /private-networks
Create a private network using QBFT 정상 기동 확인 curl -X POST --data '{"jsonrpc":"2.0","method":"qbft_getValidatorsByBlockNumber","params":["latest"], " id":1 }' localhost:8545 {" jsonrpc ":" 2.0","id":1,"result ":["0x258ed3d4c40fa5cfecb67597c6dba6248804014c","0x4914ca1ac7afb825cc1a416817597144bf878180","0x898c92dc5fff31af05de0e1a465c0ff812120d15","0x984769eacf61592cf42695a7147c9116c8ed738a"]} 4 개 노드의 주소 확인 - 이전 실습에서 노드키 자동 생성 결과로 얻었던 주소와 일치 여부 확인 at page 20 source : https:// besu.hyperledger.org /private-networks
Create a private network using QBFT 추가 학습 - 검증 노드 추가 / 삭제 - 스마트컨트랙트 배포 및 토큰 전송 등 ( 이전 챕터 Quorum Developer Quickstart 참고 ) https:// besu.hyperledger.org /private-networks/how-to/configure/consensus/ qbft#add-and-remove-validators-using-block-headers You can switch from the block header validator selection method configured here, to the contract validator selection method by updating the genesis file and configuring a transition.
Create a privacy-enabled network - Privacy transacion 기능 사용을 위해 Tessera 적용 - tx data 를 암호화 , 참여자 간에만 공유 , 기밀성 - 각 노드마다 Tessera 실행 이전 챕터의 Developer Quickstart 에서 초기 프로젝트 설정에서 privacy transaction 을 y 로 설정할 경우 tessera 가 자동 적용된다 . 이번 장은 tessera 를 step by step 으로 적용하는 실습 챕터임
Create a privacy-enabled network - 이전 챕터에서 실습한 QBFT 합의 알고리즘에 기반하여 실습 진행 - 각 Node-<N>/data 디렉토리에서 아래 명령 수행 ( 각 노드의 data 디렉토리에서 기 실습한 db 삭제 ) rm -rf caches/ database/ DATABASE_METADATA.json uploads ☞ bonsai 는 privacy mode 지원하지 않음 forest 로 설정하여 실습하기 위함 - Tessera 설치 (https:// docs.tessera.consensys.io / HowTo /Get-started/Install/Distribution) ① https:// github.com / ConsenSys / tessera /releases/latest 에서 최신 버전 다운로드 및 서버 업로드 ② tar xvf tessera-[version].tar ③ vi / etc /profile ④ source / etc /profile ⑤ tessera help 명령어로 정상동작 확인 환경변수 추가
Create a privacy-enabled network [ root@master qbft -network]# pwd /root/ qbft -network 디렉토리 구조 생성 mkdir -p Node-1/Tessera Node-2/Tessera Node-3/Tessera Node-4/Tessera source : https:// besu.hyperledger.org /private-networks
Create a privacy-enabled network 각 노드 Tessera 디렉토리에서 Tessera 통신용 공개키 / 개인키 생성 cd qbft -network/Node-<N>/ Tessera / [ root@master Tessera ]# tessera -keygen -filename nodeKey # ls nodeKey.key nodeKey.pub 생성 결과 source : https:// besu.hyperledger.org /private-networks
Create a privacy-enabled network 각 노드 Tessera 디렉토리에서 config 생성 - 각 노드 config 설정 값은 아래 링크 참조 https:// besu.hyperledger.org /private-networks/tutorials/ privacy#3-create-tessera-configuration-files cd qbft -network/ # vi Node-<N>/Tessera/tessera.conf source : https:// besu.hyperledger.org /private-networks
Create a privacy-enabled network 각 Tessera 노드 실행 각 Node-<N>/ Tessera 에서 tessera - configfile tessera.conf source : https:// besu.hyperledger.org /private-networks
Create a privacy-enabled network Besu 노드 1 실행 ( 실행 옵션으로 Tessera 연결 및 Privacy 지원 활성화 ) Node-1 에서 실행 ../../ besu /bin/ besu --data-path=data --genesis-file=../ genesis.json --data-storage-format=FOREST -- rpc -http-enabled -- rpc -http- api = ETH,NET, QBFT ,EEA,PRIV --host-allowlist="*" -- rpc -http- cors -origins="all" --privacy-enabled --privacy- url =http://127.0.0.1:9102 --privacy-public-key-file= Tessera / nodeKey.pub --min-gas-price=0 Copy the enode URL to specify Node-1 as the bootnode in the following steps. Enode URL enode ://952bfa93e63eecb6adc4c07688df3af41c9d71c4d736b108102758835bb7672ec6abf15f0afc7ae19d9c402a7e48fc92d350fe0bacfe7a0d3fc082540af7cc56@127.0.0.1:30303 2024-06-21 09:21:11.319-04:00 | main | INFO | DefaultP2PNetwork | Node address 0x258ed3d4c40fa5cfecb67597c6dba6248804014c source : https:// besu.hyperledger.org /private-networks
Create a privacy-enabled network Besu 노드 2 실행 ( 실행 옵션으로 Tessera 연결 및 Privacy 지원 활성화 ) Node-2 에서 실행 ../../ besu /bin/ besu --data-path=data --genesis-file=../ genesis.json --data-storage-format=FOREST -- bootnodes = enode ://952bfa93e63eecb6adc4c07688df3af41c9d71c4d736b108102758835bb7672ec6abf15f0afc7ae19d9c402a7e48fc92d350fe0bacfe7a0d3fc082540af7cc56@127.0.0.1:30303 -- p2p -port=30304 -- rpc -http-enabled -- rpc -http- api = ETH,NET, QBFT ,EEA,PRIV --host-allowlist="*" -- rpc -http- cors -origins="all" -- rpc -http-port=8546 --privacy-enabled --privacy- url =http://127.0.0.1:9202 --privacy-public-key-file= Tessera / nodeKey.pub --min-gas-price=0 이전 장에서 복사한 bootnode 의 enode url source : https:// besu.hyperledger.org /private-networks
Create a privacy-enabled network ../../ besu /bin/ besu --data-path=data --genesis-file=../ genesis.json --data-storage-format=FOREST -- bootnodes = enode ://952bfa93e63eecb6adc4c07688df3af41c9d71c4d736b108102758835bb7672ec6abf15f0afc7ae19d9c402a7e48fc92d350fe0bacfe7a0d3fc082540af7cc56@127.0.0.1:30303 -- p2p -port=30305 -- rpc -http-enabled -- rpc -http- api = ETH,NET,QBFT,EEA,PRIV --host-allowlist="*" -- rpc -http- cors -origins="all" -- rpc -http-port=8547 --privacy-enabled --privacy- url =http://127.0.0.1:9302 --privacy-public-key-file= Tessera / nodeKey.pub --min-gas-price=0 이전 장에서 복사한 bootnode 의 enode url Besu 노드 3 실행 ( 실행 옵션으로 Tessera 연결 및 Privacy 지원 활성화 ) Node-3 에서 실행 source : https:// besu.hyperledger.org /private-networks
Create a privacy-enabled network ../../ besu /bin/ besu --data-path=data --genesis-file=../ genesis.json --data-storage-format=FOREST -- bootnodes = enode ://952bfa93e63eecb6adc4c07688df3af41c9d71c4d736b108102758835bb7672ec6abf15f0afc7ae19d9c402a7e48fc92d350fe0bacfe7a0d3fc082540af7cc56@127.0.0.1:30303 -- p2p -port=30306 -- rpc -http-enabled -- rpc -http- api = ETH,NET,QBFT,EEA,PRIV --host-allowlist="*" -- rpc -http- cors -origins="all" -- rpc -http-port=8548 --privacy-enabled --privacy- url =http://127.0.0.1:9402 --privacy-public-key-file= Tessera / nodeKey.pub --min-gas-price=0 이전 장에서 복사한 bootnode 의 enode url Besu 노드 4 실행 ( 실행 옵션으로 Tessera 연결 및 Privacy 지원 활성화 ) Node-4 에서 실행 source : https:// besu.hyperledger.org /private-networks
Create a privacy-enabled network 결과 Tessera 노드 Besu 노드 source : https:// besu.hyperledger.org /private-networks
Create a privacy-enabled network Configure a multi-tenant node - https:// besu.hyperledger.org /private-networks/tutorials/privacy/multi-tenancy ① 특정 노드의 인스턴스를 복수로 실행할 수 있음 ② 특정 노드에 jwt 토큰을 발행하고 , 해당 토큰으로 클라이언트 요청으로 전달되는 jwt 를 파싱하여 허가된 API 에 대한 JSON-RPC 요청을 처리할 수 있음 (<- Privacy-enabled network 사용 이유 ) - keyData 가 여러 개 설정된 경우 각 Tessera 인스턴스는 자신의 키를 사용하여 트랜잭션을 처리
Create a permissioned network account-allowlist 와 nodes-allowlist 로 계정과 노드의 permission 을 관리 - perm_addNodesToAllowlist , removeAccountsFromAllowList , getAccountAllowlist 등의 API 로 권한관리 - 이전 챕터에서 실습한 QBFT 합의 알고리즘에 기반하여 실습 진행
Create a permissioned network Permission 설정 파일 생성 각 노드 Node-<N>/data 디렉토리에 아래 파일 생성 accounts-allowlist=[" 0xfe3b557e8fb62b89f4916b721be55ceb828dbd73 ", " 0x627306090abaB3A6e1400e9345bC60c78a8BEf57 "] nodes-allowlist=[] permissions_config.toml Permission 에 genesis 파일에서 명시한 첫 2 개의 account 만 allowlist 에 추가하여 실습하기 source : https:// besu.hyperledger.org /private-networks
Create a permissioned network Node 1 기동 ../../ besu /bin/ besu --data-path=data --genesis-file=../ genesis.json --permissions-nodes-config-file-enabled --permissions-accounts-config-file-enabled --data-storage-format=FOREST -- rpc -http-enabled -- rpc -http- api = ADMIN,ETH,NET,PERM,QBFT -- rpc -http-host="0.0.0.0" --host-allowlist="*" -- rpc -http- cors -origins="*" < 기존 Privacy enabled network 실습과 차이 > -- rpc -http-host="0.0.0.0" 은 외부 네트워크 ( 메타마스크 ) 등에서 접속을 허용하기 위함 -- rpc -http- api 에서 EEA, PRIV 제거 ( Private 기능을 사용하지 않는 실습 ) --privacy-enabled --privacy- url =http://127.0.0.1:9202 --privacy-public-key-file= Tessera / nodeKey.pub 제거 -- bootnode 제거 (Permission 을 추가하여 노드간 연결을 뒤에서 진행 (1 번 노드를 bootnode 로 설정예정 ) 결과 로그에서 enode 복사 enode ://952bfa93e63eecb6adc4c07688df3af41c9d71c4d736b108102758835bb7672ec6abf15f0afc7ae19d9c402a7e48fc92d350fe0bacfe7a0d3fc082540af7cc56@127.0.0.1:30303 source : https:// besu.hyperledger.org /private-networks
Create a permissioned network Permission 이 적용될 node 등록 - 각 노드의 rpc endpoint 에 각 노드 구동시 출력된 enode (4 개 ) 를 등록함 - 이는 permissions_config.toml 에 nodes-allowlist 에 노드를 추가하는 동작과 동일 curl -X POST --data '{"jsonrpc":"2.0","method":"perm_addNodesToAllowlist","params":[["enode://952bfa93e63eecb6adc4c07688df3af41c9d71c4d736b108102758835bb7672ec6abf15f0afc7ae19d9c402a7e48fc92d350fe0bacfe7a0d3fc082540af7cc56@127.0.0.1:30303","enode://f1e0e6ee986f7c189bc75b3a2f0ff4256b9d5a0ce5e799a7d81d0422eae400db96903dc09dbe1626fe4a4c7963cba5de1bae83d5e9e3a8a03e5f53819eebf518@127.0.0.1:30304","enode://00e334d5195139102afb717e3eede9c5c68d86e7cfc4e66e56f879c19ec0dfdd56ac244c03ef6cf80c94233db35e99f9a82af2d07e135a38ce27e6c411ba569e@127.0.0.1:30305","enode://1da03cac51d4fc896950ca9399fa98923ac10a0b18135f198a905cf6ad563e95396d634f0dd2f9beae0375e7da5bb16628980dcfe2bc2d91ecbcb2da8b1189cd@127.0.0.1:30306"]], "id":1}' http://127.0.0.1:8545 curl -X POST --data '{"jsonrpc":"2.0","method":"perm_addNodesToAllowlist","params":[["enode://952bfa93e63eecb6adc4c07688df3af41c9d71c4d736b108102758835bb7672ec6abf15f0afc7ae19d9c402a7e48fc92d350fe0bacfe7a0d3fc082540af7cc56@127.0.0.1:30303","enode://f1e0e6ee986f7c189bc75b3a2f0ff4256b9d5a0ce5e799a7d81d0422eae400db96903dc09dbe1626fe4a4c7963cba5de1bae83d5e9e3a8a03e5f53819eebf518@127.0.0.1:30304","enode://00e334d5195139102afb717e3eede9c5c68d86e7cfc4e66e56f879c19ec0dfdd56ac244c03ef6cf80c94233db35e99f9a82af2d07e135a38ce27e6c411ba569e@127.0.0.1:30305","enode://1da03cac51d4fc896950ca9399fa98923ac10a0b18135f198a905cf6ad563e95396d634f0dd2f9beae0375e7da5bb16628980dcfe2bc2d91ecbcb2da8b1189cd@127.0.0.1:30306"]], "id":1}' http://127.0.0.1:8546 curl -X POST --data '{"jsonrpc":"2.0","method":"perm_addNodesToAllowlist","params":[["enode://952bfa93e63eecb6adc4c07688df3af41c9d71c4d736b108102758835bb7672ec6abf15f0afc7ae19d9c402a7e48fc92d350fe0bacfe7a0d3fc082540af7cc56@127.0.0.1:30303","enode://f1e0e6ee986f7c189bc75b3a2f0ff4256b9d5a0ce5e799a7d81d0422eae400db96903dc09dbe1626fe4a4c7963cba5de1bae83d5e9e3a8a03e5f53819eebf518@127.0.0.1:30304","enode://00e334d5195139102afb717e3eede9c5c68d86e7cfc4e66e56f879c19ec0dfdd56ac244c03ef6cf80c94233db35e99f9a82af2d07e135a38ce27e6c411ba569e@127.0.0.1:30305","enode://1da03cac51d4fc896950ca9399fa98923ac10a0b18135f198a905cf6ad563e95396d634f0dd2f9beae0375e7da5bb16628980dcfe2bc2d91ecbcb2da8b1189cd@127.0.0.1:30306"]], "id":1}' http://127.0.0.1:8547 curl -X POST --data '{"jsonrpc":"2.0","method":"perm_addNodesToAllowlist","params":[["enode://952bfa93e63eecb6adc4c07688df3af41c9d71c4d736b108102758835bb7672ec6abf15f0afc7ae19d9c402a7e48fc92d350fe0bacfe7a0d3fc082540af7cc56@127.0.0.1:30303","enode://f1e0e6ee986f7c189bc75b3a2f0ff4256b9d5a0ce5e799a7d81d0422eae400db96903dc09dbe1626fe4a4c7963cba5de1bae83d5e9e3a8a03e5f53819eebf518@127.0.0.1:30304","enode://00e334d5195139102afb717e3eede9c5c68d86e7cfc4e66e56f879c19ec0dfdd56ac244c03ef6cf80c94233db35e99f9a82af2d07e135a38ce27e6c411ba569e@127.0.0.1:30305","enode://1da03cac51d4fc896950ca9399fa98923ac10a0b18135f198a905cf6ad563e95396d634f0dd2f9beae0375e7da5bb16628980dcfe2bc2d91ecbcb2da8b1189cd@127.0.0.1:30306"]], "id":1}' http://127.0.0.1:8548
Create a permissioned network Peer 노드 등록 - 노드 1 을 노드 2,3,4 에 peer 노드로 등록 - 노드 2 를 노드 3,4 에 peer 노드로 등록 - 노드 3 을 노드 4 에 peer 노드로 등록 노드 1 이 bootnode 로 인식됨 curl -X POST --data '{"jsonrpc":"2.0","method":"admin_addPeer","params":["enode://952bfa93e63eecb6adc4c07688df3af41c9d71c4d736b108102758835bb7672ec6abf15f0afc7ae19d9c402a7e48fc92d350fe0bacfe7a0d3fc082540af7cc56@127.0.0.1:30303"],"id":1}' http://127.0.0.1:8546 curl -X POST --data '{"jsonrpc":"2.0","method":"admin_addPeer","params":["enode://952bfa93e63eecb6adc4c07688df3af41c9d71c4d736b108102758835bb7672ec6abf15f0afc7ae19d9c402a7e48fc92d350fe0bacfe7a0d3fc082540af7cc56@127.0.0.1:30303"],"id":1}' http://127.0.0.1:8547 curl -X POST --data '{"jsonrpc":"2.0","method":"admin_addPeer","params":["enode://952bfa93e63eecb6adc4c07688df3af41c9d71c4d736b108102758835bb7672ec6abf15f0afc7ae19d9c402a7e48fc92d350fe0bacfe7a0d3fc082540af7cc56@127.0.0.1:30303"],"id":1}' http://127.0.0.1:8548 curl -X POST --data '{"jsonrpc":"2.0","method":"admin_addPeer","params":["enode://f1e0e6ee986f7c189bc75b3a2f0ff4256b9d5a0ce5e799a7d81d0422eae400db96903dc09dbe1626fe4a4c7963cba5de1bae83d5e9e3a8a03e5f53819eebf518@127.0.0.1:30304"],"id":1}' http://127.0.0.1:8547 curl -X POST --data '{"jsonrpc":"2.0","method":"admin_addPeer","params":["enode://f1e0e6ee986f7c189bc75b3a2f0ff4256b9d5a0ce5e799a7d81d0422eae400db96903dc09dbe1626fe4a4c7963cba5de1bae83d5e9e3a8a03e5f53819eebf518@127.0.0.1:30304"],"id":1}' http://127.0.0.1:8548 curl -X POST --data '{"jsonrpc":"2.0","method":"admin_addPeer","params":["enode://00e334d5195139102afb717e3eede9c5c68d86e7cfc4e66e56f879c19ec0dfdd56ac244c03ef6cf80c94233db35e99f9a82af2d07e135a38ce27e6c411ba569e@127.0.0.1:30305"],"id":1}' http://127.0.0.1:8548 source : https:// besu.hyperledger.org /private-networks
Create a permissioned network 정상 동작 확인 ○ 참여 peer 노드 갯수 확인 curl -X POST --data '{" jsonrpc ":"2.0","method":"net_ peerCount ","params":[]," id":1 }' localhost:8545 - 결과 : {" jsonrpc ":"2.0","id":1,"result":" 0x3 "} ○ allowlist 확인 curl -X POST --data '{" jsonrpc ":"2.0","method":"perm_ getAccountsAllowlist ","params":[]," id":1 }' -H "Content-Type: application/ json " http:// localhost:8545 - 결과 : {" jsonrpc ":" 2.0","id":1,"result ":["0xfe3b557e8fb62b89f4916b721be55ceb828dbd73","0x627306090abab3a6e1400e9345bc60c78a8bef57"]} ○ bootnode 확인 curl -X POST --data '{" jsonrpc ":"2.0","method":"admin_ nodeInfo ","params":[]," id":1 }' -H "Content-Type: application/ json " http:// localhost:8545 - 결과 : {" jsonrpc ":" 2.0","id":1,"result ":{" enode ":" enode ://952bfa93e63eecb6adc4c07688df3af41c9d71c4d736b108102758835bb7672ec6abf15f0afc7ae19d9c402a7e48fc92d350fe0bacfe7a0d3fc082540af7cc56@127.0.0.1:30303","listenAddr":"127.0.0.1:30303","ip":"127.0.0.1","name":"besu/ v24.5.2 / linux-x86_64 /oracle-java-17","id":"952bfa93e63eecb6adc4c07688df3af41c9d71c4d736b108102758835bb7672ec6abf15f0afc7ae19d9c402a7e48fc92d350fe0bacfe7a0d3fc082540af7cc56","ports":{" discovery":30303,"listener":30303 },"protocols":{"eth":{"config":{" chainId ":1337," berlinBlock ":0," qbft ":{"epochLength":30000,"blockPeriodSeconds":2,"requestTimeoutSeconds":4}},"difficulty":5288,"genesis":"0x0bfff602eb27908c50212176f59c5a40e634c9a9da745f9d32f4bf5f2acbbd07","head":"0x93ff7d6663c8a449cb3f0f0c3930ba26ff2cd65a5a9c8d89abda9a0c4f79c70e","network":1337}}}}
Create a permissioned network 테스트 - allowlist 에 있는 1 번 계정에서 allowlist 에 없는 3 번 계정으로 transfer 시도 Pending 으로 실패 0xfe3b557e8fb62b89f4916b721be55ceb828dbd73 0xf17f52151EbEF6C7334FAD080c5704D77216b732
Create a permissioned network besu 로그에 pending transaction 확인 가능 ① peding transaction 을 삭제하는 기능을 besu 에서 제공하지 않음 ② pending tx 를 삭제하기 위해서는 transaction pool size 를 작게 조절해서 oldest tx 부터 자동 삭제되게 하거나 , ③ besu 를 전체 재기동한다 . 다만 , 이때에도 메타마스크에서 pending 중인 tx 가 있기 때문에 , 재기동하고 정상 tx 를 메타마스크에서 요청하여도 이전 pending 된 내역을 다시 메타마스크에서 처리를 시도하기 때문에 정상 tx 도 처리가 안된다 . ④ 이를 위해서 아래와 같이 besu 재기동 이후에 메타마스크에서 우측과 같은 처리가 필요하다 . 메타마스크 Advanced Clear activity and nonce data 섹션의 버튼 클릭
Create a permissioned network 테스트 - allowlist 에 있는 1 번 계정에서 allowlist 에 존재하는 2 번 계정으로 transfer 시도 성공 0xfe3b557e8fb62b89f4916b721be55ceb828dbd73 0x627306090abaB3A6e1400e9345bC60c78a8BEf57 source : https:// besu.hyperledger.org /private-networks
Create a permissioned network 노드 allowlist 에 없는 임의의 besu 노드 5 를 기동 ( 기동시 bootnode 를 1 번으로 지정 ) 노드 5 에서 peer 노드의 갯수를 조회하면 으로 출력 perm_addNodesToAllowlist 를 통해 등록하지 않았기 때문에 예상된 결과임 source : https:// besu.hyperledger.org /private-networks
앞으로 다룰 내용 Kubernetes 배포 및 관리 Public Networks 실습 프로젝트 과제