Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added range checks in event parsers. Issue #180 #181

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions relayer/pkg/chainlink/ocr2/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package ocr2

import (
"encoding/hex"
"fmt"
"math"
"math/big"
"time"

Expand All @@ -21,6 +23,26 @@ var (
// Event selectors
NewTransmissionEventSelector = "019e22f866f4c5aead2809bf160d2b29e921e335d899979732101c6f3c38ff81"
ConfigSetEventSelector = "9a144bf4a6a8fd083c93211e163e59221578efcc86b93f8c97c620e7b9608a"

feltRange = Range{
new(big.Int).SetUint64(0),
caigotypes.MaxFelt.Big(),
}

uint32Range = Range{
new(big.Int).SetUint64(0),
new(big.Int).SetUint64(math.MaxUint32),
}

uint64Range = Range{
new(big.Int).SetUint64(0),
new(big.Int).SetUint64(math.MaxUint64),
}

int64Range = Range{
new(big.Int).SetInt64(math.MinInt64),
new(big.Int).SetInt64(math.MaxInt64),
}
)

// NewTransmissionEvent represents the 'NewTransmission' event
Expand All @@ -40,6 +62,19 @@ type NewTransmissionEvent struct {
Reimbursement *big.Int
}

type Range struct {
Lower *big.Int
Upper *big.Int
}

func (r *Range) Check(n *big.Int) error {
if !(n.Cmp(r.Lower) >= 0 && n.Cmp(r.Upper) <= 0) {
return fmt.Errorf("invalid: value %v is out of range [%v,%v]", n, r.Lower, r.Upper)
}

return nil
}

// ParseNewTransmissionEvent is decoding binary felt data as the NewTransmissionEvent type
func ParseNewTransmissionEvent(eventData []*caigotypes.Felt) (NewTransmissionEvent, error) {
{
Expand All @@ -50,6 +85,10 @@ func ParseNewTransmissionEvent(eventData []*caigotypes.Felt) (NewTransmissionEve
return NewTransmissionEvent{}, errors.New("invalid: event data")
}

err := uint64Range.Check(eventData[observationsLenIndex].Big())
if err != nil {
return NewTransmissionEvent{}, err
}
observationsLen := eventData[observationsLenIndex].Uint64()
if len(eventData) != constNumOfElements+int(observationsLen) {
return NewTransmissionEvent{}, errors.New("invalid: event data")
Expand All @@ -58,18 +97,34 @@ func ParseNewTransmissionEvent(eventData []*caigotypes.Felt) (NewTransmissionEve

// round_id
index := 0
err := uint32Range.Check(eventData[index].Big())
if err != nil {
return NewTransmissionEvent{}, err
}
roundId := uint32(eventData[index].Uint64())

// answer
index++
err = feltRange.Check(eventData[index].Big())
if err != nil {
return NewTransmissionEvent{}, err
}
latestAnswer := starknet.HexToSignedBig(eventData[index].String())

// transmitter
index++
err = feltRange.Check(eventData[index].Big())
if err != nil {
return NewTransmissionEvent{}, err
}
transmitter := eventData[index]

// observation_timestamp
index++
err = int64Range.Check(eventData[index].Big())
if err != nil {
return NewTransmissionEvent{}, err
}
unixTime := eventData[index].Int64()
latestTimestamp := time.Unix(unixTime, 0)

Expand All @@ -79,6 +134,10 @@ func ParseNewTransmissionEvent(eventData []*caigotypes.Felt) (NewTransmissionEve

// observation_len
index++
err = uint32Range.Check(eventData[index].Big())
if err != nil {
return NewTransmissionEvent{}, err
}
observationsLen := uint32(eventData[index].Uint64())

// observers (based on observationsLen)
Expand All @@ -90,15 +149,27 @@ func ParseNewTransmissionEvent(eventData []*caigotypes.Felt) (NewTransmissionEve
// observations (based on observationsLen)
var observations []*big.Int
for i := 0; i < int(observationsLen); i++ {
err = feltRange.Check(eventData[index].Big())
if err != nil {
return NewTransmissionEvent{}, err
}
observations = append(observations, eventData[index+i+1].Big())
}

// juels_per_fee_coin
index += int(observationsLen) + 1
err = feltRange.Check(eventData[index].Big())
if err != nil {
return NewTransmissionEvent{}, err
}
juelsPerFeeCoin := eventData[index].Big()

// juels_per_fee_coin
index++
err = feltRange.Check(eventData[index].Big())
if err != nil {
return NewTransmissionEvent{}, err
}
gasPrice := eventData[index].Big()

// config digest
Expand All @@ -114,6 +185,10 @@ func ParseNewTransmissionEvent(eventData []*caigotypes.Felt) (NewTransmissionEve

// reimbursement
index++
err = feltRange.Check(eventData[index].Big())
if err != nil {
return NewTransmissionEvent{}, err
}
reimbursement := eventData[index].Big()

return NewTransmissionEvent{
Expand All @@ -135,19 +210,33 @@ func ParseNewTransmissionEvent(eventData []*caigotypes.Felt) (NewTransmissionEve

// ParseConfigSetEvent is decoding binary felt data as the libocr ContractConfig type
func ParseConfigSetEvent(eventData []*caigotypes.Felt) (types.ContractConfig, error) {
maxObserversRange := Range{
uint64Range.Lower,
new(big.Int).SetUint64(uint64(MaxObservers)),
}

{
const oraclesLenIdx = 3
if len(eventData) < oraclesLenIdx {
return types.ContractConfig{}, errors.New("invalid: event data")
}

err := maxObserversRange.Check(eventData[oraclesLenIdx].Big())

if err != nil {
return types.ContractConfig{}, err
}
oraclesLen := eventData[oraclesLenIdx].Uint64()
onchainConfigLenIdx := oraclesLenIdx + 2*oraclesLen + 2

if uint64(len(eventData)) < onchainConfigLenIdx {
return types.ContractConfig{}, errors.New("invalid: event data")
}

err = uint64Range.Check(eventData[onchainConfigLenIdx].Big())
if err != nil {
return types.ContractConfig{}, err
}
onchainConfigLen := eventData[onchainConfigLenIdx].Uint64()
offchainConfigLenIdx := onchainConfigLenIdx + onchainConfigLen + 2

Expand All @@ -156,6 +245,11 @@ func ParseConfigSetEvent(eventData []*caigotypes.Felt) (types.ContractConfig, er
}

offchainConfigLen := eventData[offchainConfigLenIdx].Uint64()
err = uint64Range.Check(eventData[onchainConfigLenIdx].Big())
if err != nil {
return types.ContractConfig{}, err
}

if uint64(len(eventData)) != offchainConfigLenIdx+offchainConfigLen+1 {
return types.ContractConfig{}, errors.New("invalid: event data")
}
Expand All @@ -173,10 +267,18 @@ func ParseConfigSetEvent(eventData []*caigotypes.Felt) (types.ContractConfig, er

// config_count
index++
err = uint64Range.Check(eventData[index].Big())
if err != nil {
return types.ContractConfig{}, err
}
configCount := eventData[index].Uint64()

// oracles_len
index++
err = maxObserversRange.Check(eventData[index].Big())
if err != nil {
return types.ContractConfig{}, err
}
oraclesLen := eventData[index].Uint64()

// oracles
Expand All @@ -194,10 +296,18 @@ func ParseConfigSetEvent(eventData []*caigotypes.Felt) (types.ContractConfig, er

// f
index = index + int(oraclesLen)*2
err = uint64Range.Check(eventData[index].Big())
if err != nil {
return types.ContractConfig{}, err
}
f := eventData[index].Uint64()

// onchain_config length
index++
err = uint64Range.Check(eventData[index].Big())
if err != nil {
return types.ContractConfig{}, err
}
onchainConfigLen := eventData[index].Uint64()

// onchain_config (version=1, min, max)
Expand All @@ -214,10 +324,18 @@ func ParseConfigSetEvent(eventData []*caigotypes.Felt) (types.ContractConfig, er

// offchain_config_version
index += int(onchainConfigLen)
err = uint64Range.Check(eventData[index].Big())
if err != nil {
return types.ContractConfig{}, err
}
offchainConfigVersion := eventData[index].Uint64()

// offchain_config_len
index++
err = uint64Range.Check(eventData[index].Big())
if err != nil {
return types.ContractConfig{}, err
}
offchainConfigLen := eventData[index].Uint64()

// offchain_config
Expand Down