๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
WEB/Front-End๐ŸŒ

[Typescript] ๋ธ”๋ก์ฒด์ธ ๋งŒ๋“ค๊ธฐ - predictable ํ•จ์ˆ˜๋ฆฌํ„ด, ํ•จ์ˆ˜์ธ์ž

by narang111 2021. 12. 12.

js์—์„œ๋„ ์ธํ„ฐํŽ˜์ด์Šค์™€ ๋น„์Šทํ•œ class๋ผ๋Š”๊ฒŒ ์žˆ๋‹ค.

 

class Human {
    public name: string;
    public age: number;
    public gender: string;
    // ์ƒ์„ฑ์ž- ํด๋ž˜์Šค๊ฐ€ ์‹œ์ž‘ํ•  ๋•Œ๋งˆ๋‹ค ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์„œ๋“œ
    // ?๋Š” ์„ ํƒ์‚ฌํ•ญ
    constructor(name: string, age: number, gender?: string){
        this.name = name;
        this.age = age;
        this.gender = gender;
    }
}

const rin = new Human("Rin", 23, "female");

const greeting = (person: Human): string=>{
    return `Hello ${person.name} ${person.age} ${person.gender}`;
}

console.log(greeting(rin));

export {};

 

 

์•ž์„œ ๋“ค์—ˆ๋˜ ๊ฐ•์˜๋‚ด์šฉ์œผ๋กœ ๋ธ”๋ก์„ ํ•˜๋‚˜ ๋งŒ๋“ค์—ˆ๋‹ค.

class Block{
    public index: number;
    public hash: string;
    public previousHash: string;
    public data: string;
    public timestamp: number;
    constructor(
        index: number,
        hash: string,
        previousHash: string,
        data: string,
        timestamp: number
    ){
        this.index = index;
        this.hash = hash;
        this.previousHash = previousHash;
        this.data = data;
        this.timestamp = timestamp;
    }
}

const genesisBlock: Block = new Block(0, "110101101011010", "", "Hello", 12345);

// ts๊ฐ€ ๋ธ”๋ก(object)๋งŒ ๋ธ”๋ก์ฒด์ธ์— ์ถ”๊ฐ€ํ•˜๋„๋ก ์ฒดํฌ
let blockchain: [Block] = [genesisBlock];
console.log(blockchain);

export {};

 

 

์ƒˆ ๋ธ”๋ก์„ ๋งŒ๋“ค์–ด๋ณผ ์ฐจ๋ก€์ด๋‹ค.

์ƒˆ๋กœ์šด ๋ธ”๋Ÿญ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ•ด์‰ฌ๋ฅผ ๊ณ„์‚ฐํ•ด์•ผํ•œ๋‹ค.

 

class์•ˆ์—์„œ ์ผ๋ฐ˜์ ์œผ๋กœ sayHello=>... ์ด๋ ‡๊ฒŒ ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค๋ฉด ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•  ๋•Œ ๋ธ”๋Ÿญ์„ ๋จผ์ € ๋งŒ๋“ค๊ณ ๋‚˜์„œ์•ผ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋”ฐ.

๋ธ”๋ก์„ ์ƒ์„ฑํ•˜์ง€ ์•Š์•„๋„ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•œ method๋ฅผ ๋งŒ๋“ค๊ณ ์‹ถ๋‹ค.

Block ํด๋ž˜์Šค ์•ˆ์— static์œผ๋กœ ๋งŒ๋“ค์–ด์คฌ๋‹ค.

static calculateBlockHash = (
    index: number,
    previousHash: string, 
    timestamp: number, 
    data: string
  ): string => 
  CryptoJS.SHA256(index + previousHash + timestamp + data).toString();

 

 

๐Ÿ”ฝ index.ts ์™„์„ฑ์ฝ”๋“œ

import * as CryptoJS from "crypto-js"
import { createTypeOf, NumberLiteralType } from "typescript";

class Block {

    static calculateBlockHash = (
            index: number,
            previousHash: string, 
            timestamp: number, 
            data: string
        ): string => 
        CryptoJS.SHA256(index + previousHash + timestamp + data).toString();
    
    // ๊ตฌ์กฐ๊ฐ€ ์œ ํšจํ•œ์ง€
    static validateStructure = (aBlock: Block): boolean =>
        typeof aBlock.index === "number" &&
        typeof aBlock.hash === "string" &&
        typeof aBlock.previousHash === "string" &&
        typeof aBlock.timestamp === "number" &&
        typeof aBlock.data === "string";

    public index: number;
    public hash: string;
    public previousHash: string;
    public data: string;
    public timestamp: number;

    constructor(
        index: number,
        hash: string,
        previousHash: string,
        data: string,
        timestamp: number
    ) {
        this.index = index;
        this.hash = hash;
        this.previousHash = previousHash;
        this.data = data;
        this.timestamp = timestamp;
    }
}


const genesisBlock: Block = new Block(0, "110101101011010", "", "Hello", 12345);

// ts๊ฐ€ ๋ธ”๋ก(object)๋งŒ ๋ธ”๋ก์ฒด์ธ์— ์ถ”๊ฐ€ํ•˜๋„๋ก ์ฒดํฌ
let blockchain: Block[] = [genesisBlock];
const getBlockchain = (): Block[] => blockchain;
const getLatestBlock = (): Block => blockchain[blockchain.length - 1];
const getNewTimeStamp = (): number => Math.round(new Date().getTime() / 1000);
const createNewBlock = (data: string): Block => {
  const previousBlock: Block = getLatestBlock();
  const newIndex: number = previousBlock.index + 1;
  const newTimestamp: number = getNewTimeStamp();
  const newHash: string = Block.calculateBlockHash(
    newIndex,
    previousBlock.hash,
    newTimestamp,
    data
  );
  const newBlock: Block = new Block(
    newIndex,
    newHash,
    previousBlock.hash,
    data,
    newTimestamp
  );
  addBlock(newBlock);
  return newBlock;
};

// console.log(createNewBlock("hello"), createNewBlock("byebye"));

const getHashforBlock = (aBlock: Block): string =>
  Block.calculateBlockHash(
    aBlock.index,
    aBlock.previousHash,
    aBlock.timestamp,
    aBlock.data
  );

// ๊ตฌ์กฐ๊ฐ€ ์œ ํšจํ•œ์ง€ ํ™•์ธ
// ๋ธ”๋ก์ฒด์ธ์˜ ๊ธฐ๋ฐ˜์€ ๋ธ”๋ก๋“ค์ด ์ž์‹ ์˜ ์ „ ๋ธ”๋ก์œผ๋กœ์˜ ๋งํฌ๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ.
const isBlockValid = (candidateBlock: Block, previousBlock: Block): boolean => {
    if (!Block.validateStructure(candidateBlock)) {
      return false;
    } else if (previousBlock.index + 1 !== candidateBlock.index) {
      return false;
    } else if (previousBlock.hash !== candidateBlock.previousHash) {
      return false;
    } else if (getHashforBlock(candidateBlock) !== candidateBlock.hash) {
      return false;
    } else {
      return true;
    }
  };
  const addBlock = (candidateBlock: Block): void => {
    if (isBlockValid(candidateBlock, getLatestBlock())) {
      blockchain.push(candidateBlock);
    }
  };


// ๋ธ”๋ก์ฒด์ธ์— ๋ธ”๋ก ์ถ”๊ฐ€
createNewBlock("second block");
createNewBlock("third block");
createNewBlock("fourth block");

console.log(blockchain);

export {};