From bf7b8cc27550b038a0cc7af05710ea3cd5bb96f5 Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Tue, 11 Jun 2024 14:56:55 +0200 Subject: [PATCH 1/8] feat!: modify namespace type to simple bytes field --- .gitignore | 2 ++ blob/blob.go | 15 +++++----- inclusion/commitment.go | 5 +++- inclusion/commitment_test.go | 4 +-- namespace/consts.go | 6 ++-- namespace/namespace.go | 44 ++++++++++++++-------------- namespace/namespace_test.go | 55 ++++++++--------------------------- namespace/random_blob.go | 2 +- shares/split_sparse_shares.go | 5 +++- square/builder.go | 6 ++-- 10 files changed, 60 insertions(+), 84 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d1147c6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +go.work +go.work.sum \ No newline at end of file diff --git a/blob/blob.go b/blob/blob.go index d3569e4..da71ca3 100644 --- a/blob/blob.go +++ b/blob/blob.go @@ -30,19 +30,16 @@ const MaxShareVersion = 127 // basic stateless checks over it. func New(ns namespace.Namespace, blob []byte, shareVersion uint8) *Blob { return &Blob{ - NamespaceId: ns.ID, + NamespaceId: ns.ID(), Data: blob, ShareVersion: uint32(shareVersion), - NamespaceVersion: uint32(ns.Version), + NamespaceVersion: uint32(ns.Version()), } } // Namespace returns the namespace of the blob -func (b *Blob) Namespace() namespace.Namespace { - return namespace.Namespace{ - Version: uint8(b.NamespaceVersion), - ID: b.NamespaceId, - } +func (b *Blob) Namespace() (namespace.Namespace, error) { + return namespace.New(uint8(b.NamespaceVersion), b.NamespaceId) } // Validate runs a stateless validity check on the form of the struct. @@ -105,7 +102,9 @@ func MarshalBlobTx(tx []byte, blobs ...*Blob) ([]byte, error) { // Sort sorts the blobs by their namespace. func Sort(blobs []*Blob) { sort.SliceStable(blobs, func(i, j int) bool { - return bytes.Compare(blobs[i].Namespace().Bytes(), blobs[j].Namespace().Bytes()) < 0 + ns1 := append([]byte{byte(blobs[i].NamespaceVersion)}, blobs[i].NamespaceId...) + ns2 := append([]byte{byte(blobs[j].NamespaceVersion)}, blobs[j].NamespaceId...) + return bytes.Compare(ns1, ns2) < 0 }) } diff --git a/inclusion/commitment.go b/inclusion/commitment.go index d84b4e2..4583dcf 100644 --- a/inclusion/commitment.go +++ b/inclusion/commitment.go @@ -20,7 +20,10 @@ func CreateCommitment(blob *blob.Blob, merkleRootFn MerkleRootFn, subtreeRootThr if err := blob.Validate(); err != nil { return nil, err } - namespace := blob.Namespace() + namespace, err := blob.Namespace() + if err != nil { + return nil, err + } shares, err := sh.SplitBlobs(blob) if err != nil { diff --git a/inclusion/commitment_test.go b/inclusion/commitment_test.go index 60d9b37..d77d34e 100644 --- a/inclusion/commitment_test.go +++ b/inclusion/commitment_test.go @@ -92,10 +92,10 @@ func TestCreateCommitment(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { blob := &blob.Blob{ - NamespaceId: tt.namespace.ID, + NamespaceId: tt.namespace.ID(), Data: tt.blob, ShareVersion: uint32(tt.shareVersion), - NamespaceVersion: uint32(tt.namespace.Version), + NamespaceVersion: uint32(tt.namespace.Version()), } res, err := inclusion.CreateCommitment(blob, twoLeafMerkleRoot, defaultSubtreeRootThreshold) if tt.expectErr { diff --git a/namespace/consts.go b/namespace/consts.go index bef6573..9cbdda6 100644 --- a/namespace/consts.go +++ b/namespace/consts.go @@ -70,14 +70,12 @@ var ( func primaryReservedNamespace(lastByte byte) Namespace { return Namespace{ - Version: NamespaceVersionZero, - ID: append(bytes.Repeat([]byte{0x00}, NamespaceIDSize-1), lastByte), + data: append([]byte{NamespaceVersionZero}, append(bytes.Repeat([]byte{0x00}, NamespaceIDSize-1), lastByte)...), } } func secondaryReservedNamespace(lastByte byte) Namespace { return Namespace{ - Version: NamespaceVersionMax, - ID: append(bytes.Repeat([]byte{0xFF}, NamespaceIDSize-1), lastByte), + data: append([]byte{NamespaceVersionMax}, append(bytes.Repeat([]byte{0xFF}, NamespaceIDSize-1), lastByte)...), } } diff --git a/namespace/namespace.go b/namespace/namespace.go index f2e6cb6..82bf6d2 100644 --- a/namespace/namespace.go +++ b/namespace/namespace.go @@ -7,8 +7,7 @@ import ( ) type Namespace struct { - Version uint8 - ID []byte + data []byte } // New returns a new namespace with the provided version and id. @@ -23,9 +22,11 @@ func New(version uint8, id []byte) (Namespace, error) { return Namespace{}, err } + data := []byte{version} + data = append(data, id...) + return Namespace{ - Version: version, - ID: id, + data: data, }, nil } @@ -81,7 +82,17 @@ func From(b []byte) (Namespace, error) { // Bytes returns this namespace as a byte slice. func (n Namespace) Bytes() []byte { - return append([]byte{n.Version}, n.ID...) + return n.data +} + +// Version return this namespace's version +func (n Namespace) Version() uint8 { + return n.data[0] +} + +// ID returns this namespace's ID +func (n Namespace) ID() []byte { + return n.data[1:] } // validateVersionSupported returns an error if the version is not supported. @@ -147,7 +158,7 @@ func (n Namespace) Repeat(times int) []Namespace { } func (n Namespace) Equals(n2 Namespace) bool { - return n.Version == n2.Version && bytes.Equal(n.ID, n2.ID) + return bytes.Equal(n.data, n2.data) } func (n Namespace) IsLessThan(n2 Namespace) bool { @@ -167,14 +178,7 @@ func (n Namespace) IsGreaterOrEqualThan(n2 Namespace) bool { } func (n Namespace) Compare(n2 Namespace) int { - switch { - case n.Version == n2.Version: - return bytes.Compare(n.ID, n2.ID) - case n.Version < n2.Version: - return -1 - default: - return 1 - } + return bytes.Compare(n.data, n2.data) } // leftPad returns a new byte slice with the provided byte slice left-padded to the provided size. @@ -190,14 +194,10 @@ func leftPad(b []byte, size int) []byte { // deepCopy returns a deep copy of the Namespace object. func (n Namespace) deepCopy() Namespace { // Create a deep copy of the ID slice - copyID := make([]byte, len(n.ID)) - copy(copyID, n.ID) + copyData := make([]byte, len(n.data)) + copy(copyData, n.data) - // Create a new Namespace object with the copied fields - copyNamespace := Namespace{ - Version: n.Version, - ID: copyID, + return Namespace{ + data: copyData, } - - return copyNamespace } diff --git a/namespace/namespace_test.go b/namespace/namespace_test.go index 0bf5430..783641f 100644 --- a/namespace/namespace_test.go +++ b/namespace/namespace_test.go @@ -32,10 +32,7 @@ func TestNew(t *testing.T) { version: NamespaceVersionZero, id: validID, wantErr: false, - want: Namespace{ - Version: NamespaceVersionZero, - ID: validID, - }, + want: MustNew(NamespaceVersionZero, validID), }, { name: "unsupported version", @@ -76,19 +73,6 @@ func TestNew(t *testing.T) { } } -// TestRepeatNonMutability ensures that the output of Repeat method is not mutated when the original namespace is mutated. -func TestRepeatNonMutability(t *testing.T) { - n := 10 - namespace := Namespace{Version: NamespaceVersionMax, ID: []byte{1, 2, 3, 4}} - repeated := namespace.Repeat(n) - // mutate the original namespace - namespace.ID[0] = 5 - // ensure the repeated namespaces are not mutated - for i := 0; i < n; i++ { - assert.NotEqual(t, repeated[i], namespace) - } -} - func TestNewV0(t *testing.T) { type testCase struct { name string @@ -99,21 +83,15 @@ func TestNewV0(t *testing.T) { testCases := []testCase{ { - name: "valid namespace", - subID: bytes.Repeat([]byte{1}, NamespaceVersionZeroIDSize), - want: Namespace{ - Version: NamespaceVersionZero, - ID: append(NamespaceVersionZeroPrefix, bytes.Repeat([]byte{1}, NamespaceVersionZeroIDSize)...), - }, + name: "valid namespace", + subID: bytes.Repeat([]byte{1}, NamespaceVersionZeroIDSize), + want: MustNew(NamespaceVersionZero, append(NamespaceVersionZeroPrefix, bytes.Repeat([]byte{1}, NamespaceVersionZeroIDSize)...)), wantErr: false, }, { - name: "left pads subID if too short", - subID: []byte{1, 2, 3, 4}, - want: Namespace{ - Version: NamespaceVersionZero, - ID: append(NamespaceVersionZeroPrefix, []byte{0, 0, 0, 0, 0, 0, 1, 2, 3, 4}...), - }, + name: "left pads subID if too short", + subID: []byte{1, 2, 3, 4}, + want: MustNew(NamespaceVersionZero, append(NamespaceVersionZeroPrefix, []byte{0, 0, 0, 0, 0, 0, 1, 2, 3, 4}...)), wantErr: false, }, { @@ -153,19 +131,13 @@ func TestFrom(t *testing.T) { name: "valid namespace", bytes: validNamespace, wantErr: false, - want: Namespace{ - Version: NamespaceVersionZero, - ID: validID, - }, + want: MustNew(NamespaceVersionZero, validID), }, { name: "parity namespace", bytes: parityNamespace, wantErr: false, - want: Namespace{ - Version: NamespaceVersionMax, - ID: bytes.Repeat([]byte{0xFF}, NamespaceIDSize), - }, + want: MustNew(NamespaceVersionMax, bytes.Repeat([]byte{0xFF}, NamespaceIDSize)), }, { name: "unsupported version", @@ -285,10 +257,7 @@ func TestIsReserved(t *testing.T) { want: true, }, { - ns: Namespace{ - Version: math.MaxUint8, - ID: append(bytes.Repeat([]byte{0xFF}, NamespaceIDSize-1), 1), - }, + ns: MustNew(math.MaxUint8, append(bytes.Repeat([]byte{0xFF}, NamespaceIDSize-1), 1)), want: true, }, } @@ -317,8 +286,8 @@ func Test_compareMethods(t *testing.T) { for _, id1 := range ids { for _, id2 := range ids { testPairs = append(testPairs, [2]Namespace{ - {Version: ver1, ID: id1}, - {Version: ver2, ID: id2}, + MustNew(ver1, id1), + MustNew(ver2, id2), }) } } diff --git a/namespace/random_blob.go b/namespace/random_blob.go index 702e88f..b8ec7a9 100644 --- a/namespace/random_blob.go +++ b/namespace/random_blob.go @@ -32,7 +32,7 @@ func isBlobNamespace(ns Namespace) bool { return false } - if !slices.Contains(SupportedBlobNamespaceVersions, ns.Version) { + if !slices.Contains(SupportedBlobNamespaceVersions, ns.Version()) { return false } diff --git a/shares/split_sparse_shares.go b/shares/split_sparse_shares.go index a84707a..ed6f26b 100644 --- a/shares/split_sparse_shares.go +++ b/shares/split_sparse_shares.go @@ -31,7 +31,10 @@ func (sss *SparseShareSplitter) Write(blob *blob.Blob) error { } rawData := blob.Data - blobNamespace := blob.Namespace() + blobNamespace, err := blob.Namespace() + if err != nil { + return err + } // First share (note by validating the blob we can safely cast the share version to uint8) b, err := NewBuilder(blobNamespace, uint8(blob.ShareVersion), true) diff --git a/square/builder.go b/square/builder.go index 9e5414d..2d4bea6 100644 --- a/square/builder.go +++ b/square/builder.go @@ -13,7 +13,7 @@ import ( "google.golang.org/protobuf/proto" ) -type Builder struct { +type wBuilder struct { // maxSquareSize is the maximum number of rows (or columns) in the original data square maxSquareSize int // currentSize is an overestimate for the number of shares used by this builder. @@ -128,7 +128,9 @@ func (b *Builder) Export() (Square, error) { // of blobs within a namespace because b.Blobs are already ordered by tx // priority. sort.SliceStable(b.Blobs, func(i, j int) bool { - return bytes.Compare(b.Blobs[i].Blob.Namespace().Bytes(), b.Blobs[j].Blob.Namespace().Bytes()) < 0 + ns1 := append([]byte{byte(b.Blobs[i].Blob.NamespaceVersion)}, b.Blobs[i].Blob.NamespaceId...) + ns2 := append([]byte{byte(b.Blobs[j].Blob.NamespaceVersion)}, b.Blobs[j].Blob.NamespaceId...) + return bytes.Compare(ns1, ns2) < 0 }) // write all the regular transactions into compact shares From 283336b79b89da95557f50c818ade897df2146e3 Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Tue, 11 Jun 2024 14:58:30 +0200 Subject: [PATCH 2/8] fix builder --- square/builder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/square/builder.go b/square/builder.go index 2d4bea6..9fea7aa 100644 --- a/square/builder.go +++ b/square/builder.go @@ -13,7 +13,7 @@ import ( "google.golang.org/protobuf/proto" ) -type wBuilder struct { +type Builder struct { // maxSquareSize is the maximum number of rows (or columns) in the original data square maxSquareSize int // currentSize is an overestimate for the number of shares used by this builder. From 8bf0d21e616ed267fe54763d7c1fc1cf7875108c Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Tue, 11 Jun 2024 15:41:03 +0200 Subject: [PATCH 3/8] fix test --- namespace/namespace_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/namespace/namespace_test.go b/namespace/namespace_test.go index 783641f..ef96337 100644 --- a/namespace/namespace_test.go +++ b/namespace/namespace_test.go @@ -277,7 +277,7 @@ func Test_compareMethods(t *testing.T) { } vers := []byte{NamespaceVersionZero, NamespaceVersionMax} - ids := [][]byte{minID, maxID} + ids := [][]byte{append(NamespaceVersionZeroPrefix, minID...), append(NamespaceVersionZeroPrefix, maxID...)} // collect all possible pairs: (ver1 ?? ver2) x (id1 ?? id2) var testPairs [][2]Namespace From baf553f7ba5f54ee998b8f372fd9d7a5baaf4190 Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Wed, 12 Jun 2024 10:51:11 +0200 Subject: [PATCH 4/8] incorporate suggestions from reviewers --- blob/blob.go | 17 +++++++++++++---- namespace/consts.go | 8 ++------ namespace/namespace.go | 39 +++++++++++++++++++++++++++++---------- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/blob/blob.go b/blob/blob.go index da71ca3..f6eb9d6 100644 --- a/blob/blob.go +++ b/blob/blob.go @@ -39,7 +39,14 @@ func New(ns namespace.Namespace, blob []byte, shareVersion uint8) *Blob { // Namespace returns the namespace of the blob func (b *Blob) Namespace() (namespace.Namespace, error) { - return namespace.New(uint8(b.NamespaceVersion), b.NamespaceId) + return namespace.NewFromBytes(b.RawNamespace()) +} + +// Namespace returns the namespace of the blob +func (b *Blob) RawNamespace() []byte { + namespace := []byte{byte(b.NamespaceVersion)} + namespace = append(namespace, b.NamespaceId...) + return namespace } // Validate runs a stateless validity check on the form of the struct. @@ -62,6 +69,10 @@ func (b *Blob) Validate() error { return nil } +func (b *Blob) Compare(other *Blob) int { + return bytes.Compare(b.RawNamespace(), other.RawNamespace()) +} + // UnmarshalBlobTx attempts to unmarshal a transaction into blob transaction. If an // error is thrown, false is returned. func UnmarshalBlobTx(tx []byte) (*BlobTx, bool) { @@ -102,9 +113,7 @@ func MarshalBlobTx(tx []byte, blobs ...*Blob) ([]byte, error) { // Sort sorts the blobs by their namespace. func Sort(blobs []*Blob) { sort.SliceStable(blobs, func(i, j int) bool { - ns1 := append([]byte{byte(blobs[i].NamespaceVersion)}, blobs[i].NamespaceId...) - ns2 := append([]byte{byte(blobs[j].NamespaceVersion)}, blobs[j].NamespaceId...) - return bytes.Compare(ns1, ns2) < 0 + return blobs[i].Compare(blobs[j]) < 0 }) } diff --git a/namespace/consts.go b/namespace/consts.go index 9cbdda6..7f783ff 100644 --- a/namespace/consts.go +++ b/namespace/consts.go @@ -69,13 +69,9 @@ var ( ) func primaryReservedNamespace(lastByte byte) Namespace { - return Namespace{ - data: append([]byte{NamespaceVersionZero}, append(bytes.Repeat([]byte{0x00}, NamespaceIDSize-1), lastByte)...), - } + return newNamespace(NamespaceVersionZero, append(bytes.Repeat([]byte{0x00}, NamespaceIDSize-1), lastByte)) } func secondaryReservedNamespace(lastByte byte) Namespace { - return Namespace{ - data: append([]byte{NamespaceVersionMax}, append(bytes.Repeat([]byte{0xFF}, NamespaceIDSize-1), lastByte)...), - } + return newNamespace(NamespaceVersionMax, append(bytes.Repeat([]byte{0xFF}, NamespaceIDSize-1), lastByte)) } diff --git a/namespace/namespace.go b/namespace/namespace.go index 82bf6d2..270a4fc 100644 --- a/namespace/namespace.go +++ b/namespace/namespace.go @@ -22,12 +22,14 @@ func New(version uint8, id []byte) (Namespace, error) { return Namespace{}, err } - data := []byte{version} - data = append(data, id...) + return newNamespace(version, id), nil +} +func newNamespace(version uint8, id []byte) Namespace { + data := []byte{version} return Namespace{ - data: data, - }, nil + data: append(data, id...), + } } // MustNew returns a new namespace with the provided version and id. It panics @@ -40,6 +42,27 @@ func MustNew(version uint8, id []byte) Namespace { return ns } +// NewFromBytes returns a new namespace from the provided byte slice. +func NewFromBytes(bytes []byte) (Namespace, error) { + if len(bytes) != NamespaceSize { + return Namespace{}, fmt.Errorf("invalid namespace length: %v must be %v", len(bytes), NamespaceSize) + } + + err := validateVersionSupported(bytes[0]) + if err != nil { + return Namespace{}, err + } + + err = validateID(bytes[0], bytes[1:]) + if err != nil { + return Namespace{}, err + } + + return Namespace{ + data: bytes, + }, nil +} + // NewV0 returns a new namespace with version 0 and the provided subID. subID // must be <= 10 bytes. If subID is < 10 bytes, it will be left-padded with 0s // to fill 10 bytes. @@ -71,13 +94,9 @@ func MustNewV0(subID []byte) Namespace { } // From returns a namespace from the provided byte slice. +// Deprecated: Please use NewFromBytes instead. func From(b []byte) (Namespace, error) { - if len(b) != NamespaceSize { - return Namespace{}, fmt.Errorf("invalid namespace length: %v must be %v", len(b), NamespaceSize) - } - rawVersion := b[0] - rawNamespace := b[1:] - return New(rawVersion, rawNamespace) + return NewFromBytes(b) } // Bytes returns this namespace as a byte slice. From 325d5009a49084207b8c4cb49569db184ce3eb09 Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Wed, 12 Jun 2024 14:56:41 +0200 Subject: [PATCH 5/8] use a single allocation --- blob/blob.go | 5 +++-- namespace/namespace.go | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/blob/blob.go b/blob/blob.go index f6eb9d6..568237c 100644 --- a/blob/blob.go +++ b/blob/blob.go @@ -44,8 +44,9 @@ func (b *Blob) Namespace() (namespace.Namespace, error) { // Namespace returns the namespace of the blob func (b *Blob) RawNamespace() []byte { - namespace := []byte{byte(b.NamespaceVersion)} - namespace = append(namespace, b.NamespaceId...) + namespace := make([]byte, namespace.NamespaceSize) + namespace[0] = uint8(b.NamespaceVersion) + copy(namespace[1:], b.NamespaceId) return namespace } diff --git a/namespace/namespace.go b/namespace/namespace.go index 270a4fc..ff90ad4 100644 --- a/namespace/namespace.go +++ b/namespace/namespace.go @@ -26,9 +26,11 @@ func New(version uint8, id []byte) (Namespace, error) { } func newNamespace(version uint8, id []byte) Namespace { - data := []byte{version} + data := make([]byte, 1+len(id)) + data[0] = version + copy(data[1:], id) return Namespace{ - data: append(data, id...), + data: data, } } From 7e5737b8557d66ace4013d55f5a768a7ed3cdb9c Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Thu, 13 Jun 2024 11:23:09 +0200 Subject: [PATCH 6/8] implement suggestions from reviewers --- blob/blob.go | 24 ++++++++++++------------ namespace/consts.go | 4 ++++ namespace/namespace.go | 20 +++++++------------- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/blob/blob.go b/blob/blob.go index 568237c..6e809f8 100644 --- a/blob/blob.go +++ b/blob/blob.go @@ -8,12 +8,12 @@ import ( "fmt" "sort" - "github.com/celestiaorg/go-square/namespace" + ns "github.com/celestiaorg/go-square/namespace" "google.golang.org/protobuf/proto" ) // SupportedBlobNamespaceVersions is a list of namespace versions that can be specified by a user for blobs. -var SupportedBlobNamespaceVersions = []uint8{namespace.NamespaceVersionZero} +var SupportedBlobNamespaceVersions = []uint8{ns.NamespaceVersionZero} // ProtoBlobTxTypeID is included in each encoded BlobTx to help prevent // decoding binaries that are not actually BlobTxs. @@ -28,7 +28,7 @@ const MaxShareVersion = 127 // New creates a new coretypes.Blob from the provided data after performing // basic stateless checks over it. -func New(ns namespace.Namespace, blob []byte, shareVersion uint8) *Blob { +func New(ns ns.Namespace, blob []byte, shareVersion uint8) *Blob { return &Blob{ NamespaceId: ns.ID(), Data: blob, @@ -38,14 +38,14 @@ func New(ns namespace.Namespace, blob []byte, shareVersion uint8) *Blob { } // Namespace returns the namespace of the blob -func (b *Blob) Namespace() (namespace.Namespace, error) { - return namespace.NewFromBytes(b.RawNamespace()) +func (b *Blob) Namespace() (ns.Namespace, error) { + return ns.NewFromBytes(b.RawNamespace()) } -// Namespace returns the namespace of the blob +// RawNamespace returns the namespace of the blob func (b *Blob) RawNamespace() []byte { - namespace := make([]byte, namespace.NamespaceSize) - namespace[0] = uint8(b.NamespaceVersion) + namespace := make([]byte, ns.NamespaceSize) + namespace[ns.VersionIndex] = uint8(b.NamespaceVersion) copy(namespace[1:], b.NamespaceId) return namespace } @@ -55,13 +55,13 @@ func (b *Blob) Validate() error { if b == nil { return errors.New("nil blob") } - if len(b.NamespaceId) != namespace.NamespaceIDSize { - return fmt.Errorf("namespace id must be %d bytes", namespace.NamespaceIDSize) + if len(b.NamespaceId) != ns.NamespaceIDSize { + return fmt.Errorf("namespace id must be %d bytes", ns.NamespaceIDSize) } if b.ShareVersion > MaxShareVersion { return errors.New("share version can not be greater than MaxShareVersion") } - if b.NamespaceVersion > namespace.NamespaceVersionMax { + if b.NamespaceVersion > ns.NamespaceVersionMax { return errors.New("namespace version can not be greater than MaxNamespaceVersion") } if len(b.Data) == 0 { @@ -90,7 +90,7 @@ func UnmarshalBlobTx(tx []byte) (*BlobTx, bool) { return &bTx, false } for _, b := range bTx.Blobs { - if len(b.NamespaceId) != namespace.NamespaceIDSize { + if len(b.NamespaceId) != ns.NamespaceIDSize { return &bTx, false } } diff --git a/namespace/consts.go b/namespace/consts.go index 7f783ff..e8b2657 100644 --- a/namespace/consts.go +++ b/namespace/consts.go @@ -9,6 +9,10 @@ const ( // NamespaceVersionSize is the size of a namespace version in bytes. NamespaceVersionSize = 1 + // VersionIndex is the index of the version in the namespace. This should + // always be the first byte + VersionIndex = NamespaceVersionSize - 1 // 0 + // NamespaceIDSize is the size of a namespace ID in bytes. NamespaceIDSize = 28 diff --git a/namespace/namespace.go b/namespace/namespace.go index ff90ad4..5ea0778 100644 --- a/namespace/namespace.go +++ b/namespace/namespace.go @@ -50,12 +50,12 @@ func NewFromBytes(bytes []byte) (Namespace, error) { return Namespace{}, fmt.Errorf("invalid namespace length: %v must be %v", len(bytes), NamespaceSize) } - err := validateVersionSupported(bytes[0]) + err := validateVersionSupported(bytes[VersionIndex]) if err != nil { return Namespace{}, err } - err = validateID(bytes[0], bytes[1:]) + err = validateID(bytes[VersionIndex], bytes[NamespaceVersionSize:]) if err != nil { return Namespace{}, err } @@ -73,16 +73,10 @@ func NewV0(subID []byte) (Namespace, error) { return Namespace{}, fmt.Errorf("subID must be <= %v, but it was %v bytes", NamespaceVersionZeroIDSize, lenSubID) } - subID = leftPad(subID, NamespaceVersionZeroIDSize) - id := make([]byte, NamespaceIDSize) - copy(id[NamespaceVersionZeroPrefixSize:], subID) + namespace := make([]byte, NamespaceSize) + copy(namespace[NamespaceSize-len(subID):], subID) - ns, err := New(NamespaceVersionZero, id) - if err != nil { - return Namespace{}, err - } - - return ns, nil + return NewFromBytes(namespace) } // MustNewV0 returns a new namespace with version 0 and the provided subID. This @@ -108,12 +102,12 @@ func (n Namespace) Bytes() []byte { // Version return this namespace's version func (n Namespace) Version() uint8 { - return n.data[0] + return n.data[NamespaceVersionSize-1] } // ID returns this namespace's ID func (n Namespace) ID() []byte { - return n.data[1:] + return n.data[NamespaceVersionSize:] } // validateVersionSupported returns an error if the version is not supported. From 043e3970047bd1e1378685aa561172ecb40b9e9b Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Thu, 13 Jun 2024 14:40:21 +0200 Subject: [PATCH 7/8] used named constants --- blob/blob.go | 2 +- namespace/namespace.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/blob/blob.go b/blob/blob.go index 6e809f8..b3199b7 100644 --- a/blob/blob.go +++ b/blob/blob.go @@ -46,7 +46,7 @@ func (b *Blob) Namespace() (ns.Namespace, error) { func (b *Blob) RawNamespace() []byte { namespace := make([]byte, ns.NamespaceSize) namespace[ns.VersionIndex] = uint8(b.NamespaceVersion) - copy(namespace[1:], b.NamespaceId) + copy(namespace[ns.NamespaceVersionSize:], b.NamespaceId) return namespace } diff --git a/namespace/namespace.go b/namespace/namespace.go index 5ea0778..7b83fad 100644 --- a/namespace/namespace.go +++ b/namespace/namespace.go @@ -26,9 +26,9 @@ func New(version uint8, id []byte) (Namespace, error) { } func newNamespace(version uint8, id []byte) Namespace { - data := make([]byte, 1+len(id)) - data[0] = version - copy(data[1:], id) + data := make([]byte, NamespaceVersionSize+len(id)) + data[VersionIndex] = version + copy(data[NamespaceVersionSize:], id) return Namespace{ data: data, } @@ -102,7 +102,7 @@ func (n Namespace) Bytes() []byte { // Version return this namespace's version func (n Namespace) Version() uint8 { - return n.data[NamespaceVersionSize-1] + return n.data[VersionIndex] } // ID returns this namespace's ID From 56ed7ec58aec7972d65cefcfc3b887b42297c1c2 Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Thu, 13 Jun 2024 16:42:09 +0200 Subject: [PATCH 8/8] Update namespace/consts.go Co-authored-by: Rootul P --- namespace/consts.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/namespace/consts.go b/namespace/consts.go index e8b2657..f56a85b 100644 --- a/namespace/consts.go +++ b/namespace/consts.go @@ -11,7 +11,7 @@ const ( // VersionIndex is the index of the version in the namespace. This should // always be the first byte - VersionIndex = NamespaceVersionSize - 1 // 0 + VersionIndex = 0 // NamespaceIDSize is the size of a namespace ID in bytes. NamespaceIDSize = 28