tx 객체가 생성되면 이 객체는 바로 블록에 기록되는 것이 아니라 다음 블록이 생성될 때까지 기다려야 한다.
이런 tx들을 임시로 저장하는 곳을 txpool이라고 하는데 이 또한 Chain class 내에 저장하고 사용할 수 있다.
우선 chain class 안에 transactionPool 속성과 간단한 기능을 가진 tx pool 관련 함수를 추가해주자.
1. tx pool 속성 추가
/* src/core/blockchain/chain.ts */
// ...중략
export class Chain {
public blockchain : Block[]
private unspentTxOuts : unspentTxOut[]
private transactionPool : ITransaction[]
constructor() {
this.blockchain = [Block.getGenesis()]
this.unspentTxOuts = []
this.transactionPool = []
}
public getTransactionPool() : ITransaction[] {
return this.transactionPool
}
// 현재 체인의 tx pool 리턴
public appendTransactionPool( _Transaction: ITransaction) : void {
this.transactionPool.push(_Transaction)
}
// tx를 tx pool에 추가
}
2. tx pool update
다시 한 번 채굴자 시점에서 생각해보자.
블럭을 추가 할 때, txPool에 있던 tx들을 새 블럭의 data로 넘겨줘야 한다.
이를 위해서는 miningBlock 함수에서 리턴으로 addBlock함수를 실행할 때 tx pool에 있던 데이터들을 같이 넘겨주면 된다.
(원래 있던 transaction은 채굴 보상을 의미)
/* src/core/blockchain/chain.ts */
// ...중략
public miningBlock ( _account : string ) {
// ...중략
return this.addBlock(([transaction, ...this.getTransactionPool()])
}
이렇게 새로운 블럭을 생성되었다면 txpool에선 넘겨준 tx 데이터들을 다음 블럭이 생성되기 전에 제거해야 한다.
updateTransactionPool 함수를 작성해 이 기능을 넣어준다.
/* src/core/blockchain/chain.ts */
// ...중략
public updateTransactionPool ( _newBlock : Block ) : void {
let txPool : ITransaction[] = this.getTransactionPool()
// 현재 tx Pool에 있는 tx들을 가져온다
_newBlock.data.forEach((tx : ITransaction) => {
txPool = txPool.filter((txp) => {
txp.hash !== tx.hash
// 새롭게 생성된 블록의 tx들을 tx pool과 비교해
// 동일한 tx를 제거한다. (hash값이 같다면 동일한 tx라는걸 이용)
})
})
this.transactionPool = txPool
// 걸러진 tx들로 transactionPool을 업데이트한다
}
채굴자의 경우, addBlock 함수에서 이 updateTransactionPool을 호출한다.
/* src/core/blockchain/chain.ts */
public addBlock (data : ITransaction[]) : Failable < Block, string> {
// ...중략
newBlock.data.forEach((_tx : ITransaction) => {
this.updateUTXO(_tx)
})
this.updateTransactionPool(newBlock)
// utxo 업데이트 후 tx pool을 업데이트
return { isError : false, value : newBlock }
}
3. tx pool 업데이트 내용 전파
이 후 과정은 #15에서 utxo를 업데이트 해주는 것과 크게 다를 것이 없다.
다른 사람의 정보를 받아 내 체인을 최신화 할 때는 경우에 따라 addToChain, replaceChain 함수에서
updateTransactionPool 함수를 호출하면 된다.
/* src/core/blockchain/chain.ts */
public addToChain ( _receivedBlock : Block ) ; Failable < undefined, string > {
// ...중략
this.updateTransactionPool(_receivedBlock)
// utxo 업데이트 후 tx pool 최신화
return { isError : false, value : undefined }
}
public replaceChain ( _receivedChain : Block[] ) : Failable < undefined, string > {
// ...중략
this.blockchain = _receivedChain
this.blockchain.forEach((_block : IBlock) => {
this.updateTransactionPool(_block) // txpool update 코드 추가
_block.data.forEach((_tx) => {
this.updateUTXO(_tx)
})
})
return { isError : false, value : undefined }
}
이를 다른 피어들과 주고 받으려면 P2PServer class에서 txpool 업데이트를 지시할 코드를 추가하고
index.ts의 sendTransaction 라우터에서 broadcast 함수를 실행하면 된다.
/* src/core/p2p.ts */
// ...중략
export enum MessageType {
// ...중략
receivedTx = 3
}
export class P2PServer extends Chain {
// ...중략
public messageHandler(socket : WebSocket) {
// ...중략
case MessageType.receivedTx : {
// 수신인 기준으로 생각한다
const receivedChain : ITransaction = result.payload
// 만들어진 tx에 대한 정보를 받는다
if ( receivedChain : ITransaction === null ) break
const withTransaction = this.getTransactionPool().find((_tx:ITransaction) => {
return _tx.hash == receivedTransaction.hash
})
// 내 txpool을 뒤져서 방금 받은 tx와 일치하는 tx가 txpool에 있는지 확인
if ( !withTransaction ) {
this.appendTransactionPool(receivedTransaction)
}
// 없다면 내 tx pool에 추가
const message : Message = {
type : MessageType.receivedTx,
payload : receivedTransaction
}
this.broadcast(message)
// 전달받은 tx 정보를 나와 연결된 다른 노드들에게 broadcast
break
}
}
}
/* index.tx */
app.post('/sendTransaction', (req, res) => {
try {
const receivedTx : ReceivedTx = req.body
const tx = Wallet.sendTransaction(receivedTx, ws.getUnspentTxOuts())
ws.appendTransaction(tx)
// 라우터에서는 응답을 주는 입장이므로 발신인 입장에서 생각한다
const message : Message = {
type : MessageType.receivedTx,
payload : tx
}
ws.broadcast(message)
}
catch (e) {
if( e instanceof Error ) console.error(e.message)
}
res.json([])
})
여기까지하면 tx에 관한 내용도 어느 정도 구현이 끝났다.
'Blockchain' 카테고리의 다른 글
#18 metamask 활용 (0) | 2022.06.29 |
---|---|
#17 ethereum (0) | 2022.06.29 |
#15 transaction ch.5 - utxo update (0) | 2022.06.27 |
#14 transaction ch4. - transaction (0) | 2022.06.24 |
#13 tx ch3. 채굴자 보상 (0) | 2022.06.23 |