diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index 391c3949..f145a130 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -304,6 +304,12 @@ func (runner *ZeroRunner) checkUsedCells() error { } } } + + err := runner.checkDilutedCheckUsage() + if err != nil { + return err + } + return runner.checkRangeCheckUsage() } @@ -359,6 +365,17 @@ func (runner *ZeroRunner) getPermRangeCheckLimits() (uint16, uint16) { return rcMin, rcMax } +func (runner *ZeroRunner) checkDilutedCheckUsage() error { + if runner.layout.DilutedPoolInstanceDef.IsNone() { + return nil + } + + // dilutedPoolInstance := runner.layout.DilutedPoolInstanceDef.Unwrap() + // usedUnitsByBuiltins := 0 + + return nil +} + // FinalizeSegments calculates the final size of the builtins segments, // using number of allocated instances and memory cells per builtin instance. // Additionally it sets the final size of the program segment to the program size. diff --git a/pkg/vm/builtins/bitwise.go b/pkg/vm/builtins/bitwise.go index b498a321..35c19dba 100644 --- a/pkg/vm/builtins/bitwise.go +++ b/pkg/vm/builtins/bitwise.go @@ -100,3 +100,27 @@ func (b *Bitwise) String() string { func (b *Bitwise) GetAllocatedSize(segmentUsedSize uint64, vmCurrentStep uint64) (uint64, error) { return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, b.ratio, inputCellsPerBitwise, instancesPerComponentBitwise, cellsPerBitwise) } + +func (b *Bitwise) GetUsedDilutedCheckUnits(dilutedSpacing uint32, dilutedNBits uint32) uint64 { + totalNBits := uint32(251) + partition := make([]uint32, 0, totalNBits) + + for i := uint32(0); i < totalNBits; i += dilutedSpacing * dilutedNBits { + for j := uint32(0); j < dilutedSpacing; j++ { + if i+j < totalNBits { + partition = append(partition, i+j) + } + } + } + + partitionLength := uint64(len(partition)) + numTrimmed := uint64(0) + + for _, elem := range partition { + if elem+dilutedSpacing*(dilutedNBits-1)+1 > totalNBits { + numTrimmed++ + } + } + + return 4*partitionLength + numTrimmed +} diff --git a/pkg/vm/builtins/diluted_pool_instance.go b/pkg/vm/builtins/diluted_pool_instance.go new file mode 100644 index 00000000..296530b9 --- /dev/null +++ b/pkg/vm/builtins/diluted_pool_instance.go @@ -0,0 +1,40 @@ +package builtins + +type DilutedPoolInstance struct { + UnitsPerStep uint32 + Spacing uint32 + NBits uint32 +} + +// DilutedPoolInstanceOption represents an option to a `DilutedPoolInstance` +type DilutedPoolInstanceOption struct { + value *DilutedPoolInstance +} + +// `SomeDilutedPoolInstance` creates a DilutedPoolInstanceOption with a value +func SomeDilutedPoolInstance(value DilutedPoolInstance) DilutedPoolInstanceOption { + return DilutedPoolInstanceOption{value: &value} +} + +// `NoneDilutedPoolInstance` creates a DilutedPoolInstanceOption without a value +func NoneDilutedPoolInstance() DilutedPoolInstanceOption { + return DilutedPoolInstanceOption{value: nil} +} + +// `IsNone` checks if the DilutedPoolInstanceOption has no value +func (o DilutedPoolInstanceOption) IsNone() bool { + return o.value == nil +} + +// `IsSome` checks if the DilutedPoolInstanceOption has a value +func (o DilutedPoolInstanceOption) IsSome() bool { + return o.value != nil +} + +// `Unwrap` returns the value if it exists, panics otherwise +func (o DilutedPoolInstanceOption) Unwrap() DilutedPoolInstance { + if o.IsNone() { + panic("Tried to unwrap None DilutedPoolInstanceOption") + } + return *o.value +} diff --git a/pkg/vm/builtins/keccak.go b/pkg/vm/builtins/keccak.go index 00e135fb..2068b50c 100644 --- a/pkg/vm/builtins/keccak.go +++ b/pkg/vm/builtins/keccak.go @@ -89,3 +89,11 @@ func (k *Keccak) String() string { func (k *Keccak) GetAllocatedSize(segmentUsedSize uint64, vmCurrentStep uint64) (uint64, error) { return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, k.ratio, inputCellsPerKeccak, instancesPerComponentKeccak, cellsPerKeccak) } + +func (k *Keccak) GetUsedDilutedCheckUnits(dilutedNBits uint32) uint64 { + totalCells := uint64(262144) + if dilutedNBits == 0 { + return 0 + } + return totalCells / uint64(dilutedNBits) +} diff --git a/pkg/vm/builtins/layouts.go b/pkg/vm/builtins/layouts.go index 59baeb4d..7d777a06 100644 --- a/pkg/vm/builtins/layouts.go +++ b/pkg/vm/builtins/layouts.go @@ -22,10 +22,12 @@ type Layout struct { RcUnits uint64 // List of builtins to be included in given layout Builtins []LayoutBuiltin + // Option of a diluted pool instance + DilutedPoolInstanceDef DilutedPoolInstanceOption } func getPlainLayout() Layout { - return Layout{Name: "plain", RcUnits: 16, Builtins: []LayoutBuiltin{}} + return Layout{Name: "plain", RcUnits: 16, Builtins: []LayoutBuiltin{}, DilutedPoolInstanceDef: NoneDilutedPoolInstance()} } func getSmallLayout() Layout { @@ -34,7 +36,7 @@ func getSmallLayout() Layout { {Runner: &Pedersen{ratio: 8}, Builtin: starknet.Pedersen}, {Runner: &RangeCheck{ratio: 8, RangeCheckNParts: 8}, Builtin: starknet.RangeCheck}, {Runner: &ECDSA{ratio: 512}, Builtin: starknet.ECDSA}, - }} + }, DilutedPoolInstanceDef: NoneDilutedPoolInstance()} } func getDexLayout() Layout { @@ -43,7 +45,7 @@ func getDexLayout() Layout { {Runner: &Pedersen{ratio: 8}, Builtin: starknet.Pedersen}, {Runner: &RangeCheck{ratio: 8, RangeCheckNParts: 8}, Builtin: starknet.RangeCheck}, {Runner: &ECDSA{ratio: 512}, Builtin: starknet.ECDSA}, - }} + }, DilutedPoolInstanceDef: NoneDilutedPoolInstance()} } func getRecursiveLayout() Layout { @@ -52,7 +54,7 @@ func getRecursiveLayout() Layout { {Runner: &Pedersen{ratio: 128}, Builtin: starknet.Pedersen}, {Runner: &RangeCheck{ratio: 8, RangeCheckNParts: 8}, Builtin: starknet.RangeCheck}, {Runner: &Bitwise{ratio: 8}, Builtin: starknet.Bitwise}, - }} + }, DilutedPoolInstanceDef: SomeDilutedPoolInstance(DilutedPoolInstance{UnitsPerStep: 16, Spacing: 4, NBits: 16})} } func getStarknetLayout() Layout { @@ -64,7 +66,7 @@ func getStarknetLayout() Layout { {Runner: &Bitwise{ratio: 64}, Builtin: starknet.Bitwise}, {Runner: &EcOp{ratio: 1024, cache: make(map[uint64]fp.Element)}, Builtin: starknet.ECOP}, {Runner: &Poseidon{ratio: 32, cache: make(map[uint64]fp.Element)}, Builtin: starknet.Poseidon}, - }} + }, DilutedPoolInstanceDef: SomeDilutedPoolInstance(DilutedPoolInstance{UnitsPerStep: 2, Spacing: 4, NBits: 16})} } func getStarknetWithKeccakLayout() Layout { @@ -77,7 +79,7 @@ func getStarknetWithKeccakLayout() Layout { {Runner: &EcOp{ratio: 1024, cache: make(map[uint64]fp.Element)}, Builtin: starknet.ECOP}, {Runner: &Keccak{ratio: 2048, cache: make(map[uint64]fp.Element)}, Builtin: starknet.Keccak}, {Runner: &Poseidon{ratio: 32, cache: make(map[uint64]fp.Element)}, Builtin: starknet.Poseidon}, - }} + }, DilutedPoolInstanceDef: SomeDilutedPoolInstance(DilutedPoolInstance{UnitsPerStep: 16, Spacing: 4, NBits: 16})} } func getRecursiveLargeOutputLayout() Layout { @@ -87,7 +89,7 @@ func getRecursiveLargeOutputLayout() Layout { {Runner: &RangeCheck{ratio: 8, RangeCheckNParts: 8}, Builtin: starknet.RangeCheck}, {Runner: &Bitwise{ratio: 8}, Builtin: starknet.Bitwise}, {Runner: &Poseidon{ratio: 8, cache: make(map[uint64]fp.Element)}, Builtin: starknet.Poseidon}, - }} + }, DilutedPoolInstanceDef: SomeDilutedPoolInstance(DilutedPoolInstance{UnitsPerStep: 16, Spacing: 4, NBits: 16})} } func getRecursiveWithPoseidonLayout() Layout { @@ -97,7 +99,7 @@ func getRecursiveWithPoseidonLayout() Layout { {Runner: &RangeCheck{ratio: 16, RangeCheckNParts: 8}, Builtin: starknet.RangeCheck}, {Runner: &Bitwise{ratio: 16}, Builtin: starknet.Bitwise}, {Runner: &Poseidon{ratio: 64, cache: make(map[uint64]fp.Element)}, Builtin: starknet.Poseidon}, - }} + }, DilutedPoolInstanceDef: SomeDilutedPoolInstance(DilutedPoolInstance{UnitsPerStep: 8, Spacing: 4, NBits: 16})} } func getAllSolidityLayout() Layout { @@ -108,7 +110,7 @@ func getAllSolidityLayout() Layout { {Runner: &ECDSA{ratio: 512}, Builtin: starknet.ECDSA}, {Runner: &Bitwise{ratio: 256}, Builtin: starknet.Bitwise}, {Runner: &EcOp{ratio: 256, cache: make(map[uint64]fp.Element)}, Builtin: starknet.ECOP}, - }} + }, DilutedPoolInstanceDef: SomeDilutedPoolInstance(DilutedPoolInstance{UnitsPerStep: 16, Spacing: 4, NBits: 16})} } func GetLayout(layout string) (Layout, error) {