728x90

먼저 꿀팁을 나눠준 학우들에게 감사합니다..

 

박수 짝짝짝

 

평소하던데로 

깃허브에서 

레포지토리 만들고 

주소 복사한다음에

 

깃데스크탑에 들어와서 

요기서 깃클론하고

 

작업할 때 

오픈 비주얼 코드 누르고 

터미널 켜져 있으면 

그걸로 하고 아니면 새 터미널들어가서 켜고

 

 

아래 보면

터미널이 원래 cmd로 되어있을건데

 

이걸 우분투로 바꿔주면

 

짠 

다가려놔서 안보이겠지만

wsl 작업창이 됐고요

/mnt 경로가 cd

커밋도 잘되고요

 

 

 

 

 

 

/mnt 경로는 바로

mnt

mnt는 mount의 약자 뜻을 가진 경로. 리눅스 프로그램에 기기의 탈부착으로 임시로 연결된 경로가 생기면 해당 경로에서 확인할 수가 있습니다. 현재 프로젝트의 AWS에는 연결된 외부 장치나 시스템이 없으므로 아무런 경로가 나오지 않습니다. 하지만 시스템의 용량을 확장할 때나 WSL에서 윈도우 시스템을 인식할 때 해당 경로로 인식할 수가 있습니다.

//WSL에서의 윈도우 인식
///mnt 경로
c d wsl

여기서 C는 Windows에서의 C 드라이브를 의미합니다.

출처: https://tecoble.techcourse.co.kr/post/2021-10-18-linux-file-directory-system/

 

 

 

 

728x90
728x90

겨우됐다 지갑생성하기....

 

chainedBlock에 

return을 빼먹어서 였음...

 

chainedBlock.js 코드전체

더보기
const fs = require('fs')
const merkle = require('merkle')
const cryptojs =require('crypto-js') 
// const { randomBytes } = require('crypto')
const random = require('random')
const { get } = require('http')

//예상 채굴 시간과 난이도 조절 단위수를 변수로 설정한다
const BLOCK_GENERATION_INTERVAL = 10  //second
const DIFFICULT_ADJUSTMENT_INTERVAL = 10 //in blocks




//블럭 형태 (헤더, 바디)
class Block{
        constructor(header, body){
		this.header = header
		this.body = body
	}
}

class BlockHeader{
        constructor(version,index, previousHash, timestamp, merkleRoot,difficulty, nonce){
	     this.version = version
	     this.index = index
	     this.previousHash = previousHash
	     this.timetamp = timestamp //블럭만들어진 시간
	     this.merkleRoot = merkleRoot
	    //  this.bit = bit
		this.difficulty = difficulty //채굴난이도. 아직안씀
	     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()
	const index= 0 //맨처음이라 인덱스0
	const previousHash = '0'.repeat(64) //sha256암호가 64자리니까 0을 64자리로 바꿔줌
	// const timestamp = parseInt(Date.now()/1000)
	//비트코인 날짜로..비트코인최초탄생일 2009/01/03 6:15pm (UTC)
	const timestamp = 1231006505  
	const body = ['제네시스블록 바디임요']
	const tree = merkle('sha256').sync(body) //바디값불러와서 sha256으로 암호화
	const merkleRoot = tree.root() || '0'.repeat(64)
	//루트값없으면 || 뒤에값 출력
	const difficulty = 0 //헤더값에 난이도 아직 0임
	const nonce = 0

	// console.log("version : %s, timestamp: %d, body : %s",version,timestamp,body)
	// console.log("previousHash : %d", previousHash);
	// console.log("merkleRoot : %d", merkleRoot);

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

}

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


//블록저장할수있는애들, 여러개 들어갈 수 있는 배열을 만들어줌
let Blocks = [createGenesisBlock()]


//현재 있는 블록을 다 리턴해주는 함수, 블럭목록 부르는 함수
function getBlocks(){
	return Blocks
}
//제일 마지막에 만든 블록 가져오기
function getLastBlock(){
	//길이 1이니까 1-1 =0 즉 첫번째배열 불러와 
	return Blocks[Blocks.length - 1]

}

//data에는 블록이 들어오는거임, 이블록을 가지고 해시값을 만들어내는 것임
// function createHash(data){
// 	const {version, index,previousHash,timestamp,merkleRoot,difficulty,nonce}= data.header
// 	const blockString = version + index + previousHash + timestamp + merkleRoot + difficulty + nonce
// 	const hash = cryptojs.SHA256(blockString).toString()
// 	return hash
// }
function createHash(data){
	//인자로 받은 것중에 헤더를 뽑아내서
	const {version, index, previousHash, timestamp, merkleRoot, difficulty, nonce} = data.header
	const blockString = version + index + previousHash + timestamp + merkleRoot + difficulty + nonce
	//다 합쳐서 해시로 만들고 리턴
	const hash = cryptojs.SHA256(blockString).toString()
	return hash
}

function calculateHash(version, index, 
		previousHash,timestamp,merkleRoot,difficulty,nonce){
//헤더의 값에 nonce값을 추가해서 모두 더한 string을 가지고 암호화 
//한 결과 hash를 내보낸다
	const blockString = version + index + previousHash + timestamp + merkleRoot + difficulty + nonce
	const hash = cryptojs.SHA256(blockString).toString()
	return hash
}
// const genesisBlock =createGenesisBlock()
//const testHash = createHash(block)
// console.log(genesisBlock)


//다음블록 만들었을 때 기존 블록 정보 가져와
function nextBlock(bodyData){
	//마지막 블럭, 이전블록으로
	const prevBlock = getLastBlock()
	const version = getVersion()
	const index = prevBlock.header.index + 1
	//이전 블록의 해시값
	const previousHash = createHash(prevBlock)
	const timestamp = parseInt(Date.now()/1000)
	const tree = merkle('sha256').sync(bodyData)
	const merkleRoot = tree.root() || '0'.repeat(64)
	//난이도 조절하는 함수 추가 
	const difficulty = getDifficulty(getBlocks())
    // const nonce = 0
    // const header = new BlockHeader(version, index, previousHash,timestamp,merkleRoot,bit,nonce)
	const header = findBlock(version, index, 
		previousHash,timestamp,merkleRoot,difficulty)
	return new Block(header,bodyData)


}
// const block1 = nextBlock(["tranjaction1"])
// console.log(block1)


function addBlock(bodyData){
	const newBlock = nextBlock(bodyData)
	Blocks.push(newBlock)
}
// addBlock(['transaction1'])
// addBlock(['transaction2'])
// addBlock(['transaction3'])
// addBlock(['transaction4'])
// addBlock(['transaction5'])
// console.log(Blocks)

//0103
// function replaceChain(newBlocks){
// 	if (isValidChain(newBlocks)){
// if 	((newBlocks.length> Blocks.length) ||
// (newBlocks.length=== Blocks.length) && random.boolean()){
// 	Blocks = newBlocks
// 	broadcast(responseLatestMsg())
// 	} 
// }
// 	else {
// 		console.log("받은 원장에 문제가 있음")
// 	}
// }
function hexToBinary(s) {
	//헤더부분을 sha256 암호화한 결과
	//16진수 64자리를 2진수로 변환하기
	const lookupTable = {
		'0' : '0000', '1' : '0001', '2': '0010', '3' : '0011',
		'4' : '0100', '5' : '0101', '6': '0110', '7' : '0111',
		'8' : '1000', '9' : '1001', 'A': '1010', 'B' : '1011',
		'C' : '1100', 'D' : '1101', 'E': '1110', 'F' : '1111'
	}

	let ret = "";
	for(let i = 0; i < s.length; i++){
		if (lookupTable[s[i]]) {
			ret += lookupTable[s[i]];
		}
		else { return null; }
	}
	return ret;
}
function hashMatchesDifficulty(hash, difficulty) {
	//difficulty를 이용해 만든 조건을 만족하는지 hash값과 대조해
	//조건에 해당되면 블록 생성
	const hashBinary = hexToBinary(hash.toUpperCase())
	 //difficulty 난이도가 높아짐에 따라 0개수가 늘어남 
	const requirePrefix = '0'.repeat(difficulty)
	//높으면 높을수록 조건을 맞추기가 까다로워짐(nonce값과 time값이 바뀌면서 암호화값이 달라진다.)
	return hashBinary.startsWith(requirePrefix)

}

function findBlock(currentVersion, nextIndex, previousHash, nextTimestamp,
	merkleRoot, difficulty) {
		//calculateHash값이 조건이 맞을때까지 while문으로 반복
		//조건문 반복할때마다 nonce값 증가
		let nonce = 0;
		while (true) {
			var hash = calculateHash(currentVersion, nextIndex, previousHash, nextTimestamp,
				merkleRoot, difficulty,nonce)
				if (hashMatchesDifficulty(hash,difficulty)){
					return new BlockHeader(currentVersion, nextIndex, previousHash, nextTimestamp,
						merkleRoot, difficulty,nonce)

				}
				nonce++ ;
				
		}
	}

	function getDifficulty(blocks){
		const lastBlock = blocks[blocks.length -1]
		if (lastBlock.header.index !==0 && lastBlock.header.index
			% DIFFICULT_ADJUSTMENT_INTERVAL === 0){
				//마지막 블럭헤더인덱스가 0이 아니고
				//난이도 조절수만큼 나누고 나머지가 0이면

				//난이도 조정함수 실행
				return getAdjustDifficulty(lastBlock,blocks)
			}
			//난이도 리턴
			return lastBlock.header.difficulty
	}

	function getAdjustDifficulty(lastBlock, blocks){
     // 지금 블록에서 난이도 조절 단위 수만큼의 전 블록과의 time 
	 //즉, 생성시간을 비교해서 자신의 예상 시간보다 느리거나 빠르면 난이도를 조절한다.
    //적당하면 난이도가 유지되고 블럭의 생성시간이 느리면 난이도를 낮추고, 빠르면 난이도를 높인다.
		const preAdjustmentBlock = blocks[blocks.length - DIFFICULT_ADJUSTMENT_INTERVAL];
		//시간
		const elapsedTime = lastBlock.header.timestamp - preAdjustmentBlock.header.timestamp
		const expectedTime = BLOCK_GENERATION_INTERVAL * DIFFICULT_ADJUSTMENT_INTERVAL;

		if (elapsedTime/2 > expectedTime) {
			return preAdjustmentBlock.header.difficulty +1;
		}
		else if (elapsedTime * 2 < expectedTime){
			return preAdjustmentBlock.header.difficulty -1 
		}
		else {
			return preAdjustmentBlock.header.difficulty
		}
	}

	function getCurrentTimestamp(){
		//Math.round 반올림함수
		return Math.round(Date().getTime()/ 1000);
	}

	function isValidTimestamp(newBlcok, prevBlock){
		if (newBlock.header.timestamp - prevBlock.header.timestamp > 60)
			return false
		if (getCurrentTimestamp()- newBlock.header.timestamp > 60)
		    return false
		return true
		

	}




module.exports = { hashMatchesDifficulty, isValidTimestamp, getBlocks, createHash,
	 Blocks, getLastBlock, nextBlock, addBlock, getVersion, 
	 createGenesisBlock };    //내보내주는거

httpServer.js

더보기
const express = require("express")
const bodyParser = require("body-parser")
const {getBlocks, nextBlock,getVersion} = require('./chainedBlock.js')
const {addBlock}= require('./checkValidBlock')
const { connectToPeers, getSockets } = require("./p2pServer.js")
const {getPublicKeyFromWallet, initWallet} = require("./encryption")

const http_port = process.env.HTTP_PORT || 3001

function initHttpServer(){
	const app = express()
	app.use(bodyParser.json())
	//추가
	app.post("/addPeers", (req,res)=>{
		const data = req.body.data || []
		console.log(data);
		connectToPeers(data);
		res.send(data);

	})
	app.get("/peers", (req, res)=> {
		let sockInfo = []

		getSockets().forEach(
			(s)=>{
				sockInfo.push(s._socket.remoteAddress+":"+s._socket.remotePort)
			}
		)
		res.send(sockInfo)
	})

	app.get("/blocks",(req,res)=>{
 
		res.send(getBlocks())

	})
	app.get("/version",(req, res)=>{
		res.send(getVersion())
	})

	app.post("/mineBlock",(req,res)=>{
		const data = req.body.data || []
		console.log(data)
		const block = nextBlock(data)
		addBlock(block)
		// res.send(block)
		res.send(getBlocks())
	})

	app.post("/stop", (req,res)=>{
		res.send({"msg":"Stop Server!"})
		process.exit()
	})
	app.get("/address", (req,res)=>{
		initWallet()
		const address = getPublicKeyFromWallet().toString();
		console.log(getPublicKeyFromWallet())
		if(address != "") {
			res.send({"address" : address})
		}
		else {
			res.send("empty address!")
		}
	})
	app.listen(http_port,()=>{
		console.log("Listening Http Port : "+ http_port)
	})


}

initHttpServer()

 

encryption.js

더보기
const fs = require("fs")
//타원곡선개념을 사용한 디지털 터널알고르짐을 짤거임
//타원 곡선 디지털 서명 알고리즘
const ecdsa = require("elliptic")
const ec = new ecdsa.ec("secp256k1")

const privateKeyLocation = "wallet/"+
(process.env.PRIVATE_KEY || "default");
const privateKeyFile = privateKeyLocation + "/private_key"


function initWallet(){
    if (fs.existsSync(privateKeyFile)){
        console.log("기존 지갑 private key 경로 :" + privateKeyFile)
        return;
    }
    if (!fs.existsSync("wallet/")){
        fs.mkdirSync("wallet/")
    }
    if (!fs.existsSync(privateKeyLocation)){ //wallet/default 파일없다면
        fs.mkdirSync(privateKeyLocation)
        //만들어줘.
       
    }
    if (!fs.existsSync(privateKeyFile)){//프라이빗키없으면
        console.log('주소값 키값을 생성중')
        const newPrivatekey = generatePrivatekey()
        fs.writeFileSync(privateKeyFile, newPrivatekey)
        console.log('개인키 생성이 완료됐습니다')

    }
    const newPrivatekey = generatePrivatekey()
    fs.writeFileSync(privateKeyFile,newPrivatekey)
    console.log("새로운 지갑 생성 private key 경로 :" + privateKeyFile)

}

// initWallet()

//비밀키 생성
function generatePrivatekey(){
    const keyPair = ec.genKeyPair();
    const privateKey = keyPair.getPrivate();
    //16진수로 만들어서 리턴
    return privateKey.toString(16);
}
//비밀키(인증서) 출력하는 함수
function getPrivateKeyFromWallet(){
    //지갑에 만들어놓은 걸 읽을 수 있게 해줌
   const buffer = fs.readFileSync(privateKeyFile,"utf8")
   return buffer.toString();
}
//공개키(지갑주소) 만들기
function getPublicKeyFromWallet(){
    const privateKey = getPrivateKeyFromWallet();
    const key = ec.keyFromPrivate(privateKey, "hex");
    return key.getPublic().encode("hex")
}

module.exports= {getPublicKeyFromWallet,initWallet}

 

 

 

node node httpServer.js

로 실행.

 

 

 

 

 

 

 

1. 암호화 종류

단방향 암호화 : 오직 암호화만 가능

양방향 암호화 : 암호화하고 다시 복호화 가능

 

양방향에 경우 당사자 2명을 제외한 나머지 사람들이 몰라야하므로 

비밀키를 정한다. 하지만 이 비밀키를 알 수 있기 때문에 당사자 2명 각각 서로 다른 키를 가진다. 

비대칭키 암호(공개키,비밀키)

 

 

2. 공개키 알고리즘

 

공개키 알고리즘은 크게 두 가지 방식으로 분류됨

1. 소인수분해 문제를 이용해서 만들어지는 것

2. 이산 로그 문제를 이용해서 만드는 방법 입니다. (타원곡선 )

 

 

 

3. 디지털 서명

 

 

4. ECDSA 알고리즘

타원곡선 암호를 전자서명에 접목시킨 암호 알고르짐

비대칭키 암호에 해당

secp256k1 라는 기준에 맞춰진 방정식 사용

발신자에 의한 서명시 사용되는 개인키와 수신자가 발신자의 서명을 사용하는 공개키 한 쌍을 갖음

 

https://server-engineer.tistory.com/586

https://rosypark.tistory.com/108

 

 

 

 

코드 설명잘해놓음

 

https://velog.io/@nara7875/BlockChain%EC%9E%91%EC%97%85%EC%A6%9D%EB%AA%85%EB%A7%88%EC%9D%B4%EB%8B%9D

728x90
728x90

출처: node.js 교과서

 

웹소켓은 실시간 양방향 데이터 전송을 위한 기술이다. 

http와 다르게 ws라는 프로토콜을 사용한다.

노드에서는 ws나 Socket.IO 같은 패키지를 통해 웹소켓을 사용할 수 있다.

 

 

웹소켓이 나오기 이전에는 http기술을 사용하여 실시간 데이터 전송을 구현했다.

그중 한가지가 폴링polling이라는 방식인데 http가  클라이언트에서 서버로 향하는 단방향 통신이므로 주기적으로 서버에 새로운 업데이트가 있는지 확인하는 요청을 보낸 후 , 있으면 가져오는 단순방식!

 

그러다가 HTML5가 나오면서 웹브라우저와 웹서버가 지속적으로 연결된 라인을 통해 실시간으로 데이터를 주고 받을 수 있는 웹소켓이 등장!

웹소켓이 연결되면 계속 연결된 상태로 있음

따로 업데이트가 있는지 요청을 보낼 필요가 없음

 

업데이트할 내용이 생겼다면 서버에서 바로 클라이언트에 알린다. http프로토콜과 포트를 공유할 수 있어서 다른 포트에 연결할 필요도 없다

 

참고로 

서버센트 이벤트 Server Sent Event (SSE)라는 기술도 등장함

처음에 한번만 연결하면 서버가 클라이언트에 지속적으로 데이터 보냄

웹소켓과 다른점은 클라이언트에서 서버로는 데이터를 보낼 수 없다는 것. 즉 단방향통신

 

웹소켓만이 진정한 양방향 통신

 

 

 

 

 

728x90
728x90

다음과 같은 조건을 거쳐야함.

 

1. 블록구조가 유효한지

2. 현재 블록의 인덱스가 이전 블록의 인덱스보다 1만큼 큰지

3. 이전블록의 해시값과 현재 블록의 이전해시가 같은지

4. 데이터 필드로부터 계산한 머클루트와 블록헤더의 머클루트가 동일한지 

 

이 조건 다 맞으면 올바른 구조체이다.

 

 

1.블록구조가 유효한가

//블록의 각각 타입체크 블록구조 유효한지 체크하는 함수
function isValidBlockStructure(block) {
    return typeof(block.blockheader.version) === 'string'
    && typeof(block.header.index) === 'number'
    && typeof(block.header.previousHash) === 'string'
    && typeof(block.header.timestamp) === 'number'
    && typeof(block.header.merkleRoot) === 'string'
    && typeof(block.body) === 'object'
}
//위 함수를 통해 블록구조의 유효성 검사
function isValidNewBlock(newBlock, previousBlock) {
    if (isValidBlockStructure(newBlock) === false) {
        console.log('Invalid Block Structure')
        return false;
    }
    return true;
}

 

2. 현재 블록의 인덱스가 이전 블록의 인덱스보다 1만큼 큰지

 

//위 함수를 통해 블록구조의 유효성 검사
function isValidNewBlock(newBlock, previousBlock) {
    if (isValidBlockStructure(newBlock) === false) {
        console.log('Invalid Block Structure')
        return false;
        //현재블록이 이전 블록보다 1크지 않으면 false
    } else if (newBlock.header.index !== previousBlock.header.index +1 ){
        console.log('Invalid Index')
        return false;
    }
    return true;
}

3. 이전블록의 해시값과 현재 블록의 이전해시가 같은지

 

나는 새로 만들어서 하는중이라

blockcopy.js 에 블록생성block, 다음블록연결chainedBlock까지 해놨음

여기서 createHash 내보내주기 

 

//이전블록 해시값과 현재 블록해시값의 이전해시가 같은지
//보려고 내보내줘야함 
module.exports = { 
	createHash,
}

이제 현재 코드,

비교해볼 코드에 createHash 가져와야돼

 

(수업때는 checkValidBlock.js 라고 이름지은걸 걍 다시 하면서 checkedBlock.js라고 했닿 )

const {createHash} = require('./blockcopy');

 

//위 함수를 통해 블록구조의 유효성 검사
function isValidNewBlock(newBlock, previousBlock) {
    if (isValidBlockStructure(newBlock) === false) {
        console.log('Invalid Block Structure')
        return false;
    } else if (newBlock.header.index !== previousBlock.header.index +1 ){
        console.log('Invalid Index')
        return false;
        //이전블록해시랑 현재블록의 이전해시가 다르면 false
    } else if (createHash(previousBlock)!==newBlock.header.previousHash) {
        console.log('Invalid previousHash');
        return false;
    }
    return true;
}

4. 데이터 필드로부터 계산한 머클루트와 블록헤더의 머클루트가 동일한지 

 

merkle쓰려면 설치해야돼

 

npm i merkle
const merkle = require("merkle")

....

//위 함수를 통해 블록구조의 유효성 검사
function isValidNewBlock(newBlock, previousBlock) {
    if (isValidBlockStructure(newBlock) === false) {
        console.log('Invalid Block Structure')
        return false;
    } else if (newBlock.header.index !== previousBlock.header.index +1 ){
        console.log('Invalid Index')
        return false;
    } else if (createHash(previousBlock)!==newBlock.header.previousHash) {
        console.log('Invalid previousHash');
        return false;
    } else if (newBlock.body.length === 0 && ('0'.repeat(64) !== newBlock.header.merkleRoot) 
    || newBlock.body.length !== 0 && (merkle("sha256").sync(newBlock.body).root() !==newBlock.header.merkleRoot))
    {
        console.log('Invalid merkleRoot')
        return false
    }
    return true;
}

새블록 body의 길이가 0일 경우 && 머클루트는 '0'.repeat(64)이 아니면

또는 

 

새블록바디 길이가 0이 아닐경우 && 머클루트에있는 정보와  새블록 바디의 루트 정보들이 같지 않으면

false

 

 

5. 새블록추가

chainedBlock.js 하단에 추가

 

나는 blockcopy.js에 추가함요

module.exports = {
	Blocks,
	getLastBlock,
	createHash,
}

checkValidBlock.js 상단에 불러오기

 

나는 checkBlock.js에 넣음

 

const {createHash,Blocks, createHash} = require('./blockcopy');

 

 

 

 

 

 

 

 

검증과정을 마친 블록

 

//검증마친 블록들은 chainedBlock.js의 Blocks배열에 추가한다
function addBlock(newBlock){
    if(isValidNewBlock(newBlock,getLastBlock())){
        Blocks.push(newBlock)
        return true;
    }
    return false;
}

const block = nextBlock(['transaction1'])
addBlock(block)

console.log(block)

 

 

 

blockcopy.js에서의 nextBlock함수 이용해서 

블록생성하고 출력해보기 

 

 

근데 결과에 

 

계속 이게 나와서 

이 콘솔임

 

코드비교해보니까 

blockcopy.js (chainedBlock.js) 에 

index순서 바꾸니까 안뜨네 뭐냐...

blockcopy.js (chained.js)

결과

 

 

 

코드 전체

blockcopy.js

(chainedBlock.js)

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


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

//블록헤더 구조체 선언 : 헤더 구성 요소 나열
class BlockHeader {
	constructor(index, version, previousHash, timestamp, merkleRoot, bit, nonce) {
	  this.index = index
	  this.version = version
	  this.previousHash = previousHash
	  this.timestamp = 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 index = 0
  const version = getVersion()
  const previousHash = '0'.repeat(64) // 0을 64번 반복
  const timestamp = parseInt(Date.now() / 1000) // 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("merkleRoot: %s", merkleRoot);

  const header = new BlockHeader(index, version, 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
	(index,version,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);

//이전블록 해시값과 현재 블록해시값의 이전해시가 같은지
//보려고 내보내줘야함 
module.exports = { nextBlock, getLastBlock, createHash, Blocks, getVersion, getBlocks }


// function addBlock(newBlock){

// 	if(isValidNewBlock(newBlock,getLastBlock())){

// 		Blocks.push(newBlock)
// 		return true;
// 	} return false;
// }

 

checkedBlock.js

더보기
const merkle = require("merkle")
const {Blocks, createHash, getLastBlock,nextBlock} = require('./blockcopy');
// const { nextBlock } = require("./chainedBlock");


//블록구조 유효한지
//blockcopy.js에서 만든 블록체인

//블록의 각각 타입체크 블록구조 유효한지 체크하는 함수
function isValidBlockStructure(block) {
  return typeof (block.header.version) === 'string'
    && typeof (block.header.index) === 'number'
    && typeof (block.header.previousHash) === 'string'
    && typeof (block.header.timestamp) === 'number'
    && typeof (block.header.merkleRoot) === 'string'
    && typeof (block.body) === 'object'
}
//위 함수를 통해 블록구조의 유효성 검사
function isValidNewBlock(newBlock, previousBlock) {
    if (isValidBlockStructure(newBlock)===false){
		console.log('Invalid Block Structure');
		return false;
	} else if (newBlock.header.index !== previousBlock.header.index +1 ){
        console.log('Invalid Index')
        return false;
    } else if (createHash(previousBlock)!==newBlock.header.previousHash) {
        console.log('Invalid previousHash');
        return false;
        //블록길이가 0일경우
    } else if (newBlock.body.length === 0 
        //머클루트는길이가 
        && ('0'.repeat(64) !== newBlock.header.merkleRoot) 
    || newBlock.body.length !== 0 && (merkle("sha256").sync(newBlock.body).root() !==newBlock.header.merkleRoot))
    {
        console.log('Invalid merkleRoot')
        return false
    }
    return true;
}

//검증마친 블록들은 chainedBlock.js의 Blocks배열에 추가한다
function addBlock(newBlock){
    if(isValidNewBlock(newBlock,getLastBlock())){
        Blocks.push(newBlock)
        return true;
    }
    return false;
}

const block = nextBlock(['transaction1'])
addBlock(block)

console.log(block)
728x90
728x90

우분투 터미널 환경에서 깃허브 커밋하고 푸시할 때

1. 

git init

현재 폴더를 로컬 저장소로 지정

 

2.

.gitignore 파일 생성

모듈들이 커밋안되게 방지 

안에 (node_modules)

 

3.

git status

로컬 저장소의 현재상태확인

빨간 글씨체로 보여지는 파일목록은 추적되지 않은 파일들(Untracked files)

추적되지 않은 파일이란, 준비 영역이나 로컬 저장소에 한번이라도 add되거나 commit되지 않은 파일을 말한다.

반대로 추적 상태인 파일들(Tracked files)은 최소한 한번은 git add 명령을 통해 준비 영역에 포함되거나 commit을 통해 로컬 저장소에 저장된 파일이다.

4.

git add .

git add는 특정 파일만 업로드하고자 할 때 사용한다.

 

git add "파일명"



 

5. 로컬 저장소에 최종저장하는 단계

 git commit -m "메세지"

 

6. 로컬 저장소와 원격저장소를 연결

git remote add origin Git Repository 주소

*origin은 별칭이다.

 

7. 별칭내역을 확인

origin의 별칭으로 등록된 원격 저장소를 확인할 수 있다.

 

 git remote -v

 

 

8. 로컬 저장소의 파일들을 원격 저장소로 올린다.

 

git push origin master




 

 

이렇게 나옴

remote: Support for password authentication was removed on August 13, 2021. Please use a personal access token instead.
remote: Please see https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/ for more information.
fatal: Authentication failed for 'https://github.com/jsoyun/blockchain.git/'

 

그래서 찾아보니까 

 

Settings / Developer settings/Personal access tokens / Generate new token / Token 설정

으로 들어가서

 

토큰 비번을 만들어서 

비번에 넣어주니까 되더라 

 

 

 

 

 

출처:

 

에러시 이거

https://hyeo-noo.tistory.com/184

 

[Mac] GitHub push token 오류 해결

Github 오류 7.29일 새벽 갑자기 git push가 안 되는 현상을 겪었다. 오류의 첫 줄이 무슨 말이냐면 Password 인증방식이 일시적으로 brownout(shutdown?)되었다. Password 대신에 personal access token을 사용..

hyeo-noo.tistory.com

https://shxrecord.tistory.com/179 [두-번째저장소]

https://codecoco.tistory.com/74?category=512233 

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