commit inicial do projeto
This commit is contained in:
63
internal/transactions/validation.go
Normal file
63
internal/transactions/validation.go
Normal file
@ -0,0 +1,63 @@
|
||||
package transactions
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// IsValid realiza validações na transação: assinatura, saldo e nonce.
|
||||
func (tx *Transaction) IsValid(pubKey *ecdsa.PublicKey, balance float64, currentNonce uint64) error {
|
||||
if tx.IsZero() {
|
||||
return errors.New("transação malformada: campos obrigatórios ausentes")
|
||||
}
|
||||
|
||||
if tx.Value+float64(tx.Gas) > balance {
|
||||
return fmt.Errorf("saldo insuficiente: necessário %.2f, disponível %.2f", tx.Value+float64(tx.Gas), balance)
|
||||
}
|
||||
|
||||
if tx.Nonce != currentNonce {
|
||||
return fmt.Errorf("nonce inválido: esperado %d, recebido %d", currentNonce, tx.Nonce)
|
||||
}
|
||||
|
||||
r, s, err := parseSignature(tx.Signature)
|
||||
if err != nil {
|
||||
return fmt.Errorf("erro ao parsear assinatura: %v", err)
|
||||
}
|
||||
|
||||
hash := sha256.Sum256([]byte(fmt.Sprintf("%s:%s:%f:%d:%d",
|
||||
tx.From, tx.To, tx.Value, tx.Nonce, tx.Gas)))
|
||||
|
||||
if !ecdsa.Verify(pubKey, hash[:], r, s) {
|
||||
return errors.New("assinatura inválida")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseSignature converte a assinatura hex (formato r||s) em *big.Int.
|
||||
func parseSignature(sig string) (*big.Int, *big.Int, error) {
|
||||
bytes, err := hex.DecodeString(sig)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if len(bytes) != 64 {
|
||||
return nil, nil, errors.New("assinatura deve ter 64 bytes (r||s)")
|
||||
}
|
||||
r := new(big.Int).SetBytes(bytes[:32])
|
||||
s := new(big.Int).SetBytes(bytes[32:])
|
||||
return r, s, nil
|
||||
}
|
||||
|
||||
// GenerateSignature é uma função auxiliar (para testes): assina tx com chave privada.
|
||||
func (tx *Transaction) GenerateSignature(priv *ecdsa.PrivateKey) string {
|
||||
hash := sha256.Sum256([]byte(fmt.Sprintf("%s:%s:%f:%d:%d",
|
||||
tx.From, tx.To, tx.Value, tx.Nonce, tx.Gas)))
|
||||
|
||||
r, s, _ := ecdsa.Sign(rand.Reader, priv, hash[:])
|
||||
return fmt.Sprintf("%064x%064x", r, s)
|
||||
}
|
||||
Reference in New Issue
Block a user