Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Blake2s hints (Part 2) #312

Merged
merged 18 commits into from
Oct 25, 2023
35 changes: 35 additions & 0 deletions cairo_programs/blake2s_felts.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
%builtins range_check bitwise

from starkware.cairo.common.bool import TRUE
from starkware.cairo.common.alloc import alloc
from starkware.cairo.common.cairo_blake2s.blake2s import blake2s_felts
from starkware.cairo.common.cairo_builtins import BitwiseBuiltin

func main{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}() {
alloc_locals;
let inputs: felt* = alloc();
assert inputs[0] = 3456722;
assert inputs[1] = 435425528;
assert inputs[2] = 3232553;
assert inputs[3] = 2576195;
assert inputs[4] = 73471943;
assert inputs[5] = 17549868;
assert inputs[6] = 87158958;
assert inputs[7] = 6353668;
assert inputs[8] = 343656565;
assert inputs[9] = 1255962;
assert inputs[10] = 25439785;
assert inputs[11] = 1154578;
assert inputs[12] = 585849303;
assert inputs[13] = 763502;
assert inputs[14] = 43753647;
assert inputs[15] = 74256930;
let (local blake2s_ptr_start) = alloc();
let blake2s_ptr = blake2s_ptr_start;
let (result) = blake2s_felts{range_check_ptr=range_check_ptr, blake2s_ptr=blake2s_ptr}(
16, inputs, TRUE
);
assert result.low = 23022179997536219430502258022509199703;
assert result.high = 136831746058902715979837770794974289597;
return ();
}
20 changes: 20 additions & 0 deletions cairo_programs/blake2s_hello_world_hash.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
%builtins range_check bitwise

from starkware.cairo.common.alloc import alloc
from starkware.cairo.common.cairo_blake2s.blake2s import blake2s
from starkware.cairo.common.cairo_builtins import BitwiseBuiltin

// Computes the hash of "Hello World"
func main{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}() {
alloc_locals;
let inputs: felt* = alloc();
assert inputs[0] = 'Hell';
assert inputs[1] = 'o Wo';
assert inputs[2] = 'rld';
let (local blake2s_ptr_start) = alloc();
let blake2s_ptr = blake2s_ptr_start;
let (output) = blake2s{range_check_ptr=range_check_ptr, blake2s_ptr=blake2s_ptr}(inputs, 9);
assert output.low = 219917655069954262743903159041439073909;
assert output.high = 296157033687865319468534978667166017272;
return ();
}
18 changes: 18 additions & 0 deletions cairo_programs/finalize_blake2s.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
%builtins range_check bitwise

from starkware.cairo.common.alloc import alloc
from starkware.cairo.common.cairo_blake2s.blake2s import blake2s, finalize_blake2s
from starkware.cairo.common.cairo_builtins import BitwiseBuiltin

func main{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}() {
alloc_locals;
let inputs: felt* = alloc();
assert inputs[0] = 'Hell';
assert inputs[1] = 'o Wo';
assert inputs[2] = 'rld';
let (local blake2s_ptr_start) = alloc();
let blake2s_ptr = blake2s_ptr_start;
let (output) = blake2s{range_check_ptr=range_check_ptr, blake2s_ptr=blake2s_ptr}(inputs, 9);
finalize_blake2s(blake2s_ptr_start, blake2s_ptr);
return ();
}
145 changes: 145 additions & 0 deletions pkg/hints/blake2s_hints.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package hints

import (
"math"

. "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_utils"
. "github.com/lambdaclass/cairo-vm.go/pkg/lambdaworks"
. "github.com/lambdaclass/cairo-vm.go/pkg/vm"
. "github.com/lambdaclass/cairo-vm.go/pkg/vm/memory"
)

func Uint32SliceToMRSlice(u32Slice []uint32) []MaybeRelocatable {
mRSlice := make([]MaybeRelocatable, 0, len(u32Slice))
for _, u32 := range u32Slice {
mRSlice = append(mRSlice, *NewMaybeRelocatableFelt(FeltFromUint(uint(u32))))
}
return mRSlice

}

func feltSliceToUint32Slice(feltSlice []Felt) ([]uint32, error) {
uint32Slice := make([]uint32, 0, len(feltSlice))
for _, felt := range feltSlice {
val, err := felt.ToU32()
if err != nil {
return nil, err
}
uint32Slice = append(uint32Slice, val)
}
return uint32Slice, nil
}

// Returns the range from (baseAddr - baseAddrOffset) to (baseAddr - baseAddrOffset + Size)
func getUint32MemoryRange(baseAddr Relocatable, baseAddrOffset uint, size uint, segments *MemorySegmentManager) ([]uint32, error) {
baseAddr, err := baseAddr.SubUint(baseAddrOffset)
if err != nil {
return nil, err
}
feltRange, err := segments.GetFeltRange(baseAddr, size)
if err != nil {
return nil, err
}
return feltSliceToUint32Slice(feltRange)
}

// Returns the u32 value at memory[baseAddr - baseAddrOffset]
func getU32FromMemory(baseAddr Relocatable, baseAddrOffset uint, memory *Memory) (uint32, error) {
baseAddr, err := baseAddr.SubUint(baseAddrOffset)
if err != nil {
return 0, err
}
felt, err := memory.GetFelt(baseAddr)
if err != nil {
return 0, err
}
return felt.ToU32()
}

func blake2sCompute(ids IdsManager, vm *VirtualMachine) error {
output, err := ids.GetRelocatable("output", vm)
if err != nil {
return err
}
h, err := getUint32MemoryRange(output, 26, 8, &vm.Segments)
if err != nil {
return err
}
message, err := getUint32MemoryRange(output, 18, 16, &vm.Segments)
if err != nil {
return err
}
t, err := getU32FromMemory(output, 2, &vm.Segments.Memory)
if err != nil {
return err
}
f, err := getU32FromMemory(output, 1, &vm.Segments.Memory)
if err != nil {
return err
}

newState := Blake2sCompress([8]uint32(h), [16]uint32(message), t, 0, f, 0)
data := Uint32SliceToMRSlice(newState)

_, err = vm.Segments.LoadData(output, &data)
return err
}

func blake2sAddUint256Bigend(ids IdsManager, vm *VirtualMachine) error {
// Fetch ids variables
dataPtr, err := ids.GetRelocatable("data", vm)
if err != nil {
return err
}
low, err := ids.GetFelt("low", vm)
if err != nil {
return err
}
high, err := ids.GetFelt("high", vm)
if err != nil {
return err
}
// Hint logic
const MASK = math.MaxUint32
const B = 32
mask := FeltFromUint(MASK)
// First batch
data := make([]MaybeRelocatable, 0, 4)
for i := uint(0); i < 4; i++ {
data = append(data, *NewMaybeRelocatableFelt(high.Shr(B * (3 - i)).And(mask)))
}
dataPtr, err = vm.Segments.LoadData(dataPtr, &data)
if err != nil {
return err
}
// Second batch
data = make([]MaybeRelocatable, 0, 4)
for i := uint(0); i < 4; i++ {
data = append(data, *NewMaybeRelocatableFelt(low.Shr(B * (3 - i)).And(mask)))
}
_, err = vm.Segments.LoadData(dataPtr, &data)
return err
}

func blake2sFinalize(ids IdsManager, vm *VirtualMachine) error {
const N_PACKED_INSTANCES = 7
blake2sPtrEnd, err := ids.GetRelocatable("blake2s_ptr_end", vm)
if err != nil {
return err
}
var message [16]uint32
modifiedIv := IV()
modifiedIv[0] = modifiedIv[0] ^ 0x01010020
output := Blake2sCompress(modifiedIv, message, 0, 0, 0xffffffff, 0)
padding := modifiedIv[:]
padding = append(padding, message[:]...)
padding = append(padding, 0, 0xffffffff)
padding = append(padding, output[:]...)
fullPadding := padding
for i := 2; i < N_PACKED_INSTANCES; i++ {
fullPadding = append(fullPadding, padding...)
}
data := Uint32SliceToMRSlice(fullPadding)
_, err = vm.Segments.LoadData(blake2sPtrEnd, &data)
return err
}
Loading
Loading