Skip to content

Commit b333d07

Browse files
Handle errors gracefullly in process and lower data size limit (#551)
* change panics to events (#549) Co-authored-by: Joshua Hannan <[email protected]> * lowers data size --------- Co-authored-by: Greg <[email protected]>
1 parent a969d0f commit b333d07

File tree

3 files changed

+45
-52
lines changed

3 files changed

+45
-52
lines changed

contracts/FlowTransactionScheduler.cdc

Lines changed: 39 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ access(all) contract FlowTransactionScheduler {
114114
// if they need to
115115
access(all) event ConfigUpdated()
116116

117+
// Emitted when a critical issue is encountered
118+
access(all) event CriticalIssue(message: String)
119+
117120
/// Entitlements
118121
access(all) entitlement Execute
119122
access(all) entitlement Process
@@ -583,7 +586,7 @@ access(all) contract FlowTransactionScheduler {
583586
Priority.Low: 0
584587
},
585588
lowPriorityEffortLimit: 2_500,
586-
maxDataSizeMB: 0.1,
589+
maxDataSizeMB: 0.001,
587590
priorityFeeMultipliers: {
588591
Priority.High: 10.0,
589592
Priority.Medium: 5.0,
@@ -1078,27 +1081,29 @@ access(all) contract FlowTransactionScheduler {
10781081
access(self) fun rescheduleLowPriorityTransactions(slot: UFix64, transactions: [UInt64]) {
10791082
for id in transactions {
10801083
let tx = self.borrowTransaction(id: id)
1081-
?? panic("Invalid ID: \(id) transaction not found") // critical bug
1082-
1083-
assert (
1084-
tx.priority == Priority.Low,
1085-
message: "Invalid Priority: Cannot reschedule transaction with id \(id) because it is not low priority"
1086-
)
1084+
if tx == nil {
1085+
emit CriticalIssue(message: "Invalid ID: \(id) transaction not found while rescheduling low priority transactions")
1086+
continue
1087+
}
10871088

1088-
assert (
1089-
tx.scheduledTimestamp == slot,
1090-
message: "Invalid Timestamp: Cannot reschedule transaction with id \(id) because it is not scheduled at the same slot as the new transaction"
1091-
)
1089+
if tx!.priority != Priority.Low {
1090+
emit CriticalIssue(message: "Invalid Priority: Cannot reschedule transaction with id \(id) because it is not low priority")
1091+
continue
1092+
}
10921093

1094+
if tx!.scheduledTimestamp != slot {
1095+
emit CriticalIssue(message: "Invalid Timestamp: Cannot reschedule transaction with id \(id) because it is not scheduled at the same slot as the new transaction")
1096+
continue
1097+
}
1098+
10931099
let newTimestamp = self.calculateScheduledTimestamp(
10941100
timestamp: slot + 1.0,
10951101
priority: Priority.Low,
1096-
executionEffort: tx.executionEffort
1102+
executionEffort: tx!.executionEffort
10971103
)!
10981104

1099-
let effort = tx.executionEffort
1100-
1101-
let transactionData = self.removeTransaction(txData: tx)
1105+
let effort = tx!.executionEffort
1106+
let transactionData = self.removeTransaction(txData: tx!)
11021107

11031108
// Subtract the execution effort for this transaction from the slot's priority
11041109
let slotEfforts = self.slotUsedEffort[slot]!
@@ -1175,32 +1180,35 @@ access(all) contract FlowTransactionScheduler {
11751180
let transactionIDs = transactionPriorities[priority] ?? {}
11761181
for id in transactionIDs.keys {
11771182
let tx = self.borrowTransaction(id: id)
1178-
?? panic("Invalid ID: \(id) transaction not found during initial processing") // critical bug
1179-
1183+
if tx == nil {
1184+
emit CriticalIssue(message: "Invalid ID: \(id) transaction not found while preparing pending queue")
1185+
continue
1186+
}
1187+
11801188
// Only add scheduled transactions to the queue
1181-
if tx.status != Status.Scheduled {
1189+
if tx!.status != Status.Scheduled {
11821190
continue
11831191
}
11841192

11851193
// this is safeguard to prevent collection growing too large in case of block production slowdown
1186-
if tx.executionEffort >= collectionAvailableEffort || transactionsAvailableCount == 0 {
1194+
if tx!.executionEffort >= collectionAvailableEffort || transactionsAvailableCount == 0 {
11871195
emit CollectionLimitReached(
11881196
collectionEffortLimit: transactionsAvailableCount == 0 ? nil : self.config.collectionEffortLimit,
11891197
collectionTransactionsLimit: transactionsAvailableCount == 0 ? self.config.collectionTransactionsLimit : nil
11901198
)
11911199
break
11921200
}
11931201

1194-
collectionAvailableEffort = collectionAvailableEffort.saturatingSubtract(tx.executionEffort)
1202+
collectionAvailableEffort = collectionAvailableEffort.saturatingSubtract(tx!.executionEffort)
11951203
transactionsAvailableCount = transactionsAvailableCount - 1
11961204

1197-
switch tx.priority {
1205+
switch tx!.priority {
11981206
case Priority.High:
1199-
high.append(tx)
1207+
high.append(tx!)
12001208
case Priority.Medium:
1201-
medium.append(tx)
1209+
medium.append(tx!)
12021210
case Priority.Low:
1203-
low.append(tx)
1211+
low.append(tx!)
12041212
}
12051213
}
12061214
}
@@ -1235,18 +1243,20 @@ access(all) contract FlowTransactionScheduler {
12351243
}
12361244

12371245
let tx = self.borrowTransaction(id: id)
1238-
?? panic("Invalid ID: \(id) transaction not found during removal") // critical bug
1246+
if tx == nil {
1247+
emit CriticalIssue(message: "Invalid ID: \(id) transaction not found while removing executed transactions")
1248+
continue
1249+
}
12391250

12401251
// Only remove executed transactions
1241-
if tx.status != Status.Executed {
1252+
if tx!.status != Status.Executed {
12421253
continue
12431254
}
12441255

12451256
// charge the full fee for transaction execution
1246-
destroy tx.payAndRefundFees(refundMultiplier: 0.0)
1257+
destroy tx!.payAndRefundFees(refundMultiplier: 0.0)
12471258

1248-
// remove all associated transaction data
1249-
self.removeTransaction(txData: tx)
1259+
self.removeTransaction(txData: tx!)
12501260
}
12511261
}
12521262
}
@@ -1269,10 +1279,6 @@ access(all) contract FlowTransactionScheduler {
12691279
self.removeExecutedTransactions(currentTimestamp)
12701280

12711281
let pendingTransactions = self.pendingQueue()
1272-
1273-
if pendingTransactions.length == 0 {
1274-
return
1275-
}
12761282

12771283
for tx in pendingTransactions {
12781284
// Only emit the pending execution event if the transaction handler capability is borrowable

lib/go/contracts/internal/assets/assets.go

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/transactionScheduler_test.cdc

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -86,25 +86,12 @@ access(all) fun testGetSizeOfData() {
8686
Test.assertEqual(0.00000000 as UFix64, size)
8787

8888
let largeArray: [Int] = []
89-
while largeArray.length < 10000 {
89+
while largeArray.length < 199 {
9090
largeArray.append(1)
9191
}
9292

9393
size = getSizeOfData(data: largeArray)
94-
Test.assertEqual(0.05337100 as UFix64, size)
95-
96-
// let currentTime = getCurrentBlock().timestamp
97-
// let futureTime = currentTime + 100.0
98-
99-
// let estimate = FlowTransactionScheduler.estimate(
100-
// data: testData,
101-
// timestamp: futureTime,
102-
// priority: FlowTransactionScheduler.Priority.Medium,
103-
// executionEffort: 1000
104-
// )
105-
106-
// size = getSizeOfData(data: estimate)
107-
// Test.assertEqual(0.00021000 as UFix64, size)
94+
Test.assertEqual(0.00107500 as UFix64, size)
10895
}
10996

11097
/** ---------------------------------------------------------------------------------
@@ -481,7 +468,7 @@ access(all) fun testConfigDetails() {
481468
Test.assertEqual(highPriorityMaxEffort as UInt64,oldConfig.priorityEffortLimit[FlowTransactionScheduler.Priority.High]!)
482469
Test.assertEqual(mediumPriorityMaxEffort as UInt64,oldConfig.priorityEffortLimit[FlowTransactionScheduler.Priority.Medium]!)
483470
Test.assertEqual(lowPriorityMaxEffort as UInt64,oldConfig.priorityEffortLimit[FlowTransactionScheduler.Priority.Low]!)
484-
Test.assertEqual(0.1,oldConfig.maxDataSizeMB)
471+
Test.assertEqual(0.001,oldConfig.maxDataSizeMB)
485472
Test.assertEqual(10.0,oldConfig.priorityFeeMultipliers[FlowTransactionScheduler.Priority.High]!)
486473
Test.assertEqual(5.0,oldConfig.priorityFeeMultipliers[FlowTransactionScheduler.Priority.Medium]!)
487474
Test.assertEqual(2.0,oldConfig.priorityFeeMultipliers[FlowTransactionScheduler.Priority.Low]!)

0 commit comments

Comments
 (0)