code.vegaprotocol.io/vega@v0.79.0/datanode/entities/data.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package entities
    17  
    18  import (
    19  	"encoding/hex"
    20  	"encoding/json"
    21  	"fmt"
    22  	"time"
    23  
    24  	dstypes "code.vegaprotocol.io/vega/core/datasource/common"
    25  	v2 "code.vegaprotocol.io/vega/protos/data-node/api/v2"
    26  	vegapb "code.vegaprotocol.io/vega/protos/vega"
    27  	datapb "code.vegaprotocol.io/vega/protos/vega/data/v1"
    28  )
    29  
    30  type (
    31  	_Spec  struct{}
    32  	SpecID = ID[_Spec]
    33  )
    34  
    35  type (
    36  	Signer  []byte
    37  	Signers = []Signer
    38  )
    39  
    40  type Property struct {
    41  	Name  string
    42  	Value string
    43  }
    44  
    45  func SerializeSigners(signers []*dstypes.Signer) (Signers, error) {
    46  	if len(signers) > 0 {
    47  		sigList := Signers{}
    48  
    49  		for _, signer := range signers {
    50  			data, err := signer.Serialize()
    51  			if err != nil {
    52  				return nil, err
    53  			}
    54  			sigList = append(sigList, data)
    55  		}
    56  
    57  		return sigList, nil
    58  	}
    59  
    60  	return Signers{}, nil
    61  }
    62  
    63  func DeserializeSigners(data Signers) []*dstypes.Signer {
    64  	if len(data) > 0 {
    65  		signers := []*dstypes.Signer{}
    66  		for _, s := range data {
    67  			signer := dstypes.DeserializeSigner(s)
    68  			signers = append(signers, signer)
    69  		}
    70  
    71  		return signers
    72  	}
    73  
    74  	return nil
    75  }
    76  
    77  type Data struct {
    78  	Signers        Signers
    79  	Data           []Property
    80  	MetaData       []Property
    81  	MatchedSpecIds [][]byte // pgx automatically handles [][]byte to Postgres ByteaArray mappings
    82  	BroadcastAt    time.Time
    83  	Error          *string
    84  	TxHash         TxHash
    85  	VegaTime       time.Time
    86  	SeqNum         uint64
    87  }
    88  
    89  type ExternalData struct {
    90  	Data *Data
    91  }
    92  
    93  func ExternalDataFromProto(data *datapb.ExternalData, txHash TxHash, vegaTime time.Time, seqNum uint64) (*ExternalData, error) {
    94  	properties := []Property{}
    95  	specIDs := [][]byte{}
    96  	signers := Signers{}
    97  	var metaDataProperties []Property
    98  
    99  	if data.Data != nil {
   100  		properties = make([]Property, 0, len(data.Data.Data))
   101  		specIDs = make([][]byte, 0, len(data.Data.MatchedSpecIds))
   102  
   103  		for _, property := range data.Data.Data {
   104  			properties = append(properties, Property{
   105  				Name:  property.Name,
   106  				Value: property.Value,
   107  			})
   108  		}
   109  
   110  		if len(data.Data.MetaData) > 0 {
   111  			metaDataProperties = make([]Property, 0, len(data.Data.MetaData))
   112  
   113  			for _, m := range data.Data.MetaData {
   114  				metaDataProperties = append(metaDataProperties, Property{
   115  					Name:  m.Name,
   116  					Value: m.Value,
   117  				})
   118  			}
   119  		}
   120  
   121  		for _, specID := range data.Data.MatchedSpecIds {
   122  			id := SpecID(specID)
   123  			idBytes, err := id.Bytes()
   124  			if err != nil {
   125  				return nil, fmt.Errorf("cannot decode spec ID: %w", err)
   126  			}
   127  			specIDs = append(specIDs, idBytes)
   128  		}
   129  
   130  		var err error
   131  		signers, err = SerializeSigners(dstypes.SignersFromProto(data.Data.Signers))
   132  		if err != nil {
   133  			return nil, err
   134  		}
   135  	}
   136  
   137  	return &ExternalData{
   138  		Data: &Data{
   139  			Signers:        signers,
   140  			Data:           properties,
   141  			MetaData:       metaDataProperties,
   142  			MatchedSpecIds: specIDs,
   143  			BroadcastAt:    NanosToPostgresTimestamp(data.Data.BroadcastAt),
   144  			Error:          data.Data.Error,
   145  			TxHash:         txHash,
   146  			VegaTime:       vegaTime,
   147  			SeqNum:         seqNum,
   148  		},
   149  	}, nil
   150  }
   151  
   152  func (od *ExternalData) ToProto() *datapb.ExternalData {
   153  	properties := []*datapb.Property{}
   154  	specIDs := []string{}
   155  	signersAsProto := []*datapb.Signer{}
   156  	metaDataProperties := []*datapb.Property{}
   157  
   158  	if od.Data != nil {
   159  		if od.Data.Data != nil {
   160  			properties = make([]*datapb.Property, 0, len(od.Data.Data))
   161  			specIDs = make([]string, 0, len(od.Data.MatchedSpecIds))
   162  			metaDataProperties = make([]*datapb.Property, 0, len(od.Data.MetaData))
   163  
   164  			for _, prop := range od.Data.Data {
   165  				properties = append(properties, &datapb.Property{
   166  					Name:  prop.Name,
   167  					Value: prop.Value,
   168  				})
   169  			}
   170  
   171  			for _, m := range od.Data.MetaData {
   172  				metaDataProperties = append(metaDataProperties, &datapb.Property{
   173  					Name:  m.Name,
   174  					Value: m.Value,
   175  				})
   176  			}
   177  
   178  			for _, id := range od.Data.MatchedSpecIds {
   179  				hexID := hex.EncodeToString(id)
   180  				specIDs = append(specIDs, hexID)
   181  			}
   182  		}
   183  
   184  		signers := DeserializeSigners(od.Data.Signers)
   185  		signersAsProto = dstypes.SignersIntoProto(signers)
   186  	}
   187  
   188  	return &datapb.ExternalData{
   189  		Data: &datapb.Data{
   190  			Signers:        signersAsProto,
   191  			Data:           properties,
   192  			MetaData:       metaDataProperties,
   193  			MatchedSpecIds: specIDs,
   194  			BroadcastAt:    od.Data.BroadcastAt.UnixNano(),
   195  			Error:          od.Data.Error,
   196  		},
   197  	}
   198  }
   199  
   200  func (od ExternalData) ToOracleProto() *vegapb.OracleData {
   201  	return &vegapb.OracleData{
   202  		ExternalData: od.ToProto(),
   203  	}
   204  }
   205  
   206  func (od ExternalData) Cursor() *Cursor {
   207  	return NewCursor(OracleDataCursor{
   208  		VegaTime: od.Data.VegaTime,
   209  		Signers:  od.Data.Signers,
   210  	}.String())
   211  }
   212  
   213  func (od ExternalData) ToOracleProtoEdge(_ ...any) (*v2.OracleDataEdge, error) {
   214  	return &v2.OracleDataEdge{
   215  		Node:   od.ToOracleProto(),
   216  		Cursor: od.Cursor().Encode(),
   217  	}, nil
   218  }
   219  
   220  type ExternalDataCursor struct {
   221  	VegaTime time.Time `json:"vegaTime"`
   222  	Signers  Signers   `json:"signers"`
   223  }
   224  
   225  func (c ExternalDataCursor) String() string {
   226  	bs, err := json.Marshal(c)
   227  	if err != nil {
   228  		// This really shouldn't happen.
   229  		panic(fmt.Errorf("couldn't marshal oracle data cursor: %w", err))
   230  	}
   231  
   232  	return string(bs)
   233  }
   234  
   235  func (c *ExternalDataCursor) Parse(cursorString string) error {
   236  	if cursorString == "" {
   237  		return nil
   238  	}
   239  
   240  	return json.Unmarshal([]byte(cursorString), c)
   241  }
   242  
   243  type Condition struct {
   244  	Operator datapb.Condition_Operator
   245  	Value    string
   246  }
   247  
   248  func (c Condition) ToProto() *datapb.Condition {
   249  	return &datapb.Condition{
   250  		Operator: c.Operator,
   251  		Value:    c.Value,
   252  	}
   253  }
   254  
   255  func ConditionFromProto(protoCondition *datapb.Condition) Condition {
   256  	return Condition{
   257  		Operator: protoCondition.Operator,
   258  		Value:    protoCondition.Value,
   259  	}
   260  }
   261  
   262  type PropertyKey struct {
   263  	Name          string `json:"name"`
   264  	Type          datapb.PropertyKey_Type
   265  	DecimalPlaces *uint64 `json:"number_decimal_places,omitempty"`
   266  }
   267  
   268  type Filter struct {
   269  	Key        PropertyKey `json:"key"`
   270  	Conditions []Condition `json:"conditions"`
   271  }
   272  
   273  func (f Filter) ToProto() *datapb.Filter {
   274  	conditions := make([]*datapb.Condition, 0, len(f.Conditions))
   275  	for _, condition := range f.Conditions {
   276  		conditions = append(conditions, condition.ToProto())
   277  	}
   278  
   279  	var ndp *uint64
   280  	if f.Key.DecimalPlaces != nil {
   281  		v := *f.Key.DecimalPlaces
   282  		ndp = &v
   283  	}
   284  
   285  	return &datapb.Filter{
   286  		Key: &datapb.PropertyKey{
   287  			Name:                f.Key.Name,
   288  			Type:                f.Key.Type,
   289  			NumberDecimalPlaces: ndp,
   290  		},
   291  		Conditions: conditions,
   292  	}
   293  }
   294  
   295  func FiltersFromProto(filters []*datapb.Filter) []Filter {
   296  	if len(filters) == 0 {
   297  		return []Filter{}
   298  	}
   299  
   300  	results := make([]Filter, 0, len(filters))
   301  	for _, filter := range filters {
   302  		conditions := make([]Condition, 0, len(filter.Conditions))
   303  
   304  		for _, condition := range filter.Conditions {
   305  			conditions = append(conditions, Condition{
   306  				Operator: condition.Operator,
   307  				Value:    condition.Value,
   308  			})
   309  		}
   310  
   311  		var ndp *uint64
   312  		if filter.Key.NumberDecimalPlaces != nil {
   313  			v := *filter.Key.NumberDecimalPlaces
   314  			ndp = &v
   315  		}
   316  		results = append(results, Filter{
   317  			Key: PropertyKey{
   318  				Name:          filter.Key.Name,
   319  				Type:          filter.Key.Type,
   320  				DecimalPlaces: ndp,
   321  			},
   322  			Conditions: conditions,
   323  		})
   324  	}
   325  
   326  	return results
   327  }