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);
}
public updateTransactionPool(_newBlcok: IBlock): void {
let txPool: ITransaction[] = this.getTransactionPool();
_newBlcok.data.forEach((tx: ITransaction) => {
txPool = txPool.filter((txp) => {
txp.hash !== tx.hash;
});
});
this.transactionPool = txPool;
}
chain Class에 Transaction Pool을 빈배열로 생성해주고 Transaction Pool 내용을 가져오는 메서드 getTransactionPool와 Transaction Pool에 Transaction을 추가하는 메서드 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);
const txout: ITxOut = new TxOut(_account, 50);
const transaction: Transaction = new Transaction([txin], [txout]);
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의 인자값으로 코인베이스 transaction과 Transaction Pool에 담긴 Transaction 내용들을 보내줍니다.
addBlock 메서드에서 Block을 성공적으로 생성했더라면 updateTransactionPool 메서드를 사용하여 블록을 만드는데 사용한 Transaction을 TransactionPool 배열에서 삭제해줍니다.
블록을 받았을때 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);
_receviedBlock.data.forEach((tx) => {
this.updateUTXO(tx);
});
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();
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: '블록이 하나 모자랍니다. ' };
}
this.blockchain = receivedChain;
this.blockchain.forEach((_block: IBlock) => {
this.updateTransactionPool(_block);
_block.data.forEach((_tx) => {
this.updateUTXO(_tx);
});
});
return { isError: false, value: undefined };
}
addToChain 메서드와 replaceChain메서드로 블록을 새로 추가해야할 경우에도 Transaction Pool를 수정해주어야 합니다.