diff --git a/core/types/row_consumption.go b/core/types/row_consumption.go index 8d1147941886..073d36e58879 100644 --- a/core/types/row_consumption.go +++ b/core/types/row_consumption.go @@ -1,5 +1,7 @@ package types +import "slices" + type RowUsage struct { IsOk bool `json:"is_ok"` RowNumber uint64 `json:"row_number"` @@ -12,4 +14,38 @@ type SubCircuitRowUsage struct { RowNumber uint64 `json:"row_number" gencodec:"required"` } +// RowConsumptionLimit is the max number of row we support per subcircuit +const RowConsumptionLimit = 1_000_000 + type RowConsumption []SubCircuitRowUsage + +// IsOverflown returns if any subcircuits are overflown +func (rc RowConsumption) IsOverflown() bool { + return slices.ContainsFunc(rc, func(scru SubCircuitRowUsage) bool { + return scru.RowNumber > RowConsumptionLimit + }) +} + +// Difference returns rc - other +// Assumes that rc > other for all subcircuits +func (rc RowConsumption) Difference(other RowConsumption) RowConsumption { + subCircuitMap := make(map[string]uint64, len(rc)) + for _, detail := range rc { + subCircuitMap[detail.Name] = detail.RowNumber + } + + for _, detail := range other { + subCircuitMap[detail.Name] -= detail.RowNumber + } + + diff := make([]SubCircuitRowUsage, 0, len(subCircuitMap)) + for name, rowNumDiff := range subCircuitMap { + if rowNumDiff > 0 { + diff = append(diff, SubCircuitRowUsage{ + Name: name, + RowNumber: rowNumDiff, + }) + } + } + return diff +} diff --git a/core/types/row_consumption_test.go b/core/types/row_consumption_test.go new file mode 100644 index 000000000000..84d8d13376e1 --- /dev/null +++ b/core/types/row_consumption_test.go @@ -0,0 +1,80 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRowConsumptionDifference(t *testing.T) { + tests := []struct { + rc1 RowConsumption + rc2 RowConsumption + expected RowConsumption + }{ + { + rc1: RowConsumption{ + SubCircuitRowUsage{ + "sc1", + 123, + }, + SubCircuitRowUsage{ + "sc2", + 456, + }, + }, + rc2: RowConsumption{ + SubCircuitRowUsage{ + "sc2", + 111, + }, + }, + expected: RowConsumption{ + SubCircuitRowUsage{ + "sc1", + 123, + }, + SubCircuitRowUsage{ + "sc2", + 345, + }, + }, + }, + { + rc1: RowConsumption{ + SubCircuitRowUsage{ + "sc1", + 123, + }, + SubCircuitRowUsage{ + "sc2", + 456, + }, + }, + rc2: RowConsumption{ + SubCircuitRowUsage{ + "sc2", + 456, + }, + }, + expected: RowConsumption{ + SubCircuitRowUsage{ + "sc1", + 123, + }, + }, + }, + } + + makeMap := func(rc RowConsumption) map[string]uint64 { + m := make(map[string]uint64) + for _, usage := range rc { + m[usage.Name] = usage.RowNumber + } + return m + } + + for _, test := range tests { + assert.Equal(t, makeMap(test.expected), makeMap(test.rc1.Difference(test.rc2))) + } +}