Skip to content
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

feat: adding SubmitOptions to Submit #34

Merged
merged 1 commit into from
Jan 23, 2024
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
12 changes: 11 additions & 1 deletion da.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,22 @@ type DA interface {
// This method is synchronous. Upon successful submission to Data Availability layer, it returns ID identifying blob
// in DA and Proof of inclusion.
// If options is nil, default options are used.
Submit(ctx context.Context, blobs []Blob, gasPrice float64) ([]ID, []Proof, error)
Submit(ctx context.Context, blobs []Blob, opts *SubmitOptions) ([]ID, []Proof, error)

// Validate validates Commitments against the corresponding Proofs. This should be possible without retrieving the Blobs.
Validate(ctx context.Context, ids []ID, proofs []Proof) ([]bool, error)
}

// SubmitOptions are the parameters used for blob submission.
type SubmitOptions struct {
GasPrice float64
Namespace Namespace
}

// Namespace is an optional parameter used to set the location a blob should be
// posted to, for DA layers supporting the functionality.
type Namespace = []byte

// Blob is the data submitted/received from DA interface.
type Blob = []byte

Expand Down
6 changes: 6 additions & 0 deletions proto/da/da.proto
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ service DAService {
rpc Validate(ValidateRequest) returns (ValidateResponse) {}
}

// Namespace is the location for the blob to be submitted to, if supported by the DA layer.
message Namespace {
bytes value = 1;
}

// Blob is the data submitted/received from DA interface.
message Blob {
bytes value = 1;
Expand Down Expand Up @@ -85,6 +90,7 @@ message CommitResponse {
message SubmitRequest {
repeated Blob blobs = 1;
double gas_price = 2;
Namespace namespace = 3;
}

// SubmitResponse is the response type for the Submit rpc method.
Expand Down
7 changes: 4 additions & 3 deletions proxy/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,11 @@ func (c *Client) Commit(ctx context.Context, blobs []da.Blob) ([]da.Commitment,
}

// Submit submits the Blobs to Data Availability layer.
func (c *Client) Submit(ctx context.Context, blobs []da.Blob, gasPrice float64) ([]da.ID, []da.Proof, error) {
func (c *Client) Submit(ctx context.Context, blobs []da.Blob, opts *da.SubmitOptions) ([]da.ID, []da.Proof, error) {
req := &pbda.SubmitRequest{
Blobs: blobsDA2PB(blobs),
GasPrice: gasPrice,
Blobs: blobsDA2PB(blobs),
GasPrice: opts.GasPrice,
Namespace: &pbda.Namespace{Value: opts.Namespace},
}

resp, err := c.client.Submit(ctx, req)
Expand Down
5 changes: 4 additions & 1 deletion proxy/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ func (p *proxySrv) Commit(ctx context.Context, request *pbda.CommitRequest) (*pb
func (p *proxySrv) Submit(ctx context.Context, request *pbda.SubmitRequest) (*pbda.SubmitResponse, error) {
blobs := blobsPB2DA(request.Blobs)

ids, proofs, err := p.target.Submit(ctx, blobs, request.GasPrice)
ids, proofs, err := p.target.Submit(ctx, blobs, &da.SubmitOptions{
GasPrice: request.GasPrice,
Namespace: request.Namespace.GetValue(),
})
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion test/dummy.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (d *DummyDA) Commit(ctx context.Context, blobs []da.Blob) ([]da.Commitment,
}

// Submit stores blobs in DA layer.
func (d *DummyDA) Submit(ctx context.Context, blobs []da.Blob, gasPrice float64) ([]da.ID, []da.Proof, error) {
func (d *DummyDA) Submit(ctx context.Context, blobs []da.Blob, opts *da.SubmitOptions) ([]da.ID, []da.Proof, error) {
d.mu.Lock()
defer d.mu.Unlock()
ids := make([]da.ID, len(blobs))
Expand Down
65 changes: 36 additions & 29 deletions test/test_suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,72 +28,73 @@ func RunDATestSuite(t *testing.T, d da.DA) {
})
}

// TODO(tzdybal): how to get rid of those aliases?

// Blob is a type alias
type Blob = da.Blob

// ID is a type alias
type ID = da.ID

// BasicDATest tests round trip of messages to DA and back.
func BasicDATest(t *testing.T, da da.DA) {
func BasicDATest(t *testing.T, d da.DA) {
msg1 := []byte("message 1")
msg2 := []byte("message 2")

ctx := context.TODO()
id1, proof1, err := da.Submit(ctx, []Blob{msg1}, -1)
id1, proof1, err := d.Submit(ctx, []da.Blob{msg1}, &da.SubmitOptions{
GasPrice: 0,
Namespace: []byte{9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
})
assert.NoError(t, err)
assert.NotEmpty(t, id1)
assert.NotEmpty(t, proof1)

id2, proof2, err := da.Submit(ctx, []Blob{msg2}, -1)
id2, proof2, err := d.Submit(ctx, []da.Blob{msg2}, &da.SubmitOptions{
GasPrice: 0,
Namespace: []byte{9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
})
assert.NoError(t, err)
assert.NotEmpty(t, id2)
assert.NotEmpty(t, proof2)

id3, proof3, err := da.Submit(ctx, []Blob{msg1}, -1)
id3, proof3, err := d.Submit(ctx, []da.Blob{msg1}, &da.SubmitOptions{
GasPrice: 0,
Namespace: []byte{9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
})
assert.NoError(t, err)
assert.NotEmpty(t, id3)
assert.NotEmpty(t, proof3)

assert.NotEqual(t, id1, id2)
assert.NotEqual(t, id1, id3)

ret, err := da.Get(ctx, id1)
ret, err := d.Get(ctx, id1)
assert.NoError(t, err)
assert.Equal(t, []Blob{msg1}, ret)
assert.Equal(t, []da.Blob{msg1}, ret)

commitment1, err := da.Commit(ctx, []Blob{msg1})
commitment1, err := d.Commit(ctx, []da.Blob{msg1})
assert.NoError(t, err)
assert.NotEmpty(t, commitment1)

commitment2, err := da.Commit(ctx, []Blob{msg2})
commitment2, err := d.Commit(ctx, []da.Blob{msg2})
assert.NoError(t, err)
assert.NotEmpty(t, commitment2)

oks, err := da.Validate(ctx, id1, proof1)
oks, err := d.Validate(ctx, id1, proof1)
assert.NoError(t, err)
assert.NotEmpty(t, oks)
for _, ok := range oks {
assert.True(t, ok)
}

oks, err = da.Validate(ctx, id2, proof2)
oks, err = d.Validate(ctx, id2, proof2)
assert.NoError(t, err)
assert.NotEmpty(t, oks)
for _, ok := range oks {
assert.True(t, ok)
}

oks, err = da.Validate(ctx, id1, proof2)
oks, err = d.Validate(ctx, id1, proof2)
assert.NoError(t, err)
assert.NotEmpty(t, oks)
for _, ok := range oks {
assert.False(t, ok)
}

oks, err = da.Validate(ctx, id2, proof1)
oks, err = d.Validate(ctx, id2, proof1)
assert.NoError(t, err)
assert.NotEmpty(t, oks)
for _, ok := range oks {
Expand All @@ -102,19 +103,22 @@ func BasicDATest(t *testing.T, da da.DA) {
}

// CheckErrors ensures that errors are handled properly by DA.
func CheckErrors(t *testing.T, da da.DA) {
func CheckErrors(t *testing.T, d da.DA) {
ctx := context.TODO()
blob, err := da.Get(ctx, []ID{[]byte("invalid")})
blob, err := d.Get(ctx, []da.ID{[]byte("invalid")})
nashqueue marked this conversation as resolved.
Show resolved Hide resolved
assert.Error(t, err)
assert.Empty(t, blob)
}

// GetIDsTest tests iteration over DA
func GetIDsTest(t *testing.T, da da.DA) {
func GetIDsTest(t *testing.T, d da.DA) {
msgs := [][]byte{[]byte("msg1"), []byte("msg2"), []byte("msg3")}

ctx := context.TODO()
ids, proofs, err := da.Submit(ctx, msgs, -1)
ids, proofs, err := d.Submit(ctx, msgs, &da.SubmitOptions{
GasPrice: 0,
Namespace: []byte{9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
})
assert.NoError(t, err)
assert.Len(t, ids, len(msgs))
assert.Len(t, proofs, len(msgs))
Expand All @@ -126,12 +130,12 @@ func GetIDsTest(t *testing.T, da da.DA) {
// As we're the only user, we don't need to handle external data (that could be submitted in real world).
// There is no notion of height, so we need to scan the DA to get test data back.
for i := uint64(1); !found && !time.Now().After(end); i++ {
ret, err := da.GetIDs(ctx, i)
ret, err := d.GetIDs(ctx, i)
if err != nil {
t.Error("failed to get IDs:", err)
}
if len(ret) > 0 {
blobs, err := da.Get(ctx, ret)
blobs, err := d.Get(ctx, ret)
assert.NoError(t, err)

// Submit ensures atomicity of batch, so it makes sense to compare actual blobs (bodies) only when lengths
Expand All @@ -151,7 +155,7 @@ func GetIDsTest(t *testing.T, da da.DA) {
}

// ConcurrentReadWriteTest tests the use of mutex lock in DummyDA by calling separate methods that use `d.data` and making sure there's no race conditions
func ConcurrentReadWriteTest(t *testing.T, da da.DA) {
func ConcurrentReadWriteTest(t *testing.T, d da.DA) {
var wg sync.WaitGroup
wg.Add(2)

Expand All @@ -160,15 +164,18 @@ func ConcurrentReadWriteTest(t *testing.T, da da.DA) {
go func() {
defer wg.Done()
for i := uint64(1); i <= 100; i++ {
_, err := da.GetIDs(ctx, i)
_, err := d.GetIDs(ctx, i)
assert.NoError(t, err)
}
}()

go func() {
defer wg.Done()
for i := uint64(1); i <= 100; i++ {
_, _, err := da.Submit(ctx, [][]byte{[]byte("test")}, -1)
_, _, err := d.Submit(ctx, [][]byte{[]byte("test")}, &da.SubmitOptions{
GasPrice: 0,
Namespace: []byte{9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
})
assert.NoError(t, err)
}
}()
Expand Down
Loading