Skip to content

Commit

Permalink
feat(avm): add index to pedersen opcode (#5486)
Browse files Browse the repository at this point in the history
  • Loading branch information
fcarreiro committed Apr 2, 2024
1 parent 881502b commit e1d7d11
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 9 deletions.
8 changes: 6 additions & 2 deletions avm-transpiler/src/transpile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -880,18 +880,22 @@ fn handle_black_box_function(avm_instrs: &mut Vec<AvmInstruction>, operation: &B
match operation {
BlackBoxOp::PedersenHash {
inputs,
domain_separator: _,
domain_separator,
output,
} => {
let message_offset = inputs.pointer.0;
let message_size_offset = inputs.size.0;

let index_offset = domain_separator.0;
let dest_offset = output.0;

avm_instrs.push(AvmInstruction {
opcode: AvmOpcode::PEDERSEN,
indirect: Some(FIRST_OPERAND_INDIRECT),
indirect: Some(SECOND_OPERAND_INDIRECT),
operands: vec![
AvmOperand::U32 {
value: index_offset as u32,
},
AvmOperand::U32 {
value: dest_offset as u32,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ contract AvmTest {
dep::std::hash::pedersen_hash(data)
}

#[aztec(public-vm)]
fn pedersen_hash_with_index(data: [Field; 3]) -> pub Field {
dep::std::hash::pedersen_hash_with_separator(data, 20)
}

/************************************************************************
* AvmContext functions
************************************************************************/
Expand Down
1 change: 1 addition & 0 deletions yarn-project/simulator/src/avm/avm_simulator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ describe('AVM simulator: transpiled Noir contracts', () => {
describe.each([
['poseidon_hash', poseidonHash],
['pedersen_hash', pedersenHash],
['pedersen_hash_with_index', (m: Buffer[]) => pedersenHash(m, 20)],
])('Hashes with field returned in noir contracts', (name: string, hashFunction: (data: Buffer[]) => Fr) => {
it(`Should execute contract function that performs ${name} hash`, async () => {
const calldata = [new Fr(1), new Fr(2), new Fr(3)];
Expand Down
14 changes: 11 additions & 3 deletions yarn-project/simulator/src/avm/opcodes/hashing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,12 +205,14 @@ describe('Hashing Opcodes', () => {
const buf = Buffer.from([
Pedersen.opcode, // opcode
1, // indirect
...Buffer.from('02345678', 'hex'), // genIndexOffset
...Buffer.from('12345678', 'hex'), // dstOffset
...Buffer.from('23456789', 'hex'), // messageOffset
...Buffer.from('3456789a', 'hex'), // hashSize
]);
const inst = new Pedersen(
/*indirect=*/ 1,
/*genIndexOffset=*/ 0x02345678,
/*dstOffset=*/ 0x12345678,
/*messageOffset=*/ 0x23456789,
/*hashSizeOffset=*/ 0x3456789a,
Expand All @@ -224,15 +226,18 @@ describe('Hashing Opcodes', () => {
const args = [new Field(1n), new Field(2n), new Field(3n)];
const messageOffset = 0;
const sizeOffset = 10;
const genIndexOffset = 20;
const indirect = 0;
const genIndex = 20;

context.machineState.memory.setSlice(messageOffset, args);
context.machineState.memory.set(sizeOffset, new Uint32(args.length));
context.machineState.memory.set(genIndexOffset, new Uint32(genIndex));

const dstOffset = 3;

const expectedHash = pedersenHash(args);
await new Pedersen(indirect, dstOffset, messageOffset, sizeOffset).execute(context);
const expectedHash = pedersenHash(args, genIndex);
await new Pedersen(indirect, genIndexOffset, dstOffset, messageOffset, sizeOffset).execute(context);

const result = context.machineState.memory.get(dstOffset);
expect(result).toEqual(new Field(expectedHash));
Expand All @@ -241,6 +246,7 @@ describe('Hashing Opcodes', () => {
it('Should hash correctly - indirect', async () => {
const args = [new Field(1n), new Field(2n), new Field(3n)];
const indirect = new Addressing([
/*genIndexOffset=*/ AddressingMode.DIRECT,
/*dstOffset=*/ AddressingMode.DIRECT,
/*messageOffset*/ AddressingMode.INDIRECT,
/*messageSizeOffset*/ AddressingMode.INDIRECT,
Expand All @@ -249,16 +255,18 @@ describe('Hashing Opcodes', () => {
const sizeOffset = 10;
const realLocation = 4;
const realSizeLocation = 20;
const genIndexOffset = 50;

context.machineState.memory.set(messageOffset, new Uint32(realLocation));
context.machineState.memory.set(sizeOffset, new Uint32(realSizeLocation));
context.machineState.memory.setSlice(realLocation, args);
context.machineState.memory.set(realSizeLocation, new Uint32(args.length));
context.machineState.memory.set(genIndexOffset, new Uint32(0));

const dstOffset = 300;

const expectedHash = pedersenHash(args);
await new Pedersen(indirect, dstOffset, messageOffset, sizeOffset).execute(context);
await new Pedersen(indirect, genIndexOffset, dstOffset, messageOffset, sizeOffset).execute(context);

const result = context.machineState.memory.get(dstOffset);
expect(result).toEqual(new Field(expectedHash));
Expand Down
10 changes: 6 additions & 4 deletions yarn-project/simulator/src/avm/opcodes/hashing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,12 @@ export class Pedersen extends Instruction {
OperandType.UINT32,
OperandType.UINT32,
OperandType.UINT32,
OperandType.UINT32,
];

constructor(
private indirect: number,
private genIndexOffset: number,
private dstOffset: number,
private messageOffset: number,
private messageSizeOffset: number,
Expand All @@ -159,17 +161,17 @@ export class Pedersen extends Instruction {
}

async execute(context: AvmContext): Promise<void> {
const [dstOffset, messageOffset, messageSizeOffset] = Addressing.fromWire(this.indirect).resolve(
[this.dstOffset, this.messageOffset, this.messageSizeOffset],
const [genIndexOffset, dstOffset, messageOffset, messageSizeOffset] = Addressing.fromWire(this.indirect).resolve(
[this.genIndexOffset, this.dstOffset, this.messageOffset, this.messageSizeOffset],
context.machineState.memory,
);

// We hash a set of field elements
const genIndex = Number(context.machineState.memory.get(genIndexOffset).toBigInt());
const messageSize = Number(context.machineState.memory.get(messageSizeOffset).toBigInt());
const hashData = context.machineState.memory.getSlice(messageOffset, messageSize);

// No domain sep for now
const hash = pedersenHash(hashData);
const hash = pedersenHash(hashData, genIndex);
context.machineState.memory.set(dstOffset, new Field(hash));

context.machineState.incrementPc();
Expand Down

0 comments on commit e1d7d11

Please sign in to comment.