package miner import ( "dejo_node/internal/consensus" "dejo_node/internal/storage" "dejo_node/internal/transactions" "dejo_node/internal/ws" "fmt" "time" ) // Miner representa o componente responsável por propor blocos válidos. type Miner struct { Engine consensus.Engine BlockStore *storage.BlockStore Mempool *transactions.Mempool } // New cria uma nova instância de minerador func New(engine consensus.Engine, store *storage.BlockStore, mempool *transactions.Mempool) *Miner { return &Miner{ Engine: engine, BlockStore: store, Mempool: mempool, } } // MineNextBlock propõe, valida e armazena um novo bloco se possível func (m *Miner) MineNextBlock() (*transactions.Block, error) { if !m.Engine.CanPropose() { return nil, fmt.Errorf("este nó não tem permissão para propor blocos") } txns := m.Mempool.Pending() if len(txns) == 0 { return nil, fmt.Errorf("nenhuma transação pendente para minerar") } lastBlock, err := m.BlockStore.GetLatestBlock() index := uint64(0) prevHash := "" if err == nil { index = lastBlock.Index + 1 prevHash = lastBlock.Hash } blk := &transactions.Block{ Index: index, Timestamp: time.Now().Unix(), PrevHash: prevHash, Txns: txns, } blk.ComputeHash() if err := m.Engine.Finalize(blk); err != nil { return nil, fmt.Errorf("bloco rejeitado pelo consenso: %w", err) } if err := m.BlockStore.SaveBlock(blk); err != nil { return nil, fmt.Errorf("erro ao salvar bloco: %w", err) } // Emitir eventos WebSocket ws.Emit("newBlock", map[string]any{ "index": blk.Index, "hash": blk.Hash, }) for _, tx := range blk.Txns { ws.Emit("txConfirmed", map[string]any{ "hash": tx.Hash(), }) } m.Mempool.Clear() return blk, nil }