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  }