자바스크립트로 블록체인 구현 강좌 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&&notCurrentNode){
//코인 전체 네트워크에 새로운 주소 등록
bitcoin.networkNodes.push(newNodeUrl);
res.json({note: "새로운 노드가 등록되었습니다."})
}

})


결과확인

3001-3005번 서버를 다 작동시킨다.

웹브라우저에 http://localhost:3001/blockchain 입력후 확인


postman을 열어서 body로 json 데이터 전송

 

웹브라우저 다시 확인


마무리


다른 주소로도 여러번 테스트 해보자. 다음 포스팅에서 마저 정리하도록 하겠다.



  1. 기웃거리는 개발자 2018.06.14 18:03 신고

    한수 잘 배웠습니다.. 직접 코딩 해봐야 데이터 처리 흐름에 개념이 오네요.ㅎㅎ
    감사합니다~

자바스크립트로 블록체인 구현 강좌 10 - 나만의 비트코인 발행하기(소스코드)

이번 포스팅에서는 블록을 채굴할때, 즉 컴퓨팅 파워로 마이닝 할때 실행되는 app.get(/mine) 함수 부분을 작성해보도록 한다. 


순서

1.먼저 마지막 블록을 가져온다.

2.마지막 블럭의 타입은 객체 이기 때문에 key:value 형태다. 'hash' 키 값으로 해당 value(이전블럭해쉬)를 가져온다.

3.현재 블럭데이터는 이전의 발생한 거래내역을 저장해야 하기 때문에 bitcoin객체의 pendingTransaction 배열에 담긴 값을 가져와서 넣어주고, index는 마지막 블럭 index + 1을 해준다.

4. 이제 nonce, blockHash를 구할 수 있는 값들을 다 구했다. 

5. 그리고 위의 값들을 이용해서 createNewBlock()을 만든다.


// 웹브라우저에 get 방식으로 /mine 주소를 입력했을 때 실행
app.get('/mine', function (req, res) {
//마지막 블럭을 가져온다.
const lastBlock = bitcoin.getLastBlock();

//마지막 블럭의 해쉬 값, 즉 이전 블럭의 해쉬값
const previousBlockHash = lastBlock['hash'];

//현재 블락의 데이터 : 미완료된 거래내역 + 블락의 index 값
const currentBlockData = {
transactions:bitcoin.pendingTransaction,
index:lastBlock['index'] + 1
};

//이전블락해쉬, 현재블럭 데이터를 proofOfWork에 넣고 맞는 hash값(0000sfaff...)을 찾고 해당 nonce 값을 리턴.
const nonce = bitcoin.proofOfWork(previousBlockHash,currentBlockData);
//이전블락해쉬, 현재블럭 데이터, nonce 값을 넣고 현재 블락의 해쉬 값 리턴
const blockHash = bitcoin.hashBlock(previousBlockHash,currentBlockData,nonce);

//새로운 블락을 생성하려면 nonce,previousBlockHash,blockHash 값이 필요하다.
const newBlock = bitcoin.createNewBlock(nonce,previousBlockHash,blockHash);

res.json({
note: "새로운 블락이 성공적으로 만들어졌습니다.",
newBlock : newBlock
})

})


채굴자에게 보상 제공

블락을 채굴한 사람에게 보상을 해줘야 한다. 그러기 위해서는 채굴한 사람의 주소를 알아야 한다. 여기서는 npm 을 이용해서 네트워크 아이디를 임의로 지정해줘서 보상을 해주도록 하겠다.

터미널을 열고 -> 개발폴더에 위치하고 -> 명령어 입력 -> npm i uuid --save 


설치가 완료되었으면 api.js 윗부분에 아래 코드 입력

//나의 네트워크 고유 아이디 생성
var uuid = require('uuid/v1');
var nodeAddress = uuid().split('-').join('');


그리고 채굴에 대한 보상을 위한 코드 작성 - 주석으로 //채굴에 대한 보상

보상을 위해 지금 해당 비트코인 객체에 새로운 거래가 발생을 시키고, 보상으로 10비트코인을 bosang 이 nodeAddress 즉 나의 네트워크(내가 채굴했으니깐) 키에 지급한다.

// 웹브라우저에 get 방식으로 /mine 주소를 입력했을 때 실행
app.get('/mine', function (req, res) {
//마지막 블럭을 가져온다.
const lastBlock = bitcoin.getLastBlock();

//마지막 블럭의 해쉬 값, 즉 이전 블럭의 해쉬값
const previousBlockHash = lastBlock['hash'];

//현재 블락의 데이터 : 미완료된 거래내역 + 블락의 index 값
const currentBlockData = {
transactions:bitcoin.pendingTransaction,
index:lastBlock['index'] + 1
};

//이전블락해쉬, 현재블럭 데이터를 proofOfWork에 넣고 맞는 hash값(0000sfaff...)을 찾고 해당 nonce 값을 리턴.
const nonce = bitcoin.proofOfWork(previousBlockHash,currentBlockData);
//이전블락해쉬, 현재블럭 데이터, nonce 값을 넣고 현재 블락의 해쉬 값 리턴
const blockHash = bitcoin.hashBlock(previousBlockHash,currentBlockData,nonce);

//채굴에 대한 보상
bitcoin.createNewTransaction(10,"bosang0000",nodeAddress)

//새로운 블락을 생성하려면 nonce,previousBlockHash,blockHash 값이 필요하다.
const newBlock = bitcoin.createNewBlock(nonce,previousBlockHash,blockHash);

res.json({
note: "새로운 블락이 성공적으로 만들어졌습니다.",
newBlock : newBlock
})
})


테스트하기

먼저 터미널을 열고 개발 폴더에 위치하고 npm start로 서버를 실행한다. 그리고 웹브라우저에 차례대로 아래 주소를 적어본다. (꼭 차례대로 하나씩 따라해보세요)


http://localhost:3000/blockchain  - 제네시스 블럭 생성


http://localhost:3000/mine - 2번째 블록채굴 + 보상(transactoins 배열에 객체형태로 들어가 있음)


http://localhost:3000/blockchain - 2번째 블록 연결


http://localhost:3000/mine -  3번째 블록채굴 + 보상


http://localhost:3000/blockchain - 3번째 블록 연결


http://localhost:3000/transaction - 거래내역 발생


http://localhost:3000/blockchain - 거래내역은 pendingTransaction 배열에 존재



http://localhost:3000/mine - 4번째 블록 채굴 + 위의 거래내역 + 보상


http://localhost:3000/blockchain - pendingTransaction 배열 비움 + 거래내역과 보상이 담긴 4번째 블록 연결


마무리


일단 여기까지 따라오느라 정말 고생이 많으셨습니다. 여기까지 따라치면서 위와 같은 출력이 나왔다면 블록체인 기술에 대한 이해가 조금 더 생겼으리리라 생각이 됩니다. 여기서 한템포 쉬었다가 다음 포스팅 부터 또 이어서 진행하도록 하겠습니다.아래에 소스코드를 첨부했으니 참고하시면 될 것 같습니다.


소스코드

blockchain.zip


자바스크립트로 블록체인 구현 강좌 9 - 나만의 비트코인 발행하기


이번시간에는 api.js에 app.get() , app.post() 부분을 작성해주고, 개발에 조금 더 도움을 줄 node api를 설치 해보도록 하겠다. node js 에서 get, post이 부분이 이해가 안간다면...구글링을 부탁드린다..여기서는 조금이라도 알고 있다고 가정하고 쭉쭉 설명하겠다.


먼저 api.js 소스 코드다

var express = require('express')
var app = express()

// 웹브라우저에 get 방식으로 /blockchain 주소를 입력했을 때 실행
app.get('/blockchain', function (req, res) {
res.send('blockchain Start')
})

// 웹브라우저에 post 방식으로 /transaction 주소를 입력했을 때 실행
app.post('/transaction', function (req, res) {
res.send('transaction Start')
})


// 웹브라우저에 get 방식으로 /mine 주소를 입력했을 때 실행
app.get('/mine', function (req, res) {
res.send('mine Start')
})



app.listen(3000,function(){
console.log('listening on port 3000')
})

위에 소스코드 설명은 express js 기초지식에 해당되므로 여기서는 패스하고 간단하게 주석을 달아놓았다. 

서버 가동

브라우저 확인

nodemoe api 설치

nodemon  은 소스 수정시 자동으로 서버를 재실행시켜주는 api이다. 설치 안해도 무방하나 설치 해놓으면 엄청편하기 때문에 설치한다.

https://www.npmjs.com/package/nodemon

순서

터미널 열고 -> 개발폴더위치 -> npm i nodemon --save 입력 -> package.json 이동 -> script 부분에 아래 문자 추가  "start" : "nodemon --watch dev -e js dev/api.js" 

혹시나해서 나의 package.json 파일 전체를 올린다.

{
"name": "blockchain",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start" : "nodemon --watch dev -e js dev/api.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.16.3",
"nodemon": "^1.17.5",
"sha256": "^0.2.0"
}
}


그리고 다시 터미널 창으로 가서 개발 폴더에 위치하고 서버를 실행한다. 이번에는 npm start 명령으로 실행해보자.

확인 - 아래처럼 출력되면 성공이다.(안되도 크게 상관은 없다. 서버를 수동으로 재시작 해주면되니깐.)


body-parser api 설치

위에서 nodemon을 설치했던것 처럼 터미널 열기 -> 개발 폴더 위치 -> npm i body-parser --save 입력-> 엔터

이 모듈은 express js에서 post방식으로 파라미터를 넘길 수 있게 하는 모듈이다. 쉽게 말하면 웹주소를 이용해서 데이터를 넘기는 것을 도와주는 녀석이라고 생각하면 된다. 암튼 자세한건 구현하면 아~ 하고 이해가 될 것이다. 그리고 api.js 맨위쪽에 var app= express() 이 부분 아래 body paser를 사용하겠다는 코드를 작성해준다.

var express = require('express')
var app = express()
//bodyParser 임포트
var bodyParser = require('body-parser')

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:false}))



api.js 에서 post transaction 코드 작성

// 웹브라우저에 post 방식으로 /transaction 주소를 입력했을 때 실행
app.post('/transaction', function (req, res) {
console.log(req.body);
res.send(`거래 총액은 ${req.body.amount} 코인`);
})


postman에서 확인 해보기 (https://www.getpostman.com)

포스트맨은 웹상에서 데이터를 웹브라우저 주소로 넘길때 간단하게 테스트 해볼 수 있는 서비스다. 위의 홈페이지로 들어가서 각각 운영체제에 맞는 버젼을 다운로드 하자.


확인

포스트맨에 들어가서 맨위 붉은 줄 처럼 주소를 적고 body를 선택하고 raw , JSON 선택후 아래 문자를 작성한 뒤 Send 를 눌러보자. 그러면 거래 총액은 200 코인 으로 아래 소스 코드로 데이터가 넘어와서 출력된것을 알 수 가 있다.

// 웹브라우저에 post 방식으로 /transaction 주소를 입력했을 때 실행
app.post('/transaction', function (req, res) {
console.log(req.body);
res.send(`거래 총액은 ${req.body.amount} 코인`);
})


app.get /blockchain 작성 

웹브라우저에서 get 방식으로 /blockchain 주소가 들어왔을 경우. bodypaser 모듈을 임포트 하는 코드 아래에 밑의 코드 작성. 

//앞에서 만든 blockchain 모듈 임포트 -> 코인객체 생성
var Blockchain = require('./blockchain');
var bitcoin = new Blockchain();


app.get('blockchain') 부분 코드 작성

// 웹브라우저에 get 방식으로 /blockchain 주소를 입력했을 때 실행
app.get('/blockchain', function (req, res) {
res.send(bitcoin)
})


웹브라우저에서 테스트 - 제네시스 블락 정보가 json 형식으로 뜬다.

/transaction 부분을 담당하는 함수안 내용 수정 - 거래가 발생했을때 새로운 트랜잭션을 생성하기 때문에 발생하는 정보를 console.log 로 찍어주도록 하자.

// 웹브라우저에 post 방식으로 /transaction 주소를 입력했을 때 실행
app.post('/transaction', function (req, res) {

const blockIndex = bitcoin.createNewTransaction(req.body.amount,req.body.sender,req.body.recipient)
res.json({note : `트랜젝션은 ${blockIndex} 블락안으로 들어갈 예정입니다.`})

})



postman으로 확인 - 총 4번의 send를 누름 (4번의 거래 발생)



/blockchain 확인 -  위에서 발생한 트랜잭션 데이터가 pendingTransaction [] 에 들어가 있다. 저건 언제 index 1 블락으로 들어갈까? 이전전전 포스트에서 다뤘다. 새로운 블락이 생성될때. 그건언제인가? 컴퓨팅 파워를 통한 채굴. 마이닝!  그 작업을 통해서 맞는 hash 값을 찾았을 때 새로운 블락이 생성되면서 이전 거래 내역이 새로운 블락안으로 들어간다.  이번 포스팅은 여기서 마무리 하도록 하겠다.



자바스크립트로 블록체인 구현 강좌 8 - 나만의 비트코인 발행하기

이번 포스팅 부터는 앞에서 만든 blockchain을 서버에서 구현해보도록 하겠다. 우리는 서버 구축을 간단하게 도와줄 express api를 사용할것이다. 일단 구글로 가서 express npm을 검색하자. 아래 주소로 들어가도 된다.

https://www.npmjs.com/package/express

콘솔을 열어서 위에 install명령어를 자신의 개발 폴더 위치에서 입력해준다.


이제 express api를 설치 완료 했다. 

개발환경으로 가서 api.js 파일을 생성해주고 아래 소스 코드를 입력해주자 아래 소스코드는 express npm 문서에 있다. 간단하게 설명하면 app.get은 웹브라우저에 / 의 값이 들어오면 함수 아래를 실행하겠다는 뜻이다. /main, /home 등 다양한 주소를 입력해 줄 수 있다. 그러면 이 get 함수가 브라우저에 입력되는 문자열을 확인해서 함수를 실행한다. 

app.listen은 몇번 포트를 설정할것이다 라는뜻 3000이면 localhost:3000으로 입력을 해야 위에 get 함수가 실행이 된다. 설명이 너무 간단하고 추상적인데 이해가 안간다면 구글에 node js epxress 에 관한 기초지식을 쌓고 오는 것도 좋겠다.


var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.send('Hello World')
})
app.listen(3000)


네비게이션



서버실행

이제 터미널을 열고 node 경로/api.js 를 실행시켜준다. 그리고 웹브라우저에 localhost:3000을 입력- > helloworld 출력 확인



마무리

이제 blockchain을 구현할 서버작업을 마쳤다. 앞으로 이 서버가 어떻게 사용이될지 조금더 살펴보겠다.

자바스크립트로 블록체인 구현 강좌7 - 나만의 비트코인 발행하기


이번 포스팅에서는 블록체인 기술에서 핵심이라고 할 수 있는 작업증명 POW 개념을 알아보고 코드로 구현해 보자. 간단한 용어정리를 하고 넘어가자.


#용어정리

해쉬: 해쉬는 의미없는 데이터다. 컴퓨터에서 블럭의 길이를 맞추기 위해서 메모리에 작성된 의미없는 데이터다.

예)0000asdkflqwjkeljakldjflaj;

블럭: 해쉬를 가지고 있는 사람이 코인을 획득할 수 있는 블록을 의미

난이도: 블럭이 생성되는 시간을 일정하게 조정하기 위해 사용되는 개념

(전체 해쉬의 양 증가 -> 난이도 증가-> 블럭찾는데 더 많은 해쉬 필요 _> 블럭 생성시간 유지됨)

51% 공격: 전체 해쉬의 51% 이상 가진 집단이 존재할때 전체 코인의 이동정보, 즉 블록체인에 잘못된 정보가 전달 될 수 있다는 개념

pow: 컴퓨터간에 정보를 교환할때 통신방법에 대한 규칙이다. 많은 해쉬를 가진 사람이 코인을 획득할 수 있는 블럭을 더 많이 발견할 수 있는 시스템이다.



이전 포스팅에 이어서 blockchain.js에 작업증명을 담당하는 코드를 작성해보자.

#작업 순서도

    1. bitcoin.hashBlock(previousBlockHash,currentBlockData,nonce) - test.js에서 호출 할 것이다.

    2. 맞는 해쉬값(0000asldjflak) 찾을 까지 반복적으로 1. 작업을 실행한다

    3. 맞는 해쉬 값을 찾기 위해서 nonce 변경해 가면서 찾는다.

    4. 마지막으로 정확한 hash 값을 찾고 정확한 hash 값을 찾은 nonce 값을 리턴 한다.


//pow 작업 함수 - 이전블록의 해쉬, 현재 블록 데이터와 nonce 값을 사용한다.
Blockchain.prototype.proofOfWork = function(previousBlockHash,currentBlockData){

let nonce = 0;
let hash = this.hashBlock(previousBlockHash,currentBlockData,nonce);
while(hash.substring(0,4) != '0000'){
nonce++;
hash = this.hashBlock(previousBlockHash,currentBlockData,nonce)
}
return nonce;
}


이제 test.js에서 위에 blockchain.js에서 작성한 함수를 호출 해보자.


//blockchain.js 모듈을 이곳에서 가져다 쓰겠다.
const Blockchain = require('./blockchain');


//위에서 가져온 모듈의 객체를 만든다.
const bitcoin = new Blockchain();

const previousBlockHash = "abcdedferefa"
const currentBlockData = [
{
amount: 10,
sender: 'BACKadffaaf',
recipient: 'HONGllalflks'

},
{
amount: 20,
sender: 'PACKadffaaf',
recipient: 'HONGllalflks'

},
{
amount: 30,
sender: 'PACKadffaaf',
recipient: 'HONGllalflks'

}
]

//pow 작업
console.log(bitcoin.proofOfWork(previousBlockHash,currentBlockData));


실행을 하면 

이 값이 나온다.!!

함수가 총 141237번 실행 한뒤 맞는 해쉬 값을 찾았다. 그러면 이 nonce 값을 이용해서 그 맞는 해쉬 값이 무엇인지 한번 살펴보자.


test.js에서 해쉬블락 함수에 위에서 찾은 값 141237값을 넣었다. 어떤 해쉬 함수가 나올까?

console.log(bitcoin.hashBlock(previousBlockHash,currentBlockData,141237))


결과


제네시스블록 생성

제네시스 블록을 생성해보자. 간단하다. blockchain.js 페이지에서 아래 소스 코드를 작성해준다. creatNewBlock 함수의 인자값은 임의로 넣어줘도 ok.

//블록체인 데이터 구조
function Blockchain(){
this.chain = [];
this.pendingTransaction = [];
//제네시스 블락 - 임의의 인자값 넣어준다.
this.createNewBlock(100,'0','0')
}


test.js 페이지로 와서 제네시스 블럭을 한번 찍어보자. 위에서 작성했던 noce 100 , hash 0 ,  previousBlockHash 0 값이 들어가있는 제네시스 블럭이 생성되었다.

//blockchain.js 모듈을 이곳에서 가져다 쓰겠다.
const Blockchain = require('./blockchain');


//위에서 가져온 모듈의 객체를 만든다.
const bitcoin = new Blockchain();

//제네시스 블락
console.log(bitcoin)


//제네시스 블락 !
// Blockchain {
// chain:
// [ { index: 1,
// timestamp: 1527475657742,
// transactions: [],
// nonce: 100,
// hash: '0',
// previousBlockHash: '0' } ],
// pendingTransaction: [] }


마무리

이제 pow 방식으로 채굴하는 방식이 조금 이해가 될것이다. 맞는 해쉬값을 찾을때까지 pow함수를 반복하고 그 과정에서 수많은 nonce 값들이 변경된다는 사실. 그리고 이 방식이 왜 더 좋은 컴퓨팅 파워가 필요한지도 좀더 이해가 됐으리라 생각한다.


소스코드

blockchain.zip

자바스크립트로 블록체인 구현 강좌6 - 나만의 비트코인 발행하기

저번 시간에 포스팅한 sha256 암호화 값 리턴 함수가 어떻게 사용되는지 보겠다. 일단 test.js 부분을 다 지운다. 

그리고 아래 코드를 넣어준다. bitcoin 객체의 hashBlock 함수는 3개의 인자값을 받는다. 1. 이전 블락의 hash 2.현재 블록의 거래 데이터 3.nonce 값


//blockchain.js 모듈을 이곳에서 가져다 쓰겠다.
const Blockchain = require('./blockchain');


//위에서 가져온 모듈의 객체를 만든다.
const bitcoin = new Blockchain();

const previousBlockHash = "abcdedferefa"
const currentBlockData = [
{
amount: 10,
sender: 'PACKadffaaf',
recipient: 'HONGllalflks'

},
{
amount: 20,
sender: 'PACKadffaaf',
recipient: 'HONGllalflks'

},
{
amount: 30,
sender: 'PACKadffaaf',
recipient: 'HONGllalflks'

}
]

const nonce = 100;


console.log(bitcoin.hashBlock(previousBlockHash,currentBlockData,nonce))


//859096659fb3a8b0f053eb068c4b11ee24ba38fecaf6ea629ff301d14feeae84


blockchain.js에서 만든 hash 함수를 테스트 해보았다. console.log  를 찍어보면 해쉬 함수가 리턴 한 값을 볼 수가 있다. 여기서.

sender 보내는 사람이 PACK... 인데 여기서 P를 B로만 바꿔 보겠다. 그리고 실행해보자.


//blockchain.js 모듈을 이곳에서 가져다 쓰겠다.
const Blockchain = require('./blockchain');


//위에서 가져온 모듈의 객체를 만든다.
const bitcoin = new Blockchain();

const previousBlockHash = "abcdedferefa"
const currentBlockData = [
{
amount: 10,
sender: 'BACKadffaaf',
recipient: 'HONGllalflks'

},
{
amount: 20,
sender: 'PACKadffaaf',
recipient: 'HONGllalflks'

},
{
amount: 30,
sender: 'PACKadffaaf',
recipient: 'HONGllalflks'

}
]

const nonce = 100;


console.log(bitcoin.hashBlock(previousBlockHash,currentBlockData,nonce))


//ec90a89a8364d8762ec3d365f2c8c91b1547af493e068009c119356b41f9699b




문자가 하나만 달라졌는데도 해쉬 값은 완전히..전혀 다른 해쉬값이 리턴되는 것을 볼 수 있다.

자바스크립트로 블록체인 구현 강좌5 - 나만의 비트코인 발행하기


이번 포스팅에서는 sha256 해시생성기와 npm을 이용해서 sha256 모듈을 설치해서 사용해보도록하겠다.

일단.

sha256 은 암호화 알고리즘의 하나이다. 음..엄청쉽게 말해서 '어떤 입력값이든 고정된 길이의 임의의 문자열값으로 출력한다' 라고 알고 있으면 쉽다.

예를 들면 abc 값을 sha256 알고리즘에 넣고 돌리면

BA7816BF8F 01CFEA4141 40DE5DAE22 23B00361A3 96177A9CB4 10FF61F200 15AD

이값이 생성이된다. 길이를 보자.

abcdef를 넣으면?

BEF57EC7F5 3A6D40BEB6 40A780A639 C83BC29AC8 A9816F1FC6 C5C6DCD93C 4721

같은 길이의 임의의값이 출력이 된다.

 

https://passwordsgenerator.net/sha256-hash-generator

이곳에 들어가서 직접 값을 넣어봐도 된다.


그리고 한번 암호화 한건 다시 되돌리기 힘들다는 것이다. 어려운 말로 복호화가 어렵다고 하는데 그냥 아 한번 암호화 해버리면 다시 원래 값으로 되돌리기가 거의 빌게이츠가 삼와머니에서 돈빌릴 확률 보다 낮다고만 알아두자.


그러면 계속해서 코드를 작성해보자. 이번에는 인자값을 받으면 그것을 이용해서 암호화 한다음 리턴해주는 함수를 작성해보도록 한다. 


1.구글에서 npm sha256 모듈 검색 후 다운로드 하기

https://www.npmjs.com/package/sha256 여기 들어가면 npm i sha256 --save 이렇게 생긴 녀석을 볼 수 있다


2.터미널 열고 자신의 개발폴더(blockchain)로 가서 위의 명령어를 쳐준다.



3.확인해보기


3.모듈을 변수에 할당

blockchain.js 맨위에 작성

//sha256 모듈을 가져다 쓰겠다.
const sha256 = require('sha256');



4.Blockchain.prototype 함수들 이어서 맨아래 작성

//해쉬 값 리턴 함수
Blockchain.prototype.hashBlock = function(previousBlockHash,currentBlockData,nonce){
const dataAsString = previousBlockHash + nonce.toString() + JSON.stringify(currentBlockData);
const hash = sha256(dataAsString);
return hash
}


다음 포스팅에서 작성한 해쉬함수를 어떻게 사용하는지 테스트 해보도록하자.





자바스크립트로 블록체인 구현 강좌4 - 나만의 비트코인 발행하기


지난 포스팅에 이어서 이번시간에는 저번 포스팅에서 작성한 마지막 블락 가져오기 함수와 새로운 트랜젝션 생성하기 함수를 test.js 에서 한번 찍어 보겠다. 그리고 트랜잭션과 새로운 블락이 생겼을 때 , 그리고 새로운 블록이 생긴 이후 트랜잭션 데이터는 어떻게 변하는지 이 관계를 살펴보도록 하자.


test.js로 이동해서 새로운 블락을 생성하는 함수와 새로운 트랜젝션을 생성하는 함수를 하나씩 작성한다.


//blockchain.js 모듈을 이곳에서 가져다 쓰겠다.

const Blockchain = require('./blockchain')

//위에서 가져온 모듈의 객체를 만든다.
const bitcoin = new Blockchain();

//새로운 블락 만들기
bitcoin.createNewBlock(1111,"aaaaaaa","1a1a1a1a1a1a");

//새로은 트랜잭션 생성 - (총금액, 보내는이, 받는이)
bitcoin.createNewTransaction(100,'PACKadffaaf','HONGllalflks')

//찍어보기
console.log(bitcoin)


//결과
/*
Blockchain {
chain:
[ { index: 1,
timestamp: 1527228481937,
transactions: [],
nonce: 1111,
hash: '1a1a1a1a1a1a',
previousBlockHash: 'aaaaaaa' } ],
pendingTransaction:
[ { amount: 100, sender: 'PACKadffaaf', recipient: 'HONGllalflks' } ] }
*/

위의 코드에서 주석처리된 결과 부분을 보자

새로운 블락인 index 1 은 chain 배열에 객체 형태로 들어갔다. 

그뒤 발생한 새로운 트랜젝션 은 pendingTransaction 배열에 객체 형태로 들어갔다.

그래서? 이게 뭐? 라고 생각할 수도 있다. 일단은 지금까지 이론으로만 알았던 '블록 하나에  거래내역을 저장한다' 라는 말이 조금 이해가 될것이다. 

그래서 블록체인을 공용장부라고 한다. 일단은 지금 index 1 블록의 transaction[]은 비어있다. 그렇다면 지금 pendingTransaction에 있는 거래 데이터를 어떻게 index : 1 인 블록의 transaction에 기록할까? 채굴을 해야 한다. 이말은 새로운 블락이 하나더 생성이 되면 그 새로운 블락의 transaction에 지금의 미완료된 트랜젝션이 기록된다는 뜻이다.

//새로은 트랜잭션 생성 - (총금액, 보내는이, 받는이)
bitcoin.createNewTransaction(100,'PACKadffaaf','HONGllalflks') 이 코드 아래에 추가


//새로운 블락 생성 - 채굴후 얻은 블락
bitcoin.createNewBlock(2222,"bbbbbbb","2b2b2b2b2b2b");


새로운 블록이 추가 되었다. 한번 찍어보자. 뚜둥. 결과 값은 아래와 같다. 위에서 발생한 pendingTransaction 거래 기록은 새로 생성된 index 2 인 블록의 transaction[] 배열에 들어 갔다. 지금은 [Array] 이렇게 표시가 되어 있는데 저 부분만 한번 찍어보자.

//결과
/*
Blockchain {
chain:
[ { index: 1,
timestamp: 1527229062594,
transactions: [],
nonce: 1111,
hash: '1a1a1a1a1a1a',
previousBlockHash: 'aaaaaaa' },
{ index: 2,
timestamp: 1527229062594,
transactions: [Array],
nonce: 2222,
hash: '2b2b2b2b2b2b',
previousBlockHash: 'bbbbbbb' } ],
pendingTransaction: [] }

*/


index : 2 블록 부분만 찍어보았다. 아래에. transactions 배열 부분을 보자. 위에서 봤던 pendingTransaction의 객체 형태의 데이터가 들어가 있다.

//찍어보기
console.log(bitcoin.chain[1])


//결과
/*
{ index: 2,
timestamp: 1527229359157,
transactions:
[ { amount: 100, sender: 'PACKadffaaf', recipient: 'HONGllalflks' } ],
nonce: 2222,
hash: '2b2b2b2b2b2b',
previousBlockHash: 'bbbbbbb' }

*/


이제 대충 감이 올것이다. 추가로 트랜젝션을 더 발생시켜보자. 위에서 작성한 새로운 블락 만드는 소스 아래에 소스 코드를 추가해준다.

//새로은 트랜잭션 생성2 - (총금액, 보내는이, 받는이)
bitcoin.createNewTransaction(777,'PACKadffaaf','HONGllalflks')
//새로은 트랜잭션 생성3 - (총금액, 보내는이, 받는이)
bitcoin.createNewTransaction(888,'PACKadffaaf','HONGllalflks')
//새로은 트랜잭션 생성4. - (총금액, 보내는이, 받는이)
bitcoin.createNewTransaction(999,'PACKadffaaf','HONGllalflks')



그리고 다시 node 명령어로 실행을하고 결과를 보자. 위에서 발생한 트랜젝션 3건 데이터가 어디에 있는가? 이것만 빨리 캐치하면 된다. pendingTransaction 배열에 있다. 아직 미완결된 거래이기 때문에 일단 저기 들어가 있다. 그러면 저 데이터가 블락안에 들어가서 신뢰할 수 있는 데이터가 되려면 어떻게 해야 하나? 컴퓨팅 파워로 암호를 풀어서 생성해주면 된다. 일단 지금은 컴퓨팅 파워를 엄청 써서 새로운 블락을 또 생성했다고 가정하자. 또 새로운 블락이 생성이 되었기 때문에 해당 코드를 한번 더 작성해보자.


//찍어보기
console.log(bitcoin)


//결과
/*
Blockchain {
chain:
[ { index: 1,
timestamp: 1527229704057,
transactions: [],
nonce: 1111,
hash: '1a1a1a1a1a1a',
previousBlockHash: 'aaaaaaa' },
{ index: 2,
timestamp: 1527229704057,
transactions: [Array],
nonce: 2222,
hash: '2b2b2b2b2b2b',
previousBlockHash: 'bbbbbbb' } ],
pendingTransaction:
[ { amount: 777, sender: 'PACKadffaaf', recipient: 'HONGllalflks' },
{ amount: 888, sender: 'PACKadffaaf', recipient: 'HONGllalflks' },
{ amount: 999, sender: 'PACKadffaaf', recipient: 'HONGllalflks' } ] }

*/


마이닝으로 새로운 블락이 생성되었다.

//새로운 블락 만들기
bitcoin.createNewBlock(3333,"ccccccc","3c3c3c3c3c3c");


이전 거래들이 어떻게 이동이 되는지 자세히 보라. pendingTransaction[] 에 일단 값들이 보이지 않는다. 그리고 index:3 블록 transactions[] 에 Array 배열 값이 생겼다. 이제 거의 감을 잡았으리라 생각한다. 찍어보자.

console.log(bitcoin)


//결과
/*
Blockchain {
chain:
[ { index: 1,
timestamp: 1527229993383,
transactions: [],
nonce: 1111,
hash: '1a1a1a1a1a1a',
previousBlockHash: 'aaaaaaa' },
{ index: 2,
timestamp: 1527229993384,
transactions: [Array],
nonce: 2222,
hash: '2b2b2b2b2b2b',
previousBlockHash: 'bbbbbbb' },
{ index: 3,
timestamp: 1527229993384,
transactions: [Array],
nonce: 3333,
hash: '3c3c3c3c3c3c',
previousBlockHash: 'ccccccc' } ],
pendingTransaction: [] }
*/


index : 3 블록만 찍어보았다. 이전 거래내역들이 새로 생성된 블락으로 이동한것을 볼 수 있다.

//찍어보기
console.log(bitcoin.chain[2])


//결과
/*
{ index: 3,
timestamp: 1527230266389,
transactions:
[ { amount: 777, sender: 'PACKadffaaf', recipient: 'HONGllalflks' },
{ amount: 888, sender: 'PACKadffaaf', recipient: 'HONGllalflks' },
{ amount: 999, sender: 'PACKadffaaf', recipient: 'HONGllalflks' } ],
nonce: 3333,
hash: '3c3c3c3c3c3c',
previousBlockHash: 'ccccccc' }
*/


혹시나해서 test.js의 전체 코드를 올려놓는다.

//blockchain.js 모듈을 이곳에서 가져다 쓰겠다.
const Blockchain = require('./blockchain')

//위에서 가져온 모듈의 객체를 만든다.
const bitcoin = new Blockchain();

//새로운 블락 만들기
bitcoin.createNewBlock(1111,"aaaaaaa","1a1a1a1a1a1a");

//새로은 트랜잭션 생성 - (총금액, 보내는이, 받는이)
bitcoin.createNewTransaction(100,'PACKadffaaf','HONGllalflks')


//새로운 블락 생성 - 채굴후 얻은 블락(마이닝)
bitcoin.createNewBlock(2222,"bbbbbbb","2b2b2b2b2b2b");

//새로은 트랜잭션 생성2 - (총금액, 보내는이, 받는이)
bitcoin.createNewTransaction(777,'PACKadffaaf','HONGllalflks')
//새로은 트랜잭션 생성3 - (총금액, 보내는이, 받는이)
bitcoin.createNewTransaction(888,'PACKadffaaf','HONGllalflks')
//새로은 트랜잭션 생성4. - (총금액, 보내는이, 받는이)
bitcoin.createNewTransaction(999,'PACKadffaaf','HONGllalflks')


//새로운 블락 만들기
bitcoin.createNewBlock(3333,"ccccccc","3c3c3c3c3c3c");




//찍어보기
console.log(bitcoin.chain[2])


//결과
/*
{ index: 3,
timestamp: 1527230266389,
transactions:
[ { amount: 777, sender: 'PACKadffaaf', recipient: 'HONGllalflks' },
{ amount: 888, sender: 'PACKadffaaf', recipient: 'HONGllalflks' },
{ amount: 999, sender: 'PACKadffaaf', recipient: 'HONGllalflks' } ],
nonce: 3333,
hash: '3c3c3c3c3c3c',
previousBlockHash: 'ccccccc' }
*/









!!만약에 이 포스팅을 보면서 따라 해봤는데도 이해가 안간다면 이것만 기억하자. 

1.거래가 발생하면 트랜잭션 데이터가 생긴다.

2.이 데이터는 아직 신뢰할 수 없다.

3.어떻게 해야하나? -> 채굴자들이 마이닝을 해서 새로운 블락을 생성해야 한다.

4.새로운 블락이 생성되었다.

5.이전 트랜잭션 데이터는 새로운 블락에 쓰여지면서 신뢰할 수 있게된다.




자바스크립트로 블록체인 구현 강좌3 - 나만의 비트코인 발행하기



이번포스팅에서는 마지막 블록을 얻는 함수, 새로운거래가 발생할때 거래 트랜잭션 데이터를 생성하는 함수를 만들어 보도록 하겠다.

먼저 blockchain.js 로가서 이어서 코드를 작성해보자.


Blockchain.prototype.createNewBlock  ... 생략. 이 코드 아래에 마지막 블록을 가져오는 함수를 작성한다.


//마지막 블록 얻기 - chain 배열에는 블록데이터가 들어간다. 맨마지막 블록을 가져와라.
Blockchain.prototype.getLastBlock = function(){
return this.chain[this.chain.length - 1];
}


그 밑에 새로운 트랜잭션이 발생했을 때 작동되는 함수를 작성한다.

참고로 거래가 발생할때 마다 생성되는 데이터를 트랜잭션이라고 하는데, 중요한건 트랜잭션은 거래로 인해 발생한 어떤 것이지 블록이 아니다. 블록이 되려면 채굴자들이 마이닝, 즉 컴퓨팅 파워로 채굴을 해야 한다. 그래서 아직 완결이 안된 데이터라고도 할 수 있다. 우리는 맨위에 function Blockchain(){} 데이터 구조에서 this.newTransaction = [] 배열을 생성했다. 이 이름을 좀 더 직관적으로 pendingTransaction으로 바꿔주도록 하자. 아직 대기상태의, 미완결된 값이기 때문에 이렇게 작명을 해주겠다. 전부다 바꿔주도록 하자.

//새로운 트랜젝션(거래)가 발생했을 때 작동되는 함수
//인자값으로, 총액수, 보내는사람, 받는사람이 들어간다.
Blockchain.prototype.createNewTransaction = function(amount,sender,recipient){
const newTransaction = {
amount: amount,
sender: sender,
recipient: recipient
}

//맨위 트랜잭션 배열에 값을 넣어준다.
this.pendingTransaction.push(newTransaction);

//마지막 블록의 index 에서 + 1
return this.getLastBlock()['index'] + 1
}


blockchain.js의 전체 코드는 아래와 같다. 다음 포스팅에서는 test.js에서 이번 포스팅에서 만든 함수들이 어떻게 출력이되는지 찍어보도록 하겠다. 

//블록체인 데이터 구조
function Blockchain(){
this.chain = [];
this.pendingTransaction = [];
}


//블록체인 프로토 타입 함수 정의
Blockchain.prototype.createNewBlock = function(nonce,previousBlockHash,hash){
//새 블록 객체
const newBlock = {
index: this.chain.length + 1,
timestamp: Date.now(),
transactions: this.pendingTransaction,
nonce:nonce,
hash:hash,
previousBlockHash:previousBlockHash
};

//다음 거래를 위한 거래내역 배열 비워주고 새로운 블록을 chin 배열에 추가
this.pendingTransaction = [];
this.chain.push(newBlock);

return newBlock;

}

//마지막 블록 얻기 - chain 배열에는 블록데이터가 들어간다. 맨마지막 블록을 가져와라.
Blockchain.prototype.getLastBlock = function(){
return this.chain[this.chain.length - 1];
}

//새로운 트랜젝션(거래)가 발생했을 때 작동되는 함수
//인자값으로, 총액수, 보내는사람, 받는사람이 들어간다.
Blockchain.prototype.createNewTransaction = function(amount,sender,recipient){
const newTransaction = {
amount: amount,
sender: sender,
recipient: recipient
}

//맨위 트랜잭션 배열에 값을 넣어준다.
this.pendingTransaction.push(newTransaction);

//마지막 블록의 index 에서 + 1
return this.getLastBlock()['index'] + 1
}

//Blockchain 모듈화
module.exports = Blockchain;



자바스크립트로 블록체인 구현 강좌2 - 나만의 비트코인 발행하기


지난 포스팅에서는 자바스크립트로 블록체인 구현을 위한 셋팅과 자바스크립트의 데이터구조와 프로토타입에 대한 기본 지식을 알아보았다. 이번에는 지난번 포스팅에서 구현한 내용을 직접 console.log로 찍어보면서 대충 아~ 이런거구나 하고 감을 잡아보자

blockchain.js  모듈화 하기

//블록체인 데이터 구조
function Blockchain(){
this.chain = [];
this.newTransactions = [];
}


//블록체인 프로토 타입 함수 정의
Blockchain.prototype.createNewBlock = function(nonce,previousBlockHash,hash){
//새 블록 객체
const newBlock = {
index: this.chain.length + 1,
timestamp: Date.now(),
transactions: this.newTransactions,
nonce:nonce,
hash:hash,
previousBlockHash:previousBlockHash
};

//다음 거래를 위한 거래내역 배열 비워주고 새로운 블록을 chin 배열에 추가
this.newTransactions = [];
this.chain.push(newBlock);

return newBlock;

}

//Blockchain 모듈화
module.exports = Blockchain;

module.exports = Blockchain으로 다른 페이지에서도 이 모듈을 사용할 수 있게 해준다.


test.js 로 이동. 

아래와 같이 코드를 작성해준다. 위에서 작성한 블록체인 코드를 여기서 테스트 해보겠다는 뜻이다. 그리고 실행해보자.

//blockchain.js 모듈을 이곳에서 가져다 쓰겠다.
const Blockchain = require('./blockchain')

//위에서 가져온 모듈의 객체를 만든다.
const bitcoin = new Blockchain();

//찍어보기
console.log(bitcoin)


 node 명령어로 실행해보기 

 node 명령어로 실행한거 확인해보기 -  짜쟌


저게 먼지는 아직 잘 몰라도 일단 콘솔에 우리가 적은 코드랑 비스무리한게 떴다.

자 그럼 이제 직접 새로운 블락을 생성해보자

주석으로 새로운 블락 만들기를 보자. createNewBlock은 앞 포스팅에서 만들어놓은 프로토 타입 함수다. 인자값으로 일단 아무 값이나 넣어주었다.

//blockchain.js 모듈을 이곳에서 가져다 쓰겠다.
const Blockchain = require('./blockchain')

//위에서 가져온 모듈의 객체를 만든다.
const bitcoin = new Blockchain();

//새로운 블락 만들기
bitcoin.createNewBlock(1111,"aaaaaaa","1a1a1a1a1a1a");

//찍어보기
console.log(bitcoin)

//결과
//Blockchain { chain: [], newTransactions: [] }


다시 실행해보자


와우. 일단 그럴듯한 객체 데이터가 생성이 된것을 볼 수 있다. 몇개를 더 만들어 볼까?

//새로운 블락 만들기
bitcoin.createNewBlock(1111,"aaaaaaa","1a1a1a1a1a1a");
bitcoin.createNewBlock(2222,"bbbbbbb","2b2b2b2b2b2b");
bitcoin.createNewBlock(3333,"ccccccc","3c3c3c3c3c3c");


결과

Blockchain {

  chain: 

   [ { index: 1,

       timestamp: 1527223987875,

       transactions: [],

       nonce: 1111,

       hash: '1a1a1a1a1a1a',

       previousBlockHash: 'aaaaaaa' },

     { index: 2,

       timestamp: 1527223987875,

       transactions: [],

       nonce: 2222,

       hash: '2b2b2b2b2b2b',

       previousBlockHash: 'bbbbbbb' },

     { index: 3,

       timestamp: 1527223987875,

       transactions: [],

       nonce: 3333,

       hash: '3c3c3c3c3c3c',

       previousBlockHash: 'ccccccc' } ],

  newTransactions: [] }


이번 포스팅에서는 새로운 블락을 생성하고 콘솔로 한번 찍어 보았다. 아직은 이게 먼지 100% 감이 안올거다. 일단 하나씩 따라와 보자. 

+ Recent posts

티스토리 툴바