Skip to content

Commit 3ad472e

Browse files
committed
Fix batched commitment encoding
1 parent 72f516e commit 3ad472e

File tree

4 files changed

+65
-21
lines changed

4 files changed

+65
-21
lines changed

op-alt-da/commitment.go

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -180,39 +180,74 @@ func (c GenericCommitment) String() string {
180180
type BatchedCommitment []byte
181181

182182
// NewBatchedCommitment creates a new batched commitment from the given commitments
183-
func NewBatchedCommitment(comms []CommitmentData) BatchedCommitment {
184-
// Calculate total size needed: 2 bytes length + encoded bytes for each commitment
185-
totalSize := 0
183+
func NewBatchedCommitment(comms []CommitmentData) (BatchedCommitment, error) {
184+
if len(comms) == 0 {
185+
return nil, ErrInvalidCommitment
186+
}
187+
188+
// Verify all commitments are of the same type
189+
subType := comms[0].CommitmentType()
190+
for i, comm := range comms {
191+
if comm.CommitmentType() != subType {
192+
return nil, fmt.Errorf("commitment at index %d has different type than first commitment", i)
193+
}
194+
}
195+
196+
// Calculate total size needed: 1 byte for subcommitment type + (2 bytes length + raw data) for each commitment
197+
totalSize := 1 // subcommitment type byte
186198
for _, comm := range comms {
187-
encoded := comm.Encode()
188-
totalSize += 2 + len(encoded) // 2 bytes for length
199+
rawData := comm.Encode()[1:] // Skip the type byte since we'll store it once at the start
200+
totalSize += 2 + len(rawData) // 2 bytes for length + raw data
189201
}
190202

191203
result := make([]byte, totalSize)
192-
pos := 0
204+
205+
// Write the subcommitment type byte
206+
result[0] = byte(subType)
207+
pos := 1
193208

194209
for _, comm := range comms {
195-
encoded := comm.Encode()
210+
rawData := comm.Encode()[1:] // Skip the type byte
196211
// Write length (2 bytes, big endian)
197-
result[pos] = byte(len(encoded) >> 8)
198-
result[pos+1] = byte(len(encoded))
212+
result[pos] = byte(len(rawData) >> 8)
213+
result[pos+1] = byte(len(rawData))
199214
pos += 2
200215

201-
// Write encoded commitment (includes its type byte)
202-
copy(result[pos:], encoded)
203-
pos += len(encoded)
216+
// Write raw commitment data (without type byte)
217+
copy(result[pos:], rawData)
218+
pos += len(rawData)
204219
}
205220

206-
return BatchedCommitment(result)
221+
return BatchedCommitment(result), nil
207222
}
208223

209224
// DecodeBatchedCommitment validates and casts the commitment into a BatchedCommitment
210225
func DecodeBatchedCommitment(commitment []byte) (BatchedCommitment, error) {
211226
if len(commitment) == 0 {
212227
return nil, ErrInvalidCommitment
213228
}
214-
// TODO: validate batched commitments
215-
return commitment, nil
229+
230+
// Skip the subcommitment type byte when validating the structure
231+
reader := bytes.NewReader(commitment[1:])
232+
for reader.Len() > 0 {
233+
// Read length (2 bytes)
234+
var length uint16
235+
if err := binary.Read(reader, binary.BigEndian, &length); err != nil {
236+
return nil, ErrInvalidCommitment
237+
}
238+
239+
// Ensure we have enough bytes for this commitment
240+
if reader.Len() < int(length) {
241+
return nil, ErrInvalidCommitment
242+
}
243+
244+
// Skip the commitment data
245+
if _, err := reader.Seek(int64(length), io.SeekCurrent); err != nil {
246+
return nil, ErrInvalidCommitment
247+
}
248+
}
249+
250+
return BatchedCommitment(commitment), nil
216251
}
217252

218253
// CommitmentType returns the commitment type of BatchedCommitment
@@ -247,8 +282,14 @@ func (c BatchedCommitment) Verify(input []byte) error {
247282

248283
// GetCommitments returns the individual commitments in the batch
249284
func (c BatchedCommitment) GetCommitments() ([]CommitmentData, error) {
285+
if len(c) < 1 {
286+
return nil, ErrInvalidCommitment
287+
}
288+
289+
// First byte is the subcommitment type
290+
subType := CommitmentType(c[0])
291+
reader := bytes.NewReader(c[1:])
250292
var commitments []CommitmentData
251-
reader := bytes.NewReader(c)
252293

253294
for reader.Len() > 0 {
254295
// Read length (2 bytes)
@@ -263,8 +304,11 @@ func (c BatchedCommitment) GetCommitments() ([]CommitmentData, error) {
263304
return nil, ErrInvalidCommitment
264305
}
265306

307+
// Reconstruct full commitment with type byte
308+
fullData := append([]byte{byte(subType)}, data...)
309+
266310
// Decode the commitment
267-
comm, err := DecodeCommitmentData(data)
311+
comm, err := DecodeCommitmentData(fullData)
268312
if err != nil {
269313
return nil, err
270314
}

op-batcher/batcher/driver.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -832,7 +832,7 @@ func (l *BatchSubmitter) createAltDACommitment(txdata txData) (altda.CommitmentD
832832
if len(comms) == 1 {
833833
return comms[0], nil
834834
}
835-
return altda.NewBatchedCommitment(comms), nil
835+
return altda.NewBatchedCommitment(comms)
836836
}
837837

838838
func (l *BatchSubmitter) prepareAltDAInputs(txdata txData) [][]byte {

op-e2e/actions/altda/altda_batched_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,7 @@ func (a *L2AltDA) ActSubmitBatchedCommitments(t helpers.Testing, n int) {
138138

139139
// Batch submit 2 commitments
140140
a.batcher.ActL2SubmitBatchedCommitments(t, n, func(tx *types.DynamicFeeTx) {
141-
// skip txdata version byte, and only store the second commitment (33 bytes)
142-
// data = <DerivationVersion1> + <CommitmentType> + hash1 + hash2 + ...
141+
// skip txdata version byte, and only store the second commitment
143142
comm, err := altda.DecodeCommitmentData(tx.Data[1:])
144143
require.NoError(t, err)
145144

op-e2e/actions/helpers/l2_batcher.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,8 @@ func (s *L2Batcher) ActL2SubmitBatchedCommitments(t Testing, numFrames int, txOp
440440
comms[i] = comm
441441
}
442442

443-
batchedComm := altda.NewBatchedCommitment(comms)
443+
batchedComm, err := altda.NewBatchedCommitment(comms)
444+
require.NoError(t, err, "error creating batched commitment")
444445

445446
nonce, err := s.l1.PendingNonceAt(t.Ctx(), s.BatcherAddr)
446447
require.NoError(t, err, "need batcher nonce")

0 commit comments

Comments
 (0)