def test_relocate_segments():
    segments = MemorySegmentManager(memory=MemoryDict({}), prime=PRIME)

    for i in range(5):
        assert segments.add() == RelocatableValue(segment_index=i, offset=0)

    segment_sizes = [3, 8, 0, 1, 2]
    public_memory_offsets = [
        [(0, 0), (1, 1)],
        [(i, 0) for i in range(8)],
        [],
        [],
        [(1, 2)],
    ]

    # These segments are not finalized.
    assert segments.add() == RelocatableValue(segment_index=5, offset=0)
    assert segments.add() == RelocatableValue(segment_index=6, offset=0)
    segments.memory[RelocatableValue(5, 4)] = 0

    segments.memory.freeze()
    segments.compute_effective_sizes()
    for i, (size, public_memory) in enumerate(
            zip(segment_sizes, public_memory_offsets)):
        segments.finalize(i, size=size, public_memory=public_memory)

    segment_offsets = segments.relocate_segments()
    assert segment_offsets == {0: 1, 1: 4, 2: 12, 3: 12, 4: 13, 5: 15, 6: 20}
    assert segments.get_public_memory_addresses(segment_offsets) == [(1, 0),
                                                                     (2, 1),
                                                                     (4, 0),
                                                                     (5, 0),
                                                                     (6, 0),
                                                                     (7, 0),
                                                                     (8, 0),
                                                                     (9, 0),
                                                                     (10, 0),
                                                                     (11, 0),
                                                                     (14, 2)]

    # Negative flows.
    segments = MemorySegmentManager(memory=MemoryDict({}), prime=PRIME)
    segments.add(size=1)
    with pytest.raises(AssertionError,
                       match='compute_effective_sizes must be called before'):
        segments.relocate_segments()

    segments.memory[RelocatableValue(0, 2)] = 0
    segments.memory.freeze()
    segments.compute_effective_sizes()
    with pytest.raises(AssertionError,
                       match='Segment 0 exceeded its allocated size'):
        segments.relocate_segments()
Ejemplo n.º 2
0
def test_jmp_segment():
    code = """
    jmp abs [ap]; ap++
    """
    program = compile_cairo(code=code, prime=PRIME, debug_info=True)

    program_base_a = RelocatableValue(0, 10)
    program_base_b = RelocatableValue(1, 20)

    memory = {
        **{program_base_a + i: v
           for i, v in enumerate(program.data)},
        **{program_base_b + i: v
           for i, v in enumerate(program.data)}, 99: 0,
        100: program_base_b,
        101: program_base_a
    }
    context = RunContext(
        pc=program_base_a,
        ap=100,
        fp=100,
        memory=MemoryDict(memory),
        prime=PRIME,
    )

    vm = VirtualMachine(program, context, {})
    vm.step()
    assert vm.run_context.pc == program_base_b
    assert vm.get_location(vm.run_context.pc) is None
    vm.step()
    assert vm.run_context.pc == program_base_a
    assert vm.get_location(vm.run_context.pc) is not None
Ejemplo n.º 3
0
def test_memory_dict_get():
    memory = MemoryDict({14: 15})
    assert memory.get(14, 'default') == 15
    assert memory.get(1234, 'default') == 'default'
    assert memory.get(-10, 'default') == 'default'
    # Attempting to read address with a negative offset is ok, it simply returns None.
    assert memory.get(RelocatableValue(segment_index=10, offset=-2)) is None
Ejemplo n.º 4
0
def run_single(code: str,
               steps: int,
               *,
               pc=RelocatableValue(0, 10),
               ap=100,
               fp=100,
               extra_mem={}):
    program = compile_cairo(code, PRIME, debug_info=True)

    # Set memory[fp - 1] to an arbitrary value, since [fp - 1] is assumed to be set.
    memory: Dict[MaybeRelocatable, MaybeRelocatable] = {
        **{pc + i: v
           for i, v in enumerate(program.data)}, fp - 1: 1234,
        **extra_mem
    }
    context = RunContext(
        pc=pc,
        ap=ap,
        fp=fp,
        memory=MemoryDict(memory),
        prime=PRIME,
    )

    vm = VirtualMachine(program, context, {})
    for _ in range(steps):
        vm.step()
    return vm
def cairo_run(args, program_input):
    program: ProgramBase = load_program(args.program)
    initial_memory = MemoryDict()
    steps_input = args.steps

    runner = CairoRunner(program=program,
                         layout=args.layout,
                         memory=initial_memory,
                         proof_mode=args.proof_mode)

    runner.initialize_segments()
    end = runner.initialize_main_entrypoint()
    runner.initialize_vm(hint_locals={'program_input': program_input})

    try:
        additional_steps = 1 if args.proof_mode else 0
        max_steps = steps_input - additional_steps if steps_input is not None else None
        runner.run_until_pc(end, max_steps=max_steps)
        runner.original_steps = runner.vm.current_step
        runner.end_run()
    except (VmException, AssertionError) as exc:
        raise exc

    runner.read_return_values()
    runner.finalize_segments_by_effective_size()
    verify_secure_runner(runner)
    runner.relocate()
    output = retrieveOutput(runner, args.exception)

    return output
Ejemplo n.º 6
0
def test_memory_dict_serialize():
    memory = MemoryDict({1: 2, 3: 4, 5: 6})
    expected_serialized = bytes([
        1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,
        6, 0, 0])
    serialized = memory.serialize(3)
    assert expected_serialized == serialized
    assert MemoryDict.deserialize(serialized, 3) == memory
Ejemplo n.º 7
0
def test_memory_dict_get():
    md = MemoryDict({14: 15})
    assert md.get(14, 'default') == 15
    assert md.get(1234, 'default') == 'default'
    with pytest.raises(ValueError, match='must be nonnegative'):
        md.get(-10, 'default')
    # Attempting to read address with a negative offset is ok, it simply returns None.
    assert md.get(RelocatableValue(segment_index=10, offset=-2)) is None
Ejemplo n.º 8
0
def test_memory_dict_setdefault():
    md = MemoryDict({14: 15})
    md.setdefault(14, 0)
    assert md[14] == 15
    md.setdefault(123, 456)
    assert md[123] == 456
    with pytest.raises(ValueError, match='must be an int'):
        md.setdefault(10, 'default')
    with pytest.raises(ValueError, match='must be positive'):
        md.setdefault(-10, 123)
Ejemplo n.º 9
0
def test_memory_dict_check_element():
    memory = MemoryDict()
    with pytest.raises(KeyError, match='must be an int'):
        memory['not a number'] = 12
    with pytest.raises(KeyError, match='must be nonnegative'):
        memory[-12] = 13
    with pytest.raises(ValueError, match='The offset of a relocatable value must be nonnegative'):
        memory[RelocatableValue(segment_index=10, offset=-2)] = 13
    # A value may have a negative offset.
    memory[13] = RelocatableValue(segment_index=10, offset=-2)
Ejemplo n.º 10
0
def test_get_segment_used_size():
    memory = MemoryDict({
        RelocatableValue(0, 0): 0,
        RelocatableValue(0, 2): 0,
        RelocatableValue(1, 5): 0,
        RelocatableValue(1, 7): 0,
        RelocatableValue(3, 0): 0,
        RelocatableValue(4, 1): 0,
    })
    assert [get_segment_used_size(i, memory) for i in range(5)] == [3, 8, 0, 1, 2]
Ejemplo n.º 11
0
def test_memory_dict():
    d = {1: 2}
    mem = MemoryDict(d)
    d[2] = 3
    assert 2 not in mem

    assert mem[1] == 2
    with pytest.raises(UnknownMemoryError):
        mem[2]
    mem[1] = 2
    with pytest.raises(InconsistentMemoryError):
        mem[1] = 3
Ejemplo n.º 12
0
def test_memory_dict_setdefault():
    memory = MemoryDict({14: 15})
    memory.setdefault(14, 0)
    assert memory[14] == 15
    memory.setdefault(123, 456)
    assert memory[123] == 456
    with pytest.raises(ValueError, match='must be an int'):
        memory.setdefault(10, 'default')
    with pytest.raises(KeyError, match='must be nonnegative'):
        memory.setdefault(-10, 123)
    with pytest.raises(ValueError, match='The offset of a relocatable value must be nonnegative'):
        memory[RelocatableValue(segment_index=10, offset=-2)] = 13
Ejemplo n.º 13
0
    def relocate(self):
        self.segment_offsets = self.segments.relocate_segments()

        self.relocated_memory = MemoryDict({
            self.relocate_value(addr): self.relocate_value(value)
            for addr, value in self.vm_memory.items()
        })
        self.relocated_trace = relocate_trace(self.vm.trace,
                                              self.segment_offsets,
                                              self.program.prime)
        for builtin_runner in self.builtin_runners.values():
            builtin_runner.relocate(self.relocate_value)
Ejemplo n.º 14
0
def test_gen_args():
    segments = MemorySegmentManager(memory=MemoryDict({}), prime=PRIME)

    test_array = [2, 3, 7]
    arg = [1, test_array, [4, -1]]
    ptr = segments.gen_arg(arg)

    memory = segments.memory

    assert memory[ptr] == 1
    memory.get_range(memory[ptr + 1], len(test_array)) == test_array
    memory.get_range(memory[ptr + 2], 2) == [4, PRIME - 1]
Ejemplo n.º 15
0
def test_hint_exception():
    code = """
# Some comment.

%{ x = 0 %}

%{
def f():
    0 / 0  # Raises exception.
%}
[ap] = 0; ap++

%{ y = 0 %}
%{


f()
%}
[ap] = 1; ap++
"""

    # In this test we actually do write the code to a file, to allow the linecache module to fetch
    # the line raising the exception.
    cairo_file = tempfile.NamedTemporaryFile('w')
    print(code, file=cairo_file)
    cairo_file.flush()
    program = compile_cairo(code=[(code, cairo_file.name)],
                            prime=PRIME,
                            debug_info=True)
    program_base = 10
    memory = {program_base + i: v for i, v in enumerate(program.data)}

    # Set memory[fp - 1] to an arbitrary value, since [fp - 1] is assumed to be set.
    memory[99] = 1234

    context = RunContext(
        pc=program_base,
        ap=200,
        fp=100,
        memory=MemoryDict(memory),
        prime=PRIME,
    )

    vm = VirtualMachine(program, context, {})

    vm.step()
    with pytest.raises(VmException) as excinfo:
        vm.step()
    assert str(excinfo.value) == f"""\
def test_get_segment_used_size():
    memory = MemoryDict({
        RelocatableValue(0, 0): 0,
        RelocatableValue(0, 2): 0,
        RelocatableValue(1, 5): 0,
        RelocatableValue(1, 7): 0,
        RelocatableValue(3, 0): 0,
        RelocatableValue(4, 1): 0,
    })
    segments = MemorySegmentManager(memory=memory, prime=PRIME)
    segments.n_segments = 5
    memory.freeze()
    segments.compute_effective_sizes()
    assert [segments.get_segment_used_size(i)
            for i in range(5)] == [3, 8, 0, 1, 2]
Ejemplo n.º 17
0
def test_segment_relocations():
    memory = MemoryDict()

    temp_segment = RelocatableValue(segment_index=-1, offset=0)
    memory[5] = temp_segment + 2
    assert memory[5] == RelocatableValue(segment_index=-1, offset=2)
    relocation_target = RelocatableValue(segment_index=4, offset=25)
    memory.add_relocation_rule(src_ptr=temp_segment, dest_ptr=relocation_target)
    assert memory[5] == relocation_target + 2

    memory[temp_segment + 3] = 17
    memory.relocate_memory()
    assert memory.data == {
        5: relocation_target + 2,
        relocation_target + 3: 17,
    }
Ejemplo n.º 18
0
def test_skip_instruction_execution():
    code = """
%{
    x = 0
    vm.run_context.pc += 2
    vm.skip_instruction_execution = True
%}
[ap] = [ap] + 1; ap++ # This intruction will not be executed.
%{
    x = 1
%}
[ap] = 10; ap++
    """

    program = compile_cairo(code, PRIME, debug_info=True)

    initial_ap = 100
    memory: Dict[MaybeRelocatable, MaybeRelocatable] = {
        **{i: v
           for i, v in enumerate(program.data)},
        initial_ap - 1: 1234,
    }
    context = RunContext(
        pc=0,
        ap=initial_ap,
        fp=initial_ap,
        memory=MemoryDict(memory),
        prime=PRIME,
    )

    vm = VirtualMachine(program, context, {})
    vm.enter_scope({'vm': vm})
    exec_locals = vm.exec_scopes[-1]

    assert 'x' not in exec_locals
    assert vm.run_context.pc == 0
    vm.step()
    assert exec_locals['x'] == 0
    assert vm.run_context.pc == 2
    vm.step()
    assert exec_locals['x'] == 1
    assert vm.run_context.pc == 4
    assert vm.run_context.ap == initial_ap + 1
    assert vm.run_context.memory[vm.run_context.ap - 1] == 10
    vm.exit_scope()
def test_validated_memory_dict():
    memory = MemoryDict()
    memory_validator = ValidatedMemoryDict(memory=memory)

    def rule_identical_pairs(mem, addr):
        """
        Validates that the values in address pairs (i, i+1), where i is even, are identical.
        """
        offset_diff = (-1) ** (addr.offset % 2)
        other_addr = RelocatableValue.from_tuple((addr.segment_index, addr.offset + offset_diff))
        if other_addr in mem:
            assert mem[addr] == mem[other_addr]
            return {addr, other_addr}
        return set()

    def rule_constant_value(mem, addr, constant):
        assert mem[addr] == constant, \
            f'Expected value in address {addr} to be {constant}, got {mem[addr]}.'
        return {addr}

    memory_validator.add_validation_rule(1, lambda memory, addr: set())
    memory_validator.add_validation_rule(2, lambda memory, addr: {addr})
    memory_validator.add_validation_rule(3, rule_identical_pairs)
    memory_validator.add_validation_rule(4, rule_constant_value, 0)

    addr0 = RelocatableValue.from_tuple((1, 0))
    addr1 = RelocatableValue.from_tuple((2, 0))
    addr2 = RelocatableValue.from_tuple((3, 0))
    addr3 = RelocatableValue.from_tuple((3, 1))
    addr4 = RelocatableValue.from_tuple((4, 0))

    # Test validated_addresses update.
    memory_validator[addr0] = 0
    assert memory_validator._ValidatedMemoryDict__validated_addresses == set()
    memory_validator[addr1] = 0
    assert memory_validator._ValidatedMemoryDict__validated_addresses == {addr1}
    # Test validation rule application.
    memory_validator[addr2] = 1
    assert memory_validator._ValidatedMemoryDict__validated_addresses == {addr1}
    memory_validator[addr3] = 1
    assert memory_validator._ValidatedMemoryDict__validated_addresses == {addr1, addr2, addr3}

    with pytest.raises(
            AssertionError, match='Expected value in address 4:0 to be 0, got 1.'):
        memory_validator[addr4] = 1
Ejemplo n.º 20
0
def test_segment_relocation_failures():
    memory = MemoryDict()

    relocation_target = RelocatableValue(segment_index=4, offset=25)
    with pytest.raises(AssertionError, match='src_ptr.segment_index must be < 0, src_ptr=1:2.'):
        memory.add_relocation_rule(src_ptr=RelocatableValue(
            segment_index=1, offset=2), dest_ptr=relocation_target)

    with pytest.raises(AssertionError, match='src_ptr.offset must be 0, src_ptr=-3:2.'):
        memory.add_relocation_rule(src_ptr=RelocatableValue(
            segment_index=-3, offset=2), dest_ptr=relocation_target)

    memory.add_relocation_rule(src_ptr=RelocatableValue(
        segment_index=-3, offset=0), dest_ptr=relocation_target)

    with pytest.raises(
            AssertionError, match='The segment with index -3 already has a relocation rule.'):
        memory.add_relocation_rule(src_ptr=RelocatableValue(
            segment_index=-3, offset=0), dest_ptr=relocation_target)
Ejemplo n.º 21
0
def test_cairo_pie_serialize_deserialize():
    program = compile_cairo(
        code=[('%builtins output pedersen range_check ecdsa\nmain:\n[ap] = [ap]\n', '')],
        prime=DEFAULT_PRIME)
    metadata = CairoPieMetadata(
        program=program.stripped(),
        program_segment=SegmentInfo(0, 10),
        execution_segment=SegmentInfo(1, 20),
        ret_fp_segment=SegmentInfo(6, 12),
        ret_pc_segment=SegmentInfo(7, 21),
        builtin_segments={
            'a': SegmentInfo(4, 15),
        },
        extra_segments=[],
    )
    memory = MemoryDict({
        1: 2,
        RelocatableValue(3, 4): RelocatableValue(6, 7),
    })
    additional_data = {'c': ['d', 3]}
    execution_resources = ExecutionResources(
        n_steps=10,
        n_memory_holes=7,
        builtin_instance_counter={
            'output': 6,
            'pedersen': 3,
        }
    )
    cairo_pie = CairoPie(
        metadata=metadata,
        memory=memory,
        additional_data=additional_data,
        execution_resources=execution_resources
    )

    fileobj = io.BytesIO()
    cairo_pie.to_file(fileobj)
    actual_cairo_pie = CairoPie.from_file(fileobj)

    assert cairo_pie == actual_cairo_pie
Ejemplo n.º 22
0
def test_auto_deduction_rules():
    code = """
[fp + 1] = [fp] + [ap]
"""

    program = compile_cairo(code=code, prime=PRIME, debug_info=True)
    memory = {i: v for i, v in enumerate(program.data)}
    initial_ap = RelocatableValue(segment_index=1, offset=200)
    initial_fp = RelocatableValue(segment_index=2, offset=100)

    context = RunContext(
        pc=0,
        ap=initial_ap,
        fp=initial_fp,
        memory=MemoryDict(memory),
        prime=PRIME,
    )

    vm = VirtualMachine(program, context, {})

    def rule_ap_segment(vm, addr, val):
        return val

    vm.add_auto_deduction_rule(1, rule_ap_segment, 100)
    vm.add_auto_deduction_rule(2, lambda vm, addr: None)
    vm.add_auto_deduction_rule(
        2, lambda vm, addr: 200 if addr == initial_fp else None)
    vm.add_auto_deduction_rule(2, lambda vm, addr: 456)

    vm.step()

    assert vm.run_context.memory[initial_ap] == 100
    assert vm.run_context.memory[initial_fp] == 200
    assert vm.run_context.memory[initial_fp + 1] == 300

    with pytest.raises(InconsistentAutoDeductionError,
                       match='at address 2:100. 200 != 456'):
        vm.verify_auto_deductions()
Ejemplo n.º 23
0
def test_memory_validation_in_hints():
    code = """
%{ memory[ap] = 0 %}
[ap] = [ap]; ap++
%{ memory[ap] = 0 %}
[ap] = [ap]; ap++
"""

    program = compile_cairo(code=code, prime=PRIME, debug_info=True)
    initial_ap_and_fp = RelocatableValue(segment_index=1, offset=200)
    memory = {i: v for i, v in enumerate(program.data)}
    # Set memory[fp - 1] to an arbitrary value, since [fp - 1] is assumed to be set.
    memory[initial_ap_and_fp - 1] = 1234

    context = RunContext(
        pc=0,
        ap=initial_ap_and_fp,
        fp=initial_ap_and_fp,
        memory=MemoryDict(memory),
        prime=PRIME,
    )

    vm = VirtualMachine(program, context, {})

    vm.add_validation_rule(1, lambda memory, addr: {addr})
    assert vm.validated_memory._ValidatedMemoryDict__validated_addresses == set(
    )
    vm.step()
    assert vm.validated_memory._ValidatedMemoryDict__validated_addresses == {
        initial_ap_and_fp
    }

    def fail_validation(memory, addr):
        raise Exception('Validation failed.')

    vm.add_validation_rule(1, fail_validation)
    with pytest.raises(VmException, match='Exception: Validation failed.'):
        vm.step()
Ejemplo n.º 24
0
def test_memory_dict_check_element():
    md = MemoryDict()
    with pytest.raises(ValueError, match='must be an int'):
        md['not a number'] = 12
    with pytest.raises(ValueError, match='must be positive'):
        md[-12] = 13
Ejemplo n.º 25
0
def test_memory_dict_get():
    md = MemoryDict({14: 15})
    assert md.get(14, 'default') == 15
    assert md.get(1234, 'default') == 'default'
    with pytest.raises(ValueError, match='must be positive'):
        md.get(-10, 'default')
Ejemplo n.º 26
0
def test_memory_dict_multiple_values():
    memory = MemoryDict({5: 10})
    memory[5] = 10
    memory[5] = 10
    with pytest.raises(InconsistentMemoryError):
        memory[5] = 11
Ejemplo n.º 27
0
def test_memory_dict_in():
    memory = MemoryDict({1: 2, 3: 4})
    assert 1 in memory
    assert 2 not in memory
    # Test that `in` doesn't add the value to the dict.
    assert 2 not in memory
Ejemplo n.º 28
0
def cairo_run(args):
    trace_file = args.trace_file
    if trace_file is None and args.tracer:
        # If --tracer is used, use a temporary file as trace_file.
        trace_file = tempfile.NamedTemporaryFile(mode='wb')

    memory_file = args.memory_file
    if memory_file is None and args.tracer:
        # If --tracer is used, use a temporary file as memory_file.
        memory_file = tempfile.NamedTemporaryFile(mode='wb')

    debug_info_file = args.debug_info_file
    if debug_info_file is None and args.tracer:
        # If --tracer is used, use a temporary file as debug_info_file.
        debug_info_file = tempfile.NamedTemporaryFile(mode='w')

    ret_code = 0
    if args.program is not None:
        program: ProgramBase = Program.Schema().load(json.load(args.program))
        initial_memory = MemoryDict()
        steps_input = args.steps
    else:
        raise NotImplementedError('--run_from_cairo_pie is not supported.')

    runner = CairoRunner(program=program,
                         layout=args.layout,
                         memory=initial_memory,
                         proof_mode=args.proof_mode)

    runner.initialize_segments()
    end = runner.initialize_main_entrypoint()

    if args.run_from_cairo_pie is not None:
        # Add extra_segments.
        for segment_info in cairo_pie_input.metadata.extra_segments:
            runner.segments.add(size=segment_info.size)

    program_input = json.load(args.program_input) if args.program_input else {}
    runner.initialize_vm(hint_locals={'program_input': program_input})

    try:
        if args.no_end:
            assert args.steps is not None, '--steps must specified when running with --no-end.'
        else:
            additional_steps = 1 if args.proof_mode else 0
            max_steps = steps_input - additional_steps if steps_input is not None else None
            runner.run_until_pc(end, max_steps=max_steps)
            if args.proof_mode:
                # Run one more step to make sure the last pc that was executed (rather than the pc
                # after it) is __end__.
                runner.run_for_steps(1)
            runner.original_steps = runner.vm.current_step

        if args.min_steps:
            runner.run_until_steps(args.min_steps)

        if steps_input is not None:
            runner.run_until_steps(steps_input)
        elif args.proof_mode:
            runner.run_until_next_power_of_2()
            while not runner.check_used_cells():
                runner.run_for_steps(1)
                runner.run_until_next_power_of_2()
        runner.end_run()
    except (VmException, AssertionError) as exc:
        if args.debug_error:
            print(f'Got an error:\n{exc}')
            ret_code = 1
        else:
            raise exc

    if not args.no_end:
        runner.read_return_values()

    if args.no_end or not args.proof_mode:
        runner.finalize_segments_by_effective_size()
    else:
        # Finalize important segments by correct size.
        runner.finalize_segments()
        # Finalize all user segments by effective size.
        runner.finalize_segments_by_effective_size()

    if args.secure_run:
        verify_secure_runner(runner)

    if args.cairo_pie_output:
        runner.get_cairo_pie().to_file(args.cairo_pie_output)

    runner.relocate()

    if args.print_memory:
        runner.print_memory(relocated=args.relocate_prints)

    if args.print_output:
        runner.print_output()

    if args.print_info:
        runner.print_info(relocated=args.relocate_prints)
        # Skip builtin usage calculation if the execution stopped before reaching the end symbol.
        # Trying to calculate the builtin usage is likely to raise an exception and prevent the user
        # from opening the tracer.
        if args.proof_mode and not args.no_end:
            runner.print_builtin_usage()

    if trace_file is not None:
        field_bytes = math.ceil(program.prime.bit_length() / 8)
        write_binary_trace(trace_file, runner.relocated_trace)

    if memory_file is not None:
        field_bytes = math.ceil(program.prime.bit_length() / 8)
        write_binary_memory(memory_file, runner.relocated_memory, field_bytes)

    if args.air_public_input is not None:
        rc_min, rc_max = runner.get_perm_range_check_limits()
        write_air_public_input(
            layout=args.layout,
            public_input_file=args.air_public_input,
            memory=runner.relocated_memory,
            public_memory_addresses=runner.segments.
            get_public_memory_addresses(runner.segment_offsets),
            memory_segment_addresses=runner.get_memory_segment_addresses(),
            trace=runner.relocated_trace,
            rc_min=rc_min,
            rc_max=rc_max)

    if args.air_private_input is not None:
        assert args.trace_file is not None, \
            '--trace_file must be set when --air_private_input is set.'
        assert args.memory_file is not None, \
            '--memory_file must be set when --air_private_input is set.'
        json.dump(
            {
                'trace_path': f'{os.path.abspath(trace_file.name)}',
                'memory_path': f'{os.path.abspath(memory_file.name)}',
                **runner.get_air_private_input(),
            },
            args.air_private_input,
            indent=4)
        print(file=args.air_private_input)
        args.air_private_input.flush()

    if debug_info_file is not None:
        json.dump(DebugInfo.Schema().dump(runner.get_relocated_debug_info()),
                  debug_info_file)
        debug_info_file.flush()

    if args.tracer:
        CAIRO_TRACER = 'starkware.cairo.lang.tracer.tracer'
        subprocess.call(
            list(
                filter(None, [
                    sys.executable,
                    '-m',
                    CAIRO_TRACER,
                    f'--program={args.program.name}',
                    f'--trace={trace_file.name}',
                    f'--memory={memory_file.name}',
                    f'--air_public_input={args.air_public_input.name}'
                    if args.air_public_input else None,
                    f'--debug_info={debug_info_file.name}',
                ])))

    return ret_code
Ejemplo n.º 29
0
def test_memory_dict_getitem():
    memory = MemoryDict({11: 12})
    with pytest.raises(UnknownMemoryError):
        memory[12]
Ejemplo n.º 30
0
    def __init__(self,
                 program: ProgramBase,
                 layout: str,
                 memory: MemoryDict = None,
                 proof_mode: Optional[bool] = None):
        self.program = program
        self.layout = layout
        self.builtin_runners: Dict[str, BuiltinRunner] = {}
        self.original_steps = None
        self.proof_mode = False if proof_mode is None else proof_mode

        # Reconstruct the builtin list to make sure there's no unexpected builtin and that builtins
        # appears in order.
        expected_builtin_list = []

        instance = LAYOUTS[self.layout]
        non_existing_builtins = set(self.program.builtins) - set(
            instance.builtins.keys())
        assert len(non_existing_builtins) == 0, \
            f'Builtins {non_existing_builtins} are not present in layout "{self.layout}"'

        if self.layout in ['small', 'dex', 'test']:
            builtin_factories = {
                'output':
                lambda name, included: OutputBuiltinRunner(included=included),
                'pedersen':
                functools.partial(HashBuiltinRunner,
                                  ratio=instance.builtins['pedersen'].ratio,
                                  hash_func=pedersen_hash),
                'range_check':
                lambda name, included: RangeCheckBuiltinRunner(
                    included=included,
                    ratio=instance.builtins['range_check'].ratio,
                    inner_rc_bound=2**16,
                    n_parts=instance.builtins['range_check'].n_parts),
                'ecdsa':
                functools.partial(SignatureBuiltinRunner,
                                  ratio=instance.builtins['ecdsa'].ratio,
                                  process_signature=process_ecdsa,
                                  verify_signature=verify_ecdsa_sig),
                'checkpoints':
                functools.partial(CheckpointsBuiltinRunner, sample_ratio=16),
            }

            for name, factory in builtin_factories.items():
                included = name in self.program.builtins
                # In proof mode all the builtin_runners are required.
                if included or self.proof_mode:
                    self.builtin_runners[
                        f'{name}_builtin'] = factory(  # type: ignore
                            name=name, included=included)
                if included:
                    expected_builtin_list.append(name)

        assert expected_builtin_list == self.program.builtins, \
            f'Expected builtin list {expected_builtin_list} does not match {self.program.builtins}.'

        self.memory = memory if memory is not None else MemoryDict()
        self.segments = MemorySegmentManager(memory=self.memory,
                                             prime=self.program.prime)
        self.segment_offsets = None
        self.final_pc: Optional[RelocatableValue] = None