-
Notifications
You must be signed in to change notification settings - Fork 0
/
ethmultisig.go
145 lines (131 loc) · 5.24 KB
/
ethmultisig.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
package ethmultisig
import (
"crypto/ecdsa"
"fmt"
"time"
"github.com/cosmos/cosmos-sdk/codec"
clienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types"
conntypes "github.com/cosmos/ibc-go/modules/core/03-connection/types"
chantypes "github.com/cosmos/ibc-go/modules/core/04-channel/types"
"github.com/cosmos/ibc-go/modules/core/exported"
ibcexported "github.com/cosmos/ibc-go/modules/core/exported"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
gethcrypto "github.com/ethereum/go-ethereum/crypto"
ethmultisigtypes "github.com/datachainlab/ibc-proxy-solidity/modules/light-clients/xx-ethmultisig/types"
)
type ETHMultisig struct {
cdc codec.ProtoCodecMarshaler
diversifier string
keys []*ecdsa.PrivateKey
prefix []byte
}
func NewETHMultisig(cdc codec.ProtoCodecMarshaler, diversifier string, keys []*ecdsa.PrivateKey, prefix []byte) ETHMultisig {
return ETHMultisig{cdc: cdc, diversifier: diversifier, keys: keys, prefix: prefix}
}
func (m ETHMultisig) Addresses() []common.Address {
var addresses []common.Address
for _, key := range m.keys {
addr := crypto.PubkeyToAddress(key.PublicKey)
addresses = append(addresses, addr)
}
return addresses
}
// GetCurrentTimestamp returns current time
func (m ETHMultisig) GetCurrentTimestamp() uint64 {
return uint64(time.Now().UnixNano())
}
func (m ETHMultisig) SignConsensusState(height clienttypes.Height, clientID string, dstClientConsHeight ibcexported.Height, consensusState exported.ConsensusState) (*ethmultisigtypes.MultiSignature, []byte, error) {
bz, err := m.cdc.MarshalInterface(consensusState)
if err != nil {
return nil, nil, err
}
path, err := ethmultisigtypes.ConsensusCommitmentKey(m.prefix, clientID, dstClientConsHeight.GetRevisionHeight())
if err != nil {
return nil, nil, err
}
return m.SignState(ethmultisigtypes.Height(height), ethmultisigtypes.CONSENSUS, path, bz)
}
func (m ETHMultisig) SignClientState(height clienttypes.Height, clientID string, clientState exported.ClientState) (*ethmultisigtypes.MultiSignature, []byte, error) {
bz, err := m.cdc.MarshalInterface(clientState)
if err != nil {
return nil, nil, err
}
path, err := ethmultisigtypes.ClientCommitmentKey(m.prefix, clientID)
if err != nil {
return nil, nil, err
}
return m.SignState(ethmultisigtypes.Height(height), ethmultisigtypes.CLIENT, path, bz)
}
func (m ETHMultisig) SignConnectionState(height clienttypes.Height, connectionID string, connection conntypes.ConnectionEnd) (*ethmultisigtypes.MultiSignature, []byte, error) {
bz, err := m.cdc.Marshal(&connection)
if err != nil {
return nil, nil, err
}
path, err := ethmultisigtypes.ConnectionCommitmentKey(m.prefix, connectionID)
if err != nil {
return nil, nil, err
}
return m.SignState(ethmultisigtypes.Height(height), ethmultisigtypes.CONNECTION, path, bz)
}
func (m ETHMultisig) SignChannelState(height clienttypes.Height, portID, channelID string, channel chantypes.Channel) (*ethmultisigtypes.MultiSignature, []byte, error) {
bz, err := m.cdc.Marshal(&channel)
if err != nil {
return nil, nil, err
}
path, err := ethmultisigtypes.ChannelCommitmentKey(m.prefix, portID, channelID)
if err != nil {
return nil, nil, err
}
return m.SignState(ethmultisigtypes.Height(height), ethmultisigtypes.CHANNEL, path, bz)
}
func (m ETHMultisig) SignPacketState(height clienttypes.Height, portID, channelID string, sequence uint64, packetCommitment []byte) (*ethmultisigtypes.MultiSignature, []byte, error) {
if len(packetCommitment) != 32 {
return nil, nil, fmt.Errorf("packetCommitment length must be 32")
}
path, err := ethmultisigtypes.PacketCommitmentKey(m.prefix, portID, channelID, sequence)
if err != nil {
return nil, nil, err
}
return m.SignState(ethmultisigtypes.Height(height), ethmultisigtypes.PACKETCOMMITMENT, path, packetCommitment)
}
func (m ETHMultisig) SignPacketAcknowledgementState(height clienttypes.Height, portID, channelID string, sequence uint64, acknowledgementCommitment []byte) (*ethmultisigtypes.MultiSignature, []byte, error) {
if len(acknowledgementCommitment) != 32 {
return nil, nil, fmt.Errorf("acknowledgementCommitment length must be 32")
}
path, err := ethmultisigtypes.PacketAcknowledgementCommitmentKey(m.prefix, portID, channelID, sequence)
if err != nil {
return nil, nil, err
}
return m.SignState(ethmultisigtypes.Height(height), ethmultisigtypes.PACKETACKNOWLEDGEMENT, path, acknowledgementCommitment)
}
func (m ETHMultisig) SignState(height ethmultisigtypes.Height, dtp ethmultisigtypes.SignBytes_DataType, path, value []byte) (*ethmultisigtypes.MultiSignature, []byte, error) {
data, err := m.cdc.Marshal(ðmultisigtypes.StateData{
Path: path,
Value: value,
})
if err != nil {
return nil, nil, err
}
ts := m.GetCurrentTimestamp()
signBytes, err := m.cdc.Marshal(ðmultisigtypes.SignBytes{
Height: height,
Timestamp: ts,
Diversifier: m.diversifier,
DataType: dtp,
Data: data,
})
if err != nil {
return nil, nil, err
}
signHash := gethcrypto.Keccak256(signBytes)
proof := ethmultisigtypes.MultiSignature{Timestamp: ts}
for _, key := range m.keys {
sig, err := gethcrypto.Sign(signHash, key)
if err != nil {
return nil, nil, err
}
proof.Signatures = append(proof.Signatures, sig)
}
return &proof, signBytes, nil
}