code.vegaprotocol.io/vega@v0.79.0/core/datasource/external/ethcall/contract.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 ethcall
    17  
    18  import (
    19  	"encoding/hex"
    20  	"errors"
    21  	"strconv"
    22  
    23  	"code.vegaprotocol.io/vega/libs/crypto"
    24  	vegapb "code.vegaprotocol.io/vega/protos/vega"
    25  )
    26  
    27  type ContractCallEvent struct {
    28  	BlockHeight   uint64
    29  	BlockTime     uint64
    30  	SpecId        string
    31  	Result        []byte
    32  	Error         *string
    33  	SourceChainID *uint64
    34  	Heartbeat     bool
    35  }
    36  
    37  func EthereumContractCallResultFromProto(
    38  	qr *vegapb.EthContractCallEvent,
    39  ) (ContractCallEvent, error) {
    40  	res := ContractCallEvent{
    41  		SpecId:        qr.SpecId,
    42  		BlockHeight:   qr.BlockHeight,
    43  		BlockTime:     qr.BlockTime,
    44  		Result:        qr.Result,
    45  		Error:         qr.Error,
    46  		SourceChainID: qr.SourceChainId,
    47  		Heartbeat:     qr.Heartbeat,
    48  	}
    49  
    50  	if qr.BlockHeight == 0 || qr.BlockTime <= 0 {
    51  		return ContractCallEvent{}, errors.New("invalid contract call payload")
    52  	}
    53  
    54  	if qr.Heartbeat {
    55  		return res, nil
    56  	}
    57  
    58  	if (len(qr.Result) <= 0 && qr.Error == nil) || len(qr.SpecId) <= 0 {
    59  		return ContractCallEvent{}, errors.New("invalid contract call payload")
    60  	}
    61  
    62  	return res, nil
    63  }
    64  
    65  func (q *ContractCallEvent) IntoProto() *vegapb.EthContractCallEvent {
    66  	return &vegapb.EthContractCallEvent{
    67  		SpecId:        q.SpecId,
    68  		BlockHeight:   q.BlockHeight,
    69  		BlockTime:     q.BlockTime,
    70  		Result:        q.Result,
    71  		Error:         q.Error,
    72  		SourceChainId: q.SourceChainID,
    73  		Heartbeat:     q.Heartbeat,
    74  	}
    75  }
    76  
    77  func (q ContractCallEvent) Hash() string {
    78  	blockHeight := strconv.FormatUint(q.BlockHeight, 10)
    79  	blockTime := strconv.FormatUint(q.BlockTime, 10)
    80  	bytes := []byte(blockHeight + blockTime + q.SpecId)
    81  	bytes = append(bytes, q.Result...)
    82  	if q.Error != nil {
    83  		bytes = append(bytes, []byte(*q.Error)...)
    84  	}
    85  
    86  	if q.Heartbeat {
    87  		// only append if its true so that old events pre this flag existing hash to the same value
    88  		strconv.AppendBool(bytes, q.Heartbeat)
    89  	}
    90  
    91  	return hex.EncodeToString(
    92  		crypto.Hash(bytes),
    93  	)
    94  }