728x90

알아본다면 당신은 천재임 (못알아봐도 천재)

각 노드, 참여자 컴퓨터에

3001이 관리자 

6001이 노동자..

http서버는 모든 걸 보여주기 용으로 돌리는거

 

라고 대충이해했는데.. 이후에 db서버랑, 리액트서버랑 얘네가 어떻게 맞물리는지 사실 아직도 서버관계를 정확하게 모르겠다! 

 

일단 코드 여기요 (지금까지 한 것만 포크해놓음)

 

https://github.com/jsoyun/4th-project-YunminBlock

 

GitHub - jsoyun/4th-project-YunminBlock: 4th BlockChain Project

4th BlockChain Project. Contribute to jsoyun/4th-project-YunminBlock development by creating an account on GitHub.

github.com

 

 

각 컴퓨터 참여자로 노드 만들어서 

p2p서버 전달 확인해봄

 

참고로 실행할 때는 

node node1/r_httpServer.js

이렇게 했다

 

 

두 서버 각각 열고 

3001
3002

 

 

get 요청인 blocks로 들어가보면

둘다 제네시스 블록이 잘 들어가 있음요 

 

서버 연결!!

post addpeers로 

3002한테 요청하는거임 

 

3002가 6001 웹소켓으로  상대 웹소켓 주소 ws 6001로 연결

문 똑똑

 

 

 

 

peers로 연결된거 확인!

 

 

이제 둘이 연결됐으니

3002에서 채굴해보겠음 

3002 채굴돼서 들어왔지?

 

 

그렇다면 3001을 새로고침해보면 3002랑 연결되어있고 그블록의 길이가 더 길어서 추가됨

 

 

연결되어있으니까 3002에서 연속 2개 추가해도 업데이트 됨

 

 

 

 

 

 

 

3001에서 블록채굴해도 마찬가지로 3002에서 업뎃됨 

연속으로 4,5 값 넣어서 블록추가함


서버 통신 코드

 

 

 

httpServer.js

post로 보내면 

data로 이름지어서 "data" : 웹소켓 주소 가능한거임

 

이 웹소켓 주소 data가 connectToPeers함수로 들어감 얘가 웹소켓 연결해줌

P2PServer.js

 

소켓에 넣고 메세지 핸들러 함수쓰고

얘네가 보내주는거 관리하는거임 

 

 

메세지 핸들러는 이렇게 여기서 변수로 지정해줬음 

(그 검증할 때 변수 10으로 다 잡아서 블록10개 이전과 비교해서 생성시간 알아내는 거 있잖아

이거요 blockchain.js

걔랑 비슷한 원리인듯

신기한게 컴퓨터는 바보라서 걍 숫자 넣어서 계산하는 거기 때문에 시간인지 뭔지 안적어도 가능했음)

 

 

대신 쓸때는 위처럼 MessageType.QUERY_LATEST 이런식으로 해야 얘가 찾겠지?

 

 

연결됐을 때 채굴하면 broadcast로 연결되어있는애들 전부한테 뿌려주는 거

(근데 생각해보니까 마지막 최신블록 담아서 보내주는거 말고도 아예 많이 다르면 전체 교체해야되는 replace함수 써야되는데 broadcast(initMessageHandler(ws)) 이걸로 해줘야 되는거 아닌가....? 흠 정리하고 다시 수정해봐야겠다. )

 

 

 

중간에 맞이했던 에러들

브로드캐스트에 저 함수를넣지 않은 것 말고도 있음

 

갑자기 이거 뜸

(node:11496) Warning: Accessing non-existent property 'Blocks' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
(node:11496) Warning: Accessing non-existent property 'getLastBlock' of module exports inside circular dependency                                                                     cular dependency
(node:11496) Warning: Accessing non-existent property 'createHash' of module exports inside circular dependency                                                                       de circular dependency
(node:11496) Warning: Accessing non-existent property 'isValidTimestamp' of module exports  circular dependency
inside circular dependency

이게 찾아보니까 순환참조? a스크립트에서 만든 함수 내보내고 b에서 a의 함수 가져왔는데 또 가져와서? 생기는 뭐 중복돼서 그런거라고 했는데 

이전에 안뜨다가 갑자기 떠서 당황... 작동은 되는데 불안하죠잉

 

결국 전역변수에 있는 애들 다 지역변수로 넣어서 함... 

 

이런식으로.. 

 

 

 

 

 

 

아 그리고 블록체인 에 

 

이 부분 틀렸다는데 

흠 내가 이해한 거는 새블럭을 현재 시간이랑 어느정도 오차범위까지는 인정하는 코드라고 봤거든 책도 그 얘기고..

 

 

흠..어렵군!!

 

 

 

 

 

728x90
728x90

chainedBlock.js  이라 이름지음요

 

이전 글에서 블록하나를 생성했으니 여러 블록을 이어서 블록체인 만들어보기

코드는 수업때 했지만 이번에도 설명을 보면서 고대로 정리했음 https://berrypjh.tistory.com/50

설명은 똑같고 내가 헤맨거 좀좀따리 추가됨

 

(리눅스 우분투에서 작업중)

 

블록해시 값 구하기

....이전과 같음

class BlockHeader{
        constructor(version,index, previousHash, timestamp, merkleRoot, bit, nonce){
	     this.version = version
		//index 값 넣기
     	 this.index = index
	     this.previousHash = previousHash
	     this.timetamp = timestamp
	     this.merkleRoot = merkleRoot
	     this.bit = bit
	     this.nonce = nonce
		

	}
}

//버전계산하는 함수 
function getVersion(){
...

}

function createGenesisBlock(){
	const version = getVersion()
	//index 값 넣기
	const index = 0
	const previousHash = '0'.repeat(64)
	const timestamp = parseInt(Date.now()/1000)
	const body = ['hello block']
	const tree = merkle('sha256').sync(body)
	const merkleRoot = tree.root() || '0'.repeat(64)
	const bit = 0
	const nonce = 0

...     
	//헤더에 대입
	const header = new BlockHeader(version, index, previousHash, timestamp, merkleRoot, bit,nonce)
    return new Block(header, body)

}
//값넣어서 블록생성
const block = createGenesisBlock()
console.log(block)

 

1) index 값 넣어서 이후에 만들 블록체인 순서를 확인할 수 있게 한다.

(아까 index를 선언만 하고 BlockHeader constructor 구조에 안넣고 헤더에 대입에도 안넣어서 안됐었음

게다가 뒤에 선언하는거랑 넣어준 순서다르면 안되더라...)

 

 

2) 블록체인 불러오기 

//여러개 들어갈 수 있는 배열로 Blocks를 만들어줌 
let Blocks = [createGenesisBlock()]


//현재 있는 블록들을 다 리턴해주는 함수
function getBlocks(){
	return Blocks
}

function getLastBlock(){
	//길이 1이니까 1-1 =0 즉 첫번째배열 불러와 
	return Blocks[Blocks.length - 1]

}

블록체인의 블록들을 넣어줄 Blocks배열을 만들고 첫번째 블록을 생성하는 함수인 createGenesisBlock함수를 해당 배열에 미리 넣어둔다.

 

3)블록해시값 구하기

 

//블록해시 값 구하기
//data에는 블록이 들어오는거임, 이블록을 가지고 해시값을 만들어내는 것임
function createHash (data){
	const {version,previousHash,timestamp, merkleRoot, bit, nonce}= data.header
	const blockString = version +previousHash +timestamp+ merkleRoot+ bit+ nonce
	const hash = crypto.js.SHA256(blockString).toString()
	return hash
}

블록헤더 안에 든 정보들 (version 등)의 합산 정보를 구한후 SHA256으로 변환하면 블록의 블록해시값을 구할 수 있다.

 

crypto.js 쓰려면 

const cryptojs =require('crypto-js')

이거 추가해야될거야

 

node 스크립트이름

 

 

다음블록 생성하기

//다음블록 생성하기 
function nextBlock(bodyData) {
	const prevBlock = getLastBlock()
}

이전 블록의 정보(가장 최신 블록 정보)를 getLastBlock함수를 이용해서 가져오고 prevBlock에 넣어둔다.

//다음블록 생성하기 
function nextBlock(bodyData) {
	const prevBlock = getLastBlock()
	const version = getVersion()
	//다음순서니까 하나 추가됨
	const index = prevBlock.header.index +1
	//createHash함수에 이전블록 정보를 넣어 블록해시값을 구해넣는다.
	const previousHash = createHash(prevBlock)
	const timestamp = parseInt(Date.now()/1000)
	//블록body부분에 저장될 트랜잭션(거래정보)인 bodyData를
	//merkle몯ㄹ을 사용하여 트랜잭션들의 해시트리를 만들어 tree에 넣어
	const tree = merkle('sha256').sync(bodyData)
	//여기서 최종적으로 구해진 해시값인 머클루트 해시값을 merkleRoot변수에 넣어
	const merkleRoot = tree.root() || '0'.repeat(64)
	const bit = 0
	const nonce = 0

const header = new BlockHeader(index,version,previousHash,timestamp, merkleRoot, bit, nonce)
     return new Block(header,bodyData)

}

머클루트 값을 통해 단일 블록내에 존재하는 트랜잭션의 무결성을 검증할 수 있고,

머클루트 값을 이용해 블록의 해시값을 생성했기 때문에 블록의 해시의 무결성도 함께 검증할 수 있다. 

 

 

두번째 블록 생성하고 출력해보기 

//다음블록 생성하기 
function nextBlock(bodyData) {
	const prevBlock = getLastBlock()
	const version = getVersion()
	//다음순서니까 하나 추가됨
	const index = prevBlock.header.index +1
	//createHash함수에 이전블록 정보를 넣어 블록해시값을 구해넣는다.
	const previousHash = createHash(prevBlock)
	const timestamp = parseInt(Date.now()/1000)
	//블록body부분에 저장될 트랜잭션(거래정보)인 bodyData를
	//merkle몯ㄹ을 사용하여 트랜잭션들의 해시트리를 만들어 tree에 넣어
	const tree = merkle('sha256').sync(bodyData)
	//여기서 최종적으로 구해진 해시값인 머클루트 해시값을 merkleRoot변수에 넣어
	const merkleRoot = tree.root() || '0'.repeat(64)
	const bit = 0
	const nonce = 0

	const header = new BlockHeader(version,index,previousHash,timestamp, merkleRoot, bit, nonce)
    return new Block(header,bodyData)

}
//다음블록생성 출력하기
const block1 = nextBlock(["tranjaction1"])
console.log(block1)

인덱스1 이면 배열은 0부터 시작하니까 두번째 맞겠지..?

트랜잭션 값이 'tranjaction1'인 두번째 블록 생성됨 확인 

 

 

블록체인에 넣기

 

function addBlock(bodyData) {
	const newBlock = nextBlock(bodyData)
	Blocks.push(newBlock)
}

addBlock(['transaction1'])
addBlock(['transaction2'])
addBlock(['transaction3'])
addBlock(['transaction4'])
addBlock(['transaction5'])

위처럼 여러 트랜잭션을 순차적으로 addBlock함수를 통해 트랜잭션 값을 전달하여 블록을 생성하고 Blocks배열에 넣어보기

 

최종결과 출력하기

console.log(Blocks);

 

결과

 

전체 코드

더보기
const fs = require('fs')
const merkle = require('merkle')
const cryptojs = require('crypto-js')

class Block{
        constructor(header, body){
		this.header = header
		this.body = body
	}
}

class BlockHeader{
        constructor(version,index, previousHash, timestamp, merkleRoot, bit, nonce){
	     this.version = version
		//index 값 넣기
     	 this.index = index
	     this.previousHash = previousHash
	     this.timetamp = timestamp
	     this.merkleRoot = merkleRoot
	     this.bit = bit
	     this.nonce = nonce
		

	}
}

//버전계산하는 함수 
function getVersion(){
	const package = fs.readFileSync("package.json")
	console.log(JSON.parse(package).version)
	return JSON.parse(package).version

}


//getVersion()

function createGenesisBlock(){
	const version = getVersion()
	//index 값 넣기
	const index = 0
	const previousHash = '0'.repeat(64)
	const timestamp = parseInt(Date.now()/1000)
	const body = ['hello block']
	const tree = merkle('sha256').sync(body)
	const merkleRoot = tree.root() || '0'.repeat(64)
	const bit = 0
	const nonce = 0

	// console.log("version : %s, timestamp: %d, body : %s",version,timestamp,body)
	// console.log("previousHash : %d", previousHash);
	// console.log("tree :")
	// // console.log(tree)
	// console.log("merkleRoot : %s", merkleRoot);
	// console.log("merkleRoot : %s", merkleRoot.toString('hex'));
     
	//헤더에 대입
	const header = new BlockHeader(version, index, previousHash, timestamp, merkleRoot, bit,nonce)
    return new Block(header, body)

}
//값넣어서 블록생성
let Blocks = [createGenesisBlock()]
function getBlocks(){
	return Blocks
}
function getLastBlock(){
	return Blocks[Blocks.length -1]
}


//블록해시 값 구하기
function createHash (data){
	const {version,previousHash,timestamp, merkleRoot, bit, nonce}= data.header
	const blockString = version +previousHash +timestamp+ merkleRoot+ bit+ nonce
	const hash = cryptojs.SHA256(blockString).toString()
	return hash
}

// const block = createGenesisBlock()
// const testHash = createHash(block)
// console.log(testHash)

//다음블록 생성하기 
function nextBlock(bodyData) {
	const prevBlock = getLastBlock()
	const version = getVersion()
	//다음순서니까 하나 추가됨
	const index = prevBlock.header.index +1
	//createHash함수에 이전블록 정보를 넣어 블록해시값을 구해넣는다.
	const previousHash = createHash(prevBlock)
	const timestamp = parseInt(Date.now()/1000)
	//블록body부분에 저장될 트랜잭션(거래정보)인 bodyData를
	//merkle몯ㄹ을 사용하여 트랜잭션들의 해시트리를 만들어 tree에 넣어
	const tree = merkle('sha256').sync(bodyData)
	//여기서 최종적으로 구해진 해시값인 머클루트 해시값을 merkleRoot변수에 넣어
	const merkleRoot = tree.root() || '0'.repeat(64)
	const bit = 0
	const nonce = 0

	const header = new BlockHeader(version,index,previousHash,timestamp, merkleRoot, bit, nonce)
    return new Block(header,bodyData)

}
//다음블록생성 출력하기
const block1 = nextBlock(["tranjaction1"])
// console.log(block1)

//addblock함수를 통해 순차적으로 트랜잭션값전달해 블록생성하고
function addBlock(bodyData) {
	const newBlock = nextBlock(bodyData)
	Blocks.push(newBlock)
}

addBlock(['transaction1'])
addBlock(['transaction2'])
addBlock(['transaction3'])
addBlock(['transaction4'])
addBlock(['transaction5'])

console.log(Blocks);
728x90

+ Recent posts