-
Notifications
You must be signed in to change notification settings - Fork 302
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
ValidateAvailability implementation #270
Changes from 43 commits
3c24d62
1f12d6b
d8f9190
1a5f9e3
b69c0af
6dff524
25a521d
e692b0e
0d6b0f5
e4be5d4
1b2335a
28c6dee
ca8c5b2
cc7b7c4
0b8c2ca
baf2fcc
af6a815
d10e141
60afd13
4199979
bb7fd2f
f5677be
152bb82
98e1d72
ffe1719
92e4132
eba479b
0879f7a
43d420b
0510c67
69a7037
48360ca
20d4c19
50b691e
b44b303
b1276a0
ad4e5b5
cef85c7
7171843
ac324ec
cf64d14
d93f9b7
23c9d06
63e5acb
b517a38
adac1fb
0d7669e
d2fede3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package ipld | ||
|
||
import ( | ||
"math/rand" | ||
|
||
"github.com/ipfs/go-cid" | ||
"github.com/lazyledger/nmt/namespace" | ||
|
||
"github.com/lazyledger/lazyledger-core/p2p/ipld/plugin/nodes" | ||
"github.com/lazyledger/lazyledger-core/types" | ||
) | ||
|
||
// Sample is a point in 2D space over square. | ||
type Sample struct { | ||
Row, Col uint32 | ||
} | ||
|
||
// SampleSquare randomly picks *num* unique points from arbitrary *width* square | ||
// and returns them as samples. | ||
func SampleSquare(squareWidth uint32, num int) []Sample { | ||
ss := newSquareSampler(squareWidth, num) | ||
ss.sample(num) | ||
return ss.samples() | ||
} | ||
|
||
// Leaf returns leaf info needed for retrieval using data provided with DAHeader. | ||
func (s Sample) Leaf(dah *types.DataAvailabilityHeader) (cid.Cid, uint32, error) { | ||
var ( | ||
leaf uint32 | ||
root namespace.IntervalDigest | ||
) | ||
|
||
// spread leaves retrieval from both Row and Column roots | ||
if rand.Intn(2) == 0 { | ||
root = dah.ColumnRoots[s.Col] | ||
leaf = s.Row | ||
} else { | ||
root = dah.RowsRoots[s.Row] | ||
leaf = s.Col | ||
} | ||
|
||
rootCid, err := nodes.CidFromNamespacedSha256(root.Bytes()) | ||
if err != nil { | ||
return cid.Undef, 0, err | ||
} | ||
|
||
return rootCid, leaf, nil | ||
} | ||
|
||
// Equals check whenever to samples are equal. | ||
func (s Sample) Equals(to Sample) bool { | ||
return s.Row == to.Row && s.Col == to.Col | ||
} | ||
evan-forbes marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
type squareSampler struct { | ||
squareWidth uint32 | ||
smpls map[Sample]struct{} | ||
} | ||
|
||
func newSquareSampler(squareWidth uint32, expectedSamples int) *squareSampler { | ||
return &squareSampler{ | ||
squareWidth: squareWidth, | ||
smpls: make(map[Sample]struct{}, expectedSamples), | ||
} | ||
} | ||
|
||
func (ss *squareSampler) sample(num int) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Optional: I think the name There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't agree here. Generate sound like producing something imho, also from the name There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
We are producing something: random numbers which comprise |
||
if uint32(num) > ss.squareWidth*ss.squareWidth { | ||
panic("number of samples must be less than square width") | ||
} | ||
|
||
done := 0 | ||
for done < num { | ||
s := Sample{ | ||
Row: uint32(rand.Int31n(int32(ss.squareWidth))), | ||
Col: uint32(rand.Int31n(int32(ss.squareWidth))), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See the comment above on the used crypto library. I just double-checked: so this is essentially a math/rand object initialized with a crypto/rand seed. Also, the library is thread-safe which we do not really care about here as we generate these sequentially anyways. IMO, we should use crypto/rand instead. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I used There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, I assumed that we don't need to have extraordinary seed generation as we verify the validity for ourselves only, but linter seems to complain There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, we want to use crypto/rand here. Not math/rand. |
||
} | ||
|
||
if _, ok := ss.smpls[s]; ok { | ||
continue | ||
} | ||
|
||
done++ | ||
ss.smpls[s] = struct{}{} | ||
} | ||
} | ||
|
||
func (ss *squareSampler) samples() []Sample { | ||
samples := make([]Sample, 0, len(ss.smpls)) | ||
for s := range ss.smpls { | ||
samples = append(samples, s) | ||
} | ||
return samples | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package ipld | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestSampleSquare(t *testing.T) { | ||
tests := []struct { | ||
width uint32 | ||
samples int | ||
}{ | ||
{width: 10, samples: 5}, | ||
{width: 500, samples: 90}, | ||
} | ||
|
||
for _, tt := range tests { | ||
ss := SampleSquare(tt.width, tt.samples) | ||
assert.Len(t, ss, tt.samples) | ||
// check points are within width | ||
for _, s := range ss { | ||
assert.Less(t, s.Row, tt.width) | ||
assert.Less(t, s.Col, tt.width) | ||
} | ||
// checks samples are not equal | ||
for i, s1 := range ss { | ||
for j, s2 := range ss { | ||
if i != j { | ||
assert.False(t, s1.Equals(s2)) | ||
} | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use crypto/rand.