-
Notifications
You must be signed in to change notification settings - Fork 17
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: support encoding and decoding of v1 shares #80
Changes from all commits
7ab5c0b
7657933
5d4b190
f8a8cbf
921b730
cf6c382
5cb0184
487766e
e517232
46e9e0b
a5ae4fe
3f48ebf
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 | ||||
---|---|---|---|---|---|---|
|
@@ -25,9 +25,12 @@ const ProtoIndexWrapperTypeID = "INDX" | |||||
// MaxShareVersion is the maximum value a share version can be. See: [shares.MaxShareVersion]. | ||||||
const MaxShareVersion = 127 | ||||||
|
||||||
// SignerSize is the size of the signer in bytes. | ||||||
const SignerSize = 20 | ||||||
|
||||||
// Blob (stands for binary large object) is a core type that represents data | ||||||
// to be submitted to the Celestia network alongside an accompanying namespace | ||||||
// and optional signer (for proving the signer of the blob) | ||||||
// and optional signer (for proving the author of the blob) | ||||||
type Blob struct { | ||||||
namespace ns.Namespace | ||||||
data []byte | ||||||
|
@@ -37,13 +40,31 @@ type Blob struct { | |||||
|
||||||
// New creates a new coretypes.Blob from the provided data after performing | ||||||
// basic stateless checks over it. | ||||||
func New(ns ns.Namespace, data []byte, shareVersion uint8, signer []byte) *Blob { | ||||||
func New(ns ns.Namespace, data []byte, shareVersion uint8, signer []byte) (*Blob, error) { | ||||||
if shareVersion == 0 && signer != nil { | ||||||
return nil, errors.New("share version 0 does not support signer") | ||||||
} | ||||||
if shareVersion == 1 && len(signer) != SignerSize { | ||||||
return nil, errors.New("share version 1 requires signer of size 20 bytes") | ||||||
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] use the constant defined above
Suggested change
|
||||||
} | ||||||
return &Blob{ | ||||||
namespace: ns, | ||||||
data: data, | ||||||
shareVersion: shareVersion, | ||||||
signer: signer, | ||||||
}, nil | ||||||
} | ||||||
|
||||||
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. [not blocking] 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. Currently we just have this cip: https://github.com/celestiaorg/CIPs/blob/main/cips/cip-21.md But it makes sense to definitely make sure the new blob type is clearly documented. I will need to think about where the best place for that is. We should probably have it mentioned in docs.celestia.org but perhaps we want to have a go.doc or readme.md in the code to explain it. Will just jot this down as an issue so I don't forget 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. Note we have https://celestiaorg.github.io/celestia-app/specs/shares.html#share-version so it probably warrants a mention there (eventually) 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. Good point, I'll add it to the issue |
||||||
func NewV0(ns ns.Namespace, data []byte) *Blob { | ||||||
blob, err := New(ns, data, 0, nil) | ||||||
if err != nil { | ||||||
panic(err) | ||||||
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. this panic kinda scares me. Can a malicious entity provide an invalid v0 namespace to an honest light node or consensus node and cause it to hit this panic? I think it is preferable to bubble up errors from low level code like this and let the application (celestia-app or celestia-node) decide what to do with the error if it encounters one. 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. Currently, the panic is not possible, because the namespace is encapsulated so we know it's valid and there's not a signer that could be of an invalid length. However since there could be changes in the future that could make errors acceptable, I think you're right and I will switch this to being an error |
||||||
} | ||||||
return blob | ||||||
} | ||||||
|
||||||
func NewV1(ns ns.Namespace, data []byte, signer []byte) (*Blob, error) { | ||||||
return New(ns, data, 1, signer) | ||||||
} | ||||||
|
||||||
// NewFromProto creates a Blob from the proto format and performs | ||||||
|
@@ -62,12 +83,12 @@ func NewFromProto(pb *BlobProto) (*Blob, error) { | |||||
if err != nil { | ||||||
return nil, fmt.Errorf("invalid namespace: %w", err) | ||||||
} | ||||||
return &Blob{ | ||||||
namespace: ns, | ||||||
data: pb.Data, | ||||||
shareVersion: uint8(pb.ShareVersion), | ||||||
signer: pb.Signer, | ||||||
}, nil | ||||||
return New( | ||||||
ns, | ||||||
pb.Data, | ||||||
uint8(pb.ShareVersion), | ||||||
pb.Signer, | ||||||
) | ||||||
} | ||||||
|
||||||
// Namespace returns the namespace of the blob | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -72,6 +72,7 @@ func TestCreateCommitment(t *testing.T) { | |
expected []byte | ||
expectErr bool | ||
shareVersion uint8 | ||
signer []byte | ||
} | ||
tests := []test{ | ||
{ | ||
|
@@ -81,6 +82,14 @@ func TestCreateCommitment(t *testing.T) { | |
expected: []byte{0x31, 0xf5, 0x15, 0x6d, 0x5d, 0xb9, 0xa7, 0xf5, 0xb4, 0x3b, 0x29, 0x7a, 0x14, 0xc0, 0x70, 0xc2, 0xcc, 0x4e, 0xf3, 0xd6, 0x9d, 0x87, 0xed, 0x8, 0xad, 0xdd, 0x21, 0x6d, 0x9b, 0x9f, 0xa1, 0x18}, | ||
shareVersion: shares.ShareVersionZero, | ||
}, | ||
{ | ||
name: "blob of one share with signer succeeds", | ||
namespace: ns1, | ||
blob: bytes.Repeat([]byte{0xFF}, shares.AvailableBytesFromSparseShares(2)-blob.SignerSize), | ||
expected: []byte{0x88, 0x3c, 0x74, 0x6, 0x4e, 0x8e, 0x26, 0x27, 0xad, 0x58, 0x8, 0x38, 0x9f, 0x1f, 0x19, 0x24, 0x19, 0x4c, 0x1a, 0xe2, 0x3c, 0x7d, 0xf9, 0x62, 0xc8, 0xd5, 0x6d, 0xf0, 0x62, 0xa9, 0x2b, 0x2b}, | ||
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. [not blocking] |
||
shareVersion: shares.ShareVersionOne, | ||
signer: bytes.Repeat([]byte{1}, blob.SignerSize), | ||
}, | ||
{ | ||
name: "blob with unsupported share version should return error", | ||
namespace: ns1, | ||
|
@@ -91,7 +100,8 @@ func TestCreateCommitment(t *testing.T) { | |
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
blob := blob.New(tt.namespace, tt.blob, tt.shareVersion, nil) | ||
blob, err := blob.New(tt.namespace, tt.blob, tt.shareVersion, tt.signer) | ||
require.NoError(t, err) | ||
res, err := inclusion.CreateCommitment(blob, twoLeafMerkleRoot, defaultSubtreeRootThreshold) | ||
if tt.expectErr { | ||
assert.Error(t, err) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -168,6 +168,17 @@ func (b *Builder) WriteSequenceLen(sequenceLen uint32) error { | |
return nil | ||
} | ||
|
||
// WriteSigner writes the signer's information to the share. | ||
func (b *Builder) WriteSigner(signer []byte) { | ||
// only write the signer if it is the first share and the share version is 1 | ||
if b == nil || !b.isFirstShare || b.shareVersion != ShareVersionOne { | ||
return | ||
} | ||
// NOTE: we don't check whether previous data has already been expected | ||
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. [nit] 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. I think instead I want to make an assertion about the size of the |
||
// like the sequence length (we just assume it has) | ||
b.rawShareData = append(b.rawShareData, signer...) | ||
} | ||
|
||
// FlipSequenceStart flips the sequence start indicator of the share provided | ||
func (b *Builder) FlipSequenceStart() { | ||
infoByteIndex := b.indexOfInfoBytes() | ||
|
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.
[nit] I think this was accidental b/c we renamed it to signer in a different PR