Skip to content

Commit

Permalink
Implemented TestLessThanOrEqualAddress (#629)
Browse files Browse the repository at this point in the history
* Implemented core hint

* Changed Impl

* Added Cmp utility function
  • Loading branch information
Sh0g0-1758 authored Aug 15, 2024
1 parent 5bd1213 commit d06d024
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 0 deletions.
40 changes: 40 additions & 0 deletions pkg/hintrunner/core/hint.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,46 @@ func (hint *TestLessThanOrEqual) Execute(vm *VM.VirtualMachine, _ *hinter.HintRu
return nil
}

type TestLessThanOrEqualAddress struct {
dst hinter.CellRefer
lhs hinter.ResOperander
rhs hinter.ResOperander
}

func (hint *TestLessThanOrEqualAddress) String() string {
return "TestLessThanOrEqualAddress"
}

func (hint *TestLessThanOrEqualAddress) Execute(vm *VM.VirtualMachine, _ *hinter.HintRunnerContext) error {
lhsPtr, err := hinter.ResolveAsAddress(vm, hint.lhs)
if err != nil {
return fmt.Errorf("resolve lhs pointer: %w", err)
}

rhsPtr, err := hinter.ResolveAsAddress(vm, hint.rhs)
if err != nil {
return fmt.Errorf("resolve rhs pointer: %w", err)
}

resFelt := f.Element{}
if lhsPtr.Cmp(rhsPtr) <= 0 {
resFelt.SetOne()
}

dstAddr, err := hint.dst.Get(vm)
if err != nil {
return fmt.Errorf("get dst address %s: %w", dstAddr, err)
}

mv := mem.MemoryValueFromFieldElement(&resFelt)
err = vm.Memory.WriteToAddress(&dstAddr, &mv)
if err != nil {
return fmt.Errorf("write to dst address %s: %w", dstAddr, err)
}

return nil
}

type LinearSplit struct {
value hinter.ResOperander
scalar hinter.ResOperander
Expand Down
131 changes: 131 additions & 0 deletions pkg/hintrunner/core/hint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,137 @@ func TestTestLessThanOrEqFalse(t *testing.T) {
)
}

func TestLessThanOrEqualAddressTrue(t *testing.T) {
// Address of lhs and rhs are same (SegmentIndex and Offset)
vm := VM.DefaultVirtualMachine()
vm.Context.Ap = 0
vm.Context.Fp = 0
addr := mem.MemoryAddress{
SegmentIndex: VM.ExecutionSegment,
Offset: 23,
}
utils.WriteTo(vm, VM.ExecutionSegment, vm.Context.Ap, mem.MemoryValueFromMemoryAddress(&addr))

var dst hinter.ApCellRef = 1
rhs := hinter.Deref{Deref: hinter.ApCellRef(0)}
lhs := hinter.Deref{Deref: hinter.ApCellRef(0)}

hint := TestLessThanOrEqualAddress{
dst: dst,
lhs: lhs,
rhs: rhs,
}

err := hint.Execute(vm, nil)
require.NoError(t, err)
require.Equal(
t,
mem.MemoryValueFromInt(1),
utils.ReadFrom(vm, VM.ExecutionSegment, 1),
)

// Address of lhs is less than the address of rhs (Offset)
vm = VM.DefaultVirtualMachine()
vm.Context.Ap = 0
vm.Context.Fp = 0
rhsAddr := mem.MemoryAddress{
SegmentIndex: VM.ExecutionSegment,
Offset: 23,
}
lhsAddr := mem.MemoryAddress{
SegmentIndex: VM.ExecutionSegment,
Offset: 17,
}
utils.WriteTo(vm, VM.ExecutionSegment, vm.Context.Ap, mem.MemoryValueFromMemoryAddress(&rhsAddr))
utils.WriteTo(vm, VM.ExecutionSegment, vm.Context.Ap+1, mem.MemoryValueFromMemoryAddress(&lhsAddr))

dst = 2
rhs = hinter.Deref{Deref: hinter.ApCellRef(0)}
lhs = hinter.Deref{Deref: hinter.ApCellRef(1)}

hint = TestLessThanOrEqualAddress{
dst: dst,
lhs: lhs,
rhs: rhs,
}

err = hint.Execute(vm, nil)
require.NoError(t, err)
require.Equal(
t,
mem.MemoryValueFromInt(1),
utils.ReadFrom(vm, VM.ExecutionSegment, 2),
)

// Address of lhs is less than the address of rhs (SegmentIndex)
vm = VM.DefaultVirtualMachine()
vm.Context.Ap = 0
vm.Context.Fp = 0
rhsAddr = mem.MemoryAddress{
SegmentIndex: VM.ExecutionSegment + 1,
Offset: 17,
}
lhsAddr = mem.MemoryAddress{
SegmentIndex: VM.ExecutionSegment,
Offset: 23,
}
utils.WriteTo(vm, VM.ExecutionSegment, vm.Context.Ap, mem.MemoryValueFromMemoryAddress(&rhsAddr))
utils.WriteTo(vm, VM.ExecutionSegment, vm.Context.Ap+1, mem.MemoryValueFromMemoryAddress(&lhsAddr))

dst = 2
rhs = hinter.Deref{Deref: hinter.ApCellRef(0)}
lhs = hinter.Deref{Deref: hinter.ApCellRef(1)}

hint = TestLessThanOrEqualAddress{
dst: dst,
lhs: lhs,
rhs: rhs,
}

err = hint.Execute(vm, nil)
require.NoError(t, err)
require.Equal(
t,
mem.MemoryValueFromInt(1),
utils.ReadFrom(vm, VM.ExecutionSegment, 2),
)
}

func TestLessThanOrEqualAddressFalse(t *testing.T) {
vm := VM.DefaultVirtualMachine()
vm.Context.Ap = 0
vm.Context.Fp = 0
rhsAddr := mem.MemoryAddress{
SegmentIndex: VM.ExecutionSegment,
Offset: 17,
}
lhsAddr := mem.MemoryAddress{
SegmentIndex: VM.ExecutionSegment,
Offset: 23,
}
utils.WriteTo(vm, VM.ExecutionSegment, vm.Context.Ap, mem.MemoryValueFromMemoryAddress(&rhsAddr))
utils.WriteTo(vm, VM.ExecutionSegment, vm.Context.Ap+1, mem.MemoryValueFromMemoryAddress(&lhsAddr))

var dst hinter.ApCellRef = 2
rhs := hinter.Deref{Deref: hinter.ApCellRef(0)}
lhs := hinter.Deref{Deref: hinter.ApCellRef(1)}

hint := TestLessThanOrEqualAddress{
dst: dst,
lhs: lhs,
rhs: rhs,
}

err := hint.Execute(vm, nil)
require.NoError(t, err)
require.Equal(
t,
mem.EmptyMemoryValueAsFelt(),
utils.ReadFrom(vm, VM.ExecutionSegment, 2),
"Expected the hint to evaluate to False when address of lhs is larger",
)
}

func TestLinearSplit(t *testing.T) {
vm := VM.DefaultVirtualMachine()
vm.Context.Ap = 0
Expand Down
9 changes: 9 additions & 0 deletions pkg/parsers/starknet/hint.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const (
AllocSegmentName HintName = "AllocSegment"
TestLessThanName HintName = "TestLessThan"
TestLessThanOrEqualName HintName = "TestLessThanOrEqual"
TestLessThanOrEqualAddressName HintName = "TestLessThanOrEqualAddress"
WideMul128Name HintName = "WideMul128"
DivModName HintName = "DivMod"
Uint256DivModName HintName = "Uint256DivMod"
Expand Down Expand Up @@ -85,6 +86,12 @@ type TestLessThanOrEqual struct {
Dst CellRef `json:"dst" validate:"required"`
}

type TestLessThanOrEqualAddress struct {
Lhs ResOperand `json:"lhs" validate:"required"`
Rhs ResOperand `json:"rhs" validate:"required"`
Dst CellRef `json:"dst" validate:"required"`
}

type WideMul128 struct {
Lhs ResOperand `json:"lhs" validate:"required"`
Rhs ResOperand `json:"rhs" validate:"required"`
Expand Down Expand Up @@ -465,6 +472,8 @@ func (h *Hint) UnmarshalJSON(data []byte) error {
args = &TestLessThan{}
case TestLessThanOrEqualName:
args = &TestLessThanOrEqual{}
case TestLessThanOrEqualAddressName:
args = &TestLessThanOrEqualAddress{}
case WideMul128Name:
args = &WideMul128{}
case DivModName:
Expand Down
10 changes: 10 additions & 0 deletions pkg/vm/memory/memory_value.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ func (address *MemoryAddress) Equal(other *MemoryAddress) bool {
return address.SegmentIndex == other.SegmentIndex && address.Offset == other.Offset
}

func (address *MemoryAddress) Cmp(other *MemoryAddress) int {
if address.SegmentIndex == other.SegmentIndex && address.Offset == other.Offset {
return 0
} else if address.SegmentIndex < other.SegmentIndex || (address.SegmentIndex == other.SegmentIndex && address.Offset < other.Offset) {
return -1
} else {
return 1
}
}

// It crates a new memory address with the modified offset
func (address *MemoryAddress) AddOffset(offset int16) (MemoryAddress, error) {
newOffset, overflow := utils.SafeOffset(address.Offset, offset)
Expand Down

0 comments on commit d06d024

Please sign in to comment.