Skip to content

Commit c159928

Browse files
authored
Merge pull request #7781 from onflow/tim/7749-address-system-collection-malleability
Fix malleability issues in system collection for scheduled callbacks
2 parents 597c9a9 + 5206222 commit c159928

File tree

1 file changed

+32
-14
lines changed

1 file changed

+32
-14
lines changed

engine/execution/computation/computer/computer.go

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -314,10 +314,7 @@ func (e *blockComputer) queueSystemTransactions(
314314
systemLogger zerolog.Logger,
315315
) chan TransactionRequest {
316316
allTxs := append(executeCallbackTxs, systemTxn)
317-
// add execute callback transactions to the system collection info along to existing process transaction
318-
// TODO(7749): fix illegal mutation
319317
systemTxs := systemColection.CompleteCollection.Collection.Transactions
320-
systemColection.CompleteCollection.Collection.Transactions = append(systemTxs, allTxs...) //nolint:structwrite
321318
systemLogger = systemLogger.With().Uint32("num_txs", uint32(len(systemTxs))).Logger()
322319

323320
txQueue := make(chan TransactionRequest, len(allTxs))
@@ -497,19 +494,24 @@ func (e *blockComputer) executeSystemTransactions(
497494
Logger()
498495

499496
systemCollectionInfo := collectionInfo{
500-
blockId: block.BlockID(),
501-
blockIdStr: block.BlockID().String(),
502-
blockHeight: block.Block.Height,
503-
collectionIndex: userCollectionCount,
504-
CompleteCollection: &entity.CompleteCollection{
505-
Collection: flow.NewEmptyCollection(), // TODO(7749)
506-
},
497+
blockId: block.BlockID(),
498+
blockIdStr: block.BlockID().String(),
499+
blockHeight: block.Block.Height,
500+
collectionIndex: userCollectionCount,
501+
CompleteCollection: nil, // We do not yet know all the scheduled callbacks, so postpone construction of the collection.
507502
isSystemTransaction: true,
508503
}
509504

510505
var callbackTxs []*flow.TransactionBody
511506

512507
if e.vmCtx.ScheduleCallbacksEnabled {
508+
// We pass in the `systemCollectionInfo` here. However, note that at this point, the composition of the system chunk
509+
// is not yet known. Specifically, the `entity.CompleteCollection` represents the *final* output of a process and is
510+
// immutable by protocol mandate. If we had a bug in our software that accidentally illegally mutated such structs,
511+
// likely the node encountering that bug would misbehave and get slashed, or in the worst case the flow protocol might
512+
// be compromised. Therefore, we have the rigorous convention in our code base that the `CompleteCollection` is only
513+
// constructed once the final composition of the system chunk has been determined.
514+
// To that end, the CompleteCollection is nil here, such that any attempt to access the Collection will panic.
513515
callbacks, updatedTxnIndex, err := e.executeProcessCallback(
514516
callbackCtx,
515517
systemCollectionInfo,
@@ -524,6 +526,26 @@ func (e *blockComputer) executeSystemTransactions(
524526

525527
callbackTxs = callbacks
526528
txIndex = updatedTxnIndex
529+
530+
finalCollection, err := flow.NewCollection(flow.UntrustedCollection{
531+
Transactions: append(append([]*flow.TransactionBody{e.processCallbackTxn}, callbackTxs...), e.systemTxn),
532+
})
533+
if err != nil {
534+
return err
535+
}
536+
systemCollectionInfo.CompleteCollection = &entity.CompleteCollection{
537+
Collection: finalCollection,
538+
}
539+
} else {
540+
finalCollection, err := flow.NewCollection(flow.UntrustedCollection{
541+
Transactions: []*flow.TransactionBody{e.systemTxn},
542+
})
543+
if err != nil {
544+
return err
545+
}
546+
systemCollectionInfo.CompleteCollection = &entity.CompleteCollection{
547+
Collection: finalCollection,
548+
}
527549
}
528550

529551
// Update logger with number of transactions once they've become known
@@ -589,10 +611,6 @@ func (e *blockComputer) executeProcessCallback(
589611
txnIndex uint32,
590612
systemLogger zerolog.Logger,
591613
) ([]*flow.TransactionBody, uint32, error) {
592-
// add process callback transaction to the system collection info
593-
// TODO(7749): fix illegal mutation
594-
systemCollectionInfo.CompleteCollection.Collection.Transactions = append(systemCollectionInfo.CompleteCollection.Collection.Transactions, e.processCallbackTxn) //nolint:structwrite
595-
596614
request := newTransactionRequest(
597615
systemCollectionInfo,
598616
systemCtx,

0 commit comments

Comments
 (0)