Skip to content

Commit

Permalink
Implement generic math functions (ava-labs#1895)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Laine authored Oct 13, 2022
1 parent 6b7629b commit 32040ca
Show file tree
Hide file tree
Showing 21 changed files with 154 additions and 141 deletions.
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ require (
github.com/Microsoft/go-winio v0.5.2
github.com/NYTimes/gziphandler v1.1.1
github.com/ava-labs/avalanche-network-runner-sdk v0.2.0
github.com/ava-labs/coreth v0.11.1-rc.1
github.com/ava-labs/coreth v0.11.1-rc.2
github.com/btcsuite/btcd v0.23.1
github.com/btcsuite/btcd/btcutil v1.1.1
github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0-20200627015759-01fd2de07837
Expand Down Expand Up @@ -46,6 +46,7 @@ require (
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a
go.uber.org/zap v1.21.0
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d
golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5
golang.org/x/net v0.0.0-20220708220712-1185a9018129
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
Expand Down
5 changes: 3 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/ava-labs/avalanche-network-runner-sdk v0.2.0 h1:YNvM0oFlb7A825kGe0XwwZuvIXTKF1BsuvxJdRLhIaI=
github.com/ava-labs/avalanche-network-runner-sdk v0.2.0/go.mod h1:bEBRVZnGeRiNdDJAFUj+gA/TPzNDbpY/WzgDAHHwJb8=
github.com/ava-labs/coreth v0.11.1-rc.1 h1:GpSythfFCOXBoalsNvmzFBae0rgblTUnQuamgAVEhu4=
github.com/ava-labs/coreth v0.11.1-rc.1/go.mod h1:8pN1Ko0RfPoEHzBVn9bzuv0uV1b+/vNTuYC+MqY8P0g=
github.com/ava-labs/coreth v0.11.1-rc.2 h1:Q1lOyC8BJaklqDP4DR9QLEPqZTj7MLyL1f/WxaMRMNI=
github.com/ava-labs/coreth v0.11.1-rc.2/go.mod h1:OJU9zUDUrcgjBR0y4JBe0RQCHqa7Pw5YesAbuRgf0YY=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
Expand Down Expand Up @@ -485,6 +485,7 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5 h1:rxKZ2gOnYxjfmakvUUqh9Gyb6KXfrj7JWTxORTYqb0E=
golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
Expand Down
2 changes: 1 addition & 1 deletion indexer/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ func (i *index) GetContainerRange(startIndex, numToFetch uint64) ([]Container, e
}

// Calculate the last index we will fetch
lastIndex := math.Min64(startIndex+numToFetch-1, lastAcceptedIndex)
lastIndex := math.Min(startIndex+numToFetch-1, lastAcceptedIndex)
// [lastIndex] is always >= [startIndex] so this is safe.
// [numToFetch] is limited to [MaxFetchedByRange] so [containers] is bounded in size.
containers := make([]Container, int(lastIndex)-int(startIndex)+1)
Expand Down
10 changes: 5 additions & 5 deletions network/throttling/inbound_msg_byte_throttler.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func (t *inboundMsgByteThrottler) Acquire(ctx context.Context, msgSize uint64, n
}

// Take as many bytes as we can from the at-large allocation.
atLargeBytesUsed := math.Min64(
atLargeBytesUsed := math.Min(
// only give as many bytes as needed
metadata.bytesNeeded,
// don't exceed per-node limit
Expand Down Expand Up @@ -143,7 +143,7 @@ func (t *inboundMsgByteThrottler) Acquire(ctx context.Context, msgSize uint64, n
} else {
vdrBytesAllowed -= vdrBytesAlreadyUsed
}
vdrBytesUsed := math.Min64(t.remainingVdrBytes, metadata.bytesNeeded, vdrBytesAllowed)
vdrBytesUsed := math.Min(t.remainingVdrBytes, metadata.bytesNeeded, vdrBytesAllowed)
if vdrBytesUsed > 0 {
// Mark that [nodeID] used [vdrBytesUsed] from its validator allocation
t.nodeToVdrBytesUsed[nodeID] += vdrBytesUsed
Expand Down Expand Up @@ -204,7 +204,7 @@ func (t *inboundMsgByteThrottler) release(metadata *msgMetadata, nodeID ids.Node
// or messages from [nodeID] currently waiting to acquire bytes.
vdrBytesUsed := t.nodeToVdrBytesUsed[nodeID]
releasedBytes := metadata.msgSize - metadata.bytesNeeded
vdrBytesToReturn := math.Min64(releasedBytes, vdrBytesUsed)
vdrBytesToReturn := math.Min(releasedBytes, vdrBytesUsed)

// [atLargeBytesToReturn] is the number of bytes from [msgSize]
// that will be given to the at-large allocation or a message
Expand All @@ -227,7 +227,7 @@ func (t *inboundMsgByteThrottler) release(metadata *msgMetadata, nodeID ids.Node
msg := iter.Value()
// From the at-large allocation, take the maximum number of bytes
// without exceeding the per-node limit on taking from at-large pool.
atLargeBytesGiven := math.Min64(
atLargeBytesGiven := math.Min(
// don't give [msg] too many bytes
msg.bytesNeeded,
// don't exceed per-node limit
Expand Down Expand Up @@ -260,7 +260,7 @@ func (t *inboundMsgByteThrottler) release(metadata *msgMetadata, nodeID ids.Node
msg, exists := t.waitingToAcquire.Get(msgID)
if exists {
// Give [msg] all the bytes we can
bytesToGive := math.Min64(msg.bytesNeeded, vdrBytesToReturn)
bytesToGive := math.Min(msg.bytesNeeded, vdrBytesToReturn)
msg.bytesNeeded -= bytesToGive
vdrBytesToReturn -= bytesToGive
if msg.bytesNeeded == 0 {
Expand Down
6 changes: 3 additions & 3 deletions network/throttling/outbound_msg_throttler.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func (t *outboundMsgThrottler) Acquire(msg message.OutboundMessage, nodeID ids.N

// Take as many bytes as we can from the at-large allocation.
bytesNeeded := uint64(len(msg.Bytes()))
atLargeBytesUsed := math.Min64(
atLargeBytesUsed := math.Min(
// only give as many bytes as needed
bytesNeeded,
// don't exceed per-node limit
Expand All @@ -99,7 +99,7 @@ func (t *outboundMsgThrottler) Acquire(msg message.OutboundMessage, nodeID ids.N
} else {
vdrBytesAllowed -= vdrBytesAlreadyUsed
}
vdrBytesUsed := math.Min64(t.remainingVdrBytes, bytesNeeded, vdrBytesAllowed)
vdrBytesUsed := math.Min(t.remainingVdrBytes, bytesNeeded, vdrBytesAllowed)
bytesNeeded -= vdrBytesUsed
if bytesNeeded != 0 {
// Can't acquire enough bytes to queue this message to be sent
Expand Down Expand Up @@ -142,7 +142,7 @@ func (t *outboundMsgThrottler) Release(msg message.OutboundMessage, nodeID ids.N
// that will be given back to [nodeID]'s validator allocation.
vdrBytesUsed := t.nodeToVdrBytesUsed[nodeID]
msgSize := uint64(len(msg.Bytes()))
vdrBytesToReturn := math.Min64(msgSize, vdrBytesUsed)
vdrBytesToReturn := math.Min(msgSize, vdrBytesUsed)
t.nodeToVdrBytesUsed[nodeID] -= vdrBytesToReturn
if t.nodeToVdrBytesUsed[nodeID] == 0 {
delete(t.nodeToVdrBytesUsed, nodeID)
Expand Down
2 changes: 1 addition & 1 deletion node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ func (b *beaconManager) Disconnected(vdrID ids.NodeID) {
// weight can become disconnected. Because it is possible that there are
// changes to the validators set, we utilize that Sub64 returns 0 on
// error.
b.totalWeight, _ = math.Sub64(b.totalWeight, weight)
b.totalWeight, _ = math.Sub(b.totalWeight, weight)
}
b.Router.Disconnected(vdrID)
}
Expand Down
2 changes: 1 addition & 1 deletion scripts/versions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@

# Set up the versions to be used
# Don't export them as their used in the context of other calls
coreth_version=${CORETH_VERSION:-'v0.11.1-rc.1'}
coreth_version=${CORETH_VERSION:-'v0.11.1-rc.2'}
2 changes: 1 addition & 1 deletion snow/engine/avalanche/state/serializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func (s *Serializer) buildVtx(
if err != nil {
return nil, err
}
height = math.Max64(height, childHeight)
height = math.Max(height, childHeight)
}

var (
Expand Down
4 changes: 2 additions & 2 deletions snow/validators/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ func (s *set) removeWeight(vdrID ids.NodeID, weight uint64) error {
vdr := s.vdrSlice[i]

oldWeight := s.vdrWeights[i]
weight = safemath.Min64(oldWeight, weight)
weight = safemath.Min(oldWeight, weight)
s.vdrWeights[i] -= weight
vdr.removeWeight(weight)
if !s.maskedVdrs.Contains(vdrID) {
Expand Down Expand Up @@ -367,7 +367,7 @@ func (s *set) remove(vdrID ids.NodeID) error {
s.vdrMaskedWeights = s.vdrMaskedWeights[:e]

if !s.maskedVdrs.Contains(vdrID) {
newTotalWeight, err := safemath.Sub64(s.totalWeight, iElem.Weight())
newTotalWeight, err := safemath.Sub(s.totalWeight, iElem.Weight())
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion snow/validators/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (v *validator) addWeight(weight uint64) {
}

func (v *validator) removeWeight(weight uint64) {
newTotalWeight, err := safemath.Sub64(v.weight, weight)
newTotalWeight, err := safemath.Sub(v.weight, weight)
if err != nil {
newTotalWeight = 0
}
Expand Down
38 changes: 19 additions & 19 deletions utils/math/safe_math.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ package math
import (
"errors"
"math"

"golang.org/x/exp/constraints"

"github.com/ava-labs/avalanchego/utils"
)

var errOverflow = errors.New("overflow occurred")

// Max64 returns the maximum of the values provided
func Max64(max uint64, nums ...uint64) uint64 {
func Max[T constraints.Ordered](max T, nums ...T) T {
for _, num := range nums {
if num > max {
max = num
Expand All @@ -20,18 +23,7 @@ func Max64(max uint64, nums ...uint64) uint64 {
return max
}

// Min returns the minimum of the values provided
func Min(min int, nums ...int) int {
for _, num := range nums {
if num < min {
min = num
}
}
return min
}

// Min64 returns the minimum of the values provided
func Min64(min uint64, nums ...uint64) uint64 {
func Min[T constraints.Ordered](min T, nums ...T) T {
for _, num := range nums {
if num < min {
min = num
Expand All @@ -43,33 +35,41 @@ func Min64(min uint64, nums ...uint64) uint64 {
// Add64 returns:
// 1) a + b
// 2) If there is overflow, an error
//
// Note that we don't have a generic Add function because checking for
// an overflow requires knowing the max size of a given type, which we
// don't know if we're adding generic types.
func Add64(a, b uint64) (uint64, error) {
if a > math.MaxUint64-b {
return 0, errOverflow
}
return a + b, nil
}

// Sub64 returns:
// Sub returns:
// 1) a - b
// 2) If there is underflow, an error
func Sub64(a, b uint64) (uint64, error) {
func Sub[T constraints.Unsigned](a, b T) (T, error) {
if a < b {
return 0, errOverflow
return utils.Zero[T](), errOverflow
}
return a - b, nil
}

// Mul64 returns:
// 1) a * b
// 2) If there is overflow, an error
//
// Note that we don't have a generic Mul function because checking for
// an overflow requires knowing the max size of a given type, which we
// don't know if we're adding generic types.
func Mul64(a, b uint64) (uint64, error) {
if b != 0 && a > math.MaxUint64/b {
return 0, errOverflow
}
return a * b, nil
}

func Diff64(a, b uint64) uint64 {
return Max64(a, b) - Min64(a, b)
func AbsDiff[T constraints.Unsigned](a, b T) T {
return Max(a, b) - Min(a, b)
}
Loading

0 comments on commit 32040ca

Please sign in to comment.