lbry.go/schema/stake/validator.go

121 lines
3.4 KiB
Go
Raw Normal View History

package stake
2017-09-12 18:02:30 +02:00
import (
"crypto/ecdsa"
2017-09-12 18:02:30 +02:00
"crypto/sha256"
"encoding/binary"
"encoding/hex"
2017-11-08 03:39:08 +01:00
"math/big"
2020-09-01 19:58:08 +02:00
"github.com/lbryio/lbry.go/v2/extras/errors"
2020-09-01 19:45:55 +02:00
"github.com/lbryio/lbry.go/v2/schema/address"
2017-09-12 18:02:30 +02:00
)
2017-11-08 03:39:08 +01:00
const SECP256k1 = "SECP256k1"
2018-02-15 20:51:51 +01:00
//const NIST256p = "NIST256p"
//const NIST384p = "NIST384p"
func getClaimSignatureDigest(bytes ...[]byte) [32]byte {
var combined []byte
for _, b := range bytes {
combined = append(combined, b...)
}
2017-09-12 18:02:30 +02:00
digest := sha256.Sum256(combined)
return [32]byte(digest)
}
func (c *StakeHelper) VerifyDigest(certificate *StakeHelper, signature [64]byte, digest [32]byte) bool {
if certificate == nil {
return false
2017-11-08 03:39:08 +01:00
}
R := &big.Int{}
S := &big.Int{}
R.SetBytes(signature[0:32])
S.SetBytes(signature[32:64])
pk, err := certificate.GetPublicKey()
2017-11-08 03:39:08 +01:00
if err != nil {
return false
}
return ecdsa.Verify(pk.ToECDSA(), digest[:], R, S)
}
2017-11-08 03:39:08 +01:00
func (c *StakeHelper) ValidateClaimSignature(certificate *StakeHelper, k string, certificateId string, blockchainName string) (bool, error) {
if c.LegacyClaim != nil {
return c.validateV1ClaimSignature(certificate, k, certificateId, blockchainName)
2017-11-08 03:39:08 +01:00
}
return c.validateClaimSignature(certificate, k, certificateId, blockchainName)
2017-11-08 03:39:08 +01:00
}
func (c *StakeHelper) validateClaimSignature(certificate *StakeHelper, firstInputTxHash, certificateId string, blockchainName string) (bool, error) {
certificateIdSlice, err := hex.DecodeString(certificateId)
if err != nil {
return false, errors.Err(err)
2017-11-08 03:39:08 +01:00
}
certificateIdSlice = reverseBytes(certificateIdSlice)
firstInputTxIDBytes, err := hex.DecodeString(firstInputTxHash)
if err != nil {
return false, errors.Err(err)
2017-11-08 03:39:08 +01:00
}
signature := c.Signature
if signature == nil {
return false, errors.Err("claim does not have a signature")
}
signatureBytes := [64]byte{}
for i, b := range signature {
signatureBytes[i] = b
2017-11-08 03:39:08 +01:00
}
claimDigest := getClaimSignatureDigest(firstInputTxIDBytes, certificateIdSlice, c.Payload)
2017-11-27 16:22:04 +01:00
return c.VerifyDigest(certificate, signatureBytes, claimDigest), nil
2017-09-12 18:02:30 +02:00
}
func (c *StakeHelper) validateV1ClaimSignature(certificate *StakeHelper, claimAddy string, certificateId string, blockchainName string) (bool, error) {
addressBytes, err := address.DecodeAddress(claimAddy, blockchainName)
2017-11-08 03:39:08 +01:00
if err != nil {
return false, err
}
//For V1 claim_id was incorrectly stored for claim signing.
// So the bytes are not reversed like they are supposed to be (Endianess)
2017-11-08 03:39:08 +01:00
certificateIdSlice, err := hex.DecodeString(certificateId)
if err != nil {
return false, err
}
signature := c.Signature
if signature == nil {
return false, errors.Err("claim does not have a signature")
}
signatureBytes := [64]byte{}
for i := range signatureBytes {
signatureBytes[i] = signature[i]
}
claimAddress, err := address.ValidateAddress(addressBytes, blockchainName)
if err != nil {
return false, errors.Err("invalid address")
2017-11-08 03:39:08 +01:00
}
serializedNoSig, err := c.serializedNoSignature()
if err != nil {
return false, errors.Err("serialization error")
}
claimDigest := getClaimSignatureDigest(claimAddress[:], serializedNoSig, certificateIdSlice)
return c.VerifyDigest(certificate, signatureBytes, claimDigest), nil
2017-09-12 18:02:30 +02:00
}
func GetOutpointHash(txid string, vout uint32) (string, error) {
txidBytes, err := hex.DecodeString(txid)
if err != nil {
return "", errors.Err(err)
}
var voutBytes = make([]byte, 4)
binary.LittleEndian.PutUint32(voutBytes, vout)
return hex.EncodeToString(append(reverseBytes(txidBytes), voutBytes...)), nil
}