/
signature.go
81 lines (70 loc) · 1.8 KB
/
signature.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package tecdsa
import (
"encoding/hex"
"fmt"
"math/big"
"github.com/bnb-chain/tss-lib/common"
)
// Signature holds a signature in a form of two big.Int `r` and `s` values and
// a recovery ID value in {0, 1, 2, 3}.
//
// The signature is chain-agnostic. Some chains (e.g. Ethereum and BTC)
// require `v` to start from 27. Please consult the documentation about
// what the particular chain expects.
type Signature struct {
R *big.Int
S *big.Int
RecoveryID int8
}
// NewSignature constructs a new instance of the tECDSA signature based on
// the signing result.
func NewSignature(data *common.SignatureData) *Signature {
// `SignatureData` contains recovery ID as a byte slice. Only the first
// byte is relevant and is converted to `int`.
recoveryBytes := data.GetSignatureRecovery()
recoveryInt := 0
recoveryInt = (recoveryInt << 8) | int(recoveryBytes[0])
return &Signature{
R: new(big.Int).SetBytes(data.GetR()),
S: new(big.Int).SetBytes(data.GetS()),
RecoveryID: int8(recoveryInt),
}
}
// String formats Signature to a string that contains R and S values
// as hexadecimals.
func (s *Signature) String() string {
return fmt.Sprintf(
"R: 0x%s, S: 0x%s, RecoveryID: %d",
hex.EncodeToString(s.R.Bytes()),
hex.EncodeToString(s.S.Bytes()),
s.RecoveryID,
)
}
// Equals determines the equality of two signatures.
func (s *Signature) Equals(other *Signature) bool {
if s == nil || other == nil {
return s == other
}
if s.R == nil || other.R == nil {
if s.R != other.R {
return false
}
} else {
if s.R.Cmp(other.R) != 0 {
return false
}
}
if s.S == nil || other.S == nil {
if s.S != other.S {
return false
}
} else {
if s.S.Cmp(other.S) != 0 {
return false
}
}
if s.RecoveryID != other.RecoveryID {
return false
}
return true
}