블록체인 Block-Chain - 블록 생성해보기

dev_swan·2022년 6월 8일
1

블록체인

목록 보기
1/36
post-thumbnail

블록 구성 요소

const block = {
	header: {
		version: '1.0.0',
      	height : 0, // 지금까지 생성된 블록의 수
      	timestamp : 1654651835429, // 블록이 생성된 시간
		previousHash: '', // 이전 해쉬값
		hash: '', // 블록의 고유한 값
		merkleRoot: '', // 데이터값을 암호화한 값
		difficulty: 0, // 채굴에 관련된 값
		nonce: 0, // 채굴에 관련된 값
	},
	body: {
		// 데이터를 담아 놓는 공간
		data: ['asdf', 'asdf', 'asdf'],
	},
};

header에 있는 정보와 body에 있는 정보를 합친 값을 hash라 하고 hash는 그 블록의 고유한 값입니다.

Hash

npm install crypto-js


const SHA256 = require('crypto-js/sha256');

const a = 'hello hash';
console.log(SHA256(a).toString()); // e08e1d7bd3fec53b7360de39482ac30d8d1b7bedead27e013810e29095fee6fb
console.log('e08e1d7bd3fec53b7360de39482ac30d8d1b7bedead27e013810e29095fee6fb'.length); // 64

SHA256( ) 해시 함수 안에 어떠한 값을 넣어도 64글자, 32바이트로 암호화하여 반환해줍니다.
하지만 반환한 결과물을 가지고 원래의 입력한 값을 구할수는 없습니다.
이것을 단방향 암호화라고 합니다.

MerkleRoot

npm install merkle / merkleRoot를 만들어주는 라이브러리


const merkle = require('merkle');

const data = ['asdf', 'asdf', 'asdf', 'asdfasdf', 'asdfasdf', 'asdfasdf'];

const merkleTree = merkle('sha256');

console.log(merkleTree);

/* merkleTree
{
  root: [Function: root],
  level: [Function: level],
  depth: [Function: depth],
  levels: [Function: levels],
  nodes: [Function: nodes],
  getProofPath: [Function: getProofPath]
}
*/ 

const merkleRoot = merkleTree.root(); // merkleTree에 최상단의 root값을 가져옵니다.
console.log(merkleRoot);

/* merkleRoot
D4DE22242F3EB5170177D5DE1936C9C0E19E4CF2CA7E5901CF50C8FCDCD677DD
*/

merkleTree에는 data 배열 안에 있는 ['asdf', 'asdf', 'asdf', 'asdfasdf', 'asdfasdf', 'asdfasdf'] 값들을 1번째와 2번째, 3번째와 4번째 이런식으로 더하여 SHA256으로 해시화하여 암호화한 값이 들어갑니다.
merkleRoot에는 merkleTree의 최상단에 있는 암호화된 값이 들어갑니다.

블록 생성 (Javascript)

  • 블록 헤더 부분 작성
const SHA256 = require('crypto-js/sha256');
const merkle = require('merkle');

// () 가급적 매개변수는 3개이상을 하지 않도록 합시다.

class BlockHeader {
	constructor(_heigth, _previousHash) {
		this.version = BlockHeader.getVersion();
		this.heigth = _heigth;
		this.timestamp = BlockHeader.getTimestamp();
		this.previousHash = _previousHash || '0'.repeat(64);
	}

	static getVersion() {
		return '1.0.0';
	}

	static getTimestamp() {
		return new Date().getTime();
	}
}

const header = new BlockHeader(0, 'test');

console.log(header);

/* header
BlockHeader {
  version: '1.0.0',
  heigth: 0,
  timestamp: 1654666832013,
  previousHash: '0000000000000000000000000000000000000000000000000000000000000000'
}
*/

console.log(header.getVersion()); // error
  • new 라는 키워드를 사용해서 class 문법을 사용했을때 나오는 결과물의 객체는 인스턴스라고 합니다.
  • static = 인스턴스를 생성하기 전에 인스턴스 내부에서 해당 함수를 사용하고 싶을때는 static을 사용합니다.
  • static을 사용하고 인스턴스를 생성하면 static이 붙은 함수는 인스턴스에 포함되지 않습니다.
    따라서 getVersion()header에 없기 때문에 console.log(header.getVersion());는 error가 발생합니다.
  • 블록 생성 부분 작성

class Block {
	constructor(_header, _data) {
		const merkleroot = Block.getMerkleRoot(_data);
		this.version = _header.version;
		this.heigth = _header.heigth;
		this.timestamp = _header.timestamp;
		this.previousHash = _header.previousHash;
		this.hash = Block.createBlockHash(_header, merkleroot);
		this.merkleRoot = merkleroot;
		this.data = _data;
	}

	static getMerkleRoot(_data) {
		const merkleTree = merkle('sha256').sync(_data);
		const merkleRoot = merkleTree.root();
		return merkleRoot;
	}

	static createBlockHash(_header, _merkleroot) {
		const values = Object.values(_header);
		const data = values.join('') + _merkleroot;
		return SHA256(data).toString();
	}
}

const data = ['The Times 03/Jan/2009 Chancellor on brink of second bailout for banks'];

const block = new Block(header, data);

console.log(block);

/* block
Block {
  version: '1.0.0',
  heigth: 0,
  timestamp: 1654666832013,
  previousHash: '0000000000000000000000000000000000000000000000000000000000000000',
  hash: '2599cbfd637243e69f7a7133b4c6d6170f5ead233c98a1551fcb5256743df0b3',
  merkleRoot: 'A6D72BAA3DB900B03E70DF880E503E9164013B4D9A470853EDC115776323A098',
  data: [
    'The Times 03/Jan/2009 Chancellor on brink of second bailout for banks'
  ]
}
*/

블록을 생성할 때 첫번째 블록에는 이름이 붙는데 이것을 제네시스 블록이라고 합니다.
블록을 처음 생성할때에는 previousHash 값을 추가할 필요는 없습니다.

블록 생성 (TypeScript)

import SHA256 from 'crypto-js/sha256';
import merkle from 'merkle';

class BlockHeader {
	version: string;
	heigth: number;
	timestamp: number;
	previousHash: string | number;
	constructor(_heigth: number, _previousHash?: string) {
		this.version = BlockHeader.getVersion();
		this.heigth = _heigth;
		this.timestamp = BlockHeader.getTimestamp();
		this.previousHash = _previousHash || '0'.repeat(64);
	}

	static getVersion() {
		return '1.0.0';
	}

	static getTimestamp() {
		return new Date().getTime();
	}
}

const header = new BlockHeader(0);
console.log(header);

interface _headerType {
	version: string;
	heigth: number;
	timestamp: number;
	previousHash: string | number;
}

class Block {
	version: string;
	heigth: number;
	timestamp: number;
	previousHash: string | number;
	hash: string;
	merkleRoot: string;
	data: string[];

	constructor(_header: _headerType, _data: string[]) {
		const merkleroot = Block.getMerkleRoot(_data);
		this.version = _header.version;
		this.heigth = _header.heigth;
		this.timestamp = _header.timestamp;
		this.previousHash = _header.previousHash;
		this.hash = Block.createBlockHash(_header, merkleroot);
		this.merkleRoot = merkleroot;
		this.data = _data;
	}

	static getMerkleRoot(_data: string[]) {
		const merkleTree = merkle('sha256').sync(_data);
		const merkleRoot = merkleTree.root();
		return merkleRoot;
	}

	static createBlockHash(_header: {}, _merkleroot: string) {
		const values = Object.values(_header);
		const data = values.join('') + _merkleroot;
		return SHA256(data).toString();
	}
}

const data = ['The Times 03/Jan/2009 Chancellor on brink of second bailout for banks'];

const block = new Block(header, data);
console.log(block);

0개의 댓글