Skip to content
Merged
Show file tree
Hide file tree
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
59 changes: 59 additions & 0 deletions internal/bigendianbytearray/bigendianbytearray.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Package bigendianbytearray provides arithmetic operations on fixed-size byte
// arrays interpreted as unsigned big-endian integers.
package bigendianbytearray

func Min32[T ~[32]byte]() T {
return T{}
}

func Max32[T ~[32]byte]() T {
var t T
for i := range t {
t[i] = 0xff
}
return t
}

func Decrement32[T ~[32]byte](t T) (T, bool) {
tdec := t
for i := len(tdec) - 1; i >= 0; i-- {
if tdec[i] == 0 {
tdec[i] = 0xff
} else {
tdec[i]--
return tdec, true
}
}
return T{}, false
}

func WrappingDecrement32[T ~[32]byte](t T) T {
decr, ok := Decrement32(t)
if ok {
return decr
} else {
return Max32[T]()
}
}

func Increment32[T ~[32]byte](t T) (T, bool) {
tincr := t
for i := len(tincr) - 1; i >= 0; i-- {
if tincr[i] == 0xff {
tincr[i] = 0
} else {
tincr[i]++
return tincr, true
}
}
return T{}, false
}

func WrappingIncrement32[T ~[32]byte](t T) T {
incr, ok := Increment32(t)
if ok {
return incr
} else {
return Min32[T]()
}
}
29 changes: 6 additions & 23 deletions internal/jmt/digest.go
Original file line number Diff line number Diff line change
@@ -1,39 +1,22 @@
package jmt

import (
"bytes"
"crypto/sha256"

"github.com/smartcontractkit/libocr/internal/bigendianbytearray"
)

type Digest = [sha256.Size]byte

var (
MinDigest = Digest{}
MaxDigest = Digest(bytes.Repeat([]byte{0xff}, len(Digest{})))
MinDigest = bigendianbytearray.Min32[Digest]()
MaxDigest = bigendianbytearray.Max32[Digest]()
)

func DecrementDigest(digest Digest) (Digest, bool) {
decDigest := digest
for i := len(decDigest) - 1; i >= 0; i-- {
if decDigest[i] == 0 {
decDigest[i] = 0xff
} else {
decDigest[i]--
return decDigest, true
}
}
return Digest{}, false
return bigendianbytearray.Decrement32(digest)
}

func IncrementDigest(digest Digest) (Digest, bool) {
incDigest := digest
for i := len(incDigest) - 1; i >= 0; i-- {
if incDigest[i] == 0xff {
incDigest[i] = 0
} else {
incDigest[i]++
return incDigest, true
}
}
return Digest{}, false
return bigendianbytearray.Increment32(digest)
}
73 changes: 73 additions & 0 deletions internal/metricshelper/lazy_gauge.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package metricshelper

import (
"sync"

"github.com/prometheus/client_golang/prometheus"
"github.com/smartcontractkit/libocr/commontypes"
)

// LazyGauge registers its underlying Gauge the first time Set is called. This
// avoids exposing a default zero value before we have an appropriate value to
// expose.
type LazyGauge struct {
// in
registerer prometheus.Registerer
logger commontypes.Logger
name string

// local
gauge prometheus.Gauge

mu sync.Mutex
shouldRegister bool
}

func NewLazyGauge(
registerer prometheus.Registerer,
logger commontypes.Logger,
opts prometheus.GaugeOpts,
) *LazyGauge {
return &LazyGauge{
registerer,
logger,
opts.Name,
prometheus.NewGauge(opts),

sync.Mutex{},
true,
}
}

func (g *LazyGauge) Set(value float64) {
g.gauge.Set(value)

var shouldRegister bool
g.mu.Lock()
if g.shouldRegister {
shouldRegister = true
g.shouldRegister = false
}
g.mu.Unlock()

if shouldRegister {
RegisterOrLogError(g.logger, g.registerer, g.gauge, g.name)
g.gauge.Set(value) // To ensure the value is detected on collection, even if collection only sees values set after registration
}
}

// Unregister must be used instead of [prometheus.Registerer.Unregister].
// Otherwise, it would be possible for the LazyGauge to have never been Set and
// thus registered, and then after invocation of
// [prometheus.Registerer.Unregister], the next Set would cause the gauge to be
// registered, which is almost definitely unexpected behavior. In fact,
// LazyGauge intentionally does not implement prometheus.Collector to avoid
// confusion. The meaning of the return value matches that of
// [prometheus.Registerer.Unregister].
func (g *LazyGauge) Unregister() bool {
g.mu.Lock()
g.shouldRegister = false
g.mu.Unlock()

return g.registerer.Unregister(g.gauge)
}
3 changes: 2 additions & 1 deletion internal/singlewriter/conflict_tracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ func (ct *ConflictTracker) beginTransaction() (uint64, uint64) {
func (ct *ConflictTracker) lockAndPrepareToCommit(maxCommittedTxTimestampAtCreation uint64) error {
ct.mu.Lock()
if maxCommittedTxTimestampAtCreation != ct.maxCommittedTxTimestamp {
maxCommittedTxTimestamp := ct.maxCommittedTxTimestamp
ct.mu.Unlock()
return fmt.Errorf("concurrent conflict detected: expected maxCommittedTxTimestamp: %d, got: %d", maxCommittedTxTimestampAtCreation, ct.maxCommittedTxTimestamp)
return fmt.Errorf("concurrent conflict detected: expected maxCommittedTxTimestamp: %d, got: %d", maxCommittedTxTimestampAtCreation, maxCommittedTxTimestamp)
}
return nil
}
Expand Down
22 changes: 21 additions & 1 deletion internal/util/generic.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package util

import "golang.org/x/exp/constraints"
import (
"maps"

"golang.org/x/exp/constraints"
)

func PointerTo[T any](v T) *T {
return &v
Expand All @@ -14,6 +18,14 @@ func PointerIntegerCast[U constraints.Integer, T constraints.Integer](p *T) *U {
return &v
}

func SaturatingSub[T constraints.Unsigned](a T, b T) T {
if b > a {
var zero T
return zero
}
return a - b
}

func NilCoalesce[T any](maybe *T, default_ T) T {
if maybe != nil {
return *maybe
Expand All @@ -29,3 +41,11 @@ func NilCoalesceSlice[T any](maybe []T) []T {
return []T{}
}
}

// b has priority in case of key conflict with a
func MapsUnion[K comparable, V any](a map[K]V, b map[K]V) map[K]V {
c := make(map[K]V)
maps.Copy(c, a)
maps.Copy(c, b)
return c
}
13 changes: 13 additions & 0 deletions offchainreporting2plus/internal/ocr3_1/blobtypes/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"hash"

"github.com/smartcontractkit/libocr/commontypes"
"github.com/smartcontractkit/libocr/internal/bigendianbytearray"
"github.com/smartcontractkit/libocr/internal/mt"
"github.com/smartcontractkit/libocr/offchainreporting2plus/internal/config"
"github.com/smartcontractkit/libocr/offchainreporting2plus/types"
Expand Down Expand Up @@ -71,6 +72,18 @@ func (bd BlobDigest) String() string {
return fmt.Sprintf("%x", bd[:])
}

func MinBlobDigest() BlobDigest {
return bigendianbytearray.Min32[BlobDigest]()
}

func MaxBlobDigest() BlobDigest {
return bigendianbytearray.Max32[BlobDigest]()
}

func WrappingIncrementBlobDigest(bd BlobDigest) BlobDigest {
return bigendianbytearray.WrappingIncrement32(bd)
}

func MakeBlobDigest(
configDigest types.ConfigDigest,
chunkDigestsRoot mt.Digest,
Expand Down
Loading
Loading