github.com/smartcontractkit/chainlink-terra@v0.1.4/tests/e2e/common/common.go (about) 1 package common 2 3 import ( 4 "bytes" 5 "encoding/hex" 6 "fmt" 7 "math/big" 8 "sort" 9 "strings" 10 "time" 11 12 "github.com/rs/zerolog/log" 13 uuid "github.com/satori/go.uuid" 14 15 "github.com/smartcontractkit/integrations-framework/client" 16 "github.com/smartcontractkit/integrations-framework/contracts" 17 "github.com/smartcontractkit/libocr/offchainreporting2/confighelper" 18 "github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median" 19 "github.com/smartcontractkit/libocr/offchainreporting2/types" 20 "golang.org/x/crypto/curve25519" 21 ) 22 23 // TODO: those should be moved as a common part of integrations-framework 24 25 const ( 26 ChainName = "terra" 27 ) 28 29 // Those functions may be common with another chains and should be moved to another lib 30 31 type NodeKeysBundle struct { 32 PeerID string 33 OCR2Key *client.OCR2Key 34 TXKey *client.TxKey 35 } 36 37 // OCR2 keys are in format OCR2<key_type>_<network>_<key> 38 func stripKeyPrefix(key string) string { 39 chunks := strings.Split(key, "_") 40 if len(chunks) == 3 { 41 return chunks[2] 42 } 43 return key 44 } 45 46 func createNodeKeys(nodes []client.Chainlink) ([]NodeKeysBundle, error) { 47 nkb := make([]NodeKeysBundle, 0) 48 for _, n := range nodes { 49 p2pkeys, err := n.ReadP2PKeys() 50 if err != nil { 51 return nil, err 52 } 53 54 peerID := p2pkeys.Data[0].Attributes.PeerID 55 txKey, err := n.CreateTxKey(ChainName) 56 if err != nil { 57 return nil, err 58 } 59 ocrKey, err := n.CreateOCR2Key(ChainName) 60 if err != nil { 61 return nil, err 62 } 63 nkb = append(nkb, NodeKeysBundle{ 64 PeerID: peerID, 65 OCR2Key: ocrKey, 66 TXKey: txKey, 67 }) 68 } 69 return nkb, nil 70 } 71 72 func createOracleIdentities(nkb []NodeKeysBundle) ([]confighelper.OracleIdentityExtra, error) { 73 oracleIdentities := make([]confighelper.OracleIdentityExtra, 0) 74 for _, nodeKeys := range nkb { 75 offChainPubKey, err := hex.DecodeString(stripKeyPrefix(nodeKeys.OCR2Key.Data.Attributes.OffChainPublicKey)) 76 if err != nil { 77 return nil, err 78 } 79 onChainPubKey, err := hex.DecodeString(stripKeyPrefix(nodeKeys.OCR2Key.Data.Attributes.OnChainPublicKey)) 80 if err != nil { 81 return nil, err 82 } 83 cfgPubKeyTemp, err := hex.DecodeString(stripKeyPrefix(nodeKeys.OCR2Key.Data.Attributes.ConfigPublicKey)) 84 if err != nil { 85 return nil, err 86 } 87 cfgPubKeyBytes := [curve25519.PointSize]byte{} 88 copy(cfgPubKeyBytes[:], cfgPubKeyTemp) 89 oracleIdentities = append(oracleIdentities, confighelper.OracleIdentityExtra{ 90 OracleIdentity: confighelper.OracleIdentity{ 91 OffchainPublicKey: offChainPubKey, 92 OnchainPublicKey: onChainPubKey, 93 PeerID: nodeKeys.PeerID, 94 TransmitAccount: types.Account(nodeKeys.TXKey.Data.Attributes.PublicKey), 95 }, 96 ConfigEncryptionPublicKey: cfgPubKeyBytes, 97 }) 98 } 99 // program sorts oracles (need to pre-sort to allow correct onchainConfig generation) 100 sort.Slice(oracleIdentities, func(i, j int) bool { 101 return bytes.Compare(oracleIdentities[i].OracleIdentity.OnchainPublicKey, oracleIdentities[j].OracleIdentity.OnchainPublicKey) < 0 102 }) 103 return oracleIdentities, nil 104 } 105 106 func FundOracles(c client.BlockchainClient, nkb []NodeKeysBundle, amount *big.Float) error { 107 for _, nk := range nkb { 108 addr := nk.TXKey.Data.Attributes.PublicKey 109 if err := c.Fund(addr, amount); err != nil { 110 return err 111 } 112 } 113 return nil 114 } 115 116 // DefaultOffChainConfigParamsFromNodes collects OCR2 keys and creates contracts.OffChainAggregatorV2Config 117 func DefaultOffChainConfigParamsFromNodes(nodes []client.Chainlink) (contracts.OffChainAggregatorV2Config, []NodeKeysBundle, error) { 118 nkb, err := createNodeKeys(nodes) 119 if err != nil { 120 return contracts.OffChainAggregatorV2Config{}, nil, err 121 } 122 oi, err := createOracleIdentities(nkb[1:]) 123 if err != nil { 124 return contracts.OffChainAggregatorV2Config{}, nil, err 125 } 126 s := make([]int, 0) 127 for range nodes[1:] { 128 s = append(s, 1) 129 } 130 faultyNodes := 0 131 if len(nodes[1:]) > 1 { 132 faultyNodes = len(nkb[1:])/3 - 1 133 } 134 if faultyNodes == 0 { 135 faultyNodes = 1 136 } 137 log.Warn().Int("Nodes", faultyNodes).Msg("Faulty nodes") 138 return contracts.OffChainAggregatorV2Config{ 139 DeltaProgress: 2 * time.Second, 140 DeltaResend: 5 * time.Second, 141 DeltaRound: 1 * time.Second, 142 DeltaGrace: 500 * time.Millisecond, 143 DeltaStage: 10 * time.Second, 144 RMax: 3, 145 S: s, 146 Oracles: oi, 147 ReportingPluginConfig: median.OffchainConfig{ 148 AlphaReportPPB: uint64(0), 149 AlphaAcceptPPB: uint64(0), 150 }.Encode(), 151 MaxDurationQuery: 0, 152 MaxDurationObservation: 500 * time.Millisecond, 153 MaxDurationReport: 500 * time.Millisecond, 154 MaxDurationShouldAcceptFinalizedReport: 500 * time.Millisecond, 155 MaxDurationShouldTransmitAcceptedReport: 500 * time.Millisecond, 156 F: faultyNodes, 157 OnchainConfig: []byte{}, 158 }, nkb, nil 159 } 160 161 func CreateJobs(ocr2Addr string, nodes []client.Chainlink, nkb []NodeKeysBundle, mock *client.MockserverClient) error { 162 bootstrapPeers := []client.P2PData{ 163 { 164 RemoteIP: nodes[0].RemoteIP(), 165 RemotePort: "6690", 166 PeerID: nkb[0].PeerID, 167 }, 168 } 169 for nIdx, n := range nodes { 170 jobType := "offchainreporting2" 171 if nIdx == 0 { 172 jobType = "bootstrap" 173 } 174 sourceValueBridge := client.BridgeTypeAttributes{ 175 Name: "variable", 176 URL: fmt.Sprintf("%s/node%d", mock.Config.ClusterURL, nIdx), 177 RequestData: "{}", 178 } 179 observationSource := client.ObservationSourceSpecBridge(sourceValueBridge) 180 err := n.CreateBridge(&sourceValueBridge) 181 if err != nil { 182 return err 183 } 184 185 juelsBridge := client.BridgeTypeAttributes{ 186 Name: "juels", 187 URL: fmt.Sprintf("%s/juels", mock.Config.ClusterURL), 188 RequestData: "{}", 189 } 190 juelsSource := client.ObservationSourceSpecBridge(juelsBridge) 191 err = n.CreateBridge(&juelsBridge) 192 if err != nil { 193 return err 194 } 195 _, err = n.CreateTerraChain(&client.TerraChainAttributes{ChainID: "localterra"}) 196 if err != nil { 197 return err 198 } 199 relayConfig := map[string]string{ 200 "nodeType": "terra", 201 "tendermintURL": "http://terrad:26657", 202 "fcdURL": "http://fcd-api:3060", 203 "chainID": "localterra", 204 } 205 if _, err = n.CreateTerraNode(&client.TerraNodeAttributes{ 206 Name: "terra", 207 TerraChainID: relayConfig["chainID"], 208 TendermintURL: relayConfig["tendermintURL"], 209 FCDURL: relayConfig["fcdURL"], 210 }); err != nil { 211 return err 212 } 213 jobSpec := &client.OCR2TaskJobSpec{ 214 Name: fmt.Sprintf("terra-OCRv2-%d-%s", nIdx, uuid.NewV4().String()), 215 JobType: jobType, 216 ContractID: ocr2Addr, 217 Relay: ChainName, 218 RelayConfig: relayConfig, 219 P2PPeerID: nkb[nIdx].PeerID, 220 PluginType: "median", 221 P2PBootstrapPeers: bootstrapPeers, 222 OCRKeyBundleID: nkb[nIdx].OCR2Key.Data.ID, 223 TransmitterID: nkb[nIdx].TXKey.Data.ID, 224 ObservationSource: observationSource, 225 JuelsPerFeeCoinSource: juelsSource, 226 } 227 if _, err = n.CreateJob(jobSpec); err != nil { 228 return err 229 } 230 } 231 return nil 232 }