Swift의 향수를 느낄 수 있는 TypeScript...ㅎㅎㅎ

덕분에 재미있게 배워나간다! 🙆🏻‍♀️


5. class

이론이 더 있었다. 그렇다.

js에서는 interface가 없어서 tsc로 변환해도 관련 내용이 없다.

그래서 interface대신 class로 구현할 수 있다.

// index.ts
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 dahyun = new Human("Dahyun", 22, "female")

const sayHi = (person: Human): string => {
  const { name, age, gender } = person;
  return `hello ${name}, you are ${age}, you are a ${gender}!`;
};

console.log(sayHi(dahyun));

export {};
// hello Dahyun, you are 22, you are a female!

그냥 딱 봐도 저렇게 할 것 같다. 근데 js가 어떻게 생겼는지 궁금하다!

아래와 같이 public변수는 보이지 않고, 생성자만 보인다.

// index.js
// 생략 ...
class Human {
    constructor(name, age, gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }
}
// 생략 ...

6. Creat a Block 🧱

블록체인아닌 블록체인을 만들어본다...!ㅎㅎㅎ

모든 변수를 public으로 선언하여 코드가 너저분하다.

각 변수에 타입을 설정하고 Block타입의 genesisBlock 인스턴스를 생성한다.

이를 이용하여 blockchain을 만들면 Block타입 외엔 추가할 수 없다.

push라던지, 그런것들 말이다!

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, "20202020202", "", "Hello", 123456);

let blockchain: Block[] = [genesisBlock];

console.log(blockchain);

export {};

// [ Block {
//     index: 0,
//     hash: '20202020202',
//     previousHash: '',
//     data: 'Hello',
//    timestamp: 123456 } ]

7. Creat a Block #2

새로운 블록을 만드려면 해쉬를 계산해야한다.

이를 도와주는 것이 CryptoJS이다. 설치하자! yarn add CryptoJS

이후 다음과 같이 작성한다.

CryptoJS.SHA256로 해쉬를 계산하여 문자열로 변환한다.

나머지 함수는 이후 사용할 것들을 미리 구현해 둔 것이다.

import * as CryptoJS from 'crypto-js';

class Block {
  public index: number;
  public hash: string;
  public previousHash: string;
  public data: string;
  public timestamp: number;

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

  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, "20202020202", "", "Hello", 123456);

let blockchain: Block[] = [genesisBlock];

const getBlockchain = (): Block[] => blockchain;

const getLatestBlock = (): Block => blockchain[blockchain.length - 1];

const getNewTimestamp = (): number => Math.round(new Date().getTime() / 1000);

export {};

8. conclusion

사실 이 이후 강의는 블록체인에 관한 강의라서 이해도 안 가고 흥미도 가지 않는다.

결론만 적고 마무리 하자!ㅎㅎㅎ

import * as CryptoJS from 'crypto-js';

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

  static validateStructure = (aBlock: Block) => 
    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, "20202020202", "", "Hello", 123456);

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;
};

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 {};

결과는 이렇다.
각 블록에 이전 해쉬값, 현재 해쉬값을 반영하고, 나머지 요소도 잘 구현되었다.

// Result
[ Block {
    index: 0,
    hash: '20202020202',
    previousHash: '',
    data: 'Hello',
    timestamp: 123456 },
  Block {
    index: 1,
    hash:
     'a2fb80672d1640976f78b7a0f982199c978138fbf9459e806fe619e7a963d257',
    previousHash: '20202020202',
    data: 'second block',
    timestamp: 1562396051 },
  Block {
    index: 2,
    hash:
     '1fa23e4041829115d2f138f427ce9eaa7875b45515bc677149f8bb0f1a635a7d',
    previousHash:
     'a2fb80672d1640976f78b7a0f982199c978138fbf9459e806fe619e7a963d257',
    data: 'third block',
    timestamp: 1562396051 },
  Block {
    index: 3,
    hash:
     '59a4847fdbfdfaabfe02d5d2356f5b7ccd786eba962701055dd83b76ae76c86e',
    previousHash:
     '1fa23e4041829115d2f138f427ce9eaa7875b45515bc677149f8bb0f1a635a7d',
    data: 'fourth block',
    timestamp: 1562396051 } ]