72 lines
1.6 KiB
Go
72 lines
1.6 KiB
Go
package consensus
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/rand"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"errors"
|
|
"fmt"
|
|
"math/big"
|
|
"time"
|
|
|
|
"dejo_node/internal/transactions"
|
|
)
|
|
|
|
// Finalizer encapsula a lógica de selar e assinar blocos.
|
|
type Finalizer struct {
|
|
PrivateKey *ecdsa.PrivateKey
|
|
NodeID string // opcional: ID do produtor do bloco
|
|
}
|
|
|
|
// Finalize executa a finalização de um bloco:
|
|
// - Adiciona timestamp
|
|
// - Gera hash final
|
|
// - Retorna assinatura
|
|
func (f *Finalizer) Finalize(block *transactions.Block) (string, error) {
|
|
if block == nil {
|
|
return "", errors.New("bloco nulo")
|
|
}
|
|
|
|
block.Timestamp = time.Now().Unix()
|
|
|
|
// Geração do hash usando campos existentes do bloco
|
|
hashInput := []byte(
|
|
fmt.Sprintf("%d|%s|%d|%s",
|
|
block.Index,
|
|
block.PrevHash,
|
|
block.Timestamp,
|
|
f.NodeID,
|
|
),
|
|
)
|
|
hash := sha256.Sum256(hashInput)
|
|
block.Hash = hex.EncodeToString(hash[:])
|
|
|
|
r, s, err := ecdsa.Sign(rand.Reader, f.PrivateKey, hash[:])
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
sig := append(r.Bytes(), s.Bytes()...)
|
|
signature := hex.EncodeToString(sig)
|
|
|
|
return signature, nil
|
|
}
|
|
|
|
// VerifySignature verifica se a assinatura é válida com a chave pública fornecida.
|
|
func VerifySignature(block *transactions.Block, signature string, pubKey *ecdsa.PublicKey) bool {
|
|
hash, err := hex.DecodeString(block.Hash)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
sig, err := hex.DecodeString(signature)
|
|
if err != nil || len(sig) < 64 {
|
|
return false
|
|
}
|
|
|
|
r := big.NewInt(0).SetBytes(sig[:len(sig)/2])
|
|
s := big.NewInt(0).SetBytes(sig[len(sig)/2:])
|
|
|
|
return ecdsa.Verify(pubKey, hash, r, s)
|
|
} |