Fantom-foundation/go-lachesis

View on GitHub
eventcheck/parentscheck/parents_check.go

Summary

Maintainability
A
50 mins
Test Coverage
package parentscheck

import (
    "errors"

    "github.com/Fantom-foundation/go-lachesis/inter"
    "github.com/Fantom-foundation/go-lachesis/inter/idx"
    "github.com/Fantom-foundation/go-lachesis/lachesis"
)

var (
    ErrWrongSeq        = errors.New("event has wrong sequence time")
    ErrWrongLamport    = errors.New("event has wrong Lamport time")
    ErrDoubleParents   = errors.New("event has double parents")
    ErrWrongSelfParent = errors.New("event is missing self-parent")
    ErrPastTime        = errors.New("event has lower claimed time than self-parent")
)

// Checker which require only parents list + current epoch info
type Checker struct {
    config *lachesis.DagConfig
}

// New validator which performs checks, which require known the parents
func New(config *lachesis.DagConfig) *Checker {
    return &Checker{
        config: config,
    }
}

// Validate event
func (v *Checker) Validate(e *inter.Event, parents []*inter.EventHeaderData) error {
    if len(e.Parents) != len(parents) {
        panic("parentscheck: expected event's parents as an argument")
    }

    // lamport
    maxLamport := idx.Lamport(0)
    for _, p := range parents {
        maxLamport = idx.MaxLamport(maxLamport, p.Lamport)
    }
    if e.Lamport != maxLamport+1 {
        return ErrWrongLamport
    }

    // parents
    if len(e.Parents.Set()) != len(e.Parents) {
        return ErrDoubleParents
    }

    // self-parent
    for i, p := range parents {
        if (p.Creator == e.Creator) != e.IsSelfParent(e.Parents[i]) {
            return ErrWrongSelfParent
        }
    }

    // seq
    if (e.Seq <= 1) != (e.SelfParent() == nil) {
        return ErrWrongSeq
    }
    if e.SelfParent() != nil {
        selfParent := parents[0]
        if !e.IsSelfParent(selfParent.Hash()) {
            // sanity check, self-parent is always first, it's how it's stored
            return ErrWrongSelfParent
        }
        if e.Seq != selfParent.Seq+1 {
            return ErrWrongSeq
        }

        // selfParent time
        if e.ClaimedTime <= selfParent.ClaimedTime {
            return ErrPastTime
        }
    }

    return nil
}