88 lines
1.5 KiB
Go
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)
|
|
})
|
|
}
|