blockchain sandbox: UTXO chain, p2p mining, attacker node

This commit is contained in:
2026-07-26 20:37:26 +03:00
commit 7ce39c8964
18 changed files with 2536 additions and 0 deletions
+87
View File
@@ -0,0 +1,87 @@
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)
})
}