Skip to content

Commit

Permalink
Merge branch 'main' into issues/141/scaffold_proof_type
Browse files Browse the repository at this point in the history
  • Loading branch information
Olshansk committed Nov 20, 2023
2 parents fef0851 + 32513b8 commit cd58d0f
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 10 deletions.
4 changes: 2 additions & 2 deletions pkg/relayer/miner/miner.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ var (
// TODO_BLOCKER: query on-chain governance params once available.
// Setting this to 0 to effectively disables mining for now.
// I.e., all relays are added to the tree.
defaultRelayDifficulty = 0
defaultRelayDifficultyBits = 0
)

// Miner is responsible for observing servedRelayObs, hashing and checking the
Expand Down Expand Up @@ -107,7 +107,7 @@ func (mnr *miner) mapMineRelay(
relayHash := mnr.hash(relayBz)

// The relay IS NOT volume / reward applicable
if !protocol.BytesDifficultyGreaterThan(relayHash, defaultRelayDifficulty) {
if protocol.MustCountDifficultyBits(relayHash) < defaultRelayDifficultyBits {
return either.Success[*relayer.MinedRelay](nil), true
}

Expand Down
41 changes: 33 additions & 8 deletions pkg/relayer/protocol/difficulty.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,42 @@
package protocol

import (
"encoding/hex"
"strings"
"math/bits"
)

// TODO_BLOCKER: Revisit this part of the algorithm after initial TestNet Launch.
// TODO_TEST: Add extensive tests for the core relay mining business logic.
// BytesDifficultyGreaterThan determines if the bytes exceed a certain difficulty, and it
// is used to determine if a relay is volume applicable. See the spec for more details: https://github.com/pokt-network/pocket-network-protocol
func BytesDifficultyGreaterThan(bz []byte, compDifficultyBytes int) bool {
hexZerosPrefix := strings.Repeat("0", compDifficultyBytes*2) // 2 hex chars per byte.
hexBz := hex.EncodeToString(bz)

return strings.HasPrefix(hexBz, hexZerosPrefix)
// MustCountDifficultyBits returns the number of leading zero bits in the given
// byte slice. It panics if an error is encountered.
func MustCountDifficultyBits(bz []byte) int {
diff, err := CountDifficultyBits(bz)
if err != nil {
panic(err)
}

return diff
}

// CountDifficultyBits returns the number of leading zero bits in the given byte
// slice. It returns an error if the byte slice is all zero bits.
func CountDifficultyBits(bz []byte) (int, error) {
bzLen := len(bz)

var zeroBits int
for byteIdx, byteValue := range bz {
if byteValue != 0 {
zeroBits = bits.LeadingZeros8(byteValue)
if zeroBits == 8 {
// we already checked that byteValue != 0.
return 0, ErrDifficulty.Wrap("impossible code path")
}

// We have byteIdx bytes that are all 0s and one byte that has
// zeroBits number of leading 0 bits.
return (byteIdx)*8 + zeroBits, nil
}
}

return 0, ErrDifficulty.Wrapf("difficulty matches bytes length: %d; bytes (hex): % x", bzLen, bz)
}
56 changes: 56 additions & 0 deletions pkg/relayer/protocol/difficulty_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package protocol_test

import (
"fmt"
"testing"

"github.com/stretchr/testify/require"

"github.com/pokt-network/poktroll/pkg/relayer/protocol"
)

func TestCountDifficultyBits(t *testing.T) {
tests := []struct {
bz []byte
difficulty int
}{
{
bz: []byte{0b11111111, 255, 255, 255},
difficulty: 0,
},
{
bz: []byte{0b01111111, 255, 255, 255},
difficulty: 1,
},
{
bz: []byte{0, 255, 255, 255},
difficulty: 8,
},
{
bz: []byte{0, 0b01111111, 255, 255},
difficulty: 9,
},
{
bz: []byte{0, 0b00111111, 255, 255},
difficulty: 10,
},
{
bz: []byte{0, 0, 255, 255},
difficulty: 16,
},
}

for _, tt := range tests {
t.Run(fmt.Sprintf("difficulty_%d_zero_bits", tt.difficulty), func(t *testing.T) {
actualDifficulty, err := protocol.CountDifficultyBits(tt.bz)
require.NoError(t, err)
require.Equal(t, tt.difficulty, actualDifficulty)
})
}
}

func TestCountDifficultyBits_Error(t *testing.T) {
_, err := protocol.CountDifficultyBits([]byte{0, 0, 0, 0})
require.ErrorIs(t, err, protocol.ErrDifficulty)
require.ErrorContains(t, err, "difficulty matches bytes length")
}
8 changes: 8 additions & 0 deletions pkg/relayer/protocol/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package protocol

import errorsmod "cosmossdk.io/errors"

var (
ErrDifficulty = errorsmod.New(codespace, 1, "difficulty error")
codespace = "relayer/protocol"
)

0 comments on commit cd58d0f

Please sign in to comment.