-
Notifications
You must be signed in to change notification settings - Fork 460
/
singer.go
154 lines (138 loc) · 3.95 KB
/
singer.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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package testhelpers
import (
"bytes"
"context"
"crypto/rand"
"errors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/venus/pkg/crypto"
"github.com/filecoin-project/venus/pkg/wallet/key"
)
// MockSigner implements the Signer interface
type MockSigner struct {
AddrKeyInfo map[address.Address]key.KeyInfo
Addresses []address.Address
PubKeys [][]byte
}
// NewMockSigner returns a new mock signer, capable of signing data with
// keys (addresses derived from) in keyinfo
func NewMockSigner(kis []key.KeyInfo) MockSigner {
var ms MockSigner
ms.AddrKeyInfo = make(map[address.Address]key.KeyInfo)
for _, k := range kis {
// extract public key
pub, err := k.PublicKey()
if err != nil {
panic(err)
}
var newAddr address.Address
if k.SigType == crypto.SigTypeSecp256k1 {
newAddr, err = address.NewSecp256k1Address(pub)
} else if k.SigType == crypto.SigTypeBLS {
newAddr, err = address.NewBLSAddress(pub)
}
if err != nil {
panic(err)
}
ms.Addresses = append(ms.Addresses, newAddr)
ms.AddrKeyInfo[newAddr] = k
ms.PubKeys = append(ms.PubKeys, pub)
}
return ms
}
// NewMockSignersAndKeyInfo is a convenience function to generate a mock
// signers with some keys.
func NewMockSignersAndKeyInfo(numSigners int) (MockSigner, []key.KeyInfo) {
ki := MustGenerateKeyInfo(numSigners, 42)
signer := NewMockSigner(ki)
return signer, ki
}
// MustGenerateMixedKeyInfo produces m bls keys and n secp keys.
// BLS and Secp will be interleaved. The keys will be valid, but not deterministic.
func MustGenerateMixedKeyInfo(m int, n int) []key.KeyInfo {
info := []key.KeyInfo{}
for m > 0 && n > 0 {
if m > 0 {
ki, err := key.NewBLSKeyFromSeed(rand.Reader)
if err != nil {
panic(err)
}
info = append(info, ki)
m--
}
if n > 0 {
ki, err := key.NewSecpKeyFromSeed(rand.Reader)
if err != nil {
panic(err)
}
info = append(info, ki)
n--
}
}
return info
}
// MustGenerateBLSKeyInfo produces n distinct BLS keyinfos.
func MustGenerateBLSKeyInfo(n int, seed byte) []key.KeyInfo {
token := bytes.Repeat([]byte{seed}, 512)
var keyinfos []key.KeyInfo
for i := 0; i < n; i++ {
token[0] = byte(i)
ki, err := key.NewBLSKeyFromSeed(bytes.NewReader(token))
if err != nil {
panic(err)
}
keyinfos = append(keyinfos, ki)
}
return keyinfos
}
// MustGenerateKeyInfo generates `n` distinct keyinfos using seed `seed`.
// The result is deterministic (for stable tests), don't use this for real keys!
func MustGenerateKeyInfo(n int, seed byte) []key.KeyInfo {
token := bytes.Repeat([]byte{seed}, 512)
var keyinfos []key.KeyInfo
for i := 0; i < n; i++ {
token[0] = byte(i)
ki, err := key.NewSecpKeyFromSeed(bytes.NewReader(token))
if err != nil {
panic(err)
}
keyinfos = append(keyinfos, ki)
}
return keyinfos
}
// SignBytes cryptographically signs `data` using the `addr`.
func (ms MockSigner) SignBytes(_ context.Context, data []byte, addr address.Address) (*crypto.Signature, error) {
ki, ok := ms.AddrKeyInfo[addr]
if !ok {
return nil, errors.New("unknown address")
}
var sig *crypto.Signature
err := ki.UsePrivateKey(func(privateKey []byte) error {
var err error
sig, err = crypto.Sign(data, privateKey, ki.SigType)
return err
})
return sig, err
}
// HasAddress returns whether the signer can sign with this address
func (ms MockSigner) HasAddress(_ context.Context, addr address.Address) (bool, error) {
return true, nil
}
// GetAddressForPubKey looks up a KeyInfo address associated with a given PublicKeyForSecpSecretKey for a MockSigner
func (ms MockSigner) GetAddressForPubKey(pk []byte) (address.Address, error) {
var addr address.Address
for _, ki := range ms.AddrKeyInfo {
testPk, err := ki.PublicKey()
if err != nil {
return address.Undef, err
}
if bytes.Equal(testPk, pk) {
addr, err := ki.Address()
if err != nil {
return addr, errors.New("could not fetch address")
}
return addr, nil
}
}
return addr, errors.New("public key not found in wallet")
}