자바스크립트로 블록체인 구현 강좌 11 - 나만의 비트코인 발행하기
지난 포스팅에서 하나의 네트워크에서 블록체인이 어떻게 작동이 되는지 살펴보았다. 이번포스팅에서는 여러개의 노드, 즉 컴퓨터들이 참여를 할때 블록체인 데이터가 어떻게 기록되는지 살펴보겠다.
순서
1. api.js 파일 이름을 networkNode.js 로 변경하자.
2. networkNode.js 파일 윗 부분에 동적 포트관련 변수 선언해준다.
//동적 포트 package.json script 객체에서 2번째 방에 들어있는 데이터 3001,3002,3003 ...3005
var port = process.argv[2];
3. app.listen 을 아래와 같이 바꿔 준다.
//동적 포트
app.listen(port,function(){
console.log(`listening on port ${port}...`)
})
4. package.json 부분에서 script 부분을 아래와 같이 바꿔 준다.
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"node_1":"nodemon --watch dev -e js dev/networkNode.js 3001 http://localhost:3001",
"node_2":"nodemon --watch dev -e js dev/networkNode.js 3002 http://localhost:3002",
"node_3":"nodemon --watch dev -e js dev/networkNode.js 3003 http://localhost:3003",
"node_4":"nodemon --watch dev -e js dev/networkNode.js 3004 http://localhost:3004",
"node_5":"nodemon --watch dev -e js dev/networkNode.js 3005 http://localhost:3005"
},
이제 포트 3001 부터 3005번 까지의 node(서버)를 실행시킬 수 있다. 실행방법은 아래와 같다.
1. 터미널 열기
2. 개발폴더에 위치하고
3. npm run node_1
4. 터미널 창 하나 더 뛰워서 npm run node_2 반복적으로 실행
blockchain.js로 이동
//sha256 모듈을 가져다 쓰겠다.
const sha256 = require('sha256');
//현재 노드의 url -- package.json script 객체에서 3번째 방에 들어있는 데이터 http://localhost:3001
const currentNodeUrl = process.argv[3];
//블록체인 데이터 구조
function Blockchain(){
this.chain = [];
this.pendingTransaction = [];
//현재 node url -- 이부분!!!
this.currentNodeUrl = currentNodeUrl;
this.networkNodes = [];
//제네시스 블락 - 임의의 인자값 넣어준다.
this.createNewBlock(100,'0','0')
}
sha 256모듈 변수 아래에 현재 노드의 url을 알 수 있는 코드를 작성하고 function blockchain(){} 함수 안에 //현재 node url 주석 아래 두 코드를 작성해준다. 이건 접속한 node의 url 데이터를 저장하겠다는 뜻.
새로운 노드가 기존의 네트워크에 진입하는과정 (탈중앙화된 네트워크 그림)
1. 새로운 노드가 기존의 노드 네트워크에 들어가기전에 등록을 거친 후 알린다.
2. 각 노드들에게 새로운 노드 정보를 등록시켜 준다.
3.기존의 모든 노드의 데이터를 새로운 노드에게 등록한다.
소스(networkNode.js에 작성)
//새로운 노드를 등록하고 전체 네트워크에 알림
app.post('/register-and-broadcast-node',function(req,res){
})
// 네트워크에 새로운 노드 등록
app.post('/register-node',function(req,res){
})
// 새로운 노드에 기존의 노드 정보 등록
app.post('/register-nodes-bulk',function(req,res){
})
npm promise api 설치 - js에서 비동기작업을 순차적으로 or 병렬로 처리가능하게 컨트롤하는 모듈
npm install request-promise --save
npm install request --save
둘다 입력!
promise 에 대한 자세한 설명
http://programmingsummaries.tistory.com/325
모듈 임포트
맨위쪽에 promise 모듈을 사용할 변수 설정
//request-promise 모듈
var rp = require('request-promise');
새로운 노드를 전체 노드에 등록하고 알리는 코드작성
//새로운 노드를 등록하고 전체 네트워크에 알림
app.post('/register-and-broadcast-node',function(req,res){
//새로 진입한 노드 주소
const newNodeUrl = req.body.newNodeUrl;
//비트코인 네트워크에 새로 진입한 노드의 주소가 없을 경우 추가
if(bitcoin.networkNodes.indexOf(newNodeUrl) == -1){
bitcoin.networkNodes.push(newNodeUrl);
}
const regNodesPromises = [];
//비트코인 네트워크에 등록된 네트워크에 새로운 노드 정보를 등록
bitcoin.networkNodes.forEach(networkNodes => {
//register - node
const requestOption = {
uri: networkNodesUrl + '/register-node',
method: 'POST',
body:{newNodeUrl:newNodeUrl},
json:true
};
//순차적으로 비동기를 실행하기 위해서 배열에 넣음
regNodesPromises.push(rp(requestOption))
}); //for 문 끝
//순차적으로 비동기 작업 처리
Promise.all(regNodesPromises)
.then(data => {
//새로운 노드안에 전체 네트워크에 대한 정보 한번에 입력해주기
const bulkRegisterOption = {
uri : newNodeUrl + '/register-nodes-bulk',
method : 'POST',
body : {allNetworkNodes : [...bitcoin.networkNodes,bitcoin.currentNodeUrl]},
json : true
};
return rq(bulkRegisterOption);
}).then(data => {
res.json({nodt: "새로운 노드가 전체 네트워크에 성공적으로 등록이 되었습니다."});
});
});
전체 네트워크에 새로운 노드 등록하는 코드
// 네트워크에 새로운 노드 등록
app.post('/register-node',function(req,res){
//새로운 노드 주소
const newNodeUrl = req.body.newNodeUrl;
//코인 네트워크에 새로운 노드의 주소가 없다면,
const nodeNotAlreadyPresent = bitcoin.networkNodes.indexOf(newNodeUrl) == -1;
//코인의 현재 url이 새로운 노드 주소가 아니라면, 즉 현재 접속한 주소와 중복되지 않는다면,
const notCurrentNode = bitcoin.currentNodeUrl !== newNodeUrl;
if(nodeNotAlreadyPresent&¬CurrentNode){
//코인 전체 네트워크에 새로운 주소 등록
bitcoin.networkNodes.push(newNodeUrl);
res.json({note: "새로운 노드가 등록되었습니다."})
}
})
결과확인
3001-3005번 서버를 다 작동시킨다.
웹브라우저에 http://localhost:3001/blockchain 입력후 확인
postman을 열어서 body로 json 데이터 전송
웹브라우저 다시 확인
마무리
다른 주소로도 여러번 테스트 해보자. 다음 포스팅에서 마저 정리하도록 하겠다.