Skip to content

Commit

Permalink
feat: adding SubmitOptions to Submit (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
distractedm1nd authored Jan 23, 2024
1 parent fd02dcb commit d853a41
Show file tree
Hide file tree
Showing 7 changed files with 348 additions and 86 deletions.
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")})
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

0 comments on commit d853a41

Please sign in to comment.