This repository has been archived by the owner on Dec 5, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
data_verification_event.go
182 lines (144 loc) · 5.5 KB
/
data_verification_event.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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
package datadeal
import (
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"strconv"
"github.com/btcsuite/btcd/btcec"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
datadealtypes "github.com/medibloc/panacea-core/v2/x/datadeal/types"
oracletypes "github.com/medibloc/panacea-core/v2/x/oracle/types"
"github.com/medibloc/panacea-doracle/crypto"
"github.com/medibloc/panacea-doracle/event"
"github.com/medibloc/panacea-doracle/panacea"
"github.com/medibloc/panacea-doracle/validation"
log "github.com/sirupsen/logrus"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
)
var _ event.Event = (*DataVerificationEvent)(nil)
type DataVerificationEvent struct {
reactor event.Reactor
}
func NewDataVerificationEvent(r event.Reactor) DataVerificationEvent {
return DataVerificationEvent{r}
}
func (e DataVerificationEvent) GetEventQuery() string {
return "message.action = 'SellData'"
}
func (e DataVerificationEvent) EventHandler(event ctypes.ResultEvent) error {
dealIDStr := event.Events[datadealtypes.EventTypeDataVerificationVote+"."+datadealtypes.AttributeKeyDealID][0]
dataHash := event.Events[datadealtypes.EventTypeDataVerificationVote+"."+datadealtypes.AttributeKeyDataHash][0]
dealID, err := strconv.ParseUint(dealIDStr, 10, 64)
if err != nil {
return err
}
voteOption, err := e.verifyAndGetVoteOption(dealID, dataHash)
if err != nil {
log.Infof("vote No due to error while verify. dealID(%d). dataHash(%s)", dealID, dataHash)
}
msgVoteDataVerification, err := makeDataVerificationVote(
e.reactor.OracleAcc().GetAddress(),
dataHash,
dealID,
voteOption,
e.reactor.OraclePrivKey().Serialize(),
)
if err != nil {
return err
}
txBuilder := panacea.NewTxBuilder(*e.reactor.QueryClient())
txBytes, err := txBuilder.GenerateTxBytes(e.reactor.OracleAcc().GetPrivKey(), e.reactor.Config(), msgVoteDataVerification)
if err != nil {
return fmt.Errorf("generate tx failed. dealID(%d). dataHash(%s): %w", dealID, dataHash, err)
}
txHeight, txHash, err := e.reactor.BroadcastTx(txBytes)
if err != nil {
return fmt.Errorf("data verifiaction vote transaction failed. dealID(%d). dataHash(%s): %v", dealID, dataHash, err)
} else {
log.Infof("MsgVoteDataVerification transaction succeed. height(%v), hash(%s)", txHeight, txHash)
}
return nil
}
func (e DataVerificationEvent) decryptData(decryptedSharedKey, nonce, encryptedDataBz []byte) ([]byte, error) {
return crypto.DecryptWithAES256(decryptedSharedKey, nonce, encryptedDataBz)
}
func (e DataVerificationEvent) compareDataHash(dataSale *datadealtypes.DataSale, decryptedData []byte) bool {
decryptedDataHash := sha256.Sum256(decryptedData)
decryptedDataHashStr := hex.EncodeToString(decryptedDataHash[:])
return decryptedDataHashStr == dataSale.DataHash
}
func (e DataVerificationEvent) convertSellerData(deal *datadealtypes.Deal, dataSale *datadealtypes.DataSale) ([]byte, error) {
encryptedDataBz, err := e.reactor.Ipfs().Get(dataSale.VerifiableCid)
if err != nil {
log.Infof("failed to get data from IPFS: %v", err)
return nil, err
}
oraclePrivKey := e.reactor.OraclePrivKey()
sellerAcc, err := e.reactor.QueryClient().GetAccount(dataSale.SellerAddress)
if err != nil {
return nil, err
}
sellerPubKeyBytes := sellerAcc.GetPubKey().Bytes()
sellerPubKey, err := btcec.ParsePubKey(sellerPubKeyBytes, btcec.S256())
if err != nil {
return nil, err
}
decryptSharedKey := crypto.DeriveSharedKey(oraclePrivKey, sellerPubKey, crypto.KDFSHA256)
decryptedData, err := e.decryptData(decryptSharedKey, deal.Nonce, encryptedDataBz)
if err != nil {
return nil, err
}
return decryptedData, nil
}
func (e DataVerificationEvent) verifyAndGetVoteOption(dealID uint64, dataHash string) (oracletypes.VoteOption, error) {
deal, err := e.reactor.QueryClient().GetDeal(dealID)
if err != nil {
return oracletypes.VOTE_OPTION_NO, fmt.Errorf("failed to get deal. %v", err)
}
dataSale, err := e.reactor.QueryClient().GetDataSale(dataHash, dealID)
if err != nil {
return oracletypes.VOTE_OPTION_NO, fmt.Errorf("failed to get dataSale (%v)", err)
}
if dataSale.Status != datadealtypes.DATA_SALE_STATUS_VERIFICATION_VOTING_PERIOD {
return oracletypes.VOTE_OPTION_NO, errors.New("dataSale's status is not DATA_SALE_STATUS_VERIFICATION_VOTING_PERIOD")
}
decryptedData, err := e.convertSellerData(deal, dataSale)
if err != nil {
return oracletypes.VOTE_OPTION_NO, fmt.Errorf("failed to decrypt seller data, error (%v)", err)
}
if !e.compareDataHash(dataSale, decryptedData) {
log.Infof("invalid data hash")
return oracletypes.VOTE_OPTION_NO, err
}
err = validation.ValidateJSONSchemata(decryptedData, deal.DataSchema)
if err != nil {
log.Infof("failed to verify data. error(%s)", err)
return oracletypes.VOTE_OPTION_NO, err
}
return oracletypes.VOTE_OPTION_YES, nil
}
func makeDataVerificationVote(voterAddress, dataHash string, dealID uint64, voteOption oracletypes.VoteOption, oraclePrivKey []byte) (*datadealtypes.MsgVoteDataVerification, error) {
dataVerificationVote := &datadealtypes.DataVerificationVote{
VoterAddress: voterAddress,
DealId: dealID,
DataHash: dataHash,
VoteOption: voteOption,
}
key := secp256k1.PrivKey{
Key: oraclePrivKey,
}
marshaledVerificationVote, err := dataVerificationVote.Marshal()
if err != nil {
return nil, err
}
sig, err := key.Sign(marshaledVerificationVote)
if err != nil {
return nil, err
}
msgVoteDataVerification := &datadealtypes.MsgVoteDataVerification{
DataVerificationVote: dataVerificationVote,
Signature: sig,
}
return msgVoteDataVerification, nil
}