블록체인 Block-Chain - 비트코인 Transaction Pool 생성하기

dev_swan·2022년 6월 25일
0

블록체인

목록 보기
11/36
post-thumbnail

Transaction Pool 생성

export class Chain {
    private blockchain: Block[];
    private unspentTxOuts: unspentTxOut[];
    private transactionPool: ITransaction[];

    constructor() {
        this.blockchain = [Block.getGenesis()];
        this.unspentTxOuts = [];
        this.transactionPool = [];
    }

-- 생략 --

public getTransactionPool(): ITransaction[] {
        return this.transactionPool;
    }

    public appendTransactionPoll(_Transaction: ITransaction): void {
        this.transactionPool.push(_Transaction);
    }

    // TransactionPool 내용 수정
    public updateTransactionPool(_newBlcok: IBlock): void {
        let txPool: ITransaction[] = this.getTransactionPool();

        // 새로 만든 블록의 Transaction들을 모두 반복문을 돌려서
        // txPool에 있는 Transaction의 hash와 새로 만든 블록의 Transaction의 hash가 일치하지 않는것들만
        // 새로운 TransactionPool에 담아줍니다.
        _newBlcok.data.forEach((tx: ITransaction) => {
            txPool = txPool.filter((txp) => {
                txp.hash !== tx.hash;
            });
        });

        this.transactionPool = txPool;
    }

chain ClassTransaction Pool을 빈배열로 생성해주고 Transaction Pool 내용을 가져오는 메서드 getTransactionPoolTransaction PoolTransaction을 추가하는 메서드 appendTransactionPoll를 만들어주었습니다.
블록을 생성할때 Transaction Pool 내용에 있는 Transaction들을 data로 넣어줄때 data에 넣은 Transaction들은 삭제해주어야 하니 updateTransactionPool 메서드를 만들어서 TrnasactionPool의 내용과 새로운 블록의 Transaction내용을 비교하여 일치하는 것들은 사용한값이니 일치하지 않은 값들을 TransactionPool에 담아줍니다.

블록을 생성할때 Transaction Pool 내용 넣기 및 Transacion Pool 업데이트

public miningBlock(_account: string): Failable<Block, string> {
        const txin: ITxIn = new TxIn('', this.getLastestBlock().height + 1); // 해시값이 겹치지 않도록 this.getLastestBlock().height + 1를 넣어주었다.
        const txout: ITxOut = new TxOut(_account, 50); // 지갑주소와 블록을 생성했을때 받는 금액으로 OutPut내용을 만든다.
        const transaction: Transaction = new Transaction([txin], [txout]); // input 배열의 내용들과 output 배열의 내용들로 Transaction을 만든다.

        // const utxo = transaction.createUTXO(); // unspentTxOut 객체 생성
        // this.appendUTXO(utxo); // UTXO 리스트에 unspentTxOut 객체를 넣어줌

        return this.addBlcok([transaction, ...this.getTransactionPool()]);
    }

    // 블록을 추가할 때 실행할 함수
    public addBlcok(data: ITransaction[]): Failable<Block, string> {
        const previousBlock = this.getLastestBlock();
        const adjustmentBlock: Block = this.getAdjustmentBlock();
        const newBlock = Block.generateBlock(previousBlock, data, adjustmentBlock);
        const isVaild = Block.isValidNewBlock(newBlock, previousBlock);

        if (isVaild.isError) return { isError: true, error: isVaild.error };
        this.blockchain.push(newBlock);

        newBlock.data.forEach((_tx: ITransaction) => {
            this.updateUTXO(_tx);
        });

        // 사용한 트랜잭션을 트랜잭션풀에서 제거해주어야 합니다.
        this.updateTransactionPool(newBlock);
        return { isError: false, value: newBlock };
    }

mining Block에서 블록을 생성하려고 할때 addBlock의 인자값으로 코인베이스 transactionTransaction Pool에 담긴 Transaction 내용들을 보내줍니다.
addBlock 메서드에서 Block을 성공적으로 생성했더라면 updateTransactionPool 메서드를 사용하여 블록을 만드는데 사용한 TransactionTransactionPool 배열에서 삭제해줍니다.

블록을 받았을때 Transaction Poll 업데이트

// 블록을 검증하여 에러가 없을시 내 블록체인에 받은 블록을 추가하는 코드
    public addToChain(_receviedBlock: Block): Failable<undefined, string> {
        const isValid = Block.isValidNewBlock(_receviedBlock, this.getLastestBlock());
        if (isValid.isError) return { isError: true, error: isValid.error };
        this.blockchain.push(_receviedBlock);

        // UTXO 업데이트
        _receviedBlock.data.forEach((tx) => {
            this.updateUTXO(tx);
        });

        // TransactionPool 업데이트
        this.updateTransactionPool(_receviedBlock);

        return { isError: false, value: undefined };
    }
    
 -- 중략 --

// 서로의 블록체인을 비교하여 블록체인을 바꿔줄 함수
    replaceChain(receivedChain: Block[]): Failable<undefined, string> {
        const latestReceivedBlock: Block = receivedChain[receivedChain.length - 1];
        const latestBlock: Block = this.getLastestBlock();

        // 1. 받은 체인의 최신블록.heigth <= 내 체인 최신블록.height = return
        // 2. 받은 체인의 최신블록.previousHash === 내 체인 최신블록.hash = reuturn
        // 3. 받은 체인의 길이가 === 1 ( 제네시스 블록밖에 없음 ) reuturn

        if (latestReceivedBlock.height === 0) {
            return { isError: true, error: '받은 최신블록이 제네시스 블록입니다. ' };
        }

        if (latestReceivedBlock.height <= latestBlock.height) {
            return { isError: true, error: '자신의 체인이 더 길거나 같습니다. ' };
        }

        if (latestReceivedBlock.previousHash === latestBlock.hash) {
            return { isError: true, error: '블록이 하나 모자랍니다. ' };
        }

        // 4. 내 체인이 더 짧으면 받은 블록체인으로 변경
        this.blockchain = receivedChain;

        // TransactionPool 수정 UTXO 수정
        this.blockchain.forEach((_block: IBlock) => {
            // Transaction Pool 업데이트
            this.updateTransactionPool(_block);
            // UTXO 업데이트
            _block.data.forEach((_tx) => {
                this.updateUTXO(_tx);
            });
        });

        return { isError: false, value: undefined };
    }

addToChain 메서드와 replaceChain메서드로 블록을 새로 추가해야할 경우에도 Transaction Pool를 수정해주어야 합니다.

0개의 댓글