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
는 그 블록의 고유한 값입니다.
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바이트로 암호화하여 반환해줍니다.
하지만 반환한 결과물을 가지고 원래의 입력한 값을 구할수는 없습니다.
이것을 단방향 암호화라고 합니다.
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
의 최상단에 있는 암호화된 값이 들어갑니다.
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
값을 추가할 필요는 없습니다.
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);