Files
blockchain/chain/mempool.go
T

88 lines
1.5 KiB
Go

package chain
import (
"blockchain/config"
"crypto/ed25519"
"slices"
"sync"
)
type Mempool struct {
transations []*Transaction
mx sync.Mutex
}
func NewMempool() *Mempool {
return &Mempool{}
}
func (m *Mempool) Add(tx *Transaction) {
if !tx.Verify() {
return
}
m.mx.Lock()
m.transations = append(m.transations, tx)
m.mx.Unlock()
}
func (m *Mempool) Len() int {
m.mx.Lock()
defer m.mx.Unlock()
return len(m.transations)
}
func (m *Mempool) CollectBlock(miner ed25519.PublicKey) []*Transaction {
m.mx.Lock()
defer m.mx.Unlock()
txs := []*Transaction{NewCoinbaseTransaction(miner, config.Default.Chain.MiningReward)}
spent := make(map[string]struct{})
isSpent := func(s CoinSpend) bool {
_, ok := spent[s.CoinID.Key()]
return ok
}
for _, tx := range m.transations {
if slices.ContainsFunc(tx.Spends, isSpent) {
continue
}
txs = append(txs, tx)
for _, s := range tx.Spends {
spent[s.CoinID.Key()] = struct{}{}
}
}
return txs
}
func (m *Mempool) RemoveMined(block *Block) {
spent := make(map[string]struct{})
for _, tx := range block.Transactions {
if tx.IsCoinbase() {
continue
}
for _, s := range tx.Spends {
spent[s.CoinID.Key()] = struct{}{}
}
}
if len(spent) == 0 {
return
}
m.mx.Lock()
defer m.mx.Unlock()
isSpent := func(s CoinSpend) bool {
_, ok := spent[s.CoinID.Key()]
return ok
}
m.transations = slices.DeleteFunc(m.transations, func(tx *Transaction) bool {
return slices.ContainsFunc(tx.Spends, isSpent)
})
}